[llvm-commits] [llvm] r146822 - in /llvm/trunk: lib/Transforms/Utils/SimplifyCFG.cpp test/Transforms/SimplifyCFG/PredictNestedBranch.ll

Duncan Sands baldrick at free.fr
Thu Jan 5 08:13:08 PST 2012


Hi Peter,

> I would assume that boosting GVN and replacing all a's with b's in your example, even if not constant would be a good thing.  We might then only have one of them live at a time for example.

I've attached the patch.  As I'm mentioned I'm not sure this is worth doing for
the small improvements it gives (and it can increase register pressure).

> The code in SimplifyCFG is slightly more general in that it can handle other conditions like knowing that 'a<  b' means that 'a>  b' is false and other such combinations.

The CorrelatedValuePropagation pass should also be capable of getting this,
at least with the second attached patch applied.  Unfortunately it doesn't
(I'm not sure why - I never had much luck getting this pass to do anything
useful).

Ciao, Duncan.

>
> Thanks,
> Pete
>
> On Jan 4, 2012, at 12:47 PM, Duncan Sands wrote:
>
>> Hi Peter,
>>
>>> SimplifyCFG now predicts some conditional branches to true or false depending on previous branch on same comparison operands.
>>>
>>> For example,
>>>
>>> if (a == b) {
>>>      if (a>   b) // this is false
>>
>> if b is a constant then GVN will replace all instances of a with b in the
>> if block, resulting in "if (b>  b)" which will then be simplified to false.
>> The GVN code could easily be taught to also handle the case in which b is not
>> a constant.  In fact that's how I first did it, but it didn't result in
>> many improvements, so I didn't think it was worth the (small) compile time
>> cost and so I committed the "constant b only" version instead.  It would be
>> easy to resurrect it.  It only does something useful when the original
>> condition is == (or !=), but since it would replace a by b everywhere in the
>> block it can simplify all kinds of things in the block.  What do you think -
>> worth boosting the GVN code?
>>
>> Ciao, Duncan.
>>
>>>
>>> Fixes some of the issues on<rdar://problem/10554090>
>>>
>>> Added:
>>>      llvm/trunk/test/Transforms/SimplifyCFG/PredictNestedBranch.ll
>>> Modified:
>>>      llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp
>>>
>>> Modified: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp?rev=146822&r1=146821&r2=146822&view=diff
>>> ==============================================================================
>>> --- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp (original)
>>> +++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Sat Dec 17 00:32:38 2011
>>> @@ -12,6 +12,7 @@
>>>   //===----------------------------------------------------------------------===//
>>>
>>>   #define DEBUG_TYPE "simplifycfg"
>>> +#include "llvm/Transforms/Utils/CmpInstAnalysis.h"
>>>   #include "llvm/Transforms/Utils/Local.h"
>>>   #include "llvm/Constants.h"
>>>   #include "llvm/Instructions.h"
>>> @@ -1702,6 +1703,47 @@
>>>       }
>>>     }
>>>
>>> +  // Treat "if (cond1) { if (cond2) {} }" as "cond1&   cond2" and fold.
>>> +  // This gives us the value of what cond2 is given cond1 is already known to
>>> +  // be true.
>>> +  if (ICmpInst *LHS = dyn_cast<ICmpInst>(PBI->getCondition())) {
>>> +    if (ICmpInst *RHS = dyn_cast<ICmpInst>(BI->getCondition())) {
>>> +      ICmpInst::Predicate LHSCC = LHS->getPredicate(),
>>> +      RHSCC = RHS->getPredicate();
>>> +      if (PredicatesFoldable(LHSCC, RHSCC)) {
>>> +        if (LHS->getOperand(0) == RHS->getOperand(1)&&
>>> +            LHS->getOperand(1) == RHS->getOperand(0))
>>> +          LHS->swapOperands();
>>> +        if (LHS->getOperand(0) == RHS->getOperand(0)&&
>>> +            LHS->getOperand(1) == RHS->getOperand(1)&&
>>> +            BB->getSinglePredecessor()) {
>>> +          Value *Op0 = LHS->getOperand(0), *Op1 = LHS->getOperand(1);
>>> +          bool CondIsTrue = PBI->getSuccessor(0) == BB;
>>> +          unsigned LHSCode = getICmpCode(LHS, !CondIsTrue);
>>> +          unsigned RHSCode = getICmpCode(RHS);
>>> +          unsigned Code = LHSCode&   RHSCode;
>>> +
>>> +          Value *ConstantCondition = NULL;
>>> +          // If the resultant code is the same as the LHS code then as that
>>> +          // code is known to be true we can make RHS now be true.
>>> +          if (Code == LHSCode)
>>> +            ConstantCondition = ConstantInt::get(
>>> +                                 CmpInst::makeCmpResultType(LHS->getType()), 1);
>>> +          else {
>>> +            bool isSigned = LHS->isSigned() || RHS->isSigned();
>>> +            CmpInst::Predicate IgnoredNewPred;
>>> +            ConstantCondition = getICmpValue(isSigned, Code, Op0, Op1,
>>> +                                             IgnoredNewPred);
>>> +          }
>>> +          if (ConstantCondition) {
>>> +            RHS->replaceAllUsesWith(ConstantCondition);
>>> +            return true;
>>> +          }
>>> +        }
>>> +      }
>>> +    }
>>> +  }
>>> +
>>>     // If this is a conditional branch in an empty block, and if any
>>>     // predecessors is a conditional branch to one of our destinations,
>>>     // fold the conditions into logical ops and one cond br.
>>>
>>> Added: llvm/trunk/test/Transforms/SimplifyCFG/PredictNestedBranch.ll
>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/PredictNestedBranch.ll?rev=146822&view=auto
>>> ==============================================================================
>>> --- llvm/trunk/test/Transforms/SimplifyCFG/PredictNestedBranch.ll (added)
>>> +++ llvm/trunk/test/Transforms/SimplifyCFG/PredictNestedBranch.ll Sat Dec 17 00:32:38 2011
>>> @@ -0,0 +1,152 @@
>>> +
>>> +; RUN: opt<   %s -simplifycfg -dce -S | FileCheck %s
>>> +
>>> +; Test that when == is true, all 6 comparisons evaluate to true or false
>>> +; ie, a == b implies a>   b is false, but a>= b is true, and so on
>>> +define void @testEqTrue(i32 %a, i32 %b) {
>>> +; CHECK: @testEqTrue
>>> +; CHECK: icmp eq i32 %a, %b
>>> +; CHECK: call void @_Z1gi(i32 0)
>>> +; a == b implies a == b
>>> +; CHECK-NEXT: call void @_Z1gi(i32 1)
>>> +; a == b implies a>= b
>>> +; CHECK-NEXT: call void @_Z1gi(i32 3)
>>> +; a == b implies a<= b
>>> +; CHECK-NEXT: call void @_Z1gi(i32 4)
>>> +; CHECK: ret void
>>> +entry:
>>> +  %cmp = icmp eq i32 %a, %b
>>> +  br i1 %cmp, label %if.then, label %if.end18
>>> +
>>> +if.then:                                          ; preds = %entry
>>> +  call void @_Z1gi(i32 0)
>>> +  %cmp1 = icmp eq i32 %a, %b
>>> +  br i1 %cmp1, label %if.then2, label %if.end
>>> +
>>> +if.then2:                                         ; preds = %if.then
>>> +  call void @_Z1gi(i32 1)
>>> +  br label %if.end
>>> +
>>> +if.end:                                           ; preds = %if.then2, %if.then
>>> +  %cmp3 = icmp ne i32 %a, %b
>>> +  br i1 %cmp3, label %if.then4, label %if.end5
>>> +
>>> +if.then4:                                         ; preds = %if.end
>>> +  call void @_Z1gi(i32 2)
>>> +  br label %if.end5
>>> +
>>> +if.end5:                                          ; preds = %if.then4, %if.end
>>> +  %cmp6 = icmp sge i32 %a, %b
>>> +  br i1 %cmp6, label %if.then7, label %if.end8
>>> +
>>> +if.then7:                                         ; preds = %if.end5
>>> +  call void @_Z1gi(i32 3)
>>> +  br label %if.end8
>>> +
>>> +if.end8:                                          ; preds = %if.then7, %if.end5
>>> +  %cmp9 = icmp sle i32 %a, %b
>>> +  br i1 %cmp9, label %if.then10, label %if.end11
>>> +
>>> +if.then10:                                        ; preds = %if.end8
>>> +  call void @_Z1gi(i32 4)
>>> +  br label %if.end11
>>> +
>>> +if.end11:                                         ; preds = %if.then10, %if.end8
>>> +  %cmp12 = icmp sgt i32 %a, %b
>>> +  br i1 %cmp12, label %if.then13, label %if.end14
>>> +
>>> +if.then13:                                        ; preds = %if.end11
>>> +  call void @_Z1gi(i32 5)
>>> +  br label %if.end14
>>> +
>>> +if.end14:                                         ; preds = %if.then13, %if.end11
>>> +  %cmp15 = icmp slt i32 %a, %b
>>> +  br i1 %cmp15, label %if.then16, label %if.end18
>>> +
>>> +if.then16:                                        ; preds = %if.end14
>>> +  call void @_Z1gi(i32 6)
>>> +  br label %if.end18
>>> +
>>> +if.end18:                                         ; preds = %if.end14, %if.then16, %entry
>>> +  ret void
>>> +}
>>> +
>>> +; Test that when == is false, all 6 comparisons evaluate to true or false
>>> +; ie, a == b implies a>   b is false, but a>= b is true, and so on
>>> +define void @testEqFalse(i32 %a, i32 %b) {
>>> +; CHECK: @testEqFalse
>>> +; CHECK: icmp eq i32 %a, %b
>>> +; CHECK: call void @_Z1gi(i32 0)
>>> +; CHECK-NOT: call void @_Z1gi(i32 1)
>>> +; CHECK-NOT: icmp ne
>>> +; CHECK: call void @_Z1gi(i32 2)
>>> +; CHECK: icmp sge
>>> +; CHECK: call void @_Z1gi(i32 3)
>>> +; CHECK: icmp sle
>>> +; CHECK: call void @_Z1gi(i32 4)
>>> +; CHECK: icmp sgt
>>> +; CHECK: call void @_Z1gi(i32 5)
>>> +; CHECK: icmp slt
>>> +; CHECK: call void @_Z1gi(i32 6)
>>> +; CHECK: ret void
>>> +entry:
>>> +  %cmp = icmp eq i32 %a, %b
>>> +  br i1 %cmp, label %if.then, label %if.else
>>> +
>>> +if.then:                                          ; preds = %entry
>>> +  call void @_Z1gi(i32 0)
>>> +  br label %if.end18
>>> +
>>> +if.else:
>>> +  %cmp1 = icmp eq i32 %a, %b
>>> +  br i1 %cmp1, label %if.then2, label %if.end
>>> +
>>> +if.then2:                                         ; preds = %if.then
>>> +  call void @_Z1gi(i32 1)
>>> +  br label %if.end
>>> +
>>> +if.end:                                           ; preds = %if.then2, %if.then
>>> +  %cmp3 = icmp ne i32 %a, %b
>>> +  br i1 %cmp3, label %if.then4, label %if.end5
>>> +
>>> +if.then4:                                         ; preds = %if.end
>>> +  call void @_Z1gi(i32 2)
>>> +  br label %if.end5
>>> +
>>> +if.end5:                                          ; preds = %if.then4, %if.end
>>> +  %cmp6 = icmp sge i32 %a, %b
>>> +  br i1 %cmp6, label %if.then7, label %if.end8
>>> +
>>> +if.then7:                                         ; preds = %if.end5
>>> +  call void @_Z1gi(i32 3)
>>> +  br label %if.end8
>>> +
>>> +if.end8:                                          ; preds = %if.then7, %if.end5
>>> +  %cmp9 = icmp sle i32 %a, %b
>>> +  br i1 %cmp9, label %if.then10, label %if.end11
>>> +
>>> +if.then10:                                        ; preds = %if.end8
>>> +  call void @_Z1gi(i32 4)
>>> +  br label %if.end11
>>> +
>>> +if.end11:                                         ; preds = %if.then10, %if.end8
>>> +  %cmp12 = icmp sgt i32 %a, %b
>>> +  br i1 %cmp12, label %if.then13, label %if.end14
>>> +
>>> +if.then13:                                        ; preds = %if.end11
>>> +  call void @_Z1gi(i32 5)
>>> +  br label %if.end14
>>> +
>>> +if.end14:                                         ; preds = %if.then13, %if.end11
>>> +  %cmp15 = icmp slt i32 %a, %b
>>> +  br i1 %cmp15, label %if.then16, label %if.end18
>>> +
>>> +if.then16:                                        ; preds = %if.end14
>>> +  call void @_Z1gi(i32 6)
>>> +  br label %if.end18
>>> +
>>> +if.end18:                                         ; preds = %if.end14, %if.then16, %entry
>>> +  ret void
>>> +}
>>> +
>>> +declare void @_Z1gi(i32)
>>>
>>>
>>> _______________________________________________
>>> llvm-commits mailing list
>>> llvm-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>

-------------- next part --------------
A non-text attachment was scrubbed...
Name: gvn.eqprop.diff
Type: text/x-patch
Size: 3262 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20120105/c6331405/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: corvalprop.diff
Type: text/x-patch
Size: 1555 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20120105/c6331405/attachment-0001.bin>


More information about the llvm-commits mailing list