diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h --- a/llvm/include/llvm/IR/InstrTypes.h +++ b/llvm/include/llvm/IR/InstrTypes.h @@ -1756,6 +1756,10 @@ bool onlyReadsMemory() const { return doesNotAccessMemory() || hasFnAttr(Attribute::ReadOnly); } + + /// Returns true if this function is guaranteed to return. + bool willReturn() const { return hasFnAttr(Attribute::WillReturn); } + void setOnlyReadsMemory() { addAttribute(AttributeList::FunctionIndex, Attribute::ReadOnly); } diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp --- a/llvm/lib/Transforms/Utils/Local.cpp +++ b/llvm/lib/Transforms/Utils/Local.cpp @@ -420,6 +420,16 @@ return true; } + if (auto *CB = dyn_cast(I)) { + // Treat calls that may not return as alive. If the function containing the + // instruction is will return, all calls must either be dead or return. + // TODO: Remove the intrinsic escape hatch once all intrinsics set + // willreturn properly. + if (!I->getFunction()->willReturn() && !CB->willReturn() && + !isa(I)) + return false; + } + if (!I->mayHaveSideEffects()) return true; diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/fp80.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/fp80.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/fp80.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/fp80.ll @@ -17,11 +17,23 @@ @a = internal global %struct.Foo { i32 1, i64 2 }, align 8 define void @run() { -; NOT_CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone -; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@run -; NOT_CGSCC_NPM-SAME: () [[ATTR0:#.*]] { -; NOT_CGSCC_NPM-NEXT: entry: -; NOT_CGSCC_NPM-NEXT: unreachable +; IS________OPM: Function Attrs: nofree noreturn nosync nounwind readnone +; IS________OPM-LABEL: define {{[^@]+}}@run +; IS________OPM-SAME: () [[ATTR0:#.*]] { +; IS________OPM-NEXT: entry: +; IS________OPM-NEXT: [[TMP0:%.*]] = call i64 @CaptureAStruct(%struct.Foo* nocapture nofree noundef nonnull readonly align 8 dereferenceable(16) @a) [[ATTR0]] +; IS________OPM-NEXT: unreachable +; +; IS__TUNIT_NPM: Function Attrs: nofree noreturn nosync nounwind readnone +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@run +; IS__TUNIT_NPM-SAME: () [[ATTR0:#.*]] { +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[A_CAST:%.*]] = bitcast %struct.Foo* @a to i32* +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[A_CAST]], align 8 +; IS__TUNIT_NPM-NEXT: [[A_0_1:%.*]] = getelementptr [[STRUCT_FOO:%.*]], %struct.Foo* @a, i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i64, i64* [[A_0_1]], align 8 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = call i64 @CaptureAStruct(i32 [[TMP0]], i64 [[TMP1]]) [[ATTR0]] +; IS__TUNIT_NPM-NEXT: unreachable ; ; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@run @@ -86,6 +98,37 @@ ; IS__CGSCC_OPM-NEXT: [[GEP]] = getelementptr [[STRUCT_FOO:%.*]], %struct.Foo* [[A]], i64 0 ; IS__CGSCC_OPM-NEXT: br label [[LOOP]] ; +; IS________OPM: Function Attrs: nofree noreturn nosync nounwind readnone +; IS________OPM-LABEL: define {{[^@]+}}@CaptureAStruct +; IS________OPM-SAME: (%struct.Foo* noalias nofree noundef nonnull byval(%struct.Foo) align 8 dereferenceable(16) [[A:%.*]]) [[ATTR0]] { +; IS________OPM-NEXT: entry: +; IS________OPM-NEXT: [[A_PTR:%.*]] = alloca %struct.Foo*, align 8 +; IS________OPM-NEXT: br label [[LOOP:%.*]] +; IS________OPM: loop: +; IS________OPM-NEXT: [[PHI:%.*]] = phi %struct.Foo* [ null, [[ENTRY:%.*]] ], [ [[GEP:%.*]], [[LOOP]] ] +; IS________OPM-NEXT: [[TMP0:%.*]] = phi %struct.Foo* [ [[A]], [[ENTRY]] ], [ [[TMP0]], [[LOOP]] ] +; IS________OPM-NEXT: store %struct.Foo* [[PHI]], %struct.Foo** [[A_PTR]], align 8 +; IS________OPM-NEXT: [[GEP]] = getelementptr [[STRUCT_FOO:%.*]], %struct.Foo* [[A]], i64 0 +; IS________OPM-NEXT: br label [[LOOP]] +; +; IS__TUNIT_NPM: Function Attrs: nofree noreturn nosync nounwind readnone +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@CaptureAStruct +; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]]) [[ATTR0]] { +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[A_PRIV:%.*]] = alloca [[STRUCT_FOO:%.*]], align 8 +; IS__TUNIT_NPM-NEXT: [[A_PRIV_CAST:%.*]] = bitcast %struct.Foo* [[A_PRIV]] to i32* +; IS__TUNIT_NPM-NEXT: store i32 [[TMP0]], i32* [[A_PRIV_CAST]], align 4 +; IS__TUNIT_NPM-NEXT: [[A_PRIV_0_1:%.*]] = getelementptr [[STRUCT_FOO]], %struct.Foo* [[A_PRIV]], i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: store i64 [[TMP1]], i64* [[A_PRIV_0_1]], align 8 +; IS__TUNIT_NPM-NEXT: [[A_PTR:%.*]] = alloca %struct.Foo*, align 8 +; IS__TUNIT_NPM-NEXT: br label [[LOOP:%.*]] +; IS__TUNIT_NPM: loop: +; IS__TUNIT_NPM-NEXT: [[PHI:%.*]] = phi %struct.Foo* [ null, [[ENTRY:%.*]] ], [ [[GEP:%.*]], [[LOOP]] ] +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = phi %struct.Foo* [ [[A_PRIV]], [[ENTRY]] ], [ [[TMP2]], [[LOOP]] ] +; IS__TUNIT_NPM-NEXT: store %struct.Foo* [[PHI]], %struct.Foo** [[A_PTR]], align 8 +; IS__TUNIT_NPM-NEXT: [[GEP]] = getelementptr [[STRUCT_FOO]], %struct.Foo* [[A_PRIV]], i64 0 +; IS__TUNIT_NPM-NEXT: br label [[LOOP]] +; ; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone ; IS__CGSCC____-LABEL: define {{[^@]+}}@CaptureAStruct ; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]]) [[ATTR2:#.*]] { diff --git a/llvm/test/Transforms/Attributor/align.ll b/llvm/test/Transforms/Attributor/align.ll --- a/llvm/test/Transforms/Attributor/align.ll +++ b/llvm/test/Transforms/Attributor/align.ll @@ -102,30 +102,34 @@ ; TEST 6 ; SCC define i32* @test6_1() #0 { -; NOT_CGSCC_NPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable -; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test6_1 -; NOT_CGSCC_NPM-SAME: () [[ATTR1:#.*]] { -; NOT_CGSCC_NPM-NEXT: unreachable -; -; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn -; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test6_1 -; IS__CGSCC_NPM-SAME: () [[ATTR1:#.*]] { -; IS__CGSCC_NPM-NEXT: unreachable +; NOT_CGSCC_OPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable +; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@test6_1 +; NOT_CGSCC_OPM-SAME: () [[ATTR1:#.*]] { +; NOT_CGSCC_OPM-NEXT: [[RET:%.*]] = tail call i32* @test6_2() [[ATTR11:#.*]] +; NOT_CGSCC_OPM-NEXT: unreachable +; +; IS__CGSCC_OPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test6_1 +; IS__CGSCC_OPM-SAME: () [[ATTR1:#.*]] { +; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = tail call i32* @test6_2() [[ATTR12:#.*]] +; IS__CGSCC_OPM-NEXT: unreachable ; %ret = tail call i32* @test6_2() ret i32* %ret } define i32* @test6_2() #0 { -; NOT_CGSCC_NPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable -; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test6_2 -; NOT_CGSCC_NPM-SAME: () [[ATTR1]] { -; NOT_CGSCC_NPM-NEXT: unreachable -; -; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn -; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test6_2 -; IS__CGSCC_NPM-SAME: () [[ATTR1]] { -; IS__CGSCC_NPM-NEXT: unreachable +; NOT_CGSCC_OPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable +; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@test6_2 +; NOT_CGSCC_OPM-SAME: () [[ATTR1]] { +; NOT_CGSCC_OPM-NEXT: [[RET:%.*]] = tail call i32* @test6_1() [[ATTR11]] +; NOT_CGSCC_OPM-NEXT: unreachable +; +; IS__CGSCC_OPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test6_2 +; IS__CGSCC_OPM-SAME: () [[ATTR1]] { +; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = tail call i32* @test6_1() [[ATTR12]] +; IS__CGSCC_OPM-NEXT: unreachable ; %ret = tail call i32* @test6_1() ret i32* %ret @@ -967,7 +971,7 @@ ; IS__CGSCC_OPM-NEXT: [[C:%.*]] = load i1, i1* @cnd, align 1 ; IS__CGSCC_OPM-NEXT: br i1 [[C]], label [[MT:%.*]], label [[EXIT:%.*]] ; IS__CGSCC_OPM: mt: -; IS__CGSCC_OPM-NEXT: [[V:%.*]] = musttail call i32 @musttail_callee_1(i32* nocapture nofree nonnull readonly dereferenceable(4) [[P]]) [[ATTR12:#.*]] +; IS__CGSCC_OPM-NEXT: [[V:%.*]] = musttail call i32 @musttail_callee_1(i32* nocapture nofree nonnull readonly dereferenceable(4) [[P]]) [[ATTR13:#.*]] ; IS__CGSCC_OPM-NEXT: ret i32 [[V]] ; IS__CGSCC_OPM: exit: ; IS__CGSCC_OPM-NEXT: ret i32 0 @@ -978,7 +982,7 @@ ; IS__CGSCC_NPM-NEXT: [[C:%.*]] = load i1, i1* @cnd, align 1 ; IS__CGSCC_NPM-NEXT: br i1 [[C]], label [[MT:%.*]], label [[EXIT:%.*]] ; IS__CGSCC_NPM: mt: -; IS__CGSCC_NPM-NEXT: [[V:%.*]] = musttail call i32 @musttail_callee_1(i32* nocapture nofree nonnull readonly dereferenceable(4) [[P]]) [[ATTR11:#.*]] +; IS__CGSCC_NPM-NEXT: [[V:%.*]] = musttail call i32 @musttail_callee_1(i32* nocapture nofree nonnull readonly dereferenceable(4) [[P]]) [[ATTR12:#.*]] ; IS__CGSCC_NPM-NEXT: ret i32 [[V]] ; IS__CGSCC_NPM: exit: ; IS__CGSCC_NPM-NEXT: ret i32 0 diff --git a/llvm/test/Transforms/Attributor/nocapture-1.ll b/llvm/test/Transforms/Attributor/nocapture-1.ll --- a/llvm/test/Transforms/Attributor/nocapture-1.ll +++ b/llvm/test/Transforms/Attributor/nocapture-1.ll @@ -849,6 +849,8 @@ ; CHECK: Function Attrs: nounwind ; CHECK-LABEL: define {{[^@]+}}@ptr_uses ; CHECK-SAME: (i8* [[PTR:%.*]], i8* nocapture nonnull writeonly dereferenceable(1) [[WPTR:%.*]]) [[ATTR13:#.*]] { +; CHECK-NEXT: [[CALL_PTR:%.*]] = call i8* @maybe_returned_ptr(i8* readonly [[PTR]]) [[ATTR4]] +; CHECK-NEXT: [[CALL_VAL:%.*]] = call i8 @maybe_returned_val(i8* readonly [[CALL_PTR]]) [[ATTR4]] ; CHECK-NEXT: store i8 0, i8* [[WPTR]], align 1 ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/Attributor/nocapture-2.ll b/llvm/test/Transforms/Attributor/nocapture-2.ll --- a/llvm/test/Transforms/Attributor/nocapture-2.ll +++ b/llvm/test/Transforms/Attributor/nocapture-2.ll @@ -728,7 +728,7 @@ ; CHECK-LABEL: define {{[^@]+}}@not_captured_by_readonly_call_not_returned_either3 ; CHECK-SAME: (i32* nocapture readonly [[B:%.*]], i32* readonly returned [[R:%.*]]) [[ATTR8]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = call i32* @readonly_unknown_r1b(i32* nocapture readonly [[B]], i32* readonly [[R]]) [[ATTR6]] +; CHECK-NEXT: [[CALL:%.*]] = call i32* @readonly_unknown_r1b(i32* nocapture readonly [[B]], i32* readonly [[R]]) [[ATTR8]] ; CHECK-NEXT: ret i32* [[CALL]] ; entry: diff --git a/llvm/test/Transforms/Attributor/nonnull.ll b/llvm/test/Transforms/Attributor/nonnull.ll --- a/llvm/test/Transforms/Attributor/nonnull.ll +++ b/llvm/test/Transforms/Attributor/nonnull.ll @@ -149,11 +149,13 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test4_helper ; NOT_CGSCC_NPM-SAME: () [[ATTR2:#.*]] { +; NOT_CGSCC_NPM-NEXT: [[RET:%.*]] = call i8* @test4() ; NOT_CGSCC_NPM-NEXT: unreachable ; -; IS__CGSCC_NPM: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn +; IS__CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test4_helper ; IS__CGSCC_NPM-SAME: () [[ATTR2:#.*]] { +; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = call i8* @test4() ; IS__CGSCC_NPM-NEXT: unreachable ; %ret = call i8* @test4() @@ -164,11 +166,13 @@ ; NOT_CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test4 ; NOT_CGSCC_NPM-SAME: () [[ATTR2]] { +; NOT_CGSCC_NPM-NEXT: [[RET:%.*]] = call i8* @test4_helper() ; NOT_CGSCC_NPM-NEXT: unreachable ; -; IS__CGSCC_NPM: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn +; IS__CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test4 ; IS__CGSCC_NPM-SAME: () [[ATTR2]] { +; IS__CGSCC_NPM-NEXT: [[RET:%.*]] = call i8* @test4_helper() ; IS__CGSCC_NPM-NEXT: unreachable ; %ret = call i8* @test4_helper() diff --git a/llvm/test/Transforms/Attributor/norecurse.ll b/llvm/test/Transforms/Attributor/norecurse.ll --- a/llvm/test/Transforms/Attributor/norecurse.ll +++ b/llvm/test/Transforms/Attributor/norecurse.ll @@ -34,29 +34,21 @@ } define i32 @indirect_rec() { -; NOT_CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone -; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@indirect_rec -; NOT_CGSCC_NPM-SAME: () [[ATTR2:#.*]] { -; NOT_CGSCC_NPM-NEXT: unreachable -; -; IS__CGSCC_NPM: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn -; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@indirect_rec -; IS__CGSCC_NPM-SAME: () [[ATTR1:#.*]] { -; IS__CGSCC_NPM-NEXT: unreachable +; CHECK: Function Attrs: nofree noreturn nosync nounwind readnone +; CHECK-LABEL: define {{[^@]+}}@indirect_rec +; CHECK-SAME: () [[ATTR2:#.*]] { +; CHECK-NEXT: [[A:%.*]] = call i32 @indirect_rec2() [[ATTR2]] +; CHECK-NEXT: unreachable ; %a = call i32 @indirect_rec2() ret i32 %a } define i32 @indirect_rec2() { -; NOT_CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone -; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@indirect_rec2 -; NOT_CGSCC_NPM-SAME: () [[ATTR2]] { -; NOT_CGSCC_NPM-NEXT: unreachable -; -; IS__CGSCC_NPM: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn -; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@indirect_rec2 -; IS__CGSCC_NPM-SAME: () [[ATTR1]] { -; IS__CGSCC_NPM-NEXT: unreachable +; CHECK: Function Attrs: nofree noreturn nosync nounwind readnone +; CHECK-LABEL: define {{[^@]+}}@indirect_rec2 +; CHECK-SAME: () [[ATTR2]] { +; CHECK-NEXT: [[A:%.*]] = call i32 @indirect_rec() [[ATTR2]] +; CHECK-NEXT: unreachable ; %a = call i32 @indirect_rec() ret i32 %a @@ -65,7 +57,7 @@ define i32 @extern() { ; CHECK: Function Attrs: nosync readnone ; CHECK-LABEL: define {{[^@]+}}@extern -; CHECK-SAME: () [[ATTR2:#.*]] { +; CHECK-SAME: () [[ATTR3:#.*]] { ; CHECK-NEXT: [[A:%.*]] = call i32 @k() ; CHECK-NEXT: ret i32 [[A]] ; @@ -78,17 +70,11 @@ declare i32 @k() readnone define void @intrinsic(i8* %dest, i8* %src, i32 %len) { -; NOT_CGSCC_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn -; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@intrinsic -; NOT_CGSCC_NPM-SAME: (i8* nocapture nofree writeonly [[DEST:%.*]], i8* nocapture nofree readonly [[SRC:%.*]], i32 [[LEN:%.*]]) [[ATTR5:#.*]] { -; NOT_CGSCC_NPM-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture nofree writeonly [[DEST]], i8* noalias nocapture nofree readonly [[SRC]], i32 [[LEN]], i1 noundef false) [[ATTR10:#.*]] -; NOT_CGSCC_NPM-NEXT: ret void -; -; IS__CGSCC_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn -; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@intrinsic -; IS__CGSCC_NPM-SAME: (i8* nocapture nofree writeonly [[DEST:%.*]], i8* nocapture nofree readonly [[SRC:%.*]], i32 [[LEN:%.*]]) [[ATTR4:#.*]] { -; IS__CGSCC_NPM-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture nofree writeonly [[DEST]], i8* noalias nocapture nofree readonly [[SRC]], i32 [[LEN]], i1 noundef false) [[ATTR7:#.*]] -; IS__CGSCC_NPM-NEXT: ret void +; CHECK: Function Attrs: argmemonly nofree nosync nounwind willreturn +; CHECK-LABEL: define {{[^@]+}}@intrinsic +; CHECK-SAME: (i8* nocapture nofree writeonly [[DEST:%.*]], i8* nocapture nofree readonly [[SRC:%.*]], i32 [[LEN:%.*]]) [[ATTR5:#.*]] { +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture nofree writeonly [[DEST]], i8* noalias nocapture nofree readonly [[SRC]], i32 [[LEN]], i1 noundef false) [[ATTR10:#.*]] +; CHECK-NEXT: ret void ; call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dest, i8* %src, i32 %len, i1 false) ret void @@ -107,7 +93,7 @@ ; ; IS__CGSCC____: Function Attrs: norecurse nosync readnone ; IS__CGSCC____-LABEL: define {{[^@]+}}@called_by_norecurse -; IS__CGSCC____-SAME: () [[ATTR5:#.*]] { +; IS__CGSCC____-SAME: () [[ATTR6:#.*]] { ; IS__CGSCC____-NEXT: [[A:%.*]] = call i32 @k() ; IS__CGSCC____-NEXT: ret i32 undef ; @@ -123,7 +109,7 @@ ; ; IS__CGSCC____: Function Attrs: norecurse nosync readnone ; IS__CGSCC____-LABEL: define {{[^@]+}}@m -; IS__CGSCC____-SAME: () [[ATTR5]] { +; IS__CGSCC____-SAME: () [[ATTR6]] { ; IS__CGSCC____-NEXT: [[A:%.*]] = call i32 @called_by_norecurse() ; IS__CGSCC____-NEXT: ret void ; @@ -134,7 +120,7 @@ define internal i32 @called_by_norecurse_indirectly() { ; CHECK: Function Attrs: nosync readnone ; CHECK-LABEL: define {{[^@]+}}@called_by_norecurse_indirectly -; CHECK-SAME: () [[ATTR2]] { +; CHECK-SAME: () [[ATTR3]] { ; CHECK-NEXT: [[A:%.*]] = call i32 @k() ; CHECK-NEXT: ret i32 [[A]] ; @@ -150,7 +136,7 @@ ; ; IS__CGSCC____: Function Attrs: norecurse nosync readnone ; IS__CGSCC____-LABEL: define {{[^@]+}}@o -; IS__CGSCC____-SAME: () [[ATTR5]] { +; IS__CGSCC____-SAME: () [[ATTR6]] { ; IS__CGSCC____-NEXT: [[A:%.*]] = call i32 @called_by_norecurse_indirectly() ; IS__CGSCC____-NEXT: ret i32 [[A]] ; @@ -166,7 +152,7 @@ ; ; IS__CGSCC____: Function Attrs: norecurse nosync readnone ; IS__CGSCC____-LABEL: define {{[^@]+}}@p -; IS__CGSCC____-SAME: () [[ATTR5]] { +; IS__CGSCC____-SAME: () [[ATTR6]] { ; IS__CGSCC____-NEXT: [[A:%.*]] = call i32 @o() ; IS__CGSCC____-NEXT: ret i32 [[A]] ; @@ -175,48 +161,20 @@ } define void @f(i32 %x) { -; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone -; IS__TUNIT____-LABEL: define {{[^@]+}}@f -; IS__TUNIT____-SAME: (i32 [[X:%.*]]) [[ATTR7:#.*]] { -; IS__TUNIT____-NEXT: entry: -; IS__TUNIT____-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4 -; IS__TUNIT____-NEXT: store i32 [[X]], i32* [[X_ADDR]], align 4 -; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32, i32* [[X_ADDR]], align 4 -; IS__TUNIT____-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[TMP0]], 0 -; IS__TUNIT____-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] -; IS__TUNIT____: if.then: -; IS__TUNIT____-NEXT: call void @g() [[ATTR8:#.*]] -; IS__TUNIT____-NEXT: br label [[IF_END]] -; IS__TUNIT____: if.end: -; IS__TUNIT____-NEXT: ret void -; -; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone -; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f -; IS__CGSCC_OPM-SAME: (i32 [[X:%.*]]) [[ATTR7:#.*]] { -; IS__CGSCC_OPM-NEXT: entry: -; IS__CGSCC_OPM-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4 -; IS__CGSCC_OPM-NEXT: store i32 [[X]], i32* [[X_ADDR]], align 4 -; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[X_ADDR]], align 4 -; IS__CGSCC_OPM-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[TMP0]], 0 -; IS__CGSCC_OPM-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] -; IS__CGSCC_OPM: if.then: -; IS__CGSCC_OPM-NEXT: br label [[IF_END]] -; IS__CGSCC_OPM: if.end: -; IS__CGSCC_OPM-NEXT: ret void -; -; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f -; IS__CGSCC_NPM-SAME: (i32 [[X:%.*]]) [[ATTR0:#.*]] { -; IS__CGSCC_NPM-NEXT: entry: -; IS__CGSCC_NPM-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4 -; IS__CGSCC_NPM-NEXT: store i32 [[X]], i32* [[X_ADDR]], align 4 -; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[X_ADDR]], align 4 -; IS__CGSCC_NPM-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[TMP0]], 0 -; IS__CGSCC_NPM-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] -; IS__CGSCC_NPM: if.then: -; IS__CGSCC_NPM-NEXT: br label [[IF_END]] -; IS__CGSCC_NPM: if.end: -; IS__CGSCC_NPM-NEXT: ret void +; CHECK: Function Attrs: nofree nosync nounwind readnone +; CHECK-LABEL: define {{[^@]+}}@f +; CHECK-SAME: (i32 [[X:%.*]]) [[ATTR7:#.*]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4 +; CHECK-NEXT: store i32 [[X]], i32* [[X_ADDR]], align 4 +; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[X_ADDR]], align 4 +; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[TMP0]], 0 +; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] +; CHECK: if.then: +; CHECK-NEXT: call void @g() [[ATTR8:#.*]] +; CHECK-NEXT: br label [[IF_END]] +; CHECK: if.end: +; CHECK-NEXT: ret void ; entry: %x.addr = alloca i32, align 4 @@ -234,24 +192,12 @@ } define void @g() norecurse { -; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone -; IS__TUNIT____-LABEL: define {{[^@]+}}@g -; IS__TUNIT____-SAME: () [[ATTR8]] { -; IS__TUNIT____-NEXT: entry: -; IS__TUNIT____-NEXT: ret void -; -; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone -; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@g -; IS__CGSCC_OPM-SAME: () [[ATTR8:#.*]] { -; IS__CGSCC_OPM-NEXT: entry: -; IS__CGSCC_OPM-NEXT: call void @f(i32 noundef 0) [[ATTR7]] -; IS__CGSCC_OPM-NEXT: ret void -; -; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@g -; IS__CGSCC_NPM-SAME: () [[ATTR0]] { -; IS__CGSCC_NPM-NEXT: entry: -; IS__CGSCC_NPM-NEXT: ret void +; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone +; CHECK-LABEL: define {{[^@]+}}@g +; CHECK-SAME: () [[ATTR8]] { +; CHECK-NEXT: entry: +; CHECK-NEXT: call void @f(i32 noundef 0) [[ATTR7]] +; CHECK-NEXT: ret void ; entry: call void @f(i32 0) @@ -279,7 +225,7 @@ define i32 @eval_func2(i32 (i32)* , i32) local_unnamed_addr null_pointer_is_valid{ ; CHECK: Function Attrs: null_pointer_is_valid ; CHECK-LABEL: define {{[^@]+}}@eval_func2 -; CHECK-SAME: (i32 (i32)* nocapture nofree [[TMP0:%.*]], i32 [[TMP1:%.*]]) local_unnamed_addr [[ATTR6:#.*]] { +; CHECK-SAME: (i32 (i32)* nocapture nofree [[TMP0:%.*]], i32 [[TMP1:%.*]]) local_unnamed_addr [[ATTR9:#.*]] { ; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 [[TMP0]](i32 [[TMP1]]) ; CHECK-NEXT: ret i32 [[TMP3]] ; diff --git a/llvm/test/Transforms/Attributor/range.ll b/llvm/test/Transforms/Attributor/range.ll --- a/llvm/test/Transforms/Attributor/range.ll +++ b/llvm/test/Transforms/Attributor/range.ll @@ -600,7 +600,7 @@ ; ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f1 ; IS__CGSCC_OPM-SAME: (i32 [[TMP0:%.*]]) { -; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = tail call i32 @r1(), [[RNG3:!range !.*]] +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = tail call i32 @r1() [[ATTR4:#.*]], [[RNG3:!range !.*]] ; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP2]], 15 ; IS__CGSCC_OPM-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP5:%.*]] ; IS__CGSCC_OPM: 4: @@ -698,7 +698,7 @@ ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test4-g1 ; IS__CGSCC_OPM-SAME: (i32 [[U:%.*]]) [[ATTR2:#.*]] { ; IS__CGSCC_OPM-NEXT: entry: -; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = tail call i32 @test4-f1(i32 [[U]]) [[ATTR4:#.*]] +; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = tail call i32 @test4-f1(i32 [[U]]) [[ATTR5:#.*]] ; IS__CGSCC_OPM-NEXT: ret i32 [[CALL]] ; ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn @@ -790,7 +790,7 @@ ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test4-g2 ; IS__CGSCC_OPM-SAME: (i32 [[U:%.*]]) [[ATTR2]] { ; IS__CGSCC_OPM-NEXT: entry: -; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = tail call i32 @test4-f2(i32 [[U]]) [[ATTR4]] +; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = tail call i32 @test4-f2(i32 [[U]]) [[ATTR5]] ; IS__CGSCC_OPM-NEXT: ret i32 [[CALL]] ; ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn @@ -1154,10 +1154,10 @@ ; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@fcmp_caller ; IS__CGSCC_OPM-SAME: (float [[FA:%.*]], float [[FB:%.*]], double [[DA:%.*]], double [[DB:%.*]], double* nofree readnone [[DPA:%.*]], double* nofree readnone [[DPB:%.*]], i8* nofree readnone [[IPA:%.*]], i8* nofree readnone [[IPB:%.*]]) [[ATTR2]] { -; IS__CGSCC_OPM-NEXT: [[R1:%.*]] = call i1 @f_fcmp(float [[FA]], float [[FB]]) [[ATTR4]] -; IS__CGSCC_OPM-NEXT: [[R2:%.*]] = call i1 @d_fcmp(double [[DA]], double [[DB]]) [[ATTR4]] -; IS__CGSCC_OPM-NEXT: [[R3:%.*]] = call i1 @dp_icmp(double* noalias nofree readnone [[DPA]], double* noalias nofree readnone [[DPB]]) [[ATTR4]] -; IS__CGSCC_OPM-NEXT: [[R4:%.*]] = call i1 @ip_icmp(i8* noalias nofree readnone [[IPA]], i8* noalias nofree readnone [[IPB]]) [[ATTR4]] +; IS__CGSCC_OPM-NEXT: [[R1:%.*]] = call i1 @f_fcmp(float [[FA]], float [[FB]]) [[ATTR5]] +; IS__CGSCC_OPM-NEXT: [[R2:%.*]] = call i1 @d_fcmp(double [[DA]], double [[DB]]) [[ATTR5]] +; IS__CGSCC_OPM-NEXT: [[R3:%.*]] = call i1 @dp_icmp(double* noalias nofree readnone [[DPA]], double* noalias nofree readnone [[DPB]]) [[ATTR5]] +; IS__CGSCC_OPM-NEXT: [[R4:%.*]] = call i1 @ip_icmp(i8* noalias nofree readnone [[IPA]], i8* noalias nofree readnone [[IPB]]) [[ATTR5]] ; IS__CGSCC_OPM-NEXT: [[O1:%.*]] = or i1 [[R1]], [[R2]] ; IS__CGSCC_OPM-NEXT: [[O2:%.*]] = or i1 [[R3]], [[R4]] ; IS__CGSCC_OPM-NEXT: [[O3:%.*]] = or i1 [[O1]], [[O2]] @@ -1329,8 +1329,8 @@ ; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@callee_range_2 ; IS__CGSCC_OPM-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]]) [[ATTR2]] { -; IS__CGSCC_OPM-NEXT: [[R1:%.*]] = call i32 @ret1or2(i1 [[C1]]) [[ATTR4]], [[RNG5:!range !.*]] -; IS__CGSCC_OPM-NEXT: [[R2:%.*]] = call i32 @ret1or2(i1 [[C2]]) [[ATTR4]], [[RNG5]] +; IS__CGSCC_OPM-NEXT: [[R1:%.*]] = call i32 @ret1or2(i1 [[C1]]) [[ATTR5]], [[RNG5:!range !.*]] +; IS__CGSCC_OPM-NEXT: [[R2:%.*]] = call i32 @ret1or2(i1 [[C2]]) [[ATTR5]], [[RNG5]] ; IS__CGSCC_OPM-NEXT: [[A:%.*]] = add i32 [[R1]], [[R2]] ; IS__CGSCC_OPM-NEXT: [[I1:%.*]] = icmp sle i32 [[A]], 3 ; IS__CGSCC_OPM-NEXT: [[I2:%.*]] = icmp sge i32 [[A]], 2 @@ -1488,10 +1488,10 @@ ; IS__CGSCC_OPM-NEXT: [[C:%.*]] = select i1 [[D]], i1 true, i1 false ; IS__CGSCC_OPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] ; IS__CGSCC_OPM: t: -; IS__CGSCC_OPM-NEXT: [[RET1:%.*]] = call i32 @func(i1 noundef [[C]]) [[ATTR4]], [[RNG4:!range !.*]] +; IS__CGSCC_OPM-NEXT: [[RET1:%.*]] = call i32 @func(i1 noundef [[C]]) [[ATTR5]], [[RNG4:!range !.*]] ; IS__CGSCC_OPM-NEXT: ret i32 [[RET1]] ; IS__CGSCC_OPM: f: -; IS__CGSCC_OPM-NEXT: [[RET2:%.*]] = call i32 @func(i1 noundef false) [[ATTR4]], [[RNG4]] +; IS__CGSCC_OPM-NEXT: [[RET2:%.*]] = call i32 @func(i1 noundef false) [[ATTR5]], [[RNG4]] ; IS__CGSCC_OPM-NEXT: ret i32 [[RET2]] ; ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn @@ -1575,10 +1575,10 @@ ; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@check_divided_range ; IS__CGSCC_OPM-SAME: (i32 [[ARG:%.*]]) [[ATTR2]] { -; IS__CGSCC_OPM-NEXT: [[CSRET1:%.*]] = call i32 @less_than_65536(i32 noundef 0) [[ATTR4]] -; IS__CGSCC_OPM-NEXT: [[CSRET2:%.*]] = call i32 @less_than_65536(i32 [[ARG]]) [[ATTR4]] -; IS__CGSCC_OPM-NEXT: [[TRUE1:%.*]] = call i1 @is_less_than_65536(i32 [[CSRET1]]) [[ATTR4]] -; IS__CGSCC_OPM-NEXT: [[TRUE2:%.*]] = call i1 @is_less_than_65536(i32 [[CSRET2]]) [[ATTR4]] +; IS__CGSCC_OPM-NEXT: [[CSRET1:%.*]] = call i32 @less_than_65536(i32 noundef 0) [[ATTR5]] +; IS__CGSCC_OPM-NEXT: [[CSRET2:%.*]] = call i32 @less_than_65536(i32 [[ARG]]) [[ATTR5]] +; IS__CGSCC_OPM-NEXT: [[TRUE1:%.*]] = call i1 @is_less_than_65536(i32 [[CSRET1]]) [[ATTR5]] +; IS__CGSCC_OPM-NEXT: [[TRUE2:%.*]] = call i1 @is_less_than_65536(i32 [[CSRET2]]) [[ATTR5]] ; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = and i1 [[TRUE1]], [[TRUE2]] ; IS__CGSCC_OPM-NEXT: ret i1 [[RET]] ; @@ -1930,7 +1930,7 @@ ; IS__CGSCC_OPM-NEXT: [[C:%.*]] = icmp slt i8 0, [[L]] ; IS__CGSCC_OPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] ; IS__CGSCC_OPM: t: -; IS__CGSCC_OPM-NEXT: [[R:%.*]] = call i1 @non_zero(i8 [[L]]) [[ATTR4]] +; IS__CGSCC_OPM-NEXT: [[R:%.*]] = call i1 @non_zero(i8 [[L]]) [[ATTR5]] ; IS__CGSCC_OPM-NEXT: ret i1 [[R]] ; IS__CGSCC_OPM: f: ; IS__CGSCC_OPM-NEXT: ret i1 false diff --git a/llvm/test/Transforms/Attributor/readattrs.ll b/llvm/test/Transforms/Attributor/readattrs.ll --- a/llvm/test/Transforms/Attributor/readattrs.ll +++ b/llvm/test/Transforms/Attributor/readattrs.ll @@ -204,7 +204,7 @@ ; CHECK: Function Attrs: argmemonly nounwind readonly ; CHECK-LABEL: define {{[^@]+}}@test11_2 ; CHECK-SAME: (<4 x i32*> [[PTRS:%.*]]) [[ATTR6:#.*]] { -; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @test11_1(<4 x i32*> [[PTRS]]) [[ATTR2]] +; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @test11_1(<4 x i32*> [[PTRS]]) [[ATTR9:#.*]] ; CHECK-NEXT: ret <4 x i32> [[RES]] ; %res = call <4 x i32> @test11_1(<4 x i32*> %ptrs) @@ -323,7 +323,7 @@ define void @byval_not_readnone_1(i8* byval(i8) %written) readnone { ; CHECK: Function Attrs: readnone ; CHECK-LABEL: define {{[^@]+}}@byval_not_readnone_1 -; CHECK-SAME: (i8* noalias nonnull byval(i8) dereferenceable(1) [[WRITTEN:%.*]]) [[ATTR9:#.*]] { +; CHECK-SAME: (i8* noalias nonnull byval(i8) dereferenceable(1) [[WRITTEN:%.*]]) [[ATTR8:#.*]] { ; CHECK-NEXT: call void @escape_i8(i8* nonnull dereferenceable(1) [[WRITTEN]]) ; CHECK-NEXT: ret void ; @@ -395,7 +395,9 @@ define void @ptr_uses(i8* %ptr) { ; CHECK: Function Attrs: nounwind readonly ; CHECK-LABEL: define {{[^@]+}}@ptr_uses -; CHECK-SAME: (i8* nocapture readonly [[PTR:%.*]]) [[ATTR10:#.*]] { +; CHECK-SAME: (i8* nocapture readonly [[PTR:%.*]]) [[ATTR9:#.*]] { +; CHECK-NEXT: [[CALL_PTR:%.*]] = call i8* @maybe_returned_ptr(i8* readonly [[PTR]]) +; CHECK-NEXT: [[CALL_VAL:%.*]] = call i8 @maybe_returned_val(i8* readonly [[CALL_PTR]]) ; CHECK-NEXT: ret void ; %call_ptr = call i8* @maybe_returned_ptr(i8* %ptr) diff --git a/llvm/test/Transforms/BDCE/basic.ll b/llvm/test/Transforms/BDCE/basic.ll --- a/llvm/test/Transforms/BDCE/basic.ll +++ b/llvm/test/Transforms/BDCE/basic.ll @@ -392,6 +392,6 @@ ret i16 %cast } -attributes #0 = { nounwind readnone } +attributes #0 = { nounwind readnone willreturn } attributes #1 = { nounwind } diff --git a/llvm/test/Transforms/CodeGenPrepare/X86/delete-assume-dead-code.ll b/llvm/test/Transforms/CodeGenPrepare/X86/delete-assume-dead-code.ll --- a/llvm/test/Transforms/CodeGenPrepare/X86/delete-assume-dead-code.ll +++ b/llvm/test/Transforms/CodeGenPrepare/X86/delete-assume-dead-code.ll @@ -21,7 +21,7 @@ if.end: %gep = getelementptr i8, i8* %d, i32 42 - %call = call i64 @foo(i8* %gep) nounwind readonly + %call = call i64 @foo(i8* %gep) nounwind readonly willreturn %cmp2 = icmp ne i64 %call, 0 call void @llvm.assume(i1 %cmp2) br label %exit @@ -31,5 +31,5 @@ ret i32 %conv } -declare i64 @foo(i8*) nounwind readonly +declare i64 @foo(i8*) nounwind readonly willreturn declare void @llvm.assume(i1 noundef) nounwind willreturn diff --git a/llvm/test/Transforms/Coroutines/coro-split-00.ll b/llvm/test/Transforms/Coroutines/coro-split-00.ll --- a/llvm/test/Transforms/Coroutines/coro-split-00.ll +++ b/llvm/test/Transforms/Coroutines/coro-split-00.ll @@ -77,4 +77,4 @@ declare noalias i8* @malloc(i32) declare void @print(i32) -declare void @free(i8*) +declare void @free(i8*) willreturn diff --git a/llvm/test/Transforms/Coroutines/coro-split-hidden.ll b/llvm/test/Transforms/Coroutines/coro-split-hidden.ll --- a/llvm/test/Transforms/Coroutines/coro-split-hidden.ll +++ b/llvm/test/Transforms/Coroutines/coro-split-hidden.ll @@ -79,4 +79,4 @@ declare noalias i8* @malloc(i32) declare void @print(i32) -declare void @free(i8*) +declare void @free(i8*) willreturn diff --git a/llvm/test/Transforms/Coroutines/no-suspend.ll b/llvm/test/Transforms/Coroutines/no-suspend.ll --- a/llvm/test/Transforms/Coroutines/no-suspend.ll +++ b/llvm/test/Transforms/Coroutines/no-suspend.ll @@ -415,7 +415,7 @@ } declare i8* @malloc(i32) -declare void @free(i8*) +declare void @free(i8*) willreturn declare void @print(i32) declare void @foo() diff --git a/llvm/test/Transforms/DeadStoreElimination/MSSA/simple.ll b/llvm/test/Transforms/DeadStoreElimination/MSSA/simple.ll --- a/llvm/test/Transforms/DeadStoreElimination/MSSA/simple.ll +++ b/llvm/test/Transforms/DeadStoreElimination/MSSA/simple.ll @@ -234,8 +234,8 @@ } -declare noalias i8* @malloc(i32) -declare noalias i8* @calloc(i32, i32) +declare noalias i8* @malloc(i32) willreturn +declare noalias i8* @calloc(i32, i32) willreturn define void @test14(i32* %Q) { ; CHECK-LABEL: @test14( diff --git a/llvm/test/Transforms/DeadStoreElimination/MemDepAnalysis/DeleteThrowableInst.ll b/llvm/test/Transforms/DeadStoreElimination/MemDepAnalysis/DeleteThrowableInst.ll --- a/llvm/test/Transforms/DeadStoreElimination/MemDepAnalysis/DeleteThrowableInst.ll +++ b/llvm/test/Transforms/DeadStoreElimination/MemDepAnalysis/DeleteThrowableInst.ll @@ -1,8 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -basic-aa -dse -enable-dse-memoryssa=false -S | FileCheck %s -declare i8* @_Znwj(i32) local_unnamed_addr -declare void @foo() readnone +declare i8* @_Znwj(i32) willreturn +declare void @foo() readnone willreturn define void @test1(i8** %ptr) { ; CHECK-LABEL: @test1( diff --git a/llvm/test/Transforms/DeadStoreElimination/MemDepAnalysis/simple.ll b/llvm/test/Transforms/DeadStoreElimination/MemDepAnalysis/simple.ll --- a/llvm/test/Transforms/DeadStoreElimination/MemDepAnalysis/simple.ll +++ b/llvm/test/Transforms/DeadStoreElimination/MemDepAnalysis/simple.ll @@ -267,8 +267,8 @@ ret i32 addrspace(1)* %P } -declare noalias i8* @malloc(i32) -declare noalias i8* @calloc(i32, i32) +declare noalias i8* @malloc(i32) willreturn +declare noalias i8* @calloc(i32, i32) willreturn declare noalias i8* @aligned_alloc(i32, i32) declare void @free(i8*) diff --git a/llvm/test/Transforms/Inline/dead-calls-willreturn.ll b/llvm/test/Transforms/Inline/dead-calls-willreturn.ll --- a/llvm/test/Transforms/Inline/dead-calls-willreturn.ll +++ b/llvm/test/Transforms/Inline/dead-calls-willreturn.ll @@ -31,6 +31,10 @@ define void @caller_may_not_return() ssp { ; CHECK-LABEL: @caller_may_not_return( ; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[WHILE_BODY_I:%.*]] +; CHECK: while.body.i: +; CHECK-NEXT: br label [[WHILE_BODY_I]] +; CHECK: readnone_may_not_return.exit: ; CHECK-NEXT: ret void ; entry: diff --git a/llvm/test/Transforms/InstCombine/constant-fold-libfunc.ll b/llvm/test/Transforms/InstCombine/constant-fold-libfunc.ll --- a/llvm/test/Transforms/InstCombine/constant-fold-libfunc.ll +++ b/llvm/test/Transforms/InstCombine/constant-fold-libfunc.ll @@ -1,6 +1,6 @@ ; RUN: opt < %s -instcombine -S | FileCheck %s -declare double @acos(double) +declare double @acos(double) willreturn ; Check that functions without any function attributes are simplified. diff --git a/llvm/test/Transforms/InstCombine/nothrow.ll b/llvm/test/Transforms/InstCombine/nothrow.ll --- a/llvm/test/Transforms/InstCombine/nothrow.ll +++ b/llvm/test/Transforms/InstCombine/nothrow.ll @@ -1,6 +1,6 @@ ; RUN: opt < %s -instcombine -S | not grep call ; rdar://6880732 -declare double @t1(i32) readonly +declare double @t1(i32) readonly willreturn define void @t2() nounwind { call double @t1(i32 42) ;; dead call even though callee is not nothrow. diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/rint.ll b/llvm/test/Transforms/InstSimplify/ConstProp/rint.ll --- a/llvm/test/Transforms/InstSimplify/ConstProp/rint.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/rint.ll @@ -2,13 +2,13 @@ ; RUN: opt -S -early-cse -earlycse-debug-hash < %s | FileCheck %s declare float @nearbyintf(float) #0 -declare float @llvm.nearbyint.f32(float) #0 +declare float @llvm.nearbyint.f32(float) declare double @nearbyint(double) #0 -declare double @llvm.nearbyint.f64(double) #0 +declare double @llvm.nearbyint.f64(double) declare float @rintf(float) #0 -declare float @llvm.rint.f32(float) #0 +declare float @llvm.rint.f32(float) declare double @rint(double) #0 -declare double @llvm.rint.f64(double) #0 +declare double @llvm.rint.f64(double) define float @constant_fold_rint_f32_01() #0 { ; CHECK-LABEL: @constant_fold_rint_f32_01( @@ -106,4 +106,4 @@ ret double %x } -attributes #0 = { nounwind readnone } +attributes #0 = { nounwind readnone willreturn } diff --git a/llvm/test/Transforms/InstSimplify/remove-dead-call.ll b/llvm/test/Transforms/InstSimplify/remove-dead-call.ll --- a/llvm/test/Transforms/InstSimplify/remove-dead-call.ll +++ b/llvm/test/Transforms/InstSimplify/remove-dead-call.ll @@ -9,9 +9,9 @@ define internal void @func_1(i64* nocapture readnone %0) #0 { ; CHECK-LABEL: @func_1( -; CHECK-NEXT: unreachable +; CHECK-NEXT: ret void ; - unreachable + ret void } define i16 @main(i16 %0, i16** nocapture readnone %1) #1 { @@ -24,5 +24,5 @@ unreachable } -attributes #0 = { noinline norecurse nounwind readnone } +attributes #0 = { noinline norecurse nounwind readnone willreturn } attributes #1 = { norecurse nounwind readnone } diff --git a/llvm/test/Transforms/InstSimplify/returned.ll b/llvm/test/Transforms/InstSimplify/returned.ll --- a/llvm/test/Transforms/InstSimplify/returned.ll +++ b/llvm/test/Transforms/InstSimplify/returned.ll @@ -25,6 +25,6 @@ ; CHECK-NEXT: ret i1 false } -declare i8* @func1(i8* returned) nounwind readnone -declare %gept* @func2(%gept* returned) nounwind readnone +declare i8* @func1(i8* returned) nounwind readnone willreturn +declare %gept* @func2(%gept* returned) nounwind readnone willreturn diff --git a/llvm/test/Transforms/MemCpyOpt/memcpy.ll b/llvm/test/Transforms/MemCpyOpt/memcpy.ll --- a/llvm/test/Transforms/MemCpyOpt/memcpy.ll +++ b/llvm/test/Transforms/MemCpyOpt/memcpy.ll @@ -285,7 +285,7 @@ ret void } -declare noalias i8* @malloc(i32) +declare noalias i8* @malloc(i32) willreturn ; rdar://11341081 %struct.big = type { [50 x i32] } @@ -384,5 +384,6 @@ ; CHECK: attributes [[ATTR0]] = { nounwind } ; CHECK: attributes #1 = { argmemonly nofree nosync nounwind willreturn } ; CHECK: attributes #2 = { nounwind ssp } -; CHECK: attributes #3 = { nounwind ssp uwtable } -; CHECK: attributes #4 = { argmemonly nofree nosync nounwind willreturn writeonly } +; CHECK: attributes #3 = { willreturn } +; CHECK: attributes #4 = { nounwind ssp uwtable } +; CHECK: attributes #5 = { argmemonly nofree nosync nounwind willreturn writeonly } diff --git a/llvm/test/Transforms/NewGVN/eliminate-callsite-inline.ll b/llvm/test/Transforms/NewGVN/eliminate-callsite-inline.ll --- a/llvm/test/Transforms/NewGVN/eliminate-callsite-inline.ll +++ b/llvm/test/Transforms/NewGVN/eliminate-callsite-inline.ll @@ -14,4 +14,4 @@ ret void } -attributes #1 = { noinline nounwind readnone } +attributes #1 = { noinline nounwind readnone willreturn } diff --git a/llvm/test/Transforms/OpenMP/parallel_deletion.ll b/llvm/test/Transforms/OpenMP/parallel_deletion.ll --- a/llvm/test/Transforms/OpenMP/parallel_deletion.ll +++ b/llvm/test/Transforms/OpenMP/parallel_deletion.ll @@ -25,9 +25,9 @@ ; ; We delete all but the first of the parallel regions in this test. define void @delete_parallel_0() { -; CHECK-LABEL: define {{[^@]+}}@delete_parallel_0() +; CHECK-LABEL: define {{[^@]+}}@delete_parallel_0() { ; CHECK-NEXT: entry: -; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) @0, i32 noundef 0, void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*)* @.omp_outlined.willreturn to void (i32*, i32*, ...)*)) +; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) [[GLOB0:@.*]], i32 noundef 0, void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*)* @.omp_outlined.willreturn to void (i32*, i32*, ...)*)) ; CHECK-NEXT: ret void ; entry: @@ -40,9 +40,9 @@ define internal void @.omp_outlined.willreturn(i32* noalias %.global_tid., i32* noalias %.bound_tid.) { ; CHECK-LABEL: define {{[^@]+}}@.omp_outlined.willreturn -; CHECK-SAME: (i32* noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #0 +; CHECK-SAME: (i32* noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) [[ATTR0:#.*]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @unknown() #0 +; CHECK-NEXT: call void @unknown() [[ATTR0]] ; CHECK-NEXT: ret void ; entry: @@ -52,9 +52,9 @@ define internal void @.omp_outlined.willreturn.0(i32* noalias %.global_tid., i32* noalias %.bound_tid.) willreturn { ; CHECK-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.0 -; CHECK-SAME: (i32* noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #1 +; CHECK-SAME: (i32* noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) [[ATTR1:#.*]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @readonly() #4 +; CHECK-NEXT: call void @readonly() [[ATTR4:#.*]] ; CHECK-NEXT: ret void ; entry: @@ -64,9 +64,9 @@ define internal void @.omp_outlined.willreturn.1(i32* noalias %.global_tid., i32* noalias %.bound_tid.) { ; CHECK-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.1 -; CHECK-SAME: (i32* noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #2 +; CHECK-SAME: (i32* noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) [[ATTR2:#.*]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @readnone() #0 +; CHECK-NEXT: call void @readnone() [[ATTR0]] ; CHECK-NEXT: ret void ; entry: @@ -76,7 +76,7 @@ define internal void @.omp_outlined.willreturn.2(i32* noalias %.global_tid., i32* noalias %.bound_tid.) { ; CHECK-LABEL: define {{[^@]+}}@.omp_outlined.willreturn.2 -; CHECK-SAME: (i32* noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #3 +; CHECK-SAME: (i32* noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) [[ATTR3:#.*]] { ; CHECK-NEXT: entry: ; CHECK-NEXT: ret void ; @@ -97,11 +97,11 @@ ; ; We delete only the last parallel regions in this test because the others might not return. define void @delete_parallel_1() { -; CHECK-LABEL: define {{[^@]+}}@delete_parallel_1() +; CHECK-LABEL: define {{[^@]+}}@delete_parallel_1() { ; CHECK-NEXT: entry: -; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) @0, i32 noundef 0, void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*)* @.omp_outlined. to void (i32*, i32*, ...)*)) -; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) @0, i32 noundef 0, void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*)* @.omp_outlined..0 to void (i32*, i32*, ...)*)) -; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) @0, i32 noundef 0, void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*)* @.omp_outlined..1 to void (i32*, i32*, ...)*)) +; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) [[GLOB0]], i32 noundef 0, void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*)* @.omp_outlined. to void (i32*, i32*, ...)*)) +; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) [[GLOB0]], i32 noundef 0, void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*)* @.omp_outlined..0 to void (i32*, i32*, ...)*)) +; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) [[GLOB0]], i32 noundef 0, void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*)* @.omp_outlined..1 to void (i32*, i32*, ...)*)) ; CHECK-NEXT: ret void ; entry: @@ -114,7 +114,7 @@ define internal void @.omp_outlined.(i32* noalias %.global_tid., i32* noalias %.bound_tid.) { ; CHECK-LABEL: define {{[^@]+}}@.omp_outlined. -; CHECK-SAME: (i32* noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) +; CHECK-SAME: (i32* noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: call void @unknown() ; CHECK-NEXT: ret void @@ -126,9 +126,9 @@ define internal void @.omp_outlined..0(i32* noalias %.global_tid., i32* noalias %.bound_tid.) { ; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..0 -; CHECK-SAME: (i32* noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #4 +; CHECK-SAME: (i32* noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) [[ATTR4]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: call void @readonly() #4 +; CHECK-NEXT: call void @readonly() [[ATTR4]] ; CHECK-NEXT: ret void ; entry: @@ -138,7 +138,7 @@ define internal void @.omp_outlined..1(i32* noalias %.global_tid., i32* noalias %.bound_tid.) { ; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..1 -; CHECK-SAME: (i32* noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #5 +; CHECK-SAME: (i32* noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) [[ATTR5:#.*]] { ; CHECK-NEXT: entry: ; CHECK-NEXT: call void @readnone() ; CHECK-NEXT: ret void @@ -150,7 +150,7 @@ define internal void @.omp_outlined..2(i32* noalias %.global_tid., i32* noalias %.bound_tid.) { ; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..2 -; CHECK-SAME: (i32* noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) #3 +; CHECK-SAME: (i32* noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]]) [[ATTR3]] { ; CHECK-NEXT: entry: ; CHECK-NEXT: ret void ; @@ -184,16 +184,16 @@ ; FIXME: We do not realize that `a` is dead and all accesses to it can be removed ; making the parallel regions readonly and deletable. define void @delete_parallel_2() { -; CHECK-LABEL: define {{[^@]+}}@delete_parallel_2() +; CHECK-LABEL: define {{[^@]+}}@delete_parallel_2() { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[TMP:%.*]] = bitcast i32* [[A]] to i8* -; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* noundef nonnull align 4 dereferenceable(4) [[TMP]]) #0 +; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* noundef nonnull align 4 dereferenceable(4) [[TMP]]) [[ATTR0]] ; CHECK-NEXT: store i32 0, i32* [[A]], align 4 -; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) @0, i32 noundef 1, void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*, i32*)* @.omp_outlined..3 to void (i32*, i32*, ...)*), i32* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]]) -; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) @0, i32 noundef 1, void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*, i32*)* @.omp_outlined..4 to void (i32*, i32*, ...)*), i32* nocapture noundef nonnull align 4 dereferenceable(4) [[A]]) -; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) @0, i32 noundef 1, void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*, i32*)* @.omp_outlined..5 to void (i32*, i32*, ...)*), i32* nocapture noundef nonnull align 4 dereferenceable(4) [[A]]) -; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) @0, i32 noundef 1, void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*, i32*)* @.omp_outlined..6 to void (i32*, i32*, ...)*), i32* nocapture noundef nonnull align 4 dereferenceable(4) [[A]]) +; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) [[GLOB0]], i32 noundef 1, void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*, i32*)* @.omp_outlined..3 to void (i32*, i32*, ...)*), i32* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A]]) +; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) [[GLOB0]], i32 noundef 1, void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*, i32*)* @.omp_outlined..4 to void (i32*, i32*, ...)*), i32* nocapture noundef nonnull align 4 dereferenceable(4) [[A]]) +; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) [[GLOB0]], i32 noundef 1, void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*, i32*)* @.omp_outlined..5 to void (i32*, i32*, ...)*), i32* nocapture noundef nonnull align 4 dereferenceable(4) [[A]]) +; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* noundef nonnull align 8 dereferenceable(24) [[GLOB0]], i32 noundef 1, void (i32*, i32*, ...)* noundef bitcast (void (i32*, i32*, i32*)* @.omp_outlined..6 to void (i32*, i32*, ...)*), i32* nocapture noundef nonnull align 4 dereferenceable(4) [[A]]) ; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[A]] to i8* ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 noundef 4, i8* noundef nonnull [[TMP1]]) ; CHECK-NEXT: ret void @@ -214,9 +214,9 @@ define internal void @.omp_outlined..3(i32* noalias %.global_tid., i32* noalias %.bound_tid., i32* dereferenceable(4) %a) { ; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..3 -; CHECK-SAME: (i32* noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], i32* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) #6 +; CHECK-SAME: (i32* noalias nocapture nofree readnone [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], i32* nocapture nofree noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) [[ATTR6:#.*]] { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = call i32 @omp_get_thread_num() #4 +; CHECK-NEXT: [[CALL:%.*]] = call i32 @omp_get_thread_num() [[ATTR12:#.*]] ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[CALL]], 0 ; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] ; CHECK: if.then: @@ -244,17 +244,17 @@ define internal void @.omp_outlined..4(i32* noalias %.global_tid., i32* noalias %.bound_tid., i32* dereferenceable(4) %a) { ; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..4 -; CHECK-SAME: (i32* noalias nocapture nonnull readonly align 4 dereferenceable(4) [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], i32* nocapture noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) +; CHECK-SAME: (i32* noalias nocapture nonnull readonly align 4 dereferenceable(4) [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], i32* nocapture noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP:%.*]] = load i32, i32* [[DOTGLOBAL_TID_]], align 4 -; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_master(%struct.ident_t* noundef nonnull @0, i32 [[TMP]]) +; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_master(%struct.ident_t* noundef nonnull [[GLOB0]], i32 [[TMP]]) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0 ; CHECK-NEXT: br i1 [[TMP2]], label [[OMP_IF_END:%.*]], label [[OMP_IF_THEN:%.*]] ; CHECK: omp_if.then: ; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[A]], align 4 ; CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP3]], 1 ; CHECK-NEXT: store i32 [[INC]], i32* [[A]], align 4 -; CHECK-NEXT: call void @__kmpc_end_master(%struct.ident_t* noundef nonnull @0, i32 [[TMP]]) +; CHECK-NEXT: call void @__kmpc_end_master(%struct.ident_t* noundef nonnull [[GLOB0]], i32 [[TMP]]) ; CHECK-NEXT: br label [[OMP_IF_END]] ; CHECK: omp_if.end: ; CHECK-NEXT: ret void @@ -286,21 +286,21 @@ define internal void @.omp_outlined..5(i32* noalias %.global_tid., i32* noalias %.bound_tid., i32* dereferenceable(4) %a) { ; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..5 -; CHECK-SAME: (i32* noalias nocapture nonnull readonly align 4 dereferenceable(4) [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], i32* nocapture noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) +; CHECK-SAME: (i32* noalias nocapture nonnull readonly align 4 dereferenceable(4) [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], i32* nocapture noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) { ; CHECK-NEXT: entry: -; CHECK-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* noundef nonnull @0) +; CHECK-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* noundef nonnull [[GLOB0]]) [[ATTR12]] ; CHECK-NEXT: [[TMP:%.*]] = load i32, i32* [[DOTGLOBAL_TID_]], align 4 -; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_single(%struct.ident_t* noundef nonnull @0, i32 [[TMP]]) +; CHECK-NEXT: [[TMP1:%.*]] = call i32 @__kmpc_single(%struct.ident_t* noundef nonnull [[GLOB0]], i32 [[TMP]]) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0 ; CHECK-NEXT: br i1 [[TMP2]], label [[OMP_IF_END:%.*]], label [[OMP_IF_THEN:%.*]] ; CHECK: omp_if.then: ; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[A]], align 4 ; CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP3]], 1 ; CHECK-NEXT: store i32 [[INC]], i32* [[A]], align 4 -; CHECK-NEXT: call void @__kmpc_end_single(%struct.ident_t* noundef nonnull @0, i32 [[TMP]]) +; CHECK-NEXT: call void @__kmpc_end_single(%struct.ident_t* noundef nonnull [[GLOB0]], i32 [[TMP]]) ; CHECK-NEXT: br label [[OMP_IF_END]] ; CHECK: omp_if.end: -; CHECK-NEXT: call void @__kmpc_barrier(%struct.ident_t* noundef nonnull @1, i32 [[OMP_GLOBAL_THREAD_NUM]]) +; CHECK-NEXT: call void @__kmpc_barrier(%struct.ident_t* noundef nonnull [[GLOB1:@.*]], i32 [[OMP_GLOBAL_THREAD_NUM]]) ; CHECK-NEXT: ret void ; entry: @@ -324,18 +324,18 @@ define internal void @.omp_outlined..6(i32* noalias %.global_tid., i32* noalias %.bound_tid., i32* dereferenceable(4) %a) { ; CHECK-LABEL: define {{[^@]+}}@.omp_outlined..6 -; CHECK-SAME: (i32* noalias nocapture nonnull readonly align 4 dereferenceable(4) [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], i32* nocapture noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) +; CHECK-SAME: (i32* noalias nocapture nonnull readonly align 4 dereferenceable(4) [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], i32* nocapture noundef nonnull align 4 dereferenceable(4) [[A:%.*]]) { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[A1:%.*]] = alloca i32, align 4 ; CHECK-NEXT: [[DOTOMP_REDUCTION_RED_LIST:%.*]] = alloca [1 x i8*], align 8 ; CHECK-NEXT: [[TMP:%.*]] = bitcast i32* [[A1]] to i8* -; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* noundef nonnull align 4 [[TMP]]) #0 +; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 noundef 4, i8* noundef nonnull align 4 [[TMP]]) [[ATTR0]] ; CHECK-NEXT: store i32 1, i32* [[A1]], align 4 ; CHECK-NEXT: [[TMP1:%.*]] = bitcast [1 x i8*]* [[DOTOMP_REDUCTION_RED_LIST]] to i32** ; CHECK-NEXT: store i32* [[A1]], i32** [[TMP1]], align 8 ; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[DOTGLOBAL_TID_]], align 4 ; CHECK-NEXT: [[TMP3:%.*]] = bitcast [1 x i8*]* [[DOTOMP_REDUCTION_RED_LIST]] to i8* -; CHECK-NEXT: [[TMP4:%.*]] = call i32 @__kmpc_reduce_nowait(%struct.ident_t* noundef nonnull @2, i32 [[TMP2]], i32 noundef 1, i64 noundef 8, i8* noundef nonnull align 8 [[TMP3]], void (i8*, i8*)* noundef nonnull @.omp.reduction.reduction_func, [8 x i32]* noundef nonnull @.gomp_critical_user_.reduction.var) +; CHECK-NEXT: [[TMP4:%.*]] = call i32 @__kmpc_reduce_nowait(%struct.ident_t* noundef nonnull [[GLOB2:@.*]], i32 [[TMP2]], i32 noundef 1, i64 noundef 8, i8* noundef nonnull align 8 [[TMP3]], void (i8*, i8*)* noundef nonnull @.omp.reduction.reduction_func, [8 x i32]* noundef nonnull @.gomp_critical_user_.reduction.var) ; CHECK-NEXT: switch i32 [[TMP4]], label [[DOTOMP_REDUCTION_DEFAULT:%.*]] [ ; CHECK-NEXT: i32 1, label [[DOTOMP_REDUCTION_CASE1:%.*]] ; CHECK-NEXT: i32 2, label [[DOTOMP_REDUCTION_CASE2:%.*]] @@ -345,7 +345,7 @@ ; CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* [[A1]], align 4 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP5]], [[TMP6]] ; CHECK-NEXT: store i32 [[ADD]], i32* [[A]], align 4 -; CHECK-NEXT: call void @__kmpc_end_reduce_nowait(%struct.ident_t* noundef nonnull @2, i32 [[TMP2]], [8 x i32]* noundef nonnull @.gomp_critical_user_.reduction.var) +; CHECK-NEXT: call void @__kmpc_end_reduce_nowait(%struct.ident_t* noundef nonnull [[GLOB2]], i32 [[TMP2]], [8 x i32]* noundef nonnull @.gomp_critical_user_.reduction.var) ; CHECK-NEXT: br label [[DOTOMP_REDUCTION_DEFAULT]] ; CHECK: .omp.reduction.case2: ; CHECK-NEXT: [[TMP7:%.*]] = load i32, i32* [[A1]], align 4 @@ -393,7 +393,7 @@ define internal void @.omp.reduction.reduction_func(i8* %arg, i8* %arg1) { ; CHECK-LABEL: define {{[^@]+}}@.omp.reduction.reduction_func -; CHECK-SAME: (i8* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG:%.*]], i8* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG1:%.*]]) #{{[0-9]+}} +; CHECK-SAME: (i8* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG:%.*]], i8* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[ARG1:%.*]]) [[ATTR9:#.*]] { ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP:%.*]] = bitcast i8* [[ARG1]] to i32** ; CHECK-NEXT: [[TMP2:%.*]] = load i32*, i32** [[TMP]], align 8 diff --git a/llvm/test/Transforms/Reassociate/erase_inst_made_change.ll b/llvm/test/Transforms/Reassociate/erase_inst_made_change.ll --- a/llvm/test/Transforms/Reassociate/erase_inst_made_change.ll +++ b/llvm/test/Transforms/Reassociate/erase_inst_made_change.ll @@ -20,7 +20,7 @@ ret void } -define internal void @bar() noinline nounwind readnone { +define internal void @bar() noinline nounwind readnone willreturn { entry: ret void }