39 #define DEBUG_TYPE "legalizer-info" 42 "disable-gisel-legality-check",
43 cl::desc(
"Don't verify that MIR is fully legal between GlobalISel passes"),
47 OS << Opcode <<
", Tys={";
48 for (
const auto &
Type : Types) {
53 OS << Opcode <<
", MMOs={";
54 for (
const auto &MMODescr : MMODescrs) {
55 OS << MMODescr.SizeInBits <<
", ";
66 LLVM_DEBUG(
dbgs() <<
".. fallback to legacy rules (no rules defined)\n");
69 for (
const auto &Rule : Rules) {
70 if (Rule.match(Query)) {
72 std::pair<unsigned, LLT>
Mutation = Rule.determineMutation(Query);
73 LLVM_DEBUG(
dbgs() <<
".. .. " << (
unsigned)Rule.getAction() <<
", " 74 << Mutation.first <<
", " << Mutation.second <<
"\n");
75 assert((Query.
Types[Mutation.first] != Mutation.second ||
76 Rule.getAction() ==
Lower ||
79 "Simple loop detected");
80 return {Rule.getAction(), Mutation.first, Mutation.second};
92 dbgs() <<
".. type index coverage check SKIPPED: no rules defined\n");
95 const int64_t FirstUncovered = TypeIdxsCovered.find_first_unset();
96 if (FirstUncovered < 0) {
98 " user-defined predicate detected\n");
101 const bool AllCovered = (FirstUncovered >= NumTypeIdxs);
102 LLVM_DEBUG(
dbgs() <<
".. the first uncovered type index: " << FirstUncovered
103 <<
", " << (AllCovered ?
"OK" :
"FAIL") <<
"\n");
114 setScalarAction(TargetOpcode::G_ANYEXT, 1, {{1,
Legal}});
115 setScalarAction(TargetOpcode::G_ZEXT, 1, {{1,
Legal}});
116 setScalarAction(TargetOpcode::G_SEXT, 1, {{1,
Legal}});
117 setScalarAction(TargetOpcode::G_TRUNC, 0, {{1,
Legal}});
118 setScalarAction(TargetOpcode::G_TRUNC, 1, {{1,
Legal}});
120 setScalarAction(TargetOpcode::G_INTRINSIC, 0, {{1,
Legal}});
121 setScalarAction(TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS, 0, {{1,
Legal}});
142 setScalarAction(TargetOpcode::G_FNEG, 0, {{1,
Lower}});
146 assert(TablesInitialized ==
false);
148 for (
unsigned OpcodeIdx = 0; OpcodeIdx <= LastOp - FirstOp; ++OpcodeIdx) {
149 const unsigned Opcode = FirstOp + OpcodeIdx;
150 for (
unsigned TypeIdx = 0; TypeIdx != SpecifiedActions[OpcodeIdx].size();
157 std::map<uint16_t, SizeAndActionsVec> AddressSpace2SpecifiedActions;
159 std::map<uint16_t, SizeAndActionsVec> ElemSize2SpecifiedActions;
160 for (
auto LLT2Action : SpecifiedActions[OpcodeIdx][TypeIdx]) {
161 const LLT Type = LLT2Action.first;
164 auto SizeAction = std::make_pair(Type.
getSizeInBits(), Action);
170 .push_back(SizeAction);
172 ScalarSpecifiedActions.push_back(SizeAction);
180 if (TypeIdx < ScalarSizeChangeStrategies[OpcodeIdx].
size() &&
181 ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx] !=
nullptr)
182 S = ScalarSizeChangeStrategies[OpcodeIdx][TypeIdx];
184 ScalarSpecifiedActions.end());
185 checkPartialSizeAndActionsVector(ScalarSpecifiedActions);
186 setScalarAction(Opcode, TypeIdx, S(ScalarSpecifiedActions));
190 for (
auto PointerSpecifiedActions : AddressSpace2SpecifiedActions) {
191 llvm::sort(PointerSpecifiedActions.second.begin(),
192 PointerSpecifiedActions.second.end());
193 checkPartialSizeAndActionsVector(PointerSpecifiedActions.second);
197 Opcode, TypeIdx, PointerSpecifiedActions.first,
203 for (
auto VectorSpecifiedActions : ElemSize2SpecifiedActions) {
204 llvm::sort(VectorSpecifiedActions.second.begin(),
205 VectorSpecifiedActions.second.end());
206 const uint16_t ElementSize = VectorSpecifiedActions.first;
207 ElementSizesSeen.push_back({ElementSize,
Legal});
208 checkPartialSizeAndActionsVector(VectorSpecifiedActions.second);
214 for (
SizeAndAction BitsizeAndAction : VectorSpecifiedActions.second) {
215 assert(BitsizeAndAction.first % ElementSize == 0);
216 const uint16_t NumElements = BitsizeAndAction.first / ElementSize;
217 NumElementsActions.push_back({NumElements, BitsizeAndAction.second});
219 setVectorNumElementAction(
220 Opcode, TypeIdx, ElementSize,
226 if (TypeIdx < VectorElementSizeChangeStrategies[OpcodeIdx].
size() &&
227 VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx] !=
nullptr)
228 VectorElementSizeChangeStrategy =
229 VectorElementSizeChangeStrategies[OpcodeIdx][TypeIdx];
230 setScalarInVectorAction(
231 Opcode, TypeIdx, VectorElementSizeChangeStrategy(ElementSizesSeen));
235 TablesInitialized =
true;
242 std::pair<LegalizeAction, LLT>
243 LegalizerInfo::getAspectAction(
const InstrAspect &Aspect)
const {
244 assert(TablesInitialized &&
"backend forgot to call computeTables");
248 return findScalarLegalAction(Aspect);
250 return findVectorLegalAction(Aspect);
261 if (MI.
getOpcode() == TargetOpcode::G_UNMERGE_VALUES && TypeIdx == 1)
267 assert(Opcode >= FirstOp && Opcode <= LastOp &&
"Unsupported opcode");
268 return Opcode - FirstOp;
273 if (
unsigned Alias = RulesForOpcode[OpcodeIdx].getAlias()) {
274 LLVM_DEBUG(
dbgs() <<
".. opcode " << Opcode <<
" is aliased to " << Alias
278 << RulesForOpcode[OpcodeIdx].getAlias() <<
"\n");
279 assert(RulesForOpcode[OpcodeIdx].getAlias() == 0 &&
"Cannot chain aliases");
288 return RulesForOpcode[OpcodeIdx];
293 auto &Result = RulesForOpcode[OpcodeIdx];
294 assert(!Result.isAliasedByAnother() &&
"Modifying this opcode will modify aliases");
299 std::initializer_list<unsigned> Opcodes) {
300 unsigned Representative = *Opcodes.begin();
302 assert(!
empty(Opcodes) && Opcodes.begin() + 1 != Opcodes.end() &&
303 "Initializer list must have at least two opcodes");
305 for (
auto I = Opcodes.begin() + 1,
E = Opcodes.end();
I !=
E; ++
I)
309 Return.setIsAliasedByAnother();
314 unsigned OpcodeFrom) {
315 assert(OpcodeTo != OpcodeFrom &&
"Cannot alias to self");
316 assert(OpcodeTo >= FirstOp && OpcodeTo <= LastOp &&
"Unsupported opcode");
318 RulesForOpcode[OpcodeFromIdx].
aliasTo(OpcodeTo);
328 for (
unsigned i = 0; i < Query.
Types.size(); ++i) {
329 auto Action = getAspectAction({Query.
Opcode, i, Query.
Types[i]});
330 if (Action.first !=
Legal) {
332 <<
" Action=" << (
unsigned)Action.first <<
", " 333 << Action.second <<
"\n");
334 return {Action.first, i, Action.second};
350 if (!OpInfo[i].isGenericType())
356 if (SeenTypes[TypeIdx])
359 SeenTypes.
set(TypeIdx);
368 {MMO->getSize() * 8, MMO->getOrdering()});
389 unsigned LargestSizeSoFar = 0;
390 if (v.size() >= 1 && v[0].first != 1)
391 result.push_back({1, IncreaseAction});
392 for (
size_t i = 0; i < v.size(); ++i) {
393 result.push_back(v[i]);
394 LargestSizeSoFar = v[i].first;
395 if (i + 1 < v.size() && v[i + 1].first != v[i].first + 1) {
396 result.push_back({LargestSizeSoFar + 1, IncreaseAction});
397 LargestSizeSoFar = v[i].first + 1;
400 result.push_back({LargestSizeSoFar + 1, DecreaseAction});
409 if (v.size() == 0 || v[0].first != 1)
410 result.push_back({1, IncreaseAction});
411 for (
size_t i = 0; i < v.size(); ++i) {
412 result.push_back(v[i]);
413 if (i + 1 == v.size() || v[i + 1].first != v[i].first + 1) {
414 result.push_back({v[i].first + 1, DecreaseAction});
427 Vec.begin(), Vec.end(),
Size,
429 return Size < lhs.first;
431 assert(VecIt != Vec.begin() &&
"Does Vec not start with size 1?");
433 int VecIdx = VecIt - Vec.begin();
441 return {
Size, Action};
456 for (
int i = VecIdx - 1; i >= 0; --i)
459 return {Vec[i].first, Action};
465 for (std::size_t i = VecIdx + 1; i < Vec.size(); ++i)
468 return {Vec[i].first, Action};
480 std::pair<LegalizeAction, LLT>
481 LegalizerInfo::findScalarLegalAction(
const InstrAspect &Aspect)
const {
488 AddrSpace2PointerActions[OpcodeIdx].
end()) {
493 ? AddrSpace2PointerActions[OpcodeIdx]
496 : ScalarActions[OpcodeIdx];
497 if (Aspect.
Idx >= Actions.
size())
509 std::pair<LegalizeAction, LLT>
510 LegalizerInfo::findVectorLegalAction(
const InstrAspect &Aspect)
const {
517 const unsigned TypeIdx = Aspect.
Idx;
518 if (TypeIdx >= ScalarInVectorActions[OpcodeIdx].
size())
521 ScalarInVectorActions[OpcodeIdx][TypeIdx];
523 LLT IntermediateType;
524 auto ElementSizeAndAction =
528 if (ElementSizeAndAction.second !=
Legal)
529 return {ElementSizeAndAction.second, IntermediateType};
531 auto i = NumElements2Actions[OpcodeIdx].find(
532 IntermediateType.getScalarSizeInBits());
533 if (i == NumElements2Actions[OpcodeIdx].
end()) {
534 return {
NotFound, IntermediateType};
537 auto NumElementsAndAction =
538 findAction(NumElementsVec, IntermediateType.getNumElements());
539 return {NumElementsAndAction.second,
541 IntermediateType.getScalarSizeInBits())};
547 std::vector<unsigned> FailedOpcodes;
548 for (
unsigned Opcode = FirstOp; Opcode <= LastOp; ++Opcode) {
550 const unsigned NumTypeIdxs = std::accumulate(
554 ?
std::max(OpInfo.getGenericTypeIndex() + 1U, Acc)
558 <<
"): " << NumTypeIdxs <<
" type ind" 559 << (NumTypeIdxs == 1 ?
"ex" :
"ices") <<
"\n");
562 FailedOpcodes.push_back(Opcode);
564 if (!FailedOpcodes.empty()) {
565 errs() <<
"The following opcodes have ill-defined legalization rules:";
566 for (
unsigned Opcode : FailedOpcodes)
571 ", try -debug-only=legalizer-info for details");
const_iterator end(StringRef path)
Get end iterator over path.
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
This class represents lattice values for constants.
static SizeAndActionsVec increaseToLargerTypesAndDecreaseToLargest(const SizeAndActionsVec &v, LegalizeAction IncreaseAction, LegalizeAction DecreaseAction)
Helper function to implement many typical SizeChangeStrategy functions.
unsigned getScalarSizeInBits() const
The operation should be implemented in terms of a wider scalar base-type.
raw_ostream & print(raw_ostream &OS) const
std::function< SizeAndActionsVec(const SizeAndActionsVec &v)> SizeChangeStrategy
void push_back(const T &Elt)
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
Describe properties that are true of each instruction in the target description file.
unsigned getReg() const
getReg - Returns the register number.
static LLT getTypeFromTypeIdx(const MachineInstr &MI, const MachineRegisterInfo &MRI, unsigned OpIdx, unsigned TypeIdx)
Helper function to get LLT for the given type index.
std::vector< SizeAndAction > SizeAndActionsVec
The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...
Libcall
RTLIB::Libcall enum - This enum defines all of the runtime library calls the backend can emit...
static SizeAndActionsVec narrowToSmallerAndUnsupportedIfTooSmall(const SizeAndActionsVec &v)
LLT getType(unsigned Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register...
const_opInfo_iterator opInfo_begin() const
const LegalizeRuleSet & getActionDefinitions(unsigned Opcode) const
Get the action definitions for the given opcode.
static SizeAndActionsVec unsupportedForDifferentSizes(const SizeAndActionsVec &v)
A SizeChangeStrategy for the common case where legalization for a particular operation consists of on...
The operation should be synthesized from multiple instructions acting on a narrower scalar base-type...
LegalizeActionStep getAction(const LegalityQuery &Query) const
Determine what action should be taken to legalize the described instruction.
static SizeAndActionsVec widenToLargerTypesUnsupportedOtherwise(const SizeAndActionsVec &v)
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
unsigned getNumOperands() const
Retuns the total number of operands.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
This operation is completely unsupported on the target.
LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
void verify(const MCInstrInfo &MII) const
Perform simple self-diagnostic and assert if there is anything obviously wrong with the actions set u...
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
The (vector) operation should be implemented by widening the input vector and ignoring the lanes adde...
void computeTables()
Compute any ancillary tables needed to quickly decide how an operation should be handled.
void aliasActionDefinitions(unsigned OpcodeTo, unsigned OpcodeFrom)
static LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
The operation itself must be expressed in terms of simpler actions on this target.
bool isGenericType() const
virtual const LegalizerInfo * getLegalizerInfo() const
bool isLegal(const MachineInstr &MI, const MachineRegisterInfo &MRI) const
Abstract class that contains various methods for clients to notify about changes. ...
static SizeAndActionsVec decreaseToSmallerTypesAndIncreaseToSmallest(const SizeAndActionsVec &v, LegalizeAction DecreaseAction, LegalizeAction IncreaseAction)
Helper function to implement many typical SizeChangeStrategy functions.
unsigned const MachineRegisterInfo * MRI
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
The instances of the Type class are immutable: once they are created, they are never changed...
Sentinel value for when no action was found in the specified table.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Helper class to build MachineInstr.
Interface to description of machine instruction set.
bool verifyTypeIdxsCoverage(unsigned NumTypeIdxs) const
Check if there is no type index which is obviously not handled by the LegalizeRuleSet in any way at a...
unsigned getAddressSpace() const
Legalization is decided based on an instruction's opcode, which type slot we're considering, and what the existing type is.
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
cl::opt< bool > DisableGISelLegalityCheck
LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)
Get the action definition builder for the given opcode.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void sort(IteratorTy Start, IteratorTy End)
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
const MachineInstr * machineFunctionIsIllegal(const MachineFunction &MF)
Checks that MIR is fully legal, returns an illegal instruction if it's not, nullptr otherwise...
auto size(R &&Range, typename std::enable_if< std::is_same< typename std::iterator_traits< decltype(Range.begin())>::iterator_category, std::random_access_iterator_tag >::value, void >::type *=nullptr) -> decltype(std::distance(Range.begin(), Range.end()))
Get the size of a range.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
unsigned getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
The target wants to do something special with this combination of operand and type.
unsigned getOpcodeIdxForOpcode(unsigned Opcode) const
virtual bool legalizeCustom(MachineInstr &MI, MachineRegisterInfo &MRI, MachineIRBuilder &MIRBuilder, GISelChangeObserver &Observer) const
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
LegalizeAction Action
The action to take or the final answer.
static bool needsLegalizingToDifferentSize(const LegalizeAction Action)
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Fall back onto the old rules.
static SizeAndActionsVec widenToLargerTypesAndNarrowToLargest(const SizeAndActionsVec &v)
A SizeChangeStrategy for the common case where legalization for a particular operation consists of wi...
static SizeAndActionsVec moreToWiderTypesAndLessToWidest(const SizeAndActionsVec &v)
A SizeChangeStrategy for the common case where legalization for a particular vector operation consist...
LegalizeActionStep apply(const LegalityQuery &Query) const
Apply the ruleset to the given LegalityQuery.
const_opInfo_iterator opInfo_end() const
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode...
void aliasTo(unsigned Opcode)
void setLegalizeScalarToDifferentSizeStrategy(const unsigned Opcode, const unsigned TypeIdx, SizeChangeStrategy S)
The setAction calls record the non-size-changing legalization actions to take on specificly-sized typ...
static void Query(const MachineInstr &MI, AliasAnalysis &AA, bool &Read, bool &Write, bool &Effects, bool &StackPointer)
auto upper_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range))
Provide wrappers to std::upper_bound which take ranges instead of having to pass begin/end explicitly...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel...
static LLT pointer(uint16_t AddressSpace, unsigned SizeInBits)
Get a low-level pointer in the given address space (defaulting to 0).
uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
const MCOperandInfo * OpInfo
unsigned getActionDefinitionsIdx(unsigned Opcode) const
This class implements an extremely fast bulk output stream that can only output to a stream...
unsigned getGenericTypeIndex() const
static LLT vector(uint16_t NumElements, unsigned ScalarSizeInBits)
Get a low-level vector of some number of elements and element width.
This holds information about one operand of a machine instruction, indicating the register class for ...
const MachineOperand & getOperand(unsigned i) const
The operation is expected to be selectable directly by the target, and no transformation is necessary...
std::pair< uint16_t, LegalizeAction > SizeAndAction