//===-- MCInstrDescView.h ---------------------------------------*- C++ -*-===// // // 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 // //===----------------------------------------------------------------------===// /// /// \file /// Provide views around LLVM structures to represents an instruction instance, /// as well as its implicit and explicit arguments in a uniform way. /// Arguments that are explicit and independant (non tied) also have a Variable /// associated to them so the instruction can be fully defined by reading its /// Variables. /// //===----------------------------------------------------------------------===// #ifndef LLVM_TOOLS_LLVM_EXEGESIS_MCINSTRDESCVIEW_H #define LLVM_TOOLS_LLVM_EXEGESIS_MCINSTRDESCVIEW_H #include #include #include #include "RegisterAliasing.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCInstrInfo.h" namespace llvm { namespace exegesis { // A variable represents the value associated to an Operand or a set of Operands // if they are tied together. struct Variable { // Returns the index of this Variable inside Instruction's Variable. unsigned getIndex() const; // Returns the index of the Operand linked to this Variable. unsigned getPrimaryOperandIndex() const; // Returns whether this Variable has more than one Operand linked to it. bool hasTiedOperands() const; // The indices of the operands tied to this Variable. SmallVector TiedOperands; // The index of this Variable in Instruction.Variables and its associated // Value in InstructionBuilder.VariableValues. Optional Index; }; // MCOperandInfo can only represents Explicit operands. This object gives a // uniform view of Implicit and Explicit Operands. // - Index: can be used to refer to MCInstrDesc::operands for Explicit operands. // - Tracker: is set for Register Operands and is used to keep track of possible // registers and the registers reachable from them (aliasing registers). // - Info: a shortcut for MCInstrDesc::operands()[Index]. // - TiedToIndex: the index of the Operand holding the value or -1. // - ImplicitReg: a pointer to the register value when Operand is Implicit, // nullptr otherwise. // - VariableIndex: the index of the Variable holding the value for this Operand // or -1 if this operand is implicit. struct Operand { bool isExplicit() const; bool isImplicit() const; bool isImplicitReg() const; bool isDef() const; bool isUse() const; bool isReg() const; bool isTied() const; bool isVariable() const; bool isMemory() const; bool isImmediate() const; unsigned getIndex() const; unsigned getTiedToIndex() const; unsigned getVariableIndex() const; unsigned getImplicitReg() const; const RegisterAliasingTracker &getRegisterAliasing() const; const MCOperandInfo &getExplicitOperandInfo() const; // Please use the accessors above and not the following fields. Optional Index; bool IsDef = false; const RegisterAliasingTracker *Tracker = nullptr; // Set for Register Op. const MCOperandInfo *Info = nullptr; // Set for Explicit Op. Optional TiedToIndex; // Set for Reg&Explicit Op. const MCPhysReg *ImplicitReg = nullptr; // Set for Implicit Op. Optional VariableIndex; // Set for Explicit Op. }; /// A cache of BitVector to reuse between Instructions. /// The cache will only be exercised during Instruction initialization. /// For X86, this is ~160 unique vectors for all of the ~15K Instructions. struct BitVectorCache { // Finds or allocates the provided BitVector in the cache and retrieves it's // unique instance. const BitVector *getUnique(BitVector &&BV) const; private: mutable std::vector> Cache; }; // A view over an MCInstrDesc offering a convenient interface to compute // Register aliasing. struct Instruction { // Create an instruction for a particular Opcode. static std::unique_ptr create(const MCInstrInfo &InstrInfo, const RegisterAliasingTrackerCache &RATC, const BitVectorCache &BVC, unsigned Opcode); // Prevent copy or move, instructions are allocated once and cached. Instruction(const Instruction &) = delete; Instruction(Instruction &&) = delete; Instruction &operator=(const Instruction &) = delete; Instruction &operator=(Instruction &&) = delete; // Returns the Operand linked to this Variable. // In case the Variable is tied, the primary (i.e. Def) Operand is returned. const Operand &getPrimaryOperand(const Variable &Var) const; // Whether this instruction is self aliasing through its tied registers. // Repeating this instruction is guaranteed to executes sequentially. bool hasTiedRegisters() const; // Whether this instruction is self aliasing through its implicit registers. // Repeating this instruction is guaranteed to executes sequentially. bool hasAliasingImplicitRegisters() const; // Whether this instruction is self aliasing through some registers. // Repeating this instruction may execute sequentially by picking aliasing // Use and Def registers. It may also execute in parallel by picking non // aliasing Use and Def registers. bool hasAliasingRegisters(const BitVector &ForbiddenRegisters) const; // Whether this instruction's registers alias with OtherInstr's registers. bool hasAliasingRegistersThrough(const Instruction &OtherInstr, const BitVector &ForbiddenRegisters) const; // Returns whether this instruction has Memory Operands. // Repeating this instruction executes sequentially with an instruction that // reads or write the same memory region. bool hasMemoryOperands() const; // Returns whether this instruction as at least one use or one def. // Repeating this instruction may execute sequentially by adding an // instruction that aliases one of these. bool hasOneUseOrOneDef() const; // Convenient function to help with debugging. void dump(const MCRegisterInfo &RegInfo, const RegisterAliasingTrackerCache &RATC, raw_ostream &Stream) const; const MCInstrDesc &Description; const StringRef Name; // The name of this instruction. const SmallVector Operands; const SmallVector Variables; const BitVector &ImplDefRegs; // The set of aliased implicit def registers. const BitVector &ImplUseRegs; // The set of aliased implicit use registers. const BitVector &AllDefRegs; // The set of all aliased def registers. const BitVector &AllUseRegs; // The set of all aliased use registers. private: Instruction(const MCInstrDesc *Description, StringRef Name, SmallVector Operands, SmallVector Variables, const BitVector *ImplDefRegs, const BitVector *ImplUseRegs, const BitVector *AllDefRegs, const BitVector *AllUseRegs); }; // Instructions are expensive to instantiate. This class provides a cache of // Instructions with lazy construction. struct InstructionsCache { InstructionsCache(const MCInstrInfo &InstrInfo, const RegisterAliasingTrackerCache &RATC); // Returns the Instruction object corresponding to this Opcode. const Instruction &getInstr(unsigned Opcode) const; private: const MCInstrInfo &InstrInfo; const RegisterAliasingTrackerCache &RATC; mutable std::unordered_map> Instructions; const BitVectorCache BVC; }; // Represents the assignment of a Register to an Operand. struct RegisterOperandAssignment { RegisterOperandAssignment(const Operand *Operand, MCPhysReg Reg) : Op(Operand), Reg(Reg) {} const Operand *Op; // Pointer to an Explicit Register Operand. MCPhysReg Reg; bool operator==(const RegisterOperandAssignment &other) const; }; // Represents a set of Operands that would alias through the use of some // Registers. // There are two reasons why operands would alias: // - The registers assigned to each of the operands are the same or alias each // other (e.g. AX/AL) // - The operands are tied. struct AliasingRegisterOperands { SmallVector Defs; // Unlikely size() > 1. SmallVector Uses; // True is Defs and Use contain an Implicit Operand. bool hasImplicitAliasing() const; bool operator==(const AliasingRegisterOperands &other) const; }; // Returns all possible configurations leading Def registers of DefInstruction // to alias with Use registers of UseInstruction. struct AliasingConfigurations { AliasingConfigurations(const Instruction &DefInstruction, const Instruction &UseInstruction); bool empty() const; // True if no aliasing configuration is found. bool hasImplicitAliasing() const; SmallVector Configurations; }; // Writes MCInst to OS. // This is not assembly but the internal LLVM's name for instructions and // registers. void DumpMCInst(const MCRegisterInfo &MCRegisterInfo, const MCInstrInfo &MCInstrInfo, const MCInst &MCInst, raw_ostream &OS); } // namespace exegesis } // namespace llvm #endif // LLVM_TOOLS_LLVM_EXEGESIS_MCINSTRDESCVIEW_H