]> granicus.if.org Git - llvm/commitdiff
[IndVarSimplify] Fixup nowrap flags during LFTR (PR31181)
authorNikita Popov <nikita.ppv@gmail.com>
Sat, 1 Jun 2019 09:40:18 +0000 (09:40 +0000)
committerNikita Popov <nikita.ppv@gmail.com>
Sat, 1 Jun 2019 09:40:18 +0000 (09:40 +0000)
Fix for https://bugs.llvm.org/show_bug.cgi?id=31181 and partial fix
for LFTR poison handling issues in general.

When LFTR moves a condition from pre-inc to post-inc, it may now
depend on value that is poison due to nowrap flags. To avoid this,
we clear any nowrap flag that SCEV cannot prove for the post-inc
addrec.

Additionally, LFTR may switch to a different IV that is dynamically
dead and as such may be arbitrarily poison. This patch will correct
nowrap flags in some but not all cases where this happens. This is
related to the adoption of IR nowrap flags for the pre-inc addrec.
(See some of the switch_to_different_iv tests, where flags are not
dropped or insufficiently dropped.)

Finally, there are likely similar issues with the handling of GEP
inbounds, but we don't have a test case for this yet.

Differential Revision: https://reviews.llvm.org/D60935

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@362292 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/IndVarSimplify.cpp
test/Transforms/IndVarSimplify/lftr-pr31181.ll

index 0542eca0e78e0a4bd24b2886e61a7be1b0cfb3fd..0261b68e97ab0b4b951c931e1c9cfddf02e98c3c 100644 (file)
@@ -2372,6 +2372,27 @@ linearFunctionTestReplace(Loop *L, const SCEV *BackedgeTakenCount,
     CmpIndVar = IndVar->getIncomingValueForBlock(L->getExitingBlock());
   }
 
+  // It may be necessary to drop nowrap flags on the incrementing instruction
+  // if either LFTR moves from a pre-inc check to a post-inc check (in which
+  // case the increment might have previously been poison on the last iteration
+  // only) or if LFTR switches to a different IV that was previously dynamically
+  // dead (and as such may be arbitrarily poison). We remove any nowrap flags
+  // that SCEV didn't infer for the post-inc addrec (even if we use a pre-inc
+  // check), because the pre-inc addrec flags may be adopted from the original
+  // instruction, while SCEV has to explicitly prove the post-inc nowrap flags.
+  // TODO: This handling is inaccurate for one case: If we switch to a
+  // dynamically dead IV that wraps on the first loop iteration only, which is
+  // not covered by the post-inc addrec. (If the new IV was not dynamically
+  // dead, it could not be poison on the first iteration in the first place.)
+  Value *IncVar = IndVar->getIncomingValueForBlock(L->getLoopLatch());
+  if (auto *BO = dyn_cast<BinaryOperator>(IncVar)) {
+    const SCEVAddRecExpr *AR = cast<SCEVAddRecExpr>(SE->getSCEV(IncVar));
+    if (BO->hasNoUnsignedWrap())
+      BO->setHasNoUnsignedWrap(AR->hasNoUnsignedWrap());
+    if (BO->hasNoSignedWrap())
+      BO->setHasNoSignedWrap(AR->hasNoSignedWrap());
+  }
+
   Value *ExitCnt = genLoopLimit(IndVar, IVCount, L, Rewriter, SE);
   assert(ExitCnt->getType()->isPointerTy() ==
              IndVar->getType()->isPointerTy() &&
index 8316d8dbce2fe4a4218d4252ca56fbb527906fe7..6032b1d13cef023297b1936e2d0914dfdeb7cbf2 100644 (file)
@@ -15,7 +15,7 @@ define i32 @test_drop_nuw() {
 ; CHECK:       loop:
 ; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi i32 [ -2, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[LOOP]] ]
 ; CHECK-NEXT:    store i32 [[STOREMERGE]], i32* @a
-; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[STOREMERGE]], 1
+; CHECK-NEXT:    [[INC]] = add nsw i32 [[STOREMERGE]], 1
 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[INC]], 0
 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
 ; CHECK:       exit:
@@ -42,7 +42,7 @@ define i32 @test_drop_nsw() {
 ; CHECK:       loop:
 ; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[LOOP]] ]
 ; CHECK-NEXT:    store i32 [[STOREMERGE]], i32* @a
-; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[STOREMERGE]], 1
+; CHECK-NEXT:    [[INC]] = add nuw i32 [[STOREMERGE]], 1
 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[INC]], -2147483648
 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT:%.*]]
 ; CHECK:       exit:
@@ -155,7 +155,7 @@ define i32 @test_drop_nsw_var_lim(i32 %lim) {
 ; CHECK:       loop:
 ; CHECK-NEXT:    [[STOREMERGE:%.*]] = phi i32 [ [[INC:%.*]], [[LOOP]] ], [ 0, [[LOOP_PREHEADER]] ]
 ; CHECK-NEXT:    store i32 [[STOREMERGE]], i32* @a
-; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[STOREMERGE]], 1
+; CHECK-NEXT:    [[INC]] = add nuw i32 [[STOREMERGE]], 1
 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[INC]], [[TMP0]]
 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[LOOP]], label [[EXIT_LOOPEXIT:%.*]]
 ; CHECK:       exit.loopexit:
@@ -194,7 +194,7 @@ define i32 @switch_to_different_iv_post_inc(i32* %ptr, i1 %always_false) {
 ; CHECK-NEXT:    br label [[ALWAYS_TAKEN]]
 ; CHECK:       always_taken:
 ; CHECK-NEXT:    [[IV_INC]] = add nsw i32 [[IV]], 1
-; CHECK-NEXT:    [[IV2_INC]] = add nuw nsw i32 [[IV2]], 1
+; CHECK-NEXT:    [[IV2_INC]] = add nuw i32 [[IV2]], 1
 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV2_INC]], -2147483627
 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_COND]], label [[FOR_END:%.*]]
 ; CHECK:       for.end:
@@ -242,7 +242,7 @@ define i32 @switch_to_different_iv_pre_inc(i32* %ptr, i1 %always_false) {
 ; CHECK-NEXT:    br label [[ALWAYS_TAKEN]]
 ; CHECK:       always_taken:
 ; CHECK-NEXT:    [[IV_INC]] = add nsw i32 [[IV]], 1
-; CHECK-NEXT:    [[IV2_INC]] = add nuw nsw i32 [[IV2]], 1
+; CHECK-NEXT:    [[IV2_INC]] = add nuw i32 [[IV2]], 1
 ; CHECK-NEXT:    br label [[FOR_COND]]
 ; CHECK:       for.end:
 ; CHECK-NEXT:    ret i32 0
@@ -329,7 +329,7 @@ define i32 @switch_to_different_iv_second_poison(i32* %ptr, i1 %always_false) {
 ; CHECK-NEXT:    store volatile i32 [[IV2]], i32* [[PTR]]
 ; CHECK-NEXT:    br label [[ALWAYS_TAKEN]]
 ; CHECK:       always_taken:
-; CHECK-NEXT:    [[IV2_INC]] = add nuw nsw i32 [[IV2]], 1
+; CHECK-NEXT:    [[IV2_INC]] = add nsw i32 [[IV2]], 1
 ; CHECK-NEXT:    [[IV_INC]] = add nsw i32 [[IV]], 1
 ; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp ne i32 [[IV2_INC]], -2147483629
 ; CHECK-NEXT:    br i1 [[EXITCOND]], label [[FOR_COND]], label [[FOR_END:%.*]]