[llvm-commits] [llvm] r146822 - in /llvm/trunk: lib/Transforms/Utils/SimplifyCFG.cpp test/Transforms/SimplifyCFG/PredictNestedBranch.ll
Peter Cooper
peter_cooper at apple.com
Wed Jan 4 13:24:32 PST 2012
Hi Duncan
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.
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.
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
More information about the llvm-commits
mailing list