30#define DEBUG_TYPE "legalizer-info"
33 "disable-gisel-legality-check",
34 cl::desc(
"Don't verify that MIR is fully legal between GlobalISel passes"),
38 "verbose-gisel-verify-legalizer-info",
39 cl::desc(
"Print more information to dbgs about GlobalISel legalizer rules "
55 OS <<
"FewerElements";
83 OS <<
"Opcode=" <<
Opcode <<
", Tys={";
89 OS << MMODescr.MemoryTy <<
", ";
103 const std::pair<unsigned, LLT> &
Mutation) {
121 std::pair<unsigned, LLT>
Mutation) {
131 const unsigned TypeIdx =
Mutation.first;
198 if (Rule.match(Query)) {
200 std::pair<unsigned, LLT>
Mutation = Rule.determineMutation(Query);
204 "legality mutation invalid for match");
211 return {LegalizeAction::Unsupported, 0,
LLT{}};
219 <<
"no rules defined\n");
223 const int64_t FirstUncovered = TypeIdxsCovered.find_first_unset();
224 if (FirstUncovered < 0) {
227 " user-defined predicate detected\n");
231 const bool AllCovered = (FirstUncovered >= NumTypeIdxs);
232 if (NumTypeIdxs > 0) {
235 << FirstUncovered <<
", "
236 << (AllCovered ?
"OK" :
"FAIL") <<
"\n");
250 <<
"no rules defined\n");
254 const int64_t FirstUncovered = ImmIdxsCovered.find_first_unset();
255 if (FirstUncovered < 0) {
258 " user-defined predicate detected\n");
262 const bool AllCovered = (FirstUncovered >= NumImmIdxs);
264 LLVM_DEBUG(
dbgs() <<
".. the first uncovered imm index: " << FirstUncovered
265 <<
", " << (AllCovered ?
"OK" :
"FAIL") <<
"\n");
277 assert(TypeIdx <
MI.getNumOperands() &&
"Unexpected TypeIdx");
281 if (
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES && TypeIdx == 1)
282 return MRI.
getType(
MI.getOperand(
MI.getNumOperands() - 1).getReg());
287 assert(Opcode >= FirstOp && Opcode <= LastOp &&
"Unsupported opcode");
288 return Opcode - FirstOp;
293 if (
unsigned Alias = RulesForOpcode[OpcodeIdx].getAlias()) {
295 LLVM_DEBUG(
dbgs() <<
".. opcode " << Opcode <<
" is aliased to " << Alias
299 assert(RulesForOpcode[OpcodeIdx].getAlias() == 0 &&
"Cannot chain aliases");
308 return RulesForOpcode[OpcodeIdx];
313 auto &Result = RulesForOpcode[OpcodeIdx];
314 assert(!Result.isAliasedByAnother() &&
"Modifying this opcode will modify aliases");
319 std::initializer_list<unsigned> Opcodes) {
320 unsigned Representative = *Opcodes.begin();
322 assert(Opcodes.size() >= 2 &&
323 "Initializer list must have at least two opcodes");
329 Return.setIsAliasedByAnother();
334 unsigned OpcodeFrom) {
335 assert(OpcodeTo != OpcodeFrom &&
"Cannot alias to self");
336 assert(OpcodeTo >= FirstOp && OpcodeTo <= LastOp &&
"Unsupported opcode");
338 RulesForOpcode[OpcodeFromIdx].aliasTo(OpcodeTo);
354 for (
unsigned i = 0; i <
MI.getDesc().getNumOperands(); ++i) {
355 if (OpInfo[i].isGenericType()) {
358 unsigned TypeIdx = OpInfo[i].getGenericTypeIndex();
359 if (SeenTypes[TypeIdx])
362 SeenTypes.
set(TypeIdx);
366 }
else if (OpInfo[i].isGenericImm()) {
372 for (
const auto &MMO :
MI.memoperands())
375 return getAction({
MI.getOpcode(), Types, MemDescrs, Immediates});
392 return SmallTy.
isByteSized() ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
398 std::vector<unsigned> FailedOpcodes;
399 for (
unsigned Opcode = FirstOp; Opcode <= LastOp; ++Opcode) {
401 const unsigned NumTypeIdxs = std::accumulate(
402 MCID.operands().begin(),
MCID.operands().end(), 0U,
404 return OpInfo.isGenericType()
405 ? std::max(OpInfo.getGenericTypeIndex() + 1U, Acc)
408 const unsigned NumImmIdxs = std::accumulate(
409 MCID.operands().begin(),
MCID.operands().end(), 0U,
411 return OpInfo.isGenericImm()
412 ? std::max(OpInfo.getGenericImmIndex() + 1U, Acc)
417 <<
"): " << NumTypeIdxs <<
" type ind"
418 << (NumTypeIdxs == 1 ?
"ex" :
"ices") <<
", "
419 << NumImmIdxs <<
" imm ind"
420 << (NumImmIdxs == 1 ?
"ex" :
"ices") <<
"\n");
424 FailedOpcodes.push_back(Opcode);
426 FailedOpcodes.push_back(Opcode);
428 if (!FailedOpcodes.empty()) {
429 errs() <<
"The following opcodes have ill-defined legalization rules:";
430 for (
unsigned Opcode : FailedOpcodes)
435 "-debug-only=legalizer-info and "
436 "-verbose-gisel-verify-legalizer-info for details");
453 !MLI->isLegalOrCustom(
MI, MRI))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static cl::opt< bool > VerboseVerifyLegalizerInfo("verbose-gisel-verify-legalizer-info", cl::desc("Print more information to dbgs about GlobalISel legalizer rules " "being verified"), cl::Hidden)
static bool hasNoSimpleLoops(const LegalizeRule &Rule, const LegalityQuery &Q, const std::pair< unsigned, LLT > &Mutation)
static LLT getTypeFromTypeIdx(const MachineInstr &MI, const MachineRegisterInfo &MRI, unsigned OpIdx, unsigned TypeIdx)
Helper function to get LLT for the given type index.
static bool mutationIsSane(const LegalizeRule &Rule, const LegalityQuery &Q, std::pair< unsigned, LLT > Mutation)
Interface for Targets to specify which operations they can successfully select and how the others sho...
Implement a low-level type suitable for MachineInstr level instruction selection.
MachineInstr unsigned OpIdx
This file implements the SmallBitVector class.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
static constexpr ElementCount getFixed(ScalarTy MinVal)
constexpr unsigned getScalarSizeInBits() const
LLT getScalarType() const
constexpr bool isVector() const
constexpr bool isByteSized() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr ElementCount getElementCount() const
LLVM_ABI bool verifyImmIdxsCoverage(unsigned NumImmIdxs) const
Check if there is no imm index which is obviously not handled by the LegalizeRuleSet in any way at al...
LLVM_ABI 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...
LLVM_ABI LegalizeActionStep apply(const LegalityQuery &Query) const
Apply the ruleset to the given LegalityQuery.
A single rule in a legalizer info ruleset.
LegalizeAction getAction() const
const LegalizeRuleSet & getActionDefinitions(unsigned Opcode) const
Get the action definitions for the given opcode.
LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)
Get the action definition builder for the given opcode.
virtual unsigned getExtOpcodeForWideningConstant(LLT SmallTy) const
Return the opcode (SEXT/ZEXT/ANYEXT) that should be performed while widening a constant of type Small...
bool isLegalOrCustom(const LegalityQuery &Query) const
void aliasActionDefinitions(unsigned OpcodeTo, unsigned OpcodeFrom)
void verify(const MCInstrInfo &MII) const
Perform simple self-diagnostic and assert if there is anything obviously wrong with the actions set u...
unsigned getOpcodeIdxForOpcode(unsigned Opcode) const
bool isLegal(const LegalityQuery &Query) const
unsigned getActionDefinitionsIdx(unsigned Opcode) const
LegalizeActionStep getAction(const LegalityQuery &Query) const
Determine what action should be taken to legalize the described instruction.
Describe properties that are true of each instruction in the target description file.
Interface to description of machine instruction set.
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
This holds information about one operand of a machine instruction, indicating the register class for ...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Representation of each machine instruction.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
virtual const LegalizerInfo * getLegalizerInfo() const
The instances of the Type class are immutable: once they are created, they are never changed.
static constexpr bool isKnownLE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
static constexpr bool isKnownGE(const FixedOrScalableQuantity &LHS, const FixedOrScalableQuantity &RHS)
This class implements an extremely fast bulk output stream that can only output to a stream.
@ FewerElements
The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...
@ Legal
The operation is expected to be selectable directly by the target, and no transformation is necessary...
@ Libcall
The operation should be implemented as a call to some kind of runtime support library.
@ Unsupported
This operation is completely unsupported on the target.
@ Lower
The operation itself must be expressed in terms of simpler actions on this target.
@ WidenScalar
The operation should be implemented in terms of a wider scalar base-type.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
@ NarrowScalar
The operation should be synthesized from multiple instructions acting on a narrower scalar base-type.
@ Custom
The target wants to do something special with this combination of operand and type.
@ NotFound
Sentinel value for when no action was found in the specified table.
@ MoreElements
The (vector) operation should be implemented by widening the input vector and ignoring the lanes adde...
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel.
LLVM_ABI cl::opt< bool > DisableGISelLegalityCheck
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
const MachineInstr * machineFunctionIsIllegal(const MachineFunction &MF)
Checks that MIR is fully legal, returns an illegal instruction if it's not, nullptr otherwise.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
DWARFExpression::Operation Op
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
@ Custom
The result value requires a custom uniformity check.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
ArrayRef< int64_t > Immediates
ArrayRef< MemDesc > MMODescrs
Operations which require memory can use this to place requirements on the memory type for each MMO.
LLVM_ABI raw_ostream & print(raw_ostream &OS) const
LegalizeAction Action
The action to take or the final answer.