summaryrefslogtreecommitdiffstats
path: root/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-exegesis/lib/X86/Target.cpp')
-rw-r--r--llvm/tools/llvm-exegesis/lib/X86/Target.cpp82
1 files changed, 82 insertions, 0 deletions
diff --git a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
index 26a54591fb0..591edd2afae 100644
--- a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
@@ -8,7 +8,10 @@
//===----------------------------------------------------------------------===//
#include "../Target.h"
+#include "MCTargetDesc/X86MCTargetDesc.h"
#include "X86.h"
+#include "X86RegisterInfo.h"
+#include "llvm/MC/MCInstBuilder.h"
namespace exegesis {
@@ -22,9 +25,88 @@ class ExegesisX86Target : public ExegesisTarget {
// PM.add(llvm::createX86FloatingPointStackifierPass());
}
+ std::vector<llvm::MCInst>
+ setRegToConstant(const unsigned Reg) const override {
+ // FIXME: Handle FP stack:
+ // llvm::X86::RFP32RegClass
+ // llvm::X86::RFP64RegClass
+ // llvm::X86::RFP80RegClass
+ if (llvm::X86::GR8RegClass.contains(Reg)) {
+ return {llvm::MCInstBuilder(llvm::X86::MOV8ri).addReg(Reg).addImm(1)};
+ }
+ if (llvm::X86::GR16RegClass.contains(Reg)) {
+ return {llvm::MCInstBuilder(llvm::X86::MOV16ri).addReg(Reg).addImm(1)};
+ }
+ if (llvm::X86::GR32RegClass.contains(Reg)) {
+ return {llvm::MCInstBuilder(llvm::X86::MOV32ri).addReg(Reg).addImm(1)};
+ }
+ if (llvm::X86::GR64RegClass.contains(Reg)) {
+ return {llvm::MCInstBuilder(llvm::X86::MOV64ri32).addReg(Reg).addImm(1)};
+ }
+ if (llvm::X86::VR128XRegClass.contains(Reg)) {
+ return setVectorRegToConstant(Reg, 16, llvm::X86::VMOVDQUrm);
+ }
+ if (llvm::X86::VR256XRegClass.contains(Reg)) {
+ return setVectorRegToConstant(Reg, 32, llvm::X86::VMOVDQUYrm);
+ }
+ if (llvm::X86::VR512RegClass.contains(Reg)) {
+ return setVectorRegToConstant(Reg, 64, llvm::X86::VMOVDQU64Zrm);
+ }
+ return {};
+ }
+
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 uint64_t kImmValue = 0x40404040ull;
+ std::vector<llvm::MCInst> Result;
+ // Allocate scratch memory on the stack.
+ Result.push_back(llvm::MCInstBuilder(llvm::X86::SUB64ri8)
+ .addReg(llvm::X86::RSP)
+ .addReg(llvm::X86::RSP)
+ .addImm(RegSizeBytes));
+ // Fill scratch memory.
+ for (unsigned Disp = 0; Disp < RegSizeBytes; Disp += 4) {
+ Result.push_back(llvm::MCInstBuilder(llvm::X86::MOV32mi)
+ // Address = ESP
+ .addReg(llvm::X86::RSP) // BaseReg
+ .addImm(1) // ScaleAmt
+ .addReg(0) // IndexReg
+ .addImm(Disp) // Disp
+ .addReg(0) // Segment
+ // Immediate.
+ .addImm(kImmValue));
+ }
+ // Load Reg from scratch memory.
+ Result.push_back(llvm::MCInstBuilder(RMOpcode)
+ .addReg(Reg)
+ // Address = ESP
+ .addReg(llvm::X86::RSP) // BaseReg
+ .addImm(1) // ScaleAmt
+ .addReg(0) // IndexReg
+ .addImm(0) // Disp
+ .addReg(0)); // Segment
+ // Release scratch memory.
+ Result.push_back(llvm::MCInstBuilder(llvm::X86::ADD64ri8)
+ .addReg(llvm::X86::RSP)
+ .addReg(llvm::X86::RSP)
+ .addImm(RegSizeBytes));
+ return Result;
+ }
};
} // namespace
OpenPOWER on IntegriCloud