diff options
Diffstat (limited to 'include/llvm/CodeGen/GlobalISel/InstructionSelector.h')
| -rw-r--r-- | include/llvm/CodeGen/GlobalISel/InstructionSelector.h | 124 |
1 files changed, 116 insertions, 8 deletions
diff --git a/include/llvm/CodeGen/GlobalISel/InstructionSelector.h b/include/llvm/CodeGen/GlobalISel/InstructionSelector.h index 1060d8fd667e..e599a1b179ec 100644 --- a/include/llvm/CodeGen/GlobalISel/InstructionSelector.h +++ b/include/llvm/CodeGen/GlobalISel/InstructionSelector.h @@ -16,7 +16,10 @@ #ifndef LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H #define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/CodeGenCoverage.h" #include <bitset> #include <cstddef> #include <cstdint> @@ -26,9 +29,12 @@ namespace llvm { +class APInt; +class APFloat; class LLT; class MachineInstr; class MachineInstrBuilder; +class MachineFunction; class MachineOperand; class MachineRegisterInfo; class RegisterBankInfo; @@ -63,6 +69,18 @@ public: }; enum { + /// Begin a try-block to attempt a match and jump to OnFail if it is + /// unsuccessful. + /// - OnFail - The MatchTable entry at which to resume if the match fails. + /// + /// FIXME: This ought to take an argument indicating the number of try-blocks + /// to exit on failure. It's usually one but the last match attempt of + /// a block will need more. The (implemented) alternative is to tack a + /// GIM_Reject on the end of each try-block which is simpler but + /// requires an extra opcode and iteration in the interpreter on each + /// failed match. + GIM_Try, + /// Record the specified instruction /// - NewInsnID - Instruction ID to define /// - InsnID - Instruction ID @@ -81,12 +99,35 @@ enum { /// - InsnID - Instruction ID /// - Expected number of operands GIM_CheckNumOperands, + /// Check an immediate predicate on the specified instruction + /// - InsnID - Instruction ID + /// - The predicate to test + GIM_CheckI64ImmPredicate, + /// Check an immediate predicate on the specified instruction via an APInt. + /// - InsnID - Instruction ID + /// - The predicate to test + GIM_CheckAPIntImmPredicate, + /// Check a floating point immediate predicate on the specified instruction. + /// - InsnID - Instruction ID + /// - The predicate to test + GIM_CheckAPFloatImmPredicate, + /// Check a memory operation has the specified atomic ordering. + /// - InsnID - Instruction ID + /// - Ordering - The AtomicOrdering value + GIM_CheckAtomicOrdering, + GIM_CheckAtomicOrderingOrStrongerThan, + GIM_CheckAtomicOrderingWeakerThan, /// Check the type for the specified operand /// - InsnID - Instruction ID /// - OpIdx - Operand index /// - Expected type GIM_CheckType, + /// Check the type of a pointer to any address space. + /// - InsnID - Instruction ID + /// - OpIdx - Operand index + /// - SizeInBits - The size of the pointer value in bits. + GIM_CheckPointerToAny, /// Check the register bank for the specified operand /// - InsnID - Instruction ID /// - OpIdx - Operand index @@ -124,6 +165,17 @@ enum { /// - InsnID - Instruction ID GIM_CheckIsSafeToFold, + /// Check the specified operands are identical. + /// - InsnID - Instruction ID + /// - OpIdx - Operand index + /// - OtherInsnID - Other instruction ID + /// - OtherOpIdx - Other operand index + GIM_CheckIsSameOperand, + + /// Fail the current try-block, or completely fail to match if there is no + /// current try-block. + GIM_Reject, + //=== Renderers === /// Mutate an instruction @@ -141,6 +193,13 @@ enum { /// - OldInsnID - Instruction ID to copy from /// - OpIdx - The operand to copy GIR_Copy, + /// Copy an operand to the specified instruction or add a zero register if the + /// operand is a zero immediate. + /// - NewInsnID - Instruction ID to modify + /// - OldInsnID - Instruction ID to copy from + /// - OpIdx - The operand to copy + /// - ZeroReg - The zero register to use + GIR_CopyOrAddZeroReg, /// Copy an operand to the specified instruction /// - NewInsnID - Instruction ID to modify /// - OldInsnID - Instruction ID to copy from @@ -159,6 +218,10 @@ enum { /// - InsnID - Instruction ID to modify /// - RegNum - The register to add GIR_AddRegister, + /// Add a a temporary register to the specified instruction + /// - InsnID - Instruction ID to modify + /// - TempRegID - The temporary register ID to add + GIR_AddTempRegister, /// Add an immediate to the specified instruction /// - InsnID - Instruction ID to modify /// - Imm - The immediate to add @@ -167,6 +230,17 @@ enum { /// - InsnID - Instruction ID to modify /// - RendererID - The renderer to call GIR_ComplexRenderer, + /// Render sub-operands of complex operands to the specified instruction + /// - InsnID - Instruction ID to modify + /// - RendererID - The renderer to call + /// - RenderOpID - The suboperand to render. + GIR_ComplexSubOperandRenderer, + + /// Render a G_CONSTANT operator as a sign-extended immediate. + /// - NewInsnID - Instruction ID to modify + /// - OldInsnID - Instruction ID to copy from + /// The operand index is implicitly 1. + GIR_CopyConstantAsSImm, /// Constrain an instruction operand to a register class. /// - InsnID - Instruction ID to modify @@ -179,18 +253,39 @@ enum { GIR_ConstrainSelectedInstOperands, /// Merge all memory operands into instruction. /// - InsnID - Instruction ID to modify + /// - MergeInsnID... - One or more Instruction ID to merge into the result. + /// - GIU_MergeMemOperands_EndOfList - Terminates the list of instructions to + /// merge. GIR_MergeMemOperands, /// Erase from parent. /// - InsnID - Instruction ID to erase GIR_EraseFromParent, + /// Create a new temporary register that's not constrained. + /// - TempRegID - The temporary register ID to initialize. + /// - Expected type + GIR_MakeTempReg, /// A successful emission GIR_Done, + + /// Increment the rule coverage counter. + /// - RuleID - The ID of the rule that was covered. + GIR_Coverage, +}; + +enum { + /// Indicates the end of the variable-length MergeInsnID list in a + /// GIR_MergeMemOperands opcode. + GIU_MergeMemOperands_EndOfList = -1, }; /// Provides the logic to select generic machine instructions. class InstructionSelector { public: + using I64ImmediatePredicateFn = bool (*)(int64_t); + using APIntImmediatePredicateFn = bool (*)(const APInt &); + using APFloatImmediatePredicateFn = bool (*)(const APFloat &); + virtual ~InstructionSelector() = default; /// Select the (possibly generic) instruction \p I to only use target-specific @@ -203,17 +298,18 @@ public: /// if returns true: /// for I in all mutated/inserted instructions: /// !isPreISelGenericOpcode(I.getOpcode()) - /// - virtual bool select(MachineInstr &I) const = 0; + virtual bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const = 0; protected: - using ComplexRendererFn = std::function<void(MachineInstrBuilder &)>; + using ComplexRendererFns = + Optional<SmallVector<std::function<void(MachineInstrBuilder &)>, 4>>; using RecordedMIVector = SmallVector<MachineInstr *, 4>; using NewMIVector = SmallVector<MachineInstrBuilder, 4>; struct MatcherState { - std::vector<ComplexRendererFn> Renderers; + std::vector<ComplexRendererFns::value_type> Renderers; RecordedMIVector MIs; + DenseMap<unsigned, unsigned> TempRegisters; MatcherState(unsigned MaxRenderers); }; @@ -223,7 +319,10 @@ public: struct MatcherInfoTy { const LLT *TypeObjects; const PredicateBitset *FeatureBitsets; - const std::vector<ComplexMatcherMemFn> ComplexPredicates; + const I64ImmediatePredicateFn *I64ImmPredicateFns; + const APIntImmediatePredicateFn *APIntImmPredicateFns; + const APFloatImmediatePredicateFn *APFloatImmPredicateFns; + const ComplexMatcherMemFn *ComplexPredicates; }; protected: @@ -238,8 +337,8 @@ protected: const MatcherInfoTy<PredicateBitset, ComplexMatcherMemFn> &MatcherInfo, const int64_t *MatchTable, const TargetInstrInfo &TII, MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, - const RegisterBankInfo &RBI, - const PredicateBitset &AvailableFeatures) const; + const RegisterBankInfo &RBI, const PredicateBitset &AvailableFeatures, + CodeGenCoverage &CoverageInfo) const; /// Constrain a register operand of an instruction \p I to a specified /// register class. This could involve inserting COPYs before (for uses) or @@ -268,7 +367,16 @@ protected: bool isOperandImmEqual(const MachineOperand &MO, int64_t Value, const MachineRegisterInfo &MRI) const; - bool isObviouslySafeToFold(MachineInstr &MI) const; + /// Return true if the specified operand is a G_GEP with a G_CONSTANT on the + /// right-hand side. GlobalISel's separation of pointer and integer types + /// means that we don't need to worry about G_OR with equivalent semantics. + bool isBaseWithConstantOffset(const MachineOperand &Root, + const MachineRegisterInfo &MRI) const; + + /// Return true if MI can obviously be folded into IntoMI. + /// MI and IntoMI do not need to be in the same basic blocks, but MI must + /// preceed IntoMI. + bool isObviouslySafeToFold(MachineInstr &MI, MachineInstr &IntoMI) const; }; } // end namespace llvm |
