summaryrefslogtreecommitdiff
path: root/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/CodeGen/GlobalISel/InstructionSelector.h')
-rw-r--r--include/llvm/CodeGen/GlobalISel/InstructionSelector.h124
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