diff --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp --- a/llvm/lib/Transforms/Scalar/SCCP.cpp +++ b/llvm/lib/Transforms/Scalar/SCCP.cpp @@ -371,7 +371,19 @@ isa(TI)) && "Terminator must be a br, switch or indirectbr"); - if (FeasibleSuccessors.size() == 1) { + if (FeasibleSuccessors.size() == 0) { + // Branch on undef/poison, replace with unreachable. + SmallPtrSet SeenSuccs; + SmallVector Updates; + for (BasicBlock *Succ : successors(BB)) { + Succ->removePredecessor(BB); + if (SeenSuccs.insert(Succ).second) + Updates.push_back({DominatorTree::Delete, BB, Succ}); + } + TI->eraseFromParent(); + new UnreachableInst(BB->getContext(), BB); + DTU.applyUpdatesPermissive(Updates); + } else if (FeasibleSuccessors.size() == 1) { // Replace with an unconditional branch to the only feasible successor. BasicBlock *OnlyFeasibleSuccessor = *FeasibleSuccessors.begin(); SmallVector Updates; diff --git a/llvm/lib/Transforms/Utils/SCCPSolver.cpp b/llvm/lib/Transforms/Utils/SCCPSolver.cpp --- a/llvm/lib/Transforms/Utils/SCCPSolver.cpp +++ b/llvm/lib/Transforms/Utils/SCCPSolver.cpp @@ -1444,22 +1444,19 @@ } } -/// resolvedUndefsIn - While solving the dataflow for a function, we assume -/// that branches on undef values cannot reach any of their successors. -/// However, this is not a safe assumption. After we solve dataflow, this -/// method should be use to handle this. If this returns true, the solver -/// should be rerun. +/// While solving the dataflow for a function, we don't compute a result for +/// operations with an undef operand, to allow undef to be lowered to a +/// constant later. For example, constant folding of "zext i8 undef to i16" +/// would result in "i16 0", and if undef is later lowered to "i8 1", then the +/// zext result would become "i16 1" and would result into an overdefined +/// lattice value once merged with the previous result. Not computing the +/// result of the zext (treating undef the same as unknown) allows us to handle +/// a later undef->constant lowering more optimally. /// -/// This method handles this by finding an unresolved branch and marking it one -/// of the edges from the block as being feasible, even though the condition -/// doesn't say it would otherwise be. This allows SCCP to find the rest of the -/// CFG and only slightly pessimizes the analysis results (by marking one, -/// potentially infeasible, edge feasible). This cannot usefully modify the -/// constraints on the condition of the branch, as that would impact other users -/// of the value. -/// -/// This scan also checks for values that use undefs. It conservatively marks -/// them as overdefined. +/// However, if the operand remains undef when the solver returns, we do need +/// to assign some result to the instruction (otherwise we would treat it as +/// unreachable). For simplicity, we mark any instructions that are still +/// unknown/undef as overdefined. bool SCCPInstVisitor::resolvedUndefsIn(Function &F) { bool MadeChange = false; for (BasicBlock &BB : F) { @@ -1520,91 +1517,6 @@ markOverdefined(&I); MadeChange = true; } - - // Check to see if we have a branch or switch on an undefined value. If so - // we force the branch to go one way or the other to make the successor - // values live. It doesn't really matter which way we force it. - Instruction *TI = BB.getTerminator(); - if (auto *BI = dyn_cast(TI)) { - if (!BI->isConditional()) - continue; - if (!getValueState(BI->getCondition()).isUnknownOrUndef()) - continue; - - // If the input to SCCP is actually branch on undef, fix the undef to - // false. - if (isa(BI->getCondition())) { - BI->setCondition(ConstantInt::getFalse(BI->getContext())); - markEdgeExecutable(&BB, TI->getSuccessor(1)); - MadeChange = true; - continue; - } - - // Otherwise, it is a branch on a symbolic value which is currently - // considered to be undef. Make sure some edge is executable, so a - // branch on "undef" always flows somewhere. - // FIXME: Distinguish between dead code and an LLVM "undef" value. - BasicBlock *DefaultSuccessor = TI->getSuccessor(1); - if (markEdgeExecutable(&BB, DefaultSuccessor)) - MadeChange = true; - - continue; - } - - if (auto *IBR = dyn_cast(TI)) { - // Indirect branch with no successor ?. Its ok to assume it branches - // to no target. - if (IBR->getNumSuccessors() < 1) - continue; - - if (!getValueState(IBR->getAddress()).isUnknownOrUndef()) - continue; - - // If the input to SCCP is actually branch on undef, fix the undef to - // the first successor of the indirect branch. - if (isa(IBR->getAddress())) { - IBR->setAddress(BlockAddress::get(IBR->getSuccessor(0))); - markEdgeExecutable(&BB, IBR->getSuccessor(0)); - MadeChange = true; - continue; - } - - // Otherwise, it is a branch on a symbolic value which is currently - // considered to be undef. Make sure some edge is executable, so a - // branch on "undef" always flows somewhere. - // FIXME: IndirectBr on "undef" doesn't actually need to go anywhere: - // we can assume the branch has undefined behavior instead. - BasicBlock *DefaultSuccessor = IBR->getSuccessor(0); - if (markEdgeExecutable(&BB, DefaultSuccessor)) - MadeChange = true; - - continue; - } - - if (auto *SI = dyn_cast(TI)) { - if (!SI->getNumCases() || - !getValueState(SI->getCondition()).isUnknownOrUndef()) - continue; - - // If the input to SCCP is actually switch on undef, fix the undef to - // the first constant. - if (isa(SI->getCondition())) { - SI->setCondition(SI->case_begin()->getCaseValue()); - markEdgeExecutable(&BB, SI->case_begin()->getCaseSuccessor()); - MadeChange = true; - continue; - } - - // Otherwise, it is a branch on a symbolic value which is currently - // considered to be undef. Make sure some edge is executable, so a - // branch on "undef" always flows somewhere. - // FIXME: Distinguish between dead code and an LLVM "undef" value. - BasicBlock *DefaultSuccessor = SI->case_begin()->getCaseSuccessor(); - if (markEdgeExecutable(&BB, DefaultSuccessor)) - MadeChange = true; - - continue; - } } return MadeChange; diff --git a/llvm/test/Transforms/FunctionSpecialization/bug52821-use-after-free.ll b/llvm/test/Transforms/FunctionSpecialization/bug52821-use-after-free.ll --- a/llvm/test/Transforms/FunctionSpecialization/bug52821-use-after-free.ll +++ b/llvm/test/Transforms/FunctionSpecialization/bug52821-use-after-free.ll @@ -34,7 +34,7 @@ for.cond2: ; preds = %for.body2, %for.cond %phi2 = phi %mystruct* [ undef, %for.body2 ], [ null, %for.cond ] - br i1 undef, label %for.end, label %for.body2 + br i1 false, label %for.end, label %for.body2 for.body2: ; preds = %for.cond2 %arrayidx = getelementptr inbounds %mystruct, %mystruct* %phi2, i64 0, i32 1, i64 3 diff --git a/llvm/test/Transforms/FunctionSpecialization/bug55000-read-uninitialized-value.ll b/llvm/test/Transforms/FunctionSpecialization/bug55000-read-uninitialized-value.ll --- a/llvm/test/Transforms/FunctionSpecialization/bug55000-read-uninitialized-value.ll +++ b/llvm/test/Transforms/FunctionSpecialization/bug55000-read-uninitialized-value.ll @@ -10,7 +10,7 @@ define internal void @foo(ptr %TLI, ptr %DL, ptr %Ty, ptr %ValueVTs, ptr %Offsets, i64 %StartingOffset) { entry: %VT = alloca i64, align 8 - br i1 undef, label %if.then, label %if.end4 + br i1 false, label %if.then, label %if.end4 if.then: ; preds = %entry ret void diff --git a/llvm/test/Transforms/SCCP/2004-12-10-UndefBranchBug.ll b/llvm/test/Transforms/SCCP/2004-12-10-UndefBranchBug.ll --- a/llvm/test/Transforms/SCCP/2004-12-10-UndefBranchBug.ll +++ b/llvm/test/Transforms/SCCP/2004-12-10-UndefBranchBug.ll @@ -1,15 +1,14 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=sccp -S | FileCheck %s -; This function definitely returns 1, even if we don't know the direction -; of the branch. +; Branch on undef is UB, so the T block is never executed, and we can return +; undef (IPSCCP would replace the block with unreachable). define i32 @foo() { ; CHECK-LABEL: @foo( -; CHECK-NEXT: br i1 false, label [[T:%.*]], label [[T]] +; CHECK-NEXT: br i1 undef, label [[T:%.*]], label [[T]] ; CHECK: T: -; CHECK-NEXT: [[X:%.*]] = add i32 0, 1 -; CHECK-NEXT: ret i32 [[X]] +; CHECK-NEXT: ret i32 undef ; br i1 undef, label %T, label %T T: diff --git a/llvm/test/Transforms/SCCP/2008-01-27-UndefCorrelate.ll b/llvm/test/Transforms/SCCP/2008-01-27-UndefCorrelate.ll --- a/llvm/test/Transforms/SCCP/2008-01-27-UndefCorrelate.ll +++ b/llvm/test/Transforms/SCCP/2008-01-27-UndefCorrelate.ll @@ -7,21 +7,16 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[BB:%.*]] ; CHECK: bb: -; CHECK-NEXT: [[INDVAR:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[K:%.*]], [[BB_BACKEDGE:%.*]] ] -; CHECK-NEXT: [[K]] = add i32 [[INDVAR]], 1 -; CHECK-NEXT: br i1 false, label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] +; CHECK-NEXT: br i1 undef, label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] ; CHECK: cond_true: -; CHECK-NEXT: br i1 undef, label [[BB_BACKEDGE]], label [[BB12:%.*]] +; CHECK-NEXT: br i1 undef, label [[BB_BACKEDGE:%.*]], label [[BB12:%.*]] ; CHECK: bb.backedge: ; CHECK-NEXT: br label [[BB]] ; CHECK: cond_false: -; CHECK-NEXT: [[TMP9:%.*]] = icmp slt i32 [[K]], 10 -; CHECK-NEXT: br i1 [[TMP9]], label [[BB_BACKEDGE]], label [[BB12]] +; CHECK-NEXT: br i1 undef, label [[BB_BACKEDGE]], label [[BB12]] ; CHECK: bb12: -; CHECK-NEXT: [[TMP14:%.*]] = icmp eq i32 [[K]], 10 -; CHECK-NEXT: br i1 [[TMP14]], label [[COND_NEXT18:%.*]], label [[COND_TRUE17:%.*]] +; CHECK-NEXT: br i1 undef, label [[COND_NEXT18:%.*]], label [[COND_TRUE17:%.*]] ; CHECK: cond_true17: -; CHECK-NEXT: tail call void @abort() ; CHECK-NEXT: unreachable ; CHECK: cond_next18: ; CHECK-NEXT: ret i32 0 diff --git a/llvm/test/Transforms/SCCP/PR26044.ll b/llvm/test/Transforms/SCCP/PR26044.ll --- a/llvm/test/Transforms/SCCP/PR26044.ll +++ b/llvm/test/Transforms/SCCP/PR26044.ll @@ -5,14 +5,15 @@ define void @fn2(i32* %P) { ; CHECK-LABEL: define {{[^@]+}}@fn2 -; CHECK-SAME: (i32* [[P:%.*]]) +; CHECK-SAME: (i32* [[P:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[IF_END:%.*]] ; CHECK: for.cond1: -; CHECK-NEXT: br i1 false, label [[IF_END]], label [[IF_END]] +; CHECK-NEXT: unreachable ; CHECK: if.end: -; CHECK-NEXT: [[CALL:%.*]] = call i32 @fn1(i32 undef) -; CHECK-NEXT: store i32 [[CALL]], i32* [[P]] +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* undef, align 4 +; CHECK-NEXT: [[CALL:%.*]] = call i32 @fn1(i32 [[TMP0]]) +; CHECK-NEXT: store i32 [[CALL]], i32* [[P]], align 4 ; CHECK-NEXT: br label [[FOR_COND1:%.*]] ; entry: @@ -31,10 +32,10 @@ define internal i32 @fn1(i32 %p1) { ; CHECK-LABEL: define {{[^@]+}}@fn1 -; CHECK-SAME: (i32 [[P1:%.*]]) +; CHECK-SAME: (i32 [[P1:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 undef, 0 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 undef, i32 undef +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[P1]], 0 +; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[P1]], i32 [[P1]] ; CHECK-NEXT: ret i32 [[COND]] ; entry: @@ -45,15 +46,15 @@ define void @fn_no_null_opt(i32* %P) #0 { ; CHECK-LABEL: define {{[^@]+}}@fn_no_null_opt -; CHECK-SAME: (i32* [[P:%.*]]) +; CHECK-SAME: (i32* [[P:%.*]]) #[[ATTR0:[0-9]+]] { ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[IF_END:%.*]] ; CHECK: for.cond1: -; CHECK-NEXT: br i1 false, label [[IF_END]], label [[IF_END]] +; CHECK-NEXT: unreachable ; CHECK: if.end: -; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* null, align 4 +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* undef, align 4 ; CHECK-NEXT: [[CALL:%.*]] = call i32 @fn0(i32 [[TMP0]]) -; CHECK-NEXT: store i32 [[CALL]], i32* [[P]] +; CHECK-NEXT: store i32 [[CALL]], i32* [[P]], align 4 ; CHECK-NEXT: br label [[FOR_COND1:%.*]] ; entry: @@ -72,7 +73,7 @@ define internal i32 @fn0(i32 %p1) { ; CHECK-LABEL: define {{[^@]+}}@fn0 -; CHECK-SAME: (i32 [[P1:%.*]]) +; CHECK-SAME: (i32 [[P1:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[P1]], 0 ; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[P1]], i32 [[P1]] diff --git a/llvm/test/Transforms/SCCP/indirectbr.ll b/llvm/test/Transforms/SCCP/indirectbr.ll --- a/llvm/test/Transforms/SCCP/indirectbr.ll +++ b/llvm/test/Transforms/SCCP/indirectbr.ll @@ -74,15 +74,12 @@ ret void } -; Make sure we eliminate BB1 as we pick the first successor on undef. +; Branch on undef is UB, so we can convert the indirectbr to unreachable. define void @indbrtest4(i8** %Q) { ; CHECK-LABEL: @indbrtest4( ; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[BB0:%.*]] -; CHECK: BB0: -; CHECK-NEXT: call void @BB0_f() -; CHECK-NEXT: ret void +; CHECK-NEXT: unreachable ; entry: indirectbr i8* undef, [label %BB0, label %BB1] diff --git a/llvm/test/Transforms/SCCP/ipsccp-branch-unresolved-undef.ll b/llvm/test/Transforms/SCCP/ipsccp-branch-unresolved-undef.ll --- a/llvm/test/Transforms/SCCP/ipsccp-branch-unresolved-undef.ll +++ b/llvm/test/Transforms/SCCP/ipsccp-branch-unresolved-undef.ll @@ -13,9 +13,7 @@ define internal i1 @patatino(i1 %a) { ; CHECK-LABEL: define {{[^@]+}}@patatino ; CHECK-SAME: (i1 [[A:%.*]]) { -; CHECK-NEXT: br label [[ONFALSE:%.*]] -; CHECK: onfalse: -; CHECK-NEXT: ret i1 undef +; CHECK-NEXT: unreachable ; br i1 %a, label %ontrue, label %onfalse ontrue: diff --git a/llvm/test/Transforms/SCCP/return-zapped.ll b/llvm/test/Transforms/SCCP/return-zapped.ll --- a/llvm/test/Transforms/SCCP/return-zapped.ll +++ b/llvm/test/Transforms/SCCP/return-zapped.ll @@ -1,22 +1,17 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature ; RUN: opt < %s -S -passes=ipsccp | FileCheck %s -; After the first round of Solver.Solve(), the return value of @testf still -; undefined as we hit a branch on undef. Therefore the conditional branch on -; @testf's return value in @bar is unknown. In ResolvedUndefsIn, we force the -; false branch to be feasible. We later discover that @testf actually -; returns true, so we end up with an unfolded "br i1 true". +; testf() performs an unconditional branch on undef, as such the testf() return +; value used in test1() will remain "unknown" and the following branch on it +; replaced by unreachable. This is fine, as the call to testf() will already +; trigger undefined behavior. define void @test1() { ; CHECK-LABEL: define {{[^@]+}}@test1() { ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[IF_THEN:%.*]] ; CHECK: if.then: -; CHECK-NEXT: [[FOO:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[NEXT:%.*]], [[IF_THEN]] ] -; CHECK-NEXT: [[NEXT]] = add i32 [[FOO]], 1 ; CHECK-NEXT: [[CALL:%.*]] = call i1 @testf() -; CHECK-NEXT: br i1 true, label [[IF_END:%.*]], label [[IF_THEN]] -; CHECK: if.end: -; CHECK-NEXT: ret void +; CHECK-NEXT: unreachable ; entry: br label %if.then @@ -33,9 +28,7 @@ define internal i1 @testf() { ; CHECK-LABEL: define {{[^@]+}}@testf() { ; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[IF_END3:%.*]] -; CHECK: if.end3: -; CHECK-NEXT: ret i1 undef +; CHECK-NEXT: unreachable ; entry: br i1 undef, label %if.then1, label %if.end3 @@ -54,7 +47,7 @@ ; CHECK-NEXT: br label [[IF_END:%.*]] ; CHECK: if.end: ; CHECK-NEXT: [[CALL2:%.*]] = call i1 @testf() -; CHECK-NEXT: ret i1 true +; CHECK-NEXT: ret i1 undef ; entry: br label %if.end diff --git a/llvm/test/Transforms/SCCP/switch-constantfold-crash.ll b/llvm/test/Transforms/SCCP/switch-constantfold-crash.ll --- a/llvm/test/Transforms/SCCP/switch-constantfold-crash.ll +++ b/llvm/test/Transforms/SCCP/switch-constantfold-crash.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature -; RUN: opt -passes=ipsccp < %s -S | FileCheck --check-prefixes=CHECK,ONCE %s -; RUN: opt -passes='ipsccp,ipsccp' < %s -S | FileCheck --check-prefixes=CHECK,TWICE %s +; RUN: opt -passes=ipsccp < %s -S | FileCheck %s +; RUN: opt -passes='ipsccp,ipsccp' < %s -S | FileCheck %s define void @barney() { ; CHECK-LABEL: define {{[^@]+}}@barney() { @@ -62,10 +62,6 @@ define void @hoge() { ; CHECK-LABEL: define {{[^@]+}}@hoge() { ; CHECK-NEXT: bb: -; CHECK-NEXT: br label [[BB2:%.*]] -; CHECK: bb2: -; CHECK-NEXT: br label [[BB3:%.*]] -; CHECK: bb3: ; CHECK-NEXT: unreachable ; bb: @@ -94,35 +90,10 @@ ; Test case from PR49573. %default.bb is unfeasible. Make sure it gets replaced ; by an unreachable block. define void @pr49573_main() { -; ONCE-LABEL: define {{[^@]+}}@pr49573_main() { -; ONCE-NEXT: entry: -; ONCE-NEXT: [[TGT:%.*]] = call i16 @pr49573_fn() -; ONCE-NEXT: switch i16 2, label [[DEFAULT_UNREACHABLE:%.*]] [ -; ONCE-NEXT: i16 0, label [[CASE_0:%.*]] -; ONCE-NEXT: i16 2, label [[CASE_2:%.*]] -; ONCE-NEXT: ] -; ONCE: case.0: -; ONCE-NEXT: unreachable -; ONCE: default.unreachable: -; ONCE-NEXT: unreachable -; ONCE: case.2: -; ONCE-NEXT: br label [[NEXT:%.*]] -; ONCE: next: -; ONCE-NEXT: [[TGT_2:%.*]] = call i16 @pr49573_fn_2() -; ONCE-NEXT: switch i16 2, label [[DEFAULT_UNREACHABLE]] [ -; ONCE-NEXT: i16 0, label [[CASE_0]] -; ONCE-NEXT: i16 2, label [[CASE_2]] -; ONCE-NEXT: ] -; -; TWICE-LABEL: define {{[^@]+}}@pr49573_main() { -; TWICE-NEXT: entry: -; TWICE-NEXT: [[TGT:%.*]] = call i16 @pr49573_fn() -; TWICE-NEXT: br label [[CASE_2:%.*]] -; TWICE: case.2: -; TWICE-NEXT: br label [[NEXT:%.*]] -; TWICE: next: -; TWICE-NEXT: [[TGT_2:%.*]] = call i16 @pr49573_fn_2() -; TWICE-NEXT: br label [[CASE_2]] +; CHECK-LABEL: define {{[^@]+}}@pr49573_main() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TGT:%.*]] = call i16 @pr49573_fn() +; CHECK-NEXT: unreachable ; entry: %tgt = call i16 @pr49573_fn() @@ -154,26 +125,10 @@ ; Make sure a new unreachable BB is created. define void @pr49573_main_2() { -; ONCE-LABEL: define {{[^@]+}}@pr49573_main_2() { -; ONCE-NEXT: entry: -; ONCE-NEXT: [[TGT:%.*]] = call i16 @pr49573_fn() -; ONCE-NEXT: switch i16 2, label [[DEFAULT_UNREACHABLE:%.*]] [ -; ONCE-NEXT: i16 0, label [[CASE_0:%.*]] -; ONCE-NEXT: i16 2, label [[CASE_2:%.*]] -; ONCE-NEXT: ] -; ONCE: case.0: -; ONCE-NEXT: unreachable -; ONCE: default.unreachable: -; ONCE-NEXT: unreachable -; ONCE: case.2: -; ONCE-NEXT: ret void -; -; TWICE-LABEL: define {{[^@]+}}@pr49573_main_2() { -; TWICE-NEXT: entry: -; TWICE-NEXT: [[TGT:%.*]] = call i16 @pr49573_fn() -; TWICE-NEXT: br label [[CASE_2:%.*]] -; TWICE: case.2: -; TWICE-NEXT: ret void +; CHECK-LABEL: define {{[^@]+}}@pr49573_main_2() { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TGT:%.*]] = call i16 @pr49573_fn() +; CHECK-NEXT: unreachable ; entry: %tgt = call i16 @pr49573_fn() @@ -199,9 +154,7 @@ define internal i16 @pr49573_fn() { ; CHECK-LABEL: define {{[^@]+}}@pr49573_fn() { ; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[ELSE:%.*]] -; CHECK: else: -; CHECK-NEXT: ret i16 undef +; CHECK-NEXT: unreachable ; entry: br i1 undef, label %then, label %else @@ -216,9 +169,7 @@ define internal i16 @pr49573_fn_2() { ; CHECK-LABEL: define {{[^@]+}}@pr49573_fn_2() { ; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[ELSE:%.*]] -; CHECK: else: -; CHECK-NEXT: ret i16 undef +; CHECK-NEXT: unreachable ; entry: br i1 undef, label %then, label %else diff --git a/llvm/test/Transforms/SCCP/switch-undef-constantfoldterminator.ll b/llvm/test/Transforms/SCCP/switch-undef-constantfoldterminator.ll --- a/llvm/test/Transforms/SCCP/switch-undef-constantfoldterminator.ll +++ b/llvm/test/Transforms/SCCP/switch-undef-constantfoldterminator.ll @@ -29,9 +29,7 @@ ; CHECK-LABEL: define {{[^@]+}}@f3 ; CHECK-SAME: (i16 [[P1:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[LAND_END:%.*]] -; CHECK: land.end: -; CHECK-NEXT: ret i16 undef +; CHECK-NEXT: unreachable ; entry: switch i16 %p1, label %land.end [