for (const unsigned OtherOpcode : Opcodes) {
if (OtherOpcode == Instr.Description->getOpcode())
continue;
- const Instruction OtherInstr(State, OtherOpcode);
+ const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode);
if (OtherInstr.hasMemoryOperands())
continue;
if (Instr.hasAliasingRegistersThrough(OtherInstr))
}
RATC.reset(new RegisterAliasingTrackerCache(
getRegInfo(), getFunctionReservedRegs(getTargetMachine())));
+ IC.reset(new InstructionsCache(getInstrInfo(), getRATC()));
}
LLVMState::LLVMState()
#ifndef LLVM_TOOLS_LLVM_EXEGESIS_LLVMSTATE_H
#define LLVM_TOOLS_LLVM_EXEGESIS_LLVMSTATE_H
+#include "MCInstrDescView.h"
#include "RegisterAliasing.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCInst.h"
return *TargetMachine->getMCSubtargetInfo();
}
const RegisterAliasingTrackerCache &getRATC() const { return *RATC; }
+ const InstructionsCache &getIC() const { return *IC; }
private:
const ExegesisTarget *TheExegesisTarget;
std::unique_ptr<const llvm::TargetMachine> TargetMachine;
std::unique_ptr<const RegisterAliasingTrackerCache> RATC;
+ std::unique_ptr<const InstructionsCache> IC;
};
} // namespace exegesis
return *Info;
}
-Instruction::Instruction(const LLVMState &State, unsigned Opcode)
- : Description(&State.getInstrInfo().get(Opcode)),
- Name(State.getInstrInfo().getName(Opcode)) {
- const auto &RATC = State.getRATC();
+Instruction::Instruction(const llvm::MCInstrInfo &InstrInfo,
+ const RegisterAliasingTrackerCache &RATC,
+ unsigned Opcode)
+ : Description(&InstrInfo.get(Opcode)), Name(InstrInfo.getName(Opcode)) {
unsigned OpIndex = 0;
for (; OpIndex < Description->getNumOperands(); ++OpIndex) {
const auto &OpInfo = Description->opInfo_begin()[OpIndex];
Stream << "- hasAliasingRegisters\n";
}
+InstructionsCache::InstructionsCache(const llvm::MCInstrInfo &InstrInfo,
+ const RegisterAliasingTrackerCache &RATC)
+ : InstrInfo(InstrInfo), RATC(RATC) {}
+
+const Instruction &InstructionsCache::getInstr(unsigned Opcode) const {
+ auto &Found = Instructions[Opcode];
+ if (!Found)
+ Found.reset(new Instruction(InstrInfo, RATC, Opcode));
+ return *Found;
+}
+
bool RegisterOperandAssignment::
operator==(const RegisterOperandAssignment &Other) const {
return std::tie(Op, Reg) == std::tie(Other.Op, Other.Reg);
#define LLVM_TOOLS_LLVM_EXEGESIS_MCINSTRDESCVIEW_H
#include <random>
+#include <unordered_map>
-#include "LlvmState.h"
#include "RegisterAliasing.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
// A view over an MCInstrDesc offering a convenient interface to compute
// Register aliasing.
struct Instruction {
- Instruction(const LLVMState &State, unsigned Opcode);
+ Instruction(const llvm::MCInstrInfo &InstrInfo,
+ const RegisterAliasingTrackerCache &RATC, unsigned Opcode);
// Returns the Operand linked to this Variable.
// In case the Variable is tied, the primary (i.e. Def) Operand is returned.
llvm::BitVector AllUseRegs; // The set of all aliased use registers.
};
+// Instructions are expensive to instantiate. This class provides a cache of
+// Instructions with lazy construction.
+struct InstructionsCache {
+ InstructionsCache(const llvm::MCInstrInfo &InstrInfo,
+ const RegisterAliasingTrackerCache &RATC);
+
+ // Returns the Instruction object corresponding to this Opcode.
+ const Instruction &getInstr(unsigned Opcode) const;
+
+private:
+ const llvm::MCInstrInfo &InstrInfo;
+ const RegisterAliasingTrackerCache &RATC;
+ mutable std::unordered_map<unsigned, std::unique_ptr<Instruction>>
+ Instructions;
+};
+
// Represents the assignment of a Register to an Operand.
struct RegisterOperandAssignment {
RegisterOperandAssignment(const Operand *Operand, llvm::MCPhysReg Reg)
// Generates code snippets for opcode `Opcode`.
static llvm::Expected<std::vector<BenchmarkCode>>
generateSnippets(const LLVMState &State, unsigned Opcode) {
- const Instruction Instr(State, Opcode);
+ const Instruction &Instr = State.getIC().getInstr(Opcode);
const llvm::MCInstrDesc &InstrDesc = *Instr.Description;
// Ignore instructions that we cannot run.
if (InstrDesc.isPseudo())
std::vector<CodeTemplate> checkAndGetCodeTemplates(unsigned Opcode) {
randomGenerator().seed(0); // Initialize seed.
- const Instruction Instr(State, Opcode);
+ const Instruction &Instr = State.getIC().getInstr(Opcode);
auto CodeTemplateOrError = Generator.generateCodeTemplates(Instr);
EXPECT_FALSE(CodeTemplateOrError.takeError()); // Valid configuration.
return std::move(CodeTemplateOrError.get());
// - hasAliasingImplicitRegisters (execution is always serial)
// - hasAliasingRegisters
const unsigned Opcode = llvm::X86::MOVSB;
- const Instruction Instr(State, Opcode);
+ const Instruction &Instr = State.getIC().getInstr(Opcode);
auto Error = Generator.generateCodeTemplates(Instr).takeError();
EXPECT_TRUE((bool)Error);
llvm::consumeError(std::move(Error));
FakeSnippetGenerator(const LLVMState &State) : SnippetGenerator(State) {}
Instruction createInstruction(unsigned Opcode) {
- return Instruction(State, Opcode);
+ return State.getIC().getInstr(Opcode);
}
private: