//===-- InstructionSnippetGenerator.h ---------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// /// \file /// Defines helper classes to generate code snippets, in particular register /// assignment. /// //===----------------------------------------------------------------------===// #ifndef LLVM_TOOLS_LLVM_EXEGESIS_INSTRUCTIONSNIPPETGENERATOR_H #define LLVM_TOOLS_LLVM_EXEGESIS_INSTRUCTIONSNIPPETGENERATOR_H #include "OperandGraph.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCRegisterInfo.h" #include namespace exegesis { // A Variable represents a set of possible values that we need to choose from. // It may represent one or more explicit operands that are tied together, or one // implicit operand. class Variable final { public: bool IsUse = false; bool IsDef = false; bool IsReg = false; // Lists all the explicit operand indices that are tied to this variable. // Empty if Variable represents an implicit operand. llvm::SmallVector ExplicitOperands; // - In case of explicit operands, PossibleRegisters is the expansion of the // operands's RegClass registers. Please note that tied together explicit // operands share the same RegClass. // - In case of implicit operands, PossibleRegisters is a singleton MCPhysReg. llvm::SmallSetVector PossibleRegisters; // If RegInfo is null, register names won't get resolved. void print(llvm::raw_ostream &OS, const llvm::MCRegisterInfo *RegInfo) const; }; // Builds a model of implicit and explicit operands for InstrDesc into // Variables. llvm::SmallVector getVariables(const llvm::MCRegisterInfo &RegInfo, const llvm::MCInstrDesc &InstrDesc, const llvm::BitVector &ReservedRegs); // A simple object to represent a Variable assignement. struct VariableAssignment { VariableAssignment(size_t VarIdx, llvm::MCPhysReg AssignedReg); size_t VarIdx; llvm::MCPhysReg AssignedReg; bool operator==(const VariableAssignment &) const; bool operator<(const VariableAssignment &) const; }; // An AssignmentChain is a set of assignement realizing a dependency chain. // We inherit from std::set to leverage uniqueness of elements. using AssignmentChain = std::set; // Debug function to print an assignment chain. void dumpAssignmentChain(const llvm::MCRegisterInfo &RegInfo, const AssignmentChain &Chain); // Inserts Variables into a graph representing register aliasing and finds all // the possible dependency chains for this instruction, i.e. all the possible // assignement of operands that would make execution of the instruction // sequential. std::vector computeSequentialAssignmentChains(const llvm::MCRegisterInfo &RegInfo, llvm::ArrayRef Vars); // Selects a random configuration leading to a dependency chain. // The result is a vector of the same size as `Vars`. // `random_index_for_size` is a functor giving a random value in [0, arg[. std::vector getRandomAssignment(llvm::ArrayRef Vars, llvm::ArrayRef Chains, const std::function &RandomIndexForSize); // Finds an assignment of registers to variables such that no two variables are // assigned the same register. // The result is a vector of the same size as `Vars`, or `{}` if the // assignment is not feasible. std::vector getExclusiveAssignment(llvm::ArrayRef Vars); // Finds a greedy assignment of registers to variables. Each variable gets // assigned the first possible register that is not already assigned to a // previous variable. If there is no such register, the variable gets assigned // the first possible register. // The result is a vector of the same size as `Vars`, or `{}` if the // assignment is not feasible. std::vector getGreedyAssignment(llvm::ArrayRef Vars); // Generates an LLVM MCInst with the previously computed variables. // Immediate values are set to 1. llvm::MCInst generateMCInst(const llvm::MCInstrDesc &InstrDesc, llvm::ArrayRef Vars, llvm::ArrayRef VarRegs); } // namespace exegesis #endif // LLVM_TOOLS_LLVM_EXEGESIS_INSTRUCTIONSNIPPETGENERATOR_H