summaryrefslogtreecommitdiffstats
path: root/llvm/tools
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools')
-rw-r--r--llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp50
-rw-r--r--llvm/tools/llvm-exegesis/lib/Assembler.cpp35
-rw-r--r--llvm/tools/llvm-exegesis/lib/Assembler.h8
-rw-r--r--llvm/tools/llvm-exegesis/lib/BenchmarkCode.h2
-rw-r--r--llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp2
-rw-r--r--llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp10
-rw-r--r--llvm/tools/llvm-exegesis/lib/SnippetGenerator.h4
-rw-r--r--llvm/tools/llvm-exegesis/lib/Target.cpp22
-rw-r--r--llvm/tools/llvm-exegesis/lib/Target.h21
-rw-r--r--llvm/tools/llvm-exegesis/lib/X86/Target.cpp154
10 files changed, 151 insertions, 157 deletions
diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index a65713b9f42..90c5927ad29 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -9,6 +9,7 @@
#include "../Target.h"
#include "../Latency.h"
#include "AArch64.h"
+#include "AArch64RegisterInfo.h"
namespace exegesis {
@@ -26,38 +27,51 @@ private:
}
};
-class ExegesisAArch64Target : public ExegesisTarget {
- std::vector<llvm::MCInst> setRegToConstant(const llvm::MCSubtargetInfo &STI,
- unsigned Reg) const override {
- llvm_unreachable("Not yet implemented");
- }
+namespace {
- std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI,
- const llvm::APInt &Value,
- unsigned Reg) const override {
- llvm_unreachable("Not yet implemented");
+static unsigned getLoadImmediateOpcode(unsigned RegBitWidth) {
+ switch (RegBitWidth) {
+ case 32:
+ return llvm::AArch64::MOVi32imm;
+ case 64:
+ return llvm::AArch64::MOVi64imm;
}
+ llvm_unreachable("Invalid Value Width");
+}
- unsigned getScratchMemoryRegister(const llvm::Triple &) const override {
- llvm_unreachable("Not yet implemented");
- }
+// Generates instruction to load an immediate value into a register.
+static llvm::MCInst loadImmediate(unsigned Reg, unsigned RegBitWidth,
+ const llvm::APInt &Value) {
+ if (Value.getBitWidth() > RegBitWidth)
+ llvm_unreachable("Value must fit in the Register");
+ return llvm::MCInstBuilder(getLoadImmediateOpcode(RegBitWidth))
+ .addReg(Reg)
+ .addImm(Value.getZExtValue());
+}
- void fillMemoryOperands(InstructionBuilder &IB, unsigned Reg,
- unsigned Offset) const override {
- llvm_unreachable("Not yet implemented");
- }
+} // namespace
- unsigned getMaxMemoryAccessSize() const override {
- llvm_unreachable("Not yet implemented");
+class ExegesisAArch64Target : public ExegesisTarget {
+ std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI,
+ unsigned Reg,
+ const llvm::APInt &Value) const override {
+ if (llvm::AArch64::GPR32RegClass.contains(Reg))
+ return {loadImmediate(Reg, 32, Value)};
+ if (llvm::AArch64::GPR64RegClass.contains(Reg))
+ return {loadImmediate(Reg, 64, Value)};
+ llvm::errs() << "setRegTo is not implemented, results will be unreliable\n";
+ return {};
}
bool matchesArch(llvm::Triple::ArchType Arch) const override {
return Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be;
}
+
void addTargetSpecificPasses(llvm::PassManagerBase &PM) const override {
// Function return is a pseudo-instruction that needs to be expanded
PM.add(llvm::createAArch64ExpandPseudoPass());
}
+
std::unique_ptr<BenchmarkRunner>
createLatencyBenchmarkRunner(const LLVMState &State) const override {
return llvm::make_unique<AArch64LatencyBenchmarkRunner>(State);
diff --git a/llvm/tools/llvm-exegesis/lib/Assembler.cpp b/llvm/tools/llvm-exegesis/lib/Assembler.cpp
index 3b8b1d6bf38..cb6e9e13e65 100644
--- a/llvm/tools/llvm-exegesis/lib/Assembler.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Assembler.cpp
@@ -29,17 +29,17 @@ static constexpr const char ModuleID[] = "ExegesisInfoTest";
static constexpr const char FunctionID[] = "foo";
static std::vector<llvm::MCInst>
-generateSnippetSetupCode(const llvm::ArrayRef<unsigned> RegsToDef,
- const ExegesisTarget &ET,
- const llvm::LLVMTargetMachine &TM, bool &IsComplete) {
- IsComplete = true;
+generateSnippetSetupCode(const ExegesisTarget &ET,
+ const llvm::MCSubtargetInfo *const MSI,
+ llvm::ArrayRef<RegisterValue> RegisterInitialValues,
+ bool &IsSnippetSetupComplete) {
std::vector<llvm::MCInst> Result;
- for (const unsigned Reg : RegsToDef) {
+ for (const RegisterValue &RV : RegisterInitialValues) {
// Load a constant in the register.
- const auto Code = ET.setRegToConstant(*TM.getMCSubtargetInfo(), Reg);
- if (Code.empty())
- IsComplete = false;
- Result.insert(Result.end(), Code.begin(), Code.end());
+ const auto SetRegisterCode = ET.setRegTo(*MSI, RV.Register, RV.Value);
+ if (SetRegisterCode.empty())
+ IsSnippetSetupComplete = false;
+ Result.insert(Result.end(), SetRegisterCode.begin(), SetRegisterCode.end());
}
return Result;
}
@@ -149,7 +149,7 @@ llvm::BitVector getFunctionReservedRegs(const llvm::TargetMachine &TM) {
void assembleToStream(const ExegesisTarget &ET,
std::unique_ptr<llvm::LLVMTargetMachine> TM,
llvm::ArrayRef<unsigned> LiveIns,
- llvm::ArrayRef<unsigned> RegsToDef,
+ llvm::ArrayRef<RegisterValue> RegisterInitialValues,
llvm::ArrayRef<llvm::MCInst> Instructions,
llvm::raw_pwrite_stream &AsmStream) {
std::unique_ptr<llvm::LLVMContext> Context =
@@ -171,13 +171,12 @@ void assembleToStream(const ExegesisTarget &ET,
MF.getRegInfo().addLiveIn(Reg);
bool IsSnippetSetupComplete = false;
- std::vector<llvm::MCInst> SnippetWithSetup =
- generateSnippetSetupCode(RegsToDef, ET, *TM, IsSnippetSetupComplete);
- if (!SnippetWithSetup.empty()) {
- SnippetWithSetup.insert(SnippetWithSetup.end(), Instructions.begin(),
- Instructions.end());
- Instructions = SnippetWithSetup;
- }
+ std::vector<llvm::MCInst> Code =
+ generateSnippetSetupCode(ET, TM->getMCSubtargetInfo(),
+ RegisterInitialValues, IsSnippetSetupComplete);
+
+ Code.insert(Code.end(), Instructions.begin(), Instructions.end());
+
// If the snippet setup is not complete, we disable liveliness tracking. This
// means that we won't know what values are in the registers.
if (!IsSnippetSetupComplete)
@@ -188,7 +187,7 @@ void assembleToStream(const ExegesisTarget &ET,
MF.getRegInfo().freezeReservedRegs(MF);
// Fill the MachineFunction from the instructions.
- fillMachineFunction(MF, LiveIns, Instructions);
+ fillMachineFunction(MF, LiveIns, Code);
// We create the pass manager, run the passes to populate AsmBuffer.
llvm::MCContext &MCContext = MMI->getContext();
diff --git a/llvm/tools/llvm-exegesis/lib/Assembler.h b/llvm/tools/llvm-exegesis/lib/Assembler.h
index d5b542bc1bb..76030ae8f00 100644
--- a/llvm/tools/llvm-exegesis/lib/Assembler.h
+++ b/llvm/tools/llvm-exegesis/lib/Assembler.h
@@ -39,6 +39,12 @@ class ExegesisTarget;
// convention and target machine).
llvm::BitVector getFunctionReservedRegs(const llvm::TargetMachine &TM);
+// A simple object storing the value for a particular register.
+struct RegisterValue {
+ unsigned Register;
+ llvm::APInt Value;
+};
+
// 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
@@ -46,7 +52,7 @@ llvm::BitVector getFunctionReservedRegs(const llvm::TargetMachine &TM);
void assembleToStream(const ExegesisTarget &ET,
std::unique_ptr<llvm::LLVMTargetMachine> TM,
llvm::ArrayRef<unsigned> LiveIns,
- llvm::ArrayRef<unsigned> RegsToDef,
+ llvm::ArrayRef<RegisterValue> RegisterInitialValues,
llvm::ArrayRef<llvm::MCInst> Instructions,
llvm::raw_pwrite_stream &AsmStream);
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkCode.h b/llvm/tools/llvm-exegesis/lib/BenchmarkCode.h
index 1195adf45f3..03708683106 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkCode.h
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkCode.h
@@ -23,7 +23,7 @@ struct BenchmarkCode {
// Before the code is executed some instructions are added to setup the
// registers initial values.
- std::vector<unsigned> RegsToDef;
+ std::vector<RegisterValue> RegisterInitialValues;
// We also need to provide the registers that are live on entry for the
// assembler to generate proper prologue/epilogue.
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index 2d82f594553..6c22d1c0cec 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -104,7 +104,7 @@ BenchmarkRunner::writeObjectFile(const BenchmarkCode &BC,
return std::move(E);
llvm::raw_fd_ostream OFS(ResultFD, true /*ShouldClose*/);
assembleToStream(State.getExegesisTarget(), State.createTargetMachine(),
- BC.LiveIns, BC.RegsToDef, Code, OFS);
+ BC.LiveIns, BC.RegisterInitialValues, Code, OFS);
return ResultPath.str();
}
diff --git a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp
index 5b51a09923a..cb58b2dfc4b 100644
--- a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp
+++ b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp
@@ -49,7 +49,7 @@ SnippetGenerator::generateConfigurations(unsigned Opcode) const {
}
if (CT.ScratchSpacePointerInReg)
BC.LiveIns.push_back(CT.ScratchSpacePointerInReg);
- BC.RegsToDef = computeRegsToDef(CT.Instructions);
+ BC.RegisterInitialValues = computeRegisterInitialValues(CT.Instructions);
Output.push_back(std::move(BC));
}
return Output;
@@ -57,14 +57,14 @@ SnippetGenerator::generateConfigurations(unsigned Opcode) const {
return E.takeError();
}
-std::vector<unsigned> SnippetGenerator::computeRegsToDef(
+std::vector<RegisterValue> SnippetGenerator::computeRegisterInitialValues(
const std::vector<InstructionBuilder> &Instructions) 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();
- std::vector<unsigned> RegsToDef;
+ std::vector<RegisterValue> RIV;
for (const InstructionBuilder &IB : Instructions) {
// Returns the register that this Operand sets or uses, or 0 if this is not
// a register.
@@ -82,7 +82,7 @@ std::vector<unsigned> SnippetGenerator::computeRegsToDef(
if (!Op.IsDef) {
const unsigned Reg = GetOpReg(Op);
if (Reg > 0 && !DefinedRegs.test(Reg)) {
- RegsToDef.push_back(Reg);
+ RIV.push_back(RegisterValue{Reg, llvm::APInt()});
DefinedRegs.set(Reg);
}
}
@@ -96,7 +96,7 @@ std::vector<unsigned> SnippetGenerator::computeRegsToDef(
}
}
}
- return RegsToDef;
+ return RIV;
}
llvm::Expected<CodeTemplate> SnippetGenerator::generateSelfAliasingCodeTemplate(
diff --git a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.h b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.h
index ced8ebc5a28..2a412ba95e6 100644
--- a/llvm/tools/llvm-exegesis/lib/SnippetGenerator.h
+++ b/llvm/tools/llvm-exegesis/lib/SnippetGenerator.h
@@ -48,8 +48,8 @@ public:
generateConfigurations(unsigned Opcode) const;
// Given a snippet, computes which registers the setup code needs to define.
- std::vector<unsigned>
- computeRegsToDef(const std::vector<InstructionBuilder> &Snippet) const;
+ std::vector<RegisterValue> computeRegisterInitialValues(
+ const std::vector<InstructionBuilder> &Snippet) const;
protected:
const LLVMState &State;
diff --git a/llvm/tools/llvm-exegesis/lib/Target.cpp b/llvm/tools/llvm-exegesis/lib/Target.cpp
index b45c821823f..8baa8499c92 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Target.cpp
@@ -89,27 +89,9 @@ namespace {
// Default implementation.
class ExegesisDefaultTarget : public ExegesisTarget {
private:
- std::vector<llvm::MCInst> setRegToConstant(const llvm::MCSubtargetInfo &STI,
- unsigned Reg) const override {
- llvm_unreachable("Not yet implemented");
- }
-
std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI,
- const llvm::APInt &Value,
- unsigned Reg) const override {
- llvm_unreachable("Not yet implemented");
- }
-
- unsigned getScratchMemoryRegister(const llvm::Triple &) const override {
- llvm_unreachable("Not yet implemented");
- }
-
- void fillMemoryOperands(InstructionBuilder &IB, unsigned Reg,
- unsigned Offset) const override {
- llvm_unreachable("Not yet implemented");
- }
-
- unsigned getMaxMemoryAccessSize() const override {
+ unsigned Reg,
+ const llvm::APInt &Value) const override {
llvm_unreachable("Not yet implemented");
}
diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h
index 85147937966..5deb4c56aea 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/llvm/tools/llvm-exegesis/lib/Target.h
@@ -36,29 +36,32 @@ public:
virtual void addTargetSpecificPasses(llvm::PassManagerBase &PM) const {}
// Generates code to move a constant into a the given register.
+ // Precondition: Value must fit into Reg.
virtual std::vector<llvm::MCInst>
- setRegToConstant(const llvm::MCSubtargetInfo &STI, unsigned Reg) const = 0;
-
- // Generates code to move a constant into a the given register.
- virtual std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI,
- const llvm::APInt &Value,
- unsigned Reg) const = 0;
+ setRegTo(const llvm::MCSubtargetInfo &STI, unsigned Reg,
+ const llvm::APInt &Value) const = 0;
// 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 = 0;
+ virtual unsigned getScratchMemoryRegister(const llvm::Triple &) const {
+ return 0;
+ }
// Fills memory operands with references to the address at [Reg] + Offset.
virtual void fillMemoryOperands(InstructionBuilder &IB, unsigned Reg,
- unsigned Offset) const = 0;
+ 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 = 0;
+ virtual unsigned getMaxMemoryAccessSize() const { return 0; }
// Creates a snippet generator for the given mode.
std::unique_ptr<SnippetGenerator>
diff --git a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
index e55e77d876c..2d8f9582d43 100644
--- a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
@@ -101,8 +101,8 @@ protected:
}
};
-static unsigned GetLoadImmediateOpcode(const llvm::APInt &Value) {
- switch (Value.getBitWidth()) {
+static unsigned GetLoadImmediateOpcode(unsigned RegBitWidth) {
+ switch (RegBitWidth) {
case 8:
return llvm::X86::MOV8ri;
case 16:
@@ -115,8 +115,12 @@ static unsigned GetLoadImmediateOpcode(const llvm::APInt &Value) {
llvm_unreachable("Invalid Value Width");
}
-static llvm::MCInst loadImmediate(unsigned Reg, const llvm::APInt &Value) {
- return llvm::MCInstBuilder(GetLoadImmediateOpcode(Value))
+// Generates instruction to load an immediate value into a register.
+static llvm::MCInst loadImmediate(unsigned Reg, unsigned RegBitWidth,
+ const llvm::APInt &Value) {
+ if (Value.getBitWidth() > RegBitWidth)
+ llvm_unreachable("Value must fit in the Register");
+ return llvm::MCInstBuilder(GetLoadImmediateOpcode(RegBitWidth))
.addReg(Reg)
.addImm(Value.getZExtValue());
}
@@ -163,39 +167,67 @@ static llvm::MCInst releaseStackSpace(unsigned Bytes) {
.addImm(Bytes);
}
+// Reserves some space on the stack, fills it with the content of the provided
+// constant and provide methods to load the stack value into a register.
struct ConstantInliner {
explicit ConstantInliner(const llvm::APInt &Constant)
: StackSize(Constant.getBitWidth() / 8) {
assert(Constant.getBitWidth() % 8 == 0 && "Must be a multiple of 8");
- Add(allocateStackSpace(StackSize));
+ add(allocateStackSpace(StackSize));
size_t ByteOffset = 0;
for (; StackSize - ByteOffset >= 4; ByteOffset += 4)
- Add(fillStackSpace(
+ add(fillStackSpace(
llvm::X86::MOV32mi, ByteOffset,
Constant.extractBits(32, ByteOffset * 8).getZExtValue()));
if (StackSize - ByteOffset >= 2) {
- Add(fillStackSpace(
+ add(fillStackSpace(
llvm::X86::MOV16mi, ByteOffset,
Constant.extractBits(16, ByteOffset * 8).getZExtValue()));
ByteOffset += 2;
}
if (StackSize - ByteOffset >= 1)
- Add(fillStackSpace(
+ add(fillStackSpace(
llvm::X86::MOV8mi, ByteOffset,
Constant.extractBits(8, ByteOffset * 8).getZExtValue()));
}
- ConstantInliner &Add(const llvm::MCInst &Inst) {
- Instructions.push_back(Inst);
- return *this;
+ std::vector<llvm::MCInst> loadAndFinalize(unsigned Reg, unsigned RegBitWidth,
+ unsigned Opcode) {
+ assert(StackSize * 8 == RegBitWidth &&
+ "Value does not have the correct size");
+ add(loadToReg(Reg, Opcode));
+ add(releaseStackSpace(StackSize));
+ return std::move(Instructions);
+ }
+
+ std::vector<llvm::MCInst>
+ loadX87AndFinalize(unsigned Reg, unsigned RegBitWidth, unsigned Opcode) {
+ assert(StackSize * 8 == RegBitWidth &&
+ "Value does not have the correct size");
+ add(llvm::MCInstBuilder(Opcode)
+ .addReg(llvm::X86::RSP) // BaseReg
+ .addImm(1) // ScaleAmt
+ .addReg(0) // IndexReg
+ .addImm(0) // Disp
+ .addReg(0)); // Segment
+ if (Reg != llvm::X86::ST0)
+ add(llvm::MCInstBuilder(llvm::X86::ST_Frr).addReg(Reg));
+ add(releaseStackSpace(StackSize));
+ return std::move(Instructions);
}
- std::vector<llvm::MCInst> finalize() {
- Add(releaseStackSpace(StackSize));
+ std::vector<llvm::MCInst> popFlagAndFinalize() {
+ assert(StackSize * 8 == 64 && "Value does not have the correct size");
+ add(llvm::MCInstBuilder(llvm::X86::POPF64));
return std::move(Instructions);
}
private:
+ ConstantInliner &add(const llvm::MCInst &Inst) {
+ Instructions.push_back(Inst);
+ return *this;
+ }
+
const size_t StackSize;
std::vector<llvm::MCInst> Instructions;
};
@@ -248,64 +280,47 @@ class ExegesisX86Target : public ExegesisTarget {
}
}
- std::vector<llvm::MCInst> setRegToConstant(const llvm::MCSubtargetInfo &STI,
- unsigned Reg) const override {
- // GPR.
+ std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI,
+ unsigned Reg,
+ const llvm::APInt &Value) const override {
if (llvm::X86::GR8RegClass.contains(Reg))
- return {llvm::MCInstBuilder(llvm::X86::MOV8ri).addReg(Reg).addImm(1)};
+ return {loadImmediate(Reg, 8, Value)};
if (llvm::X86::GR16RegClass.contains(Reg))
- return {llvm::MCInstBuilder(llvm::X86::MOV16ri).addReg(Reg).addImm(1)};
+ return {loadImmediate(Reg, 16, Value)};
if (llvm::X86::GR32RegClass.contains(Reg))
- return {llvm::MCInstBuilder(llvm::X86::MOV32ri).addReg(Reg).addImm(1)};
+ return {loadImmediate(Reg, 32, Value)};
if (llvm::X86::GR64RegClass.contains(Reg))
- return {llvm::MCInstBuilder(llvm::X86::MOV64ri32).addReg(Reg).addImm(1)};
- // MMX.
+ return {loadImmediate(Reg, 64, Value)};
+ ConstantInliner CI(Value);
if (llvm::X86::VR64RegClass.contains(Reg))
- return setVectorRegToConstant(Reg, 8, llvm::X86::MMX_MOVQ64rm);
- // {X,Y,Z}MM.
+ return CI.loadAndFinalize(Reg, 64, llvm::X86::MMX_MOVQ64rm);
if (llvm::X86::VR128XRegClass.contains(Reg)) {
if (STI.getFeatureBits()[llvm::X86::FeatureAVX512])
- return setVectorRegToConstant(Reg, 16, llvm::X86::VMOVDQU32Z128rm);
+ return CI.loadAndFinalize(Reg, 128, llvm::X86::VMOVDQU32Z128rm);
if (STI.getFeatureBits()[llvm::X86::FeatureAVX])
- return setVectorRegToConstant(Reg, 16, llvm::X86::VMOVDQUrm);
- return setVectorRegToConstant(Reg, 16, llvm::X86::MOVDQUrm);
+ return CI.loadAndFinalize(Reg, 128, llvm::X86::VMOVDQUrm);
+ return CI.loadAndFinalize(Reg, 128, llvm::X86::MOVDQUrm);
}
if (llvm::X86::VR256XRegClass.contains(Reg)) {
if (STI.getFeatureBits()[llvm::X86::FeatureAVX512])
- return setVectorRegToConstant(Reg, 32, llvm::X86::VMOVDQU32Z256rm);
- return setVectorRegToConstant(Reg, 32, llvm::X86::VMOVDQUYrm);
+ return CI.loadAndFinalize(Reg, 256, llvm::X86::VMOVDQU32Z256rm);
+ if (STI.getFeatureBits()[llvm::X86::FeatureAVX])
+ return CI.loadAndFinalize(Reg, 256, llvm::X86::VMOVDQUYrm);
}
if (llvm::X86::VR512RegClass.contains(Reg))
- return setVectorRegToConstant(Reg, 64, llvm::X86::VMOVDQU32Zrm);
- // X87.
- if (llvm::X86::RFP32RegClass.contains(Reg) ||
- llvm::X86::RFP64RegClass.contains(Reg) ||
- llvm::X86::RFP80RegClass.contains(Reg))
- return setVectorRegToConstant(Reg, 8, llvm::X86::LD_Fp64m);
- if (Reg == llvm::X86::EFLAGS) {
- // Set all flags to 0 but the bits that are "reserved and set to 1".
- constexpr const uint32_t kImmValue = 0x00007002u;
- std::vector<llvm::MCInst> Result;
- Result.push_back(allocateStackSpace(8));
- Result.push_back(fillStackSpace(llvm::X86::MOV64mi32, 0, kImmValue));
- Result.push_back(llvm::MCInstBuilder(llvm::X86::POPF64)); // Also pops.
- return Result;
+ if (STI.getFeatureBits()[llvm::X86::FeatureAVX512])
+ return CI.loadAndFinalize(Reg, 512, llvm::X86::VMOVDQU32Zrm);
+ if (llvm::X86::RSTRegClass.contains(Reg)) {
+ if (Value.getBitWidth() == 32)
+ return CI.loadX87AndFinalize(Reg, 32, llvm::X86::LD_F32m);
+ if (Value.getBitWidth() == 64)
+ return CI.loadX87AndFinalize(Reg, 64, llvm::X86::LD_F64m);
+ if (Value.getBitWidth() == 80)
+ return CI.loadX87AndFinalize(Reg, 80, llvm::X86::LD_F80m);
}
- llvm_unreachable("Not yet implemented");
- }
-
- std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI,
- const llvm::APInt &Value,
- unsigned Reg) const override {
- if (llvm::X86::GR8RegClass.contains(Reg) ||
- llvm::X86::GR16RegClass.contains(Reg) ||
- llvm::X86::GR32RegClass.contains(Reg) ||
- llvm::X86::GR64RegClass.contains(Reg))
- return {loadImmediate(Reg, Value)};
- ConstantInliner CI(Value);
- if (llvm::X86::VR64RegClass.contains(Reg))
- return CI.Add(loadToReg(Reg, llvm::X86::MMX_MOVQ64rm)).finalize();
- llvm_unreachable("Not yet implemented");
+ if (Reg == llvm::X86::EFLAGS)
+ return CI.popFlagAndFinalize();
+ return {}; // Not yet implemented.
}
std::unique_ptr<SnippetGenerator>
@@ -321,31 +336,6 @@ class ExegesisX86Target : public ExegesisTarget {
bool matchesArch(llvm::Triple::ArchType Arch) const override {
return Arch == llvm::Triple::x86_64 || Arch == llvm::Triple::x86;
}
-
-private:
- // setRegToConstant() specialized for a vector register of size
- // `RegSizeBytes`. `RMOpcode` is the opcode used to do a memory -> vector
- // register load.
- static std::vector<llvm::MCInst>
- setVectorRegToConstant(const unsigned Reg, const unsigned RegSizeBytes,
- const unsigned RMOpcode) {
- // There is no instruction to directly set XMM, go through memory.
- // Since vector values can be interpreted as integers of various sizes (8
- // to 64 bits) as well as floats and double, so we chose an immediate
- // value that has set bits for all byte values and is a normal float/
- // double. 0x40404040 is ~32.5 when interpreted as a double and ~3.0f when
- // interpreted as a float.
- constexpr const uint32_t kImmValue = 0x40404040u;
- std::vector<llvm::MCInst> Result;
- Result.push_back(allocateStackSpace(RegSizeBytes));
- constexpr const unsigned kMov32NumBytes = 4;
- for (unsigned Disp = 0; Disp < RegSizeBytes; Disp += kMov32NumBytes) {
- Result.push_back(fillStackSpace(llvm::X86::MOV32mi, Disp, kImmValue));
- }
- Result.push_back(loadToReg(Reg, RMOpcode));
- Result.push_back(releaseStackSpace(RegSizeBytes));
- return Result;
- }
};
} // namespace
OpenPOWER on IntegriCloud