diff --git a/llvm/lib/Transforms/Utils/LCSSA.cpp b/llvm/lib/Transforms/Utils/LCSSA.cpp index 76f2685062698..af79dc456ea6d 100644 --- a/llvm/lib/Transforms/Utils/LCSSA.cpp +++ b/llvm/lib/Transforms/Utils/LCSSA.cpp @@ -107,13 +107,15 @@ bool llvm::formLCSSAForInstructions(SmallVectorImpl &Worklist, if (ExitBlocks.empty()) continue; - for (Use &U : I->uses()) { + for (Use &U : make_early_inc_range(I->uses())) { Instruction *User = cast(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, diff --git a/llvm/test/Transforms/LCSSA/unreachable-use.ll b/llvm/test/Transforms/LCSSA/unreachable-use.ll index 0c70f7a3ef9b8..ea730257daa1a 100644 --- a/llvm/test/Transforms/LCSSA/unreachable-use.ll +++ b/llvm/test/Transforms/LCSSA/unreachable-use.ll @@ -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 +} diff --git a/llvm/test/Transforms/LoopVectorize/lcssa-crashes.ll b/llvm/test/Transforms/LoopVectorize/lcssa-crashes.ll index 6c466540e7089..05d9e027fc223 100644 --- a/llvm/test/Transforms/LoopVectorize/lcssa-crashes.ll +++ b/llvm/test/Transforms/LoopVectorize/lcssa-crashes.ll @@ -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 +}