[llvm-exegesis] Fix support for LEA64_32r.
authorClement Courbet <courbet@google.com>
Tue, 21 Jan 2020 10:58:51 +0000 (11:58 +0100)
committerClement Courbet <courbet@google.com>
Tue, 21 Jan 2020 12:58:23 +0000 (13:58 +0100)
Summary:
Add unit test to show the issue: We must select an *aliasing* output
register, not the exact register.

Reviewers: gchatelet

Subscribers: tschuett, mstojanovic, llvm-commits

Tags: #llvm

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

llvm/test/tools/llvm-exegesis/X86/latency-LEA64_32r.s [new file with mode: 0644]
llvm/tools/llvm-exegesis/lib/X86/Target.cpp

diff --git a/llvm/test/tools/llvm-exegesis/X86/latency-LEA64_32r.s b/llvm/test/tools/llvm-exegesis/X86/latency-LEA64_32r.s
new file mode 100644 (file)
index 0000000..40b6db9
--- /dev/null
@@ -0,0 +1,16 @@
+# RUN: llvm-exegesis -mode=latency -opcode-name=LEA64_32r -repetition-mode=duplicate -max-configs-per-opcode=2 | FileCheck %s
+# RUN: llvm-exegesis -mode=latency -opcode-name=LEA64_32r -repetition-mode=loop -max-configs-per-opcode=2 | FileCheck %s
+
+CHECK:      ---
+CHECK-NEXT: mode: latency
+CHECK-NEXT: key:
+CHECK-NEXT:   instructions:
+CHECK-NEXT:     LEA64_32r
+CHECK-NEXT: config: '0(%[[REG1:[A-Z0-9]+]], %[[REG1]], 1)'
+
+CHECK:      ---
+CHECK-NEXT: mode: latency
+CHECK-NEXT: key:
+CHECK-NEXT:   instructions:
+CHECK-NEXT:     LEA64_32r
+CHECK-NEXT: config: '42(%[[REG2:[A-Z0-9]+]], %[[REG2]], 1)'
index 47b14f2..c739eae 100644 (file)
@@ -188,7 +188,8 @@ static void setMemOp(InstructionTemplate &IT, int OpIdx,
 static Expected<std::vector<CodeTemplate>> generateLEATemplatesCommon(
     const Instruction &Instr, const BitVector &ForbiddenRegisters,
     const LLVMState &State, const SnippetGenerator::Options &Opts,
-    std::function<unsigned(unsigned, unsigned)> GetDestReg) {
+    std::function<void(unsigned, unsigned, BitVector &CandidateDestRegs)>
+        RestrictDestRegs) {
   assert(Instr.Operands.size() == 6 && "invalid LEA");
   assert(X86II::getMemoryOperandNo(Instr.Description.TSFlags) == 1 &&
          "invalid LEA");
@@ -222,8 +223,15 @@ static Expected<std::vector<CodeTemplate>> generateLEATemplatesCommon(
           // SegmentReg must be 0 for LEA.
           setMemOp(IT, 5, MCOperand::createReg(0));
 
-          // Output reg is selected by the caller.
-          setMemOp(IT, 0, MCOperand::createReg(GetDestReg(BaseReg, IndexReg)));
+          // Output reg candidates are selected by the caller.
+          auto PossibleDestRegsNow = PossibleDestRegs;
+          RestrictDestRegs(BaseReg, IndexReg, PossibleDestRegsNow);
+          assert(PossibleDestRegsNow.set_bits().begin() !=
+                     PossibleDestRegsNow.set_bits().end() &&
+                 "no remaining registers");
+          setMemOp(
+              IT, 0,
+              MCOperand::createReg(*PossibleDestRegsNow.set_bits().begin()));
 
           CodeTemplate CT;
           CT.Instructions.push_back(std::move(IT));
@@ -261,12 +269,15 @@ X86SerialSnippetGenerator::generateCodeTemplates(
   // LEA gets special attention.
   const auto Opcode = Instr.Description.getOpcode();
   if (Opcode == X86::LEA64r || Opcode == X86::LEA64_32r) {
-    return generateLEATemplatesCommon(Instr, ForbiddenRegisters, State, Opts,
-                                      [](unsigned BaseReg, unsigned IndexReg) {
-                                        // We just select the same base and
-                                        // output register.
-                                        return BaseReg;
-                                      });
+    return generateLEATemplatesCommon(
+        Instr, ForbiddenRegisters, State, Opts,
+        [this](unsigned BaseReg, unsigned IndexReg,
+               BitVector &CandidateDestRegs) {
+          // We just select a destination register that aliases the base
+          // register.
+          CandidateDestRegs &=
+              State.getRATC().getRegister(BaseReg).aliasedBits();
+        });
   }
 
   switch (getX86FPFlags(Instr)) {
@@ -312,22 +323,15 @@ X86ParallelSnippetGenerator::generateCodeTemplates(
   // LEA gets special attention.
   const auto Opcode = Instr.Description.getOpcode();
   if (Opcode == X86::LEA64r || Opcode == X86::LEA64_32r) {
-    // Any destination register that is not used for adddressing is fine.
-    auto PossibleDestRegs =
-        Instr.Operands[0].getRegisterAliasing().sourceBits();
-    remove(PossibleDestRegs, ForbiddenRegisters);
     return generateLEATemplatesCommon(
         Instr, ForbiddenRegisters, State, Opts,
-        [this, &PossibleDestRegs](unsigned BaseReg, unsigned IndexReg) {
-          auto PossibleDestRegsNow = PossibleDestRegs;
-          remove(PossibleDestRegsNow,
+        [this](unsigned BaseReg, unsigned IndexReg,
+               BitVector &CandidateDestRegs) {
+          // Any destination register that is not used for addressing is fine.
+          remove(CandidateDestRegs,
                  State.getRATC().getRegister(BaseReg).aliasedBits());
-          remove(PossibleDestRegsNow,
+          remove(CandidateDestRegs,
                  State.getRATC().getRegister(IndexReg).aliasedBits());
-          assert(PossibleDestRegsNow.set_bits().begin() !=
-                     PossibleDestRegsNow.set_bits().end() &&
-                 "no remaining registers");
-          return *PossibleDestRegsNow.set_bits().begin();
         });
   }