summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp')
-rw-r--r--llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp146
1 files changed, 146 insertions, 0 deletions
diff --git a/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp b/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp
index ae985629136..f3111797993 100644
--- a/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp
+++ b/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp
@@ -15,4 +15,150 @@ CodeTemplate::CodeTemplate(CodeTemplate &&) = default;
CodeTemplate &CodeTemplate::operator=(CodeTemplate &&) = default;
+InstructionTemplate::InstructionTemplate(const Instruction &Instr)
+ : Instr(Instr), VariableValues(Instr.Variables.size()) {}
+
+InstructionTemplate::InstructionTemplate(InstructionTemplate &&) = default;
+
+InstructionTemplate &InstructionTemplate::
+operator=(InstructionTemplate &&) = default;
+
+InstructionTemplate::InstructionTemplate(const InstructionTemplate &) = default;
+
+InstructionTemplate &InstructionTemplate::
+operator=(const InstructionTemplate &) = default;
+
+unsigned InstructionTemplate::getOpcode() const {
+ return Instr.Description->getOpcode();
+}
+
+llvm::MCOperand &InstructionTemplate::getValueFor(const Variable &Var) {
+ return VariableValues[Var.Index];
+}
+
+const llvm::MCOperand &
+InstructionTemplate::getValueFor(const Variable &Var) const {
+ return VariableValues[Var.Index];
+}
+
+llvm::MCOperand &InstructionTemplate::getValueFor(const Operand &Op) {
+ assert(Op.VariableIndex >= 0);
+ return getValueFor(Instr.Variables[Op.VariableIndex]);
+}
+
+const llvm::MCOperand &
+InstructionTemplate::getValueFor(const Operand &Op) const {
+ assert(Op.VariableIndex >= 0);
+ return getValueFor(Instr.Variables[Op.VariableIndex]);
+}
+
+// forward declaration.
+static void randomize(const Instruction &Instr, const Variable &Var,
+ llvm::MCOperand &AssignedValue,
+ const llvm::BitVector &ForbiddenRegs);
+
+bool InstructionTemplate::hasImmediateVariables() const {
+ return llvm::any_of(Instr.Variables, [this](const Variable &Var) {
+ assert(!Var.TiedOperands.empty());
+ const unsigned OpIndex = Var.TiedOperands[0];
+ const Operand &Op = Instr.Operands[OpIndex];
+ assert(Op.Info);
+ return Op.Info->OperandType == llvm::MCOI::OPERAND_IMMEDIATE;
+ });
+}
+
+void InstructionTemplate::randomizeUnsetVariables(
+ const llvm::BitVector &ForbiddenRegs) {
+ for (const Variable &Var : Instr.Variables) {
+ llvm::MCOperand &AssignedValue = getValueFor(Var);
+ if (!AssignedValue.isValid())
+ randomize(Instr, Var, AssignedValue, ForbiddenRegs);
+ }
+}
+
+llvm::MCInst InstructionTemplate::build() const {
+ llvm::MCInst Result;
+ Result.setOpcode(Instr.Description->Opcode);
+ for (const auto &Op : Instr.Operands)
+ if (Op.IsExplicit)
+ Result.addOperand(getValueFor(Op));
+ return Result;
+}
+
+std::mt19937 &randomGenerator() {
+ static std::random_device RandomDevice;
+ static std::mt19937 RandomGenerator(RandomDevice());
+ return RandomGenerator;
+}
+
+static size_t randomIndex(size_t Size) {
+ assert(Size > 0);
+ std::uniform_int_distribution<> Distribution(0, Size - 1);
+ return Distribution(randomGenerator());
+}
+
+template <typename C>
+static auto randomElement(const C &Container) -> decltype(Container[0]) {
+ return Container[randomIndex(Container.size())];
+}
+
+static void randomize(const Instruction &Instr, const Variable &Var,
+ llvm::MCOperand &AssignedValue,
+ const llvm::BitVector &ForbiddenRegs) {
+ assert(!Var.TiedOperands.empty());
+ const Operand &Op = Instr.Operands[Var.TiedOperands.front()];
+ assert(Op.Info != nullptr);
+ const auto &OpInfo = *Op.Info;
+ switch (OpInfo.OperandType) {
+ case llvm::MCOI::OperandType::OPERAND_IMMEDIATE:
+ // FIXME: explore immediate values too.
+ AssignedValue = llvm::MCOperand::createImm(1);
+ break;
+ case llvm::MCOI::OperandType::OPERAND_REGISTER: {
+ assert(Op.Tracker);
+ auto AllowedRegs = Op.Tracker->sourceBits();
+ assert(AllowedRegs.size() == ForbiddenRegs.size());
+ for (auto I : ForbiddenRegs.set_bits())
+ AllowedRegs.reset(I);
+ AssignedValue = llvm::MCOperand::createReg(randomBit(AllowedRegs));
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static void setRegisterOperandValue(const RegisterOperandAssignment &ROV,
+ InstructionTemplate &IB) {
+ assert(ROV.Op);
+ if (ROV.Op->IsExplicit) {
+ auto &AssignedValue = IB.getValueFor(*ROV.Op);
+ if (AssignedValue.isValid()) {
+ assert(AssignedValue.isReg() && AssignedValue.getReg() == ROV.Reg);
+ return;
+ }
+ AssignedValue = llvm::MCOperand::createReg(ROV.Reg);
+ } else {
+ assert(ROV.Op->ImplicitReg != nullptr);
+ assert(ROV.Reg == *ROV.Op->ImplicitReg);
+ }
+}
+
+size_t randomBit(const llvm::BitVector &Vector) {
+ assert(Vector.any());
+ auto Itr = Vector.set_bits_begin();
+ for (size_t I = randomIndex(Vector.count()); I != 0; --I)
+ ++Itr;
+ return *Itr;
+}
+
+void setRandomAliasing(const AliasingConfigurations &AliasingConfigurations,
+ InstructionTemplate &DefIB, InstructionTemplate &UseIB) {
+ assert(!AliasingConfigurations.empty());
+ assert(!AliasingConfigurations.hasImplicitAliasing());
+ const auto &RandomConf = randomElement(AliasingConfigurations.Configurations);
+ setRegisterOperandValue(randomElement(RandomConf.Defs), DefIB);
+ setRegisterOperandValue(randomElement(RandomConf.Uses), UseIB);
+}
+
} // namespace exegesis
OpenPOWER on IntegriCloud