Go to the documentation of this file.
28 using namespace LegalizeActions;
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"),
49 OS <<
"FewerElements";
73 OS <<
"UseLegacyRules";
80 OS << Opcode <<
", Tys={";
81 for (
const auto &
Type : Types) {
86 OS << Opcode <<
", MMOs={";
87 for (
const auto &MMODescr : MMODescrs) {
88 OS << MMODescr.MemoryTy <<
", ";
98 const std::pair<unsigned, LLT> &
Mutation) {
115 std::pair<unsigned, LLT>
Mutation) {
121 const unsigned TypeIdx =
Mutation.first;
187 LLVM_DEBUG(
dbgs() <<
".. fallback to legacy rules (no rules defined)\n");
191 if (Rule.match(Query)) {
193 std::pair<unsigned, LLT>
Mutation = Rule.determineMutation(Query);
197 "legality mutation invalid for match");
211 dbgs() <<
".. type index coverage check SKIPPED: no rules defined\n");
214 const int64_t FirstUncovered = TypeIdxsCovered.find_first_unset();
215 if (FirstUncovered < 0) {
217 " user-defined predicate detected\n");
220 const bool AllCovered = (FirstUncovered >= NumTypeIdxs);
222 LLVM_DEBUG(
dbgs() <<
".. the first uncovered type index: " << FirstUncovered
223 <<
", " << (AllCovered ?
"OK" :
"FAIL") <<
"\n");
234 dbgs() <<
".. imm index coverage check SKIPPED: no rules defined\n");
237 const int64_t FirstUncovered = ImmIdxsCovered.find_first_unset();
238 if (FirstUncovered < 0) {
240 " user-defined predicate detected\n");
243 const bool AllCovered = (FirstUncovered >= NumImmIdxs);
244 LLVM_DEBUG(
dbgs() <<
".. the first uncovered imm index: " << FirstUncovered
245 <<
", " << (AllCovered ?
"OK" :
"FAIL") <<
"\n");
256 assert(TypeIdx <
MI.getNumOperands() &&
"Unexpected TypeIdx");
260 if (
MI.getOpcode() == TargetOpcode::G_UNMERGE_VALUES && TypeIdx == 1)
261 return MRI.
getType(
MI.getOperand(
MI.getNumOperands() - 1).getReg());
266 assert(Opcode >= FirstOp && Opcode <= LastOp &&
"Unsupported opcode");
267 return Opcode - FirstOp;
271 unsigned OpcodeIdx = getOpcodeIdxForOpcode(Opcode);
272 if (
unsigned Alias = RulesForOpcode[OpcodeIdx].getAlias()) {
273 LLVM_DEBUG(
dbgs() <<
".. opcode " << Opcode <<
" is aliased to " << Alias
275 OpcodeIdx = getOpcodeIdxForOpcode(Alias);
276 assert(RulesForOpcode[OpcodeIdx].getAlias() == 0 &&
"Cannot chain aliases");
284 unsigned OpcodeIdx = getActionDefinitionsIdx(Opcode);
285 return RulesForOpcode[OpcodeIdx];
289 unsigned OpcodeIdx = getActionDefinitionsIdx(Opcode);
290 auto &Result = RulesForOpcode[OpcodeIdx];
291 assert(!Result.isAliasedByAnother() &&
"Modifying this opcode will modify aliases");
296 std::initializer_list<unsigned> Opcodes) {
297 unsigned Representative = *Opcodes.begin();
300 "Initializer list must have at least two opcodes");
303 aliasActionDefinitions(Representative,
Op);
305 auto &Return = getActionDefinitionsBuilder(Representative);
306 Return.setIsAliasedByAnother();
311 unsigned OpcodeFrom) {
312 assert(OpcodeTo != OpcodeFrom &&
"Cannot alias to self");
313 assert(OpcodeTo >= FirstOp && OpcodeTo <= LastOp &&
"Unsupported opcode");
314 const unsigned OpcodeFromIdx = getOpcodeIdxForOpcode(OpcodeFrom);
315 RulesForOpcode[OpcodeFromIdx].aliasTo(OpcodeTo);
325 return getLegacyLegalizerInfo().getAction(Query);
335 for (
unsigned i = 0;
i <
MI.getDesc().getNumOperands(); ++
i) {
336 if (!OpInfo[
i].isGenericType())
342 if (SeenTypes[TypeIdx])
345 SeenTypes.
set(TypeIdx);
352 for (
const auto &MMO :
MI.memoperands())
353 MemDescrs.push_back({*MMO});
355 return getAction({
MI.getOpcode(), Types, MemDescrs});
365 auto Action = getAction(
MI,
MRI).Action;
372 return SmallTy.
isByteSized() ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
378 std::vector<unsigned> FailedOpcodes;
379 for (
unsigned Opcode = FirstOp; Opcode <= LastOp; ++Opcode) {
381 const unsigned NumTypeIdxs = std::accumulate(
384 return OpInfo.isGenericType()
385 ? std::max(OpInfo.getGenericTypeIndex() + 1U, Acc)
388 const unsigned NumImmIdxs = std::accumulate(
391 return OpInfo.isGenericImm()
392 ? std::max(OpInfo.getGenericImmIndex() + 1U, Acc)
396 <<
"): " << NumTypeIdxs <<
" type ind"
397 << (NumTypeIdxs == 1 ?
"ex" :
"ices") <<
", "
398 << NumImmIdxs <<
" imm ind"
399 << (NumImmIdxs == 1 ?
"ex" :
"ices") <<
"\n");
402 FailedOpcodes.push_back(Opcode);
404 FailedOpcodes.push_back(Opcode);
406 if (!FailedOpcodes.empty()) {
407 errs() <<
"The following opcodes have ill-defined legalization rules:";
408 for (
unsigned Opcode : FailedOpcodes)
413 ", try -debug-only=legalizer-info for details");
430 !MLI->isLegalOrCustom(
MI,
MRI))
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.
unsigned getOpcodeIdxForOpcode(unsigned Opcode) const
unsigned getScalarSizeInBits() const
@ MoreElements
The (vector) operation should be implemented by widening the input vector and ignoring the lanes adde...
LegalizeRuleSet & getActionDefinitionsBuilder(unsigned Opcode)
Get the action definition builder for the given opcode.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LegalizeAction Action
The action to take or the final answer.
const_opInfo_iterator opInfo_end() const
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
static bool isKnownLE(const LinearPolySize &LHS, const LinearPolySize &RHS)
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel.
@ NarrowScalar
The operation should be synthesized from multiple instructions acting on a narrower scalar base-type.
cl::opt< bool > DisableGISelLegalityCheck
LLT getScalarType() const
The instances of the Type class are immutable: once they are created, they are never changed.
@ WidenScalar
The operation should be implemented in terms of a wider scalar base-type.
@ UseLegacyRules
Fall back onto the old rules.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LegalizeActionStep apply(const LegalityQuery &Query) const
Apply the ruleset to the given LegalityQuery.
This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...
This holds information about one operand of a machine instruction, indicating the register class for ...
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
A single rule in a legalizer info ruleset.
@ NotFound
Sentinel value for when no action was found in the specified table.
TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Describe properties that are true of each instruction in the target description file.
const MachineInstr * machineFunctionIsIllegal(const MachineFunction &MF)
Checks that MIR is fully legal, returns an illegal instruction if it's not, nullptr otherwise.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
@ Libcall
The operation should be implemented as a call to some kind of runtime support library.
@ Custom
The target wants to do something special with this combination of operand and type.
virtual unsigned getExtOpcodeForWideningConstant(LLT SmallTy) const
Return the opcode (SEXT/ZEXT/ANYEXT) that should be performed while widening a constant of type Small...
@ Legal
The operation is expected to be selectable directly by the target, and no transformation is necessary...
static ElementCount getFixed(ScalarTy MinVal)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Representation of each machine instruction.
@ Bitcast
Perform the operation on a different, but equivalently sized type.
uint16_t getNumElements() const
Returns the number of elements in a vector LLT.
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...
static LLT getTypeFromTypeIdx(const MachineInstr &MI, const MachineRegisterInfo &MRI, unsigned OpIdx, unsigned TypeIdx)
Helper function to get LLT for the given type index.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LegalizeActionStep getAction(const LegalityQuery &Query) const
Determine what action should be taken to legalize the described instruction.
static bool isKnownGE(const LinearPolySize &LHS, const LinearPolySize &RHS)
static bool hasNoSimpleLoops(const LegalizeRule &Rule, const LegalityQuery &Q, const std::pair< unsigned, LLT > &Mutation)
StringRef getName(unsigned Opcode) const
Returns the name for the instructions with the given opcode.
The LegalityQuery object bundles together all the information that's needed to decide whether a given...
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
unsigned const MachineRegisterInfo * MRI
virtual const LegalizerInfo * getLegalizerInfo() const
unsigned getGenericTypeIndex() const
Interface to description of machine instruction set.
constexpr bool empty(const T &RangeOrContainer)
Test whether RangeOrContainer is empty. Similar to C++17 std::empty.
LegalizeAction getAction() const
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...
@ FewerElements
The (vector) operation should be implemented by splitting it into sub-vectors where the operation is ...
const_opInfo_iterator opInfo_begin() const
@ Unsupported
This operation is completely unsupported on the target.
void verify(const MCInstrInfo &MII) const
Perform simple self-diagnostic and assert if there is anything obviously wrong with the actions set u...
raw_ostream & print(raw_ostream &OS) const
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
void aliasActionDefinitions(unsigned OpcodeTo, unsigned OpcodeFrom)
ElementCount getElementCount() const
const LegalizeRuleSet & getActionDefinitions(unsigned Opcode) const
Get the action definitions for the given opcode.
bool isLegalOrCustom(const LegalityQuery &Query) const
@ Unsupported
This operation is completely unsupported on the target.
static bool mutationIsSane(const LegalizeRule &Rule, const LegalityQuery &Q, std::pair< unsigned, LLT > Mutation)
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
@ Lower
The operation itself must be expressed in terms of simpler actions on this target.
bool isLegal(const LegalityQuery &Query) const
unsigned getActionDefinitionsIdx(unsigned Opcode) const