109467b48Spatrick //===-- MCInstrDescView.h ---------------------------------------*- C++ -*-===// 209467b48Spatrick // 309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information. 509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 609467b48Spatrick // 709467b48Spatrick //===----------------------------------------------------------------------===// 809467b48Spatrick /// 909467b48Spatrick /// \file 1009467b48Spatrick /// Provide views around LLVM structures to represents an instruction instance, 1109467b48Spatrick /// as well as its implicit and explicit arguments in a uniform way. 1209467b48Spatrick /// Arguments that are explicit and independant (non tied) also have a Variable 1309467b48Spatrick /// associated to them so the instruction can be fully defined by reading its 1409467b48Spatrick /// Variables. 1509467b48Spatrick /// 1609467b48Spatrick //===----------------------------------------------------------------------===// 1709467b48Spatrick 1809467b48Spatrick #ifndef LLVM_TOOLS_LLVM_EXEGESIS_MCINSTRDESCVIEW_H 1909467b48Spatrick #define LLVM_TOOLS_LLVM_EXEGESIS_MCINSTRDESCVIEW_H 2009467b48Spatrick 2109467b48Spatrick #include <memory> 2209467b48Spatrick #include <random> 2309467b48Spatrick #include <unordered_map> 2409467b48Spatrick 2509467b48Spatrick #include "RegisterAliasing.h" 2609467b48Spatrick #include "llvm/ADT/ArrayRef.h" 2709467b48Spatrick #include "llvm/MC/MCInst.h" 2809467b48Spatrick #include "llvm/MC/MCInstrDesc.h" 2909467b48Spatrick #include "llvm/MC/MCInstrInfo.h" 3009467b48Spatrick 3109467b48Spatrick namespace llvm { 3209467b48Spatrick namespace exegesis { 3309467b48Spatrick 3409467b48Spatrick // A variable represents the value associated to an Operand or a set of Operands 3509467b48Spatrick // if they are tied together. 3609467b48Spatrick struct Variable { 3709467b48Spatrick // Returns the index of this Variable inside Instruction's Variable. 3809467b48Spatrick unsigned getIndex() const; 3909467b48Spatrick 4009467b48Spatrick // Returns the index of the Operand linked to this Variable. 4109467b48Spatrick unsigned getPrimaryOperandIndex() const; 4209467b48Spatrick 4309467b48Spatrick // Returns whether this Variable has more than one Operand linked to it. 4409467b48Spatrick bool hasTiedOperands() const; 4509467b48Spatrick 4609467b48Spatrick // The indices of the operands tied to this Variable. 4709467b48Spatrick SmallVector<unsigned, 2> TiedOperands; 4809467b48Spatrick 4909467b48Spatrick // The index of this Variable in Instruction.Variables and its associated 5009467b48Spatrick // Value in InstructionBuilder.VariableValues. 51*d415bd75Srobert std::optional<uint8_t> Index; 5209467b48Spatrick }; 5309467b48Spatrick 5409467b48Spatrick // MCOperandInfo can only represents Explicit operands. This object gives a 5509467b48Spatrick // uniform view of Implicit and Explicit Operands. 5609467b48Spatrick // - Index: can be used to refer to MCInstrDesc::operands for Explicit operands. 5709467b48Spatrick // - Tracker: is set for Register Operands and is used to keep track of possible 5809467b48Spatrick // registers and the registers reachable from them (aliasing registers). 5909467b48Spatrick // - Info: a shortcut for MCInstrDesc::operands()[Index]. 6009467b48Spatrick // - TiedToIndex: the index of the Operand holding the value or -1. 61*d415bd75Srobert // - ImplicitReg: the register value when Operand is Implicit, 0 otherwise. 6209467b48Spatrick // - VariableIndex: the index of the Variable holding the value for this Operand 6309467b48Spatrick // or -1 if this operand is implicit. 6409467b48Spatrick struct Operand { 6509467b48Spatrick bool isExplicit() const; 6609467b48Spatrick bool isImplicit() const; 6709467b48Spatrick bool isImplicitReg() const; 6809467b48Spatrick bool isDef() const; 6909467b48Spatrick bool isUse() const; 7009467b48Spatrick bool isReg() const; 7109467b48Spatrick bool isTied() const; 7209467b48Spatrick bool isVariable() const; 7309467b48Spatrick bool isMemory() const; 7409467b48Spatrick bool isImmediate() const; 7509467b48Spatrick unsigned getIndex() const; 7609467b48Spatrick unsigned getTiedToIndex() const; 7709467b48Spatrick unsigned getVariableIndex() const; 7809467b48Spatrick unsigned getImplicitReg() const; 7909467b48Spatrick const RegisterAliasingTracker &getRegisterAliasing() const; 8009467b48Spatrick const MCOperandInfo &getExplicitOperandInfo() const; 8109467b48Spatrick 8209467b48Spatrick // Please use the accessors above and not the following fields. 83*d415bd75Srobert std::optional<uint8_t> Index; 8409467b48Spatrick bool IsDef = false; 8509467b48Spatrick const RegisterAliasingTracker *Tracker = nullptr; // Set for Register Op. 8609467b48Spatrick const MCOperandInfo *Info = nullptr; // Set for Explicit Op. 87*d415bd75Srobert std::optional<uint8_t> TiedToIndex; // Set for Reg&Explicit Op. 88*d415bd75Srobert MCPhysReg ImplicitReg = 0; // Non-0 for Implicit Op. 89*d415bd75Srobert std::optional<uint8_t> VariableIndex; // Set for Explicit Op. 9009467b48Spatrick }; 9109467b48Spatrick 9209467b48Spatrick /// A cache of BitVector to reuse between Instructions. 9309467b48Spatrick /// The cache will only be exercised during Instruction initialization. 9409467b48Spatrick /// For X86, this is ~160 unique vectors for all of the ~15K Instructions. 9509467b48Spatrick struct BitVectorCache { 9609467b48Spatrick // Finds or allocates the provided BitVector in the cache and retrieves it's 9709467b48Spatrick // unique instance. 9809467b48Spatrick const BitVector *getUnique(BitVector &&BV) const; 9909467b48Spatrick 10009467b48Spatrick private: 10109467b48Spatrick mutable std::vector<std::unique_ptr<BitVector>> Cache; 10209467b48Spatrick }; 10309467b48Spatrick 10409467b48Spatrick // A view over an MCInstrDesc offering a convenient interface to compute 10509467b48Spatrick // Register aliasing. 10609467b48Spatrick struct Instruction { 10709467b48Spatrick // Create an instruction for a particular Opcode. 10809467b48Spatrick static std::unique_ptr<Instruction> 10909467b48Spatrick create(const MCInstrInfo &InstrInfo, const RegisterAliasingTrackerCache &RATC, 11009467b48Spatrick const BitVectorCache &BVC, unsigned Opcode); 11109467b48Spatrick 11209467b48Spatrick // Prevent copy or move, instructions are allocated once and cached. 11309467b48Spatrick Instruction(const Instruction &) = delete; 11409467b48Spatrick Instruction(Instruction &&) = delete; 11509467b48Spatrick Instruction &operator=(const Instruction &) = delete; 11609467b48Spatrick Instruction &operator=(Instruction &&) = delete; 11709467b48Spatrick 11809467b48Spatrick // Returns the Operand linked to this Variable. 11909467b48Spatrick // In case the Variable is tied, the primary (i.e. Def) Operand is returned. 12009467b48Spatrick const Operand &getPrimaryOperand(const Variable &Var) const; 12109467b48Spatrick 12209467b48Spatrick // Whether this instruction is self aliasing through its tied registers. 12309467b48Spatrick // Repeating this instruction is guaranteed to executes sequentially. 12409467b48Spatrick bool hasTiedRegisters() const; 12509467b48Spatrick 12609467b48Spatrick // Whether this instruction is self aliasing through its implicit registers. 12709467b48Spatrick // Repeating this instruction is guaranteed to executes sequentially. 12809467b48Spatrick bool hasAliasingImplicitRegisters() const; 12909467b48Spatrick 13009467b48Spatrick // Whether this instruction is self aliasing through some registers. 13109467b48Spatrick // Repeating this instruction may execute sequentially by picking aliasing 13209467b48Spatrick // Use and Def registers. It may also execute in parallel by picking non 13309467b48Spatrick // aliasing Use and Def registers. 13409467b48Spatrick bool hasAliasingRegisters(const BitVector &ForbiddenRegisters) const; 13509467b48Spatrick 13609467b48Spatrick // Whether this instruction's registers alias with OtherInstr's registers. 13709467b48Spatrick bool hasAliasingRegistersThrough(const Instruction &OtherInstr, 13809467b48Spatrick const BitVector &ForbiddenRegisters) const; 13909467b48Spatrick 14009467b48Spatrick // Returns whether this instruction has Memory Operands. 14109467b48Spatrick // Repeating this instruction executes sequentially with an instruction that 14209467b48Spatrick // reads or write the same memory region. 14309467b48Spatrick bool hasMemoryOperands() const; 14409467b48Spatrick 14509467b48Spatrick // Returns whether this instruction as at least one use or one def. 14609467b48Spatrick // Repeating this instruction may execute sequentially by adding an 14709467b48Spatrick // instruction that aliases one of these. 14809467b48Spatrick bool hasOneUseOrOneDef() const; 14909467b48Spatrick 15009467b48Spatrick // Convenient function to help with debugging. 15109467b48Spatrick void dump(const MCRegisterInfo &RegInfo, 15209467b48Spatrick const RegisterAliasingTrackerCache &RATC, 15309467b48Spatrick raw_ostream &Stream) const; 15409467b48Spatrick 15509467b48Spatrick const MCInstrDesc &Description; 15609467b48Spatrick const StringRef Name; // The name of this instruction. 15709467b48Spatrick const SmallVector<Operand, 8> Operands; 15809467b48Spatrick const SmallVector<Variable, 4> Variables; 15909467b48Spatrick const BitVector &ImplDefRegs; // The set of aliased implicit def registers. 16009467b48Spatrick const BitVector &ImplUseRegs; // The set of aliased implicit use registers. 16109467b48Spatrick const BitVector &AllDefRegs; // The set of all aliased def registers. 16209467b48Spatrick const BitVector &AllUseRegs; // The set of all aliased use registers. 16309467b48Spatrick private: 16409467b48Spatrick Instruction(const MCInstrDesc *Description, StringRef Name, 16509467b48Spatrick SmallVector<Operand, 8> Operands, 16609467b48Spatrick SmallVector<Variable, 4> Variables, const BitVector *ImplDefRegs, 16709467b48Spatrick const BitVector *ImplUseRegs, const BitVector *AllDefRegs, 16809467b48Spatrick const BitVector *AllUseRegs); 16909467b48Spatrick }; 17009467b48Spatrick 17109467b48Spatrick // Instructions are expensive to instantiate. This class provides a cache of 17209467b48Spatrick // Instructions with lazy construction. 17309467b48Spatrick struct InstructionsCache { 17409467b48Spatrick InstructionsCache(const MCInstrInfo &InstrInfo, 17509467b48Spatrick const RegisterAliasingTrackerCache &RATC); 17609467b48Spatrick 17709467b48Spatrick // Returns the Instruction object corresponding to this Opcode. 17809467b48Spatrick const Instruction &getInstr(unsigned Opcode) const; 17909467b48Spatrick 18009467b48Spatrick private: 18109467b48Spatrick const MCInstrInfo &InstrInfo; 18209467b48Spatrick const RegisterAliasingTrackerCache &RATC; 18309467b48Spatrick mutable std::unordered_map<unsigned, std::unique_ptr<Instruction>> 18409467b48Spatrick Instructions; 18509467b48Spatrick const BitVectorCache BVC; 18609467b48Spatrick }; 18709467b48Spatrick 18809467b48Spatrick // Represents the assignment of a Register to an Operand. 18909467b48Spatrick struct RegisterOperandAssignment { RegisterOperandAssignmentRegisterOperandAssignment19009467b48Spatrick RegisterOperandAssignment(const Operand *Operand, MCPhysReg Reg) 19109467b48Spatrick : Op(Operand), Reg(Reg) {} 19209467b48Spatrick 19309467b48Spatrick const Operand *Op; // Pointer to an Explicit Register Operand. 19409467b48Spatrick MCPhysReg Reg; 19509467b48Spatrick 19609467b48Spatrick bool operator==(const RegisterOperandAssignment &other) const; 19709467b48Spatrick }; 19809467b48Spatrick 19909467b48Spatrick // Represents a set of Operands that would alias through the use of some 20009467b48Spatrick // Registers. 20109467b48Spatrick // There are two reasons why operands would alias: 20209467b48Spatrick // - The registers assigned to each of the operands are the same or alias each 20309467b48Spatrick // other (e.g. AX/AL) 20409467b48Spatrick // - The operands are tied. 20509467b48Spatrick struct AliasingRegisterOperands { 20609467b48Spatrick SmallVector<RegisterOperandAssignment, 1> Defs; // Unlikely size() > 1. 20709467b48Spatrick SmallVector<RegisterOperandAssignment, 2> Uses; 20809467b48Spatrick 20909467b48Spatrick // True is Defs and Use contain an Implicit Operand. 21009467b48Spatrick bool hasImplicitAliasing() const; 21109467b48Spatrick 21209467b48Spatrick bool operator==(const AliasingRegisterOperands &other) const; 21309467b48Spatrick }; 21409467b48Spatrick 21509467b48Spatrick // Returns all possible configurations leading Def registers of DefInstruction 21609467b48Spatrick // to alias with Use registers of UseInstruction. 21709467b48Spatrick struct AliasingConfigurations { 21809467b48Spatrick AliasingConfigurations(const Instruction &DefInstruction, 219*d415bd75Srobert const Instruction &UseInstruction, 220*d415bd75Srobert const BitVector &ForbiddenRegisters); 22109467b48Spatrick 22209467b48Spatrick bool empty() const; // True if no aliasing configuration is found. 22309467b48Spatrick bool hasImplicitAliasing() const; 22409467b48Spatrick 22509467b48Spatrick SmallVector<AliasingRegisterOperands, 32> Configurations; 22609467b48Spatrick }; 22709467b48Spatrick 22809467b48Spatrick // Writes MCInst to OS. 22909467b48Spatrick // This is not assembly but the internal LLVM's name for instructions and 23009467b48Spatrick // registers. 23109467b48Spatrick void DumpMCInst(const MCRegisterInfo &MCRegisterInfo, 23209467b48Spatrick const MCInstrInfo &MCInstrInfo, const MCInst &MCInst, 23309467b48Spatrick raw_ostream &OS); 23409467b48Spatrick 23509467b48Spatrick } // namespace exegesis 23609467b48Spatrick } // namespace llvm 23709467b48Spatrick 23809467b48Spatrick #endif // LLVM_TOOLS_LLVM_EXEGESIS_MCINSTRDESCVIEW_H 239