diff options
author | Benjamin Kramer <benny.kra@googlemail.com> | 2012-03-02 15:34:43 +0000 |
---|---|---|
committer | Benjamin Kramer <benny.kra@googlemail.com> | 2012-03-02 15:34:43 +0000 |
commit | d9d80b1dde81b4470300de3775dcc3c841fc4f9a (patch) | |
tree | 7e2d193ad07de0f5aa54f379ca17c1b36cdd1808 /llvm | |
parent | 053384edef757c5fdc7c8d496f1e5b50238ac2df (diff) | |
download | bcm5719-llvm-d9d80b1dde81b4470300de3775dcc3c841fc4f9a.tar.gz bcm5719-llvm-d9d80b1dde81b4470300de3775dcc3c841fc4f9a.zip |
LVI: Recognize the form instcombine canonicalizes range checks into when forming constant ranges.
This could probably be made a lot smarter, but this is a common case and doesn't require LVI to scan a lot
of code. With this change CVP can optimize away the "shift == 0" case in Hashing.h that only gets hit when
"shift" is in a range not containing 0.
llvm-svn: 151919
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/Analysis/LazyValueInfo.cpp | 20 | ||||
-rw-r--r-- | llvm/test/Transforms/CorrelatedValuePropagation/range.ll | 43 |
2 files changed, 59 insertions, 4 deletions
diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp index e1c099e4356..279d6a91ec6 100644 --- a/llvm/lib/Analysis/LazyValueInfo.cpp +++ b/llvm/lib/Analysis/LazyValueInfo.cpp @@ -24,6 +24,7 @@ #include "llvm/Support/CFG.h" #include "llvm/Support/ConstantRange.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/PatternMatch.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/ValueHandle.h" #include "llvm/ADT/DenseSet.h" @@ -31,6 +32,7 @@ #include <map> #include <stack> using namespace llvm; +using namespace PatternMatch; char LazyValueInfo::ID = 0; INITIALIZE_PASS_BEGIN(LazyValueInfo, "lazy-value-info", @@ -795,9 +797,8 @@ bool LazyValueInfoCache::getEdgeValue(Value *Val, BasicBlock *BBFrom, // If the condition of the branch is an equality comparison, we may be // able to infer the value. ICmpInst *ICI = dyn_cast<ICmpInst>(BI->getCondition()); - if (ICI && ICI->getOperand(0) == Val && - isa<Constant>(ICI->getOperand(1))) { - if (ICI->isEquality()) { + if (ICI && isa<Constant>(ICI->getOperand(1))) { + if (ICI->isEquality() && ICI->getOperand(0) == Val) { // We know that V has the RHS constant if this is a true SETEQ or // false SETNE. if (isTrueDest == (ICI->getPredicate() == ICmpInst::ICMP_EQ)) @@ -807,12 +808,23 @@ bool LazyValueInfoCache::getEdgeValue(Value *Val, BasicBlock *BBFrom, return true; } - if (ConstantInt *CI = dyn_cast<ConstantInt>(ICI->getOperand(1))) { + // Recognize the range checking idiom that InstCombine produces. + // (X-C1) u< C2 --> [C1, C1+C2) + ConstantInt *NegOffset = 0; + if (ICI->getPredicate() == ICmpInst::ICMP_ULT) + match(ICI->getOperand(0), m_Add(m_Specific(Val), + m_ConstantInt(NegOffset))); + + ConstantInt *CI = dyn_cast<ConstantInt>(ICI->getOperand(1)); + if (CI && (ICI->getOperand(0) == Val || NegOffset)) { // Calculate the range of values that would satisfy the comparison. ConstantRange CmpRange(CI->getValue(), CI->getValue()+1); ConstantRange TrueValues = ConstantRange::makeICmpRegion(ICI->getPredicate(), CmpRange); + if (NegOffset) // Apply the offset from above. + TrueValues = TrueValues.subtract(NegOffset->getValue()); + // If we're interested in the false dest, invert the condition. if (!isTrueDest) TrueValues = TrueValues.inverse(); diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/range.ll b/llvm/test/Transforms/CorrelatedValuePropagation/range.ll new file mode 100644 index 00000000000..9b70ed200ed --- /dev/null +++ b/llvm/test/Transforms/CorrelatedValuePropagation/range.ll @@ -0,0 +1,43 @@ +; RUN: opt -correlated-propagation -S < %s | FileCheck %s + +declare i32 @foo() + +define i32 @test1(i32 %a) nounwind { + %a.off = add i32 %a, -8 + %cmp = icmp ult i32 %a.off, 8 + br i1 %cmp, label %then, label %else + +then: + %dead = icmp eq i32 %a, 7 + br i1 %dead, label %end, label %else + +else: + ret i32 1 + +end: + ret i32 2 + +; CHECK: @test1 +; CHECK: then: +; CHECK-NEXT: br i1 false, label %end, label %else +} + +define i32 @test2(i32 %a) nounwind { + %a.off = add i32 %a, -8 + %cmp = icmp ult i32 %a.off, 8 + br i1 %cmp, label %then, label %else + +then: + %dead = icmp ugt i32 %a, 15 + br i1 %dead, label %end, label %else + +else: + ret i32 1 + +end: + ret i32 2 + +; CHECK: @test2 +; CHECK: then: +; CHECK-NEXT: br i1 false, label %end, label %else +} |