//===- 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>]>; // // 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 { 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 : MCInstPredicate { int OpIndex = Index; } // Return true if machine operand at position `Index` is a register operand. class CheckIsRegOperand : MCOperandPredicate; // Return true if machine operand at position `Index` is an immediate operand. class CheckIsImmOperand : MCOperandPredicate; // Check if machine operands at index `First` and index `Second` both reference // the same register. class CheckSameRegOperand : 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 : MCOperandPredicate { 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 : CheckOperandBase { Register Reg = R; } // Check if register operand at index `Index` is the invalid register. class CheckInvalidRegOperand : CheckOperandBase; // 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 : CheckOperandBase { 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 : CheckOperandBase { string ImmVal = Value; } // Expands to a call to `FunctionMapper` if field `FunctionMapper` is set. // Otherwise, it expands to a CheckNot>. class CheckRegOperandSimple : CheckOperandBase; // Expands to a call to `FunctionMapper` if field `FunctionMapper` is set. // Otherwise, it simply evaluates to TruePred. class CheckImmOperandSimple : CheckOperandBase; // Check that the operand at position `Index` is immediate value zero. class CheckZeroOperand : CheckImmOperand; // Check that the instruction has exactly `Num` operands. class CheckNumOperands : 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>` // sequence. class CheckOpcode Opcodes> : MCInstPredicate { list 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 Opcodes> : CheckOpcode; // 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 : 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 Preds> : MCInstPredicate { list Predicates = Preds; } // Check that all of the predicates in `Preds` evaluate to true. class CheckAll Sequence> : CheckPredicateSequence; // Check that at least one of the predicates in `Preds` evaluates to true. class CheckAny Sequence> : CheckPredicateSequence; // 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 : 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 opcodes, MCStatement caseStmt> { list 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 cases, MCStatement default> : MCStatement { list Cases = cases; MCStatement DefaultCase = default; } // Base class for function predicates. class FunctionPredicateBase { 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 : FunctionPredicateBase, 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 : MCInstPredicate { string MCInstFnName = MCInstFn; 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 opcodes, MCInstPredicate pred, list operands = []> { list Opcodes = opcodes; MCInstPredicate Predicate = pred; list 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 opcodes, MCInstPredicate pred, list BrokenDeps = []> : InstructionEquivalenceClass; // 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 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 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 classes> { STIPredicateDecl Declaration = declaration; list Classes = classes; SchedMachineModel SchedModel = ?; } // Convenience classes and definitions used by processor scheduling models to // describe dependency breaking instructions and move elimination candidates. let UpdatesOpcodeMask = 1 in { def IsZeroIdiomDecl : STIPredicateDecl<"isZeroIdiom">; let Delegates = [IsZeroIdiomDecl] in def IsDepBreakingDecl : STIPredicateDecl<"isDependencyBreaking">; } // UpdatesOpcodeMask def IsOptimizableRegisterMoveDecl : STIPredicateDecl<"isOptimizableRegisterMove">; class IsZeroIdiomFunction classes> : STIPredicate; class IsDepBreakingFunction classes> : STIPredicate; class IsOptimizableRegisterMove classes> : STIPredicate;