From 6d16fd8353b5152b4fe683b828189dbecc068811 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Sat, 6 Apr 2019 14:16:26 +0000 Subject: [PATCH] [llvm-exegesis][X86] Handle CMOVcc/SETcc OPERAND_COND_CODE OperandType Summary: D60041 / D60138 refactoring changed how CMOV/SETcc opcodes are handled. concode is now an immediate, with it's own operand type. This at least allows to not crash on the opcode. However, this still won't generate all the snippets with all the condcode enumerators. D60066 does that. Reviewers: courbet, gchatelet Reviewed By: gchatelet Subscribers: tschuett, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D60057 llvm-svn: 357841 --- .../llvm-exegesis/X86/latency-CMOV32rr.s | 9 ++++++ tools/llvm-exegesis/lib/SnippetGenerator.cpp | 31 +++---------------- tools/llvm-exegesis/lib/SnippetGenerator.h | 3 +- tools/llvm-exegesis/lib/Target.cpp | 24 ++++++++++++++ tools/llvm-exegesis/lib/Target.h | 8 +++++ tools/llvm-exegesis/lib/X86/Target.cpp | 21 +++++++++++++ 6 files changed, 69 insertions(+), 27 deletions(-) create mode 100644 test/tools/llvm-exegesis/X86/latency-CMOV32rr.s diff --git a/test/tools/llvm-exegesis/X86/latency-CMOV32rr.s b/test/tools/llvm-exegesis/X86/latency-CMOV32rr.s new file mode 100644 index 00000000000..d983c2b0613 --- /dev/null +++ b/test/tools/llvm-exegesis/X86/latency-CMOV32rr.s @@ -0,0 +1,9 @@ +# RUN: llvm-exegesis -mode=latency -opcode-name=CMOV32rr | FileCheck %s + +CHECK: --- +CHECK-NEXT: mode: latency +CHECK-NEXT: key: +CHECK-NEXT: instructions: +CHECK-NEXT: CMOV32rr +CHECK-NEXT: config: '' +CHECK-LAST: ... diff --git a/tools/llvm-exegesis/lib/SnippetGenerator.cpp b/tools/llvm-exegesis/lib/SnippetGenerator.cpp index 44592fd89a3..8cbde9f0186 100644 --- a/tools/llvm-exegesis/lib/SnippetGenerator.cpp +++ b/tools/llvm-exegesis/lib/SnippetGenerator.cpp @@ -12,6 +12,7 @@ #include "Assembler.h" #include "MCInstrDescView.h" #include "SnippetGenerator.h" +#include "Target.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" @@ -50,7 +51,7 @@ SnippetGenerator::generateConfigurations(const Instruction &Instr) const { BenchmarkCode BC; BC.Info = CT.Info; for (InstructionTemplate &IT : CT.Instructions) { - randomizeUnsetVariables(ForbiddenRegs, IT); + randomizeUnsetVariables(State.getExegesisTarget(), ForbiddenRegs, IT); BC.Instructions.push_back(IT.build()); } if (CT.ScratchSpacePointerInReg) @@ -156,29 +157,6 @@ 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) { - const Operand &Op = Instr.getPrimaryOperand(Var); - switch (Op.getExplicitOperandInfo().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.isReg()); - auto AllowedRegs = Op.getRegisterAliasing().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); @@ -212,12 +190,13 @@ void setRandomAliasing(const AliasingConfigurations &AliasingConfigurations, setRegisterOperandValue(randomElement(RandomConf.Uses), UseIB); } -void randomizeUnsetVariables(const llvm::BitVector &ForbiddenRegs, +void randomizeUnsetVariables(const ExegesisTarget &Target, + const llvm::BitVector &ForbiddenRegs, InstructionTemplate &IT) { for (const Variable &Var : IT.Instr.Variables) { llvm::MCOperand &AssignedValue = IT.getValueFor(Var); if (!AssignedValue.isValid()) - randomize(IT.Instr, Var, AssignedValue, ForbiddenRegs); + Target.randomizeMCOperand(IT.Instr, Var, AssignedValue, ForbiddenRegs); } } diff --git a/tools/llvm-exegesis/lib/SnippetGenerator.h b/tools/llvm-exegesis/lib/SnippetGenerator.h index a07bc6981ae..289fa02096a 100644 --- a/tools/llvm-exegesis/lib/SnippetGenerator.h +++ b/tools/llvm-exegesis/lib/SnippetGenerator.h @@ -88,7 +88,8 @@ void setRandomAliasing(const AliasingConfigurations &AliasingConfigurations, // Assigns a Random Value to all Variables in IT that are still Invalid. // Do not use any of the registers in `ForbiddenRegs`. -void randomizeUnsetVariables(const llvm::BitVector &ForbiddenRegs, +void randomizeUnsetVariables(const ExegesisTarget &Target, + const llvm::BitVector &ForbiddenRegs, InstructionTemplate &IT); } // namespace exegesis diff --git a/tools/llvm-exegesis/lib/Target.cpp b/tools/llvm-exegesis/lib/Target.cpp index c662f1f5566..945aabb8a3f 100644 --- a/tools/llvm-exegesis/lib/Target.cpp +++ b/tools/llvm-exegesis/lib/Target.cpp @@ -86,6 +86,30 @@ ExegesisTarget::createUopsBenchmarkRunner(const LLVMState &State) const { return llvm::make_unique(State); } +void ExegesisTarget::randomizeMCOperand( + const Instruction &Instr, const Variable &Var, + llvm::MCOperand &AssignedValue, + const llvm::BitVector &ForbiddenRegs) const { + const Operand &Op = Instr.getPrimaryOperand(Var); + switch (Op.getExplicitOperandInfo().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.isReg()); + auto AllowedRegs = Op.getRegisterAliasing().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_assert(std::is_pod::value, "We shouldn't have dynamic initialization here"); const PfmCountersInfo PfmCountersInfo::Default = {nullptr, nullptr, nullptr, diff --git a/tools/llvm-exegesis/lib/Target.h b/tools/llvm-exegesis/lib/Target.h index ab760bfa820..0c574780865 100644 --- a/tools/llvm-exegesis/lib/Target.h +++ b/tools/llvm-exegesis/lib/Target.h @@ -102,6 +102,14 @@ public: // matter as long as it's large enough. virtual unsigned getMaxMemoryAccessSize() const { return 0; } + // Assigns a random operand of the right type to variable Var. + // The default implementation only handles generic operand types. + // The target is responsible for handling any operand + // starting from OPERAND_FIRST_TARGET. + virtual void randomizeMCOperand(const Instruction &Instr, const Variable &Var, + llvm::MCOperand &AssignedValue, + const llvm::BitVector &ForbiddenRegs) const; + // Creates a snippet generator for the given mode. std::unique_ptr createSnippetGenerator(InstructionBenchmark::ModeE Mode, diff --git a/tools/llvm-exegesis/lib/X86/Target.cpp b/tools/llvm-exegesis/lib/X86/Target.cpp index 6ef1953352f..01e3589cc2d 100644 --- a/tools/llvm-exegesis/lib/X86/Target.cpp +++ b/tools/llvm-exegesis/lib/X86/Target.cpp @@ -433,6 +433,10 @@ private: unsigned getMaxMemoryAccessSize() const override { return 64; } + void randomizeMCOperand(const Instruction &Instr, const Variable &Var, + llvm::MCOperand &AssignedValue, + const llvm::BitVector &ForbiddenRegs) const override; + void fillMemoryOperands(InstructionTemplate &IT, unsigned Reg, unsigned Offset) const override; @@ -485,6 +489,23 @@ ExegesisX86Target::getScratchMemoryRegister(const llvm::Triple &TT) const { return TT.isOSWindows() ? llvm::X86::RCX : llvm::X86::RDI; } +void ExegesisX86Target::randomizeMCOperand( + const Instruction &Instr, const Variable &Var, + llvm::MCOperand &AssignedValue, + const llvm::BitVector &ForbiddenRegs) const { + ExegesisTarget::randomizeMCOperand(Instr, Var, AssignedValue, ForbiddenRegs); + + const Operand &Op = Instr.getPrimaryOperand(Var); + switch (Op.getExplicitOperandInfo().OperandType) { + case llvm::X86::OperandType::OPERAND_COND_CODE: + // FIXME: explore all CC variants. + AssignedValue = llvm::MCOperand::createImm(1); + break; + default: + break; + } +} + void ExegesisX86Target::fillMemoryOperands(InstructionTemplate &IT, unsigned Reg, unsigned Offset) const {