| 1 | //===-- MCInstrDescView.h ---------------------------------------*- C++ -*-===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | /// |
| 9 | /// \file |
| 10 | /// Provide views around LLVM structures to represents an instruction instance, |
| 11 | /// as well as its implicit and explicit arguments in a uniform way. |
| 12 | /// Arguments that are explicit and independant (non tied) also have a Variable |
| 13 | /// associated to them so the instruction can be fully defined by reading its |
| 14 | /// Variables. |
| 15 | /// |
| 16 | //===----------------------------------------------------------------------===// |
| 17 | |
| 18 | #ifndef LLVM_TOOLS_LLVM_EXEGESIS_MCINSTRDESCVIEW_H |
| 19 | #define LLVM_TOOLS_LLVM_EXEGESIS_MCINSTRDESCVIEW_H |
| 20 | |
| 21 | #include <memory> |
| 22 | #include <random> |
| 23 | #include <unordered_map> |
| 24 | |
| 25 | #include "RegisterAliasing.h" |
| 26 | #include "llvm/ADT/ArrayRef.h" |
| 27 | #include "llvm/MC/MCInst.h" |
| 28 | #include "llvm/MC/MCInstrDesc.h" |
| 29 | #include "llvm/MC/MCInstrInfo.h" |
| 30 | |
| 31 | namespace llvm { |
| 32 | namespace exegesis { |
| 33 | |
| 34 | // A variable represents the value associated to an Operand or a set of Operands |
| 35 | // if they are tied together. |
| 36 | struct Variable { |
| 37 | // Returns the index of this Variable inside Instruction's Variable. |
| 38 | unsigned getIndex() const; |
| 39 | |
| 40 | // Returns the index of the Operand linked to this Variable. |
| 41 | unsigned getPrimaryOperandIndex() const; |
| 42 | |
| 43 | // Returns whether this Variable has more than one Operand linked to it. |
| 44 | bool hasTiedOperands() const; |
| 45 | |
| 46 | // The indices of the operands tied to this Variable. |
| 47 | SmallVector<unsigned, 2> TiedOperands; |
| 48 | |
| 49 | // The index of this Variable in Instruction.Variables and its associated |
| 50 | // Value in InstructionBuilder.VariableValues. |
| 51 | std::optional<uint8_t> Index; |
| 52 | }; |
| 53 | |
| 54 | // MCOperandInfo can only represents Explicit operands. This object gives a |
| 55 | // uniform view of Implicit and Explicit Operands. |
| 56 | // - Index: can be used to refer to MCInstrDesc::operands for Explicit operands. |
| 57 | // - Tracker: is set for Register Operands and is used to keep track of possible |
| 58 | // registers and the registers reachable from them (aliasing registers). |
| 59 | // - Info: a shortcut for MCInstrDesc::operands()[Index]. |
| 60 | // - TiedToIndex: the index of the Operand holding the value or -1. |
| 61 | // - ImplicitReg: the register value when Operand is Implicit, 0 otherwise. |
| 62 | // - VariableIndex: the index of the Variable holding the value for this Operand |
| 63 | // or -1 if this operand is implicit. |
| 64 | struct Operand { |
| 65 | bool isExplicit() const; |
| 66 | bool isImplicit() const; |
| 67 | bool isImplicitReg() const; |
| 68 | bool isDef() const; |
| 69 | bool isUse() const; |
| 70 | bool isReg() const; |
| 71 | bool isTied() const; |
| 72 | bool isVariable() const; |
| 73 | bool isMemory() const; |
| 74 | bool isImmediate() const; |
| 75 | bool isEarlyClobber() const; |
| 76 | unsigned getIndex() const; |
| 77 | unsigned getTiedToIndex() const; |
| 78 | unsigned getVariableIndex() const; |
| 79 | MCRegister getImplicitReg() const; |
| 80 | const RegisterAliasingTracker &getRegisterAliasing() const; |
| 81 | const MCOperandInfo &getExplicitOperandInfo() const; |
| 82 | |
| 83 | // Please use the accessors above and not the following fields. |
| 84 | std::optional<uint8_t> Index; |
| 85 | bool IsDef = false; |
| 86 | bool IsEarlyClobber = false; |
| 87 | const RegisterAliasingTracker *Tracker = nullptr; // Set for Register Op. |
| 88 | const MCOperandInfo *Info = nullptr; // Set for Explicit Op. |
| 89 | std::optional<uint8_t> TiedToIndex; // Set for Reg&Explicit Op. |
| 90 | MCRegister ImplicitReg; // Non-0 for Implicit Op. |
| 91 | std::optional<uint8_t> VariableIndex; // Set for Explicit Op. |
| 92 | }; |
| 93 | |
| 94 | /// A cache of BitVector to reuse between Instructions. |
| 95 | /// The cache will only be exercised during Instruction initialization. |
| 96 | /// For X86, this is ~160 unique vectors for all of the ~15K Instructions. |
| 97 | struct BitVectorCache { |
| 98 | // Finds or allocates the provided BitVector in the cache and retrieves it's |
| 99 | // unique instance. |
| 100 | const BitVector *getUnique(BitVector &&BV) const; |
| 101 | |
| 102 | private: |
| 103 | mutable std::vector<std::unique_ptr<BitVector>> Cache; |
| 104 | }; |
| 105 | |
| 106 | // A view over an MCInstrDesc offering a convenient interface to compute |
| 107 | // Register aliasing. |
| 108 | struct Instruction { |
| 109 | // Create an instruction for a particular Opcode. |
| 110 | static std::unique_ptr<Instruction> |
| 111 | create(const MCInstrInfo &InstrInfo, const RegisterAliasingTrackerCache &RATC, |
| 112 | const BitVectorCache &BVC, unsigned Opcode); |
| 113 | |
| 114 | // Prevent copy or move, instructions are allocated once and cached. |
| 115 | Instruction(const Instruction &) = delete; |
| 116 | Instruction(Instruction &&) = delete; |
| 117 | Instruction &operator=(const Instruction &) = delete; |
| 118 | Instruction &operator=(Instruction &&) = delete; |
| 119 | |
| 120 | unsigned getOpcode() const { return Description.getOpcode(); } |
| 121 | |
| 122 | // Returns the Operand linked to this Variable. |
| 123 | // In case the Variable is tied, the primary (i.e. Def) Operand is returned. |
| 124 | const Operand &getPrimaryOperand(const Variable &Var) const; |
| 125 | |
| 126 | // Whether this instruction is self aliasing through its tied registers. |
| 127 | // Repeating this instruction is guaranteed to executes sequentially. |
| 128 | bool hasTiedRegisters() const; |
| 129 | |
| 130 | // Whether this instruction is self aliasing through its implicit registers. |
| 131 | // Repeating this instruction is guaranteed to executes sequentially. |
| 132 | bool hasAliasingImplicitRegisters() const; |
| 133 | |
| 134 | // Whether this instruction is self aliasing through some registers. |
| 135 | // Repeating this instruction may execute sequentially by picking aliasing |
| 136 | // Use and Def registers. It may also execute in parallel by picking non |
| 137 | // aliasing Use and Def registers. |
| 138 | bool hasAliasingRegisters(const BitVector &ForbiddenRegisters) const; |
| 139 | |
| 140 | // Whether this instruction is self aliasing through some registers. |
| 141 | // Repeating this instruction may execute sequentially by picking aliasing |
| 142 | // Def and Not Memory Use registers. It may also execute in parallel by |
| 143 | // picking non aliasing Def and Not Memory Use registers. |
| 144 | bool hasAliasingNotMemoryRegisters(const BitVector &ForbiddenRegisters) const; |
| 145 | |
| 146 | // Whether this instruction's registers alias with OtherInstr's registers. |
| 147 | bool hasAliasingRegistersThrough(const Instruction &OtherInstr, |
| 148 | const BitVector &ForbiddenRegisters) const; |
| 149 | |
| 150 | // Returns whether this instruction has Memory Operands. |
| 151 | // Repeating this instruction executes sequentially with an instruction that |
| 152 | // reads or write the same memory region. |
| 153 | bool hasMemoryOperands() const; |
| 154 | |
| 155 | // Returns whether this instruction as at least one use or one def. |
| 156 | // Repeating this instruction may execute sequentially by adding an |
| 157 | // instruction that aliases one of these. |
| 158 | bool hasOneUseOrOneDef() const; |
| 159 | |
| 160 | // Convenient function to help with debugging. |
| 161 | void dump(const MCRegisterInfo &RegInfo, |
| 162 | const RegisterAliasingTrackerCache &RATC, |
| 163 | raw_ostream &Stream) const; |
| 164 | |
| 165 | const MCInstrDesc &Description; |
| 166 | const StringRef Name; // The name of this instruction. |
| 167 | const SmallVector<Operand, 8> Operands; |
| 168 | const SmallVector<Variable, 4> Variables; |
| 169 | const BitVector &ImplDefRegs; // The set of aliased implicit def registers. |
| 170 | const BitVector &ImplUseRegs; // The set of aliased implicit use registers. |
| 171 | const BitVector &AllDefRegs; // The set of all aliased def registers. |
| 172 | const BitVector &AllUseRegs; // The set of all aliased use registers. |
| 173 | // The set of all aliased not memory use registers. |
| 174 | const BitVector &NonMemoryRegs; |
| 175 | |
| 176 | private: |
| 177 | Instruction(const MCInstrDesc *Description, StringRef Name, |
| 178 | SmallVector<Operand, 8> Operands, |
| 179 | SmallVector<Variable, 4> Variables, const BitVector *ImplDefRegs, |
| 180 | const BitVector *ImplUseRegs, const BitVector *AllDefRegs, |
| 181 | const BitVector *AllUseRegs, const BitVector *NonMemoryRegs); |
| 182 | }; |
| 183 | |
| 184 | // Instructions are expensive to instantiate. This class provides a cache of |
| 185 | // Instructions with lazy construction. |
| 186 | struct InstructionsCache { |
| 187 | InstructionsCache(const MCInstrInfo &InstrInfo, |
| 188 | const RegisterAliasingTrackerCache &RATC); |
| 189 | |
| 190 | // Returns the Instruction object corresponding to this Opcode. |
| 191 | const Instruction &getInstr(unsigned Opcode) const; |
| 192 | |
| 193 | private: |
| 194 | const MCInstrInfo &InstrInfo; |
| 195 | const RegisterAliasingTrackerCache &RATC; |
| 196 | mutable std::unordered_map<unsigned, std::unique_ptr<Instruction>> |
| 197 | Instructions; |
| 198 | const BitVectorCache BVC; |
| 199 | }; |
| 200 | |
| 201 | // Represents the assignment of a Register to an Operand. |
| 202 | struct RegisterOperandAssignment { |
| 203 | RegisterOperandAssignment(const Operand *Operand, MCPhysReg Reg) |
| 204 | : Op(Operand), Reg(Reg) {} |
| 205 | |
| 206 | const Operand *Op; // Pointer to an Explicit Register Operand. |
| 207 | MCPhysReg Reg; |
| 208 | |
| 209 | bool operator==(const RegisterOperandAssignment &other) const; |
| 210 | }; |
| 211 | |
| 212 | // Represents a set of Operands that would alias through the use of some |
| 213 | // Registers. |
| 214 | // There are two reasons why operands would alias: |
| 215 | // - The registers assigned to each of the operands are the same or alias each |
| 216 | // other (e.g. AX/AL) |
| 217 | // - The operands are tied. |
| 218 | struct AliasingRegisterOperands { |
| 219 | SmallVector<RegisterOperandAssignment, 1> Defs; // Unlikely size() > 1. |
| 220 | SmallVector<RegisterOperandAssignment, 2> Uses; |
| 221 | |
| 222 | // True is Defs and Use contain an Implicit Operand. |
| 223 | bool hasImplicitAliasing() const; |
| 224 | |
| 225 | bool operator==(const AliasingRegisterOperands &other) const; |
| 226 | }; |
| 227 | |
| 228 | // Returns all possible configurations leading Def registers of DefInstruction |
| 229 | // to alias with Use registers of UseInstruction. |
| 230 | struct AliasingConfigurations { |
| 231 | AliasingConfigurations(const Instruction &DefInstruction, |
| 232 | const Instruction &UseInstruction, |
| 233 | const BitVector &ForbiddenRegisters); |
| 234 | |
| 235 | bool empty() const; // True if no aliasing configuration is found. |
| 236 | bool hasImplicitAliasing() const; |
| 237 | |
| 238 | SmallVector<AliasingRegisterOperands, 32> Configurations; |
| 239 | }; |
| 240 | |
| 241 | // Writes MCInst to OS. |
| 242 | // This is not assembly but the internal LLVM's name for instructions and |
| 243 | // registers. |
| 244 | void DumpMCInst(const MCRegisterInfo &MCRegisterInfo, |
| 245 | const MCInstrInfo &MCInstrInfo, const MCInst &MCInst, |
| 246 | raw_ostream &OS); |
| 247 | |
| 248 | } // namespace exegesis |
| 249 | } // namespace llvm |
| 250 | |
| 251 | #endif // LLVM_TOOLS_LLVM_EXEGESIS_MCINSTRDESCVIEW_H |
| 252 | |