1 //===- lib/CodeGen/GlobalISel/LegalizerInfo.cpp - Legalizer ---------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Implement an interface to specify and query how an illegal operation on a
10 // given type should be expanded.
12 // Issues to be resolved:
14 // + Support weird types like i3, <7 x i3>, ...
15 // + Operations with more than one type (ICMP, CMPXCHG, intrinsics, ...)
17 //===----------------------------------------------------------------------===//
19 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
20 #include "llvm/ADT/SmallBitVector.h"
21 #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h"
22 #include "llvm/CodeGen/MachineInstr.h"
23 #include "llvm/CodeGen/MachineOperand.h"
24 #include "llvm/CodeGen/MachineRegisterInfo.h"
25 #include "llvm/CodeGen/TargetOpcodes.h"
26 #include "llvm/MC/MCInstrDesc.h"
27 #include "llvm/MC/MCInstrInfo.h"
28 #include "llvm/Support/Debug.h"
29 #include "llvm/Support/ErrorHandling.h"
30 #include "llvm/Support/LowLevelTypeImpl.h"
31 #include "llvm/Support/MathExtras.h"
36 using namespace LegalizeActions
;
38 #define DEBUG_TYPE "legalizer-info"
40 cl::opt
<bool> llvm::DisableGISelLegalityCheck(
41 "disable-gisel-legality-check",
42 cl::desc("Don't verify that MIR is fully legal between GlobalISel passes"),
45 raw_ostream
&llvm::operator<<(raw_ostream
&OS
, LegalizeAction Action
) {
57 OS
<< "FewerElements";
78 OS
<< "UseLegacyRules";
84 raw_ostream
&LegalityQuery::print(raw_ostream
&OS
) const {
85 OS
<< Opcode
<< ", Tys={";
86 for (const auto &Type
: Types
) {
91 OS
<< Opcode
<< ", MMOs={";
92 for (const auto &MMODescr
: MMODescrs
) {
93 OS
<< MMODescr
.SizeInBits
<< ", ";
101 // Make sure the rule won't (trivially) loop forever.
102 static bool hasNoSimpleLoops(const LegalizeRule
&Rule
, const LegalityQuery
&Q
,
103 const std::pair
<unsigned, LLT
> &Mutation
) {
104 switch (Rule
.getAction()) {
111 return Q
.Types
[Mutation
.first
] != Mutation
.second
;
116 // Make sure the returned mutation makes sense for the match type.
117 static bool mutationIsSane(const LegalizeRule
&Rule
,
118 const LegalityQuery
&Q
,
119 std::pair
<unsigned, LLT
> Mutation
) {
120 // If the user wants a custom mutation, then we can't really say much about
121 // it. Return true, and trust that they're doing the right thing.
122 if (Rule
.getAction() == Custom
)
125 const unsigned TypeIdx
= Mutation
.first
;
126 const LLT OldTy
= Q
.Types
[TypeIdx
];
127 const LLT NewTy
= Mutation
.second
;
129 switch (Rule
.getAction()) {
132 if (!OldTy
.isVector())
135 if (NewTy
.isVector()) {
136 if (Rule
.getAction() == FewerElements
) {
137 // Make sure the element count really decreased.
138 if (NewTy
.getNumElements() >= OldTy
.getNumElements())
141 // Make sure the element count really increased.
142 if (NewTy
.getNumElements() <= OldTy
.getNumElements())
147 // Make sure the element type didn't change.
148 return NewTy
.getScalarType() == OldTy
.getElementType();
152 if (OldTy
.isVector()) {
153 // Number of elements should not change.
154 if (!NewTy
.isVector() || OldTy
.getNumElements() != NewTy
.getNumElements())
157 // Both types must be vectors
158 if (NewTy
.isVector())
162 if (Rule
.getAction() == NarrowScalar
) {
163 // Make sure the size really decreased.
164 if (NewTy
.getScalarSizeInBits() >= OldTy
.getScalarSizeInBits())
167 // Make sure the size really increased.
168 if (NewTy
.getScalarSizeInBits() <= OldTy
.getScalarSizeInBits())
180 LegalizeActionStep
LegalizeRuleSet::apply(const LegalityQuery
&Query
) const {
181 LLVM_DEBUG(dbgs() << "Applying legalizer ruleset to: "; Query
.print(dbgs());
184 LLVM_DEBUG(dbgs() << ".. fallback to legacy rules (no rules defined)\n");
185 return {LegalizeAction::UseLegacyRules
, 0, LLT
{}};
187 for (const LegalizeRule
&Rule
: Rules
) {
188 if (Rule
.match(Query
)) {
189 LLVM_DEBUG(dbgs() << ".. match\n");
190 std::pair
<unsigned, LLT
> Mutation
= Rule
.determineMutation(Query
);
191 LLVM_DEBUG(dbgs() << ".. .. " << Rule
.getAction() << ", "
192 << Mutation
.first
<< ", " << Mutation
.second
<< "\n");
193 assert(mutationIsSane(Rule
, Query
, Mutation
) &&
194 "legality mutation invalid for match");
195 assert(hasNoSimpleLoops(Rule
, Query
, Mutation
) && "Simple loop detected");
196 return {Rule
.getAction(), Mutation
.first
, Mutation
.second
};
198 LLVM_DEBUG(dbgs() << ".. no match\n");
200 LLVM_DEBUG(dbgs() << ".. unsupported\n");
201 return {LegalizeAction::Unsupported
, 0, LLT
{}};
204 bool LegalizeRuleSet::verifyTypeIdxsCoverage(unsigned NumTypeIdxs
) const {
208 dbgs() << ".. type index coverage check SKIPPED: no rules defined\n");
211 const int64_t FirstUncovered
= TypeIdxsCovered
.find_first_unset();
212 if (FirstUncovered
< 0) {
213 LLVM_DEBUG(dbgs() << ".. type index coverage check SKIPPED:"
214 " user-defined predicate detected\n");
217 const bool AllCovered
= (FirstUncovered
>= NumTypeIdxs
);
218 LLVM_DEBUG(dbgs() << ".. the first uncovered type index: " << FirstUncovered
219 << ", " << (AllCovered
? "OK" : "FAIL") << "\n");
226 LegalizerInfo::LegalizerInfo() : TablesInitialized(false) {
228 // FIXME: these two (G_ANYEXT and G_TRUNC?) can be legalized to the
229 // fundamental load/store Jakob proposed. Once loads & stores are supported.
230 setScalarAction(TargetOpcode::G_ANYEXT
, 1, {{1, Legal
}});
231 setScalarAction(TargetOpcode::G_ZEXT
, 1, {{1, Legal
}});
232 setScalarAction(TargetOpcode::G_SEXT
, 1, {{1, Legal
}});
233 setScalarAction(TargetOpcode::G_TRUNC
, 0, {{1, Legal
}});
234 setScalarAction(TargetOpcode::G_TRUNC
, 1, {{1, Legal
}});
236 setScalarAction(TargetOpcode::G_INTRINSIC
, 0, {{1, Legal
}});
237 setScalarAction(TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS
, 0, {{1, Legal
}});
239 setLegalizeScalarToDifferentSizeStrategy(
240 TargetOpcode::G_IMPLICIT_DEF
, 0, narrowToSmallerAndUnsupportedIfTooSmall
);
241 setLegalizeScalarToDifferentSizeStrategy(
242 TargetOpcode::G_ADD
, 0, widenToLargerTypesAndNarrowToLargest
);
243 setLegalizeScalarToDifferentSizeStrategy(
244 TargetOpcode::G_OR
, 0, widenToLargerTypesAndNarrowToLargest
);
245 setLegalizeScalarToDifferentSizeStrategy(
246 TargetOpcode::G_LOAD
, 0, narrowToSmallerAndUnsupportedIfTooSmall
);
247 setLegalizeScalarToDifferentSizeStrategy(
248 TargetOpcode::G_STORE
, 0, narrowToSmallerAndUnsupportedIfTooSmall
);
250 setLegalizeScalarToDifferentSizeStrategy(
251 TargetOpcode::G_BRCOND
, 0, widenToLargerTypesUnsupportedOtherwise
);
252 setLegalizeScalarToDifferentSizeStrategy(
253 TargetOpcode::G_INSERT
, 0, narrowToSmallerAndUnsupportedIfTooSmall
);
254 setLegalizeScalarToDifferentSizeStrategy(
255 TargetOpcode::G_EXTRACT
, 0, narrowToSmallerAndUnsupportedIfTooSmall
);
256 setLegalizeScalarToDifferentSizeStrategy(
257 TargetOpcode::G_EXTRACT
, 1, narrowToSmallerAndUnsupportedIfTooSmall
);
258 setScalarAction(TargetOpcode::G_FNEG
, 0, {{1, Lower
}});
261 void LegalizerInfo::computeTables() {
262 assert(TablesInitialized
== false);
264 for (unsigned OpcodeIdx
= 0; OpcodeIdx
<= LastOp
- FirstOp
; ++OpcodeIdx
) {
265 const unsigned Opcode
= FirstOp
+ OpcodeIdx
;
266 for (unsigned TypeIdx
= 0; TypeIdx
!= SpecifiedActions
[OpcodeIdx
].size();
268 // 0. Collect information specified through the setAction API, i.e.
269 // for specific bit sizes.
271 SizeAndActionsVec ScalarSpecifiedActions
;
272 // For pointer types:
273 std::map
<uint16_t, SizeAndActionsVec
> AddressSpace2SpecifiedActions
;
275 std::map
<uint16_t, SizeAndActionsVec
> ElemSize2SpecifiedActions
;
276 for (auto LLT2Action
: SpecifiedActions
[OpcodeIdx
][TypeIdx
]) {
277 const LLT Type
= LLT2Action
.first
;
278 const LegalizeAction Action
= LLT2Action
.second
;
280 auto SizeAction
= std::make_pair(Type
.getSizeInBits(), Action
);
281 if (Type
.isPointer())
282 AddressSpace2SpecifiedActions
[Type
.getAddressSpace()].push_back(
284 else if (Type
.isVector())
285 ElemSize2SpecifiedActions
[Type
.getElementType().getSizeInBits()]
286 .push_back(SizeAction
);
288 ScalarSpecifiedActions
.push_back(SizeAction
);
291 // 1. Handle scalar types
293 // Decide how to handle bit sizes for which no explicit specification
295 SizeChangeStrategy S
= &unsupportedForDifferentSizes
;
296 if (TypeIdx
< ScalarSizeChangeStrategies
[OpcodeIdx
].size() &&
297 ScalarSizeChangeStrategies
[OpcodeIdx
][TypeIdx
] != nullptr)
298 S
= ScalarSizeChangeStrategies
[OpcodeIdx
][TypeIdx
];
299 llvm::sort(ScalarSpecifiedActions
);
300 checkPartialSizeAndActionsVector(ScalarSpecifiedActions
);
301 setScalarAction(Opcode
, TypeIdx
, S(ScalarSpecifiedActions
));
304 // 2. Handle pointer types
305 for (auto PointerSpecifiedActions
: AddressSpace2SpecifiedActions
) {
306 llvm::sort(PointerSpecifiedActions
.second
);
307 checkPartialSizeAndActionsVector(PointerSpecifiedActions
.second
);
308 // For pointer types, we assume that there isn't a meaningfull way
309 // to change the number of bits used in the pointer.
311 Opcode
, TypeIdx
, PointerSpecifiedActions
.first
,
312 unsupportedForDifferentSizes(PointerSpecifiedActions
.second
));
315 // 3. Handle vector types
316 SizeAndActionsVec ElementSizesSeen
;
317 for (auto VectorSpecifiedActions
: ElemSize2SpecifiedActions
) {
318 llvm::sort(VectorSpecifiedActions
.second
);
319 const uint16_t ElementSize
= VectorSpecifiedActions
.first
;
320 ElementSizesSeen
.push_back({ElementSize
, Legal
});
321 checkPartialSizeAndActionsVector(VectorSpecifiedActions
.second
);
322 // For vector types, we assume that the best way to adapt the number
323 // of elements is to the next larger number of elements type for which
324 // the vector type is legal, unless there is no such type. In that case,
325 // legalize towards a vector type with a smaller number of elements.
326 SizeAndActionsVec NumElementsActions
;
327 for (SizeAndAction BitsizeAndAction
: VectorSpecifiedActions
.second
) {
328 assert(BitsizeAndAction
.first
% ElementSize
== 0);
329 const uint16_t NumElements
= BitsizeAndAction
.first
/ ElementSize
;
330 NumElementsActions
.push_back({NumElements
, BitsizeAndAction
.second
});
332 setVectorNumElementAction(
333 Opcode
, TypeIdx
, ElementSize
,
334 moreToWiderTypesAndLessToWidest(NumElementsActions
));
336 llvm::sort(ElementSizesSeen
);
337 SizeChangeStrategy VectorElementSizeChangeStrategy
=
338 &unsupportedForDifferentSizes
;
339 if (TypeIdx
< VectorElementSizeChangeStrategies
[OpcodeIdx
].size() &&
340 VectorElementSizeChangeStrategies
[OpcodeIdx
][TypeIdx
] != nullptr)
341 VectorElementSizeChangeStrategy
=
342 VectorElementSizeChangeStrategies
[OpcodeIdx
][TypeIdx
];
343 setScalarInVectorAction(
344 Opcode
, TypeIdx
, VectorElementSizeChangeStrategy(ElementSizesSeen
));
348 TablesInitialized
= true;
351 // FIXME: inefficient implementation for now. Without ComputeValueVTs we're
352 // probably going to need specialized lookup structures for various types before
353 // we have any hope of doing well with something like <13 x i3>. Even the common
354 // cases should do better than what we have now.
355 std::pair
<LegalizeAction
, LLT
>
356 LegalizerInfo::getAspectAction(const InstrAspect
&Aspect
) const {
357 assert(TablesInitialized
&& "backend forgot to call computeTables");
358 // These *have* to be implemented for now, they're the fundamental basis of
359 // how everything else is transformed.
360 if (Aspect
.Type
.isScalar() || Aspect
.Type
.isPointer())
361 return findScalarLegalAction(Aspect
);
362 assert(Aspect
.Type
.isVector());
363 return findVectorLegalAction(Aspect
);
366 /// Helper function to get LLT for the given type index.
367 static LLT
getTypeFromTypeIdx(const MachineInstr
&MI
,
368 const MachineRegisterInfo
&MRI
, unsigned OpIdx
,
370 assert(TypeIdx
< MI
.getNumOperands() && "Unexpected TypeIdx");
371 // G_UNMERGE_VALUES has variable number of operands, but there is only
372 // one source type and one destination type as all destinations must be the
373 // same type. So, get the last operand if TypeIdx == 1.
374 if (MI
.getOpcode() == TargetOpcode::G_UNMERGE_VALUES
&& TypeIdx
== 1)
375 return MRI
.getType(MI
.getOperand(MI
.getNumOperands() - 1).getReg());
376 return MRI
.getType(MI
.getOperand(OpIdx
).getReg());
379 unsigned LegalizerInfo::getOpcodeIdxForOpcode(unsigned Opcode
) const {
380 assert(Opcode
>= FirstOp
&& Opcode
<= LastOp
&& "Unsupported opcode");
381 return Opcode
- FirstOp
;
384 unsigned LegalizerInfo::getActionDefinitionsIdx(unsigned Opcode
) const {
385 unsigned OpcodeIdx
= getOpcodeIdxForOpcode(Opcode
);
386 if (unsigned Alias
= RulesForOpcode
[OpcodeIdx
].getAlias()) {
387 LLVM_DEBUG(dbgs() << ".. opcode " << Opcode
<< " is aliased to " << Alias
389 OpcodeIdx
= getOpcodeIdxForOpcode(Alias
);
390 LLVM_DEBUG(dbgs() << ".. opcode " << Alias
<< " is aliased to "
391 << RulesForOpcode
[OpcodeIdx
].getAlias() << "\n");
392 assert(RulesForOpcode
[OpcodeIdx
].getAlias() == 0 && "Cannot chain aliases");
398 const LegalizeRuleSet
&
399 LegalizerInfo::getActionDefinitions(unsigned Opcode
) const {
400 unsigned OpcodeIdx
= getActionDefinitionsIdx(Opcode
);
401 return RulesForOpcode
[OpcodeIdx
];
404 LegalizeRuleSet
&LegalizerInfo::getActionDefinitionsBuilder(unsigned Opcode
) {
405 unsigned OpcodeIdx
= getActionDefinitionsIdx(Opcode
);
406 auto &Result
= RulesForOpcode
[OpcodeIdx
];
407 assert(!Result
.isAliasedByAnother() && "Modifying this opcode will modify aliases");
411 LegalizeRuleSet
&LegalizerInfo::getActionDefinitionsBuilder(
412 std::initializer_list
<unsigned> Opcodes
) {
413 unsigned Representative
= *Opcodes
.begin();
415 assert(!empty(Opcodes
) && Opcodes
.begin() + 1 != Opcodes
.end() &&
416 "Initializer list must have at least two opcodes");
418 for (auto I
= Opcodes
.begin() + 1, E
= Opcodes
.end(); I
!= E
; ++I
)
419 aliasActionDefinitions(Representative
, *I
);
421 auto &Return
= getActionDefinitionsBuilder(Representative
);
422 Return
.setIsAliasedByAnother();
426 void LegalizerInfo::aliasActionDefinitions(unsigned OpcodeTo
,
427 unsigned OpcodeFrom
) {
428 assert(OpcodeTo
!= OpcodeFrom
&& "Cannot alias to self");
429 assert(OpcodeTo
>= FirstOp
&& OpcodeTo
<= LastOp
&& "Unsupported opcode");
430 const unsigned OpcodeFromIdx
= getOpcodeIdxForOpcode(OpcodeFrom
);
431 RulesForOpcode
[OpcodeFromIdx
].aliasTo(OpcodeTo
);
435 LegalizerInfo::getAction(const LegalityQuery
&Query
) const {
436 LegalizeActionStep Step
= getActionDefinitions(Query
.Opcode
).apply(Query
);
437 if (Step
.Action
!= LegalizeAction::UseLegacyRules
) {
441 for (unsigned i
= 0; i
< Query
.Types
.size(); ++i
) {
442 auto Action
= getAspectAction({Query
.Opcode
, i
, Query
.Types
[i
]});
443 if (Action
.first
!= Legal
) {
444 LLVM_DEBUG(dbgs() << ".. (legacy) Type " << i
<< " Action="
445 << Action
.first
<< ", " << Action
.second
<< "\n");
446 return {Action
.first
, i
, Action
.second
};
448 LLVM_DEBUG(dbgs() << ".. (legacy) Type " << i
<< " Legal\n");
450 LLVM_DEBUG(dbgs() << ".. (legacy) Legal\n");
451 return {Legal
, 0, LLT
{}};
455 LegalizerInfo::getAction(const MachineInstr
&MI
,
456 const MachineRegisterInfo
&MRI
) const {
457 SmallVector
<LLT
, 2> Types
;
458 SmallBitVector
SeenTypes(8);
459 const MCOperandInfo
*OpInfo
= MI
.getDesc().OpInfo
;
460 // FIXME: probably we'll need to cache the results here somehow?
461 for (unsigned i
= 0; i
< MI
.getDesc().getNumOperands(); ++i
) {
462 if (!OpInfo
[i
].isGenericType())
465 // We must only record actions once for each TypeIdx; otherwise we'd
466 // try to legalize operands multiple times down the line.
467 unsigned TypeIdx
= OpInfo
[i
].getGenericTypeIndex();
468 if (SeenTypes
[TypeIdx
])
471 SeenTypes
.set(TypeIdx
);
473 LLT Ty
= getTypeFromTypeIdx(MI
, MRI
, i
, TypeIdx
);
477 SmallVector
<LegalityQuery::MemDesc
, 2> MemDescrs
;
478 for (const auto &MMO
: MI
.memoperands())
479 MemDescrs
.push_back({8 * MMO
->getSize() /* in bits */,
480 8 * MMO
->getAlignment(),
481 MMO
->getOrdering()});
483 return getAction({MI
.getOpcode(), Types
, MemDescrs
});
486 bool LegalizerInfo::isLegal(const MachineInstr
&MI
,
487 const MachineRegisterInfo
&MRI
) const {
488 return getAction(MI
, MRI
).Action
== Legal
;
491 bool LegalizerInfo::isLegalOrCustom(const MachineInstr
&MI
,
492 const MachineRegisterInfo
&MRI
) const {
493 auto Action
= getAction(MI
, MRI
).Action
;
494 // If the action is custom, it may not necessarily modify the instruction,
495 // so we have to assume it's legal.
496 return Action
== Legal
|| Action
== Custom
;
499 bool LegalizerInfo::legalizeCustom(MachineInstr
&MI
, MachineRegisterInfo
&MRI
,
500 MachineIRBuilder
&MIRBuilder
,
501 GISelChangeObserver
&Observer
) const {
505 LegalizerInfo::SizeAndActionsVec
506 LegalizerInfo::increaseToLargerTypesAndDecreaseToLargest(
507 const SizeAndActionsVec
&v
, LegalizeAction IncreaseAction
,
508 LegalizeAction DecreaseAction
) {
509 SizeAndActionsVec result
;
510 unsigned LargestSizeSoFar
= 0;
511 if (v
.size() >= 1 && v
[0].first
!= 1)
512 result
.push_back({1, IncreaseAction
});
513 for (size_t i
= 0; i
< v
.size(); ++i
) {
514 result
.push_back(v
[i
]);
515 LargestSizeSoFar
= v
[i
].first
;
516 if (i
+ 1 < v
.size() && v
[i
+ 1].first
!= v
[i
].first
+ 1) {
517 result
.push_back({LargestSizeSoFar
+ 1, IncreaseAction
});
518 LargestSizeSoFar
= v
[i
].first
+ 1;
521 result
.push_back({LargestSizeSoFar
+ 1, DecreaseAction
});
525 LegalizerInfo::SizeAndActionsVec
526 LegalizerInfo::decreaseToSmallerTypesAndIncreaseToSmallest(
527 const SizeAndActionsVec
&v
, LegalizeAction DecreaseAction
,
528 LegalizeAction IncreaseAction
) {
529 SizeAndActionsVec result
;
530 if (v
.size() == 0 || v
[0].first
!= 1)
531 result
.push_back({1, IncreaseAction
});
532 for (size_t i
= 0; i
< v
.size(); ++i
) {
533 result
.push_back(v
[i
]);
534 if (i
+ 1 == v
.size() || v
[i
+ 1].first
!= v
[i
].first
+ 1) {
535 result
.push_back({v
[i
].first
+ 1, DecreaseAction
});
541 LegalizerInfo::SizeAndAction
542 LegalizerInfo::findAction(const SizeAndActionsVec
&Vec
, const uint32_t Size
) {
544 // Find the last element in Vec that has a bitsize equal to or smaller than
545 // the requested bit size.
546 // That is the element just before the first element that is bigger than Size.
547 auto It
= partition_point(
548 Vec
, [=](const SizeAndAction
&A
) { return A
.first
<= Size
; });
549 assert(It
!= Vec
.begin() && "Does Vec not start with size 1?");
550 int VecIdx
= It
- Vec
.begin() - 1;
552 LegalizeAction Action
= Vec
[VecIdx
].second
;
558 return {Size
, Action
};
560 // FIXME: is this special case still needed and correct?
561 // Special case for scalarization:
562 if (Vec
== SizeAndActionsVec({{1, FewerElements
}}))
563 return {1, FewerElements
};
566 // The following needs to be a loop, as for now, we do allow needing to
567 // go over "Unsupported" bit sizes before finding a legalizable bit size.
568 // e.g. (s8, WidenScalar), (s9, Unsupported), (s32, Legal). if Size==8,
569 // we need to iterate over s9, and then to s32 to return (s32, Legal).
570 // If we want to get rid of the below loop, we should have stronger asserts
571 // when building the SizeAndActionsVecs, probably not allowing
572 // "Unsupported" unless at the ends of the vector.
573 for (int i
= VecIdx
- 1; i
>= 0; --i
)
574 if (!needsLegalizingToDifferentSize(Vec
[i
].second
) &&
575 Vec
[i
].second
!= Unsupported
)
576 return {Vec
[i
].first
, Action
};
577 llvm_unreachable("");
581 // See above, the following needs to be a loop, at least for now.
582 for (std::size_t i
= VecIdx
+ 1; i
< Vec
.size(); ++i
)
583 if (!needsLegalizingToDifferentSize(Vec
[i
].second
) &&
584 Vec
[i
].second
!= Unsupported
)
585 return {Vec
[i
].first
, Action
};
586 llvm_unreachable("");
589 return {Size
, Unsupported
};
592 llvm_unreachable("NotFound");
594 llvm_unreachable("Action has an unknown enum value");
597 std::pair
<LegalizeAction
, LLT
>
598 LegalizerInfo::findScalarLegalAction(const InstrAspect
&Aspect
) const {
599 assert(Aspect
.Type
.isScalar() || Aspect
.Type
.isPointer());
600 if (Aspect
.Opcode
< FirstOp
|| Aspect
.Opcode
> LastOp
)
601 return {NotFound
, LLT()};
602 const unsigned OpcodeIdx
= getOpcodeIdxForOpcode(Aspect
.Opcode
);
603 if (Aspect
.Type
.isPointer() &&
604 AddrSpace2PointerActions
[OpcodeIdx
].find(Aspect
.Type
.getAddressSpace()) ==
605 AddrSpace2PointerActions
[OpcodeIdx
].end()) {
606 return {NotFound
, LLT()};
608 const SmallVector
<SizeAndActionsVec
, 1> &Actions
=
609 Aspect
.Type
.isPointer()
610 ? AddrSpace2PointerActions
[OpcodeIdx
]
611 .find(Aspect
.Type
.getAddressSpace())
613 : ScalarActions
[OpcodeIdx
];
614 if (Aspect
.Idx
>= Actions
.size())
615 return {NotFound
, LLT()};
616 const SizeAndActionsVec
&Vec
= Actions
[Aspect
.Idx
];
617 // FIXME: speed up this search, e.g. by using a results cache for repeated
619 auto SizeAndAction
= findAction(Vec
, Aspect
.Type
.getSizeInBits());
620 return {SizeAndAction
.second
,
621 Aspect
.Type
.isScalar() ? LLT::scalar(SizeAndAction
.first
)
622 : LLT::pointer(Aspect
.Type
.getAddressSpace(),
623 SizeAndAction
.first
)};
626 std::pair
<LegalizeAction
, LLT
>
627 LegalizerInfo::findVectorLegalAction(const InstrAspect
&Aspect
) const {
628 assert(Aspect
.Type
.isVector());
629 // First legalize the vector element size, then legalize the number of
630 // lanes in the vector.
631 if (Aspect
.Opcode
< FirstOp
|| Aspect
.Opcode
> LastOp
)
632 return {NotFound
, Aspect
.Type
};
633 const unsigned OpcodeIdx
= getOpcodeIdxForOpcode(Aspect
.Opcode
);
634 const unsigned TypeIdx
= Aspect
.Idx
;
635 if (TypeIdx
>= ScalarInVectorActions
[OpcodeIdx
].size())
636 return {NotFound
, Aspect
.Type
};
637 const SizeAndActionsVec
&ElemSizeVec
=
638 ScalarInVectorActions
[OpcodeIdx
][TypeIdx
];
640 LLT IntermediateType
;
641 auto ElementSizeAndAction
=
642 findAction(ElemSizeVec
, Aspect
.Type
.getScalarSizeInBits());
644 LLT::vector(Aspect
.Type
.getNumElements(), ElementSizeAndAction
.first
);
645 if (ElementSizeAndAction
.second
!= Legal
)
646 return {ElementSizeAndAction
.second
, IntermediateType
};
648 auto i
= NumElements2Actions
[OpcodeIdx
].find(
649 IntermediateType
.getScalarSizeInBits());
650 if (i
== NumElements2Actions
[OpcodeIdx
].end()) {
651 return {NotFound
, IntermediateType
};
653 const SizeAndActionsVec
&NumElementsVec
= (*i
).second
[TypeIdx
];
654 auto NumElementsAndAction
=
655 findAction(NumElementsVec
, IntermediateType
.getNumElements());
656 return {NumElementsAndAction
.second
,
657 LLT::vector(NumElementsAndAction
.first
,
658 IntermediateType
.getScalarSizeInBits())};
661 bool LegalizerInfo::legalizeIntrinsic(MachineInstr
&MI
,
662 MachineRegisterInfo
&MRI
,
663 MachineIRBuilder
&MIRBuilder
) const {
667 /// \pre Type indices of every opcode form a dense set starting from 0.
668 void LegalizerInfo::verify(const MCInstrInfo
&MII
) const {
670 std::vector
<unsigned> FailedOpcodes
;
671 for (unsigned Opcode
= FirstOp
; Opcode
<= LastOp
; ++Opcode
) {
672 const MCInstrDesc
&MCID
= MII
.get(Opcode
);
673 const unsigned NumTypeIdxs
= std::accumulate(
674 MCID
.opInfo_begin(), MCID
.opInfo_end(), 0U,
675 [](unsigned Acc
, const MCOperandInfo
&OpInfo
) {
676 return OpInfo
.isGenericType()
677 ? std::max(OpInfo
.getGenericTypeIndex() + 1U, Acc
)
680 LLVM_DEBUG(dbgs() << MII
.getName(Opcode
) << " (opcode " << Opcode
681 << "): " << NumTypeIdxs
<< " type ind"
682 << (NumTypeIdxs
== 1 ? "ex" : "ices") << "\n");
683 const LegalizeRuleSet
&RuleSet
= getActionDefinitions(Opcode
);
684 if (!RuleSet
.verifyTypeIdxsCoverage(NumTypeIdxs
))
685 FailedOpcodes
.push_back(Opcode
);
687 if (!FailedOpcodes
.empty()) {
688 errs() << "The following opcodes have ill-defined legalization rules:";
689 for (unsigned Opcode
: FailedOpcodes
)
690 errs() << " " << MII
.getName(Opcode
);
693 report_fatal_error("ill-defined LegalizerInfo"
694 ", try -debug-only=legalizer-info for details");
700 // FIXME: This should be in the MachineVerifier, but it can't use the
701 // LegalizerInfo as it's currently in the separate GlobalISel library.
702 // Note that RegBankSelected property already checked in the verifier
703 // has the same layering problem, but we only use inline methods so
704 // end up not needing to link against the GlobalISel library.
705 const MachineInstr
*llvm::machineFunctionIsIllegal(const MachineFunction
&MF
) {
706 if (const LegalizerInfo
*MLI
= MF
.getSubtarget().getLegalizerInfo()) {
707 const MachineRegisterInfo
&MRI
= MF
.getRegInfo();
708 for (const MachineBasicBlock
&MBB
: MF
)
709 for (const MachineInstr
&MI
: MBB
)
710 if (isPreISelGenericOpcode(MI
.getOpcode()) &&
711 !MLI
->isLegalOrCustom(MI
, MRI
))