378 lines
16 KiB
TableGen
378 lines
16 KiB
TableGen
|
//===- TargetInstrPredicate.td - ---------------------------*- tablegen -*-===//
|
||
|
//
|
||
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||
|
// See https://llvm.org/LICENSE.txt for license information.
|
||
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
//
|
||
|
// This file defines class MCInstPredicate and its subclasses.
|
||
|
//
|
||
|
// MCInstPredicate definitions are used by target scheduling models to describe
|
||
|
// constraints on instructions.
|
||
|
//
|
||
|
// Here is an example of an MCInstPredicate definition in TableGen:
|
||
|
//
|
||
|
// def MCInstPredicateExample : CheckAll<[
|
||
|
// CheckOpcode<[BLR]>,
|
||
|
// CheckIsRegOperand<0>,
|
||
|
// CheckNot<CheckRegOperand<0, LR>>]>;
|
||
|
//
|
||
|
// The syntax for MCInstPredicate is declarative, and predicate definitions can
|
||
|
// be composed together in order to generate more complex constraints.
|
||
|
//
|
||
|
// The `CheckAll` from the example defines a composition of three different
|
||
|
// predicates. Definition `MCInstPredicateExample` identifies instructions
|
||
|
// whose opcode is BLR, and whose first operand is a register different from
|
||
|
// register `LR`.
|
||
|
//
|
||
|
// Every MCInstPredicate class has a well-known semantic in tablegen. For
|
||
|
// example, `CheckOpcode` is a special type of predicate used to describe a
|
||
|
// constraint on the value of an instruction opcode.
|
||
|
//
|
||
|
// MCInstPredicate definitions are typically used by scheduling models to
|
||
|
// construct MCSchedPredicate definitions (see the definition of class
|
||
|
// MCSchedPredicate in llvm/Target/TargetSchedule.td).
|
||
|
// In particular, an MCSchedPredicate can be used instead of a SchedPredicate
|
||
|
// when defining the set of SchedReadVariant and SchedWriteVariant of a
|
||
|
// processor scheduling model.
|
||
|
//
|
||
|
// The `MCInstPredicateExample` definition above is equivalent (and therefore
|
||
|
// could replace) the following definition from a previous ExynosM3 model (see
|
||
|
// AArch64SchedExynosM3.td):
|
||
|
//
|
||
|
// def M3BranchLinkFastPred : SchedPredicate<[{
|
||
|
// MI->getOpcode() == AArch64::BLR &&
|
||
|
// MI->getOperand(0).isReg() &&
|
||
|
// MI->getOperand(0).getReg() != AArch64::LR}]>;
|
||
|
//
|
||
|
// The main advantage of using MCInstPredicate instead of SchedPredicate is
|
||
|
// portability: users don't need to specify predicates in C++. As a consequence
|
||
|
// of this, MCInstPredicate definitions are not bound to a particular
|
||
|
// representation (i.e. MachineInstr vs MCInst).
|
||
|
//
|
||
|
// Tablegen backends know how to expand MCInstPredicate definitions into actual
|
||
|
// C++ code that works on MachineInstr (and/or MCInst).
|
||
|
//
|
||
|
// Instances of class PredicateExpander (see utils/Tablegen/PredicateExpander.h)
|
||
|
// know how to expand a predicate. For each MCInstPredicate class, there must be
|
||
|
// an "expand" method available in the PredicateExpander interface.
|
||
|
//
|
||
|
// For example, a `CheckOpcode` predicate is expanded using method
|
||
|
// `PredicateExpander::expandCheckOpcode()`.
|
||
|
//
|
||
|
// New MCInstPredicate classes must be added to this file. For each new class
|
||
|
// XYZ, an "expandXYZ" method must be added to the PredicateExpander.
|
||
|
//
|
||
|
//===----------------------------------------------------------------------===//
|
||
|
|
||
|
// Forward declarations.
|
||
|
class Instruction;
|
||
|
class SchedMachineModel;
|
||
|
|
||
|
// A generic machine instruction predicate.
|
||
|
class MCInstPredicate;
|
||
|
|
||
|
class MCTrue : MCInstPredicate; // A predicate that always evaluates to True.
|
||
|
class MCFalse : MCInstPredicate; // A predicate that always evaluates to False.
|
||
|
def TruePred : MCTrue;
|
||
|
def FalsePred : MCFalse;
|
||
|
|
||
|
// A predicate used to negate the outcome of another predicate.
|
||
|
// It allows to easily express "set difference" operations. For example, it
|
||
|
// makes it easy to describe a check that tests if an opcode is not part of a
|
||
|
// set of opcodes.
|
||
|
class CheckNot<MCInstPredicate P> : MCInstPredicate {
|
||
|
MCInstPredicate Pred = P;
|
||
|
}
|
||
|
|
||
|
// This class is used as a building block to define predicates on instruction
|
||
|
// operands. It is used to reference a specific machine operand.
|
||
|
class MCOperandPredicate<int Index> : MCInstPredicate {
|
||
|
int OpIndex = Index;
|
||
|
}
|
||
|
|
||
|
// Return true if machine operand at position `Index` is a register operand.
|
||
|
class CheckIsRegOperand<int Index> : MCOperandPredicate<Index>;
|
||
|
|
||
|
// Return true if machine operand at position `Index` is an immediate operand.
|
||
|
class CheckIsImmOperand<int Index> : MCOperandPredicate<Index>;
|
||
|
|
||
|
// Check if machine operands at index `First` and index `Second` both reference
|
||
|
// the same register.
|
||
|
class CheckSameRegOperand<int First, int Second> : MCInstPredicate {
|
||
|
int FirstIndex = First;
|
||
|
int SecondIndex = Second;
|
||
|
}
|
||
|
|
||
|
// Base class for checks on register/immediate operands.
|
||
|
// It allows users to define checks like:
|
||
|
// MyFunction(MI->getOperand(Index).getImm()) == Val;
|
||
|
//
|
||
|
// In the example above, `MyFunction` is a function that takes as input an
|
||
|
// immediate operand value, and returns another value. Field `FunctionMapper` is
|
||
|
// the name of the function to call on the operand value.
|
||
|
class CheckOperandBase<int Index, string Fn = ""> : MCOperandPredicate<Index> {
|
||
|
string FunctionMapper = Fn;
|
||
|
}
|
||
|
|
||
|
// Check that the machine register operand at position `Index` references
|
||
|
// register R. This predicate assumes that we already checked that the machine
|
||
|
// operand at position `Index` is a register operand.
|
||
|
class CheckRegOperand<int Index, Register R> : CheckOperandBase<Index> {
|
||
|
Register Reg = R;
|
||
|
}
|
||
|
|
||
|
// Check if register operand at index `Index` is the invalid register.
|
||
|
class CheckInvalidRegOperand<int Index> : CheckOperandBase<Index>;
|
||
|
|
||
|
// Return true if machine operand at position `Index` is a valid
|
||
|
// register operand.
|
||
|
class CheckValidRegOperand<int Index> :
|
||
|
CheckNot<CheckInvalidRegOperand<Index>>;
|
||
|
|
||
|
// Check that the operand at position `Index` is immediate `Imm`.
|
||
|
// If field `FunctionMapper` is a non-empty string, then function
|
||
|
// `FunctionMapper` is applied to the operand value, and the return value is then
|
||
|
// compared against `Imm`.
|
||
|
class CheckImmOperand<int Index, int Imm> : CheckOperandBase<Index> {
|
||
|
int ImmVal = Imm;
|
||
|
}
|
||
|
|
||
|
// Similar to CheckImmOperand, however the immediate is not a literal number.
|
||
|
// This is useful when we want to compare the value of an operand against an
|
||
|
// enum value, and we know the actual integer value of that enum.
|
||
|
class CheckImmOperand_s<int Index, string Value> : CheckOperandBase<Index> {
|
||
|
string ImmVal = Value;
|
||
|
}
|
||
|
|
||
|
// Expands to a call to `FunctionMapper` if field `FunctionMapper` is set.
|
||
|
// Otherwise, it expands to a CheckNot<CheckInvalidRegOperand<Index>>.
|
||
|
class CheckRegOperandSimple<int Index> : CheckOperandBase<Index>;
|
||
|
|
||
|
// Expands to a call to `FunctionMapper` if field `FunctionMapper` is set.
|
||
|
// Otherwise, it simply evaluates to TruePred.
|
||
|
class CheckImmOperandSimple<int Index> : CheckOperandBase<Index>;
|
||
|
|
||
|
// Check that the operand at position `Index` is immediate value zero.
|
||
|
class CheckZeroOperand<int Index> : CheckImmOperand<Index, 0>;
|
||
|
|
||
|
// Check that the instruction has exactly `Num` operands.
|
||
|
class CheckNumOperands<int Num> : MCInstPredicate {
|
||
|
int NumOps = Num;
|
||
|
}
|
||
|
|
||
|
// Check that the instruction opcode is one of the opcodes in set `Opcodes`.
|
||
|
// This is a simple set membership query. The easier way to check if an opcode
|
||
|
// is not a member of the set is by using a `CheckNot<CheckOpcode<[...]>>`
|
||
|
// sequence.
|
||
|
class CheckOpcode<list<Instruction> Opcodes> : MCInstPredicate {
|
||
|
list<Instruction> ValidOpcodes = Opcodes;
|
||
|
}
|
||
|
|
||
|
// Check that the instruction opcode is a pseudo opcode member of the set
|
||
|
// `Opcodes`. This check is always expanded to "false" if we are generating
|
||
|
// code for MCInst.
|
||
|
class CheckPseudo<list<Instruction> Opcodes> : CheckOpcode<Opcodes>;
|
||
|
|
||
|
// A non-portable predicate. Only to use as a last resort when a block of code
|
||
|
// cannot possibly be converted in a declarative way using other MCInstPredicate
|
||
|
// classes. This check is always expanded to "false" when generating code for
|
||
|
// MCInst.
|
||
|
class CheckNonPortable<string Code> : MCInstPredicate {
|
||
|
string CodeBlock = Code;
|
||
|
}
|
||
|
|
||
|
// A sequence of predicates. It is used as the base class for CheckAll, and
|
||
|
// CheckAny. It allows to describe compositions of predicates.
|
||
|
class CheckPredicateSequence<list<MCInstPredicate> Preds> : MCInstPredicate {
|
||
|
list<MCInstPredicate> Predicates = Preds;
|
||
|
}
|
||
|
|
||
|
// Check that all of the predicates in `Preds` evaluate to true.
|
||
|
class CheckAll<list<MCInstPredicate> Sequence>
|
||
|
: CheckPredicateSequence<Sequence>;
|
||
|
|
||
|
// Check that at least one of the predicates in `Preds` evaluates to true.
|
||
|
class CheckAny<list<MCInstPredicate> Sequence>
|
||
|
: CheckPredicateSequence<Sequence>;
|
||
|
|
||
|
|
||
|
// Used to expand the body of a function predicate. See the definition of
|
||
|
// TIIPredicate below.
|
||
|
class MCStatement;
|
||
|
|
||
|
// Expands to a return statement. The return expression is a boolean expression
|
||
|
// described by a MCInstPredicate.
|
||
|
class MCReturnStatement<MCInstPredicate predicate> : MCStatement {
|
||
|
MCInstPredicate Pred = predicate;
|
||
|
}
|
||
|
|
||
|
// Used to automatically construct cases of a switch statement where the switch
|
||
|
// variable is an instruction opcode. There is a 'case' for every opcode in the
|
||
|
// `opcodes` list, and each case is associated with MCStatement `caseStmt`.
|
||
|
class MCOpcodeSwitchCase<list<Instruction> opcodes, MCStatement caseStmt> {
|
||
|
list<Instruction> Opcodes = opcodes;
|
||
|
MCStatement CaseStmt = caseStmt;
|
||
|
}
|
||
|
|
||
|
// Expands to a switch statement. The switch variable is an instruction opcode.
|
||
|
// The auto-generated switch is populated by a number of cases based on the
|
||
|
// `cases` list in input. A default case is automatically generated, and it
|
||
|
// evaluates to `default`.
|
||
|
class MCOpcodeSwitchStatement<list<MCOpcodeSwitchCase> cases,
|
||
|
MCStatement default> : MCStatement {
|
||
|
list<MCOpcodeSwitchCase> Cases = cases;
|
||
|
MCStatement DefaultCase = default;
|
||
|
}
|
||
|
|
||
|
// Base class for function predicates.
|
||
|
class FunctionPredicateBase<string name, MCStatement body> {
|
||
|
string FunctionName = name;
|
||
|
MCStatement Body = body;
|
||
|
}
|
||
|
|
||
|
// Check that a call to method `Name` in class "XXXInstrInfo" (where XXX is
|
||
|
// the name of a target) returns true.
|
||
|
//
|
||
|
// TIIPredicate definitions are used to model calls to the target-specific
|
||
|
// InstrInfo. A TIIPredicate is treated specially by the InstrInfoEmitter
|
||
|
// tablegen backend, which will use it to automatically generate a definition in
|
||
|
// the target specific `InstrInfo` class.
|
||
|
//
|
||
|
// There cannot be multiple TIIPredicate definitions with the same name for the
|
||
|
// same target.
|
||
|
class TIIPredicate<string Name, MCStatement body>
|
||
|
: FunctionPredicateBase<Name, body>, MCInstPredicate;
|
||
|
|
||
|
// A function predicate that takes as input a machine instruction, and returns
|
||
|
// a boolean value.
|
||
|
//
|
||
|
// This predicate is expanded into a function call by the PredicateExpander.
|
||
|
// In particular, the PredicateExpander would either expand this predicate into
|
||
|
// a call to `MCInstFn`, or into a call to`MachineInstrFn` depending on whether
|
||
|
// it is lowering predicates for MCInst or MachineInstr.
|
||
|
//
|
||
|
// In this context, `MCInstFn` and `MachineInstrFn` are both function names.
|
||
|
class CheckFunctionPredicate<string MCInstFn, string MachineInstrFn> : MCInstPredicate {
|
||
|
string MCInstFnName = MCInstFn;
|
||
|
string MachineInstrFnName = MachineInstrFn;
|
||
|
}
|
||
|
|
||
|
// Similar to CheckFunctionPredicate. However it assumes that MachineInstrFn is
|
||
|
// a method in TargetInstrInfo, and MCInstrFn takes an extra pointer to
|
||
|
// MCInstrInfo.
|
||
|
//
|
||
|
// It Expands to:
|
||
|
// - TIIPointer->MachineInstrFn(MI)
|
||
|
// - MCInstrFn(MI, MCII);
|
||
|
class CheckFunctionPredicateWithTII<string MCInstFn, string MachineInstrFn, string
|
||
|
TIIPointer = "TII"> : MCInstPredicate {
|
||
|
string MCInstFnName = MCInstFn;
|
||
|
string TIIPtrName = TIIPointer;
|
||
|
string MachineInstrFnName = MachineInstrFn;
|
||
|
}
|
||
|
|
||
|
// Used to classify machine instructions based on a machine instruction
|
||
|
// predicate.
|
||
|
//
|
||
|
// Let IC be an InstructionEquivalenceClass definition, and MI a machine
|
||
|
// instruction. We say that MI belongs to the equivalence class described by IC
|
||
|
// if and only if the following two conditions are met:
|
||
|
// a) MI's opcode is in the `opcodes` set, and
|
||
|
// b) `Predicate` evaluates to true when applied to MI.
|
||
|
//
|
||
|
// Instances of this class can be used by processor scheduling models to
|
||
|
// describe instructions that have a property in common. For example,
|
||
|
// InstructionEquivalenceClass definitions can be used to identify the set of
|
||
|
// dependency breaking instructions for a processor model.
|
||
|
//
|
||
|
// An (optional) list of operand indices can be used to further describe
|
||
|
// properties that apply to instruction operands. For example, it can be used to
|
||
|
// identify register uses of a dependency breaking instructions that are not in
|
||
|
// a RAW dependency.
|
||
|
class InstructionEquivalenceClass<list<Instruction> opcodes,
|
||
|
MCInstPredicate pred,
|
||
|
list<int> operands = []> {
|
||
|
list<Instruction> Opcodes = opcodes;
|
||
|
MCInstPredicate Predicate = pred;
|
||
|
list<int> OperandIndices = operands;
|
||
|
}
|
||
|
|
||
|
// Used by processor models to describe dependency breaking instructions.
|
||
|
//
|
||
|
// This is mainly an alias for InstructionEquivalenceClass. Input operand
|
||
|
// `BrokenDeps` identifies the set of "broken dependencies". There is one bit
|
||
|
// per each implicit and explicit input operand. An empty set of broken
|
||
|
// dependencies means: "explicit input register operands are independent."
|
||
|
class DepBreakingClass<list<Instruction> opcodes, MCInstPredicate pred,
|
||
|
list<int> BrokenDeps = []>
|
||
|
: InstructionEquivalenceClass<opcodes, pred, BrokenDeps>;
|
||
|
|
||
|
// A function descriptor used to describe the signature of a predicate methods
|
||
|
// which will be expanded by the STIPredicateExpander into a tablegen'd
|
||
|
// XXXGenSubtargetInfo class member definition (here, XXX is a target name).
|
||
|
//
|
||
|
// It describes the signature of a TargetSubtarget hook, as well as a few extra
|
||
|
// properties. Examples of extra properties are:
|
||
|
// - The default return value for the auto-generate function hook.
|
||
|
// - A list of subtarget hooks (Delegates) that are called from this function.
|
||
|
//
|
||
|
class STIPredicateDecl<string name, MCInstPredicate default = FalsePred,
|
||
|
bit overrides = true, bit expandForMC = true,
|
||
|
bit updatesOpcodeMask = false,
|
||
|
list<STIPredicateDecl> delegates = []> {
|
||
|
string Name = name;
|
||
|
|
||
|
MCInstPredicate DefaultReturnValue = default;
|
||
|
|
||
|
// True if this method is declared as virtual in class TargetSubtargetInfo.
|
||
|
bit OverridesBaseClassMember = overrides;
|
||
|
|
||
|
// True if we need an equivalent predicate function in the MC layer.
|
||
|
bit ExpandForMC = expandForMC;
|
||
|
|
||
|
// True if the autogenerated method has a extra in/out APInt param used as a
|
||
|
// mask of operands.
|
||
|
bit UpdatesOpcodeMask = updatesOpcodeMask;
|
||
|
|
||
|
// A list of STIPredicates used by this definition to delegate part of the
|
||
|
// computation. For example, STIPredicateFunction `isDependencyBreaking()`
|
||
|
// delegates to `isZeroIdiom()` part of its computation.
|
||
|
list<STIPredicateDecl> Delegates = delegates;
|
||
|
}
|
||
|
|
||
|
// A predicate function definition member of class `XXXGenSubtargetInfo`.
|
||
|
//
|
||
|
// If `Declaration.ExpandForMC` is true, then SubtargetEmitter
|
||
|
// will also expand another definition of this method that accepts a MCInst.
|
||
|
class STIPredicate<STIPredicateDecl declaration,
|
||
|
list<InstructionEquivalenceClass> classes> {
|
||
|
STIPredicateDecl Declaration = declaration;
|
||
|
list<InstructionEquivalenceClass> Classes = classes;
|
||
|
SchedMachineModel SchedModel = ?;
|
||
|
}
|
||
|
|
||
|
// Convenience classes and definitions used by processor scheduling models to
|
||
|
// describe dependency breaking instructions and move elimination candidates.
|
||
|
let UpdatesOpcodeMask = true in {
|
||
|
|
||
|
def IsZeroIdiomDecl : STIPredicateDecl<"isZeroIdiom">;
|
||
|
|
||
|
let Delegates = [IsZeroIdiomDecl] in
|
||
|
def IsDepBreakingDecl : STIPredicateDecl<"isDependencyBreaking">;
|
||
|
|
||
|
} // UpdatesOpcodeMask
|
||
|
|
||
|
def IsOptimizableRegisterMoveDecl
|
||
|
: STIPredicateDecl<"isOptimizableRegisterMove">;
|
||
|
|
||
|
class IsZeroIdiomFunction<list<DepBreakingClass> classes>
|
||
|
: STIPredicate<IsZeroIdiomDecl, classes>;
|
||
|
|
||
|
class IsDepBreakingFunction<list<DepBreakingClass> classes>
|
||
|
: STIPredicate<IsDepBreakingDecl, classes>;
|
||
|
|
||
|
class IsOptimizableRegisterMove<list<InstructionEquivalenceClass> classes>
|
||
|
: STIPredicate<IsOptimizableRegisterMoveDecl, classes>;
|