]> granicus.if.org Git - llvm/commitdiff
[x86] Fix an even stranger corner case where we have multiple levels of
authorChandler Carruth <chandlerc@gmail.com>
Sat, 19 Aug 2017 23:35:50 +0000 (23:35 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Sat, 19 Aug 2017 23:35:50 +0000 (23:35 +0000)
cmov self-refrencing.

Pointed out by Amjad Aboud in code review, test case minorly simplified
from the one he posted.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@311267 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86CmovConversion.cpp
test/CodeGen/X86/x86-cmov-converter.ll

index 46285b994f52236047fbff09f35cad27ed8c3a39..c2e37b8f7f372284f25d9c4ab886042c4d77e600 100644 (file)
@@ -646,9 +646,17 @@ void X86CmovConverterPass::convertCmovInstsToBranches(
     // Skip any CMOVs in this group which don't load from memory.
     if (!MI.mayLoad()) {
       // Remember the false-side register input.
-      FalseBBRegRewriteTable[MI.getOperand(0).getReg()] =
+      unsigned FalseReg =
           MI.getOperand(X86::getCondFromCMovOpc(MI.getOpcode()) == CC ? 1 : 2)
               .getReg();
+      // Walk back through any intermediate cmovs referenced.
+      for (;;) {
+        auto FRIt = FalseBBRegRewriteTable.find(FalseReg);
+        if (FRIt == FalseBBRegRewriteTable.end())
+          break;
+        FalseReg = FRIt->second;
+      }
+      FalseBBRegRewriteTable[MI.getOperand(0).getReg()] = FalseReg;
       continue;
     }
 
index ccd8dc9a304a96e4e5386b67be3927918cbdbdcd..cdb8894bfd91656c89afc6baaeaa5761778ca399 100644 (file)
@@ -428,7 +428,8 @@ entry:
 }
 
 ; Test that we can convert a group of cmovs where only one has a memory
-; operand and where that memory operand's registers come from a prior cmov in the group.
+; operand and where that memory operand's registers come from a prior cmov in
+; the group.
 define i32 @test_cmov_memoperand_in_group_reuse_for_addr(i32 %a, i32 %b, i32* %x, i32* %y) #0 {
 ; CHECK-LABEL: test_cmov_memoperand_in_group_reuse_for_addr:
 entry:
@@ -467,4 +468,25 @@ entry:
   ret i32 %z
 }
 
+; Test that we can convert a group of cmovs where only one has a memory
+; operand and where that memory operand's registers come from a prior cmov and
+; where that cmov gets *its* input from a prior cmov in the group.
+define i32 @test_cmov_memoperand_in_group_reuse_for_addr3(i32 %a, i32 %b, i32* %x, i32* %y, i32* %z) #0 {
+; CHECK-LABEL: test_cmov_memoperand_in_group_reuse_for_addr3:
+entry:
+  %cond = icmp ugt i32 %a, %b
+; CHECK:         cmpl
+  %p = select i1 %cond, i32* %x, i32* %y
+  %p2 = select i1 %cond, i32* %z, i32* %p
+  %load = load i32, i32* %p2
+  %r = select i1 %cond, i32 %a, i32 %load
+; CHECK-NOT:     cmov
+; CHECK:         ja [[FALSE_BB:.*]]
+; CHECK:         movl (%r{{..}}), %[[R:.*]]
+; CHECK:       [[FALSE_BB]]:
+; CHECK:         movl %[[R]], %eax
+; CHECK:         retq
+  ret i32 %r
+}
+
 attributes #0 = {"target-cpu"="x86-64"}