[llvm] r260705 - [LVI] Exploit nsw/nuw when computing constant ranges

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 12 11:05:17 PST 2016


Author: reames
Date: Fri Feb 12 13:05:16 2016
New Revision: 260705

URL: http://llvm.org/viewvc/llvm-project?rev=260705&view=rev
Log:
[LVI] Exploit nsw/nuw when computing constant ranges

As the title says. Modelled after similar code in SCEV.

This is useful when analysing induction variables in loops which have been canonicalized by other passes. I wrote the tests as non-loops specifically to avoid the generality introduced in http://reviews.llvm.org/D17174. While that can handle many induction variables without *needing* to exploit nsw, there's no reason not to use it if we've already proven it.

Differential Revision: http://reviews.llvm.org/D17177


Modified:
    llvm/trunk/lib/Analysis/LazyValueInfo.cpp
    llvm/trunk/test/Transforms/CorrelatedValuePropagation/basic.ll

Modified: llvm/trunk/lib/Analysis/LazyValueInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/LazyValueInfo.cpp?rev=260705&r1=260704&r2=260705&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/LazyValueInfo.cpp (original)
+++ llvm/trunk/lib/Analysis/LazyValueInfo.cpp Fri Feb 12 13:05:16 2016
@@ -961,6 +961,27 @@ bool LazyValueInfoCache::solveBlockValue
   if (isa<BinaryOperator>(BBI)) {
     if (ConstantInt *RHS = dyn_cast<ConstantInt>(BBI->getOperand(1))) {
       RHSRange = ConstantRange(RHS->getValue());
+
+      // Try to use information about wrap flags to refine the range LHS can
+      // legally have.  This is a slightly weird way to implement forward
+      // propagation over overflowing instructions, but it seems to be the only
+      // clean one we have.  NOTE: Because we may have speculated the
+      // instruction, we can't constrain other uses of LHS even if they would
+      // seem to be equivelent control dependent with this op.
+      if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(BBI)) {
+        unsigned WrapKind = 0;
+        if (OBO->hasNoSignedWrap())
+          WrapKind |= OverflowingBinaryOperator::NoSignedWrap;
+        if (OBO->hasNoUnsignedWrap())
+          WrapKind |= OverflowingBinaryOperator::NoUnsignedWrap;
+
+        if (WrapKind) {
+          auto OpCode = static_cast<Instruction::BinaryOps>(BBI->getOpcode());
+          auto NoWrapCR =
+            ConstantRange::makeNoWrapRegion(OpCode, RHS->getValue(), WrapKind);
+          LHSRange = LHSRange.intersectWith(NoWrapCR);
+        }
+      }
     } else {
       BBLV.markOverdefined();
       return true;

Modified: llvm/trunk/test/Transforms/CorrelatedValuePropagation/basic.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/CorrelatedValuePropagation/basic.ll?rev=260705&r1=260704&r2=260705&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/CorrelatedValuePropagation/basic.ll (original)
+++ llvm/trunk/test/Transforms/CorrelatedValuePropagation/basic.ll Fri Feb 12 13:05:16 2016
@@ -199,3 +199,58 @@ out:
 next:
   ret void
 }
+
+; Can we use nsw in LVI to prove lack of overflow?
+define i1 @add_nsw(i32 %s) {
+; CHECK-LABEL: @add_nsw(
+entry:
+  %cmp = icmp sgt i32 %s, 0
+  br i1 %cmp, label %positive, label %out
+
+positive:
+  %add = add nsw i32 %s, 1
+  %res = icmp sgt i32 %add, 0
+  br label %next
+next:
+; CHECK: next:
+; CHECK: ret i1 true
+  ret i1 %res
+out:
+  ret i1 false
+}
+
+define i1 @add_nsw2(i32 %s) {
+; CHECK-LABEL: @add_nsw2(
+entry:
+  %cmp = icmp sge i32 %s, 0
+  br i1 %cmp, label %positive, label %out
+
+positive:
+  %add = add nsw i32 %s, 1
+  %res = icmp ne i32 %add, 0
+  br label %next
+next:
+; CHECK: next:
+; CHECK: ret i1 true
+  ret i1 %res
+out:
+  ret i1 false
+}
+
+define i1 @add_nuw(i32 %s) {
+; CHECK-LABEL: @add_nuw(
+entry:
+  %cmp = icmp ult i32 %s, 400
+  br i1 %cmp, label %positive, label %out
+
+positive:
+  %add = add nsw i32 %s, 1
+  %res = icmp ne i32 %add, -100
+  br label %next
+next:
+; CHECK: next:
+; CHECK: ret i1 true
+  ret i1 %res
+out:
+  ret i1 false
+}




More information about the llvm-commits mailing list