diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp index f98833bd11989..65e6e3a5bb43b 100644 --- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp +++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp @@ -2425,6 +2425,8 @@ bool AANonNull::isImpliedByIR(Attributor &A, const IRPosition &IRP, AttrKinds.push_back(Attribute::Dereferenceable); if (A.hasAttr(IRP, AttrKinds, IgnoreSubsumingPositions, Attribute::NonNull)) return true; + if (IRP.getPositionKind() == IRP_RETURNED) + return false; DominatorTree *DT = nullptr; AssumptionCache *AC = nullptr; @@ -2436,25 +2438,8 @@ bool AANonNull::isImpliedByIR(Attributor &A, const IRPosition &IRP, } } - SmallVector Worklist; - if (IRP.getPositionKind() != IRP_RETURNED) { - Worklist.push_back({IRP.getAssociatedValue(), IRP.getCtxI()}); - } else { - bool UsedAssumedInformation = false; - if (!A.checkForAllInstructions( - [&](Instruction &I) { - Worklist.push_back({*cast(I).getReturnValue(), &I}); - return true; - }, - IRP.getAssociatedFunction(), nullptr, {Instruction::Ret}, - UsedAssumedInformation)) - return false; - } - - if (llvm::any_of(Worklist, [&](AA::ValueAndContext VAC) { - return !isKnownNonZero(VAC.getValue(), A.getDataLayout(), 0, AC, - VAC.getCtxI(), DT); - })) + if (!isKnownNonZero(&IRP.getAssociatedValue(), A.getDataLayout(), 0, AC, + IRP.getCtxI(), DT)) return false; A.manifestAttrs(IRP, {Attribute::get(IRP.getAnchorValue().getContext(), diff --git a/llvm/test/Transforms/Attributor/nonnull.ll b/llvm/test/Transforms/Attributor/nonnull.ll index 42d81792c2f4e..4b0114299bb59 100644 --- a/llvm/test/Transforms/Attributor/nonnull.ll +++ b/llvm/test/Transforms/Attributor/nonnull.ll @@ -9,6 +9,9 @@ declare nonnull ptr @ret_nonnull() declare void @llvm.assume(i1) ; Return a pointer trivially nonnull (call return attribute) +;. +; CHECK: @G = internal global i64 1, align 8 +;. define ptr @test1() { ; CHECK-LABEL: define {{[^@]+}}@test1() { ; CHECK-NEXT: [[RET:%.*]] = call nonnull ptr @ret_nonnull() @@ -34,10 +37,10 @@ define ptr @test2A(i1 %c, ptr %ret) { ; CHECK-SAME: (i1 noundef [[C:%.*]], ptr nofree nonnull readnone returned "no-capture-maybe-returned" [[RET:%.*]]) #[[ATTR2:[0-9]+]] { ; CHECK-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]] ; CHECK: A: -; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR15:[0-9]+]] [ "nonnull"(ptr [[RET]]) ] +; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR16:[0-9]+]] [ "nonnull"(ptr [[RET]]) ] ; CHECK-NEXT: ret ptr [[RET]] ; CHECK: B: -; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR15]] [ "nonnull"(ptr [[RET]]) ] +; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR16]] [ "nonnull"(ptr [[RET]]) ] ; CHECK-NEXT: ret ptr [[RET]] ; br i1 %c, label %A, label %B @@ -55,10 +58,10 @@ define ptr @test2B(i1 %c, ptr %ret) { ; CHECK-SAME: (i1 noundef [[C:%.*]], ptr nofree nonnull readnone returned dereferenceable(4) "no-capture-maybe-returned" [[RET:%.*]]) #[[ATTR2]] { ; CHECK-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]] ; CHECK: A: -; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR15]] [ "dereferenceable"(ptr [[RET]], i32 4) ] +; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR16]] [ "dereferenceable"(ptr [[RET]], i32 4) ] ; CHECK-NEXT: ret ptr [[RET]] ; CHECK: B: -; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR15]] [ "dereferenceable"(ptr [[RET]], i32 4) ] +; CHECK-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR16]] [ "dereferenceable"(ptr [[RET]], i32 4) ] ; CHECK-NEXT: ret ptr [[RET]] ; br i1 %c, label %A, label %B @@ -274,7 +277,7 @@ define ptr @test10(ptr %a, i64 %n) { ; CHECK-LABEL: define {{[^@]+}}@test10 ; CHECK-SAME: (ptr nofree readnone "no-capture-maybe-returned" [[A:%.*]], i64 [[N:%.*]]) #[[ATTR2]] { ; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[N]], 0 -; CHECK-NEXT: call void @llvm.assume(i1 noundef [[CMP]]) #[[ATTR15]] +; CHECK-NEXT: call void @llvm.assume(i1 noundef [[CMP]]) #[[ATTR16]] ; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[N]] ; CHECK-NEXT: ret ptr [[B]] ; @@ -397,20 +400,20 @@ define internal ptr @f1(ptr %arg) { ; TUNIT-NEXT: [[TMP:%.*]] = icmp eq ptr [[ARG]], null ; TUNIT-NEXT: br i1 [[TMP]], label [[BB9:%.*]], label [[BB1:%.*]] ; TUNIT: bb1: -; TUNIT-NEXT: [[TRUETMP2:%.*]] = load i32, ptr [[ARG]], align 4 -; TUNIT-NEXT: [[TRUETMP3:%.*]] = icmp eq i32 [[TRUETMP2]], 0 -; TUNIT-NEXT: br i1 [[TRUETMP3]], label [[BB6:%.*]], label [[BB4:%.*]] +; TUNIT-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARG]], align 4 +; TUNIT-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 +; TUNIT-NEXT: br i1 [[TMP3]], label [[BB6:%.*]], label [[BB4:%.*]] ; TUNIT: bb4: -; TUNIT-NEXT: [[TRUETMP5:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 1 -; TUNIT-NEXT: [[TMP5B:%.*]] = tail call ptr @f3(ptr nofree nonnull readonly [[TRUETMP5]]) #[[ATTR16:[0-9]+]] +; TUNIT-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 1 +; TUNIT-NEXT: [[TMP5B:%.*]] = tail call ptr @f3(ptr nofree nonnull readonly [[TMP5]]) #[[ATTR17:[0-9]+]] ; TUNIT-NEXT: [[TMP5C:%.*]] = getelementptr inbounds i32, ptr [[TMP5B]], i64 -1 ; TUNIT-NEXT: br label [[BB9]] ; TUNIT: bb6: -; TUNIT-NEXT: [[TRUETMP7:%.*]] = tail call ptr @f2(ptr nofree nonnull readonly align 4 dereferenceable(4) [[ARG]]) #[[ATTR16]] -; TUNIT-NEXT: ret ptr [[TRUETMP7]] +; TUNIT-NEXT: [[TMP7:%.*]] = tail call ptr @f2(ptr nofree nonnull readonly align 4 dereferenceable(4) [[ARG]]) #[[ATTR17]] +; TUNIT-NEXT: ret ptr [[TMP7]] ; TUNIT: bb9: -; TUNIT-NEXT: [[TRUETMP10:%.*]] = phi ptr [ [[TMP5C]], [[BB4]] ], [ inttoptr (i64 4 to ptr), [[BB:%.*]] ] -; TUNIT-NEXT: ret ptr [[TRUETMP10]] +; TUNIT-NEXT: [[TMP10:%.*]] = phi ptr [ [[TMP5C]], [[BB4]] ], [ inttoptr (i64 4 to ptr), [[BB:%.*]] ] +; TUNIT-NEXT: ret ptr [[TMP10]] ; ; CGSCC: Function Attrs: nofree nosync nounwind memory(argmem: read) ; CGSCC-LABEL: define {{[^@]+}}@f1 @@ -419,20 +422,20 @@ define internal ptr @f1(ptr %arg) { ; CGSCC-NEXT: [[TMP:%.*]] = icmp eq ptr [[ARG]], null ; CGSCC-NEXT: br i1 [[TMP]], label [[BB9:%.*]], label [[BB1:%.*]] ; CGSCC: bb1: -; CGSCC-NEXT: [[TRUETMP2:%.*]] = load i32, ptr [[ARG]], align 4 -; CGSCC-NEXT: [[TRUETMP3:%.*]] = icmp eq i32 [[TRUETMP2]], 0 -; CGSCC-NEXT: br i1 [[TRUETMP3]], label [[BB6:%.*]], label [[BB4:%.*]] +; CGSCC-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARG]], align 4 +; CGSCC-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP2]], 0 +; CGSCC-NEXT: br i1 [[TMP3]], label [[BB6:%.*]], label [[BB4:%.*]] ; CGSCC: bb4: -; CGSCC-NEXT: [[TRUETMP5:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 1 -; CGSCC-NEXT: [[TMP5B:%.*]] = tail call ptr @f3(ptr nofree nonnull readonly [[TRUETMP5]]) #[[ATTR16:[0-9]+]] +; CGSCC-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 1 +; CGSCC-NEXT: [[TMP5B:%.*]] = tail call ptr @f3(ptr nofree nonnull readonly [[TMP5]]) #[[ATTR17:[0-9]+]] ; CGSCC-NEXT: [[TMP5C:%.*]] = getelementptr inbounds i32, ptr [[TMP5B]], i64 -1 ; CGSCC-NEXT: br label [[BB9]] ; CGSCC: bb6: -; CGSCC-NEXT: [[TRUETMP7:%.*]] = tail call ptr @f2(ptr nofree nonnull readonly align 4 dereferenceable(4) [[ARG]]) #[[ATTR16]] -; CGSCC-NEXT: ret ptr [[TRUETMP7]] +; CGSCC-NEXT: [[TMP7:%.*]] = tail call ptr @f2(ptr nofree nonnull readonly align 4 dereferenceable(4) [[ARG]]) #[[ATTR17]] +; CGSCC-NEXT: ret ptr [[TMP7]] ; CGSCC: bb9: -; CGSCC-NEXT: [[TRUETMP10:%.*]] = phi ptr [ [[TMP5C]], [[BB4]] ], [ inttoptr (i64 4 to ptr), [[BB:%.*]] ] -; CGSCC-NEXT: ret ptr [[TRUETMP10]] +; CGSCC-NEXT: [[TMP10:%.*]] = phi ptr [ [[TMP5C]], [[BB4]] ], [ inttoptr (i64 4 to ptr), [[BB:%.*]] ] +; CGSCC-NEXT: ret ptr [[TMP10]] ; bb: @@ -464,14 +467,14 @@ define internal ptr @f2(ptr %arg) { ; TUNIT-LABEL: define {{[^@]+}}@f2 ; TUNIT-SAME: (ptr nofree nonnull readonly align 4 dereferenceable(4) [[ARG:%.*]]) #[[ATTR6]] { ; TUNIT-NEXT: bb: -; TUNIT-NEXT: [[TMP:%.*]] = tail call ptr @f1(ptr nofree readonly [[ARG]]) #[[ATTR16]] +; TUNIT-NEXT: [[TMP:%.*]] = tail call ptr @f1(ptr nofree readonly [[ARG]]) #[[ATTR17]] ; TUNIT-NEXT: ret ptr [[TMP]] ; ; CGSCC: Function Attrs: nofree nosync nounwind memory(argmem: read) ; CGSCC-LABEL: define {{[^@]+}}@f2 ; CGSCC-SAME: (ptr nofree nonnull readonly align 4 dereferenceable(4) [[ARG:%.*]]) #[[ATTR5]] { ; CGSCC-NEXT: bb: -; CGSCC-NEXT: [[TMP:%.*]] = tail call ptr @f1(ptr nofree readonly [[ARG]]) #[[ATTR16]] +; CGSCC-NEXT: [[TMP:%.*]] = tail call ptr @f1(ptr nofree readonly [[ARG]]) #[[ATTR17]] ; CGSCC-NEXT: ret ptr [[TMP]] ; bb: @@ -485,14 +488,14 @@ define dso_local noalias ptr @f3(ptr %arg) { ; TUNIT-LABEL: define {{[^@]+}}@f3 ; TUNIT-SAME: (ptr nofree readonly [[ARG:%.*]]) #[[ATTR6]] { ; TUNIT-NEXT: bb: -; TUNIT-NEXT: [[TMP:%.*]] = call ptr @f1(ptr nofree readonly [[ARG]]) #[[ATTR16]] +; TUNIT-NEXT: [[TMP:%.*]] = call ptr @f1(ptr nofree readonly [[ARG]]) #[[ATTR17]] ; TUNIT-NEXT: ret ptr [[TMP]] ; ; CGSCC: Function Attrs: nofree nosync nounwind memory(argmem: read) ; CGSCC-LABEL: define {{[^@]+}}@f3 ; CGSCC-SAME: (ptr nofree readonly [[ARG:%.*]]) #[[ATTR5]] { ; CGSCC-NEXT: bb: -; CGSCC-NEXT: [[TMP:%.*]] = call ptr @f1(ptr nofree readonly [[ARG]]) #[[ATTR16]] +; CGSCC-NEXT: [[TMP:%.*]] = call ptr @f1(ptr nofree readonly [[ARG]]) #[[ATTR17]] ; CGSCC-NEXT: ret ptr [[TMP]] ; bb: @@ -856,7 +859,7 @@ define i8 @parent6(ptr %a, ptr %b) { define i8 @parent7(ptr %a) { ; CHECK-LABEL: define {{[^@]+}}@parent7 ; CHECK-SAME: (ptr nonnull [[A:%.*]]) { -; CHECK-NEXT: [[RET:%.*]] = call i8 @use1safecall(ptr nonnull readonly [[A]]) #[[ATTR17:[0-9]+]] +; CHECK-NEXT: [[RET:%.*]] = call i8 @use1safecall(ptr nonnull readonly [[A]]) #[[ATTR18:[0-9]+]] ; CHECK-NEXT: call void @use1nonnull(ptr nonnull [[A]]) ; CHECK-NEXT: ret i8 [[RET]] ; @@ -877,12 +880,12 @@ define i1 @parent8(ptr %a, ptr %bogus1, ptr %b) personality ptr @esfp{ ; TUNIT-SAME: (ptr nonnull [[A:%.*]], ptr nocapture nofree readnone [[BOGUS1:%.*]], ptr nonnull [[B:%.*]]) #[[ATTR5]] personality ptr @esfp { ; TUNIT-NEXT: entry: ; TUNIT-NEXT: invoke void @use2nonnull(ptr nonnull [[A]], ptr nonnull [[B]]) -; TUNIT-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]] +; TUNIT-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]] ; TUNIT: cont: ; TUNIT-NEXT: ret i1 false ; TUNIT: exc: ; TUNIT-NEXT: [[LP:%.*]] = landingpad { ptr, i32 } -; TUNIT-NEXT: filter [0 x ptr] zeroinitializer +; TUNIT-NEXT: filter [0 x ptr] zeroinitializer ; TUNIT-NEXT: unreachable ; ; CGSCC: Function Attrs: nounwind @@ -890,12 +893,12 @@ define i1 @parent8(ptr %a, ptr %bogus1, ptr %b) personality ptr @esfp{ ; CGSCC-SAME: (ptr nonnull [[A:%.*]], ptr nocapture nofree readnone [[BOGUS1:%.*]], ptr nonnull [[B:%.*]]) #[[ATTR4]] personality ptr @esfp { ; CGSCC-NEXT: entry: ; CGSCC-NEXT: invoke void @use2nonnull(ptr nonnull [[A]], ptr nonnull [[B]]) -; CGSCC-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]] +; CGSCC-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]] ; CGSCC: cont: ; CGSCC-NEXT: ret i1 false ; CGSCC: exc: ; CGSCC-NEXT: [[LP:%.*]] = landingpad { ptr, i32 } -; CGSCC-NEXT: filter [0 x ptr] zeroinitializer +; CGSCC-NEXT: filter [0 x ptr] zeroinitializer ; CGSCC-NEXT: unreachable ; @@ -963,7 +966,6 @@ define ptr addrspace(3) @as(ptr addrspace(3) dereferenceable(4) %p) { ret ptr addrspace(3) %p } -; CHECK-NOT: @g2() define internal ptr @g2() { ; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define {{[^@]+}}@g2 @@ -982,7 +984,7 @@ define ptr @g1() { ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none) ; CGSCC-LABEL: define {{[^@]+}}@g1 ; CGSCC-SAME: () #[[ATTR10:[0-9]+]] { -; CGSCC-NEXT: [[C:%.*]] = call noundef nonnull align 4 ptr @g2() #[[ATTR18:[0-9]+]] +; CGSCC-NEXT: [[C:%.*]] = call noundef nonnull align 4 ptr @g2() #[[ATTR19:[0-9]+]] ; CGSCC-NEXT: ret ptr [[C]] ; %c = call ptr @g2() @@ -1100,33 +1102,33 @@ define i32 @nonnull_exec_ctx_1(ptr %a, i32 %b) { ; TUNIT-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1 ; TUNIT-SAME: (ptr [[A:%.*]], i32 [[B:%.*]]) #[[ATTR8]] { ; TUNIT-NEXT: en: -; TUNIT-NEXT: [[TRUETMP3:%.*]] = icmp eq i32 [[B]], 0 -; TUNIT-NEXT: br i1 [[TRUETMP3]], label [[EX:%.*]], label [[HD:%.*]] +; TUNIT-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 +; TUNIT-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] ; TUNIT: ex: -; TUNIT-NEXT: [[TRUETMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR7]] -; TUNIT-NEXT: ret i32 [[TRUETMP5]] +; TUNIT-NEXT: [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR7]] +; TUNIT-NEXT: ret i32 [[TMP5]] ; TUNIT: hd: -; TUNIT-NEXT: [[TRUETMP7:%.*]] = phi i32 [ [[TRUETMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] +; TUNIT-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] ; TUNIT-NEXT: tail call void @h(ptr [[A]]) #[[ATTR7]] -; TUNIT-NEXT: [[TRUETMP8]] = add nuw i32 [[TRUETMP7]], 1 -; TUNIT-NEXT: [[TRUETMP9:%.*]] = icmp eq i32 [[TRUETMP8]], [[B]] -; TUNIT-NEXT: br i1 [[TRUETMP9]], label [[EX]], label [[HD]] +; TUNIT-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 +; TUNIT-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] +; TUNIT-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] ; ; CGSCC: Function Attrs: mustprogress nounwind willreturn ; CGSCC-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1 ; CGSCC-SAME: (ptr [[A:%.*]], i32 [[B:%.*]]) #[[ATTR7]] { ; CGSCC-NEXT: en: -; CGSCC-NEXT: [[TRUETMP3:%.*]] = icmp eq i32 [[B]], 0 -; CGSCC-NEXT: br i1 [[TRUETMP3]], label [[EX:%.*]], label [[HD:%.*]] +; CGSCC-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 +; CGSCC-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] ; CGSCC: ex: -; CGSCC-NEXT: [[TRUETMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR6]] -; CGSCC-NEXT: ret i32 [[TRUETMP5]] +; CGSCC-NEXT: [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR6]] +; CGSCC-NEXT: ret i32 [[TMP5]] ; CGSCC: hd: -; CGSCC-NEXT: [[TRUETMP7:%.*]] = phi i32 [ [[TRUETMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] +; CGSCC-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] ; CGSCC-NEXT: tail call void @h(ptr [[A]]) #[[ATTR6]] -; CGSCC-NEXT: [[TRUETMP8]] = add nuw i32 [[TRUETMP7]], 1 -; CGSCC-NEXT: [[TRUETMP9:%.*]] = icmp eq i32 [[TRUETMP8]], [[B]] -; CGSCC-NEXT: br i1 [[TRUETMP9]], label [[EX]], label [[HD]] +; CGSCC-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 +; CGSCC-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] +; CGSCC-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] ; en: %tmp3 = icmp eq i32 %b, 0 @@ -1150,37 +1152,37 @@ define i32 @nonnull_exec_ctx_1b(ptr %a, i32 %b) { ; TUNIT-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1b ; TUNIT-SAME: (ptr [[A:%.*]], i32 [[B:%.*]]) #[[ATTR8]] { ; TUNIT-NEXT: en: -; TUNIT-NEXT: [[TRUETMP3:%.*]] = icmp eq i32 [[B]], 0 -; TUNIT-NEXT: br i1 [[TRUETMP3]], label [[EX:%.*]], label [[HD:%.*]] +; TUNIT-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 +; TUNIT-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] ; TUNIT: ex: -; TUNIT-NEXT: [[TRUETMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR7]] -; TUNIT-NEXT: ret i32 [[TRUETMP5]] +; TUNIT-NEXT: [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR7]] +; TUNIT-NEXT: ret i32 [[TMP5]] ; TUNIT: hd: -; TUNIT-NEXT: [[TRUETMP7:%.*]] = phi i32 [ [[TRUETMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] +; TUNIT-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] ; TUNIT-NEXT: tail call void @h(ptr [[A]]) #[[ATTR7]] ; TUNIT-NEXT: br label [[HD2]] ; TUNIT: hd2: -; TUNIT-NEXT: [[TRUETMP8]] = add nuw i32 [[TRUETMP7]], 1 -; TUNIT-NEXT: [[TRUETMP9:%.*]] = icmp eq i32 [[TRUETMP8]], [[B]] -; TUNIT-NEXT: br i1 [[TRUETMP9]], label [[EX]], label [[HD]] +; TUNIT-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 +; TUNIT-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] +; TUNIT-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] ; ; CGSCC: Function Attrs: mustprogress nounwind willreturn ; CGSCC-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1b ; CGSCC-SAME: (ptr [[A:%.*]], i32 [[B:%.*]]) #[[ATTR7]] { ; CGSCC-NEXT: en: -; CGSCC-NEXT: [[TRUETMP3:%.*]] = icmp eq i32 [[B]], 0 -; CGSCC-NEXT: br i1 [[TRUETMP3]], label [[EX:%.*]], label [[HD:%.*]] +; CGSCC-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 +; CGSCC-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] ; CGSCC: ex: -; CGSCC-NEXT: [[TRUETMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR6]] -; CGSCC-NEXT: ret i32 [[TRUETMP5]] +; CGSCC-NEXT: [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR6]] +; CGSCC-NEXT: ret i32 [[TMP5]] ; CGSCC: hd: -; CGSCC-NEXT: [[TRUETMP7:%.*]] = phi i32 [ [[TRUETMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] +; CGSCC-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] ; CGSCC-NEXT: tail call void @h(ptr [[A]]) #[[ATTR6]] ; CGSCC-NEXT: br label [[HD2]] ; CGSCC: hd2: -; CGSCC-NEXT: [[TRUETMP8]] = add nuw i32 [[TRUETMP7]], 1 -; CGSCC-NEXT: [[TRUETMP9:%.*]] = icmp eq i32 [[TRUETMP8]], [[B]] -; CGSCC-NEXT: br i1 [[TRUETMP9]], label [[EX]], label [[HD]] +; CGSCC-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 +; CGSCC-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] +; CGSCC-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] ; en: %tmp3 = icmp eq i32 %b, 0 @@ -1207,33 +1209,33 @@ define i32 @nonnull_exec_ctx_2(ptr %a, i32 %b) willreturn nounwind { ; TUNIT-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2 ; TUNIT-SAME: (ptr nonnull [[A:%.*]], i32 [[B:%.*]]) #[[ATTR8]] { ; TUNIT-NEXT: en: -; TUNIT-NEXT: [[TRUETMP3:%.*]] = icmp eq i32 [[B]], 0 -; TUNIT-NEXT: br i1 [[TRUETMP3]], label [[EX:%.*]], label [[HD:%.*]] +; TUNIT-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 +; TUNIT-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] ; TUNIT: ex: -; TUNIT-NEXT: [[TRUETMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR5]] -; TUNIT-NEXT: ret i32 [[TRUETMP5]] +; TUNIT-NEXT: [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR5]] +; TUNIT-NEXT: ret i32 [[TMP5]] ; TUNIT: hd: -; TUNIT-NEXT: [[TRUETMP7:%.*]] = phi i32 [ [[TRUETMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] +; TUNIT-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] ; TUNIT-NEXT: tail call void @h(ptr nonnull [[A]]) #[[ATTR5]] -; TUNIT-NEXT: [[TRUETMP8]] = add nuw i32 [[TRUETMP7]], 1 -; TUNIT-NEXT: [[TRUETMP9:%.*]] = icmp eq i32 [[TRUETMP8]], [[B]] -; TUNIT-NEXT: br i1 [[TRUETMP9]], label [[EX]], label [[HD]] +; TUNIT-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 +; TUNIT-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] +; TUNIT-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] ; ; CGSCC: Function Attrs: mustprogress nounwind willreturn ; CGSCC-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2 ; CGSCC-SAME: (ptr nonnull [[A:%.*]], i32 [[B:%.*]]) #[[ATTR7]] { ; CGSCC-NEXT: en: -; CGSCC-NEXT: [[TRUETMP3:%.*]] = icmp eq i32 [[B]], 0 -; CGSCC-NEXT: br i1 [[TRUETMP3]], label [[EX:%.*]], label [[HD:%.*]] +; CGSCC-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 +; CGSCC-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] ; CGSCC: ex: -; CGSCC-NEXT: [[TRUETMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR4]] -; CGSCC-NEXT: ret i32 [[TRUETMP5]] +; CGSCC-NEXT: [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR4]] +; CGSCC-NEXT: ret i32 [[TMP5]] ; CGSCC: hd: -; CGSCC-NEXT: [[TRUETMP7:%.*]] = phi i32 [ [[TRUETMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] +; CGSCC-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] ; CGSCC-NEXT: tail call void @h(ptr nonnull [[A]]) #[[ATTR4]] -; CGSCC-NEXT: [[TRUETMP8]] = add nuw i32 [[TRUETMP7]], 1 -; CGSCC-NEXT: [[TRUETMP9:%.*]] = icmp eq i32 [[TRUETMP8]], [[B]] -; CGSCC-NEXT: br i1 [[TRUETMP9]], label [[EX]], label [[HD]] +; CGSCC-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 +; CGSCC-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] +; CGSCC-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] ; en: %tmp3 = icmp eq i32 %b, 0 @@ -1257,37 +1259,37 @@ define i32 @nonnull_exec_ctx_2b(ptr %a, i32 %b) willreturn nounwind { ; TUNIT-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2b ; TUNIT-SAME: (ptr nonnull [[A:%.*]], i32 [[B:%.*]]) #[[ATTR8]] { ; TUNIT-NEXT: en: -; TUNIT-NEXT: [[TRUETMP3:%.*]] = icmp eq i32 [[B]], 0 -; TUNIT-NEXT: br i1 [[TRUETMP3]], label [[EX:%.*]], label [[HD:%.*]] +; TUNIT-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 +; TUNIT-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] ; TUNIT: ex: -; TUNIT-NEXT: [[TRUETMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR5]] -; TUNIT-NEXT: ret i32 [[TRUETMP5]] +; TUNIT-NEXT: [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR5]] +; TUNIT-NEXT: ret i32 [[TMP5]] ; TUNIT: hd: -; TUNIT-NEXT: [[TRUETMP7:%.*]] = phi i32 [ [[TRUETMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] +; TUNIT-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] ; TUNIT-NEXT: tail call void @h(ptr nonnull [[A]]) #[[ATTR5]] ; TUNIT-NEXT: br label [[HD2]] ; TUNIT: hd2: -; TUNIT-NEXT: [[TRUETMP8]] = add nuw i32 [[TRUETMP7]], 1 -; TUNIT-NEXT: [[TRUETMP9:%.*]] = icmp eq i32 [[TRUETMP8]], [[B]] -; TUNIT-NEXT: br i1 [[TRUETMP9]], label [[EX]], label [[HD]] +; TUNIT-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 +; TUNIT-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] +; TUNIT-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] ; ; CGSCC: Function Attrs: mustprogress nounwind willreturn ; CGSCC-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2b ; CGSCC-SAME: (ptr nonnull [[A:%.*]], i32 [[B:%.*]]) #[[ATTR7]] { ; CGSCC-NEXT: en: -; CGSCC-NEXT: [[TRUETMP3:%.*]] = icmp eq i32 [[B]], 0 -; CGSCC-NEXT: br i1 [[TRUETMP3]], label [[EX:%.*]], label [[HD:%.*]] +; CGSCC-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 +; CGSCC-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] ; CGSCC: ex: -; CGSCC-NEXT: [[TRUETMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR4]] -; CGSCC-NEXT: ret i32 [[TRUETMP5]] +; CGSCC-NEXT: [[TMP5:%.*]] = tail call i32 @g(ptr nonnull [[A]]) #[[ATTR4]] +; CGSCC-NEXT: ret i32 [[TMP5]] ; CGSCC: hd: -; CGSCC-NEXT: [[TRUETMP7:%.*]] = phi i32 [ [[TRUETMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] +; CGSCC-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] ; CGSCC-NEXT: tail call void @h(ptr nonnull [[A]]) #[[ATTR4]] ; CGSCC-NEXT: br label [[HD2]] ; CGSCC: hd2: -; CGSCC-NEXT: [[TRUETMP8]] = add nuw i32 [[TRUETMP7]], 1 -; CGSCC-NEXT: [[TRUETMP9:%.*]] = icmp eq i32 [[TRUETMP8]], [[B]] -; CGSCC-NEXT: br i1 [[TRUETMP9]], label [[EX]], label [[HD]] +; CGSCC-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 +; CGSCC-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] +; CGSCC-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] ; en: %tmp3 = icmp eq i32 %b, 0 @@ -1393,7 +1395,7 @@ define ptr @mybasename(ptr nofree readonly %str) { ; TUNIT: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(read) ; TUNIT-LABEL: define {{[^@]+}}@mybasename ; TUNIT-SAME: (ptr nofree readonly [[STR:%.*]]) #[[ATTR14:[0-9]+]] { -; TUNIT-NEXT: [[CALL:%.*]] = call ptr @strrchr(ptr nofree readonly [[STR]], i32 noundef 47) #[[ATTR18:[0-9]+]] +; TUNIT-NEXT: [[CALL:%.*]] = call ptr @strrchr(ptr nofree readonly [[STR]], i32 noundef 47) #[[ATTR19:[0-9]+]] ; TUNIT-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[CALL]], null ; TUNIT-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 1 ; TUNIT-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], ptr [[ADD_PTR]], ptr [[STR]] @@ -1402,7 +1404,7 @@ define ptr @mybasename(ptr nofree readonly %str) { ; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(read) ; CGSCC-LABEL: define {{[^@]+}}@mybasename ; CGSCC-SAME: (ptr nofree readonly [[STR:%.*]]) #[[ATTR14:[0-9]+]] { -; CGSCC-NEXT: [[CALL:%.*]] = call ptr @strrchr(ptr nofree readonly [[STR]], i32 noundef 47) #[[ATTR19:[0-9]+]] +; CGSCC-NEXT: [[CALL:%.*]] = call ptr @strrchr(ptr nofree readonly [[STR]], i32 noundef 47) #[[ATTR20:[0-9]+]] ; CGSCC-NEXT: [[TOBOOL:%.*]] = icmp ne ptr [[CALL]], null ; CGSCC-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, ptr [[CALL]], i64 1 ; CGSCC-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], ptr [[ADD_PTR]], ptr [[STR]] @@ -1425,14 +1427,14 @@ define void @nonnull_assume_pos(ptr %arg) { ; ; TUNIT-LABEL: define {{[^@]+}}@nonnull_assume_pos ; TUNIT-SAME: (ptr nocapture nofree nonnull readnone [[ARG:%.*]]) { -; TUNIT-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR15]] [ "nonnull"(ptr [[ARG]]) ] +; TUNIT-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR16]] [ "nonnull"(ptr [[ARG]]) ] ; TUNIT-NEXT: call void @use_i8_ptr(ptr noalias nocapture nofree nonnull readnone [[ARG]]) #[[ATTR5]] ; TUNIT-NEXT: [[TMP1:%.*]] = call ptr @unknown() ; TUNIT-NEXT: ret void ; ; CGSCC-LABEL: define {{[^@]+}}@nonnull_assume_pos ; CGSCC-SAME: (ptr nocapture nofree nonnull readnone [[ARG:%.*]]) { -; CGSCC-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR15]] [ "nonnull"(ptr [[ARG]]) ] +; CGSCC-NEXT: call void @llvm.assume(i1 noundef true) #[[ATTR16]] [ "nonnull"(ptr [[ARG]]) ] ; CGSCC-NEXT: call void @use_i8_ptr(ptr noalias nocapture nofree nonnull readnone [[ARG]]) #[[ATTR4]] ; CGSCC-NEXT: [[TMP1:%.*]] = call ptr @unknown() ; CGSCC-NEXT: ret void @@ -1554,14 +1556,14 @@ define void @phi_caller(ptr %p) { ; TUNIT: Function Attrs: nounwind ; TUNIT-LABEL: define {{[^@]+}}@phi_caller ; TUNIT-SAME: (ptr nofree [[P:%.*]]) #[[ATTR5]] { -; TUNIT-NEXT: [[C:%.*]] = call nonnull ptr @phi(ptr noalias nofree readnone [[P]]) #[[ATTR19:[0-9]+]] +; TUNIT-NEXT: [[C:%.*]] = call nonnull ptr @phi(ptr noalias nofree readnone [[P]]) #[[ATTR20:[0-9]+]] ; TUNIT-NEXT: call void @use_i8_ptr(ptr noalias nocapture nofree nonnull readnone [[C]]) #[[ATTR5]] ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: nounwind ; CGSCC-LABEL: define {{[^@]+}}@phi_caller ; CGSCC-SAME: (ptr nofree [[P:%.*]]) #[[ATTR4]] { -; CGSCC-NEXT: [[C:%.*]] = call nonnull ptr @phi(ptr noalias nofree readnone [[P]]) #[[ATTR20:[0-9]+]] +; CGSCC-NEXT: [[C:%.*]] = call nonnull ptr @phi(ptr noalias nofree readnone [[P]]) #[[ATTR21:[0-9]+]] ; CGSCC-NEXT: call void @use_i8_ptr(ptr noalias nocapture nofree nonnull readnone [[C]]) #[[ATTR4]] ; CGSCC-NEXT: ret void ; @@ -1594,15 +1596,15 @@ define void @multi_ret_caller(ptr %p) { ; TUNIT: Function Attrs: nounwind ; TUNIT-LABEL: define {{[^@]+}}@multi_ret_caller ; TUNIT-SAME: (ptr nofree [[P:%.*]]) #[[ATTR5]] { -; TUNIT-NEXT: [[C:%.*]] = call nonnull ptr @multi_ret(ptr noalias nofree readnone [[P]]) #[[ATTR19]] -; TUNIT-NEXT: call void @use_i8_ptr(ptr noalias nocapture nofree nonnull readnone [[C]]) #[[ATTR5]] +; TUNIT-NEXT: [[C:%.*]] = call ptr @multi_ret(ptr noalias nofree readnone [[P]]) #[[ATTR20]] +; TUNIT-NEXT: call void @use_i8_ptr(ptr noalias nocapture nofree readnone [[C]]) #[[ATTR5]] ; TUNIT-NEXT: ret void ; ; CGSCC: Function Attrs: nounwind ; CGSCC-LABEL: define {{[^@]+}}@multi_ret_caller ; CGSCC-SAME: (ptr nofree [[P:%.*]]) #[[ATTR4]] { -; CGSCC-NEXT: [[C:%.*]] = call nonnull ptr @multi_ret(ptr noalias nofree readnone [[P]]) #[[ATTR20]] -; CGSCC-NEXT: call void @use_i8_ptr(ptr noalias nocapture nofree nonnull readnone [[C]]) #[[ATTR4]] +; CGSCC-NEXT: [[C:%.*]] = call ptr @multi_ret(ptr noalias nofree readnone [[P]]) #[[ATTR21]] +; CGSCC-NEXT: call void @use_i8_ptr(ptr noalias nocapture nofree readnone [[C]]) #[[ATTR4]] ; CGSCC-NEXT: ret void ; %c = call ptr @multi_ret(ptr %p) @@ -1610,6 +1612,32 @@ define void @multi_ret_caller(ptr %p) { ret void } +@G = internal global i64 1, align 8 +define dso_local ptr @update_global_in_alive_bb() { +; CHECK: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn +; CHECK-LABEL: define {{[^@]+}}@update_global_in_alive_bb +; CHECK-SAME: () #[[ATTR15:[0-9]+]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr @G, align 8 +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[TMP0]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: store i64 0, ptr @G, align 8 +; CHECK-NEXT: ret ptr inttoptr (i64 5 to ptr) +; CHECK: if.else: +; CHECK-NEXT: ret ptr null +; +entry: + %0 = load i64, ptr @G, align 8 + %cmp = icmp ne i64 %0, 0 + br i1 %cmp, label %if.then, label %if.else +if.then: + store i64 0, ptr @G, align 8 + ret ptr inttoptr (i64 5 to ptr) +if.else: + ret ptr null +} + attributes #0 = { null_pointer_is_valid } attributes #1 = { nounwind willreturn} ;. @@ -1628,11 +1656,12 @@ attributes #1 = { nounwind willreturn} ; TUNIT: attributes #[[ATTR12]] = { noinline optnone } ; TUNIT: attributes #[[ATTR13:[0-9]+]] = { nofree nounwind willreturn memory(read) } ; TUNIT: attributes #[[ATTR14]] = { mustprogress nofree nosync nounwind willreturn memory(read) } -; TUNIT: attributes #[[ATTR15]] = { nofree willreturn memory(write) } -; TUNIT: attributes #[[ATTR16]] = { nofree nosync nounwind memory(read) } -; TUNIT: attributes #[[ATTR17]] = { nosync willreturn memory(read) } -; TUNIT: attributes #[[ATTR18]] = { nofree nosync willreturn memory(read) } -; TUNIT: attributes #[[ATTR19]] = { nofree nosync nounwind willreturn memory(none) } +; TUNIT: attributes #[[ATTR15]] = { mustprogress nofree norecurse nosync nounwind willreturn } +; TUNIT: attributes #[[ATTR16]] = { nofree willreturn memory(write) } +; TUNIT: attributes #[[ATTR17]] = { nofree nosync nounwind memory(read) } +; TUNIT: attributes #[[ATTR18]] = { nosync willreturn memory(read) } +; TUNIT: attributes #[[ATTR19]] = { nofree nosync willreturn memory(read) } +; TUNIT: attributes #[[ATTR20]] = { nofree nosync nounwind willreturn memory(none) } ;. ; CGSCC: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) } ; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) } @@ -1649,10 +1678,11 @@ attributes #1 = { nounwind willreturn} ; CGSCC: attributes #[[ATTR12]] = { noinline optnone } ; CGSCC: attributes #[[ATTR13:[0-9]+]] = { nofree nounwind willreturn memory(read) } ; CGSCC: attributes #[[ATTR14]] = { mustprogress nofree nosync nounwind willreturn memory(read) } -; CGSCC: attributes #[[ATTR15]] = { nofree willreturn memory(write) } -; CGSCC: attributes #[[ATTR16]] = { nofree nosync nounwind memory(read) } -; CGSCC: attributes #[[ATTR17]] = { nosync willreturn memory(read) } -; CGSCC: attributes #[[ATTR18]] = { nofree nosync willreturn } -; CGSCC: attributes #[[ATTR19]] = { nofree nosync willreturn memory(read) } -; CGSCC: attributes #[[ATTR20]] = { nofree willreturn } +; CGSCC: attributes #[[ATTR15]] = { mustprogress nofree norecurse nosync nounwind willreturn } +; CGSCC: attributes #[[ATTR16]] = { nofree willreturn memory(write) } +; CGSCC: attributes #[[ATTR17]] = { nofree nosync nounwind memory(read) } +; CGSCC: attributes #[[ATTR18]] = { nosync willreturn memory(read) } +; CGSCC: attributes #[[ATTR19]] = { nofree nosync willreturn } +; CGSCC: attributes #[[ATTR20]] = { nofree nosync willreturn memory(read) } +; CGSCC: attributes #[[ATTR21]] = { nofree willreturn } ;. diff --git a/llvm/test/Transforms/Attributor/value-simplify.ll b/llvm/test/Transforms/Attributor/value-simplify.ll index 0ee06afe92f22..484faac292da1 100644 --- a/llvm/test/Transforms/Attributor/value-simplify.ll +++ b/llvm/test/Transforms/Attributor/value-simplify.ll @@ -508,7 +508,7 @@ define ptr @complicated_args_preallocated() { ; CGSCC-SAME: () #[[ATTR4:[0-9]+]] { ; CGSCC-NEXT: [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 noundef 1) #[[ATTR13]] ; CGSCC-NEXT: [[CALL:%.*]] = call ptr @test_preallocated(ptr nofree noundef writeonly preallocated(i32) align 4294967296 null) #[[ATTR14:[0-9]+]] [ "preallocated"(token [[C]]) ] -; CGSCC-NEXT: unreachable +; CGSCC-NEXT: ret ptr null ; %c = call token @llvm.call.preallocated.setup(i32 1) %call = call ptr @test_preallocated(ptr preallocated(i32) null) ["preallocated"(token %c)] diff --git a/llvm/test/Transforms/FunctionAttrs/nonnull.ll b/llvm/test/Transforms/FunctionAttrs/nonnull.ll index d9bdb6298ed0f..1f525fc8d7740 100644 --- a/llvm/test/Transforms/FunctionAttrs/nonnull.ll +++ b/llvm/test/Transforms/FunctionAttrs/nonnull.ll @@ -8,9 +8,13 @@ declare nonnull ptr @ret_nonnull() ; Return a pointer trivially nonnull (call return attribute) define ptr @test1() { -; COMMON-LABEL: define nonnull ptr @test1() { -; COMMON-NEXT: [[RET:%.*]] = call ptr @ret_nonnull() -; COMMON-NEXT: ret ptr [[RET]] +; FNATTRS-LABEL: define nonnull ptr @test1() { +; FNATTRS-NEXT: [[RET:%.*]] = call ptr @ret_nonnull() +; FNATTRS-NEXT: ret ptr [[RET]] +; +; ATTRIBUTOR-LABEL: define ptr @test1() { +; ATTRIBUTOR-NEXT: [[RET:%.*]] = call ptr @ret_nonnull() +; ATTRIBUTOR-NEXT: ret ptr [[RET]] ; %ret = call ptr @ret_nonnull() ret ptr %ret @@ -22,7 +26,7 @@ define ptr @test2(ptr nonnull %p) { ; FNATTRS-SAME: ptr nonnull readnone returned [[P:%.*]]) #[[ATTR0:[0-9]+]] { ; FNATTRS-NEXT: ret ptr [[P]] ; -; ATTRIBUTOR-LABEL: define nonnull ptr @test2( +; ATTRIBUTOR-LABEL: define ptr @test2( ; ATTRIBUTOR-SAME: ptr nofree nonnull readnone [[P:%.*]]) #[[ATTR0:[0-9]+]] { ; ATTRIBUTOR-NEXT: ret ptr [[P]] ; @@ -59,11 +63,17 @@ end: } define ptr @test3(i1 %c) { -; COMMON-LABEL: define nonnull ptr @test3( -; COMMON-SAME: i1 [[C:%.*]]) { -; COMMON-NEXT: [[TMP1:%.*]] = call ptr @scc_binder(i1 [[C]]) -; COMMON-NEXT: [[RET:%.*]] = call ptr @ret_nonnull() -; COMMON-NEXT: ret ptr [[RET]] +; FNATTRS-LABEL: define nonnull ptr @test3( +; FNATTRS-SAME: i1 [[C:%.*]]) { +; FNATTRS-NEXT: [[TMP1:%.*]] = call ptr @scc_binder(i1 [[C]]) +; FNATTRS-NEXT: [[RET:%.*]] = call ptr @ret_nonnull() +; FNATTRS-NEXT: ret ptr [[RET]] +; +; ATTRIBUTOR-LABEL: define ptr @test3( +; ATTRIBUTOR-SAME: i1 [[C:%.*]]) { +; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = call ptr @scc_binder(i1 [[C]]) +; ATTRIBUTOR-NEXT: [[RET:%.*]] = call ptr @ret_nonnull() +; ATTRIBUTOR-NEXT: ret ptr [[RET]] ; call ptr @scc_binder(i1 %c) %ret = call ptr @ret_nonnull() @@ -149,15 +159,25 @@ define ptr @test5(i1 %c) { ; Local analysis, but going through a self recursive phi define ptr @test6a() { -; COMMON-LABEL: define nonnull ptr @test6a() { -; COMMON-NEXT: entry: -; COMMON-NEXT: [[RET:%.*]] = call ptr @ret_nonnull() -; COMMON-NEXT: br label [[LOOP:%.*]] -; COMMON: loop: -; COMMON-NEXT: [[PHI:%.*]] = phi ptr [ [[RET]], [[ENTRY:%.*]] ], [ [[PHI]], [[LOOP]] ] -; COMMON-NEXT: br i1 undef, label [[LOOP]], label [[EXIT:%.*]] -; COMMON: exit: -; COMMON-NEXT: ret ptr [[PHI]] +; FNATTRS-LABEL: define nonnull ptr @test6a() { +; FNATTRS-NEXT: entry: +; FNATTRS-NEXT: [[RET:%.*]] = call ptr @ret_nonnull() +; FNATTRS-NEXT: br label [[LOOP:%.*]] +; FNATTRS: loop: +; FNATTRS-NEXT: [[PHI:%.*]] = phi ptr [ [[RET]], [[ENTRY:%.*]] ], [ [[PHI]], [[LOOP]] ] +; FNATTRS-NEXT: br i1 undef, label [[LOOP]], label [[EXIT:%.*]] +; FNATTRS: exit: +; FNATTRS-NEXT: ret ptr [[PHI]] +; +; ATTRIBUTOR-LABEL: define ptr @test6a() { +; ATTRIBUTOR-NEXT: entry: +; ATTRIBUTOR-NEXT: [[RET:%.*]] = call ptr @ret_nonnull() +; ATTRIBUTOR-NEXT: br label [[LOOP:%.*]] +; ATTRIBUTOR: loop: +; ATTRIBUTOR-NEXT: [[PHI:%.*]] = phi ptr [ [[RET]], [[ENTRY:%.*]] ], [ [[PHI]], [[LOOP]] ] +; ATTRIBUTOR-NEXT: br i1 undef, label [[LOOP]], label [[EXIT:%.*]] +; ATTRIBUTOR: exit: +; ATTRIBUTOR-NEXT: ret ptr [[PHI]] ; entry: %ret = call ptr @ret_nonnull() @@ -170,16 +190,27 @@ exit: } define ptr @test6b(i1 %c) { -; COMMON-LABEL: define nonnull ptr @test6b( -; COMMON-SAME: i1 [[C:%.*]]) { -; COMMON-NEXT: entry: -; COMMON-NEXT: [[RET:%.*]] = call ptr @ret_nonnull() -; COMMON-NEXT: br label [[LOOP:%.*]] -; COMMON: loop: -; COMMON-NEXT: [[PHI:%.*]] = phi ptr [ [[RET]], [[ENTRY:%.*]] ], [ [[PHI]], [[LOOP]] ] -; COMMON-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] -; COMMON: exit: -; COMMON-NEXT: ret ptr [[PHI]] +; FNATTRS-LABEL: define nonnull ptr @test6b( +; FNATTRS-SAME: i1 [[C:%.*]]) { +; FNATTRS-NEXT: entry: +; FNATTRS-NEXT: [[RET:%.*]] = call ptr @ret_nonnull() +; FNATTRS-NEXT: br label [[LOOP:%.*]] +; FNATTRS: loop: +; FNATTRS-NEXT: [[PHI:%.*]] = phi ptr [ [[RET]], [[ENTRY:%.*]] ], [ [[PHI]], [[LOOP]] ] +; FNATTRS-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] +; FNATTRS: exit: +; FNATTRS-NEXT: ret ptr [[PHI]] +; +; ATTRIBUTOR-LABEL: define ptr @test6b( +; ATTRIBUTOR-SAME: i1 [[C:%.*]]) { +; ATTRIBUTOR-NEXT: entry: +; ATTRIBUTOR-NEXT: [[RET:%.*]] = call ptr @ret_nonnull() +; ATTRIBUTOR-NEXT: br label [[LOOP:%.*]] +; ATTRIBUTOR: loop: +; ATTRIBUTOR-NEXT: [[PHI:%.*]] = phi ptr [ [[RET]], [[ENTRY:%.*]] ], [ [[PHI]], [[LOOP]] ] +; ATTRIBUTOR-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] +; ATTRIBUTOR: exit: +; ATTRIBUTOR-NEXT: ret ptr [[PHI]] ; entry: %ret = call ptr @ret_nonnull() @@ -209,7 +240,7 @@ define ptr @test8(ptr %a) { ; FNATTRS-NEXT: [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 1 ; FNATTRS-NEXT: ret ptr [[B]] ; -; ATTRIBUTOR-LABEL: define nonnull ptr @test8( +; ATTRIBUTOR-LABEL: define ptr @test8( ; ATTRIBUTOR-SAME: ptr nofree readnone [[A:%.*]]) #[[ATTR0]] { ; ATTRIBUTOR-NEXT: [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 1 ; ATTRIBUTOR-NEXT: ret ptr [[B]] @@ -246,7 +277,7 @@ define ptr @test10(ptr %a, i64 %n) { ; ATTRIBUTOR-LABEL: define ptr @test10( ; ATTRIBUTOR-SAME: ptr nofree readnone [[A:%.*]], i64 [[N:%.*]]) #[[ATTR3:[0-9]+]] { ; ATTRIBUTOR-NEXT: [[CMP:%.*]] = icmp ne i64 [[N]], 0 -; ATTRIBUTOR-NEXT: call void @llvm.assume(i1 [[CMP]]) #[[ATTR14:[0-9]+]] +; ATTRIBUTOR-NEXT: call void @llvm.assume(i1 [[CMP]]) #[[ATTR15:[0-9]+]] ; ATTRIBUTOR-NEXT: [[B:%.*]] = getelementptr inbounds i8, ptr [[A]], i64 [[N]] ; ATTRIBUTOR-NEXT: ret ptr [[B]] ; @@ -272,7 +303,7 @@ define ptr @test11(ptr) local_unnamed_addr { ; FNATTRS-NEXT: [[TMP6:%.*]] = phi ptr [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] ; FNATTRS-NEXT: ret ptr [[TMP6]] ; -; ATTRIBUTOR-LABEL: define nonnull ptr @test11( +; ATTRIBUTOR-LABEL: define ptr @test11( ; ATTRIBUTOR-SAME: ptr [[TMP0:%.*]]) local_unnamed_addr { ; ATTRIBUTOR-NEXT: [[TMP2:%.*]] = icmp eq ptr [[TMP0]], null ; ATTRIBUTOR-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] @@ -392,11 +423,11 @@ define internal ptr @f1(ptr %arg) { ; ATTRIBUTOR-NEXT: br i1 [[TMP3]], label [[BB6:%.*]], label [[BB4:%.*]] ; ATTRIBUTOR: bb4: ; ATTRIBUTOR-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 1 -; ATTRIBUTOR-NEXT: [[TMP5B:%.*]] = tail call ptr @f3(ptr readonly [[TMP5]]) #[[ATTR15:[0-9]+]] +; ATTRIBUTOR-NEXT: [[TMP5B:%.*]] = tail call ptr @f3(ptr readonly [[TMP5]]) #[[ATTR16:[0-9]+]] ; ATTRIBUTOR-NEXT: [[TMP5C:%.*]] = getelementptr inbounds i32, ptr [[TMP5B]], i64 -1 ; ATTRIBUTOR-NEXT: br label [[BB9]] ; ATTRIBUTOR: bb6: -; ATTRIBUTOR-NEXT: [[TMP7:%.*]] = tail call ptr @f2(ptr readonly [[ARG]]) #[[ATTR15]] +; ATTRIBUTOR-NEXT: [[TMP7:%.*]] = tail call ptr @f2(ptr readonly [[ARG]]) #[[ATTR16]] ; ATTRIBUTOR-NEXT: ret ptr [[TMP7]] ; ATTRIBUTOR: bb9: ; ATTRIBUTOR-NEXT: [[TMP10:%.*]] = phi ptr [ [[TMP5C]], [[BB4]] ], [ inttoptr (i64 4 to ptr), [[BB:%.*]] ] @@ -438,7 +469,7 @@ define internal ptr @f2(ptr %arg) { ; ATTRIBUTOR-LABEL: define internal ptr @f2( ; ATTRIBUTOR-SAME: ptr readonly [[ARG:%.*]]) #[[ATTR5]] { ; ATTRIBUTOR-NEXT: bb: -; ATTRIBUTOR-NEXT: [[TMP:%.*]] = tail call ptr @f1(ptr readonly [[ARG]]) #[[ATTR15]] +; ATTRIBUTOR-NEXT: [[TMP:%.*]] = tail call ptr @f1(ptr readonly [[ARG]]) #[[ATTR16]] ; ATTRIBUTOR-NEXT: ret ptr [[TMP]] ; bb: @@ -459,7 +490,7 @@ define dso_local noalias ptr @f3(ptr %arg) { ; ATTRIBUTOR-LABEL: define dso_local noalias ptr @f3( ; ATTRIBUTOR-SAME: ptr nofree readonly [[ARG:%.*]]) #[[ATTR5]] { ; ATTRIBUTOR-NEXT: bb: -; ATTRIBUTOR-NEXT: [[TMP:%.*]] = call ptr @f1(ptr nofree readonly [[ARG]]) #[[ATTR15]] +; ATTRIBUTOR-NEXT: [[TMP:%.*]] = call ptr @f1(ptr nofree readonly [[ARG]]) #[[ATTR16]] ; ATTRIBUTOR-NEXT: ret ptr [[TMP]] ; bb: @@ -512,10 +543,10 @@ define void @f16(ptr %a, ptr %b, i8 %c) { ; ATTRIBUTOR-NEXT: [[CMP:%.*]] = icmp eq i8 [[C]], 0 ; ATTRIBUTOR-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; ATTRIBUTOR: if.then: -; ATTRIBUTOR-NEXT: tail call void @fun2(ptr nonnull [[A]], ptr nonnull [[B]]) #[[ATTR16:[0-9]+]] +; ATTRIBUTOR-NEXT: tail call void @fun2(ptr nonnull [[A]], ptr nonnull [[B]]) #[[ATTR17:[0-9]+]] ; ATTRIBUTOR-NEXT: ret void ; ATTRIBUTOR: if.else: -; ATTRIBUTOR-NEXT: tail call void @fun2(ptr nonnull [[A]], ptr [[B]]) #[[ATTR16]] +; ATTRIBUTOR-NEXT: tail call void @fun2(ptr nonnull [[A]], ptr [[B]]) #[[ATTR17]] ; ATTRIBUTOR-NEXT: ret void ; %cmp = icmp eq i8 %c, 0 @@ -554,13 +585,13 @@ define void @f17(ptr %a, i8 %c) { ; ATTRIBUTOR-NEXT: [[CMP:%.*]] = icmp eq i8 [[C]], 0 ; ATTRIBUTOR-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; ATTRIBUTOR: if.then: -; ATTRIBUTOR-NEXT: tail call void @fun0() #[[ATTR16]] +; ATTRIBUTOR-NEXT: tail call void @fun0() #[[ATTR17]] ; ATTRIBUTOR-NEXT: br label [[CONT:%.*]] ; ATTRIBUTOR: if.else: -; ATTRIBUTOR-NEXT: tail call void @fun0() #[[ATTR16]] +; ATTRIBUTOR-NEXT: tail call void @fun0() #[[ATTR17]] ; ATTRIBUTOR-NEXT: br label [[CONT]] ; ATTRIBUTOR: cont: -; ATTRIBUTOR-NEXT: tail call void @fun1(ptr nonnull [[A]]) #[[ATTR16]] +; ATTRIBUTOR-NEXT: tail call void @fun1(ptr nonnull [[A]]) #[[ATTR17]] ; ATTRIBUTOR-NEXT: ret void ; %cmp = icmp eq i8 %c, 0 @@ -615,22 +646,22 @@ define void @f18(ptr %a, ptr %b, i8 %c) { ; ATTRIBUTOR-NEXT: [[CMP1:%.*]] = icmp eq i8 [[C]], 0 ; ATTRIBUTOR-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] ; ATTRIBUTOR: if.then: -; ATTRIBUTOR-NEXT: tail call void @fun0() #[[ATTR16]] +; ATTRIBUTOR-NEXT: tail call void @fun0() #[[ATTR17]] ; ATTRIBUTOR-NEXT: br label [[CONT:%.*]] ; ATTRIBUTOR: if.else: -; ATTRIBUTOR-NEXT: tail call void @fun0() #[[ATTR16]] +; ATTRIBUTOR-NEXT: tail call void @fun0() #[[ATTR17]] ; ATTRIBUTOR-NEXT: br label [[CONT]] ; ATTRIBUTOR: cont: ; ATTRIBUTOR-NEXT: [[CMP2:%.*]] = icmp eq i8 [[C]], 1 ; ATTRIBUTOR-NEXT: br i1 [[CMP2]], label [[CONT_THEN:%.*]], label [[CONT_ELSE:%.*]] ; ATTRIBUTOR: cont.then: -; ATTRIBUTOR-NEXT: tail call void @fun1(ptr nonnull [[B]]) #[[ATTR16]] +; ATTRIBUTOR-NEXT: tail call void @fun1(ptr nonnull [[B]]) #[[ATTR17]] ; ATTRIBUTOR-NEXT: br label [[CONT2:%.*]] ; ATTRIBUTOR: cont.else: -; ATTRIBUTOR-NEXT: tail call void @fun0() #[[ATTR16]] +; ATTRIBUTOR-NEXT: tail call void @fun0() #[[ATTR17]] ; ATTRIBUTOR-NEXT: br label [[CONT2]] ; ATTRIBUTOR: cont2: -; ATTRIBUTOR-NEXT: tail call void @fun1(ptr nonnull [[A]]) #[[ATTR16]] +; ATTRIBUTOR-NEXT: tail call void @fun1(ptr nonnull [[A]]) #[[ATTR17]] ; ATTRIBUTOR-NEXT: ret void ; %cmp1 = icmp eq i8 %c, 0 @@ -883,7 +914,7 @@ define i8 @parent7(ptr %a) { ; ; ATTRIBUTOR-LABEL: define i8 @parent7( ; ATTRIBUTOR-SAME: ptr nonnull [[A:%.*]]) { -; ATTRIBUTOR-NEXT: [[RET:%.*]] = call i8 @use1safecall(ptr nonnull [[A]]) #[[ATTR16]] +; ATTRIBUTOR-NEXT: [[RET:%.*]] = call i8 @use1safecall(ptr nonnull [[A]]) #[[ATTR17]] ; ATTRIBUTOR-NEXT: call void @use1nonnull(ptr nonnull [[A]]) ; ATTRIBUTOR-NEXT: ret i8 [[RET]] ; @@ -905,26 +936,26 @@ define i1 @parent8(ptr %a, ptr %bogus1, ptr %b) personality ptr @esfp{ ; FNATTRS-SAME: ptr nonnull [[A:%.*]], ptr nocapture readnone [[BOGUS1:%.*]], ptr nonnull [[B:%.*]]) #[[ATTR7]] personality ptr @esfp { ; FNATTRS-NEXT: entry: ; FNATTRS-NEXT: invoke void @use2nonnull(ptr [[A]], ptr [[B]]) -; FNATTRS-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]] +; FNATTRS-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]] ; FNATTRS: cont: ; FNATTRS-NEXT: [[NULL_CHECK:%.*]] = icmp eq ptr [[B]], null ; FNATTRS-NEXT: ret i1 [[NULL_CHECK]] ; FNATTRS: exc: ; FNATTRS-NEXT: [[LP:%.*]] = landingpad { ptr, i32 } -; FNATTRS-NEXT: filter [0 x ptr] zeroinitializer +; FNATTRS-NEXT: filter [0 x ptr] zeroinitializer ; FNATTRS-NEXT: unreachable ; ; ATTRIBUTOR-LABEL: define i1 @parent8( ; ATTRIBUTOR-SAME: ptr nonnull [[A:%.*]], ptr nocapture nofree readnone [[BOGUS1:%.*]], ptr nonnull [[B:%.*]]) #[[ATTR8]] personality ptr @esfp { ; ATTRIBUTOR-NEXT: entry: ; ATTRIBUTOR-NEXT: invoke void @use2nonnull(ptr nonnull [[A]], ptr nonnull [[B]]) -; ATTRIBUTOR-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]] +; ATTRIBUTOR-NEXT: to label [[CONT:%.*]] unwind label [[EXC:%.*]] ; ATTRIBUTOR: cont: ; ATTRIBUTOR-NEXT: [[NULL_CHECK:%.*]] = icmp eq ptr [[B]], null ; ATTRIBUTOR-NEXT: ret i1 [[NULL_CHECK]] ; ATTRIBUTOR: exc: ; ATTRIBUTOR-NEXT: [[LP:%.*]] = landingpad { ptr, i32 } -; ATTRIBUTOR-NEXT: filter [0 x ptr] zeroinitializer +; ATTRIBUTOR-NEXT: filter [0 x ptr] zeroinitializer ; ATTRIBUTOR-NEXT: unreachable ; @@ -948,7 +979,7 @@ define ptr @gep1(ptr %p) { ; FNATTRS-NEXT: [[Q:%.*]] = getelementptr inbounds i32, ptr [[P]], i32 1 ; FNATTRS-NEXT: ret ptr [[Q]] ; -; ATTRIBUTOR-LABEL: define nonnull ptr @gep1( +; ATTRIBUTOR-LABEL: define ptr @gep1( ; ATTRIBUTOR-SAME: ptr nofree readnone [[P:%.*]]) #[[ATTR0]] { ; ATTRIBUTOR-NEXT: [[Q:%.*]] = getelementptr inbounds i32, ptr [[P]], i32 1 ; ATTRIBUTOR-NEXT: ret ptr [[Q]] @@ -1415,5 +1446,42 @@ define void @PR43833_simple(ptr %0, i32 %1) { br i1 %11, label %7, label %8 } +@G = internal global i64 1, align 8 +define dso_local ptr @update_global_in_alive_bb() { +; FNATTRS-LABEL: define dso_local noundef ptr @update_global_in_alive_bb( +; FNATTRS-SAME: ) #[[ATTR12:[0-9]+]] { +; FNATTRS-NEXT: entry: +; FNATTRS-NEXT: [[TMP0:%.*]] = load i64, ptr @G, align 8 +; FNATTRS-NEXT: [[CMP:%.*]] = icmp ne i64 [[TMP0]], 0 +; FNATTRS-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; FNATTRS: if.then: +; FNATTRS-NEXT: store i64 0, ptr @G, align 8 +; FNATTRS-NEXT: ret ptr inttoptr (i64 5 to ptr) +; FNATTRS: if.else: +; FNATTRS-NEXT: ret ptr null +; +; ATTRIBUTOR-LABEL: define dso_local ptr @update_global_in_alive_bb( +; ATTRIBUTOR-SAME: ) #[[ATTR14:[0-9]+]] { +; ATTRIBUTOR-NEXT: entry: +; ATTRIBUTOR-NEXT: [[TMP0:%.*]] = load i64, ptr @G, align 8 +; ATTRIBUTOR-NEXT: [[CMP:%.*]] = icmp ne i64 [[TMP0]], 0 +; ATTRIBUTOR-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; ATTRIBUTOR: if.then: +; ATTRIBUTOR-NEXT: store i64 0, ptr @G, align 8 +; ATTRIBUTOR-NEXT: ret ptr inttoptr (i64 5 to ptr) +; ATTRIBUTOR: if.else: +; ATTRIBUTOR-NEXT: ret ptr null +; +entry: + %0 = load i64, ptr @G, align 8 + %cmp = icmp ne i64 %0, 0 + br i1 %cmp, label %if.then, label %if.else +if.then: + store i64 0, ptr @G, align 8 + ret ptr inttoptr (i64 5 to ptr) +if.else: + ret ptr null +} + attributes #0 = { null_pointer_is_valid } attributes #1 = { nounwind willreturn}