From e12236f216fd10580c830e4cd5c7ec7cd283ee03 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Sat, 19 Aug 2017 23:35:50 +0000 Subject: [PATCH] [x86] Fix an even stranger corner case where we have multiple levels of 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 | 10 +++++++++- test/CodeGen/X86/x86-cmov-converter.ll | 24 +++++++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/lib/Target/X86/X86CmovConversion.cpp b/lib/Target/X86/X86CmovConversion.cpp index 46285b994f5..c2e37b8f7f3 100644 --- a/lib/Target/X86/X86CmovConversion.cpp +++ b/lib/Target/X86/X86CmovConversion.cpp @@ -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; } diff --git a/test/CodeGen/X86/x86-cmov-converter.ll b/test/CodeGen/X86/x86-cmov-converter.ll index ccd8dc9a304..cdb8894bfd9 100644 --- a/test/CodeGen/X86/x86-cmov-converter.ll +++ b/test/CodeGen/X86/x86-cmov-converter.ll @@ -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"} -- 2.50.1