[llvm] r338567 - [llvm-exegesis] Provide a way to handle memory instructions.
Guillaume Chatelet via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 1 07:41:45 PDT 2018
Author: gchatelet
Date: Wed Aug 1 07:41:45 2018
New Revision: 338567
URL: http://llvm.org/viewvc/llvm-project?rev=338567&view=rev
Log:
[llvm-exegesis] Provide a way to handle memory instructions.
Summary:
And implement memory instructions on X86.
This fixes PR36906.
Reviewers: gchatelet
Reviewed By: gchatelet
Subscribers: lebedev.ri, filcab, mgorny, tschuett, RKSimon, llvm-commits
Differential Revision: https://reviews.llvm.org/D48935
Added:
llvm/trunk/unittests/tools/llvm-exegesis/BenchmarkRunnerTest.cpp
Modified:
llvm/trunk/tools/llvm-exegesis/lib/Assembler.cpp
llvm/trunk/tools/llvm-exegesis/lib/Assembler.h
llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h
llvm/trunk/tools/llvm-exegesis/lib/Latency.cpp
llvm/trunk/tools/llvm-exegesis/lib/Latency.h
llvm/trunk/tools/llvm-exegesis/lib/MCInstrDescView.cpp
llvm/trunk/tools/llvm-exegesis/lib/MCInstrDescView.h
llvm/trunk/tools/llvm-exegesis/lib/RegisterAliasing.h
llvm/trunk/tools/llvm-exegesis/lib/Target.cpp
llvm/trunk/tools/llvm-exegesis/lib/Target.h
llvm/trunk/tools/llvm-exegesis/lib/Uops.cpp
llvm/trunk/tools/llvm-exegesis/lib/Uops.h
llvm/trunk/tools/llvm-exegesis/lib/X86/Target.cpp
llvm/trunk/unittests/tools/llvm-exegesis/ARM/AssemblerTest.cpp
llvm/trunk/unittests/tools/llvm-exegesis/CMakeLists.txt
llvm/trunk/unittests/tools/llvm-exegesis/Common/AssemblerUtils.h
llvm/trunk/unittests/tools/llvm-exegesis/X86/AssemblerTest.cpp
llvm/trunk/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp
Modified: llvm/trunk/tools/llvm-exegesis/lib/Assembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/Assembler.cpp?rev=338567&r1=338566&r2=338567&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/Assembler.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/Assembler.cpp Wed Aug 1 07:41:45 2018
@@ -66,12 +66,16 @@ static bool addPass(llvm::PassManagerBas
return false;
}
-// Creates a void MachineFunction with no argument.
+// Creates a void(int8*) MachineFunction.
static llvm::MachineFunction &
-createVoidVoidMachineFunction(llvm::StringRef FunctionID, llvm::Module *Module,
- llvm::MachineModuleInfo *MMI) {
+createVoidVoidPtrMachineFunction(llvm::StringRef FunctionID,
+ llvm::Module *Module,
+ llvm::MachineModuleInfo *MMI) {
llvm::Type *const ReturnType = llvm::Type::getInt32Ty(Module->getContext());
- llvm::FunctionType *FunctionType = llvm::FunctionType::get(ReturnType, false);
+ llvm::Type *const MemParamType = llvm::PointerType::get(
+ llvm::Type::getInt8Ty(Module->getContext()), 0 /*default address space*/);
+ llvm::FunctionType *FunctionType =
+ llvm::FunctionType::get(ReturnType, {MemParamType}, false);
llvm::Function *const F = llvm::Function::Create(
FunctionType, llvm::GlobalValue::InternalLinkage, FunctionID, Module);
// Making sure we can create a MachineFunction out of this Function even if it
@@ -81,9 +85,12 @@ createVoidVoidMachineFunction(llvm::Stri
}
static void fillMachineFunction(llvm::MachineFunction &MF,
+ llvm::ArrayRef<unsigned> LiveIns,
llvm::ArrayRef<llvm::MCInst> Instructions) {
llvm::MachineBasicBlock *MBB = MF.CreateMachineBasicBlock();
MF.push_back(MBB);
+ for (const unsigned Reg : LiveIns)
+ MBB->addLiveIn(Reg);
const llvm::MCInstrInfo *MCII = MF.getTarget().getMCInstrInfo();
llvm::DebugLoc DL;
for (const llvm::MCInst &Inst : Instructions) {
@@ -134,13 +141,14 @@ llvm::BitVector getFunctionReservedRegs(
std::unique_ptr<llvm::MachineModuleInfo> MMI =
llvm::make_unique<llvm::MachineModuleInfo>(&TM);
llvm::MachineFunction &MF =
- createVoidVoidMachineFunction(FunctionID, Module.get(), MMI.get());
+ createVoidVoidPtrMachineFunction(FunctionID, Module.get(), MMI.get());
// Saving reserved registers for client.
return MF.getSubtarget().getRegisterInfo()->getReservedRegs(MF);
}
void assembleToStream(const ExegesisTarget &ET,
std::unique_ptr<llvm::LLVMTargetMachine> TM,
+ llvm::ArrayRef<unsigned> LiveIns,
llvm::ArrayRef<unsigned> RegsToDef,
llvm::ArrayRef<llvm::MCInst> Instructions,
llvm::raw_pwrite_stream &AsmStream) {
@@ -151,13 +159,17 @@ void assembleToStream(const ExegesisTarg
std::unique_ptr<llvm::MachineModuleInfo> MMI =
llvm::make_unique<llvm::MachineModuleInfo>(TM.get());
llvm::MachineFunction &MF =
- createVoidVoidMachineFunction(FunctionID, Module.get(), MMI.get());
+ createVoidVoidPtrMachineFunction(FunctionID, Module.get(), MMI.get());
// We need to instruct the passes that we're done with SSA and virtual
// registers.
auto &Properties = MF.getProperties();
Properties.set(llvm::MachineFunctionProperties::Property::NoVRegs);
Properties.reset(llvm::MachineFunctionProperties::Property::IsSSA);
+
+ for (const unsigned Reg : LiveIns)
+ MF.getRegInfo().addLiveIn(Reg);
+
bool IsSnippetSetupComplete = false;
std::vector<llvm::MCInst> SnippetWithSetup =
generateSnippetSetupCode(RegsToDef, ET, *TM, IsSnippetSetupComplete);
@@ -176,7 +188,7 @@ void assembleToStream(const ExegesisTarg
MF.getRegInfo().freezeReservedRegs(MF);
// Fill the MachineFunction from the instructions.
- fillMachineFunction(MF, Instructions);
+ fillMachineFunction(MF, LiveIns, Instructions);
// We create the pass manager, run the passes to populate AsmBuffer.
llvm::MCContext &MCContext = MMI->getContext();
Modified: llvm/trunk/tools/llvm-exegesis/lib/Assembler.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/Assembler.h?rev=338567&r1=338566&r2=338567&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/Assembler.h (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/Assembler.h Wed Aug 1 07:41:45 2018
@@ -39,12 +39,13 @@ class ExegesisTarget;
// convention and target machine).
llvm::BitVector getFunctionReservedRegs(const llvm::TargetMachine &TM);
-// Creates a temporary `void foo()` function containing the provided
+// Creates a temporary `void foo(char*)` function containing the provided
// Instructions. Runs a set of llvm Passes to provide correct prologue and
// epilogue. Once the MachineFunction is ready, it is assembled for TM to
// AsmStream, the temporary function is eventually discarded.
void assembleToStream(const ExegesisTarget &ET,
std::unique_ptr<llvm::LLVMTargetMachine> TM,
+ llvm::ArrayRef<unsigned> LiveIns,
llvm::ArrayRef<unsigned> RegsToDef,
llvm::ArrayRef<llvm::MCInst> Instructions,
llvm::raw_pwrite_stream &AsmStream);
@@ -59,7 +60,7 @@ getObjectFromBuffer(llvm::StringRef Buff
llvm::object::OwningBinary<llvm::object::ObjectFile>
getObjectFromFile(llvm::StringRef Filename);
-// Consumes an ObjectFile containing a `void foo()` function and make it
+// Consumes an ObjectFile containing a `void foo(char*)` function and make it
// executable.
struct ExecutableFunction {
explicit ExecutableFunction(
@@ -70,7 +71,9 @@ struct ExecutableFunction {
llvm::StringRef getFunctionBytes() const { return FunctionBytes; }
// Executes the function.
- void operator()() const { ((void (*)())(intptr_t)FunctionBytes.data())(); }
+ void operator()(char *Memory) const {
+ ((void (*)(char *))(intptr_t)FunctionBytes.data())(Memory);
+ }
std::unique_ptr<llvm::LLVMContext> Context;
std::unique_ptr<llvm::ExecutionEngine> ExecEngine;
Modified: llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp?rev=338567&r1=338566&r2=338567&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp Wed Aug 1 07:41:45 2018
@@ -30,7 +30,7 @@ BenchmarkRunner::BenchmarkRunner(const L
InstructionBenchmark::ModeE Mode)
: State(State), RATC(State.getRegInfo(),
getFunctionReservedRegs(State.getTargetMachine())),
- Mode(Mode) {}
+ Mode(Mode), Scratch(llvm::make_unique<ScratchSpace>()) {}
BenchmarkRunner::~BenchmarkRunner() = default;
@@ -119,7 +119,7 @@ BenchmarkRunner::runOne(const BenchmarkC
<< *ObjectFilePath << "\n";
const ExecutableFunction EF(State.createTargetMachine(),
getObjectFromFile(*ObjectFilePath));
- InstrBenchmark.Measurements = runMeasurements(EF, NumRepetitions);
+ InstrBenchmark.Measurements = runMeasurements(EF, *Scratch, NumRepetitions);
return InstrBenchmark;
}
@@ -132,9 +132,14 @@ BenchmarkRunner::generateConfigurations(
BenchmarkConfiguration Configuration;
Configuration.Info = Prototype.Explanation;
for (InstructionInstance &II : Prototype.Snippet) {
- II.randomizeUnsetVariables();
+ II.randomizeUnsetVariables(
+ Prototype.ScratchSpaceReg
+ ? RATC.getRegister(Prototype.ScratchSpaceReg).aliasedBits()
+ : RATC.emptyRegisters());
Configuration.Snippet.push_back(II.build());
}
+ if (Prototype.ScratchSpaceReg)
+ Configuration.SnippetSetup.LiveIns.push_back(Prototype.ScratchSpaceReg);
Configuration.SnippetSetup.RegsToDef = computeRegsToDef(Prototype.Snippet);
return std::vector<BenchmarkConfiguration>{Configuration};
} else
@@ -144,6 +149,7 @@ BenchmarkRunner::generateConfigurations(
std::vector<unsigned> BenchmarkRunner::computeRegsToDef(
const std::vector<InstructionInstance> &Snippet) const {
// Collect all register uses and create an assignment for each of them.
+ // Ignore memory operands which are handled separately.
// Loop invariant: DefinedRegs[i] is true iif it has been set at least once
// before the current instruction.
llvm::BitVector DefinedRegs = RATC.emptyRegisters();
@@ -152,11 +158,12 @@ std::vector<unsigned> BenchmarkRunner::c
// Returns the register that this Operand sets or uses, or 0 if this is not
// a register.
const auto GetOpReg = [&II](const Operand &Op) -> unsigned {
- if (Op.ImplicitReg) {
+ if (Op.IsMem)
+ return 0;
+ if (Op.ImplicitReg)
return *Op.ImplicitReg;
- } else if (Op.IsExplicit && II.getValueFor(Op).isReg()) {
+ if (Op.IsExplicit && II.getValueFor(Op).isReg())
return II.getValueFor(Op).getReg();
- }
return 0;
};
// Collect used registers that have never been def'ed.
@@ -173,9 +180,8 @@ std::vector<unsigned> BenchmarkRunner::c
for (const Operand &Op : II.Instr.Operands) {
if (Op.IsDef) {
const unsigned Reg = GetOpReg(Op);
- if (Reg > 0) {
+ if (Reg > 0)
DefinedRegs.set(Reg);
- }
}
}
}
@@ -192,7 +198,7 @@ BenchmarkRunner::writeObjectFile(const B
return std::move(E);
llvm::raw_fd_ostream OFS(ResultFD, true /*ShouldClose*/);
assembleToStream(State.getExegesisTarget(), State.createTargetMachine(),
- Setup.RegsToDef, Code, OFS);
+ Setup.LiveIns, Setup.RegsToDef, Code, OFS);
return ResultPath.str();
}
Modified: llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h?rev=338567&r1=338566&r2=338567&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.h Wed Aug 1 07:41:45 2018
@@ -23,6 +23,8 @@
#include "RegisterAliasing.h"
#include "llvm/MC/MCInst.h"
#include "llvm/Support/Error.h"
+#include <cstdlib>
+#include <memory>
#include <vector>
namespace exegesis {
@@ -40,6 +42,7 @@ struct BenchmarkConfiguration {
// measurement it should be as short as possible. It is usually used to setup
// the content of the Registers.
struct Setup {
+ std::vector<unsigned> LiveIns; // The registers that are live on entry.
std::vector<unsigned> RegsToDef;
};
Setup SnippetSetup;
@@ -66,6 +69,23 @@ public:
std::vector<unsigned>
computeRegsToDef(const std::vector<InstructionInstance> &Snippet) const;
+ // Scratch space to run instructions that touch memory.
+ struct ScratchSpace {
+ static constexpr const size_t kAlignment = 1024;
+ static constexpr const size_t kSize = 1 << 20; // 1MB.
+ ScratchSpace()
+ : UnalignedPtr(llvm::make_unique<char[]>(kSize + kAlignment)),
+ AlignedPtr(
+ UnalignedPtr.get() + kAlignment -
+ (reinterpret_cast<intptr_t>(UnalignedPtr.get()) % kAlignment)) {}
+ char *ptr() const { return AlignedPtr; }
+ void clear() { std::memset(ptr(), 0, kSize); }
+
+ private:
+ const std::unique_ptr<char[]> UnalignedPtr;
+ char *const AlignedPtr;
+ };
+
protected:
const LLVMState &State;
const RegisterAliasingTrackerCache RATC;
@@ -84,7 +104,7 @@ private:
generatePrototype(unsigned Opcode) const = 0;
virtual std::vector<BenchmarkMeasure>
- runMeasurements(const ExecutableFunction &EF,
+ runMeasurements(const ExecutableFunction &EF, ScratchSpace &Scratch,
const unsigned NumRepetitions) const = 0;
// Internal helpers.
@@ -101,6 +121,8 @@ private:
llvm::ArrayRef<llvm::MCInst> Code) const;
const InstructionBenchmark::ModeE Mode;
+
+ const std::unique_ptr<ScratchSpace> Scratch;
};
} // namespace exegesis
Modified: llvm/trunk/tools/llvm-exegesis/lib/Latency.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/Latency.cpp?rev=338567&r1=338566&r2=338567&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/Latency.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/Latency.cpp Wed Aug 1 07:41:45 2018
@@ -108,6 +108,7 @@ const char *LatencyBenchmarkRunner::getC
std::vector<BenchmarkMeasure>
LatencyBenchmarkRunner::runMeasurements(const ExecutableFunction &Function,
+ ScratchSpace &Scratch,
const unsigned NumRepetitions) const {
// Cycle measurements include some overhead from the kernel. Repeat the
// measure several times and take the minimum value.
@@ -121,8 +122,9 @@ LatencyBenchmarkRunner::runMeasurements(
llvm::report_fatal_error("invalid perf event");
for (size_t I = 0; I < NumMeasurements; ++I) {
pfm::Counter Counter(CyclesPerfEvent);
+ Scratch.clear();
Counter.start();
- Function();
+ Function(Scratch.ptr());
Counter.stop();
const int64_t Value = Counter.read();
if (Value < MinLatency)
Modified: llvm/trunk/tools/llvm-exegesis/lib/Latency.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/Latency.h?rev=338567&r1=338566&r2=338567&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/Latency.h (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/Latency.h Wed Aug 1 07:41:45 2018
@@ -36,7 +36,7 @@ private:
const Instruction &Instr) const;
std::vector<BenchmarkMeasure>
- runMeasurements(const ExecutableFunction &EF,
+ runMeasurements(const ExecutableFunction &EF, ScratchSpace &Scratch,
const unsigned NumRepetitions) const override;
virtual const char *getCounterName() const;
Modified: llvm/trunk/tools/llvm-exegesis/lib/MCInstrDescView.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/MCInstrDescView.cpp?rev=338567&r1=338566&r2=338567&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/MCInstrDescView.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/MCInstrDescView.cpp Wed Aug 1 07:41:45 2018
@@ -26,6 +26,7 @@ Instruction::Instruction(const llvm::MCI
Operand Operand;
Operand.Index = OpIndex;
Operand.IsDef = (OpIndex < MCInstrDesc.getNumDefs());
+ Operand.IsMem = OpInfo.OperandType == llvm::MCOI::OPERAND_MEMORY;
Operand.IsExplicit = true;
// TODO(gchatelet): Handle isLookupPtrRegClass.
if (OpInfo.RegClass >= 0)
@@ -83,6 +84,11 @@ Instruction::Instruction(const llvm::MCI
}
}
+bool Instruction::hasMemoryOperands() const {
+ return std::any_of(Operands.begin(), Operands.end(),
+ [](const Operand &Op) { return Op.IsMem; });
+}
+
InstructionInstance::InstructionInstance(const Instruction &Instr)
: Instr(Instr), VariableValues(Instr.Variables.size()) {}
@@ -91,6 +97,11 @@ InstructionInstance::InstructionInstance
InstructionInstance &InstructionInstance::
operator=(InstructionInstance &&) = default;
+InstructionInstance::InstructionInstance(const InstructionInstance &) = default;
+
+InstructionInstance &InstructionInstance::
+operator=(const InstructionInstance &) = default;
+
unsigned InstructionInstance::getOpcode() const {
return Instr.Description->getOpcode();
}
@@ -117,7 +128,8 @@ InstructionInstance::getValueFor(const O
// forward declaration.
static void randomize(const Instruction &Instr, const Variable &Var,
- llvm::MCOperand &AssignedValue);
+ llvm::MCOperand &AssignedValue,
+ const llvm::BitVector &ForbiddenRegs);
bool InstructionInstance::hasImmediateVariables() const {
return llvm::any_of(Instr.Variables, [this](const Variable &Var) {
@@ -129,11 +141,12 @@ bool InstructionInstance::hasImmediateVa
});
}
-void InstructionInstance::randomizeUnsetVariables() {
+void InstructionInstance::randomizeUnsetVariables(
+ const llvm::BitVector &ForbiddenRegs) {
for (const Variable &Var : Instr.Variables) {
llvm::MCOperand &AssignedValue = getValueFor(Var);
if (!AssignedValue.isValid())
- randomize(Instr, Var, AssignedValue);
+ randomize(Instr, Var, AssignedValue, ForbiddenRegs);
}
}
@@ -222,7 +235,8 @@ static auto randomElement(const C &Conta
}
static void randomize(const Instruction &Instr, const Variable &Var,
- llvm::MCOperand &AssignedValue) {
+ llvm::MCOperand &AssignedValue,
+ const llvm::BitVector &ForbiddenRegs) {
assert(!Var.TiedOperands.empty());
const Operand &Op = Instr.Operands[Var.TiedOperands.front()];
assert(Op.Info != nullptr);
@@ -234,8 +248,11 @@ static void randomize(const Instruction
break;
case llvm::MCOI::OperandType::OPERAND_REGISTER: {
assert(Op.Tracker);
- const auto &Registers = Op.Tracker->sourceBits();
- AssignedValue = llvm::MCOperand::createReg(randomBit(Registers));
+ 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:
Modified: llvm/trunk/tools/llvm-exegesis/lib/MCInstrDescView.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/MCInstrDescView.h?rev=338567&r1=338566&r2=338567&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/MCInstrDescView.h (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/MCInstrDescView.h Wed Aug 1 07:41:45 2018
@@ -58,6 +58,7 @@ struct Variable {
struct Operand {
unsigned Index = 0;
bool IsDef = false;
+ bool IsMem = false;
bool IsExplicit = false;
const RegisterAliasingTracker *Tracker = nullptr; // Set for Register Op.
const llvm::MCOperandInfo *Info = nullptr; // Set for Explicit Op.
@@ -72,6 +73,8 @@ struct Instruction {
Instruction(const llvm::MCInstrDesc &MCInstrDesc,
const RegisterAliasingTrackerCache &ATC);
+ bool hasMemoryOperands() const;
+
const llvm::MCInstrDesc *Description; // Never nullptr.
llvm::SmallVector<Operand, 8> Operands;
llvm::SmallVector<Variable, 4> Variables;
@@ -83,11 +86,8 @@ struct Instruction {
struct InstructionInstance {
InstructionInstance(const Instruction &Instr);
- // No copy.
- InstructionInstance(const InstructionInstance &) = delete;
- InstructionInstance &operator=(const InstructionInstance &) = delete;
-
- // Moving is OK.
+ InstructionInstance(const InstructionInstance &);
+ InstructionInstance &operator=(const InstructionInstance &);
InstructionInstance(InstructionInstance &&);
InstructionInstance &operator=(InstructionInstance &&);
@@ -99,7 +99,8 @@ struct InstructionInstance {
bool hasImmediateVariables() const;
// Assigns a Random Value to all Variables that are still Invalid.
- void randomizeUnsetVariables();
+ // Do not use any of the registers in `ForbiddenRegs`.
+ void randomizeUnsetVariables(const llvm::BitVector &ForbiddenRegs);
// Returns the instance as an llvm::MCInst. The InstructionInstance must be
// fully allocated (no invalid variables).
@@ -125,6 +126,9 @@ struct SnippetPrototype {
SnippetPrototype &operator=(SnippetPrototype &&);
std::string Explanation;
+ // If the prototype uses the provided scratch memory, the register in which
+ // the pointer to this memory is passed in to the function.
+ unsigned ScratchSpaceReg = 0;
std::vector<InstructionInstance> Snippet;
};
Modified: llvm/trunk/tools/llvm-exegesis/lib/RegisterAliasing.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/RegisterAliasing.h?rev=338567&r1=338566&r2=338567&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/RegisterAliasing.h (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/RegisterAliasing.h Wed Aug 1 07:41:45 2018
@@ -62,6 +62,7 @@ struct RegisterAliasingTracker {
private:
RegisterAliasingTracker(const llvm::MCRegisterInfo &RegInfo);
+ RegisterAliasingTracker(const RegisterAliasingTracker &) = delete;
void FillOriginAndAliasedBits(const llvm::MCRegisterInfo &RegInfo,
const llvm::BitVector &OriginalBits);
Modified: llvm/trunk/tools/llvm-exegesis/lib/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/Target.cpp?rev=338567&r1=338566&r2=338567&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/Target.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/Target.cpp Wed Aug 1 07:41:45 2018
@@ -30,9 +30,8 @@ void ExegesisTarget::registerTarget(Exeg
FirstTarget = Target;
return;
}
- assert(Target->Next == nullptr && "target has already been registered");
if (Target->Next != nullptr)
- return;
+ return; // Already registered.
Target->Next = FirstTarget;
FirstTarget = Target;
}
Modified: llvm/trunk/tools/llvm-exegesis/lib/Target.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/Target.h?rev=338567&r1=338566&r2=338567&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/Target.h (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/Target.h Wed Aug 1 07:41:45 2018
@@ -22,6 +22,7 @@
#include "LlvmState.h"
#include "llvm/ADT/Triple.h"
#include "llvm/CodeGen/TargetPassConfig.h"
+#include "llvm/IR/CallingConv.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCRegisterInfo.h"
@@ -39,6 +40,27 @@ public:
return {};
}
+ // Returns the register pointing to scratch memory, or 0 if this target does
+ // not support memory operands. The benchmark function uses the default
+ // calling convention.
+ virtual unsigned getScratchMemoryRegister(const llvm::Triple &) const {
+ return 0;
+ }
+
+ // Fills memory operands with references to the address at [Reg] + Offset.
+ virtual void fillMemoryOperands(InstructionInstance &II, unsigned Reg,
+ unsigned Offset) const {
+ llvm_unreachable(
+ "fillMemoryOperands() requires getScratchMemoryRegister() > 0");
+ }
+
+ // Returns the maximum number of bytes a load/store instruction can access at
+ // once. This is typically the size of the largest register available on the
+ // processor. Note that this only used as a hint to generate independant
+ // load/stores to/from memory, so the exact returned value does not really
+ // matter as long as it's large enough.
+ virtual unsigned getMaxMemoryAccessSize() const { return 0; }
+
// Creates a benchmark runner for the given mode.
std::unique_ptr<BenchmarkRunner>
createBenchmarkRunner(InstructionBenchmark::ModeE Mode,
Modified: llvm/trunk/tools/llvm-exegesis/lib/Uops.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/Uops.cpp?rev=338567&r1=338566&r2=338567&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/Uops.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/Uops.cpp Wed Aug 1 07:41:45 2018
@@ -13,6 +13,7 @@
#include "BenchmarkRunner.h"
#include "MCInstrDescView.h"
#include "PerfHelper.h"
+#include "Target.h"
// FIXME: Load constants into registers (e.g. with fld1) to not break
// instructions like x87.
@@ -84,19 +85,11 @@ static bool hasUnknownOperand(const llvm
return OpInfo.OperandType == llvm::MCOI::OPERAND_UNKNOWN;
}
-// FIXME: Handle memory, see PR36905.
-static bool hasMemoryOperand(const llvm::MCOperandInfo &OpInfo) {
- return OpInfo.OperandType == llvm::MCOI::OPERAND_MEMORY;
-}
-
llvm::Error
UopsBenchmarkRunner::isInfeasible(const llvm::MCInstrDesc &MCInstrDesc) const {
if (llvm::any_of(MCInstrDesc.operands(), hasUnknownOperand))
return llvm::make_error<BenchmarkFailure>(
"Infeasible : has unknown operands");
- if (llvm::any_of(MCInstrDesc.operands(), hasMemoryOperand))
- return llvm::make_error<BenchmarkFailure>(
- "Infeasible : has memory operands");
return llvm::Error::success();
}
@@ -131,18 +124,70 @@ static void remove(llvm::BitVector &a, c
UopsBenchmarkRunner::~UopsBenchmarkRunner() = default;
+void UopsBenchmarkRunner::instantiateMemoryOperands(
+ const unsigned ScratchSpaceReg,
+ std::vector<InstructionInstance> &Snippet) const {
+ if (ScratchSpaceReg == 0)
+ return; // no memory operands.
+ const auto &ET = State.getExegesisTarget();
+ const unsigned MemStep = ET.getMaxMemoryAccessSize();
+ const size_t OriginalSnippetSize = Snippet.size();
+ size_t I = 0;
+ for (InstructionInstance &II : Snippet) {
+ ET.fillMemoryOperands(II, ScratchSpaceReg, I * MemStep);
+ ++I;
+ }
+
+ while (Snippet.size() < kMinNumDifferentAddresses) {
+ InstructionInstance II = Snippet[I % OriginalSnippetSize];
+ ET.fillMemoryOperands(II, ScratchSpaceReg, I * MemStep);
+ ++I;
+ Snippet.push_back(std::move(II));
+ }
+ assert(I * MemStep < ScratchSpace::kSize && "not enough scratch space");
+}
+
llvm::Expected<SnippetPrototype>
UopsBenchmarkRunner::generatePrototype(unsigned Opcode) const {
const auto &InstrDesc = State.getInstrInfo().get(Opcode);
if (auto E = isInfeasible(InstrDesc))
return std::move(E);
const Instruction Instr(InstrDesc, RATC);
+ const auto &ET = State.getExegesisTarget();
+ SnippetPrototype Prototype;
+
+ const llvm::BitVector *ScratchSpaceAliasedRegs = nullptr;
+ if (Instr.hasMemoryOperands()) {
+ Prototype.ScratchSpaceReg =
+ ET.getScratchMemoryRegister(State.getTargetMachine().getTargetTriple());
+ if (Prototype.ScratchSpaceReg == 0)
+ return llvm::make_error<BenchmarkFailure>(
+ "Infeasible : target does not support memory instructions");
+ ScratchSpaceAliasedRegs =
+ &RATC.getRegister(Prototype.ScratchSpaceReg).aliasedBits();
+ // If the instruction implicitly writes to ScratchSpaceReg , abort.
+ // FIXME: We could make a copy of the scratch register.
+ for (const auto &Op : Instr.Operands) {
+ if (Op.IsDef && Op.ImplicitReg &&
+ ScratchSpaceAliasedRegs->test(*Op.ImplicitReg))
+ return llvm::make_error<BenchmarkFailure>(
+ "Infeasible : memory instruction uses scratch memory register");
+ }
+ }
+
const AliasingConfigurations SelfAliasing(Instr, Instr);
+ InstructionInstance II(Instr);
if (SelfAliasing.empty()) {
- return generateUnconstrainedPrototype(Instr, "instruction is parallel");
+ Prototype.Explanation = "instruction is parallel, repeating a random one.";
+ Prototype.Snippet.push_back(std::move(II));
+ instantiateMemoryOperands(Prototype.ScratchSpaceReg, Prototype.Snippet);
+ return std::move(Prototype);
}
if (SelfAliasing.hasImplicitAliasing()) {
- return generateUnconstrainedPrototype(Instr, "instruction is serial");
+ Prototype.Explanation = "instruction is serial, repeating a random one.";
+ Prototype.Snippet.push_back(std::move(II));
+ instantiateMemoryOperands(Prototype.ScratchSpaceReg, Prototype.Snippet);
+ return std::move(Prototype);
}
const auto TiedVariables = getTiedVariables(Instr);
if (!TiedVariables.empty()) {
@@ -155,23 +200,27 @@ UopsBenchmarkRunner::generatePrototype(u
assert(!Var->TiedOperands.empty());
const Operand &Op = Instr.Operands[Var->TiedOperands.front()];
assert(Op.Tracker);
- SnippetPrototype Prototype;
Prototype.Explanation =
"instruction has tied variables using static renaming.";
for (const llvm::MCPhysReg Reg : Op.Tracker->sourceBits().set_bits()) {
- Prototype.Snippet.emplace_back(Instr);
- Prototype.Snippet.back().getValueFor(*Var) =
- llvm::MCOperand::createReg(Reg);
+ if (ScratchSpaceAliasedRegs && ScratchSpaceAliasedRegs->test(Reg))
+ continue; // Do not use the scratch memory address register.
+ InstructionInstance TmpII = II;
+ TmpII.getValueFor(*Var) = llvm::MCOperand::createReg(Reg);
+ Prototype.Snippet.push_back(std::move(TmpII));
}
+ instantiateMemoryOperands(Prototype.ScratchSpaceReg, Prototype.Snippet);
return std::move(Prototype);
}
- InstructionInstance II(Instr);
// No tied variables, we pick random values for defs.
llvm::BitVector Defs(State.getRegInfo().getNumRegs());
for (const auto &Op : Instr.Operands) {
- if (Op.Tracker && Op.IsExplicit && Op.IsDef) {
+ if (Op.Tracker && Op.IsExplicit && Op.IsDef && !Op.IsMem) {
auto PossibleRegisters = Op.Tracker->sourceBits();
remove(PossibleRegisters, RATC.reservedRegisters());
+ // Do not use the scratch memory address register.
+ if (ScratchSpaceAliasedRegs)
+ remove(PossibleRegisters, *ScratchSpaceAliasedRegs);
assert(PossibleRegisters.any() && "No register left to choose from");
const auto RandomReg = randomBit(PossibleRegisters);
Defs.set(RandomReg);
@@ -181,24 +230,28 @@ UopsBenchmarkRunner::generatePrototype(u
// And pick random use values that are not reserved and don't alias with defs.
const auto DefAliases = getAliasedBits(State.getRegInfo(), Defs);
for (const auto &Op : Instr.Operands) {
- if (Op.Tracker && Op.IsExplicit && !Op.IsDef) {
+ if (Op.Tracker && Op.IsExplicit && !Op.IsDef && !Op.IsMem) {
auto PossibleRegisters = Op.Tracker->sourceBits();
remove(PossibleRegisters, RATC.reservedRegisters());
+ // Do not use the scratch memory address register.
+ if (ScratchSpaceAliasedRegs)
+ remove(PossibleRegisters, *ScratchSpaceAliasedRegs);
remove(PossibleRegisters, DefAliases);
assert(PossibleRegisters.any() && "No register left to choose from");
const auto RandomReg = randomBit(PossibleRegisters);
II.getValueFor(Op) = llvm::MCOperand::createReg(RandomReg);
}
}
- SnippetPrototype Prototype;
Prototype.Explanation =
"instruction has no tied variables picking Uses different from defs";
Prototype.Snippet.push_back(std::move(II));
+ instantiateMemoryOperands(Prototype.ScratchSpaceReg, Prototype.Snippet);
return std::move(Prototype);
}
std::vector<BenchmarkMeasure>
UopsBenchmarkRunner::runMeasurements(const ExecutableFunction &Function,
+ ScratchSpace &Scratch,
const unsigned NumRepetitions) const {
const auto &SchedModel = State.getSubtargetInfo().getSchedModel();
@@ -220,8 +273,9 @@ UopsBenchmarkRunner::runMeasurements(con
llvm::report_fatal_error(
llvm::Twine("invalid perf event ").concat(PfmCounters));
pfm::Counter Counter(UopPerfEvent);
+ Scratch.clear();
Counter.start();
- Function();
+ Function(Scratch.ptr());
Counter.stop();
CounterValue += Counter.read();
}
@@ -232,4 +286,6 @@ UopsBenchmarkRunner::runMeasurements(con
return Result;
}
+constexpr const size_t UopsBenchmarkRunner::kMinNumDifferentAddresses;
+
} // namespace exegesis
Modified: llvm/trunk/tools/llvm-exegesis/lib/Uops.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/Uops.h?rev=338567&r1=338566&r2=338567&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/Uops.h (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/Uops.h Wed Aug 1 07:41:45 2018
@@ -28,12 +28,41 @@ public:
llvm::Expected<SnippetPrototype>
generatePrototype(unsigned Opcode) const override;
+ static constexpr const size_t kMinNumDifferentAddresses = 6;
+
private:
llvm::Error isInfeasible(const llvm::MCInstrDesc &MCInstrDesc) const;
std::vector<BenchmarkMeasure>
- runMeasurements(const ExecutableFunction &EF,
+ runMeasurements(const ExecutableFunction &EF, ScratchSpace &Scratch,
const unsigned NumRepetitions) const override;
+
+ // Instantiates memory operands within a snippet.
+ // To make computations as parallel as possible, we generate independant
+ // memory locations for instructions that load and store. If there are less
+ // than kMinNumDifferentAddresses in the original snippet, we duplicate
+ // instructions until there are this number of instructions.
+ // For example, assuming kMinNumDifferentAddresses=5 and
+ // getMaxMemoryAccessSize()=64, if the original snippet is:
+ // mov eax, [memory]
+ // we might generate:
+ // mov eax, [rdi]
+ // mov eax, [rdi + 64]
+ // mov eax, [rdi + 128]
+ // mov eax, [rdi + 192]
+ // mov eax, [rdi + 256]
+ // If the original snippet is:
+ // mov eax, [memory]
+ // add eax, [memory]
+ // we might generate:
+ // mov eax, [rdi]
+ // add eax, [rdi + 64]
+ // mov eax, [rdi + 128]
+ // add eax, [rdi + 192]
+ // mov eax, [rdi + 256]
+ void
+ instantiateMemoryOperands(unsigned ScratchSpaceReg,
+ std::vector<InstructionInstance> &Snippet) const;
};
} // namespace exegesis
Modified: llvm/trunk/tools/llvm-exegesis/lib/X86/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/X86/Target.cpp?rev=338567&r1=338566&r2=338567&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/X86/Target.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/X86/Target.cpp Wed Aug 1 07:41:45 2018
@@ -109,6 +109,48 @@ class ExegesisX86Target : public Exegesi
PM.add(llvm::createX86FloatingPointStackifierPass());
}
+ unsigned getScratchMemoryRegister(const llvm::Triple &TT) const override {
+ if (!TT.isArch64Bit()) {
+ // FIXME: This would require popping from the stack, so we would have to
+ // add some additional setup code.
+ return 0;
+ }
+ return TT.isOSWindows() ? llvm::X86::RCX : llvm::X86::RDI;
+ }
+
+ unsigned getMaxMemoryAccessSize() const override { return 64; }
+
+ void fillMemoryOperands(InstructionInstance &II, unsigned Reg,
+ unsigned Offset) const override {
+ // FIXME: For instructions that read AND write to memory, we use the same
+ // value for input and output.
+ for (size_t I = 0, E = II.Instr.Operands.size(); I < E; ++I) {
+ const Operand *Op = &II.Instr.Operands[I];
+ if (Op->IsExplicit && Op->IsMem) {
+ // Case 1: 5-op memory.
+ assert((I + 5 <= E) && "x86 memory references are always 5 ops");
+ II.getValueFor(*Op) = llvm::MCOperand::createReg(Reg); // BaseReg
+ Op = &II.Instr.Operands[++I];
+ assert(Op->IsMem);
+ assert(Op->IsExplicit);
+ II.getValueFor(*Op) = llvm::MCOperand::createImm(1); // ScaleAmt
+ Op = &II.Instr.Operands[++I];
+ assert(Op->IsMem);
+ assert(Op->IsExplicit);
+ II.getValueFor(*Op) = llvm::MCOperand::createReg(0); // IndexReg
+ Op = &II.Instr.Operands[++I];
+ assert(Op->IsMem);
+ assert(Op->IsExplicit);
+ II.getValueFor(*Op) = llvm::MCOperand::createImm(Offset); // Disp
+ Op = &II.Instr.Operands[++I];
+ assert(Op->IsMem);
+ assert(Op->IsExplicit);
+ II.getValueFor(*Op) = llvm::MCOperand::createReg(0); // Segment
+ // Case2: segment:index addressing. We assume that ES is 0.
+ }
+ }
+ }
+
std::vector<llvm::MCInst> setRegToConstant(const llvm::MCSubtargetInfo &STI,
unsigned Reg) const override {
// GPR.
Modified: llvm/trunk/unittests/tools/llvm-exegesis/ARM/AssemblerTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/tools/llvm-exegesis/ARM/AssemblerTest.cpp?rev=338567&r1=338566&r2=338567&view=diff
==============================================================================
--- llvm/trunk/unittests/tools/llvm-exegesis/ARM/AssemblerTest.cpp (original)
+++ llvm/trunk/unittests/tools/llvm-exegesis/ARM/AssemblerTest.cpp Wed Aug 1 07:41:45 2018
@@ -30,11 +30,13 @@ protected:
};
TEST_F(ARMMachineFunctionGeneratorTest, DISABLED_JitFunction) {
- Check(llvm::MCInst(), 0x1e, 0xff, 0x2f, 0xe1);
+ Check(ExegesisTarget::getDefault(), {}, llvm::MCInst(), 0x1e, 0xff, 0x2f,
+ 0xe1);
}
TEST_F(ARMMachineFunctionGeneratorTest, DISABLED_JitFunctionADDrr) {
- Check(MCInstBuilder(llvm::ARM::ADDrr)
+ Check(ExegesisTarget::getDefault(), {llvm::ARM::R0},
+ MCInstBuilder(llvm::ARM::ADDrr)
.addReg(llvm::ARM::R0)
.addReg(llvm::ARM::R0)
.addReg(llvm::ARM::R0)
Added: llvm/trunk/unittests/tools/llvm-exegesis/BenchmarkRunnerTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/tools/llvm-exegesis/BenchmarkRunnerTest.cpp?rev=338567&view=auto
==============================================================================
--- llvm/trunk/unittests/tools/llvm-exegesis/BenchmarkRunnerTest.cpp (added)
+++ llvm/trunk/unittests/tools/llvm-exegesis/BenchmarkRunnerTest.cpp Wed Aug 1 07:41:45 2018
@@ -0,0 +1,31 @@
+//===-- BenchmarkRunnerTest.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "BenchmarkRunner.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+
+namespace exegesis {
+
+namespace {
+
+TEST(ScratchSpaceTest, Works) {
+ BenchmarkRunner::ScratchSpace Space;
+ EXPECT_EQ(reinterpret_cast<intptr_t>(Space.ptr()) %
+ BenchmarkRunner::ScratchSpace::kAlignment,
+ 0u);
+ Space.ptr()[0] = 42;
+ Space.ptr()[BenchmarkRunner::ScratchSpace::kSize - 1] = 43;
+ Space.clear();
+ EXPECT_EQ(Space.ptr()[0], 0);
+ EXPECT_EQ(Space.ptr()[BenchmarkRunner::ScratchSpace::kSize - 1], 0);
+}
+
+} // namespace
+} // namespace exegesis
Modified: llvm/trunk/unittests/tools/llvm-exegesis/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/tools/llvm-exegesis/CMakeLists.txt?rev=338567&r1=338566&r2=338567&view=diff
==============================================================================
--- llvm/trunk/unittests/tools/llvm-exegesis/CMakeLists.txt (original)
+++ llvm/trunk/unittests/tools/llvm-exegesis/CMakeLists.txt Wed Aug 1 07:41:45 2018
@@ -12,6 +12,7 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(LLVMExegesisTests
BenchmarkResultTest.cpp
+ BenchmarkRunnerTest.cpp
ClusteringTest.cpp
PerfHelperTest.cpp
)
Modified: llvm/trunk/unittests/tools/llvm-exegesis/Common/AssemblerUtils.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/tools/llvm-exegesis/Common/AssemblerUtils.h?rev=338567&r1=338566&r2=338567&view=diff
==============================================================================
--- llvm/trunk/unittests/tools/llvm-exegesis/Common/AssemblerUtils.h (original)
+++ llvm/trunk/unittests/tools/llvm-exegesis/Common/AssemblerUtils.h Wed Aug 1 07:41:45 2018
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "Assembler.h"
+#include "BenchmarkRunner.h"
#include "Target.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
@@ -36,21 +37,19 @@ protected:
}
}
- template <class... Bs> inline void Check(llvm::MCInst MCInst, Bs... Bytes) {
- CheckWithSetup(ExegesisTarget::getDefault(), {}, MCInst, Bytes...);
- }
-
template <class... Bs>
- inline void CheckWithSetup(const ExegesisTarget &ET,
- llvm::ArrayRef<unsigned> RegsToDef,
- llvm::MCInst MCInst, Bs... Bytes) {
+ inline void Check(const ExegesisTarget &ET,
+ llvm::ArrayRef<unsigned> RegsToDef, llvm::MCInst MCInst,
+ Bs... Bytes) {
ExecutableFunction Function =
(MCInst.getOpcode() == 0) ? assembleToFunction(ET, RegsToDef, {})
: assembleToFunction(ET, RegsToDef, {MCInst});
ASSERT_THAT(Function.getFunctionBytes().str(),
testing::ElementsAre(Bytes...));
- if (CanExecute)
- Function();
+ if (CanExecute) {
+ BenchmarkRunner::ScratchSpace Scratch;
+ Function(Scratch.ptr());
+ }
}
private:
@@ -73,7 +72,8 @@ private:
llvm::ArrayRef<llvm::MCInst> Instructions) {
llvm::SmallString<256> Buffer;
llvm::raw_svector_ostream AsmStream(Buffer);
- assembleToStream(ET, createTargetMachine(), RegsToDef, Instructions,
+ assembleToStream(ET, createTargetMachine(), /*LiveIns=*/{},
+ RegsToDef, Instructions,
AsmStream);
return ExecutableFunction(createTargetMachine(),
getObjectFromBuffer(AsmStream.str()));
Modified: llvm/trunk/unittests/tools/llvm-exegesis/X86/AssemblerTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/tools/llvm-exegesis/X86/AssemblerTest.cpp?rev=338567&r1=338566&r2=338567&view=diff
==============================================================================
--- llvm/trunk/unittests/tools/llvm-exegesis/X86/AssemblerTest.cpp (original)
+++ llvm/trunk/unittests/tools/llvm-exegesis/X86/AssemblerTest.cpp Wed Aug 1 07:41:45 2018
@@ -11,6 +11,9 @@
#include "X86InstrInfo.h"
namespace exegesis {
+
+void InitializeX86ExegesisTarget();
+
namespace {
using llvm::MCInstBuilder;
@@ -31,25 +34,39 @@ protected:
LLVMInitializeX86TargetMC();
LLVMInitializeX86Target();
LLVMInitializeX86AsmPrinter();
+ InitializeX86ExegesisTarget();
}
};
TEST_F(X86MachineFunctionGeneratorTest, DISABLED_JitFunction) {
- Check(llvm::MCInst(), 0xc3);
+ Check(ExegesisTarget::getDefault(), {}, llvm::MCInst(), 0xc3);
}
-TEST_F(X86MachineFunctionGeneratorTest, DISABLED_JitFunctionXOR32rr) {
- Check(MCInstBuilder(XOR32rr).addReg(EAX).addReg(EAX).addReg(EAX), 0x31, 0xc0,
+TEST_F(X86MachineFunctionGeneratorTest, DISABLED_JitFunctionXOR32rr_Default) {
+ Check(ExegesisTarget::getDefault(), {EAX},
+ MCInstBuilder(XOR32rr).addReg(EAX).addReg(EAX).addReg(EAX), 0x31, 0xc0,
0xc3);
}
+TEST_F(X86MachineFunctionGeneratorTest, DISABLED_JitFunctionXOR32rr_X86) {
+ const auto *ET = ExegesisTarget::lookup(llvm::Triple("x86_64-unknown-linux"));
+ ASSERT_NE(ET, nullptr);
+ Check(*ET, {EAX}, MCInstBuilder(XOR32rr).addReg(EAX).addReg(EAX).addReg(EAX),
+ // mov eax, 1
+ 0xb8, 0x01, 0x00, 0x00, 0x00,
+ // xor eax, eax
+ 0x31, 0xc0, 0xc3);
+}
+
TEST_F(X86MachineFunctionGeneratorTest, DISABLED_JitFunctionMOV64ri) {
- Check(MCInstBuilder(MOV64ri32).addReg(RAX).addImm(42), 0x48, 0xc7, 0xc0, 0x2a,
+ Check(ExegesisTarget::getDefault(), {},
+ MCInstBuilder(MOV64ri32).addReg(RAX).addImm(42), 0x48, 0xc7, 0xc0, 0x2a,
0x00, 0x00, 0x00, 0xc3);
}
TEST_F(X86MachineFunctionGeneratorTest, DISABLED_JitFunctionMOV32ri) {
- Check(MCInstBuilder(MOV32ri).addReg(EAX).addImm(42), 0xb8, 0x2a, 0x00, 0x00,
+ Check(ExegesisTarget::getDefault(), {},
+ MCInstBuilder(MOV32ri).addReg(EAX).addImm(42), 0xb8, 0x2a, 0x00, 0x00,
0x00, 0xc3);
}
Modified: llvm/trunk/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp?rev=338567&r1=338566&r2=338567&view=diff
==============================================================================
--- llvm/trunk/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp (original)
+++ llvm/trunk/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp Wed Aug 1 07:41:45 2018
@@ -18,6 +18,9 @@
#include <unordered_set>
namespace exegesis {
+
+void InitializeX86ExegesisTarget();
+
namespace {
using testing::AnyOf;
@@ -41,6 +44,7 @@ protected:
LLVMInitializeX86TargetMC();
LLVMInitializeX86Target();
LLVMInitializeX86AsmPrinter();
+ InitializeX86ExegesisTarget();
}
const LLVMState State;
@@ -215,6 +219,30 @@ TEST_F(UopsSnippetGeneratorTest, NoTiedV
EXPECT_THAT(II.VariableValues[3], IsInvalid());
}
+TEST_F(UopsSnippetGeneratorTest, MemoryUse) {
+ // Mov32rm reads from memory.
+ const unsigned Opcode = llvm::X86::MOV32rm;
+ const SnippetPrototype Proto = checkAndGetConfigurations(Opcode);
+ EXPECT_THAT(Proto.Explanation, HasSubstr("no tied variables"));
+ ASSERT_THAT(Proto.Snippet,
+ SizeIs(UopsBenchmarkRunner::kMinNumDifferentAddresses));
+ const InstructionInstance &II = Proto.Snippet[0];
+ EXPECT_THAT(II.getOpcode(), Opcode);
+ ASSERT_THAT(II.VariableValues, SizeIs(6));
+ EXPECT_EQ(II.VariableValues[2].getImm(), 1);
+ EXPECT_EQ(II.VariableValues[3].getReg(), 0u);
+ EXPECT_EQ(II.VariableValues[4].getImm(), 0);
+ EXPECT_EQ(II.VariableValues[5].getReg(), 0u);
+}
+
+TEST_F(UopsSnippetGeneratorTest, MemoryUse_Movsb) {
+ // MOVSB writes to scratch memory register.
+ const unsigned Opcode = llvm::X86::MOVSB;
+ auto Error = Runner.generatePrototype(Opcode).takeError();
+ EXPECT_TRUE((bool)Error);
+ llvm::consumeError(std::move(Error));
+}
+
class FakeBenchmarkRunner : public BenchmarkRunner {
public:
FakeBenchmarkRunner(const LLVMState &State)
@@ -232,7 +260,7 @@ private:
}
std::vector<BenchmarkMeasure>
- runMeasurements(const ExecutableFunction &EF,
+ runMeasurements(const ExecutableFunction &EF, ScratchSpace &Scratch,
const unsigned NumRepetitions) const override {
return {};
}
More information about the llvm-commits
mailing list