[PATCH] D19211: Teach ValueTracking that compare-and-branch on poison is UB

Sanjoy Das via llvm-commits llvm-commits at lists.llvm.org
Sun Apr 17 20:51:36 PDT 2016


sanjoy created this revision.
sanjoy added reviewers: broune, bjarke.roune, majnemer.
sanjoy added a subscriber: llvm-commits.
Herald added a subscriber: mcrosier.

This lets us optimize the interesting case of

  do {
    I = PHI(I_Begin, I_Next);
    I_Next = I +nsw 1
    Use(Sext(I_Next))
  } while (I_Next < N);

Note: we "already get" the above case, but the way we do so is
incorrect.  Making our poison value analysis smarter about this will let
us get rid of the buggy behavior (in a later patch) without regressing
too much performance across the board.

http://reviews.llvm.org/D19211

Files:
  lib/Analysis/ValueTracking.cpp
  test/Analysis/ScalarEvolution/flags-from-poison.ll

Index: test/Analysis/ScalarEvolution/flags-from-poison.ll
===================================================================
--- test/Analysis/ScalarEvolution/flags-from-poison.ll
+++ test/Analysis/ScalarEvolution/flags-from-poison.ll
@@ -116,6 +116,55 @@
   ret void
 }
 
+; Example where an add should get the nuw flag: the UB-on-poison in
+; this example is not due to a memory operation, but due to a
+; compare-and-branch.
+define void @test-add-nuw-from-icmp-and-branch(
+    float* %input, i32 %offset, i32 %numIterations) {
+; CHECK-LABEL: @test-add-nuw-from-icmp-and-branch
+entry:
+  br label %loop
+loop:
+  %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
+
+; CHECK: %index32 =
+; CHECK: --> {%offset,+,1}<nuw>
+  %index32 = add nuw i32 %i, %offset
+
+  %nexti = add nuw i32 %i, 1
+  %exitcond = icmp eq i32 %index32, %numIterations
+  br i1 %exitcond, label %exit, label %loop
+
+exit:
+  ret void
+}
+
+; Like @test-add-nuw-from-icmp-and-branch, but we're testing just the
+; icmp logic here (this pattern is unlikely to appear in real code).
+define void @test-add-nuw-from-icmp(float* %input, i32 %offset,
+                                    i32 %numIterations) {
+; CHECK-LABEL: @test-add-nuw-from-icmp
+entry:
+  br label %loop
+loop:
+  %i = phi i32 [ %nexti, %loop ], [ 0, %entry ]
+
+; CHECK: %index32 =
+; CHECK: --> {%offset,+,1}<nuw>
+  %index32 = add nuw i32 %i, %offset
+  %cmp = icmp sgt i32 %index32, 0
+  %cmp.idx = sext i1 %cmp to i32
+
+  %ptr = getelementptr inbounds float, float* %input, i32 %cmp.idx
+  %nexti = add nuw i32 %i, 1
+  %f = load float, float* %ptr, align 4
+  %exitcond = icmp eq i32 %nexti, %numIterations
+  br i1 %exitcond, label %exit, label %loop
+
+exit:
+  ret void
+}
+
 ; With no load to trigger UB from poison, we cannot infer nsw.
 define void @test-add-no-load(float* %input, i32 %offset, i32 %numIterations) {
 ; CHECK-LABEL: @test-add-no-load
Index: lib/Analysis/ValueTracking.cpp
===================================================================
--- lib/Analysis/ValueTracking.cpp
+++ lib/Analysis/ValueTracking.cpp
@@ -3371,6 +3371,11 @@
       return false;
     }
 
+    case Instruction::ICmp:
+      // Comparing poison with any value yields poison.  This is why, for
+      // instance, x s< (x +nsw 1) can be folded to true.
+      return true;
+
     case Instruction::GetElementPtr:
       // A GEP implicitly represents a sequence of additions, subtractions,
       // truncations, sign extensions and multiplications. The multiplications
@@ -3405,6 +3410,11 @@
     case Instruction::SRem:
       return I->getOperand(1);
 
+    case Instruction::Br:
+      if (cast<BranchInst>(I)->isConditional())
+        return cast<BranchInst>(I)->getCondition();
+      return nullptr;
+
     default:
       return nullptr;
   }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D19211.54028.patch
Type: text/x-patch
Size: 2797 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160418/736d77e7/attachment.bin>


More information about the llvm-commits mailing list