Index: llvm/lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -4531,15 +4531,36 @@ Changed = true; } else { assert(BI->isConditional() && "Can't get here with an uncond branch."); - Value* Cond = BI->getCondition(); + Value *Cond = BI->getCondition(); assert(BI->getSuccessor(0) != BI->getSuccessor(1) && "The destinations are guaranteed to be different here."); + + // We are eliminating at least one use of the condition by erasing the + // conditional branch. If there are other uses of the condition or its + // operands, preserve information for those uses by creating an assume. + auto shouldCreateAssume = [](Value *Cond) { + if (!Cond->hasOneUse()) + return true; + + CmpInst::Predicate Pred; + Value *X, *Y; + if (match(Cond, m_Cmp(Pred, m_Value(X), m_Value(Y)))) { + if (!isa(X) && !X->hasOneUse()) + return true; + if (!isa(Y) && !Y->hasOneUse()) + return true; + } + return false; + }; + if (BI->getSuccessor(0) == BB) { - Builder.CreateAssumption(Builder.CreateNot(Cond)); + if (shouldCreateAssume(Cond)) + Builder.CreateAssumption(Builder.CreateNot(Cond)); Builder.CreateBr(BI->getSuccessor(1)); } else { assert(BI->getSuccessor(1) == BB && "Incorrect CFG"); - Builder.CreateAssumption(Cond); + if (shouldCreateAssume(Cond)) + Builder.CreateAssumption(Cond); Builder.CreateBr(BI->getSuccessor(0)); } EraseTerminatorAndDCECond(BI); Index: llvm/test/Transforms/LoopVectorize/if-pred-stores.ll =================================================================== --- llvm/test/Transforms/LoopVectorize/if-pred-stores.ll +++ llvm/test/Transforms/LoopVectorize/if-pred-stores.ll @@ -194,8 +194,6 @@ define void @bug18724(i1 %cond) { ; UNROLL-LABEL: @bug18724( ; UNROLL-NEXT: entry: -; UNROLL-NEXT: [[TMP0:%.*]] = xor i1 [[COND:%.*]], true -; UNROLL-NEXT: call void @llvm.assume(i1 [[TMP0]]) ; UNROLL-NEXT: br label [[FOR_BODY14:%.*]] ; UNROLL: for.body14: ; UNROLL-NEXT: [[INDVARS_IV3:%.*]] = phi i64 [ [[INDVARS_IV_NEXT4:%.*]], [[FOR_INC23:%.*]] ], [ undef, [[ENTRY:%.*]] ] @@ -210,9 +208,6 @@ ; UNROLL: for.inc23: ; UNROLL-NEXT: [[INEWCHUNKS_2]] = phi i32 [ [[INC21]], [[IF_THEN18]] ], [ [[INEWCHUNKS_120]], [[FOR_BODY14]] ] ; UNROLL-NEXT: [[INDVARS_IV_NEXT4]] = add nsw i64 [[INDVARS_IV3]], 1 -; UNROLL-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV3]] to i32 -; UNROLL-NEXT: [[CMP13:%.*]] = icmp slt i32 [[TMP1]], 0 -; UNROLL-NEXT: call void @llvm.assume(i1 [[CMP13]]) ; UNROLL-NEXT: br label [[FOR_BODY14]] ; ; UNROLL-NOSIMPLIFY-LABEL: @bug18724( @@ -285,8 +280,6 @@ ; ; VEC-LABEL: @bug18724( ; VEC-NEXT: entry: -; VEC-NEXT: [[TMP0:%.*]] = xor i1 [[COND:%.*]], true -; VEC-NEXT: call void @llvm.assume(i1 [[TMP0]]) ; VEC-NEXT: br label [[FOR_BODY14:%.*]] ; VEC: for.body14: ; VEC-NEXT: [[INDVARS_IV3:%.*]] = phi i64 [ [[INDVARS_IV_NEXT4:%.*]], [[FOR_INC23:%.*]] ], [ undef, [[ENTRY:%.*]] ] @@ -301,9 +294,6 @@ ; VEC: for.inc23: ; VEC-NEXT: [[INEWCHUNKS_2]] = phi i32 [ [[INC21]], [[IF_THEN18]] ], [ [[INEWCHUNKS_120]], [[FOR_BODY14]] ] ; VEC-NEXT: [[INDVARS_IV_NEXT4]] = add nsw i64 [[INDVARS_IV3]], 1 -; VEC-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV3]] to i32 -; VEC-NEXT: [[CMP13:%.*]] = icmp slt i32 [[TMP1]], 0 -; VEC-NEXT: call void @llvm.assume(i1 [[CMP13]]) ; VEC-NEXT: br label [[FOR_BODY14]] ; entry: Index: llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll =================================================================== --- llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll +++ llvm/test/Transforms/SimplifyCFG/UnreachableEliminate.ll @@ -4,8 +4,6 @@ define void @test1(i1 %C, i1* %BP) { ; CHECK-LABEL: @test1( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[C:%.*]], true -; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]]) ; CHECK-NEXT: ret void ; entry: @@ -64,8 +62,6 @@ define void @test5(i1 %cond, i8* %ptr) { ; CHECK-LABEL: @test5( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[COND:%.*]], true -; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]]) ; CHECK-NEXT: store i8 2, i8* [[PTR:%.*]], align 8 ; CHECK-NEXT: ret void ; @@ -109,8 +105,6 @@ define void @test6(i1 %cond, i8* %ptr) { ; CHECK-LABEL: @test6( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[COND:%.*]], true -; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]]) ; CHECK-NEXT: store i8 2, i8* [[PTR:%.*]], align 8 ; CHECK-NEXT: ret void ; @@ -149,8 +143,6 @@ define i32 @test7(i1 %X) { ; CHECK-LABEL: @test7( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[X:%.*]], true -; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]]) ; CHECK-NEXT: ret i32 0 ; entry: @@ -168,8 +160,6 @@ define void @test8(i1 %X, void ()* %Y) { ; CHECK-LABEL: @test8( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[X:%.*]], true -; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]]) ; CHECK-NEXT: call void [[Y:%.*]]() ; CHECK-NEXT: ret void ; @@ -211,9 +201,7 @@ define void @test9(i1 %X, i8* %Y) { ; CHECK-LABEL: @test9( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[X:%.*]], true -; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]]) -; CHECK-NEXT: [[TMP1:%.*]] = call i8* @fn_nonnull_noundef_arg(i8* [[Y:%.*]]) +; CHECK-NEXT: [[TMP0:%.*]] = call i8* @fn_nonnull_noundef_arg(i8* [[Y:%.*]]) ; CHECK-NEXT: ret void ; entry: @@ -267,9 +255,7 @@ define void @test9_null_callsite(i1 %X, i8* %Y) { ; CHECK-LABEL: @test9_null_callsite( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[X:%.*]], true -; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]]) -; CHECK-NEXT: [[TMP1:%.*]] = call i8* @fn_nonnull_arg(i8* noundef nonnull [[Y:%.*]]) +; CHECK-NEXT: [[TMP0:%.*]] = call i8* @fn_nonnull_arg(i8* noundef nonnull [[Y:%.*]]) ; CHECK-NEXT: ret void ; entry: @@ -308,10 +294,8 @@ define void @test9_gep_zero(i1 %X, i8* %Y) { ; CHECK-LABEL: @test9_gep_zero( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[X:%.*]], true -; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]]) ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i8, i8* [[Y:%.*]], i64 0 -; CHECK-NEXT: [[TMP1:%.*]] = call i8* @fn_nonnull_noundef_arg(i8* [[GEP]]) +; CHECK-NEXT: [[TMP0:%.*]] = call i8* @fn_nonnull_noundef_arg(i8* [[GEP]]) ; CHECK-NEXT: ret void ; entry: @@ -330,11 +314,9 @@ define void @test9_gep_bitcast(i1 %X, i32* %Y) { ; CHECK-LABEL: @test9_gep_bitcast( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[X:%.*]], true -; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]]) ; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, i32* [[Y:%.*]], i64 0 ; CHECK-NEXT: [[BC:%.*]] = bitcast i32* [[GEP]] to i8* -; CHECK-NEXT: [[TMP1:%.*]] = call i8* @fn_nonnull_noundef_arg(i8* [[BC]]) +; CHECK-NEXT: [[TMP0:%.*]] = call i8* @fn_nonnull_noundef_arg(i8* [[BC]]) ; CHECK-NEXT: ret void ; entry: Index: llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest.ll =================================================================== --- llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest.ll +++ llvm/test/Transforms/SimplifyCFG/fold-branch-to-common-dest.ll @@ -847,9 +847,6 @@ ; CHECK-NEXT: entry: ; CHECK-NEXT: br label [[FOR_COND1:%.*]] ; CHECK: for.cond1: -; CHECK-NEXT: [[V:%.*]] = load i8, i8* @f.b, align 1 -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[V]], 1 -; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]]) ; CHECK-NEXT: br label [[FOR_COND1]] ; entry: Index: llvm/test/Transforms/SimplifyCFG/simplifyUnreachable-degenerate-conditional-branch-with-matching-destinations.ll =================================================================== --- llvm/test/Transforms/SimplifyCFG/simplifyUnreachable-degenerate-conditional-branch-with-matching-destinations.ll +++ llvm/test/Transforms/SimplifyCFG/simplifyUnreachable-degenerate-conditional-branch-with-matching-destinations.ll @@ -8,9 +8,6 @@ define void @widget() { ; CHECK-LABEL: @widget( ; CHECK-NEXT: bb: -; CHECK-NEXT: [[I:%.*]] = load i16, i16* @global, align 1 -; CHECK-NEXT: [[I13:%.*]] = icmp ne i16 [[I]], 0 -; CHECK-NEXT: call void @llvm.assume(i1 [[I13]]) ; CHECK-NEXT: unreachable ; bb: Index: llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll =================================================================== --- llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll +++ llvm/test/Transforms/SimplifyCFG/switch-range-to-icmp.ll @@ -107,8 +107,6 @@ define void @PR42737(i32* %a, i1 %c) { ; CHECK-LABEL: @PR42737( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = xor i1 [[C:%.*]], true -; CHECK-NEXT: call void @llvm.assume(i1 [[TMP0]]) ; CHECK-NEXT: unreachable ; entry: Index: llvm/test/Transforms/SimplifyCFG/unreachable_assume.ll =================================================================== --- llvm/test/Transforms/SimplifyCFG/unreachable_assume.ll +++ llvm/test/Transforms/SimplifyCFG/unreachable_assume.ll @@ -1,6 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s +; We add an assume to preserve information about %p. + define i32 @assume1(i32 %p) { ; CHECK-LABEL: @assume1( ; CHECK-NEXT: entry: @@ -22,6 +24,7 @@ ret i32 %call } +; We add an assume to preserve information about %p. define i32 @assume2(i32 %p) { ; CHECK-LABEL: @assume2(