[llvm] r342644 - [llvm-exegesis] Improve Register Setup (roll forward of D51856).

Guillaume Chatelet via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 20 05:22:18 PDT 2018


Author: gchatelet
Date: Thu Sep 20 05:22:18 2018
New Revision: 342644

URL: http://llvm.org/viewvc/llvm-project?rev=342644&view=rev
Log:
[llvm-exegesis] Improve Register Setup (roll forward of D51856).

Summary:
Added function to set a register to a particular value + tests.
Add EFLAGS test, use new setRegTo instead of setRegToConstant.

Reviewers: courbet, javed.absar

Subscribers: llvm-commits, tschuett, mgorny

Differential Revision: https://reviews.llvm.org/D52297

Modified:
    llvm/trunk/tools/llvm-exegesis/lib/AArch64/Target.cpp
    llvm/trunk/tools/llvm-exegesis/lib/Assembler.cpp
    llvm/trunk/tools/llvm-exegesis/lib/Assembler.h
    llvm/trunk/tools/llvm-exegesis/lib/BenchmarkCode.h
    llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
    llvm/trunk/tools/llvm-exegesis/lib/SnippetGenerator.cpp
    llvm/trunk/tools/llvm-exegesis/lib/SnippetGenerator.h
    llvm/trunk/tools/llvm-exegesis/lib/Target.cpp
    llvm/trunk/tools/llvm-exegesis/lib/Target.h
    llvm/trunk/tools/llvm-exegesis/lib/X86/Target.cpp
    llvm/trunk/unittests/tools/llvm-exegesis/AArch64/TargetTest.cpp
    llvm/trunk/unittests/tools/llvm-exegesis/ARM/AssemblerTest.cpp
    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
    llvm/trunk/unittests/tools/llvm-exegesis/X86/TargetTest.cpp

Modified: llvm/trunk/tools/llvm-exegesis/lib/AArch64/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/AArch64/Target.cpp?rev=342644&r1=342643&r2=342644&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/AArch64/Target.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/AArch64/Target.cpp Thu Sep 20 05:22:18 2018
@@ -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");
-  }
-
-  std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI,
-                                     const llvm::APInt &Value,
-                                     unsigned Reg) const override {
-    llvm_unreachable("Not yet implemented");
-  }
+namespace {
 
-  unsigned getScratchMemoryRegister(const llvm::Triple &) 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");
+}
+
+// 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);

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=342644&r1=342643&r2=342644&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/Assembler.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/Assembler.cpp Thu Sep 20 05:22:18 2018
@@ -29,17 +29,17 @@ static constexpr const char ModuleID[] =
 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(
 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 ExegesisTarg
     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 ExegesisTarg
   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();

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=342644&r1=342643&r2=342644&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/Assembler.h (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/Assembler.h Thu Sep 20 05:22:18 2018
@@ -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(
 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);
 

Modified: llvm/trunk/tools/llvm-exegesis/lib/BenchmarkCode.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/BenchmarkCode.h?rev=342644&r1=342643&r2=342644&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/BenchmarkCode.h (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/BenchmarkCode.h Thu Sep 20 05:22:18 2018
@@ -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.

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=342644&r1=342643&r2=342644&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/BenchmarkRunner.cpp Thu Sep 20 05:22:18 2018
@@ -104,7 +104,7 @@ BenchmarkRunner::writeObjectFile(const B
     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();
 }
 

Modified: llvm/trunk/tools/llvm-exegesis/lib/SnippetGenerator.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/SnippetGenerator.cpp?rev=342644&r1=342643&r2=342644&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/SnippetGenerator.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/SnippetGenerator.cpp Thu Sep 20 05:22:18 2018
@@ -49,7 +49,7 @@ SnippetGenerator::generateConfigurations
       }
       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
     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::
       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::
       }
     }
   }
-  return RegsToDef;
+  return RIV;
 }
 
 llvm::Expected<CodeTemplate> SnippetGenerator::generateSelfAliasingCodeTemplate(

Modified: llvm/trunk/tools/llvm-exegesis/lib/SnippetGenerator.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-exegesis/lib/SnippetGenerator.h?rev=342644&r1=342643&r2=342644&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/SnippetGenerator.h (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/SnippetGenerator.h Thu Sep 20 05:22:18 2018
@@ -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;

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=342644&r1=342643&r2=342644&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/Target.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/Target.cpp Thu Sep 20 05:22:18 2018
@@ -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");
   }
 

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=342644&r1=342643&r2=342644&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/Target.h (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/Target.h Thu Sep 20 05:22:18 2018
@@ -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>

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=342644&r1=342643&r2=342644&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-exegesis/lib/X86/Target.cpp (original)
+++ llvm/trunk/tools/llvm-exegesis/lib/X86/Target.cpp Thu Sep 20 05:22:18 2018
@@ -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(c
   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(un
       .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 Exegesi
     }
   }
 
-  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;
-    }
-    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 (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);
+    }
+    if (Reg == llvm::X86::EFLAGS)
+      return CI.popFlagAndFinalize();
+    return {}; // Not yet implemented.
   }
 
   std::unique_ptr<SnippetGenerator>
@@ -321,31 +336,6 @@ class ExegesisX86Target : public Exegesi
   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

Modified: llvm/trunk/unittests/tools/llvm-exegesis/AArch64/TargetTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/tools/llvm-exegesis/AArch64/TargetTest.cpp?rev=342644&r1=342643&r2=342644&view=diff
==============================================================================
--- llvm/trunk/unittests/tools/llvm-exegesis/AArch64/TargetTest.cpp (original)
+++ llvm/trunk/unittests/tools/llvm-exegesis/AArch64/TargetTest.cpp Thu Sep 20 05:22:18 2018
@@ -15,11 +15,16 @@ void InitializeAArch64ExegesisTarget();
 
 namespace {
 
+using llvm::APInt;
+using llvm::MCInst;
 using testing::Gt;
+using testing::IsEmpty;
+using testing::Not;
 using testing::NotNull;
-using testing::SizeIs;
 
-constexpr const char kTriple[] = "aarch64-unknown-linux";
+static const char kTriple[] = "aarch64-unknown-linux";
+static const char kGenericCpu[] = "generic";
+static const char kNoFeatures[] = "";
 
 class AArch64TargetTest : public ::testing::Test {
 protected:
@@ -29,7 +34,10 @@ protected:
     std::string error;
     Target_ = llvm::TargetRegistry::lookupTarget(kTriple, error);
     EXPECT_THAT(Target_, NotNull());
+    STI_.reset(
+        Target_->createMCSubtargetInfo(kTriple, kGenericCpu, kNoFeatures));
   }
+
   static void SetUpTestCase() {
     LLVMInitializeAArch64TargetInfo();
     LLVMInitializeAArch64Target();
@@ -37,9 +45,20 @@ protected:
     InitializeAArch64ExegesisTarget();
   }
 
+  std::vector<MCInst> setRegTo(unsigned Reg, const APInt &Value) {
+    return ExegesisTarget_->setRegTo(*STI_, Reg, Value);
+  }
+
   const llvm::Target *Target_;
   const ExegesisTarget *const ExegesisTarget_;
+  std::unique_ptr<llvm::MCSubtargetInfo> STI_;
 };
 
+TEST_F(AArch64TargetTest, SetRegToConstant) {
+  // The AArch64 target currently doesn't know how to set register values.
+  const auto Insts = setRegTo(llvm::AArch64::X0, llvm::APInt());
+  EXPECT_THAT(Insts, Not(IsEmpty()));
+}
+
 } // namespace
 } // namespace exegesis

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=342644&r1=342643&r2=342644&view=diff
==============================================================================
--- llvm/trunk/unittests/tools/llvm-exegesis/ARM/AssemblerTest.cpp (original)
+++ llvm/trunk/unittests/tools/llvm-exegesis/ARM/AssemblerTest.cpp Thu Sep 20 05:22:18 2018
@@ -30,12 +30,11 @@ protected:
 };
 
 TEST_F(ARMMachineFunctionGeneratorTest, DISABLED_JitFunction) {
-  Check(ExegesisTarget::getDefault(), {}, llvm::MCInst(), 0x1e, 0xff, 0x2f,
-        0xe1);
+  Check({}, llvm::MCInst(), 0x1e, 0xff, 0x2f, 0xe1);
 }
 
 TEST_F(ARMMachineFunctionGeneratorTest, DISABLED_JitFunctionADDrr) {
-  Check(ExegesisTarget::getDefault(), {llvm::ARM::R0},
+  Check({{llvm::ARM::R0, llvm::APInt()}},
         MCInstBuilder(llvm::ARM::ADDrr)
             .addReg(llvm::ARM::R0)
             .addReg(llvm::ARM::R0)

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=342644&r1=342643&r2=342644&view=diff
==============================================================================
--- llvm/trunk/unittests/tools/llvm-exegesis/Common/AssemblerUtils.h (original)
+++ llvm/trunk/unittests/tools/llvm-exegesis/Common/AssemblerUtils.h Thu Sep 20 05:22:18 2018
@@ -32,7 +32,9 @@ protected:
                                    const std::string &CpuName)
       : TT(TT), CpuName(CpuName),
         CanExecute(llvm::Triple(TT).getArch() ==
-                   llvm::Triple(llvm::sys::getProcessTriple()).getArch()) {
+                   llvm::Triple(llvm::sys::getProcessTriple()).getArch()),
+        ET(ExegesisTarget::lookup(llvm::Triple(TT))) {
+    assert(ET);
     if (!CanExecute) {
       llvm::outs() << "Skipping execution, host:"
                    << llvm::sys::getProcessTriple() << ", target:" << TT
@@ -41,12 +43,12 @@ protected:
   }
 
   template <class... Bs>
-  inline void Check(const ExegesisTarget &ET,
-                    llvm::ArrayRef<unsigned> RegsToDef, llvm::MCInst MCInst,
-                    Bs... Bytes) {
+  inline void Check(llvm::ArrayRef<RegisterValue> RegisterInitialValues,
+                    llvm::MCInst MCInst, Bs... Bytes) {
     ExecutableFunction Function =
-        (MCInst.getOpcode() == 0) ? assembleToFunction(ET, RegsToDef, {})
-                                  : assembleToFunction(ET, RegsToDef, {MCInst});
+        (MCInst.getOpcode() == 0)
+            ? assembleToFunction(RegisterInitialValues, {})
+            : assembleToFunction(RegisterInitialValues, {MCInst});
     ASSERT_THAT(Function.getFunctionBytes().str(),
                 testing::ElementsAre(Bytes...));
     if (CanExecute) {
@@ -70,14 +72,12 @@ private:
   }
 
   ExecutableFunction
-  assembleToFunction(const ExegesisTarget &ET,
-                     llvm::ArrayRef<unsigned> RegsToDef,
+  assembleToFunction(llvm::ArrayRef<RegisterValue> RegisterInitialValues,
                      llvm::ArrayRef<llvm::MCInst> Instructions) {
     llvm::SmallString<256> Buffer;
     llvm::raw_svector_ostream AsmStream(Buffer);
-    assembleToStream(ET, createTargetMachine(), /*LiveIns=*/{},
-                     RegsToDef, Instructions,
-                     AsmStream);
+    assembleToStream(*ET, createTargetMachine(), /*LiveIns=*/{},
+                     RegisterInitialValues, Instructions, AsmStream);
     return ExecutableFunction(createTargetMachine(),
                               getObjectFromBuffer(AsmStream.str()));
   }
@@ -85,6 +85,7 @@ private:
   const std::string TT;
   const std::string CpuName;
   const bool CanExecute;
+  const ExegesisTarget *const ET;
 };
 
 } // namespace exegesis

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=342644&r1=342643&r2=342644&view=diff
==============================================================================
--- llvm/trunk/unittests/tools/llvm-exegesis/X86/AssemblerTest.cpp (original)
+++ llvm/trunk/unittests/tools/llvm-exegesis/X86/AssemblerTest.cpp Thu Sep 20 05:22:18 2018
@@ -39,19 +39,12 @@ protected:
 };
 
 TEST_F(X86MachineFunctionGeneratorTest, DISABLED_JitFunction) {
-  Check(ExegesisTarget::getDefault(), {}, llvm::MCInst(), 0xc3);
-}
-
-TEST_F(X86MachineFunctionGeneratorTest, DISABLED_JitFunctionXOR32rr_Default) {
-  Check(ExegesisTarget::getDefault(), {EAX},
-        MCInstBuilder(XOR32rr).addReg(EAX).addReg(EAX).addReg(EAX), 0x31, 0xc0,
-        0xc3);
+  Check({}, llvm::MCInst(), 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),
+  Check({{EAX, llvm::APInt(32, 1)}},
+        MCInstBuilder(XOR32rr).addReg(EAX).addReg(EAX).addReg(EAX),
         // mov eax, 1
         0xb8, 0x01, 0x00, 0x00, 0x00,
         // xor eax, eax
@@ -59,15 +52,13 @@ TEST_F(X86MachineFunctionGeneratorTest,
 }
 
 TEST_F(X86MachineFunctionGeneratorTest, DISABLED_JitFunctionMOV64ri) {
-  Check(ExegesisTarget::getDefault(), {},
-        MCInstBuilder(MOV64ri32).addReg(RAX).addImm(42), 0x48, 0xc7, 0xc0, 0x2a,
-        0x00, 0x00, 0x00, 0xc3);
+  Check({}, MCInstBuilder(MOV64ri32).addReg(RAX).addImm(42), 0x48, 0xc7, 0xc0,
+        0x2a, 0x00, 0x00, 0x00, 0xc3);
 }
 
 TEST_F(X86MachineFunctionGeneratorTest, DISABLED_JitFunctionMOV32ri) {
-  Check(ExegesisTarget::getDefault(), {},
-        MCInstBuilder(MOV32ri).addReg(EAX).addImm(42), 0xb8, 0x2a, 0x00, 0x00,
-        0x00, 0xc3);
+  Check({}, MCInstBuilder(MOV32ri).addReg(EAX).addImm(42), 0xb8, 0x2a, 0x00,
+        0x00, 0x00, 0xc3);
 }
 
 } // namespace

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=342644&r1=342643&r2=342644&view=diff
==============================================================================
--- llvm/trunk/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp (original)
+++ llvm/trunk/unittests/tools/llvm-exegesis/X86/SnippetGeneratorTest.cpp Thu Sep 20 05:22:18 2018
@@ -261,7 +261,13 @@ private:
 
 using FakeSnippetGeneratorTest = SnippetGeneratorTest<FakeSnippetGenerator>;
 
-TEST_F(FakeSnippetGeneratorTest, ComputeRegsToDefAdd16ri) {
+testing::Matcher<const RegisterValue &> IsRegisterValue(unsigned Reg,
+                                                        llvm::APInt Value) {
+  return testing::AllOf(testing::Field(&RegisterValue::Register, Reg),
+                        testing::Field(&RegisterValue::Value, Value));
+}
+
+TEST_F(FakeSnippetGeneratorTest, ComputeRegisterInitialValuesAdd16ri) {
   // ADD16ri:
   // explicit def 0       : reg RegClass=GR16
   // explicit use 1       : reg RegClass=GR16 | TIED_TO:0
@@ -272,11 +278,11 @@ TEST_F(FakeSnippetGeneratorTest, Compute
       llvm::MCOperand::createReg(llvm::X86::AX);
   std::vector<InstructionBuilder> Snippet;
   Snippet.push_back(std::move(IB));
-  const auto RegsToDef = Generator.computeRegsToDef(Snippet);
-  EXPECT_THAT(RegsToDef, UnorderedElementsAre(llvm::X86::AX));
+  const auto RIV = Generator.computeRegisterInitialValues(Snippet);
+  EXPECT_THAT(RIV, ElementsAre(IsRegisterValue(llvm::X86::AX, llvm::APInt())));
 }
 
-TEST_F(FakeSnippetGeneratorTest, ComputeRegsToDefAdd64rr) {
+TEST_F(FakeSnippetGeneratorTest, ComputeRegisterInitialValuesAdd64rr) {
   // ADD64rr:
   //  mov64ri rax, 42
   //  add64rr rax, rax, rbx
@@ -298,8 +304,8 @@ TEST_F(FakeSnippetGeneratorTest, Compute
     Snippet.push_back(std::move(Add));
   }
 
-  const auto RegsToDef = Generator.computeRegsToDef(Snippet);
-  EXPECT_THAT(RegsToDef, UnorderedElementsAre(llvm::X86::RBX));
+  const auto RIV = Generator.computeRegisterInitialValues(Snippet);
+  EXPECT_THAT(RIV, ElementsAre(IsRegisterValue(llvm::X86::RBX, llvm::APInt())));
 }
 
 } // namespace

Modified: llvm/trunk/unittests/tools/llvm-exegesis/X86/TargetTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/tools/llvm-exegesis/X86/TargetTest.cpp?rev=342644&r1=342643&r2=342644&view=diff
==============================================================================
--- llvm/trunk/unittests/tools/llvm-exegesis/X86/TargetTest.cpp (original)
+++ llvm/trunk/unittests/tools/llvm-exegesis/X86/TargetTest.cpp Thu Sep 20 05:22:18 2018
@@ -13,7 +13,7 @@
 
 namespace llvm {
 
-bool operator==(const llvm::MCOperand &a, const llvm::MCOperand &b) {
+bool operator==(const MCOperand &a, const MCOperand &b) {
   if (a.isImm() && b.isImm())
     return a.getImm() == b.getImm();
   if (a.isReg() && b.isReg())
@@ -21,7 +21,7 @@ bool operator==(const llvm::MCOperand &a
   return false;
 }
 
-bool operator==(const llvm::MCInst &a, const llvm::MCInst &b) {
+bool operator==(const MCInst &a, const MCInst &b) {
   if (a.getOpcode() != b.getOpcode())
     return false;
   if (a.getNumOperands() != b.getNumOperands())
@@ -41,17 +41,71 @@ void InitializeX86ExegesisTarget();
 
 namespace {
 
+using testing::AllOf;
 using testing::ElementsAre;
+using testing::ElementsAreArray;
+using testing::Eq;
 using testing::Gt;
+using testing::Matcher;
 using testing::NotNull;
+using testing::Property;
 using testing::SizeIs;
 
 using llvm::APInt;
 using llvm::MCInst;
 using llvm::MCInstBuilder;
+using llvm::MCOperand;
 
-constexpr const char kTriple[] = "x86_64-unknown-linux";
+Matcher<MCOperand> IsImm(int64_t Value) {
+  return AllOf(Property(&MCOperand::isImm, Eq(true)),
+               Property(&MCOperand::getImm, Eq(Value)));
+}
+
+Matcher<MCOperand> IsReg(unsigned Reg) {
+  return AllOf(Property(&MCOperand::isReg, Eq(true)),
+               Property(&MCOperand::getReg, Eq(Reg)));
+}
+
+Matcher<MCInst> OpcodeIs(unsigned Opcode) {
+  return Property(&MCInst::getOpcode, Eq(Opcode));
+}
+
+Matcher<MCInst> IsMovImmediate(unsigned Opcode, int64_t Reg, int64_t Value) {
+  return AllOf(OpcodeIs(Opcode), ElementsAre(IsReg(Reg), IsImm(Value)));
+}
+
+Matcher<MCInst> IsMovValueToStack(unsigned Opcode, int64_t Value,
+                                  size_t Offset) {
+  return AllOf(OpcodeIs(Opcode),
+               ElementsAre(IsReg(llvm::X86::RSP), IsImm(1), IsReg(0),
+                           IsImm(Offset), IsReg(0), IsImm(Value)));
+}
+
+Matcher<MCInst> IsMovValueFromStack(unsigned Opcode, unsigned Reg) {
+  return AllOf(OpcodeIs(Opcode),
+               ElementsAre(IsReg(Reg), IsReg(llvm::X86::RSP), IsImm(1),
+                           IsReg(0), IsImm(0), IsReg(0)));
+}
+
+Matcher<MCInst> IsStackAllocate(unsigned Size) {
+  return AllOf(
+      OpcodeIs(llvm::X86::SUB64ri8),
+      ElementsAre(IsReg(llvm::X86::RSP), IsReg(llvm::X86::RSP), IsImm(Size)));
+}
+
+Matcher<MCInst> IsStackDeallocate(unsigned Size) {
+  return AllOf(
+      OpcodeIs(llvm::X86::ADD64ri8),
+      ElementsAre(IsReg(llvm::X86::RSP), IsReg(llvm::X86::RSP), IsImm(Size)));
+}
 
+static const char kTriple[] = "x86_64-unknown-linux";
+static const char kFeaturesEmpty[] = "";
+static const char kFeaturesAvx[] = "+avx";
+static const char kFeaturesAvx512VL[] = "+avx512vl";
+static const char kCpuCore2[] = "core2";
+
+template <const char *CPU, const char *Features>
 class X86TargetTest : public ::testing::Test {
 protected:
   X86TargetTest()
@@ -60,7 +114,9 @@ protected:
     std::string error;
     Target_ = llvm::TargetRegistry::lookupTarget(kTriple, error);
     EXPECT_THAT(Target_, NotNull());
+    STI_.reset(Target_->createMCSubtargetInfo(kTriple, kCpuCore2, Features));
   }
+
   static void SetUpTestCase() {
     LLVMInitializeX86TargetInfo();
     LLVMInitializeX86Target();
@@ -68,173 +124,208 @@ protected:
     InitializeX86ExegesisTarget();
   }
 
+  std::vector<MCInst> setRegTo(unsigned Reg, const APInt &Value) {
+    return ExegesisTarget_->setRegTo(*STI_, Reg, Value);
+  }
+
   const llvm::Target *Target_;
   const ExegesisTarget *const ExegesisTarget_;
+  std::unique_ptr<llvm::MCSubtargetInfo> STI_;
 };
 
-TEST_F(X86TargetTest, SetRegToConstantGPR) {
-  const std::unique_ptr<llvm::MCSubtargetInfo> STI(
-      Target_->createMCSubtargetInfo(kTriple, "core2", ""));
-  const auto Insts = ExegesisTarget_->setRegToConstant(*STI, llvm::X86::EAX);
-  EXPECT_THAT(Insts, SizeIs(1));
-  EXPECT_EQ(Insts[0].getOpcode(), llvm::X86::MOV32ri);
-  EXPECT_EQ(Insts[0].getOperand(0).getReg(), llvm::X86::EAX);
-}
-
-TEST_F(X86TargetTest, SetRegToConstantXMM_SSE2) {
-  const std::unique_ptr<llvm::MCSubtargetInfo> STI(
-      Target_->createMCSubtargetInfo(kTriple, "core2", ""));
-  const auto Insts = ExegesisTarget_->setRegToConstant(*STI, llvm::X86::XMM1);
-  EXPECT_THAT(Insts, SizeIs(7U));
-  EXPECT_EQ(Insts[0].getOpcode(), llvm::X86::SUB64ri8);
-  EXPECT_EQ(Insts[1].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[2].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[3].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[4].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[5].getOpcode(), llvm::X86::MOVDQUrm);
-  EXPECT_EQ(Insts[6].getOpcode(), llvm::X86::ADD64ri8);
-}
-
-TEST_F(X86TargetTest, SetRegToConstantXMM_AVX) {
-  const std::unique_ptr<llvm::MCSubtargetInfo> STI(
-      Target_->createMCSubtargetInfo(kTriple, "core2", "+avx"));
-  const auto Insts = ExegesisTarget_->setRegToConstant(*STI, llvm::X86::XMM1);
-  EXPECT_THAT(Insts, SizeIs(7U));
-  EXPECT_EQ(Insts[0].getOpcode(), llvm::X86::SUB64ri8);
-  EXPECT_EQ(Insts[1].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[2].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[3].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[4].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[5].getOpcode(), llvm::X86::VMOVDQUrm);
-  EXPECT_EQ(Insts[6].getOpcode(), llvm::X86::ADD64ri8);
-}
-
-TEST_F(X86TargetTest, SetRegToConstantXMM_AVX512) {
-  const std::unique_ptr<llvm::MCSubtargetInfo> STI(
-      Target_->createMCSubtargetInfo(kTriple, "core2", "+avx512vl"));
-  const auto Insts = ExegesisTarget_->setRegToConstant(*STI, llvm::X86::XMM1);
-  EXPECT_THAT(Insts, SizeIs(7U));
-  EXPECT_EQ(Insts[0].getOpcode(), llvm::X86::SUB64ri8);
-  EXPECT_EQ(Insts[1].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[2].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[3].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[4].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[5].getOpcode(), llvm::X86::VMOVDQU32Z128rm);
-  EXPECT_EQ(Insts[6].getOpcode(), llvm::X86::ADD64ri8);
-}
-
-TEST_F(X86TargetTest, SetRegToConstantMMX) {
-  const std::unique_ptr<llvm::MCSubtargetInfo> STI(
-      Target_->createMCSubtargetInfo(kTriple, "core2", ""));
-  const auto Insts = ExegesisTarget_->setRegToConstant(*STI, llvm::X86::MM1);
-  EXPECT_THAT(Insts, SizeIs(5U));
-  EXPECT_EQ(Insts[0].getOpcode(), llvm::X86::SUB64ri8);
-  EXPECT_EQ(Insts[1].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[2].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[3].getOpcode(), llvm::X86::MMX_MOVQ64rm);
-  EXPECT_EQ(Insts[4].getOpcode(), llvm::X86::ADD64ri8);
-}
-
-TEST_F(X86TargetTest, SetRegToConstantYMM_AVX) {
-  const std::unique_ptr<llvm::MCSubtargetInfo> STI(
-      Target_->createMCSubtargetInfo(kTriple, "core2", "+avx"));
-  const auto Insts = ExegesisTarget_->setRegToConstant(*STI, llvm::X86::YMM1);
-  EXPECT_THAT(Insts, SizeIs(11U));
-  EXPECT_EQ(Insts[0].getOpcode(), llvm::X86::SUB64ri8);
-  EXPECT_EQ(Insts[1].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[2].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[3].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[4].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[5].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[6].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[7].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[8].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[9].getOpcode(), llvm::X86::VMOVDQUYrm);
-  EXPECT_EQ(Insts[10].getOpcode(), llvm::X86::ADD64ri8);
-}
-
-TEST_F(X86TargetTest, SetRegToConstantYMM_AVX512) {
-  const std::unique_ptr<llvm::MCSubtargetInfo> STI(
-      Target_->createMCSubtargetInfo(kTriple, "core2", "+avx512vl"));
-  const auto Insts = ExegesisTarget_->setRegToConstant(*STI, llvm::X86::YMM1);
-  EXPECT_THAT(Insts, SizeIs(11U));
-  EXPECT_EQ(Insts[0].getOpcode(), llvm::X86::SUB64ri8);
-  EXPECT_EQ(Insts[1].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[2].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[3].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[4].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[5].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[6].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[7].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[8].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[9].getOpcode(), llvm::X86::VMOVDQU32Z256rm);
-  EXPECT_EQ(Insts[10].getOpcode(), llvm::X86::ADD64ri8);
-}
-
-TEST_F(X86TargetTest, SetRegToConstantZMM_AVX512) {
-  const std::unique_ptr<llvm::MCSubtargetInfo> STI(
-      Target_->createMCSubtargetInfo(kTriple, "core2", "+avx512vl"));
-  const auto Insts = ExegesisTarget_->setRegToConstant(*STI, llvm::X86::ZMM1);
-  EXPECT_THAT(Insts, SizeIs(19U));
-  EXPECT_EQ(Insts[0].getOpcode(), llvm::X86::SUB64ri8);
-  EXPECT_EQ(Insts[1].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[2].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[3].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[4].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[5].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[6].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[7].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[8].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[9].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[10].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[11].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[12].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[13].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[14].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[15].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[16].getOpcode(), llvm::X86::MOV32mi);
-  EXPECT_EQ(Insts[17].getOpcode(), llvm::X86::VMOVDQU32Zrm);
-  EXPECT_EQ(Insts[18].getOpcode(), llvm::X86::ADD64ri8);
-}
-
-TEST_F(X86TargetTest, SetToAPInt) {
-  const std::unique_ptr<llvm::MCSubtargetInfo> STI(
-      Target_->createMCSubtargetInfo(kTriple, "core2", ""));
-  // EXPECT_THAT(ExegesisTarget_->setRegTo(*STI, APInt(8, 0xFFU),
-  // llvm::X86::AL),
-  //             ElementsAre((MCInst)MCInstBuilder(llvm::X86::MOV8ri)
-  //                             .addReg(llvm::X86::AL)
-  //                             .addImm(0xFFU)));
-  // EXPECT_THAT(
-  //     ExegesisTarget_->setRegTo(*STI, APInt(16, 0xFFFFU), llvm::X86::BX),
-  //     ElementsAre((MCInst)MCInstBuilder(llvm::X86::MOV16ri)
-  //                     .addReg(llvm::X86::BX)
-  //                     .addImm(0xFFFFU)));
-  // EXPECT_THAT(
-  //     ExegesisTarget_->setRegTo(*STI, APInt(32, 0x7FFFFU), llvm::X86::ECX),
-  //     ElementsAre((MCInst)MCInstBuilder(llvm::X86::MOV32ri)
-  //                     .addReg(llvm::X86::ECX)
-  //                     .addImm(0x7FFFFU)));
-  // EXPECT_THAT(ExegesisTarget_->setRegTo(*STI, APInt(64,
-  // 0x7FFFFFFFFFFFFFFFULL),
-  //                                       llvm::X86::RDX),
-  //             ElementsAre((MCInst)MCInstBuilder(llvm::X86::MOV64ri)
-  //                             .addReg(llvm::X86::RDX)
-  //                             .addImm(0x7FFFFFFFFFFFFFFFULL)));
-
-  const std::unique_ptr<llvm::MCRegisterInfo> MRI(
-      Target_->createMCRegInfo(kTriple));
-  const std::unique_ptr<llvm::MCAsmInfo> MAI(
-      Target_->createMCAsmInfo(*MRI, kTriple));
-  const std::unique_ptr<llvm::MCInstrInfo> MII(Target_->createMCInstrInfo());
-  const std::unique_ptr<llvm::MCInstPrinter> MIP(
-      Target_->createMCInstPrinter(llvm::Triple(kTriple), 1, *MAI, *MII, *MRI));
-
-  for (const auto M : ExegesisTarget_->setRegTo(
-           *STI, APInt(80, "ABCD1234123456785678", 16), llvm::X86::MM0)) {
-    MIP->printInst(&M, llvm::errs(), "", *STI);
-    llvm::errs() << "\n";
-  }
+using Core2TargetTest = X86TargetTest<kCpuCore2, kFeaturesEmpty>;
+using Core2AvxTargetTest = X86TargetTest<kCpuCore2, kFeaturesAvx>;
+using Core2Avx512TargetTest = X86TargetTest<kCpuCore2, kFeaturesAvx512VL>;
+
+TEST_F(Core2TargetTest, SetFlags) {
+  const unsigned Reg = llvm::X86::EFLAGS;
+  EXPECT_THAT(
+      setRegTo(Reg, APInt(64, 0x1111222233334444ULL)),
+      ElementsAre(IsStackAllocate(8),
+                  IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 0),
+                  IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 4),
+                  OpcodeIs(llvm::X86::POPF64)));
+}
+
+TEST_F(Core2TargetTest, SetRegToGR8Value) {
+  const uint8_t Value = 0xFFU;
+  const unsigned Reg = llvm::X86::AL;
+  EXPECT_THAT(setRegTo(Reg, APInt(8, Value)),
+              ElementsAre(IsMovImmediate(llvm::X86::MOV8ri, Reg, Value)));
+}
+
+TEST_F(Core2TargetTest, SetRegToGR16Value) {
+  const uint16_t Value = 0xFFFFU;
+  const unsigned Reg = llvm::X86::BX;
+  EXPECT_THAT(setRegTo(Reg, APInt(16, Value)),
+              ElementsAre(IsMovImmediate(llvm::X86::MOV16ri, Reg, Value)));
+}
+
+TEST_F(Core2TargetTest, SetRegToGR32Value) {
+  const uint32_t Value = 0x7FFFFU;
+  const unsigned Reg = llvm::X86::ECX;
+  EXPECT_THAT(setRegTo(Reg, APInt(32, Value)),
+              ElementsAre(IsMovImmediate(llvm::X86::MOV32ri, Reg, Value)));
+}
+
+TEST_F(Core2TargetTest, SetRegToGR64Value) {
+  const uint64_t Value = 0x7FFFFFFFFFFFFFFFULL;
+  const unsigned Reg = llvm::X86::RDX;
+  EXPECT_THAT(setRegTo(Reg, APInt(64, Value)),
+              ElementsAre(IsMovImmediate(llvm::X86::MOV64ri, Reg, Value)));
+}
+
+TEST_F(Core2TargetTest, SetRegToVR64Value) {
+  EXPECT_THAT(
+      setRegTo(llvm::X86::MM0, APInt(64, 0x1111222233334444ULL)),
+      ElementsAre(IsStackAllocate(8),
+                  IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 0),
+                  IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 4),
+                  IsMovValueFromStack(llvm::X86::MMX_MOVQ64rm, llvm::X86::MM0),
+                  IsStackDeallocate(8)));
+}
+
+TEST_F(Core2TargetTest, SetRegToVR128Value_Use_MOVDQUrm) {
+  EXPECT_THAT(
+      setRegTo(llvm::X86::XMM0,
+               APInt(128, "11112222333344445555666677778888", 16)),
+      ElementsAre(IsStackAllocate(16),
+                  IsMovValueToStack(llvm::X86::MOV32mi, 0x77778888UL, 0),
+                  IsMovValueToStack(llvm::X86::MOV32mi, 0x55556666UL, 4),
+                  IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 8),
+                  IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 12),
+                  IsMovValueFromStack(llvm::X86::MOVDQUrm, llvm::X86::XMM0),
+                  IsStackDeallocate(16)));
+}
+
+TEST_F(Core2AvxTargetTest, SetRegToVR128Value_Use_VMOVDQUrm) {
+  EXPECT_THAT(
+      setRegTo(llvm::X86::XMM0,
+               APInt(128, "11112222333344445555666677778888", 16)),
+      ElementsAre(IsStackAllocate(16),
+                  IsMovValueToStack(llvm::X86::MOV32mi, 0x77778888UL, 0),
+                  IsMovValueToStack(llvm::X86::MOV32mi, 0x55556666UL, 4),
+                  IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 8),
+                  IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 12),
+                  IsMovValueFromStack(llvm::X86::VMOVDQUrm, llvm::X86::XMM0),
+                  IsStackDeallocate(16)));
+}
+
+TEST_F(Core2Avx512TargetTest, SetRegToVR128Value_Use_VMOVDQU32Z128rm) {
+  EXPECT_THAT(
+      setRegTo(llvm::X86::XMM0,
+               APInt(128, "11112222333344445555666677778888", 16)),
+      ElementsAre(
+          IsStackAllocate(16),
+          IsMovValueToStack(llvm::X86::MOV32mi, 0x77778888UL, 0),
+          IsMovValueToStack(llvm::X86::MOV32mi, 0x55556666UL, 4),
+          IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 8),
+          IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 12),
+          IsMovValueFromStack(llvm::X86::VMOVDQU32Z128rm, llvm::X86::XMM0),
+          IsStackDeallocate(16)));
+}
+
+TEST_F(Core2AvxTargetTest, SetRegToVR256Value_Use_VMOVDQUYrm) {
+  const char ValueStr[] =
+      "1111111122222222333333334444444455555555666666667777777788888888";
+  EXPECT_THAT(setRegTo(llvm::X86::YMM0, APInt(256, ValueStr, 16)),
+              ElementsAreArray(
+                  {IsStackAllocate(32),
+                   IsMovValueToStack(llvm::X86::MOV32mi, 0x88888888UL, 0),
+                   IsMovValueToStack(llvm::X86::MOV32mi, 0x77777777UL, 4),
+                   IsMovValueToStack(llvm::X86::MOV32mi, 0x66666666UL, 8),
+                   IsMovValueToStack(llvm::X86::MOV32mi, 0x55555555UL, 12),
+                   IsMovValueToStack(llvm::X86::MOV32mi, 0x44444444UL, 16),
+                   IsMovValueToStack(llvm::X86::MOV32mi, 0x33333333UL, 20),
+                   IsMovValueToStack(llvm::X86::MOV32mi, 0x22222222UL, 24),
+                   IsMovValueToStack(llvm::X86::MOV32mi, 0x11111111UL, 28),
+                   IsMovValueFromStack(llvm::X86::VMOVDQUYrm, llvm::X86::YMM0),
+                   IsStackDeallocate(32)}));
+}
+
+TEST_F(Core2Avx512TargetTest, SetRegToVR256Value_Use_VMOVDQU32Z256rm) {
+  const char ValueStr[] =
+      "1111111122222222333333334444444455555555666666667777777788888888";
+  EXPECT_THAT(
+      setRegTo(llvm::X86::YMM0, APInt(256, ValueStr, 16)),
+      ElementsAreArray(
+          {IsStackAllocate(32),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0x88888888UL, 0),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0x77777777UL, 4),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0x66666666UL, 8),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0x55555555UL, 12),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0x44444444UL, 16),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0x33333333UL, 20),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0x22222222UL, 24),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0x11111111UL, 28),
+           IsMovValueFromStack(llvm::X86::VMOVDQU32Z256rm, llvm::X86::YMM0),
+           IsStackDeallocate(32)}));
+}
+
+TEST_F(Core2Avx512TargetTest, SetRegToVR512Value) {
+  const char ValueStr[] =
+      "1111111122222222333333334444444455555555666666667777777788888888"
+      "99999999AAAAAAAABBBBBBBBCCCCCCCCDDDDDDDDEEEEEEEEFFFFFFFF00000000";
+  EXPECT_THAT(
+      setRegTo(llvm::X86::ZMM0, APInt(512, ValueStr, 16)),
+      ElementsAreArray(
+          {IsStackAllocate(64),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0x00000000UL, 0),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0xFFFFFFFFUL, 4),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0xEEEEEEEEUL, 8),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0xDDDDDDDDUL, 12),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0xCCCCCCCCUL, 16),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0xBBBBBBBBUL, 20),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0xAAAAAAAAUL, 24),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0x99999999UL, 28),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0x88888888UL, 32),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0x77777777UL, 36),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0x66666666UL, 40),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0x55555555UL, 44),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0x44444444UL, 48),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0x33333333UL, 52),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0x22222222UL, 56),
+           IsMovValueToStack(llvm::X86::MOV32mi, 0x11111111UL, 60),
+           IsMovValueFromStack(llvm::X86::VMOVDQU32Zrm, llvm::X86::ZMM0),
+           IsStackDeallocate(64)}));
+}
+
+TEST_F(Core2TargetTest, SetRegToST0_32Bits) {
+  EXPECT_THAT(
+      setRegTo(llvm::X86::ST0, APInt(32, 0x11112222ULL)),
+      ElementsAre(IsStackAllocate(4),
+                  IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 0),
+                  OpcodeIs(llvm::X86::LD_F32m), IsStackDeallocate(4)));
+}
+
+TEST_F(Core2TargetTest, SetRegToST1_32Bits) {
+  const MCInst CopySt0ToSt1 =
+      llvm::MCInstBuilder(llvm::X86::ST_Frr).addReg(llvm::X86::ST1);
+  EXPECT_THAT(
+      setRegTo(llvm::X86::ST1, APInt(32, 0x11112222ULL)),
+      ElementsAre(IsStackAllocate(4),
+                  IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 0),
+                  OpcodeIs(llvm::X86::LD_F32m), CopySt0ToSt1,
+                  IsStackDeallocate(4)));
+}
+
+TEST_F(Core2TargetTest, SetRegToST0_64Bits) {
+  EXPECT_THAT(
+      setRegTo(llvm::X86::ST0, APInt(64, 0x1111222233334444ULL)),
+      ElementsAre(IsStackAllocate(8),
+                  IsMovValueToStack(llvm::X86::MOV32mi, 0x33334444UL, 0),
+                  IsMovValueToStack(llvm::X86::MOV32mi, 0x11112222UL, 4),
+                  OpcodeIs(llvm::X86::LD_F64m), IsStackDeallocate(8)));
+}
+
+TEST_F(Core2TargetTest, SetRegToST0_80Bits) {
+  EXPECT_THAT(
+      setRegTo(llvm::X86::ST0, APInt(80, "11112222333344445555", 16)),
+      ElementsAre(IsStackAllocate(10),
+                  IsMovValueToStack(llvm::X86::MOV32mi, 0x44445555UL, 0),
+                  IsMovValueToStack(llvm::X86::MOV32mi, 0x22223333UL, 4),
+                  IsMovValueToStack(llvm::X86::MOV16mi, 0x1111UL, 8),
+                  OpcodeIs(llvm::X86::LD_F80m), IsStackDeallocate(10)));
 }
 
 } // namespace




More information about the llvm-commits mailing list