[llvm-commits] [llvm] r146822 - in /llvm/trunk: lib/Transforms/Utils/SimplifyCFG.cpp test/Transforms/SimplifyCFG/PredictNestedBranch.ll
Peter Cooper
peter_cooper at apple.com
Thu Jan 5 10:27:51 PST 2012
Hi Duncan
Thanks for this. I might not have time to try it out to measure performance for a few days but i'll let you know what i find when i do get time.
Thanks,
Pete
On Jan 5, 2012, at 8:13 AM, Duncan Sands wrote:
> 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
>>
>
> <gvn.eqprop.diff><corvalprop.diff>
More information about the llvm-commits
mailing list