Index: lib/Transforms/Utils/Local.cpp =================================================================== --- lib/Transforms/Utils/Local.cpp +++ lib/Transforms/Utils/Local.cpp @@ -420,7 +420,15 @@ return true; } - if (!I->mayHaveSideEffects()) + bool WillReturn = true; + if (auto *CB = dyn_cast(I)) { + // FIXME: We temporarily assume that all intrinsics are willreturn. + // Remove this hack once intrinsics consistently use default attributes. + WillReturn = CB->hasFnAttr(Attribute::WillReturn) || + isa(CB); + } + + if (!I->mayHaveSideEffects() && WillReturn) return true; // Special case intrinsics that "may have side effects" but can be deleted Index: test/Transforms/Attributor/ArgumentPromotion/fp80.ll =================================================================== --- test/Transforms/Attributor/ArgumentPromotion/fp80.ll +++ test/Transforms/Attributor/ArgumentPromotion/fp80.ll @@ -17,16 +17,32 @@ @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 ; IS__CGSCC____-SAME: () [[ATTR0:#.*]] { ; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[A_CAST:%.*]] = bitcast %struct.Foo* @a to i32* +; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* [[A_CAST]], align 8 +; IS__CGSCC____-NEXT: [[A_0_1:%.*]] = getelementptr [[STRUCT_FOO:%.*]], %struct.Foo* @a, i32 0, i32 1 +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = load i64, i64* [[A_0_1]], align 8 ; IS__CGSCC____-NEXT: unreachable ; entry: @@ -86,6 +102,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:#.*]] { Index: test/Transforms/Attributor/align.ll =================================================================== --- test/Transforms/Attributor/align.ll +++ 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 Index: test/Transforms/Attributor/nocapture-1.ll =================================================================== --- test/Transforms/Attributor/nocapture-1.ll +++ 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 ; Index: test/Transforms/Attributor/nocapture-2.ll =================================================================== --- test/Transforms/Attributor/nocapture-2.ll +++ 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: Index: test/Transforms/Attributor/nonnull.ll =================================================================== --- test/Transforms/Attributor/nonnull.ll +++ test/Transforms/Attributor/nonnull.ll @@ -146,30 +146,22 @@ ; nonnull if neither can ever return null. (In this case, they ; just never return period.) define i8* @test4_helper() { -; 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: unreachable -; -; IS__CGSCC_NPM: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn -; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test4_helper -; IS__CGSCC_NPM-SAME: () [[ATTR2:#.*]] { -; IS__CGSCC_NPM-NEXT: unreachable +; CHECK: Function Attrs: nofree noreturn nosync nounwind readnone +; CHECK-LABEL: define {{[^@]+}}@test4_helper +; CHECK-SAME: () [[ATTR2:#.*]] { +; CHECK-NEXT: [[RET:%.*]] = call i8* @test4() [[ATTR2]] +; CHECK-NEXT: unreachable ; %ret = call i8* @test4() ret i8* %ret } define i8* @test4() { -; 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: unreachable -; -; IS__CGSCC_NPM: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn -; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test4 -; IS__CGSCC_NPM-SAME: () [[ATTR2]] { -; IS__CGSCC_NPM-NEXT: unreachable +; CHECK: Function Attrs: nofree noreturn nosync nounwind readnone +; CHECK-LABEL: define {{[^@]+}}@test4 +; CHECK-SAME: () [[ATTR2]] { +; CHECK-NEXT: [[RET:%.*]] = call i8* @test4_helper() [[ATTR2]] +; CHECK-NEXT: unreachable ; %ret = call i8* @test4_helper() ret i8* %ret @@ -908,13 +900,13 @@ define i8 @parent7(i8* %a) { ; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@parent7 ; NOT_CGSCC_OPM-SAME: (i8* nonnull [[A:%.*]]) { -; NOT_CGSCC_OPM-NEXT: [[RET:%.*]] = call i8 @use1safecall(i8* nonnull readonly [[A]]) [[ATTR14:#.*]] +; NOT_CGSCC_OPM-NEXT: [[RET:%.*]] = call i8 @use1safecall(i8* nonnull readonly [[A]]) [[ATTR7:#.*]] ; NOT_CGSCC_OPM-NEXT: call void @use1nonnull(i8* nonnull [[A]]) ; NOT_CGSCC_OPM-NEXT: ret i8 [[RET]] ; ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@parent7 ; IS__CGSCC_OPM-SAME: (i8* nonnull [[A:%.*]]) { -; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = call i8 @use1safecall(i8* nonnull readonly [[A]]) [[ATTR15:#.*]] +; IS__CGSCC_OPM-NEXT: [[RET:%.*]] = call i8 @use1safecall(i8* nonnull readonly [[A]]) [[ATTR8:#.*]] ; IS__CGSCC_OPM-NEXT: call void @use1nonnull(i8* nonnull [[A]]) ; IS__CGSCC_OPM-NEXT: ret i8 [[RET]] ; @@ -1520,7 +1512,7 @@ ; NOT_CGSCC_OPM: Function Attrs: nofree nounwind readonly willreturn ; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@mybasename ; NOT_CGSCC_OPM-SAME: (i8* nofree readonly [[STR:%.*]]) [[ATTR11:#.*]] { -; NOT_CGSCC_OPM-NEXT: [[CALL:%.*]] = call i8* @strrchr(i8* nofree readonly [[STR]], i32 noundef 47) [[ATTR15:#.*]] +; NOT_CGSCC_OPM-NEXT: [[CALL:%.*]] = call i8* @strrchr(i8* nofree readonly [[STR]], i32 noundef 47) [[ATTR14:#.*]] ; NOT_CGSCC_OPM-NEXT: [[TOBOOL:%.*]] = icmp ne i8* [[CALL]], null ; NOT_CGSCC_OPM-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[CALL]], i64 1 ; NOT_CGSCC_OPM-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i8* [[ADD_PTR]], i8* [[STR]] @@ -1529,7 +1521,7 @@ ; IS__CGSCC_OPM: Function Attrs: nofree nounwind readonly willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@mybasename ; IS__CGSCC_OPM-SAME: (i8* nofree readonly [[STR:%.*]]) [[ATTR12:#.*]] { -; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call i8* @strrchr(i8* nofree readonly [[STR]], i32 noundef 47) [[ATTR16:#.*]] +; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call i8* @strrchr(i8* nofree readonly [[STR]], i32 noundef 47) [[ATTR15:#.*]] ; IS__CGSCC_OPM-NEXT: [[TOBOOL:%.*]] = icmp ne i8* [[CALL]], null ; IS__CGSCC_OPM-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i8, i8* [[CALL]], i64 1 ; IS__CGSCC_OPM-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i8* [[ADD_PTR]], i8* [[STR]] Index: test/Transforms/Attributor/norecurse.ll =================================================================== --- test/Transforms/Attributor/norecurse.ll +++ 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]] ; Index: test/Transforms/Attributor/range.ll =================================================================== --- test/Transforms/Attributor/range.ll +++ 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 Index: test/Transforms/Attributor/readattrs.ll =================================================================== --- test/Transforms/Attributor/readattrs.ll +++ test/Transforms/Attributor/readattrs.ll @@ -57,10 +57,10 @@ ret i1 %A } -declare void @test4_1(i8* nocapture) readonly +declare void @test4_1(i8* nocapture) readonly willreturn define void @test4_2(i8* %p) { -; CHECK: Function Attrs: readonly +; CHECK: Function Attrs: readonly willreturn ; CHECK-LABEL: define {{[^@]+}}@test4_2 ; CHECK-SAME: (i8* nocapture readonly [[P:%.*]]) [[ATTR2:#.*]] { ; CHECK-NEXT: call void @test4_1(i8* nocapture readonly [[P]]) [[ATTR2]] @@ -147,7 +147,7 @@ ; IS__CGSCC____-LABEL: define {{[^@]+}}@test8_2 ; IS__CGSCC____-SAME: (i32* nocapture nofree writeonly [[P:%.*]]) [[ATTR3]] { ; IS__CGSCC____-NEXT: entry: -; IS__CGSCC____-NEXT: [[CALL:%.*]] = call align 4 i32* @test8_1(i32* noalias nofree readnone "no-capture-maybe-returned" [[P]]) [[ATTR11:#.*]] +; IS__CGSCC____-NEXT: [[CALL:%.*]] = call align 4 i32* @test8_1(i32* noalias nofree readnone "no-capture-maybe-returned" [[P]]) [[ATTR12:#.*]] ; IS__CGSCC____-NEXT: store i32 10, i32* [[CALL]], align 4 ; IS__CGSCC____-NEXT: ret void ; @@ -166,13 +166,13 @@ ; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@test9 ; IS__TUNIT____-SAME: (<4 x i32*> [[PTRS:%.*]], <4 x i32> [[VAL:%.*]]) [[ATTR0]] { -; IS__TUNIT____-NEXT: call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32> [[VAL]], <4 x i32*> [[PTRS]], i32 noundef 4, <4 x i1> noundef ) [[ATTR10:#.*]] +; IS__TUNIT____-NEXT: call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32> [[VAL]], <4 x i32*> [[PTRS]], i32 noundef 4, <4 x i1> noundef ) [[ATTR11:#.*]] ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@test9 ; IS__CGSCC____-SAME: (<4 x i32*> [[PTRS:%.*]], <4 x i32> [[VAL:%.*]]) [[ATTR4:#.*]] { -; IS__CGSCC____-NEXT: call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32> [[VAL]], <4 x i32*> [[PTRS]], i32 noundef 4, <4 x i1> noundef ) [[ATTR12:#.*]] +; IS__CGSCC____-NEXT: call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32> [[VAL]], <4 x i32*> [[PTRS]], i32 noundef 4, <4 x i1> noundef ) [[ATTR13:#.*]] ; IS__CGSCC____-NEXT: ret void ; call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32>%val, <4 x i32*> %ptrs, i32 4, <4 x i1>) @@ -182,26 +182,20 @@ ; CHECK: declare <4 x i32> @llvm.masked.gather declare <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*>, i32, <4 x i1>, <4 x i32>) define <4 x i32> @test10(<4 x i32*> %ptrs) { -; IS__TUNIT____: Function Attrs: nofree nosync nounwind readonly willreturn -; IS__TUNIT____-LABEL: define {{[^@]+}}@test10 -; IS__TUNIT____-SAME: (<4 x i32*> [[PTRS:%.*]]) [[ATTR4:#.*]] { -; IS__TUNIT____-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[PTRS]], i32 noundef 4, <4 x i1> noundef , <4 x i32> undef) [[ATTR11:#.*]] -; IS__TUNIT____-NEXT: ret <4 x i32> [[RES]] -; -; IS__CGSCC____: Function Attrs: nofree nosync nounwind readonly willreturn -; IS__CGSCC____-LABEL: define {{[^@]+}}@test10 -; IS__CGSCC____-SAME: (<4 x i32*> [[PTRS:%.*]]) [[ATTR5:#.*]] { -; IS__CGSCC____-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[PTRS]], i32 noundef 4, <4 x i1> noundef , <4 x i32> undef) [[ATTR13:#.*]] -; IS__CGSCC____-NEXT: ret <4 x i32> [[RES]] +; CHECK: Function Attrs: nofree nosync nounwind readonly willreturn +; CHECK-LABEL: define {{[^@]+}}@test10 +; CHECK-SAME: (<4 x i32*> [[PTRS:%.*]]) [[ATTR5:#.*]] { +; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[PTRS]], i32 noundef 4, <4 x i1> noundef , <4 x i32> undef) [[ATTR2]] +; CHECK-NEXT: ret <4 x i32> [[RES]] ; %res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %ptrs, i32 4, <4 x i1>, <4 x i32>undef) ret <4 x i32> %res } ; CHECK: declare <4 x i32> @test11_1 -declare <4 x i32> @test11_1(<4 x i32*>) argmemonly nounwind readonly +declare <4 x i32> @test11_1(<4 x i32*>) argmemonly nounwind readonly willreturn define <4 x i32> @test11_2(<4 x i32*> %ptrs) { -; CHECK: Function Attrs: argmemonly nounwind readonly +; CHECK: Function Attrs: argmemonly nounwind readonly willreturn ; 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]] @@ -295,7 +289,7 @@ define void @byval_not_readonly_1(i8* byval(i8) %written) readonly { ; CHECK: Function Attrs: readonly ; CHECK-LABEL: define {{[^@]+}}@byval_not_readonly_1 -; CHECK-SAME: (i8* noalias nonnull byval(i8) dereferenceable(1) [[WRITTEN:%.*]]) [[ATTR2]] { +; CHECK-SAME: (i8* noalias nonnull byval(i8) dereferenceable(1) [[WRITTEN:%.*]]) [[ATTR9:#.*]] { ; CHECK-NEXT: call void @escape_i8(i8* nonnull dereferenceable(1) [[WRITTEN]]) ; CHECK-NEXT: ret void ; @@ -323,7 +317,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:%.*]]) [[ATTR10:#.*]] { ; CHECK-NEXT: call void @escape_i8(i8* nonnull dereferenceable(1) [[WRITTEN]]) ; CHECK-NEXT: ret void ; @@ -368,14 +362,14 @@ define void @testbyval(i8* %read_only) { ; IS__TUNIT____-LABEL: define {{[^@]+}}@testbyval ; IS__TUNIT____-SAME: (i8* nocapture readonly [[READ_ONLY:%.*]]) { -; IS__TUNIT____-NEXT: call void @byval_not_readonly_1(i8* nocapture readonly [[READ_ONLY]]) [[ATTR2:#.*]] +; IS__TUNIT____-NEXT: call void @byval_not_readonly_1(i8* nocapture readonly [[READ_ONLY]]) [[ATTR8:#.*]] ; IS__TUNIT____-NEXT: call void @byval_not_readnone_1(i8* noalias nocapture readnone [[READ_ONLY]]) ; IS__TUNIT____-NEXT: ret void ; ; IS__CGSCC____: Function Attrs: readonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@testbyval -; IS__CGSCC____-SAME: (i8* nocapture nonnull readonly dereferenceable(1) [[READ_ONLY:%.*]]) [[ATTR2:#.*]] { -; IS__CGSCC____-NEXT: call void @byval_not_readonly_1(i8* noalias nocapture nonnull readonly dereferenceable(1) [[READ_ONLY]]) [[ATTR2]] +; IS__CGSCC____-SAME: (i8* nocapture nonnull readonly dereferenceable(1) [[READ_ONLY:%.*]]) [[ATTR9:#.*]] { +; IS__CGSCC____-NEXT: call void @byval_not_readonly_1(i8* noalias nocapture nonnull readonly dereferenceable(1) [[READ_ONLY]]) [[ATTR9]] ; IS__CGSCC____-NEXT: call void @byval_not_readnone_1(i8* noalias nocapture nonnull readnone dereferenceable(1) [[READ_ONLY]]) ; IS__CGSCC____-NEXT: ret void ; @@ -393,10 +387,19 @@ declare void @val_use(i8 %ptr) readonly nounwind define void @ptr_uses(i8* %ptr) { -; CHECK: Function Attrs: nounwind readonly -; CHECK-LABEL: define {{[^@]+}}@ptr_uses -; CHECK-SAME: (i8* nocapture readonly [[PTR:%.*]]) [[ATTR10:#.*]] { -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nounwind readonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@ptr_uses +; IS__TUNIT____-SAME: (i8* nocapture readonly [[PTR:%.*]]) [[ATTR10:#.*]] { +; IS__TUNIT____-NEXT: [[CALL_PTR:%.*]] = call i8* @maybe_returned_ptr(i8* readonly [[PTR]]) [[ATTR10]] +; IS__TUNIT____-NEXT: [[CALL_VAL:%.*]] = call i8 @maybe_returned_val(i8* readonly [[CALL_PTR]]) [[ATTR10]] +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nounwind readonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@ptr_uses +; IS__CGSCC____-SAME: (i8* nocapture readonly [[PTR:%.*]]) [[ATTR11:#.*]] { +; IS__CGSCC____-NEXT: [[CALL_PTR:%.*]] = call i8* @maybe_returned_ptr(i8* readonly [[PTR]]) [[ATTR11]] +; IS__CGSCC____-NEXT: [[CALL_VAL:%.*]] = call i8 @maybe_returned_val(i8* readonly [[CALL_PTR]]) [[ATTR11]] +; IS__CGSCC____-NEXT: ret void ; %call_ptr = call i8* @maybe_returned_ptr(i8* %ptr) %call_val = call i8 @maybe_returned_val(i8* %call_ptr) Index: test/Transforms/BDCE/basic.ll =================================================================== --- test/Transforms/BDCE/basic.ll +++ test/Transforms/BDCE/basic.ll @@ -392,6 +392,6 @@ ret i16 %cast } -attributes #0 = { nounwind readnone } +attributes #0 = { nounwind readnone willreturn } attributes #1 = { nounwind } Index: test/Transforms/CodeGenPrepare/X86/delete-assume-dead-code.ll =================================================================== --- test/Transforms/CodeGenPrepare/X86/delete-assume-dead-code.ll +++ 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 Index: test/Transforms/InstCombine/nothrow.ll =================================================================== --- test/Transforms/InstCombine/nothrow.ll +++ 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. Index: test/Transforms/InstSimplify/ConstProp/rint.ll =================================================================== --- test/Transforms/InstSimplify/ConstProp/rint.ll +++ 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 } Index: test/Transforms/InstSimplify/remove-dead-call.ll =================================================================== --- test/Transforms/InstSimplify/remove-dead-call.ll +++ 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 } Index: test/Transforms/InstSimplify/returned.ll =================================================================== --- test/Transforms/InstSimplify/returned.ll +++ 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 Index: test/Transforms/NewGVN/eliminate-callsite-inline.ll =================================================================== --- test/Transforms/NewGVN/eliminate-callsite-inline.ll +++ test/Transforms/NewGVN/eliminate-callsite-inline.ll @@ -14,4 +14,4 @@ ret void } -attributes #1 = { noinline nounwind readnone } +attributes #1 = { noinline nounwind readnone willreturn } Index: test/Transforms/OpenMP/parallel_deletion.ll =================================================================== --- test/Transforms/OpenMP/parallel_deletion.ll +++ 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 Index: test/Transforms/Reassociate/erase_inst_made_change.ll =================================================================== --- test/Transforms/Reassociate/erase_inst_made_change.ll +++ 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 }