[LCSSA] Update unreachable uses with poison.
authorFlorian Hahn <flo@fhahn.com>
Sun, 4 Sep 2022 21:22:36 +0000 (22:22 +0100)
committerFlorian Hahn <flo@fhahn.com>
Sun, 4 Sep 2022 21:26:18 +0000 (22:26 +0100)
Users of LCSSA may not expect non-phi uses when checking the uses
outside a loop, which may cause crashes. This is due to the fact that we
do not update uses in unreachable blocks.

To ensure all reachable uses outside the loop are phis, update uses in
unreachable blocks to use poison in dead code.

Fixes #57508.

llvm/lib/Transforms/Utils/LCSSA.cpp
llvm/test/Transforms/LCSSA/unreachable-use.ll
llvm/test/Transforms/LoopVectorize/lcssa-crashes.ll

index 76f2685..af79dc4 100644 (file)
@@ -107,13 +107,15 @@ bool llvm::formLCSSAForInstructions(SmallVectorImpl<Instruction *> &Worklist,
     if (ExitBlocks.empty())
       continue;
 
-    for (Use &U : I->uses()) {
+    for (Use &U : make_early_inc_range(I->uses())) {
       Instruction *User = cast<Instruction>(U.getUser());
       BasicBlock *UserBB = User->getParent();
 
       // Skip uses in unreachable blocks.
-      if (!DT.isReachableFromEntry(UserBB))
+      if (!DT.isReachableFromEntry(UserBB)) {
+        U.set(PoisonValue::get(I->getType()));
         continue;
+      }
 
       // For practical purposes, we consider that the use in a PHI
       // occurs in the respective predecessor block. For more info,
index 0c70f7a..ea73025 100644 (file)
@@ -42,3 +42,21 @@ bb32:
 bb45:
   unreachable
 }
+
+define void @multiple_unreachable_uses(ptr %A, ptr %B) {
+entry:
+  br label %loop
+
+loop:
+  %gep.A = getelementptr inbounds float, ptr %A, i64 10
+  %gep.B = getelementptr inbounds ptr, ptr %B, i64 20
+  br i1 false, label %exit, label %loop
+
+dead:                 ; No predecessors!
+  %l1 = load float, ptr %gep.A, align 4
+  %l2 = load ptr, ptr %gep.B, align 8
+  br label %exit
+
+exit:
+  ret void
+}
index 6c46654..05d9e02 100644 (file)
@@ -114,3 +114,54 @@ while.end:
   %add58 = add i32 %inc46, 4
   ret void
 }
+
+; Make sure LV doesn't crash on IR where some LCSSA uses are unreachable.
+define i32 @pr57508(ptr %src) {
+; CHECK-LABEL: @pr57508(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
+; CHECK:       vector.ph:
+; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
+; CHECK:       vector.body:
+; CHECK-NEXT:    [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
+; CHECK-NEXT:    [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
+; CHECK-NEXT:    [[TMP0:%.*]] = icmp eq i64 [[INDEX_NEXT]], 2000
+; CHECK-NEXT:    br i1 [[TMP0]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]]
+; CHECK:       middle.block:
+; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i64 2001, 2000
+; CHECK-NEXT:    br i1 [[CMP_N]], label [[LOOP_EXIT:%.*]], label [[SCALAR_PH]]
+; CHECK:       scalar.ph:
+; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i64 [ 2000, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    [[BC_RESUME_VAL1:%.*]] = phi i32 [ 2000, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY]] ]
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ]
+; CHECK-NEXT:    [[LOCAL:%.*]] = phi i32 [ [[LOCAL_NEXT:%.*]], [[LOOP]] ], [ [[BC_RESUME_VAL1]], [[SCALAR_PH]] ]
+; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
+; CHECK-NEXT:    [[LOCAL_NEXT]] = add i32 [[LOCAL]], 1
+; CHECK-NEXT:    [[EC:%.*]] = icmp eq i64 [[IV]], 2000
+; CHECK-NEXT:    br i1 [[EC]], label [[LOOP_EXIT]], label [[LOOP]], !llvm.loop [[LOOP5:![0-9]+]]
+; CHECK:       loop.exit:
+; CHECK-NEXT:    unreachable
+; CHECK:       bb:
+; CHECK-NEXT:    [[LOCAL_USE:%.*]] = add i32 poison, 1
+; CHECK-NEXT:    ret i32 [[LOCAL_USE]]
+;
+entry:
+  br label %loop
+
+loop:
+  %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ]
+  %local = phi i32 [ %local.next, %loop ], [ 0, %entry ]
+  %iv.next = add nuw nsw i64 %iv, 1
+  %local.next  = add i32 %local, 1
+  %ec = icmp eq i64 %iv, 2000
+  br i1 %ec, label %loop.exit, label %loop
+
+loop.exit:
+  unreachable
+
+bb:
+  %local.use = add i32 %local, 1
+  ret i32 %local.use
+}