diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-02-01-ReturnAttrs.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-02-01-ReturnAttrs.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-02-01-ReturnAttrs.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-02-01-ReturnAttrs.ll @@ -1,16 +1,18 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM define internal i32 @deref(i32* %x) nounwind { +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@deref ; IS__TUNIT_OPM-SAME: (i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[X:%.*]]) ; IS__TUNIT_OPM-NEXT: entry: ; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[X]], align 4 ; IS__TUNIT_OPM-NEXT: ret i32 [[TMP2]] ; +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@deref ; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]]) ; IS__TUNIT_NPM-NEXT: entry: @@ -19,6 +21,7 @@ ; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[X_PRIV]], align 4 ; IS__TUNIT_NPM-NEXT: ret i32 [[TMP2]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@deref ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[X:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -31,14 +34,16 @@ } define i32 @f(i32 %x) { -; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@f -; NOT_TUNIT_NPM-SAME: (i32 [[X:%.*]]) -; NOT_TUNIT_NPM-NEXT: entry: -; NOT_TUNIT_NPM-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4 -; NOT_TUNIT_NPM-NEXT: store i32 [[X]], i32* [[X_ADDR]], align 4 -; NOT_TUNIT_NPM-NEXT: [[TMP1:%.*]] = call i32 @deref(i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[X_ADDR]]) -; NOT_TUNIT_NPM-NEXT: ret i32 [[TMP1]] +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@f +; IS__TUNIT_OPM-SAME: (i32 [[X:%.*]]) +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4 +; IS__TUNIT_OPM-NEXT: store i32 [[X]], i32* [[X_ADDR]], align 4 +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = call i32 @deref(i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[X_ADDR]]) +; IS__TUNIT_OPM-NEXT: ret i32 [[TMP1]] ; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@f ; IS__TUNIT_NPM-SAME: (i32 [[X:%.*]]) ; IS__TUNIT_NPM-NEXT: entry: @@ -48,6 +53,15 @@ ; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = call i32 @deref(i32 [[TMP0]]) ; IS__TUNIT_NPM-NEXT: ret i32 [[TMP1]] ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@f +; IS__CGSCC____-SAME: (i32 [[X:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4 +; IS__CGSCC____-NEXT: store i32 [[X]], i32* [[X_ADDR]], align 4 +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @deref(i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[X_ADDR]]) +; IS__CGSCC____-NEXT: ret i32 [[TMP1]] +; entry: %x_addr = alloca i32 store i32 %x, i32* %x_addr, align 4 diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-07-02-array-indexing.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-07-02-array-indexing.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-07-02-array-indexing.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-07-02-array-indexing.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -9,17 +9,31 @@ ; because there is a load of %A in the entry block define internal i32 @callee(i1 %C, i32* %A) { ; -; CHECK-LABEL: define {{[^@]+}}@callee -; CHECK-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[A_0:%.*]] = load i32, i32* [[A]], align 4 -; CHECK-NEXT: br label [[F:%.*]] -; CHECK: T: -; CHECK-NEXT: unreachable -; CHECK: F: -; CHECK-NEXT: [[A_2:%.*]] = getelementptr i32, i32* [[A]], i32 2 -; CHECK-NEXT: [[R:%.*]] = load i32, i32* [[A_2]], align 4 -; CHECK-NEXT: ret i32 [[R]] +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@callee +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[A_0:%.*]] = load i32, i32* [[A]], align 4 +; IS__TUNIT____-NEXT: br label [[F:%.*]] +; IS__TUNIT____: T: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: F: +; IS__TUNIT____-NEXT: [[A_2:%.*]] = getelementptr i32, i32* [[A]], i32 2 +; IS__TUNIT____-NEXT: [[R:%.*]] = load i32, i32* [[A_2]], align 4 +; IS__TUNIT____-NEXT: ret i32 [[R]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@callee +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[A_0:%.*]] = load i32, i32* [[A]], align 4 +; IS__CGSCC____-NEXT: br label [[F:%.*]] +; IS__CGSCC____: T: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: F: +; IS__CGSCC____-NEXT: [[A_2:%.*]] = getelementptr i32, i32* [[A]], i32 2 +; IS__CGSCC____-NEXT: [[R:%.*]] = load i32, i32* [[A_2]], align 4 +; IS__CGSCC____-NEXT: ret i32 [[R]] ; entry: ; Unconditonally load the element at %A @@ -37,11 +51,13 @@ } define i32 @foo(i32* %A) { +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@foo ; IS__TUNIT____-SAME: (i32* nocapture nofree readonly [[A:%.*]]) ; IS__TUNIT____-NEXT: [[X:%.*]] = call i32 @callee(i32* nocapture nofree readonly align 4 [[A]]) ; IS__TUNIT____-NEXT: ret i32 [[X]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@foo ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A:%.*]]) ; IS__CGSCC____-NEXT: [[X:%.*]] = call i32 @callee(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A]]) diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-07-CGUpdate.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-07-CGUpdate.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-07-CGUpdate.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-07-CGUpdate.ll @@ -1,10 +1,11 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM define internal fastcc i32 @hash(i32* %ts, i32 %mod) nounwind { +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@hash() ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: unreachable @@ -14,10 +15,17 @@ } define void @encode(i32* %m, i32* %ts, i32* %new) nounwind { -; CHECK-LABEL: define {{[^@]+}}@encode -; CHECK-SAME: (i32* nocapture nofree readnone [[M:%.*]], i32* nocapture nofree readnone [[TS:%.*]], i32* nocapture nofree readnone [[NEW:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree noreturn nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@encode +; IS__TUNIT____-SAME: (i32* nocapture nofree readnone [[M:%.*]], i32* nocapture nofree readnone [[TS:%.*]], i32* nocapture nofree readnone [[NEW:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@encode +; IS__CGSCC____-SAME: (i32* nocapture nofree readnone [[M:%.*]], i32* nocapture nofree readnone [[TS:%.*]], i32* nocapture nofree readnone [[NEW:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: unreachable ; entry: %0 = call fastcc i32 @hash( i32* %ts, i32 0 ) nounwind ; [#uses=0] diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-08-CGUpdateSelfEdge.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-08-CGUpdateSelfEdge.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-08-CGUpdateSelfEdge.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-08-CGUpdateSelfEdge.ll @@ -1,10 +1,11 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM define internal fastcc i32 @term_SharingList(i32* %Term, i32* %List) nounwind { +; IS__TUNIT____: Function Attrs: nounwind ; IS__TUNIT____-LABEL: define {{[^@]+}}@term_SharingList ; IS__TUNIT____-SAME: (i32* [[TERM:%.*]], i32* [[LIST:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -15,6 +16,7 @@ ; IS__TUNIT____: bb5: ; IS__TUNIT____-NEXT: ret i32 0 ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@term_SharingList() ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: br i1 false, label [[BB:%.*]], label [[BB5:%.*]] @@ -35,14 +37,25 @@ } define i32 @term_Sharing(i32* %Term) nounwind { -; CHECK-LABEL: define {{[^@]+}}@term_Sharing -; CHECK-SAME: (i32* nocapture nofree readnone [[TERM:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: br i1 false, label [[BB_I:%.*]], label [[BB14:%.*]] -; CHECK: bb.i: -; CHECK-NEXT: unreachable -; CHECK: bb14: -; CHECK-NEXT: ret i32 0 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@term_Sharing +; IS__TUNIT____-SAME: (i32* nocapture nofree readnone [[TERM:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: br i1 false, label [[BB_I:%.*]], label [[BB14:%.*]] +; IS__TUNIT____: bb.i: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: bb14: +; IS__TUNIT____-NEXT: ret i32 0 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@term_Sharing +; IS__CGSCC____-SAME: (i32* nocapture nofree readnone [[TERM:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br i1 false, label [[BB_I:%.*]], label [[BB14:%.*]] +; IS__CGSCC____: bb.i: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: bb14: +; IS__CGSCC____-NEXT: ret i32 0 ; entry: br i1 false, label %bb.i, label %bb14 diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/aggregate-promote.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/aggregate-promote.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/aggregate-promote.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/aggregate-promote.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -8,14 +8,25 @@ @G = constant %T { i32 0, i32 0, i32 17, i32 25 } define internal i32 @test(%T* %p) { -; CHECK-LABEL: define {{[^@]+}}@test() -; CHECK-NEXT: entry: -; CHECK-NEXT: [[A_GEP:%.*]] = getelementptr [[T:%.*]], %T* @G, i64 0, i32 3 -; CHECK-NEXT: [[B_GEP:%.*]] = getelementptr [[T]], %T* @G, i64 0, i32 2 -; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[A_GEP]], align 4 -; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[B_GEP]], align 4 -; CHECK-NEXT: [[V:%.*]] = add i32 [[A]], [[B]] -; CHECK-NEXT: ret i32 [[V]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[A_GEP:%.*]] = getelementptr [[T:%.*]], %T* @G, i64 0, i32 3 +; IS__TUNIT____-NEXT: [[B_GEP:%.*]] = getelementptr [[T]], %T* @G, i64 0, i32 2 +; IS__TUNIT____-NEXT: [[A:%.*]] = load i32, i32* [[A_GEP]], align 4 +; IS__TUNIT____-NEXT: [[B:%.*]] = load i32, i32* [[B_GEP]], align 4 +; IS__TUNIT____-NEXT: [[V:%.*]] = add i32 [[A]], [[B]] +; IS__TUNIT____-NEXT: ret i32 [[V]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[A_GEP:%.*]] = getelementptr [[T:%.*]], %T* @G, i64 0, i32 3 +; IS__CGSCC____-NEXT: [[B_GEP:%.*]] = getelementptr [[T]], %T* @G, i64 0, i32 2 +; IS__CGSCC____-NEXT: [[A:%.*]] = load i32, i32* [[A_GEP]], align 4 +; IS__CGSCC____-NEXT: [[B:%.*]] = load i32, i32* [[B_GEP]], align 4 +; IS__CGSCC____-NEXT: [[V:%.*]] = add i32 [[A]], [[B]] +; IS__CGSCC____-NEXT: ret i32 [[V]] ; entry: %a.gep = getelementptr %T, %T* %p, i64 0, i32 3 @@ -27,10 +38,17 @@ } define i32 @caller() { -; CHECK-LABEL: define {{[^@]+}}@caller() -; CHECK-NEXT: entry: -; CHECK-NEXT: [[V:%.*]] = call i32 @test() -; CHECK-NEXT: ret i32 [[V]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@caller() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[V:%.*]] = call i32 @test() +; IS__TUNIT____-NEXT: ret i32 [[V]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@caller() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[V:%.*]] = call i32 @test() +; IS__CGSCC____-NEXT: ret i32 [[V]] ; entry: %v = call i32 @test(%T* @G) diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/alignment.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/alignment.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/alignment.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/alignment.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=11 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=11 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -55,6 +55,7 @@ ; Test2 ; Different alignemnt privatizable arguments define internal i32 @test(i32* %X, i64* %Y) { +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test ; IS__TUNIT_OPM-SAME: (i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[X:%.*]], i64* noalias nocapture nofree nonnull readonly align 8 dereferenceable(8) [[Y:%.*]]) ; IS__TUNIT_OPM-NEXT: [[A:%.*]] = load i32, i32* [[X]], align 4 @@ -68,6 +69,7 @@ ; IS__TUNIT_OPM: Return2: ; IS__TUNIT_OPM-NEXT: ret i32 [[A]] ; +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@test ; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]]) ; IS__TUNIT_NPM-NEXT: [[Y_PRIV:%.*]] = alloca i64, align 8 @@ -85,6 +87,7 @@ ; IS__TUNIT_NPM: Return2: ; IS__TUNIT_NPM-NEXT: ret i32 [[A]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@test ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[X:%.*]], i64* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[Y:%.*]]) ; IS__CGSCC____-NEXT: [[A:%.*]] = load i32, i32* [[X]], align 4 @@ -111,6 +114,7 @@ } define internal i32 @caller(i32* %A) { +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@caller ; IS__TUNIT_OPM-SAME: (i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A:%.*]]) ; IS__TUNIT_OPM-NEXT: [[B:%.*]] = alloca i64, align 8 @@ -118,6 +122,7 @@ ; IS__TUNIT_OPM-NEXT: [[C:%.*]] = call i32 @test(i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A]], i64* noalias nocapture nofree nonnull readonly align 8 dereferenceable(8) [[B]]) ; IS__TUNIT_OPM-NEXT: ret i32 [[C]] ; +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@caller ; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]]) ; IS__TUNIT_NPM-NEXT: [[A_PRIV:%.*]] = alloca i32, align 4 @@ -129,6 +134,7 @@ ; IS__TUNIT_NPM-NEXT: [[C:%.*]] = call i32 @test(i32 [[TMP2]], i64 [[TMP3]]) ; IS__TUNIT_NPM-NEXT: ret i32 [[C]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@caller ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A:%.*]]) ; IS__CGSCC____-NEXT: [[B:%.*]] = alloca i64, align 8 @@ -143,18 +149,27 @@ } define i32 @callercaller() { -; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@callercaller() -; NOT_TUNIT_NPM-NEXT: [[B:%.*]] = alloca i32, align 4 -; NOT_TUNIT_NPM-NEXT: store i32 2, i32* [[B]], align 4 -; NOT_TUNIT_NPM-NEXT: [[X:%.*]] = call i32 @caller(i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B]]) -; NOT_TUNIT_NPM-NEXT: ret i32 [[X]] +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@callercaller() +; IS__TUNIT_OPM-NEXT: [[B:%.*]] = alloca i32, align 4 +; IS__TUNIT_OPM-NEXT: store i32 2, i32* [[B]], align 4 +; IS__TUNIT_OPM-NEXT: [[X:%.*]] = call i32 @caller(i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B]]) +; IS__TUNIT_OPM-NEXT: ret i32 [[X]] ; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@callercaller() ; IS__TUNIT_NPM-NEXT: [[B:%.*]] = alloca i32, align 4 ; IS__TUNIT_NPM-NEXT: store i32 2, i32* [[B]], align 4 ; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[B]], align 4 ; IS__TUNIT_NPM-NEXT: [[X:%.*]] = call i32 @caller(i32 [[TMP1]]) ; IS__TUNIT_NPM-NEXT: ret i32 [[X]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@callercaller() +; IS__CGSCC____-NEXT: [[B:%.*]] = alloca i32, align 4 +; IS__CGSCC____-NEXT: store i32 2, i32* [[B]], align 4 +; IS__CGSCC____-NEXT: [[X:%.*]] = call i32 @caller(i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B]]) +; IS__CGSCC____-NEXT: ret i32 [[X]] ; %B = alloca i32 store i32 2, i32* %B diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -9,6 +9,7 @@ ; Don't drop 'byval' on %X here. define internal i32 @f(%struct.ss* byval %b, i32* byval %X, i32 %i) nounwind { ; +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@f ; IS__TUNIT_OPM-SAME: (%struct.ss* noalias nocapture nofree nonnull byval align 8 dereferenceable(12) [[B:%.*]], i32* noalias nocapture nofree nonnull byval align 4 dereferenceable(4) [[X:%.*]], i32 [[I:%.*]]) ; IS__TUNIT_OPM-NEXT: entry: @@ -21,6 +22,7 @@ ; IS__TUNIT_OPM-NEXT: [[A:%.*]] = add i32 [[L]], [[TMP2]] ; IS__TUNIT_OPM-NEXT: ret i32 [[A]] ; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@f ; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]], i32 [[TMP2:%.*]], i32 [[I:%.*]]) ; IS__TUNIT_NPM-NEXT: entry: @@ -40,6 +42,7 @@ ; IS__TUNIT_NPM-NEXT: [[A:%.*]] = add i32 [[L]], [[TMP2]] ; IS__TUNIT_NPM-NEXT: ret i32 [[A]] ; +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f ; IS__CGSCC_OPM-SAME: (%struct.ss* noalias nocapture nofree nonnull byval align 8 dereferenceable(12) [[B:%.*]], i32* noalias nocapture nofree nonnull byval align 4 dereferenceable(4) [[X:%.*]]) ; IS__CGSCC_OPM-NEXT: entry: @@ -52,6 +55,7 @@ ; IS__CGSCC_OPM-NEXT: [[A:%.*]] = add i32 [[L]], [[TMP2]] ; IS__CGSCC_OPM-NEXT: ret i32 [[A]] ; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f ; IS__CGSCC_NPM-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]], i32 [[TMP2:%.*]]) ; IS__CGSCC_NPM-NEXT: entry: @@ -87,6 +91,7 @@ ; Also make sure we don't drop the call zeroext attribute. define i32 @test(i32* %X) { ; +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test ; IS__TUNIT_OPM-SAME: (i32* nocapture nofree readonly align 4 [[X:%.*]]) ; IS__TUNIT_OPM-NEXT: entry: @@ -98,6 +103,7 @@ ; IS__TUNIT_OPM-NEXT: [[C:%.*]] = call i32 @f(%struct.ss* noalias nocapture nofree nonnull readonly byval align 8 dereferenceable(12) [[S]], i32* nocapture nofree readonly byval align 4 [[X]], i32 zeroext 0) ; IS__TUNIT_OPM-NEXT: ret i32 [[C]] ; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@test ; IS__TUNIT_NPM-SAME: (i32* nocapture nofree readonly align 4 [[X:%.*]]) ; IS__TUNIT_NPM-NEXT: entry: @@ -114,6 +120,7 @@ ; IS__TUNIT_NPM-NEXT: [[C:%.*]] = call i32 @f(i32 [[TMP0]], i64 [[TMP1]], i32 [[TMP2]], i32 zeroext 0) ; IS__TUNIT_NPM-NEXT: ret i32 [[C]] ; +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test ; IS__CGSCC_OPM-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[X:%.*]]) ; IS__CGSCC_OPM-NEXT: entry: @@ -125,6 +132,7 @@ ; IS__CGSCC_OPM-NEXT: [[C:%.*]] = call i32 @f(%struct.ss* noalias nocapture nofree nonnull readnone byval align 8 dereferenceable(12) [[S]], i32* noalias nocapture nofree nonnull readnone byval align 4 dereferenceable(4) [[X]]) ; IS__CGSCC_OPM-NEXT: ret i32 [[C]] ; +; IS__CGSCC_NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test ; IS__CGSCC_NPM-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[X:%.*]]) ; IS__CGSCC_NPM-NEXT: entry: diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/basictest.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/basictest.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/basictest.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/basictest.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=8 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=8 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -6,6 +6,7 @@ target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" define internal i32 @test(i32* %X, i32* %Y) { +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test ; IS__TUNIT_OPM-SAME: (i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[X:%.*]], i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[Y:%.*]]) ; IS__TUNIT_OPM-NEXT: [[A:%.*]] = load i32, i32* [[X]], align 4 @@ -13,6 +14,7 @@ ; IS__TUNIT_OPM-NEXT: [[C:%.*]] = add i32 [[A]], [[B]] ; IS__TUNIT_OPM-NEXT: ret i32 [[C]] ; +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@test ; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) ; IS__TUNIT_NPM-NEXT: [[Y_PRIV:%.*]] = alloca i32, align 4 @@ -24,6 +26,7 @@ ; IS__TUNIT_NPM-NEXT: [[C:%.*]] = add i32 [[A]], [[B]] ; IS__TUNIT_NPM-NEXT: ret i32 [[C]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@test ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[X:%.*]], i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[Y:%.*]]) ; IS__CGSCC____-NEXT: [[A:%.*]] = load i32, i32* [[X]], align 4 @@ -38,6 +41,7 @@ } define internal i32 @caller(i32* %B) { +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@caller ; IS__TUNIT_OPM-SAME: (i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B:%.*]]) ; IS__TUNIT_OPM-NEXT: [[A:%.*]] = alloca i32, align 4 @@ -45,6 +49,7 @@ ; IS__TUNIT_OPM-NEXT: [[C:%.*]] = call i32 @test(i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A]], i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B]]) ; IS__TUNIT_OPM-NEXT: ret i32 [[C]] ; +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@caller ; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]]) ; IS__TUNIT_NPM-NEXT: [[B_PRIV:%.*]] = alloca i32, align 4 @@ -56,6 +61,7 @@ ; IS__TUNIT_NPM-NEXT: [[C:%.*]] = call i32 @test(i32 [[TMP2]], i32 [[TMP3]]) ; IS__TUNIT_NPM-NEXT: ret i32 [[C]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@caller ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B:%.*]]) ; IS__CGSCC____-NEXT: [[A:%.*]] = alloca i32, align 4 @@ -70,18 +76,27 @@ } define i32 @callercaller() { -; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@callercaller() -; NOT_TUNIT_NPM-NEXT: [[B:%.*]] = alloca i32, align 4 -; NOT_TUNIT_NPM-NEXT: store i32 2, i32* [[B]], align 4 -; NOT_TUNIT_NPM-NEXT: [[X:%.*]] = call i32 @caller(i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B]]) -; NOT_TUNIT_NPM-NEXT: ret i32 [[X]] +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@callercaller() +; IS__TUNIT_OPM-NEXT: [[B:%.*]] = alloca i32, align 4 +; IS__TUNIT_OPM-NEXT: store i32 2, i32* [[B]], align 4 +; IS__TUNIT_OPM-NEXT: [[X:%.*]] = call i32 @caller(i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B]]) +; IS__TUNIT_OPM-NEXT: ret i32 [[X]] ; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@callercaller() ; IS__TUNIT_NPM-NEXT: [[B:%.*]] = alloca i32, align 4 ; IS__TUNIT_NPM-NEXT: store i32 2, i32* [[B]], align 4 ; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[B]], align 4 ; IS__TUNIT_NPM-NEXT: [[X:%.*]] = call i32 @caller(i32 [[TMP1]]) ; IS__TUNIT_NPM-NEXT: ret i32 [[X]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@callercaller() +; IS__CGSCC____-NEXT: [[B:%.*]] = alloca i32, align 4 +; IS__CGSCC____-NEXT: store i32 2, i32* [[B]], align 4 +; IS__CGSCC____-NEXT: [[X:%.*]] = call i32 @caller(i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B]]) +; IS__CGSCC____-NEXT: ret i32 [[X]] ; %B = alloca i32 store i32 2, i32* %B diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -7,6 +7,7 @@ %struct.ss = type { i32, i64 } define internal void @f(%struct.ss* byval %b, i32* byval %X) nounwind { +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f ; IS__CGSCC_OPM-SAME: (%struct.ss* noalias nocapture nofree nonnull byval align 8 dereferenceable(12) [[B:%.*]], i32* noalias nocapture nofree nonnull writeonly byval align 4 dereferenceable(4) [[X:%.*]]) ; IS__CGSCC_OPM-NEXT: entry: @@ -17,6 +18,7 @@ ; IS__CGSCC_OPM-NEXT: store i32 0, i32* [[X]], align 4 ; 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 [[TMP0:%.*]], i64 [[TMP1:%.*]], i32 [[TMP2:%.*]]) ; IS__CGSCC_NPM-NEXT: entry: @@ -46,6 +48,7 @@ define i32 @test(i32* %X) { ; +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@test ; IS__TUNIT____-SAME: (i32* nocapture nofree readonly align 4 [[X:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -56,6 +59,7 @@ ; IS__TUNIT____-NEXT: store i64 2, i64* [[TMP4]], align 4 ; IS__TUNIT____-NEXT: ret i32 0 ; +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test ; IS__CGSCC_OPM-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[X:%.*]]) ; IS__CGSCC_OPM-NEXT: entry: @@ -66,6 +70,7 @@ ; IS__CGSCC_OPM-NEXT: store i64 2, i64* [[TMP4]], align 4 ; IS__CGSCC_OPM-NEXT: ret i32 0 ; +; IS__CGSCC_NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test ; IS__CGSCC_NPM-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[X:%.*]]) ; IS__CGSCC_NPM-NEXT: entry: diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -9,28 +9,55 @@ %struct.ss = type { i32, i64 } define internal i32 @f(%struct.ss* byval %b) nounwind { -; IS________OPM-LABEL: define {{[^@]+}}@f -; IS________OPM-SAME: (%struct.ss* noalias nocapture nofree nonnull byval align 8 dereferenceable(12) [[B:%.*]]) -; IS________OPM-NEXT: entry: -; IS________OPM-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS:%.*]], %struct.ss* [[B]], i32 0, i32 0 -; IS________OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 8 -; IS________OPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 -; IS________OPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 8 -; IS________OPM-NEXT: ret i32 [[TMP1]] +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@f +; IS__TUNIT_OPM-SAME: (%struct.ss* noalias nocapture nofree nonnull byval align 8 dereferenceable(12) [[B:%.*]]) +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS:%.*]], %struct.ss* [[B]], i32 0, i32 0 +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 8 +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 +; IS__TUNIT_OPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 8 +; IS__TUNIT_OPM-NEXT: ret i32 [[TMP1]] +; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@f +; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[B_PRIV:%.*]] = alloca [[STRUCT_SS:%.*]], align 4 +; IS__TUNIT_NPM-NEXT: [[B_PRIV_CAST:%.*]] = bitcast %struct.ss* [[B_PRIV]] to i32* +; IS__TUNIT_NPM-NEXT: store i32 [[TMP0]], i32* [[B_PRIV_CAST]], align 4 +; IS__TUNIT_NPM-NEXT: [[B_PRIV_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: store i64 [[TMP1]], i64* [[B_PRIV_0_1]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 0 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 8 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 8 +; IS__TUNIT_NPM-NEXT: ret i32 [[TMP1]] ; -; IS________NPM-LABEL: define {{[^@]+}}@f -; IS________NPM-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]]) -; IS________NPM-NEXT: entry: -; IS________NPM-NEXT: [[B_PRIV:%.*]] = alloca [[STRUCT_SS:%.*]], align 4 -; IS________NPM-NEXT: [[B_PRIV_CAST:%.*]] = bitcast %struct.ss* [[B_PRIV]] to i32* -; IS________NPM-NEXT: store i32 [[TMP0]], i32* [[B_PRIV_CAST]], align 4 -; IS________NPM-NEXT: [[B_PRIV_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 1 -; IS________NPM-NEXT: store i64 [[TMP1]], i64* [[B_PRIV_0_1]], align 4 -; IS________NPM-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 0 -; IS________NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 8 -; IS________NPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 -; IS________NPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 8 -; IS________NPM-NEXT: ret i32 [[TMP1]] +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f +; IS__CGSCC_OPM-SAME: (%struct.ss* noalias nocapture nofree nonnull byval align 8 dereferenceable(12) [[B:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS:%.*]], %struct.ss* [[B]], i32 0, i32 0 +; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 8 +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 +; IS__CGSCC_OPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 8 +; IS__CGSCC_OPM-NEXT: ret i32 [[TMP1]] +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f +; IS__CGSCC_NPM-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[B_PRIV:%.*]] = alloca [[STRUCT_SS:%.*]], align 4 +; IS__CGSCC_NPM-NEXT: [[B_PRIV_CAST:%.*]] = bitcast %struct.ss* [[B_PRIV]] to i32* +; IS__CGSCC_NPM-NEXT: store i32 [[TMP0]], i32* [[B_PRIV_CAST]], align 4 +; IS__CGSCC_NPM-NEXT: [[B_PRIV_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 1 +; IS__CGSCC_NPM-NEXT: store i64 [[TMP1]], i64* [[B_PRIV_0_1]], align 4 +; IS__CGSCC_NPM-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 0 +; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 8 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 +; IS__CGSCC_NPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 8 +; IS__CGSCC_NPM-NEXT: ret i32 [[TMP1]] ; entry: %tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0 @@ -42,28 +69,55 @@ define internal i32 @g(%struct.ss* byval align 32 %b) nounwind { -; IS________OPM-LABEL: define {{[^@]+}}@g -; IS________OPM-SAME: (%struct.ss* noalias nocapture nofree nonnull byval align 32 dereferenceable(12) [[B:%.*]]) -; IS________OPM-NEXT: entry: -; IS________OPM-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS:%.*]], %struct.ss* [[B]], i32 0, i32 0 -; IS________OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 32 -; IS________OPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 -; IS________OPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 32 -; IS________OPM-NEXT: ret i32 [[TMP2]] +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@g +; IS__TUNIT_OPM-SAME: (%struct.ss* noalias nocapture nofree nonnull byval align 32 dereferenceable(12) [[B:%.*]]) +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS:%.*]], %struct.ss* [[B]], i32 0, i32 0 +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 32 +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 +; IS__TUNIT_OPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 32 +; IS__TUNIT_OPM-NEXT: ret i32 [[TMP2]] +; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@g +; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[B_PRIV:%.*]] = alloca [[STRUCT_SS:%.*]], align 4 +; IS__TUNIT_NPM-NEXT: [[B_PRIV_CAST:%.*]] = bitcast %struct.ss* [[B_PRIV]] to i32* +; IS__TUNIT_NPM-NEXT: store i32 [[TMP0]], i32* [[B_PRIV_CAST]], align 4 +; IS__TUNIT_NPM-NEXT: [[B_PRIV_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: store i64 [[TMP1]], i64* [[B_PRIV_0_1]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 0 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 32 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 32 +; IS__TUNIT_NPM-NEXT: ret i32 [[TMP2]] ; -; IS________NPM-LABEL: define {{[^@]+}}@g -; IS________NPM-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]]) -; IS________NPM-NEXT: entry: -; IS________NPM-NEXT: [[B_PRIV:%.*]] = alloca [[STRUCT_SS:%.*]], align 4 -; IS________NPM-NEXT: [[B_PRIV_CAST:%.*]] = bitcast %struct.ss* [[B_PRIV]] to i32* -; IS________NPM-NEXT: store i32 [[TMP0]], i32* [[B_PRIV_CAST]], align 4 -; IS________NPM-NEXT: [[B_PRIV_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 1 -; IS________NPM-NEXT: store i64 [[TMP1]], i64* [[B_PRIV_0_1]], align 4 -; IS________NPM-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 0 -; IS________NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 32 -; IS________NPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 -; IS________NPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 32 -; IS________NPM-NEXT: ret i32 [[TMP2]] +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@g +; IS__CGSCC_OPM-SAME: (%struct.ss* noalias nocapture nofree nonnull byval align 32 dereferenceable(12) [[B:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS:%.*]], %struct.ss* [[B]], i32 0, i32 0 +; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 32 +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 +; IS__CGSCC_OPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 32 +; IS__CGSCC_OPM-NEXT: ret i32 [[TMP2]] +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@g +; IS__CGSCC_NPM-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[B_PRIV:%.*]] = alloca [[STRUCT_SS:%.*]], align 4 +; IS__CGSCC_NPM-NEXT: [[B_PRIV_CAST:%.*]] = bitcast %struct.ss* [[B_PRIV]] to i32* +; IS__CGSCC_NPM-NEXT: store i32 [[TMP0]], i32* [[B_PRIV_CAST]], align 4 +; IS__CGSCC_NPM-NEXT: [[B_PRIV_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 1 +; IS__CGSCC_NPM-NEXT: store i64 [[TMP1]], i64* [[B_PRIV_0_1]], align 4 +; IS__CGSCC_NPM-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 0 +; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 32 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 +; IS__CGSCC_NPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 32 +; IS__CGSCC_NPM-NEXT: ret i32 [[TMP2]] ; entry: %tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0 @@ -75,6 +129,7 @@ define i32 @main() nounwind { +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@main() ; IS__TUNIT_OPM-NEXT: entry: ; IS__TUNIT_OPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]], align 4 @@ -87,6 +142,7 @@ ; IS__TUNIT_OPM-NEXT: [[A:%.*]] = add i32 [[C0]], [[C1]] ; IS__TUNIT_OPM-NEXT: ret i32 [[A]] ; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@main() ; IS__TUNIT_NPM-NEXT: entry: ; IS__TUNIT_NPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]], align 4 @@ -107,6 +163,7 @@ ; IS__TUNIT_NPM-NEXT: [[A:%.*]] = add i32 [[C0]], [[C1]] ; IS__TUNIT_NPM-NEXT: ret i32 [[A]] ; +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@main() ; IS__CGSCC_OPM-NEXT: entry: ; IS__CGSCC_OPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]], align 4 @@ -119,6 +176,7 @@ ; IS__CGSCC_OPM-NEXT: [[A:%.*]] = add i32 [[C0]], [[C1]] ; IS__CGSCC_OPM-NEXT: ret i32 [[A]] ; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@main() ; IS__CGSCC_NPM-NEXT: entry: ; IS__CGSCC_NPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]], align 4 diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/chained.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/chained.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/chained.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/chained.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -9,11 +9,19 @@ define internal i32 @test(i32** %x) { ; -; CHECK-LABEL: define {{[^@]+}}@test() -; CHECK-NEXT: entry: -; CHECK-NEXT: [[Y:%.*]] = load i32*, i32** @G2, align 8 -; CHECK-NEXT: [[Z:%.*]] = load i32, i32* [[Y]], align 4 -; CHECK-NEXT: ret i32 [[Z]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[Y:%.*]] = load i32*, i32** @G2, align 8 +; IS__TUNIT____-NEXT: [[Z:%.*]] = load i32, i32* [[Y]], align 4 +; IS__TUNIT____-NEXT: ret i32 [[Z]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[Y:%.*]] = load i32*, i32** @G2, align 8 +; IS__CGSCC____-NEXT: [[Z:%.*]] = load i32, i32* [[Y]], align 4 +; IS__CGSCC____-NEXT: ret i32 [[Z]] ; entry: %y = load i32*, i32** %x @@ -22,10 +30,17 @@ } define i32 @caller() { -; CHECK-LABEL: define {{[^@]+}}@caller() -; CHECK-NEXT: entry: -; CHECK-NEXT: [[X:%.*]] = call i32 @test() -; CHECK-NEXT: ret i32 [[X]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@caller() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[X:%.*]] = call i32 @test() +; IS__TUNIT____-NEXT: ret i32 [[X]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@caller() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[X:%.*]] = call i32 @test() +; IS__CGSCC____-NEXT: ret i32 [[X]] ; entry: %x = call i32 @test(i32** @G2) diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -6,15 +6,27 @@ ; Don't promote around control flow. define internal i32 @callee(i1 %C, i32* %P) { -; CHECK-LABEL: define {{[^@]+}}@callee -; CHECK-SAME: (i1 [[C:%.*]], i32* nocapture nofree readonly [[P:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] -; CHECK: T: -; CHECK-NEXT: ret i32 17 -; CHECK: F: -; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P]], align 4 -; CHECK-NEXT: ret i32 [[X]] +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@callee +; IS__TUNIT____-SAME: (i1 [[C:%.*]], i32* nocapture nofree readonly [[P:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] +; IS__TUNIT____: T: +; IS__TUNIT____-NEXT: ret i32 17 +; IS__TUNIT____: F: +; IS__TUNIT____-NEXT: [[X:%.*]] = load i32, i32* [[P]], align 4 +; IS__TUNIT____-NEXT: ret i32 [[X]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@callee +; IS__CGSCC____-SAME: (i1 [[C:%.*]], i32* nocapture nofree readonly [[P:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] +; IS__CGSCC____: T: +; IS__CGSCC____-NEXT: ret i32 17 +; IS__CGSCC____: F: +; IS__CGSCC____-NEXT: [[X:%.*]] = load i32, i32* [[P]], align 4 +; IS__CGSCC____-NEXT: ret i32 [[X]] ; entry: br i1 %C, label %T, label %F @@ -28,11 +40,19 @@ } define i32 @foo(i1 %C, i32* %P) { -; CHECK-LABEL: define {{[^@]+}}@foo -; CHECK-SAME: (i1 [[C:%.*]], i32* nocapture nofree readonly [[P:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[X:%.*]] = call i32 @callee(i1 [[C]], i32* nocapture nofree readonly [[P]]) -; CHECK-NEXT: ret i32 [[X]] +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@foo +; IS__TUNIT____-SAME: (i1 [[C:%.*]], i32* nocapture nofree readonly [[P:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[X:%.*]] = call i32 @callee(i1 [[C]], i32* nocapture nofree readonly [[P]]) +; IS__TUNIT____-NEXT: ret i32 [[X]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@foo +; IS__CGSCC____-SAME: (i1 [[C:%.*]], i32* nocapture nofree readonly [[P:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[X:%.*]] = call i32 @callee(i1 [[C]], i32* nocapture nofree readonly [[P]]) +; IS__CGSCC____-NEXT: ret i32 [[X]] ; entry: %X = call i32 @callee(i1 %C, i32* %P) diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow2.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow2.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow2.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow2.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=8 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=8 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -7,6 +7,7 @@ target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128" define internal i32 @callee(i1 %C, i32* %P) { +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@callee ; IS__TUNIT_OPM-SAME: (i1 [[C:%.*]], i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) ; IS__TUNIT_OPM-NEXT: br label [[F:%.*]] @@ -16,6 +17,7 @@ ; IS__TUNIT_OPM-NEXT: [[X:%.*]] = load i32, i32* [[P]], align 4 ; IS__TUNIT_OPM-NEXT: ret i32 [[X]] ; +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@callee ; IS__TUNIT_NPM-SAME: (i1 [[C:%.*]], i32 [[TMP0:%.*]]) ; IS__TUNIT_NPM-NEXT: [[P_PRIV:%.*]] = alloca i32, align 4 @@ -27,6 +29,7 @@ ; IS__TUNIT_NPM-NEXT: [[X:%.*]] = load i32, i32* [[P_PRIV]], align 4 ; IS__TUNIT_NPM-NEXT: ret i32 [[X]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@callee ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) ; IS__CGSCC____-NEXT: br label [[F:%.*]] @@ -47,12 +50,14 @@ } define i32 @foo() { +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@foo() ; IS__TUNIT_OPM-NEXT: [[A:%.*]] = alloca i32, align 4 ; IS__TUNIT_OPM-NEXT: store i32 17, i32* [[A]], align 4 ; IS__TUNIT_OPM-NEXT: [[X:%.*]] = call i32 @callee(i1 false, i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A]]) ; IS__TUNIT_OPM-NEXT: ret i32 [[X]] ; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@foo() ; IS__TUNIT_NPM-NEXT: [[A:%.*]] = alloca i32, align 4 ; IS__TUNIT_NPM-NEXT: store i32 17, i32* [[A]], align 4 @@ -60,6 +65,7 @@ ; IS__TUNIT_NPM-NEXT: [[X:%.*]] = call i32 @callee(i1 false, i32 [[TMP1]]) ; IS__TUNIT_NPM-NEXT: ret i32 [[X]] ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@foo() ; IS__CGSCC____-NEXT: [[A:%.*]] = alloca i32, align 4 ; IS__CGSCC____-NEXT: store i32 17, i32* [[A]], align 4 diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/crash.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/crash.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/crash.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/crash.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -9,14 +9,25 @@ ; Inlining should nuke the invoke (and any inlined calls) here even with ; argument promotion running along with it. define void @zot() personality i32 (...)* @wibble { -; CHECK-LABEL: define {{[^@]+}}@zot() #0 personality i32 (...)* @wibble -; CHECK-NEXT: bb: -; CHECK-NEXT: call void @hoge() -; CHECK-NEXT: unreachable -; CHECK: bb1: -; CHECK-NEXT: unreachable -; CHECK: bb2: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree noreturn nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@zot() #0 personality i32 (...)* @wibble +; IS__TUNIT____-NEXT: bb: +; IS__TUNIT____-NEXT: call void @hoge() +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: bb1: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: bb2: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@zot() #0 personality i32 (...)* @wibble +; IS__CGSCC____-NEXT: bb: +; IS__CGSCC____-NEXT: call void @hoge() +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: bb1: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: bb2: +; IS__CGSCC____-NEXT: unreachable ; bb: invoke void @hoge() @@ -32,9 +43,15 @@ } define internal void @hoge() { -; CHECK-LABEL: define {{[^@]+}}@hoge() -; CHECK-NEXT: bb: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree noreturn nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@hoge() +; IS__TUNIT____-NEXT: bb: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@hoge() +; IS__CGSCC____-NEXT: bb: +; IS__CGSCC____-NEXT: unreachable ; bb: %tmp = call fastcc i8* @spam(i1 (i8*)* @eggs) @@ -43,6 +60,7 @@ } define internal fastcc i8* @spam(i1 (i8*)* %arg) { +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@spam() ; IS__CGSCC____-NEXT: bb: ; IS__CGSCC____-NEXT: unreachable @@ -58,6 +76,7 @@ } define internal i1 @barney(i8* %arg) { +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@barney() ; IS__CGSCC____-NEXT: bb: ; IS__CGSCC____-NEXT: ret i1 undef @@ -67,11 +86,13 @@ } define i32 @test_inf_promote_caller(i32 %arg) { +; IS__TUNIT____: Function Attrs: nofree noreturn nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@test_inf_promote_caller ; IS__TUNIT____-SAME: (i32 [[ARG:%.*]]) ; IS__TUNIT____-NEXT: bb: ; IS__TUNIT____-NEXT: unreachable ; +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@test_inf_promote_caller ; IS__CGSCC____-SAME: (i32 [[ARG:%.*]]) ; IS__CGSCC____-NEXT: bb: @@ -88,6 +109,7 @@ } define internal i32 @test_inf_promote_callee(%S* %arg, %S* %arg1) { +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@test_inf_promote_callee() ; IS__CGSCC____-NEXT: bb: ; IS__CGSCC____-NEXT: unreachable diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/dbg.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/dbg.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/dbg.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/dbg.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM 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 @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; TODO: The old pass manager cgscc run is disabled as it causes a crash on windows which is under investigation: http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/23151 @@ -17,9 +17,15 @@ @a = internal global %struct.Foo { i32 1, i64 2 }, align 8 define void @run() { -; CHECK-LABEL: define {{[^@]+}}@run() -; CHECK-NEXT: entry: -; CHECK-NEXT: unreachable +; NOT_CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@run() +; NOT_CGSCC_NPM-NEXT: entry: +; NOT_CGSCC_NPM-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@run() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: unreachable ; entry: tail call i8 @UseLongDoubleUnsafely(%union.u* byval align 16 bitcast (%struct.s* @b to %union.u*)) @@ -30,6 +36,7 @@ } define internal i8 @UseLongDoubleUnsafely(%union.u* byval align 16 %arg) { +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@UseLongDoubleUnsafely() ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: ret i8 undef @@ -42,6 +49,7 @@ } define internal x86_fp80 @UseLongDoubleSafely(%union.u* byval align 16 %arg) { +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@UseLongDoubleSafely() ; IS__CGSCC____-NEXT: ret x86_fp80 undef ; @@ -51,6 +59,7 @@ } define internal i64 @AccessPaddingOfStruct(%struct.Foo* byval %a) { +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@AccessPaddingOfStruct() ; IS__CGSCC____-NEXT: ret i64 undef ; @@ -72,6 +81,7 @@ ; IS__CGSCC_OPM-NEXT: [[GEP]] = getelementptr [[STRUCT_FOO:%.*]], %struct.Foo* [[A]], i64 0 ; IS__CGSCC_OPM-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:%.*]]) ; IS__CGSCC____-NEXT: entry: diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -10,6 +10,7 @@ ; Argpromote + sroa should change this to passing the two integers by value. define internal i32 @f(%struct.ss* inalloca %s) { +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@f ; IS__TUNIT____-SAME: (%struct.ss* inalloca noalias nocapture nofree nonnull align 4 dereferenceable(8) [[S:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -20,6 +21,7 @@ ; IS__TUNIT____-NEXT: [[R:%.*]] = add i32 [[A]], [[B]] ; IS__TUNIT____-NEXT: ret i32 [[R]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@f ; IS__CGSCC____-SAME: (%struct.ss* inalloca nocapture nofree nonnull align 4 dereferenceable(8) [[S:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -40,15 +42,27 @@ } define i32 @main() { -; CHECK-LABEL: define {{[^@]+}}@main() -; CHECK-NEXT: entry: -; CHECK-NEXT: [[S:%.*]] = alloca inalloca [[STRUCT_SS:%.*]], align 4 -; CHECK-NEXT: [[F0:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 -; CHECK-NEXT: [[F1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 -; CHECK-NEXT: store i32 1, i32* [[F0]], align 4 -; CHECK-NEXT: store i32 2, i32* [[F1]], align 4 -; CHECK-NEXT: [[R:%.*]] = call i32 @f(%struct.ss* inalloca noalias nocapture nofree nonnull align 4 dereferenceable(8) [[S]]) -; CHECK-NEXT: ret i32 [[R]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@main() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[S:%.*]] = alloca inalloca [[STRUCT_SS:%.*]], align 4 +; IS__TUNIT____-NEXT: [[F0:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 +; IS__TUNIT____-NEXT: [[F1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__TUNIT____-NEXT: store i32 1, i32* [[F0]], align 4 +; IS__TUNIT____-NEXT: store i32 2, i32* [[F1]], align 4 +; IS__TUNIT____-NEXT: [[R:%.*]] = call i32 @f(%struct.ss* inalloca noalias nocapture nofree nonnull align 4 dereferenceable(8) [[S]]) +; IS__TUNIT____-NEXT: ret i32 [[R]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@main() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[S:%.*]] = alloca inalloca [[STRUCT_SS:%.*]], align 4 +; IS__CGSCC____-NEXT: [[F0:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 +; IS__CGSCC____-NEXT: [[F1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__CGSCC____-NEXT: store i32 1, i32* [[F0]], align 4 +; IS__CGSCC____-NEXT: store i32 2, i32* [[F1]], align 4 +; IS__CGSCC____-NEXT: [[R:%.*]] = call i32 @f(%struct.ss* inalloca noalias nocapture nofree nonnull align 4 dereferenceable(8) [[S]]) +; IS__CGSCC____-NEXT: ret i32 [[R]] ; entry: %S = alloca inalloca %struct.ss @@ -62,6 +76,7 @@ ; Argpromote can't promote %a because of the icmp use. define internal i1 @g(%struct.ss* %a, %struct.ss* inalloca %b) nounwind { +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@g ; IS__CGSCC____-SAME: (%struct.ss* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[A:%.*]], %struct.ss* inalloca nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[B:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -73,9 +88,15 @@ } define i32 @test() { -; CHECK-LABEL: define {{[^@]+}}@test() -; CHECK-NEXT: entry: -; CHECK-NEXT: ret i32 0 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret i32 0 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i32 0 ; entry: %S = alloca inalloca %struct.ss diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/invalidation.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/invalidation.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/invalidation.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/invalidation.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; Check that when argument promotion changes a function in some parent node of ; the call graph, any analyses that happened to be cached for that function are ; actually invalidated. We are using `demanded-bits` here because when printed @@ -12,6 +12,7 @@ @G = constant i32 0 define internal i32 @a(i32* %x) { +; CHECK: Function Attrs: nofree nosync nounwind readonly willreturn ; CHECK-LABEL: define {{[^@]+}}@a() ; CHECK-NEXT: entry: ; CHECK-NEXT: [[V:%.*]] = load i32, i32* @G, align 4 @@ -23,6 +24,7 @@ } define i32 @b() { +; CHECK: Function Attrs: nofree nosync nounwind readonly willreturn ; CHECK-LABEL: define {{[^@]+}}@b() ; CHECK-NEXT: entry: ; CHECK-NEXT: [[V:%.*]] = call i32 @a() @@ -34,6 +36,7 @@ } define i32 @c() { +; CHECK: Function Attrs: nofree nosync nounwind readonly willreturn ; CHECK-LABEL: define {{[^@]+}}@c() ; CHECK-NEXT: entry: ; CHECK-NEXT: [[V1:%.*]] = call i32 @a() diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -11,6 +11,7 @@ } define internal i32 @test(i32* %X, i32* %Y) { +; IS__CGSCC_OPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test ; IS__CGSCC_OPM-SAME: (i32* noalias nocapture nofree writeonly align 4 [[X:%.*]]) ; IS__CGSCC_OPM-NEXT: br i1 true, label [[LIVE:%.*]], label [[DEAD:%.*]] @@ -20,6 +21,7 @@ ; IS__CGSCC_OPM: dead: ; IS__CGSCC_OPM-NEXT: unreachable ; +; IS__CGSCC_NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test ; IS__CGSCC_NPM-SAME: (i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[X:%.*]]) ; IS__CGSCC_NPM-NEXT: br i1 true, label [[LIVE:%.*]], label [[DEAD:%.*]] @@ -40,12 +42,14 @@ } define internal i32 @caller(i32* %B) { +; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@caller() ; IS__CGSCC_OPM-NEXT: [[A:%.*]] = alloca i32, align 4 ; IS__CGSCC_OPM-NEXT: store i32 1, i32* [[A]], align 4 ; IS__CGSCC_OPM-NEXT: [[C:%.*]] = call i32 @test(i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A]]) ; IS__CGSCC_OPM-NEXT: ret i32 0 ; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@caller() ; IS__CGSCC_NPM-NEXT: [[A:%.*]] = alloca i32, align 4 ; IS__CGSCC_NPM-NEXT: store i32 1, i32* [[A]], align 4 @@ -59,10 +63,17 @@ } define i32 @callercaller() { -; CHECK-LABEL: define {{[^@]+}}@callercaller() -; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 -; CHECK-NEXT: store i32 2, i32* [[B]], align 4 -; CHECK-NEXT: ret i32 0 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@callercaller() +; IS__TUNIT____-NEXT: [[B:%.*]] = alloca i32, align 4 +; IS__TUNIT____-NEXT: store i32 2, i32* [[B]], align 4 +; IS__TUNIT____-NEXT: ret i32 0 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@callercaller() +; IS__CGSCC____-NEXT: [[B:%.*]] = alloca i32, align 4 +; IS__CGSCC____-NEXT: store i32 2, i32* [[B]], align 4 +; IS__CGSCC____-NEXT: ret i32 0 ; %B = alloca i32 store i32 2, i32* %B diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead_2.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead_2.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead_2.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/live_called_from_dead_2.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=8 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -11,6 +11,7 @@ } define internal i32 @test(i32* %X, i32* %Y) { +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@test ; IS__TUNIT____-SAME: (i32* noalias nocapture nofree writeonly align 4 [[X:%.*]]) ; IS__TUNIT____-NEXT: br i1 true, label [[LIVE:%.*]], label [[DEAD:%.*]] @@ -20,6 +21,7 @@ ; IS__TUNIT____: dead: ; IS__TUNIT____-NEXT: unreachable ; +; IS__CGSCC_OPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test ; IS__CGSCC_OPM-SAME: (i32* nocapture nofree writeonly align 4 [[X:%.*]]) ; IS__CGSCC_OPM-NEXT: br i1 true, label [[LIVE:%.*]], label [[DEAD:%.*]] @@ -29,6 +31,7 @@ ; IS__CGSCC_OPM: dead: ; IS__CGSCC_OPM-NEXT: unreachable ; +; IS__CGSCC_NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test ; IS__CGSCC_NPM-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[X:%.*]]) ; IS__CGSCC_NPM-NEXT: br i1 true, label [[LIVE:%.*]], label [[DEAD:%.*]] @@ -49,6 +52,7 @@ } define internal i32 @caller(i32* %B) { +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@caller ; IS__TUNIT____-SAME: (i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[B:%.*]]) ; IS__TUNIT____-NEXT: [[A:%.*]] = alloca i32, align 4 @@ -56,6 +60,7 @@ ; IS__TUNIT____-NEXT: [[C:%.*]] = call i32 @test(i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[B]]) ; IS__TUNIT____-NEXT: ret i32 0 ; +; IS__CGSCC_OPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@caller ; IS__CGSCC_OPM-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[B:%.*]]) ; IS__CGSCC_OPM-NEXT: [[A:%.*]] = alloca i32, align 4 @@ -63,6 +68,7 @@ ; IS__CGSCC_OPM-NEXT: [[C:%.*]] = call i32 @test(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[B]]) ; IS__CGSCC_OPM-NEXT: ret i32 0 ; +; IS__CGSCC_NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@caller ; IS__CGSCC_NPM-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[B:%.*]]) ; IS__CGSCC_NPM-NEXT: [[A:%.*]] = alloca i32, align 4 @@ -77,11 +83,19 @@ } define i32 @callercaller() { -; CHECK-LABEL: define {{[^@]+}}@callercaller() -; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 -; CHECK-NEXT: store i32 2, i32* [[B]], align 4 -; CHECK-NEXT: [[X:%.*]] = call i32 @caller(i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[B]]) -; CHECK-NEXT: ret i32 0 +; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@callercaller() +; NOT_CGSCC_NPM-NEXT: [[B:%.*]] = alloca i32, align 4 +; NOT_CGSCC_NPM-NEXT: store i32 2, i32* [[B]], align 4 +; NOT_CGSCC_NPM-NEXT: [[X:%.*]] = call i32 @caller(i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[B]]) +; NOT_CGSCC_NPM-NEXT: ret i32 0 +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@callercaller() +; IS__CGSCC_NPM-NEXT: [[B:%.*]] = alloca i32, align 4 +; IS__CGSCC_NPM-NEXT: store i32 2, i32* [[B]], align 4 +; IS__CGSCC_NPM-NEXT: [[X:%.*]] = call i32 @caller(i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[B]]) +; IS__CGSCC_NPM-NEXT: ret i32 0 ; %B = alloca i32 store i32 2, i32* %B diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/musttail.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/musttail.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/musttail.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/musttail.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -10,14 +10,25 @@ %T = type { i32, i32, i32, i32 } define internal i32 @test(%T* %p) { -; CHECK-LABEL: define {{[^@]+}}@test -; CHECK-SAME: (%T* nocapture nofree readonly [[P:%.*]]) -; CHECK-NEXT: [[A_GEP:%.*]] = getelementptr [[T:%.*]], %T* [[P]], i64 0, i32 3 -; CHECK-NEXT: [[B_GEP:%.*]] = getelementptr [[T]], %T* [[P]], i64 0, i32 2 -; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[A_GEP]], align 4 -; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[B_GEP]], align 4 -; CHECK-NEXT: [[V:%.*]] = add i32 [[A]], [[B]] -; CHECK-NEXT: ret i32 [[V]] +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test +; IS__TUNIT____-SAME: (%T* nocapture nofree readonly [[P:%.*]]) +; IS__TUNIT____-NEXT: [[A_GEP:%.*]] = getelementptr [[T:%.*]], %T* [[P]], i64 0, i32 3 +; IS__TUNIT____-NEXT: [[B_GEP:%.*]] = getelementptr [[T]], %T* [[P]], i64 0, i32 2 +; IS__TUNIT____-NEXT: [[A:%.*]] = load i32, i32* [[A_GEP]], align 4 +; IS__TUNIT____-NEXT: [[B:%.*]] = load i32, i32* [[B_GEP]], align 4 +; IS__TUNIT____-NEXT: [[V:%.*]] = add i32 [[A]], [[B]] +; IS__TUNIT____-NEXT: ret i32 [[V]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test +; IS__CGSCC____-SAME: (%T* nocapture nofree readonly [[P:%.*]]) +; IS__CGSCC____-NEXT: [[A_GEP:%.*]] = getelementptr [[T:%.*]], %T* [[P]], i64 0, i32 3 +; IS__CGSCC____-NEXT: [[B_GEP:%.*]] = getelementptr [[T]], %T* [[P]], i64 0, i32 2 +; IS__CGSCC____-NEXT: [[A:%.*]] = load i32, i32* [[A_GEP]], align 4 +; IS__CGSCC____-NEXT: [[B:%.*]] = load i32, i32* [[B_GEP]], align 4 +; IS__CGSCC____-NEXT: [[V:%.*]] = add i32 [[A]], [[B]] +; IS__CGSCC____-NEXT: ret i32 [[V]] ; %a.gep = getelementptr %T, %T* %p, i64 0, i32 3 %b.gep = getelementptr %T, %T* %p, i64 0, i32 2 @@ -28,10 +39,17 @@ } define i32 @caller(%T* %p) { -; CHECK-LABEL: define {{[^@]+}}@caller -; CHECK-SAME: (%T* nocapture nofree readonly [[P:%.*]]) -; CHECK-NEXT: [[V:%.*]] = musttail call i32 @test(%T* nocapture nofree readonly [[P]]) -; CHECK-NEXT: ret i32 [[V]] +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@caller +; IS__TUNIT____-SAME: (%T* nocapture nofree readonly [[P:%.*]]) +; IS__TUNIT____-NEXT: [[V:%.*]] = musttail call i32 @test(%T* nocapture nofree readonly [[P]]) +; IS__TUNIT____-NEXT: ret i32 [[V]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@caller +; IS__CGSCC____-SAME: (%T* nocapture nofree readonly [[P:%.*]]) +; IS__CGSCC____-NEXT: [[V:%.*]] = musttail call i32 @test(%T* nocapture nofree readonly [[P]]) +; IS__CGSCC____-NEXT: ret i32 [[V]] ; %v = musttail call i32 @test(%T* %p) ret i32 %v @@ -40,14 +58,21 @@ ; Don't promote arguments of musttail caller define i32 @foo(%T* %p, i32 %v) { -; CHECK-LABEL: define {{[^@]+}}@foo -; CHECK-SAME: (%T* nocapture nofree readnone [[P:%.*]], i32 [[V:%.*]]) -; CHECK-NEXT: ret i32 0 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@foo +; IS__TUNIT____-SAME: (%T* nocapture nofree readnone [[P:%.*]], i32 [[V:%.*]]) +; IS__TUNIT____-NEXT: ret i32 0 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@foo +; IS__CGSCC____-SAME: (%T* nocapture nofree readnone [[P:%.*]], i32 [[V:%.*]]) +; IS__CGSCC____-NEXT: ret i32 0 ; ret i32 0 } define internal i32 @test2(%T* %p, i32 %p2) { +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@test2 ; IS__CGSCC____-SAME: (%T* nocapture nofree readonly [[P:%.*]], i32 [[P2:%.*]]) ; IS__CGSCC____-NEXT: [[A_GEP:%.*]] = getelementptr [[T:%.*]], %T* [[P]], i64 0, i32 3 @@ -68,10 +93,12 @@ } define i32 @caller2(%T* %g) { +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@caller2 ; IS__TUNIT____-SAME: (%T* nocapture nofree readnone [[G:%.*]]) ; IS__TUNIT____-NEXT: ret i32 0 ; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@caller2 ; IS__CGSCC____-SAME: (%T* nocapture nofree readonly align 4 [[G:%.*]]) ; IS__CGSCC____-NEXT: [[V:%.*]] = call i32 @test2(%T* nocapture nofree readonly [[G]], i32 0) @@ -86,11 +113,19 @@ ; is kept as well. define i32 @bar(%T* %p, i32 %v) { -; CHECK-LABEL: define {{[^@]+}}@bar -; CHECK-SAME: (%T* nocapture nofree nonnull writeonly dereferenceable(4) [[P:%.*]], i32 [[V:%.*]]) -; CHECK-NEXT: [[I32PTR:%.*]] = getelementptr [[T:%.*]], %T* [[P]], i64 0, i32 0 -; CHECK-NEXT: store i32 [[V]], i32* [[I32PTR]], align 4 -; CHECK-NEXT: ret i32 0 +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@bar +; IS__TUNIT____-SAME: (%T* nocapture nofree nonnull writeonly dereferenceable(4) [[P:%.*]], i32 [[V:%.*]]) +; IS__TUNIT____-NEXT: [[I32PTR:%.*]] = getelementptr [[T:%.*]], %T* [[P]], i64 0, i32 0 +; IS__TUNIT____-NEXT: store i32 [[V]], i32* [[I32PTR]], align 4 +; IS__TUNIT____-NEXT: ret i32 0 +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@bar +; IS__CGSCC____-SAME: (%T* nocapture nofree nonnull writeonly dereferenceable(4) [[P:%.*]], i32 [[V:%.*]]) +; IS__CGSCC____-NEXT: [[I32PTR:%.*]] = getelementptr [[T:%.*]], %T* [[P]], i64 0, i32 0 +; IS__CGSCC____-NEXT: store i32 [[V]], i32* [[I32PTR]], align 4 +; IS__CGSCC____-NEXT: ret i32 0 ; %i32ptr = getelementptr %T, %T* %p, i64 0, i32 0 store i32 %v, i32* %i32ptr @@ -98,15 +133,27 @@ } define internal i32 @test2b(%T* %p, i32 %p2) { -; CHECK-LABEL: define {{[^@]+}}@test2b -; CHECK-SAME: (%T* nocapture nofree readonly [[P:%.*]], i32 [[P2:%.*]]) -; CHECK-NEXT: [[A_GEP:%.*]] = getelementptr [[T:%.*]], %T* [[P]], i64 0, i32 3 -; CHECK-NEXT: [[B_GEP:%.*]] = getelementptr [[T]], %T* [[P]], i64 0, i32 2 -; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[A_GEP]], align 4 -; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[B_GEP]], align 4 -; CHECK-NEXT: [[V:%.*]] = add i32 [[A]], [[B]] -; CHECK-NEXT: [[CA:%.*]] = musttail call i32 @bar(%T* undef, i32 [[V]]) -; CHECK-NEXT: ret i32 [[CA]] +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test2b +; IS__TUNIT____-SAME: (%T* nocapture nofree readonly [[P:%.*]], i32 [[P2:%.*]]) +; IS__TUNIT____-NEXT: [[A_GEP:%.*]] = getelementptr [[T:%.*]], %T* [[P]], i64 0, i32 3 +; IS__TUNIT____-NEXT: [[B_GEP:%.*]] = getelementptr [[T]], %T* [[P]], i64 0, i32 2 +; IS__TUNIT____-NEXT: [[A:%.*]] = load i32, i32* [[A_GEP]], align 4 +; IS__TUNIT____-NEXT: [[B:%.*]] = load i32, i32* [[B_GEP]], align 4 +; IS__TUNIT____-NEXT: [[V:%.*]] = add i32 [[A]], [[B]] +; IS__TUNIT____-NEXT: [[CA:%.*]] = musttail call i32 @bar(%T* undef, i32 [[V]]) +; IS__TUNIT____-NEXT: ret i32 [[CA]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test2b +; IS__CGSCC____-SAME: (%T* nocapture nofree readonly [[P:%.*]], i32 [[P2:%.*]]) +; IS__CGSCC____-NEXT: [[A_GEP:%.*]] = getelementptr [[T:%.*]], %T* [[P]], i64 0, i32 3 +; IS__CGSCC____-NEXT: [[B_GEP:%.*]] = getelementptr [[T]], %T* [[P]], i64 0, i32 2 +; IS__CGSCC____-NEXT: [[A:%.*]] = load i32, i32* [[A_GEP]], align 4 +; IS__CGSCC____-NEXT: [[B:%.*]] = load i32, i32* [[B_GEP]], align 4 +; IS__CGSCC____-NEXT: [[V:%.*]] = add i32 [[A]], [[B]] +; IS__CGSCC____-NEXT: [[CA:%.*]] = musttail call i32 @bar(%T* undef, i32 [[V]]) +; IS__CGSCC____-NEXT: ret i32 [[CA]] ; %a.gep = getelementptr %T, %T* %p, i64 0, i32 3 %b.gep = getelementptr %T, %T* %p, i64 0, i32 2 @@ -118,11 +165,13 @@ } define i32 @caller2b(%T* %g) { +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@caller2b ; IS__TUNIT____-SAME: (%T* nocapture nofree readonly [[G:%.*]]) ; IS__TUNIT____-NEXT: [[V:%.*]] = call i32 @test2b(%T* nocapture nofree readonly [[G]], i32 undef) ; IS__TUNIT____-NEXT: ret i32 0 ; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@caller2b ; IS__CGSCC____-SAME: (%T* nocapture nofree readonly align 4 [[G:%.*]]) ; IS__CGSCC____-NEXT: [[V:%.*]] = call i32 @test2b(%T* nocapture nofree readonly [[G]], i32 0) diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/naked_functions.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/naked_functions.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/naked_functions.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/naked_functions.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -20,6 +20,7 @@ } define internal i32 @foo(i32*) #0 { +; CHECK: Function Attrs: naked ; CHECK-LABEL: define {{[^@]+}}@foo ; CHECK-SAME: (i32* [[TMP0:%.*]]) ; CHECK-NEXT: entry: diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/nonzero-address-spaces.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/nonzero-address-spaces.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/nonzero-address-spaces.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/nonzero-address-spaces.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -12,6 +12,7 @@ @g = common global i32 0, align 4 define i32 @bar() { +; CHECK: Function Attrs: noreturn ; CHECK-LABEL: define {{[^@]+}}@bar() addrspace(1) ; CHECK-NEXT: entry: ; CHECK-NEXT: [[CALL:%.*]] = call addrspace(1) i32 @foo() @@ -24,6 +25,7 @@ } define internal i32 @foo(i32*) { +; CHECK: Function Attrs: noreturn ; CHECK-LABEL: define {{[^@]+}}@foo() addrspace(1) ; CHECK-NEXT: entry: ; CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/pr27568.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/pr27568.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/pr27568.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/pr27568.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/pr32917.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/pr32917.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/pr32917.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/pr32917.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -9,6 +9,7 @@ @a = common local_unnamed_addr global i32 0, align 4 define i32 @fn2() local_unnamed_addr { +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@fn2() local_unnamed_addr ; IS__TUNIT____-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 ; IS__TUNIT____-NEXT: [[TMP2:%.*]] = sext i32 [[TMP1]] to i64 @@ -16,6 +17,7 @@ ; IS__TUNIT____-NEXT: call fastcc void @fn1(i32* nocapture nofree readonly align 4 [[TMP3]]) ; IS__TUNIT____-NEXT: ret i32 undef ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@fn2() local_unnamed_addr ; IS__CGSCC____-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 ; IS__CGSCC____-NEXT: [[TMP2:%.*]] = sext i32 [[TMP1]] to i64 @@ -31,12 +33,21 @@ } define internal fastcc void @fn1(i32* nocapture readonly) unnamed_addr { -; CHECK-LABEL: define {{[^@]+}}@fn1 -; CHECK-SAME: (i32* nocapture nofree nonnull readonly align 4 [[TMP0:%.*]]) unnamed_addr -; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 -1 -; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 -; CHECK-NEXT: store i32 [[TMP3]], i32* @a, align 4 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@fn1 +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readonly align 4 [[TMP0:%.*]]) unnamed_addr +; IS__TUNIT____-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 -1 +; IS__TUNIT____-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 +; IS__TUNIT____-NEXT: store i32 [[TMP3]], i32* @a, align 4 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@fn1 +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 [[TMP0:%.*]]) unnamed_addr +; IS__CGSCC____-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 -1 +; IS__CGSCC____-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 +; IS__CGSCC____-NEXT: store i32 [[TMP3]], i32* @a, align 4 +; IS__CGSCC____-NEXT: ret void ; %2 = getelementptr inbounds i32, i32* %0, i64 -1 %3 = load i32, i32* %2, align 4 diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/pr33641_remove_arg_dbgvalue.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/pr33641_remove_arg_dbgvalue.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/pr33641_remove_arg_dbgvalue.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/pr33641_remove_arg_dbgvalue.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -14,10 +14,17 @@ %fun_t = type void (%p_t)* define void @foo() { -; CHECK-LABEL: define {{[^@]+}}@foo() -; CHECK-NEXT: [[TMP:%.*]] = alloca void (i16*)*, align 8 -; CHECK-NEXT: store void (i16*)* @bar, void (i16*)** [[TMP]], align 8 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@foo() +; IS__TUNIT____-NEXT: [[TMP:%.*]] = alloca void (i16*)*, align 8 +; IS__TUNIT____-NEXT: store void (i16*)* @bar, void (i16*)** [[TMP]], align 8 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@foo() +; IS__CGSCC____-NEXT: [[TMP:%.*]] = alloca void (i16*)*, align 8 +; IS__CGSCC____-NEXT: store void (i16*)* @bar, void (i16*)** [[TMP]], align 8 +; IS__CGSCC____-NEXT: ret void ; %tmp = alloca %fun_t store %fun_t @bar, %fun_t* %tmp @@ -25,6 +32,7 @@ } define internal void @bar(%p_t %p) { +; CHECK: Function Attrs: nosync nounwind readnone willreturn ; CHECK-LABEL: define {{[^@]+}}@bar ; CHECK-SAME: (i16* nocapture nofree readnone [[P:%.*]]) ; CHECK-NEXT: call void @llvm.dbg.value(metadata i16* [[P]], metadata !3, metadata !DIExpression()) #3, !dbg !5 diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/profile.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/profile.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/profile.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/profile.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/reserve-tbaa.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/reserve-tbaa.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/reserve-tbaa.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/reserve-tbaa.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -17,6 +17,7 @@ @d = global i8 0, align 1 define internal fastcc void @fn(i32* nocapture readonly %p1, i64* nocapture readonly %p2) { +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@fn ; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P1:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -25,6 +26,7 @@ ; IS__TUNIT____-NEXT: store i8 [[CONV1]], i8* @d, align 1, !tbaa !4 ; IS__TUNIT____-NEXT: ret void ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@fn() ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* @g, align 4, !tbaa !0 @@ -42,6 +44,7 @@ } define i32 @main() { +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@main() ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32**, i32*** @e, align 8, !tbaa !5 @@ -51,6 +54,7 @@ ; IS__TUNIT____-NEXT: call fastcc void @fn(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) @g) ; IS__TUNIT____-NEXT: ret i32 0 ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@main() ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32**, i32*** @e, align 8, !tbaa !5 diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/sret.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/sret.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/sret.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/sret.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -9,16 +9,18 @@ define internal void @add({i32, i32}* %this, i32* sret %r) { ; -; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@add -; NOT_TUNIT_NPM-SAME: ({ i32, i32 }* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[THIS:%.*]], i32* nocapture nofree nonnull sret writeonly align 4 dereferenceable(4) [[R:%.*]]) -; NOT_TUNIT_NPM-NEXT: [[AP:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[THIS]], i32 0, i32 0 -; NOT_TUNIT_NPM-NEXT: [[BP:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[THIS]], i32 0, i32 1 -; NOT_TUNIT_NPM-NEXT: [[A:%.*]] = load i32, i32* [[AP]], align 8 -; NOT_TUNIT_NPM-NEXT: [[B:%.*]] = load i32, i32* [[BP]], align 4 -; NOT_TUNIT_NPM-NEXT: [[AB:%.*]] = add i32 [[A]], [[B]] -; NOT_TUNIT_NPM-NEXT: store i32 [[AB]], i32* [[R]], align 4 -; NOT_TUNIT_NPM-NEXT: ret void +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind willreturn +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@add +; IS__TUNIT_OPM-SAME: ({ i32, i32 }* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[THIS:%.*]], i32* nocapture nofree nonnull sret writeonly align 4 dereferenceable(4) [[R:%.*]]) +; IS__TUNIT_OPM-NEXT: [[AP:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[THIS]], i32 0, i32 0 +; IS__TUNIT_OPM-NEXT: [[BP:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[THIS]], i32 0, i32 1 +; IS__TUNIT_OPM-NEXT: [[A:%.*]] = load i32, i32* [[AP]], align 8 +; IS__TUNIT_OPM-NEXT: [[B:%.*]] = load i32, i32* [[BP]], align 4 +; IS__TUNIT_OPM-NEXT: [[AB:%.*]] = add i32 [[A]], [[B]] +; IS__TUNIT_OPM-NEXT: store i32 [[AB]], i32* [[R]], align 4 +; IS__TUNIT_OPM-NEXT: ret void ; +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@add ; IS__TUNIT_NPM-SAME: ({ i32, i32 }* noalias nocapture nofree nonnull readonly align 8 dereferenceable(8) [[THIS:%.*]], i32* noalias nocapture nofree nonnull sret writeonly align 4 dereferenceable(4) [[R:%.*]]) ; IS__TUNIT_NPM-NEXT: [[AP:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[THIS]], i32 0, i32 0 @@ -28,6 +30,17 @@ ; IS__TUNIT_NPM-NEXT: [[AB:%.*]] = add i32 [[A]], [[B]] ; IS__TUNIT_NPM-NEXT: store i32 [[AB]], i32* [[R]], align 4 ; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@add +; IS__CGSCC____-SAME: ({ i32, i32 }* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[THIS:%.*]], i32* nocapture nofree nonnull sret writeonly align 4 dereferenceable(4) [[R:%.*]]) +; IS__CGSCC____-NEXT: [[AP:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[THIS]], i32 0, i32 0 +; IS__CGSCC____-NEXT: [[BP:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[THIS]], i32 0, i32 1 +; IS__CGSCC____-NEXT: [[A:%.*]] = load i32, i32* [[AP]], align 8 +; IS__CGSCC____-NEXT: [[B:%.*]] = load i32, i32* [[BP]], align 4 +; IS__CGSCC____-NEXT: [[AB:%.*]] = add i32 [[A]], [[B]] +; IS__CGSCC____-NEXT: store i32 [[AB]], i32* [[R]], align 4 +; IS__CGSCC____-NEXT: ret void ; %ap = getelementptr {i32, i32}, {i32, i32}* %this, i32 0, i32 0 %bp = getelementptr {i32, i32}, {i32, i32}* %this, i32 0, i32 1 @@ -39,17 +52,33 @@ } define void @f() { -; IS________OPM-LABEL: define {{[^@]+}}@f() -; IS________OPM-NEXT: [[R:%.*]] = alloca i32, align 4 -; IS________OPM-NEXT: [[PAIR:%.*]] = alloca { i32, i32 }, align 8 -; IS________OPM-NEXT: call void @add({ i32, i32 }* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[PAIR]], i32* nocapture nofree nonnull sret writeonly align 4 dereferenceable(4) [[R]]) -; IS________OPM-NEXT: ret void -; -; IS________NPM-LABEL: define {{[^@]+}}@f() -; IS________NPM-NEXT: [[R:%.*]] = alloca i32, align 4 -; IS________NPM-NEXT: [[PAIR:%.*]] = alloca { i32, i32 }, align 8 -; IS________NPM-NEXT: call void @add({ i32, i32 }* noalias nocapture nofree nonnull readonly align 8 dereferenceable(8) [[PAIR]], i32* noalias nocapture nofree nonnull sret writeonly align 4 dereferenceable(4) [[R]]) -; IS________NPM-NEXT: ret void +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@f() +; IS__TUNIT_OPM-NEXT: [[R:%.*]] = alloca i32, align 4 +; IS__TUNIT_OPM-NEXT: [[PAIR:%.*]] = alloca { i32, i32 }, align 8 +; IS__TUNIT_OPM-NEXT: call void @add({ i32, i32 }* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[PAIR]], i32* nocapture nofree nonnull sret writeonly align 4 dereferenceable(4) [[R]]) +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@f() +; IS__TUNIT_NPM-NEXT: [[R:%.*]] = alloca i32, align 4 +; IS__TUNIT_NPM-NEXT: [[PAIR:%.*]] = alloca { i32, i32 }, align 8 +; IS__TUNIT_NPM-NEXT: call void @add({ i32, i32 }* noalias nocapture nofree nonnull readonly align 8 dereferenceable(8) [[PAIR]], i32* noalias nocapture nofree nonnull sret writeonly align 4 dereferenceable(4) [[R]]) +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f() +; IS__CGSCC_OPM-NEXT: [[R:%.*]] = alloca i32, align 4 +; IS__CGSCC_OPM-NEXT: [[PAIR:%.*]] = alloca { i32, i32 }, align 8 +; IS__CGSCC_OPM-NEXT: call void @add({ i32, i32 }* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[PAIR]], i32* nocapture nofree nonnull sret writeonly align 4 dereferenceable(4) [[R]]) +; 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-NEXT: [[R:%.*]] = alloca i32, align 4 +; IS__CGSCC_NPM-NEXT: [[PAIR:%.*]] = alloca { i32, i32 }, align 8 +; IS__CGSCC_NPM-NEXT: call void @add({ i32, i32 }* noalias nocapture nofree nonnull readonly align 8 dereferenceable(8) [[PAIR]], i32* noalias nocapture nofree nonnull sret writeonly align 4 dereferenceable(4) [[R]]) +; IS__CGSCC_NPM-NEXT: ret void ; %r = alloca i32 %pair = alloca {i32, i32} diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/tail.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/tail.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/tail.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/tail.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/variadic.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/variadic.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/variadic.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/variadic.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/2008-06-09-WeakProp.ll b/llvm/test/Transforms/Attributor/IPConstantProp/2008-06-09-WeakProp.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/2008-06-09-WeakProp.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/2008-06-09-WeakProp.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -8,6 +8,7 @@ ; PR2411 define weak i32 @foo() nounwind { +; CHECK: Function Attrs: nounwind ; CHECK-LABEL: define {{[^@]+}}@foo() ; CHECK-NEXT: entry: ; CHECK-NEXT: ret i32 1 @@ -17,6 +18,7 @@ } define i32 @main() nounwind { +; CHECK: Function Attrs: nounwind ; CHECK-LABEL: define {{[^@]+}}@main() ; CHECK-NEXT: entry: ; CHECK-NEXT: [[R:%.*]] = call i32 @foo() diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll b/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/2009-09-24-byval-ptr.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -9,6 +9,7 @@ %struct.MYstr = type { i8, i32 } @mystr = internal global %struct.MYstr zeroinitializer ; <%struct.MYstr*> [#uses=3] define internal void @vfu1(%struct.MYstr* byval align 4 %u) nounwind { +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@vfu1 ; IS__CGSCC_OPM-SAME: (%struct.MYstr* noalias nocapture nofree nonnull writeonly byval align 8 dereferenceable(8) [[U:%.*]]) ; IS__CGSCC_OPM-NEXT: entry: @@ -20,6 +21,7 @@ ; IS__CGSCC_OPM: return: ; IS__CGSCC_OPM-NEXT: ret void ; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@vfu1 ; IS__CGSCC_NPM-SAME: (i8 [[TMP0:%.*]], i32 [[TMP1:%.*]]) ; IS__CGSCC_NPM-NEXT: entry: @@ -48,6 +50,7 @@ } define internal i32 @vfu2(%struct.MYstr* byval align 4 %u) nounwind readonly { +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readonly willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@vfu2 ; IS__TUNIT_OPM-SAME: (%struct.MYstr* noalias nocapture nofree nonnull readonly byval align 8 dereferenceable(8) [[U:%.*]]) ; IS__TUNIT_OPM-NEXT: entry: @@ -59,6 +62,7 @@ ; IS__TUNIT_OPM-NEXT: [[TMP5:%.*]] = add i32 [[TMP4]], [[TMP1]] ; IS__TUNIT_OPM-NEXT: ret i32 [[TMP5]] ; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readonly willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@vfu2 ; IS__TUNIT_NPM-SAME: (i8 [[TMP0:%.*]], i32 [[TMP1:%.*]]) ; IS__TUNIT_NPM-NEXT: entry: @@ -75,6 +79,7 @@ ; IS__TUNIT_NPM-NEXT: [[TMP7:%.*]] = add i32 [[TMP6]], [[TMP3]] ; IS__TUNIT_NPM-NEXT: ret i32 [[TMP7]] ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@vfu2() ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* @mystr, i32 0, i32 1 @@ -96,11 +101,13 @@ } define i32 @unions() nounwind { +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@unions() ; IS__TUNIT_OPM-NEXT: entry: ; IS__TUNIT_OPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2(%struct.MYstr* nocapture nofree nonnull readonly byval align 8 dereferenceable(8) @mystr) ; IS__TUNIT_OPM-NEXT: ret i32 [[RESULT]] ; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@unions() ; IS__TUNIT_NPM-NEXT: entry: ; IS__TUNIT_NPM-NEXT: [[MYSTR_CAST:%.*]] = bitcast %struct.MYstr* @mystr to i8* @@ -110,6 +117,7 @@ ; IS__TUNIT_NPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2(i8 [[TMP0]], i32 [[TMP1]]) ; IS__TUNIT_NPM-NEXT: ret i32 [[RESULT]] ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@unions() ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[RESULT:%.*]] = call i32 @vfu2() @@ -122,36 +130,71 @@ } define internal i32 @vfu2_v2(%struct.MYstr* byval align 4 %u) nounwind readonly { -; IS________OPM-LABEL: define {{[^@]+}}@vfu2_v2 -; IS________OPM-SAME: (%struct.MYstr* noalias nocapture nofree nonnull byval align 8 dereferenceable(8) [[U:%.*]]) -; IS________OPM-NEXT: entry: -; IS________OPM-NEXT: [[Z:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* [[U]], i32 0, i32 1 -; IS________OPM-NEXT: store i32 99, i32* [[Z]], align 4 -; IS________OPM-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U]], i32 0, i32 1 -; IS________OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 -; IS________OPM-NEXT: [[TMP2:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U]], i32 0, i32 0 -; IS________OPM-NEXT: [[TMP3:%.*]] = load i8, i8* [[TMP2]], align 8 -; IS________OPM-NEXT: [[TMP4:%.*]] = zext i8 [[TMP3]] to i32 -; IS________OPM-NEXT: [[TMP5:%.*]] = add i32 [[TMP4]], [[TMP1]] -; IS________OPM-NEXT: ret i32 [[TMP5]] -; -; IS________NPM-LABEL: define {{[^@]+}}@vfu2_v2 -; IS________NPM-SAME: (i8 [[TMP0:%.*]], i32 [[TMP1:%.*]]) -; IS________NPM-NEXT: entry: -; IS________NPM-NEXT: [[U_PRIV:%.*]] = alloca [[STRUCT_MYSTR:%.*]], align 8 -; IS________NPM-NEXT: [[U_PRIV_CAST:%.*]] = bitcast %struct.MYstr* [[U_PRIV]] to i8* -; IS________NPM-NEXT: store i8 [[TMP0]], i8* [[U_PRIV_CAST]], align 1 -; IS________NPM-NEXT: [[U_PRIV_0_1:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 1 -; IS________NPM-NEXT: store i32 [[TMP1]], i32* [[U_PRIV_0_1]], align 4 -; IS________NPM-NEXT: [[Z:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 1 -; IS________NPM-NEXT: store i32 99, i32* [[Z]], align 4 -; IS________NPM-NEXT: [[TMP2:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 1 -; IS________NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 -; IS________NPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 0 -; IS________NPM-NEXT: [[TMP5:%.*]] = load i8, i8* [[TMP4]], align 8 -; IS________NPM-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 -; IS________NPM-NEXT: [[TMP7:%.*]] = add i32 [[TMP6]], [[TMP3]] -; IS________NPM-NEXT: ret i32 [[TMP7]] +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@vfu2_v2 +; IS__TUNIT_OPM-SAME: (%struct.MYstr* noalias nocapture nofree nonnull byval align 8 dereferenceable(8) [[U:%.*]]) +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[Z:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* [[U]], i32 0, i32 1 +; IS__TUNIT_OPM-NEXT: store i32 99, i32* [[Z]], align 4 +; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U]], i32 0, i32 1 +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U]], i32 0, i32 0 +; IS__TUNIT_OPM-NEXT: [[TMP3:%.*]] = load i8, i8* [[TMP2]], align 8 +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = zext i8 [[TMP3]] to i32 +; IS__TUNIT_OPM-NEXT: [[TMP5:%.*]] = add i32 [[TMP4]], [[TMP1]] +; IS__TUNIT_OPM-NEXT: ret i32 [[TMP5]] +; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@vfu2_v2 +; IS__TUNIT_NPM-SAME: (i8 [[TMP0:%.*]], i32 [[TMP1:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[U_PRIV:%.*]] = alloca [[STRUCT_MYSTR:%.*]], align 8 +; IS__TUNIT_NPM-NEXT: [[U_PRIV_CAST:%.*]] = bitcast %struct.MYstr* [[U_PRIV]] to i8* +; IS__TUNIT_NPM-NEXT: store i8 [[TMP0]], i8* [[U_PRIV_CAST]], align 1 +; IS__TUNIT_NPM-NEXT: [[U_PRIV_0_1:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP1]], i32* [[U_PRIV_0_1]], align 4 +; IS__TUNIT_NPM-NEXT: [[Z:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: store i32 99, i32* [[Z]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 0 +; IS__TUNIT_NPM-NEXT: [[TMP5:%.*]] = load i8, i8* [[TMP4]], align 8 +; IS__TUNIT_NPM-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 +; IS__TUNIT_NPM-NEXT: [[TMP7:%.*]] = add i32 [[TMP6]], [[TMP3]] +; IS__TUNIT_NPM-NEXT: ret i32 [[TMP7]] +; +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@vfu2_v2 +; IS__CGSCC_OPM-SAME: (%struct.MYstr* noalias nocapture nofree nonnull byval align 8 dereferenceable(8) [[U:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[Z:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* [[U]], i32 0, i32 1 +; IS__CGSCC_OPM-NEXT: store i32 99, i32* [[Z]], align 4 +; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U]], i32 0, i32 1 +; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U]], i32 0, i32 0 +; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = load i8, i8* [[TMP2]], align 8 +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = zext i8 [[TMP3]] to i32 +; IS__CGSCC_OPM-NEXT: [[TMP5:%.*]] = add i32 [[TMP4]], [[TMP1]] +; IS__CGSCC_OPM-NEXT: ret i32 [[TMP5]] +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@vfu2_v2 +; IS__CGSCC_NPM-SAME: (i8 [[TMP0:%.*]], i32 [[TMP1:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[U_PRIV:%.*]] = alloca [[STRUCT_MYSTR:%.*]], align 8 +; IS__CGSCC_NPM-NEXT: [[U_PRIV_CAST:%.*]] = bitcast %struct.MYstr* [[U_PRIV]] to i8* +; IS__CGSCC_NPM-NEXT: store i8 [[TMP0]], i8* [[U_PRIV_CAST]], align 1 +; IS__CGSCC_NPM-NEXT: [[U_PRIV_0_1:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 1 +; IS__CGSCC_NPM-NEXT: store i32 [[TMP1]], i32* [[U_PRIV_0_1]], align 4 +; IS__CGSCC_NPM-NEXT: [[Z:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 1 +; IS__CGSCC_NPM-NEXT: store i32 99, i32* [[Z]], align 4 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 1 +; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 0 +; IS__CGSCC_NPM-NEXT: [[TMP5:%.*]] = load i8, i8* [[TMP4]], align 8 +; IS__CGSCC_NPM-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 +; IS__CGSCC_NPM-NEXT: [[TMP7:%.*]] = add i32 [[TMP6]], [[TMP3]] +; IS__CGSCC_NPM-NEXT: ret i32 [[TMP7]] ; entry: %z = getelementptr %struct.MYstr, %struct.MYstr* %u, i32 0, i32 1 @@ -166,11 +209,13 @@ } define i32 @unions_v2() nounwind { +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@unions_v2() ; IS__TUNIT_OPM-NEXT: entry: ; IS__TUNIT_OPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2_v2(%struct.MYstr* nocapture nofree nonnull readonly byval align 8 dereferenceable(8) @mystr) ; IS__TUNIT_OPM-NEXT: ret i32 [[RESULT]] ; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@unions_v2() ; IS__TUNIT_NPM-NEXT: entry: ; IS__TUNIT_NPM-NEXT: [[MYSTR_CAST:%.*]] = bitcast %struct.MYstr* @mystr to i8* @@ -180,11 +225,13 @@ ; IS__TUNIT_NPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2_v2(i8 [[TMP0]], i32 [[TMP1]]) ; IS__TUNIT_NPM-NEXT: ret i32 [[RESULT]] ; +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@unions_v2() ; IS__CGSCC_OPM-NEXT: entry: ; IS__CGSCC_OPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2_v2(%struct.MYstr* noalias nocapture nofree nonnull readnone byval align 8 dereferenceable(8) @mystr) ; IS__CGSCC_OPM-NEXT: ret i32 [[RESULT]] ; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@unions_v2() ; IS__CGSCC_NPM-NEXT: entry: ; IS__CGSCC_NPM-NEXT: [[MYSTR_CAST1:%.*]] = bitcast %struct.MYstr* @mystr to i8* diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll b/llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/PR16052.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -8,11 +8,13 @@ target triple = "x86_64-unknown-linux-gnu" define i64 @fn2() { +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@fn2() ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 undef) #0, !range !0 ; IS__TUNIT____-NEXT: ret i64 [[CALL2]] ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@fn2() ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 undef) @@ -26,6 +28,7 @@ } define i64 @fn2b(i32 %arg) { +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@fn2b ; IS__TUNIT____-SAME: (i32 [[ARG:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -34,6 +37,7 @@ ; IS__TUNIT____-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 [[DIV]]) #0, !range !0 ; IS__TUNIT____-NEXT: ret i64 [[CALL2]] ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@fn2b ; IS__CGSCC____-SAME: (i32 [[ARG:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -50,11 +54,13 @@ } define i64 @fn2c() { +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@fn2c() ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 42) #0, !range !0 ; IS__TUNIT____-NEXT: ret i64 [[CALL2]] ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@fn2c() ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: ret i64 42 @@ -67,12 +73,21 @@ } define internal i64 @fn1(i64 %p1) { -; CHECK-LABEL: define {{[^@]+}}@fn1 -; CHECK-SAME: (i64 returned [[P1:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i64 [[P1]], 0 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 [[P1]], i64 [[P1]] -; CHECK-NEXT: ret i64 [[COND]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@fn1 +; IS__TUNIT____-SAME: (i64 returned [[P1:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[TOBOOL:%.*]] = icmp ne i64 [[P1]], 0 +; IS__TUNIT____-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 [[P1]], i64 [[P1]] +; IS__TUNIT____-NEXT: ret i64 [[COND]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@fn1 +; IS__CGSCC____-SAME: (i64 returned [[P1:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[TOBOOL:%.*]] = icmp ne i64 [[P1]], 0 +; IS__CGSCC____-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i64 [[P1]], i64 [[P1]] +; IS__CGSCC____-NEXT: ret i64 [[COND]] ; entry: %tobool = icmp ne i64 %p1, 0 diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/PR26044.ll b/llvm/test/Transforms/Attributor/IPConstantProp/PR26044.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/PR26044.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/PR26044.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -8,6 +8,7 @@ define void @fn2(i32* %P, i1 %C) { ; +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind ; IS__TUNIT____-LABEL: define {{[^@]+}}@fn2 ; IS__TUNIT____-SAME: (i32* nocapture nofree [[P:%.*]], i1 [[C:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -23,6 +24,7 @@ ; IS__TUNIT____: exit: ; IS__TUNIT____-NEXT: ret void ; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@fn2 ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull align 4 dereferenceable(4) [[P:%.*]], i1 [[C:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -55,12 +57,21 @@ } define internal i32 @fn1(i32 %p1) { -; CHECK-LABEL: define {{[^@]+}}@fn1 -; CHECK-SAME: (i32 returned [[P1:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[P1]], 0 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[P1]], i32 [[P1]] -; CHECK-NEXT: ret i32 [[COND]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@fn1 +; IS__TUNIT____-SAME: (i32 returned [[P1:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[P1]], 0 +; IS__TUNIT____-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[P1]], i32 [[P1]] +; IS__TUNIT____-NEXT: ret i32 [[COND]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@fn1 +; IS__CGSCC____-SAME: (i32 returned [[P1:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[P1]], 0 +; IS__CGSCC____-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[P1]], i32 [[P1]] +; IS__CGSCC____-NEXT: ret i32 [[COND]] ; entry: %tobool = icmp ne i32 %p1, 0 @@ -70,6 +81,7 @@ define void @fn_no_null_opt(i32* %P, i1 %C) null_pointer_is_valid { ; +; IS__TUNIT____: Function Attrs: nofree nosync nounwind null_pointer_is_valid ; IS__TUNIT____-LABEL: define {{[^@]+}}@fn_no_null_opt ; IS__TUNIT____-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i1 [[C:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -85,6 +97,7 @@ ; IS__TUNIT____: exit: ; IS__TUNIT____-NEXT: ret void ; +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@fn_no_null_opt ; IS__CGSCC_OPM-SAME: (i32* nocapture nofree writeonly align 4 dereferenceable_or_null(4) [[P:%.*]], i1 [[C:%.*]]) ; IS__CGSCC_OPM-NEXT: entry: @@ -100,6 +113,7 @@ ; IS__CGSCC_OPM: exit: ; IS__CGSCC_OPM-NEXT: ret void ; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@fn_no_null_opt ; IS__CGSCC_NPM-SAME: (i32* nocapture nofree writeonly align 4 dereferenceable_or_null(4) [[P:%.*]], i1 [[C:%.*]]) ; IS__CGSCC_NPM-NEXT: entry: @@ -132,12 +146,21 @@ } define internal i32 @fn0(i32 %p1) { -; CHECK-LABEL: define {{[^@]+}}@fn0 -; CHECK-SAME: (i32 returned [[P1:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[P1]], 0 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[P1]], i32 [[P1]] -; CHECK-NEXT: ret i32 [[COND]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@fn0 +; IS__TUNIT____-SAME: (i32 returned [[P1:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[P1]], 0 +; IS__TUNIT____-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[P1]], i32 [[P1]] +; IS__TUNIT____-NEXT: ret i32 [[COND]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@fn0 +; IS__CGSCC____-SAME: (i32 returned [[P1:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[P1]], 0 +; IS__CGSCC____-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 [[P1]], i32 [[P1]] +; IS__CGSCC____-NEXT: ret i32 [[COND]] ; entry: %tobool = icmp ne i32 %p1, 0 diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/PR43857.ll b/llvm/test/Transforms/Attributor/IPConstantProp/PR43857.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/PR43857.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/PR43857.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -10,21 +10,30 @@ declare dso_local fastcc float @bar(%struct.wobble* noalias, <8 x i32>) unnamed_addr define %struct.zot @widget(<8 x i32> %arg) local_unnamed_addr { -; CHECK-LABEL: define {{[^@]+}}@widget -; CHECK-SAME: (<8 x i32> [[ARG:%.*]]) local_unnamed_addr -; CHECK-NEXT: bb: -; CHECK-NEXT: ret [[STRUCT_ZOT:%.*]] undef +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@widget +; IS__TUNIT____-SAME: (<8 x i32> [[ARG:%.*]]) local_unnamed_addr +; IS__TUNIT____-NEXT: bb: +; IS__TUNIT____-NEXT: ret [[STRUCT_ZOT:%.*]] undef +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@widget +; IS__CGSCC____-SAME: (<8 x i32> [[ARG:%.*]]) local_unnamed_addr +; IS__CGSCC____-NEXT: bb: +; IS__CGSCC____-NEXT: ret [[STRUCT_ZOT:%.*]] undef ; bb: ret %struct.zot undef } define void @baz(<8 x i32> %arg) local_unnamed_addr { +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@baz ; IS__TUNIT____-SAME: (<8 x i32> [[ARG:%.*]]) local_unnamed_addr ; IS__TUNIT____-NEXT: bb: ; IS__TUNIT____-NEXT: ret void ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@baz ; IS__CGSCC____-SAME: (<8 x i32> [[ARG:%.*]]) local_unnamed_addr ; IS__CGSCC____-NEXT: bb: diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll b/llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -36,18 +36,29 @@ ; FIXME we should recognize this as UB and make it an unreachable. define dso_local i16 @foo(i16 %a) { -; CHECK-LABEL: define {{[^@]+}}@foo -; CHECK-SAME: (i16 [[A:%.*]]) -; CHECK-NEXT: [[CALL:%.*]] = call i16 @bar() -; CHECK-NEXT: ret i16 [[CALL]] +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@foo +; NOT_CGSCC_NPM-SAME: (i16 [[A:%.*]]) +; NOT_CGSCC_NPM-NEXT: [[CALL:%.*]] = call i16 @bar() +; NOT_CGSCC_NPM-NEXT: ret i16 [[CALL]] +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@foo +; IS__CGSCC_NPM-SAME: (i16 [[A:%.*]]) +; IS__CGSCC_NPM-NEXT: [[CALL:%.*]] = call i16 @bar() +; IS__CGSCC_NPM-NEXT: ret i16 [[CALL]] ; %call = call i16 bitcast (i16 (i16, i16) * @bar to i16 (i16) *)(i16 %a) ret i16 %call } define internal i16 @bar(i16 %p1, i16 %p2) { -; CHECK-LABEL: define {{[^@]+}}@bar() -; CHECK-NEXT: ret i16 0 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@bar() +; IS__TUNIT____-NEXT: ret i16 0 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@bar() +; IS__CGSCC____-NEXT: ret i16 0 ; ret i16 0 } @@ -63,10 +74,17 @@ } define internal i16 @bar2(i16 %p1, i16 %p2) { -; CHECK-LABEL: define {{[^@]+}}@bar2 -; CHECK-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]]) -; CHECK-NEXT: [[A:%.*]] = add i16 [[P1]], [[P2]] -; CHECK-NEXT: ret i16 [[A]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@bar2 +; IS__TUNIT____-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]]) +; IS__TUNIT____-NEXT: [[A:%.*]] = add i16 [[P1]], [[P2]] +; IS__TUNIT____-NEXT: ret i16 [[A]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@bar2 +; IS__CGSCC____-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]]) +; IS__CGSCC____-NEXT: [[A:%.*]] = add i16 [[P1]], [[P2]] +; IS__CGSCC____-NEXT: ret i16 [[A]] ; %a = add i16 %p1, %p2 ret i16 %a @@ -99,6 +117,7 @@ } define internal i16 @vararg_prop(i16 %p1, ...) { +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@vararg_prop ; IS__CGSCC____-SAME: (i16 returned [[P1:%.*]], ...) ; IS__CGSCC____-NEXT: ret i16 7 @@ -107,9 +126,15 @@ } define internal i16 @vararg_no_prop(i16 %p1, i16 %p2, ...) { -; CHECK-LABEL: define {{[^@]+}}@vararg_no_prop -; CHECK-SAME: (i16 returned [[P1:%.*]], i16 [[P2:%.*]], ...) -; CHECK-NEXT: ret i16 7 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@vararg_no_prop +; IS__TUNIT____-SAME: (i16 returned [[P1:%.*]], i16 [[P2:%.*]], ...) +; IS__TUNIT____-NEXT: ret i16 7 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@vararg_no_prop +; IS__CGSCC____-SAME: (i16 returned [[P1:%.*]], i16 [[P2:%.*]], ...) +; IS__CGSCC____-NEXT: ret i16 7 ; ret i16 %p1 } diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/arg-type-mismatch.ll b/llvm/test/Transforms/Attributor/IPConstantProp/arg-type-mismatch.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/arg-type-mismatch.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/arg-type-mismatch.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -18,9 +18,15 @@ } define internal i16 @bar(i16 %p1, i16 %p2) { -; CHECK-LABEL: define {{[^@]+}}@bar -; CHECK-SAME: (i16 [[P1:%.*]], i16 returned [[P2:%.*]]) -; CHECK-NEXT: ret i16 [[P2]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@bar +; IS__TUNIT____-SAME: (i16 [[P1:%.*]], i16 returned [[P2:%.*]]) +; IS__TUNIT____-NEXT: ret i16 [[P2]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@bar +; IS__CGSCC____-SAME: (i16 [[P1:%.*]], i16 returned [[P2:%.*]]) +; IS__CGSCC____-NEXT: ret i16 [[P2]] ; ret i16 %p2 } diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/comdat-ipo.ll b/llvm/test/Transforms/Attributor/IPConstantProp/comdat-ipo.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/comdat-ipo.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/comdat-ipo.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -7,8 +7,13 @@ ; See PR26774 define i32 @baz() { -; CHECK-LABEL: define {{[^@]+}}@baz() -; CHECK-NEXT: ret i32 10 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@baz() +; IS__TUNIT____-NEXT: ret i32 10 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@baz() +; IS__CGSCC____-NEXT: ret i32 10 ; ret i32 10 } diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/dangling-block-address.ll b/llvm/test/Transforms/Attributor/IPConstantProp/dangling-block-address.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/dangling-block-address.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/dangling-block-address.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -15,6 +15,7 @@ @bar.l = internal constant [2 x i8*] [i8* blockaddress(@bar, %lab0), i8* blockaddress(@bar, %end)] ; <[2 x i8*]*> [#uses=1] define internal void @foo(i32 %x) nounwind readnone { +; IS__CGSCC____: Function Attrs: nounwind readnone ; IS__CGSCC____-LABEL: define {{[^@]+}}@foo ; IS__CGSCC____-SAME: (i32 [[X:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -29,6 +30,7 @@ } define internal void @bar(i32* nocapture %pc) nounwind readonly { +; IS__CGSCC_OPM: Function Attrs: nounwind readonly ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@bar ; IS__CGSCC_OPM-SAME: (i32* nocapture [[PC:%.*]]) ; IS__CGSCC_OPM-NEXT: entry: @@ -66,9 +68,15 @@ } define i32 @main() nounwind readnone { -; CHECK-LABEL: define {{[^@]+}}@main() -; CHECK-NEXT: entry: -; CHECK-NEXT: ret i32 0 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@main() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret i32 0 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@main() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i32 0 ; entry: ret i32 0 diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/deadarg.ll b/llvm/test/Transforms/Attributor/IPConstantProp/deadarg.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/deadarg.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/deadarg.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/fp-bc-icmp-const-fold.ll b/llvm/test/Transforms/Attributor/IPConstantProp/fp-bc-icmp-const-fold.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/fp-bc-icmp-const-fold.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/fp-bc-icmp-const-fold.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -7,32 +7,61 @@ target triple = "powerpc64-bgq-linux" define void @test(i32 signext %n) { -; CHECK-LABEL: define {{[^@]+}}@test -; CHECK-SAME: (i32 signext [[N:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: unreachable -; CHECK: if.then: -; CHECK-NEXT: unreachable -; CHECK: if.end: -; CHECK-NEXT: unreachable -; CHECK: if.then2: -; CHECK-NEXT: unreachable -; CHECK: if.end4: -; CHECK-NEXT: unreachable -; CHECK: if.then9: -; CHECK-NEXT: unreachable -; CHECK: if.then12: -; CHECK-NEXT: unreachable -; CHECK: if.else14: -; CHECK-NEXT: unreachable -; CHECK: do.body: -; CHECK-NEXT: unreachable -; CHECK: if.then33: -; CHECK-NEXT: unreachable -; CHECK: cond.false.i28: -; CHECK-NEXT: unreachable -; CHECK: _ZN5boost4math4signIgEEiRKT_.exit30: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree noreturn nosync nounwind readnone +; IS__TUNIT____-LABEL: define {{[^@]+}}@test +; IS__TUNIT____-SAME: (i32 signext [[N:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: if.then: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: if.end: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: if.then2: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: if.end4: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: if.then9: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: if.then12: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: if.else14: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: do.body: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: if.then33: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: cond.false.i28: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: _ZN5boost4math4signIgEEiRKT_.exit30: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone +; IS__CGSCC____-LABEL: define {{[^@]+}}@test +; IS__CGSCC____-SAME: (i32 signext [[N:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: if.then: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: if.end: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: if.then2: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: if.end4: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: if.then9: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: if.then12: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: if.else14: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: do.body: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: if.then33: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: cond.false.i28: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: _ZN5boost4math4signIgEEiRKT_.exit30: +; IS__CGSCC____-NEXT: unreachable ; entry: diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/global.ll b/llvm/test/Transforms/Attributor/IPConstantProp/global.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/global.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/global.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -7,16 +7,29 @@ @_ZL6test1g = internal global i32 42, align 4 define void @_Z7test1f1v() nounwind { -; CHECK-LABEL: define {{[^@]+}}@_Z7test1f1v() -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP:%.*]] = load i32, i32* @_ZL6test1g, align 4 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP]], 0 -; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] -; CHECK: if.then: -; CHECK-NEXT: store i32 0, i32* @_ZL6test1g, align 4 -; CHECK-NEXT: br label [[IF_END]] -; CHECK: if.end: -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@_Z7test1f1v() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[TMP:%.*]] = load i32, i32* @_ZL6test1g, align 4 +; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP]], 0 +; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] +; IS__TUNIT____: if.then: +; IS__TUNIT____-NEXT: store i32 0, i32* @_ZL6test1g, align 4 +; IS__TUNIT____-NEXT: br label [[IF_END]] +; IS__TUNIT____: if.end: +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@_Z7test1f1v() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[TMP:%.*]] = load i32, i32* @_ZL6test1g, align 4 +; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP]], 0 +; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] +; IS__CGSCC____: if.then: +; IS__CGSCC____-NEXT: store i32 0, i32* @_ZL6test1g, align 4 +; IS__CGSCC____-NEXT: br label [[IF_END]] +; IS__CGSCC____: if.end: +; IS__CGSCC____-NEXT: ret void ; entry: %tmp = load i32, i32* @_ZL6test1g, align 4 @@ -32,10 +45,17 @@ } define i32 @_Z7test1f2v() nounwind { -; CHECK-LABEL: define {{[^@]+}}@_Z7test1f2v() -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP:%.*]] = load i32, i32* @_ZL6test1g, align 4 -; CHECK-NEXT: ret i32 [[TMP]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@_Z7test1f2v() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[TMP:%.*]] = load i32, i32* @_ZL6test1g, align 4 +; IS__TUNIT____-NEXT: ret i32 [[TMP]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@_Z7test1f2v() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[TMP:%.*]] = load i32, i32* @_ZL6test1g, align 4 +; IS__CGSCC____-NEXT: ret i32 [[TMP]] ; entry: %tmp = load i32, i32* @_ZL6test1g, align 4 diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/multiple_callbacks.ll b/llvm/test/Transforms/Attributor/IPConstantProp/multiple_callbacks.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/multiple_callbacks.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/multiple_callbacks.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -40,30 +40,51 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" define internal i32 @cb0(i32 %zero) { -; CHECK-LABEL: define {{[^@]+}}@cb0 -; CHECK-SAME: (i32 returned [[ZERO:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: ret i32 0 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@cb0 +; IS__TUNIT____-SAME: (i32 returned [[ZERO:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret i32 0 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@cb0 +; IS__CGSCC____-SAME: (i32 returned [[ZERO:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i32 0 ; entry: ret i32 %zero } define internal i32 @cb1(i32 %unknown) { -; CHECK-LABEL: define {{[^@]+}}@cb1 -; CHECK-SAME: (i32 returned [[UNKNOWN:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: ret i32 [[UNKNOWN]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@cb1 +; IS__TUNIT____-SAME: (i32 returned [[UNKNOWN:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret i32 [[UNKNOWN]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@cb1 +; IS__CGSCC____-SAME: (i32 returned [[UNKNOWN:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i32 [[UNKNOWN]] ; entry: ret i32 %unknown } define internal i32 @cb2(i32 %unknown) { -; CHECK-LABEL: define {{[^@]+}}@cb2 -; CHECK-SAME: (i32 returned [[UNKNOWN:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: ret i32 [[UNKNOWN]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@cb2 +; IS__TUNIT____-SAME: (i32 returned [[UNKNOWN:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret i32 [[UNKNOWN]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@cb2 +; IS__CGSCC____-SAME: (i32 returned [[UNKNOWN:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i32 [[UNKNOWN]] ; entry: %call = call i32 @cb0(i32 0) @@ -71,20 +92,34 @@ } define internal i32 @cb3(i32 %unknown) { -; CHECK-LABEL: define {{[^@]+}}@cb3 -; CHECK-SAME: (i32 returned [[UNKNOWN:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: ret i32 [[UNKNOWN]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@cb3 +; IS__TUNIT____-SAME: (i32 returned [[UNKNOWN:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret i32 [[UNKNOWN]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@cb3 +; IS__CGSCC____-SAME: (i32 returned [[UNKNOWN:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i32 [[UNKNOWN]] ; entry: ret i32 %unknown } define internal i32 @cb4(i32 %unknown) { -; CHECK-LABEL: define {{[^@]+}}@cb4 -; CHECK-SAME: (i32 returned [[UNKNOWN:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: ret i32 [[UNKNOWN]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@cb4 +; IS__TUNIT____-SAME: (i32 returned [[UNKNOWN:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret i32 [[UNKNOWN]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@cb4 +; IS__CGSCC____-SAME: (i32 returned [[UNKNOWN:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i32 [[UNKNOWN]] ; entry: ret i32 %unknown diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/musttail-call.ll b/llvm/test/Transforms/Attributor/IPConstantProp/musttail-call.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/musttail-call.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/musttail-call.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -86,6 +86,7 @@ } define internal i8* @no_side_effects(i8 %v) readonly nounwind { +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@no_side_effects ; IS__CGSCC____-SAME: (i8 [[V:%.*]]) ; IS__CGSCC____-NEXT: ret i8* null diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/naked-return.ll b/llvm/test/Transforms/Attributor/IPConstantProp/naked-return.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/naked-return.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/naked-return.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -8,6 +8,7 @@ target triple = "i686-pc-windows-msvc19.0.24215" define i32 @dipsy(i32, i32) local_unnamed_addr #0 { +; CHECK: Function Attrs: naked ; CHECK-LABEL: define {{[^@]+}}@dipsy ; CHECK-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) local_unnamed_addr ; CHECK-NEXT: BasicBlock0: @@ -20,6 +21,7 @@ } define void @tinkywinky(i32, i32, i32) local_unnamed_addr #0 { +; CHECK: Function Attrs: naked ; CHECK-LABEL: define {{[^@]+}}@tinkywinky ; CHECK-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]], i32 [[TMP2:%.*]]) local_unnamed_addr ; CHECK-NEXT: BasicBlock1: diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/openmp_parallel_for.ll b/llvm/test/Transforms/Attributor/IPConstantProp/openmp_parallel_for.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/openmp_parallel_for.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/openmp_parallel_for.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/pthreads.ll b/llvm/test/Transforms/Attributor/IPConstantProp/pthreads.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/pthreads.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/pthreads.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -67,21 +67,30 @@ declare !callback !0 dso_local i32 @pthread_create(i64*, %union.pthread_attr_t*, i8* (i8*)*, i8*) define internal i8* @foo(i8* %arg) { -; CHECK-LABEL: define {{[^@]+}}@foo -; CHECK-SAME: (i8* noalias nofree readnone returned align 536870912 "no-capture-maybe-returned" [[ARG:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: ret i8* null +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@foo +; IS__TUNIT____-SAME: (i8* noalias nofree readnone returned align 536870912 "no-capture-maybe-returned" [[ARG:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret i8* null +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@foo +; IS__CGSCC____-SAME: (i8* noalias nofree readnone returned align 536870912 "no-capture-maybe-returned" [[ARG:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i8* null ; entry: ret i8* %arg } define internal i8* @bar(i8* %arg) { +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@bar ; IS__TUNIT____-SAME: (i8* noalias nofree nonnull readnone returned align 8 dereferenceable(8) "no-capture-maybe-returned" [[ARG:%.*]]) ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: ret i8* bitcast (i8** @GlobalVPtr to i8*) ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@bar ; IS__CGSCC____-SAME: (i8* nofree readnone returned "no-capture-maybe-returned" [[ARG:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -92,11 +101,13 @@ } define internal i8* @baz(i8* %arg) { +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@baz ; IS__TUNIT____-SAME: (i8* noalias nofree nonnull readnone returned align 8 dereferenceable(1) "no-capture-maybe-returned" [[ARG:%.*]]) ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: ret i8* [[ARG]] ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@baz ; IS__CGSCC____-SAME: (i8* nofree nonnull readnone returned align 8 dereferenceable(1) "no-capture-maybe-returned" [[ARG:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -107,11 +118,13 @@ } define internal i8* @buz(i8* %arg) { +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@buz ; IS__TUNIT____-SAME: (i8* noalias nofree nonnull readnone returned align 8 dereferenceable(1) "no-capture-maybe-returned" [[ARG:%.*]]) ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: ret i8* [[ARG]] ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@buz ; IS__CGSCC____-SAME: (i8* nofree nonnull readnone returned align 8 dereferenceable(1) "no-capture-maybe-returned" [[ARG:%.*]]) ; IS__CGSCC____-NEXT: entry: diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/recursion.ll b/llvm/test/Transforms/Attributor/IPConstantProp/recursion.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/recursion.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/recursion.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -7,6 +7,7 @@ ; CHECK-NOT: %X define internal i32 @foo(i32 %X) { +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@foo() ; IS__CGSCC____-NEXT: unreachable ; @@ -16,8 +17,13 @@ } define void @bar() { -; CHECK-LABEL: define {{[^@]+}}@bar() -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree noreturn nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@bar() +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@bar() +; IS__CGSCC____-NEXT: unreachable ; call i32 @foo( i32 17 ) ; :1 [#uses=0] ret void diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/remove-call-inst.ll b/llvm/test/Transforms/Attributor/IPConstantProp/remove-call-inst.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/remove-call-inst.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/remove-call-inst.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -11,9 +11,15 @@ ; FIXME: Remove obsolete calls/instructions define i32 @main() noreturn nounwind { -; CHECK-LABEL: define {{[^@]+}}@main() -; CHECK-NEXT: entry: -; CHECK-NEXT: ret i32 123 +; IS__TUNIT____: Function Attrs: nofree noreturn nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@main() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret i32 123 +; +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@main() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i32 123 ; entry: %call2 = tail call i32 @wwrite(i64 0) nounwind @@ -21,6 +27,7 @@ } define internal i32 @wwrite(i64 %i) nounwind readnone { +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@wwrite() ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: switch i64 0, label [[SW_DEFAULT:%.*]] [ diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll b/llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/return-argument.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -6,6 +6,7 @@ ;; This function returns its second argument on all return statements define internal i32* @incdec(i1 %C, i32* %V) { +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@incdec ; IS__TUNIT____-SAME: (i1 [[C:%.*]], i32* noalias nofree nonnull returned align 4 dereferenceable(4) "no-capture-maybe-returned" [[V:%.*]]) ; IS__TUNIT____-NEXT: [[X:%.*]] = load i32, i32* [[V]], align 4 @@ -19,6 +20,7 @@ ; IS__TUNIT____-NEXT: store i32 [[X2]], i32* [[V]], align 4 ; IS__TUNIT____-NEXT: ret i32* [[V]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@incdec ; IS__CGSCC____-SAME: (i1 [[C:%.*]], i32* nofree nonnull returned align 4 dereferenceable(4) "no-capture-maybe-returned" [[V:%.*]]) ; IS__CGSCC____-NEXT: [[X:%.*]] = load i32, i32* [[V]], align 4 @@ -49,12 +51,21 @@ ;; This function returns its first argument as a part of a multiple return ;; value define internal { i32, i32 } @foo(i32 %A, i32 %B) { -; CHECK-LABEL: define {{[^@]+}}@foo -; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) -; CHECK-NEXT: [[X:%.*]] = add i32 [[A]], [[B]] -; CHECK-NEXT: [[Y:%.*]] = insertvalue { i32, i32 } undef, i32 [[A]], 0 -; CHECK-NEXT: [[Z:%.*]] = insertvalue { i32, i32 } [[Y]], i32 [[X]], 1 -; CHECK-NEXT: ret { i32, i32 } [[Z]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@foo +; IS__TUNIT____-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) +; IS__TUNIT____-NEXT: [[X:%.*]] = add i32 [[A]], [[B]] +; IS__TUNIT____-NEXT: [[Y:%.*]] = insertvalue { i32, i32 } undef, i32 [[A]], 0 +; IS__TUNIT____-NEXT: [[Z:%.*]] = insertvalue { i32, i32 } [[Y]], i32 [[X]], 1 +; IS__TUNIT____-NEXT: ret { i32, i32 } [[Z]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@foo +; IS__CGSCC____-SAME: (i32 [[A:%.*]], i32 [[B:%.*]]) +; IS__CGSCC____-NEXT: [[X:%.*]] = add i32 [[A]], [[B]] +; IS__CGSCC____-NEXT: [[Y:%.*]] = insertvalue { i32, i32 } undef, i32 [[A]], 0 +; IS__CGSCC____-NEXT: [[Z:%.*]] = insertvalue { i32, i32 } [[Y]], i32 [[X]], 1 +; IS__CGSCC____-NEXT: ret { i32, i32 } [[Z]] ; %X = add i32 %A, %B %Y = insertvalue { i32, i32 } undef, i32 %A, 0 @@ -63,6 +74,7 @@ } define void @caller(i1 %C) personality i32 (...)* @__gxx_personality_v0 { +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@caller ; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #2 personality i32 (...)* @__gxx_personality_v0 ; IS__TUNIT____-NEXT: [[Q:%.*]] = alloca i32, align 4 @@ -81,6 +93,7 @@ ; IS__TUNIT____: RET: ; IS__TUNIT____-NEXT: ret void ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@caller ; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #1 personality i32 (...)* @__gxx_personality_v0 ; IS__CGSCC____-NEXT: [[Q:%.*]] = alloca i32, align 4 diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/return-constant.ll b/llvm/test/Transforms/Attributor/IPConstantProp/return-constant.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/return-constant.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/return-constant.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -7,14 +7,25 @@ ; FIXME: icmp folding is missing define i1 @invokecaller(i1 %C) personality i32 (...)* @__gxx_personality_v0 { -; CHECK-LABEL: define {{[^@]+}}@invokecaller -; CHECK-SAME: (i1 [[C:%.*]]) #0 personality i32 (...)* @__gxx_personality_v0 -; CHECK-NEXT: [[X:%.*]] = call i32 @foo(i1 [[C]]) -; CHECK-NEXT: br label [[OK:%.*]] -; CHECK: OK: -; CHECK-NEXT: ret i1 true -; CHECK: FAIL: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@invokecaller +; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #0 personality i32 (...)* @__gxx_personality_v0 +; IS__TUNIT____-NEXT: [[X:%.*]] = call i32 @foo(i1 [[C]]) +; IS__TUNIT____-NEXT: br label [[OK:%.*]] +; IS__TUNIT____: OK: +; IS__TUNIT____-NEXT: ret i1 true +; IS__TUNIT____: FAIL: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@invokecaller +; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #0 personality i32 (...)* @__gxx_personality_v0 +; IS__CGSCC____-NEXT: [[X:%.*]] = call i32 @foo(i1 [[C]]) +; IS__CGSCC____-NEXT: br label [[OK:%.*]] +; IS__CGSCC____: OK: +; IS__CGSCC____-NEXT: ret i1 true +; IS__CGSCC____: FAIL: +; IS__CGSCC____-NEXT: unreachable ; %X = invoke i32 @foo( i1 %C ) to label %OK unwind label %FAIL ; [#uses=1] OK: @@ -27,6 +38,7 @@ } define internal i32 @foo(i1 %C) { +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@foo ; IS__TUNIT____-SAME: (i1 [[C:%.*]]) ; IS__TUNIT____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] @@ -35,6 +47,7 @@ ; IS__TUNIT____: F: ; IS__TUNIT____-NEXT: ret i32 undef ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@foo ; IS__CGSCC____-SAME: (i1 [[C:%.*]]) ; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] @@ -53,9 +66,15 @@ } define i1 @caller(i1 %C) { -; CHECK-LABEL: define {{[^@]+}}@caller -; CHECK-SAME: (i1 [[C:%.*]]) -; CHECK-NEXT: ret i1 true +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@caller +; IS__TUNIT____-SAME: (i1 [[C:%.*]]) +; IS__TUNIT____-NEXT: ret i1 true +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@caller +; IS__CGSCC____-SAME: (i1 [[C:%.*]]) +; IS__CGSCC____-NEXT: ret i1 true ; %X = call i32 @foo( i1 %C ) ; [#uses=1] %Y = icmp ne i32 %X, 0 ; [#uses=1] diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/return-constants.ll b/llvm/test/Transforms/Attributor/IPConstantProp/return-constants.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/return-constants.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/return-constants.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=8 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=8 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -9,17 +9,31 @@ %0 = type { i32, i32 } define internal %0 @foo(i1 %Q) { -; CHECK-LABEL: define {{[^@]+}}@foo -; CHECK-SAME: (i1 [[Q:%.*]]) -; CHECK-NEXT: br i1 [[Q]], label [[T:%.*]], label [[F:%.*]] -; CHECK: T: -; CHECK-NEXT: [[MRV:%.*]] = insertvalue [[TMP0:%.*]] undef, i32 21, 0 -; CHECK-NEXT: [[MRV1:%.*]] = insertvalue [[TMP0]] %mrv, i32 22, 1 -; CHECK-NEXT: ret [[TMP0]] %mrv1 -; CHECK: F: -; CHECK-NEXT: [[MRV2:%.*]] = insertvalue [[TMP0]] undef, i32 21, 0 -; CHECK-NEXT: [[MRV3:%.*]] = insertvalue [[TMP0]] %mrv2, i32 23, 1 -; CHECK-NEXT: ret [[TMP0]] %mrv3 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@foo +; IS__TUNIT____-SAME: (i1 [[Q:%.*]]) +; IS__TUNIT____-NEXT: br i1 [[Q]], label [[T:%.*]], label [[F:%.*]] +; IS__TUNIT____: T: +; IS__TUNIT____-NEXT: [[MRV:%.*]] = insertvalue [[TMP0:%.*]] undef, i32 21, 0 +; IS__TUNIT____-NEXT: [[MRV1:%.*]] = insertvalue [[TMP0]] %mrv, i32 22, 1 +; IS__TUNIT____-NEXT: ret [[TMP0]] %mrv1 +; IS__TUNIT____: F: +; IS__TUNIT____-NEXT: [[MRV2:%.*]] = insertvalue [[TMP0]] undef, i32 21, 0 +; IS__TUNIT____-NEXT: [[MRV3:%.*]] = insertvalue [[TMP0]] %mrv2, i32 23, 1 +; IS__TUNIT____-NEXT: ret [[TMP0]] %mrv3 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@foo +; IS__CGSCC____-SAME: (i1 [[Q:%.*]]) +; IS__CGSCC____-NEXT: br i1 [[Q]], label [[T:%.*]], label [[F:%.*]] +; IS__CGSCC____: T: +; IS__CGSCC____-NEXT: [[MRV:%.*]] = insertvalue [[TMP0:%.*]] undef, i32 21, 0 +; IS__CGSCC____-NEXT: [[MRV1:%.*]] = insertvalue [[TMP0]] %mrv, i32 22, 1 +; IS__CGSCC____-NEXT: ret [[TMP0]] %mrv1 +; IS__CGSCC____: F: +; IS__CGSCC____-NEXT: [[MRV2:%.*]] = insertvalue [[TMP0]] undef, i32 21, 0 +; IS__CGSCC____-NEXT: [[MRV3:%.*]] = insertvalue [[TMP0]] %mrv2, i32 23, 1 +; IS__CGSCC____-NEXT: ret [[TMP0]] %mrv3 ; br i1 %Q, label %T, label %F @@ -35,16 +49,29 @@ } define internal %0 @bar(i1 %Q) { -; CHECK-LABEL: define {{[^@]+}}@bar -; CHECK-SAME: (i1 [[Q:%.*]]) -; CHECK-NEXT: [[A:%.*]] = insertvalue [[TMP0:%.*]] undef, i32 21, 0 -; CHECK-NEXT: br i1 [[Q]], label [[T:%.*]], label [[F:%.*]] -; CHECK: T: -; CHECK-NEXT: [[B:%.*]] = insertvalue [[TMP0]] %A, i32 22, 1 -; CHECK-NEXT: ret [[TMP0]] %B -; CHECK: F: -; CHECK-NEXT: [[C:%.*]] = insertvalue [[TMP0]] %A, i32 23, 1 -; CHECK-NEXT: ret [[TMP0]] %C +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@bar +; IS__TUNIT____-SAME: (i1 [[Q:%.*]]) +; IS__TUNIT____-NEXT: [[A:%.*]] = insertvalue [[TMP0:%.*]] undef, i32 21, 0 +; IS__TUNIT____-NEXT: br i1 [[Q]], label [[T:%.*]], label [[F:%.*]] +; IS__TUNIT____: T: +; IS__TUNIT____-NEXT: [[B:%.*]] = insertvalue [[TMP0]] %A, i32 22, 1 +; IS__TUNIT____-NEXT: ret [[TMP0]] %B +; IS__TUNIT____: F: +; IS__TUNIT____-NEXT: [[C:%.*]] = insertvalue [[TMP0]] %A, i32 23, 1 +; IS__TUNIT____-NEXT: ret [[TMP0]] %C +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@bar +; IS__CGSCC____-SAME: (i1 [[Q:%.*]]) +; IS__CGSCC____-NEXT: [[A:%.*]] = insertvalue [[TMP0:%.*]] undef, i32 21, 0 +; IS__CGSCC____-NEXT: br i1 [[Q]], label [[T:%.*]], label [[F:%.*]] +; IS__CGSCC____: T: +; IS__CGSCC____-NEXT: [[B:%.*]] = insertvalue [[TMP0]] %A, i32 22, 1 +; IS__CGSCC____-NEXT: ret [[TMP0]] %B +; IS__CGSCC____: F: +; IS__CGSCC____-NEXT: [[C:%.*]] = insertvalue [[TMP0]] %A, i32 23, 1 +; IS__CGSCC____-NEXT: ret [[TMP0]] %C ; %A = insertvalue %0 undef, i32 21, 0 br i1 %Q, label %T, label %F @@ -59,10 +86,17 @@ } define %0 @caller(i1 %Q) { -; CHECK-LABEL: define {{[^@]+}}@caller -; CHECK-SAME: (i1 [[Q:%.*]]) -; CHECK-NEXT: [[X:%.*]] = call [[TMP0:%.*]] @foo(i1 [[Q]]) -; CHECK-NEXT: ret [[TMP0]] %X +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@caller +; IS__TUNIT____-SAME: (i1 [[Q:%.*]]) +; IS__TUNIT____-NEXT: [[X:%.*]] = call [[TMP0:%.*]] @foo(i1 [[Q]]) +; IS__TUNIT____-NEXT: ret [[TMP0]] %X +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@caller +; IS__CGSCC____-SAME: (i1 [[Q:%.*]]) +; IS__CGSCC____-NEXT: [[X:%.*]] = call [[TMP0:%.*]] @foo(i1 [[Q]]) +; IS__CGSCC____-NEXT: ret [[TMP0]] %X ; %X = call %0 @foo(i1 %Q) %A = extractvalue %0 %X, 0 @@ -77,18 +111,33 @@ ; Similar to @caller but the result of both calls are actually used. define i32 @caller2(i1 %Q) { -; CHECK-LABEL: define {{[^@]+}}@caller2 -; CHECK-SAME: (i1 [[Q:%.*]]) -; CHECK-NEXT: [[X:%.*]] = call [[TMP0:%.*]] @foo(i1 [[Q]]) -; CHECK-NEXT: [[A:%.*]] = extractvalue [[TMP0]] %X, 0 -; CHECK-NEXT: [[B:%.*]] = extractvalue [[TMP0]] %X, 1 -; CHECK-NEXT: [[Y:%.*]] = call [[TMP0]] @bar(i1 [[Q]]) -; CHECK-NEXT: [[C:%.*]] = extractvalue [[TMP0]] %Y, 0 -; CHECK-NEXT: [[D:%.*]] = extractvalue [[TMP0]] %Y, 1 -; CHECK-NEXT: [[M:%.*]] = add i32 [[A]], [[C]] -; CHECK-NEXT: [[N:%.*]] = add i32 [[B]], [[D]] -; CHECK-NEXT: [[R:%.*]] = add i32 [[N]], [[M]] -; CHECK-NEXT: ret i32 [[R]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@caller2 +; IS__TUNIT____-SAME: (i1 [[Q:%.*]]) +; IS__TUNIT____-NEXT: [[X:%.*]] = call [[TMP0:%.*]] @foo(i1 [[Q]]) +; IS__TUNIT____-NEXT: [[A:%.*]] = extractvalue [[TMP0]] %X, 0 +; IS__TUNIT____-NEXT: [[B:%.*]] = extractvalue [[TMP0]] %X, 1 +; IS__TUNIT____-NEXT: [[Y:%.*]] = call [[TMP0]] @bar(i1 [[Q]]) +; IS__TUNIT____-NEXT: [[C:%.*]] = extractvalue [[TMP0]] %Y, 0 +; IS__TUNIT____-NEXT: [[D:%.*]] = extractvalue [[TMP0]] %Y, 1 +; IS__TUNIT____-NEXT: [[M:%.*]] = add i32 [[A]], [[C]] +; IS__TUNIT____-NEXT: [[N:%.*]] = add i32 [[B]], [[D]] +; IS__TUNIT____-NEXT: [[R:%.*]] = add i32 [[N]], [[M]] +; IS__TUNIT____-NEXT: ret i32 [[R]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@caller2 +; IS__CGSCC____-SAME: (i1 [[Q:%.*]]) +; IS__CGSCC____-NEXT: [[X:%.*]] = call [[TMP0:%.*]] @foo(i1 [[Q]]) +; IS__CGSCC____-NEXT: [[A:%.*]] = extractvalue [[TMP0]] %X, 0 +; IS__CGSCC____-NEXT: [[B:%.*]] = extractvalue [[TMP0]] %X, 1 +; IS__CGSCC____-NEXT: [[Y:%.*]] = call [[TMP0]] @bar(i1 [[Q]]) +; IS__CGSCC____-NEXT: [[C:%.*]] = extractvalue [[TMP0]] %Y, 0 +; IS__CGSCC____-NEXT: [[D:%.*]] = extractvalue [[TMP0]] %Y, 1 +; IS__CGSCC____-NEXT: [[M:%.*]] = add i32 [[A]], [[C]] +; IS__CGSCC____-NEXT: [[N:%.*]] = add i32 [[B]], [[D]] +; IS__CGSCC____-NEXT: [[R:%.*]] = add i32 [[N]], [[M]] +; IS__CGSCC____-NEXT: ret i32 [[R]] ; %X = call %0 @foo(i1 %Q) %A = extractvalue %0 %X, 0 diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/solve-after-each-resolving-undefs-for-function.ll b/llvm/test/Transforms/Attributor/IPConstantProp/solve-after-each-resolving-undefs-for-function.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/solve-after-each-resolving-undefs-for-function.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/solve-after-each-resolving-undefs-for-function.ll @@ -1,10 +1,11 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM define internal i32 @testf(i1 %c) { +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@testf ; IS__CGSCC____-SAME: (i1 [[C:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -30,6 +31,7 @@ } define internal i32 @test1(i1 %c) { +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@test1 ; IS__CGSCC____-SAME: (i1 [[C:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -57,9 +59,15 @@ } define i32 @main(i1 %c) { -; CHECK-LABEL: define {{[^@]+}}@main -; CHECK-SAME: (i1 [[C:%.*]]) -; CHECK-NEXT: ret i32 99 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@main +; IS__TUNIT____-SAME: (i1 [[C:%.*]]) +; IS__TUNIT____-NEXT: ret i32 99 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@main +; IS__CGSCC____-SAME: (i1 [[C:%.*]]) +; IS__CGSCC____-NEXT: ret i32 99 ; %res = call i32 @test1(i1 %c) ret i32 %res diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/thread_local_acs.ll b/llvm/test/Transforms/Attributor/IPConstantProp/thread_local_acs.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/thread_local_acs.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/thread_local_acs.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -24,13 +24,23 @@ @gsh = dso_local global i32 0, align 4 define internal i32 @callee(i32* %thread_local_ptr, i32* %shared_ptr) { -; CHECK-LABEL: define {{[^@]+}}@callee -; CHECK-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[THREAD_LOCAL_PTR:%.*]], i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[SHARED_PTR:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP:%.*]] = load i32, i32* [[THREAD_LOCAL_PTR]], align 4 -; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @gsh, align 4 -; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP]], [[TMP1]] -; CHECK-NEXT: ret i32 [[ADD]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@callee +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[THREAD_LOCAL_PTR:%.*]], i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[SHARED_PTR:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[TMP:%.*]] = load i32, i32* [[THREAD_LOCAL_PTR]], align 4 +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = load i32, i32* @gsh, align 4 +; IS__TUNIT____-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP]], [[TMP1]] +; IS__TUNIT____-NEXT: ret i32 [[ADD]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@callee +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[THREAD_LOCAL_PTR:%.*]], i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[SHARED_PTR:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[TMP:%.*]] = load i32, i32* [[THREAD_LOCAL_PTR]], align 4 +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = load i32, i32* @gsh, align 4 +; IS__CGSCC____-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP]], [[TMP1]] +; IS__CGSCC____-NEXT: ret i32 [[ADD]] ; entry: %tmp = load i32, i32* %thread_local_ptr, align 4 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 @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=11 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=11 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -12,28 +12,47 @@ ; TEST 1 define i32* @test1(i32* align 8 %0) #0 { -; CHECK-LABEL: define {{[^@]+}}@test1 -; CHECK-SAME: (i32* nofree readnone returned align 8 "no-capture-maybe-returned" [[TMP0:%.*]]) -; CHECK-NEXT: ret i32* [[TMP0]] +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test1 +; IS__TUNIT____-SAME: (i32* nofree readnone returned align 8 "no-capture-maybe-returned" [[TMP0:%.*]]) +; IS__TUNIT____-NEXT: ret i32* [[TMP0]] +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test1 +; IS__CGSCC____-SAME: (i32* nofree readnone returned align 8 "no-capture-maybe-returned" [[TMP0:%.*]]) +; IS__CGSCC____-NEXT: ret i32* [[TMP0]] ; ret i32* %0 } ; TEST 2 define i32* @test2(i32* %0) #0 { -; CHECK-LABEL: define {{[^@]+}}@test2 -; CHECK-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[TMP0:%.*]]) -; CHECK-NEXT: ret i32* [[TMP0]] +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test2 +; IS__TUNIT____-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[TMP0:%.*]]) +; IS__TUNIT____-NEXT: ret i32* [[TMP0]] +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test2 +; IS__CGSCC____-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[TMP0:%.*]]) +; IS__CGSCC____-NEXT: ret i32* [[TMP0]] ; ret i32* %0 } ; TEST 3 define i32* @test3(i32* align 8 %0, i32* align 4 %1, i1 %2) #0 { -; CHECK-LABEL: define {{[^@]+}}@test3 -; CHECK-SAME: (i32* nofree readnone align 8 "no-capture-maybe-returned" [[TMP0:%.*]], i32* nofree readnone align 4 "no-capture-maybe-returned" [[TMP1:%.*]], i1 [[TMP2:%.*]]) -; CHECK-NEXT: [[RET:%.*]] = select i1 [[TMP2]], i32* [[TMP0]], i32* [[TMP1]] -; CHECK-NEXT: ret i32* [[RET]] +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test3 +; IS__TUNIT____-SAME: (i32* nofree readnone align 8 "no-capture-maybe-returned" [[TMP0:%.*]], i32* nofree readnone align 4 "no-capture-maybe-returned" [[TMP1:%.*]], i1 [[TMP2:%.*]]) +; IS__TUNIT____-NEXT: [[RET:%.*]] = select i1 [[TMP2]], i32* [[TMP0]], i32* [[TMP1]] +; IS__TUNIT____-NEXT: ret i32* [[RET]] +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test3 +; IS__CGSCC____-SAME: (i32* nofree readnone align 8 "no-capture-maybe-returned" [[TMP0:%.*]], i32* nofree readnone align 4 "no-capture-maybe-returned" [[TMP1:%.*]], i1 [[TMP2:%.*]]) +; IS__CGSCC____-NEXT: [[RET:%.*]] = select i1 [[TMP2]], i32* [[TMP0]], i32* [[TMP1]] +; IS__CGSCC____-NEXT: ret i32* [[RET]] ; %ret = select i1 %2, i32* %0, i32* %1 ret i32* %ret @@ -41,10 +60,17 @@ ; TEST 4 define i32* @test4(i32* align 32 %0, i32* align 32 %1, i1 %2) #0 { -; CHECK-LABEL: define {{[^@]+}}@test4 -; CHECK-SAME: (i32* nofree readnone align 32 "no-capture-maybe-returned" [[TMP0:%.*]], i32* nofree readnone align 32 "no-capture-maybe-returned" [[TMP1:%.*]], i1 [[TMP2:%.*]]) -; CHECK-NEXT: [[RET:%.*]] = select i1 [[TMP2]], i32* [[TMP0]], i32* [[TMP1]] -; CHECK-NEXT: ret i32* [[RET]] +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test4 +; IS__TUNIT____-SAME: (i32* nofree readnone align 32 "no-capture-maybe-returned" [[TMP0:%.*]], i32* nofree readnone align 32 "no-capture-maybe-returned" [[TMP1:%.*]], i1 [[TMP2:%.*]]) +; IS__TUNIT____-NEXT: [[RET:%.*]] = select i1 [[TMP2]], i32* [[TMP0]], i32* [[TMP1]] +; IS__TUNIT____-NEXT: ret i32* [[RET]] +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test4 +; IS__CGSCC____-SAME: (i32* nofree readnone align 32 "no-capture-maybe-returned" [[TMP0:%.*]], i32* nofree readnone align 32 "no-capture-maybe-returned" [[TMP1:%.*]], i1 [[TMP2:%.*]]) +; IS__CGSCC____-NEXT: [[RET:%.*]] = select i1 [[TMP2]], i32* [[TMP0]], i32* [[TMP1]] +; IS__CGSCC____-NEXT: ret i32* [[RET]] ; %ret = select i1 %2, i32* %0, i32* %1 ret i32* %ret @@ -76,16 +102,26 @@ ; TEST 6 ; SCC define i32* @test6_1() #0 { -; CHECK-LABEL: define {{[^@]+}}@test6_1() -; CHECK-NEXT: unreachable +; NOT_CGSCC_NPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test6_1() +; 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-NEXT: unreachable ; %ret = tail call i32* @test6_2() ret i32* %ret } define i32* @test6_2() #0 { -; CHECK-LABEL: define {{[^@]+}}@test6_2() -; CHECK-NEXT: unreachable +; NOT_CGSCC_NPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test6_2() +; 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-NEXT: unreachable ; %ret = tail call i32* @test6_1() ret i32* %ret @@ -111,6 +147,7 @@ ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f1(i8* readnone %0) local_unnamed_addr #0 { +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__TUNIT____-LABEL: define {{[^@]+}}@f1 ; IS__TUNIT____-SAME: (i8* noalias nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr ; IS__TUNIT____-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null @@ -122,6 +159,7 @@ ; IS__TUNIT____-NEXT: [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] ; IS__TUNIT____-NEXT: ret i8* [[TMP6]] ; +; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__CGSCC____-LABEL: define {{[^@]+}}@f1 ; IS__CGSCC____-SAME: (i8* nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr ; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null @@ -148,6 +186,7 @@ ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f2(i8* readnone %0) local_unnamed_addr #0 { +; CHECK: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; CHECK-LABEL: define {{[^@]+}}@f2() local_unnamed_addr ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8* @a1, null ; CHECK-NEXT: br i1 [[TMP1]], label [[TMP4:%.*]], label [[TMP2:%.*]] @@ -180,6 +219,7 @@ ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f3(i8* readnone %0) local_unnamed_addr #0 { +; CHECK: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; CHECK-LABEL: define {{[^@]+}}@f3() local_unnamed_addr ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8* @a2, null ; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP4:%.*]] @@ -205,10 +245,12 @@ ; TEST 7 ; Better than IR information define align 4 i8* @test7() #0 { +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__TUNIT____-LABEL: define {{[^@]+}}@test7() ; IS__TUNIT____-NEXT: [[C:%.*]] = tail call i8* @f1(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" @a1) ; IS__TUNIT____-NEXT: ret i8* [[C]] ; +; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__CGSCC____-LABEL: define {{[^@]+}}@test7() ; IS__CGSCC____-NEXT: [[C:%.*]] = tail call nonnull align 8 dereferenceable(1) i8* @f1(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) @a1) ; IS__CGSCC____-NEXT: ret i8* [[C]] @@ -220,6 +262,7 @@ ; TEST 7b ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f1b(i8* readnone %0) local_unnamed_addr #0 { +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind uwtable ; IS__TUNIT____-LABEL: define {{[^@]+}}@f1b ; IS__TUNIT____-SAME: (i8* noalias nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr ; IS__TUNIT____-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null @@ -233,6 +276,7 @@ ; IS__TUNIT____-NEXT: [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] ; IS__TUNIT____-NEXT: ret i8* [[TMP6]] ; +; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind uwtable ; IS__CGSCC____-LABEL: define {{[^@]+}}@f1b ; IS__CGSCC____-SAME: (i8* nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr ; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null @@ -263,6 +307,7 @@ ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f2b(i8* readnone %0) local_unnamed_addr #0 { ; +; CHECK: Function Attrs: nofree noinline nosync nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@f2b() local_unnamed_addr ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8* @a1, null ; CHECK-NEXT: br i1 [[TMP1]], label [[TMP4:%.*]], label [[TMP2:%.*]] @@ -296,6 +341,7 @@ ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f3b(i8* readnone %0) local_unnamed_addr #0 { ; +; CHECK: Function Attrs: nofree noinline nosync nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@f3b() local_unnamed_addr ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8* @a2, null ; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP4:%.*]] @@ -319,11 +365,13 @@ } define align 4 i32* @test7b(i32* align 32 %p) #0 { +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind uwtable ; IS__TUNIT____-LABEL: define {{[^@]+}}@test7b ; IS__TUNIT____-SAME: (i32* nofree readnone returned align 32 "no-capture-maybe-returned" [[P:%.*]]) ; IS__TUNIT____-NEXT: [[TMP1:%.*]] = tail call i8* @f1b(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" @a1) ; IS__TUNIT____-NEXT: ret i32* [[P]] ; +; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind uwtable ; IS__CGSCC____-LABEL: define {{[^@]+}}@test7b ; IS__CGSCC____-SAME: (i32* nofree readnone returned align 32 "no-capture-maybe-returned" [[P:%.*]]) ; IS__CGSCC____-NEXT: [[TMP1:%.*]] = tail call i8* @f1b(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) @a1) @@ -356,6 +404,7 @@ declare void @user_i32_ptr(i32* nocapture readnone) nounwind define internal void @test8(i32* %a, i32* %b, i32* %c) { +; IS__TUNIT____: Function Attrs: nounwind ; IS__TUNIT____-LABEL: define {{[^@]+}}@test8 ; IS__TUNIT____-SAME: (i32* noalias nocapture readnone align 4 [[A:%.*]], i32* noalias nocapture readnone align 4 [[B:%.*]], i32* noalias nocapture readnone [[C:%.*]]) ; IS__TUNIT____-NEXT: call void @user_i32_ptr(i32* noalias nocapture readnone align 4 [[A]]) @@ -363,6 +412,7 @@ ; IS__TUNIT____-NEXT: call void @user_i32_ptr(i32* noalias nocapture readnone [[C]]) ; IS__TUNIT____-NEXT: ret void ; +; IS__CGSCC____: Function Attrs: nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@test8 ; IS__CGSCC____-SAME: (i32* nocapture readnone align 4 [[A:%.*]], i32* nocapture readnone align 4 [[B:%.*]], i32* nocapture readnone [[C:%.*]]) ; IS__CGSCC____-NEXT: call void @user_i32_ptr(i32* noalias nocapture readnone align 4 [[A]]) @@ -396,6 +446,7 @@ ; FIXME: This will work with an upcoming patch (D66618 or similar) ; store i32 -1, i32* %g1, align 32 define i32* @test10a(i32* align 32 %p) { +; CHECK: Function Attrs: nofree nosync nounwind ; CHECK-LABEL: define {{[^@]+}}@test10a ; CHECK-SAME: (i32* nofree nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) ; CHECK-NEXT: [[L:%.*]] = load i32, i32* [[P]], align 32 @@ -438,6 +489,7 @@ ; FIXME: This will work with an upcoming patch (D66618 or similar) ; store i32 -1, i32* %g1, align 32 define i32* @test10b(i32* align 32 %p) { +; CHECK: Function Attrs: nofree nosync nounwind ; CHECK-LABEL: define {{[^@]+}}@test10b ; CHECK-SAME: (i32* nofree nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) ; CHECK-NEXT: [[L:%.*]] = load i32, i32* [[P]], align 32 @@ -475,11 +527,19 @@ define i64 @test11(i32* %p) { -; CHECK-LABEL: define {{[^@]+}}@test11 -; CHECK-SAME: (i32* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[P:%.*]]) -; CHECK-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* -; CHECK-NEXT: [[RET:%.*]] = load i64, i64* [[P_CAST]], align 8 -; CHECK-NEXT: ret i64 [[RET]] +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test11 +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[P:%.*]]) +; IS__TUNIT____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* +; IS__TUNIT____-NEXT: [[RET:%.*]] = load i64, i64* [[P_CAST]], align 8 +; IS__TUNIT____-NEXT: ret i64 [[RET]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test11 +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[P:%.*]]) +; IS__CGSCC____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* +; IS__CGSCC____-NEXT: [[RET:%.*]] = load i64, i64* [[P_CAST]], align 8 +; IS__CGSCC____-NEXT: ret i64 [[RET]] ; %p-cast = bitcast i32* %p to i64* %ret = load i64, i64* %p-cast, align 8 @@ -491,13 +551,23 @@ ; FXIME: %p should have nonnull define i64 @test12-1(i32* align 4 %p) { -; CHECK-LABEL: define {{[^@]+}}@test12-1 -; CHECK-SAME: (i32* nocapture nofree readonly align 16 [[P:%.*]]) -; CHECK-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* -; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 1 -; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, i64* [[ARRAYIDX0]], i64 3 -; CHECK-NEXT: [[RET:%.*]] = load i64, i64* [[ARRAYIDX1]], align 16 -; CHECK-NEXT: ret i64 [[RET]] +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test12-1 +; IS__TUNIT____-SAME: (i32* nocapture nofree readonly align 16 [[P:%.*]]) +; IS__TUNIT____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* +; IS__TUNIT____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 1 +; IS__TUNIT____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, i64* [[ARRAYIDX0]], i64 3 +; IS__TUNIT____-NEXT: [[RET:%.*]] = load i64, i64* [[ARRAYIDX1]], align 16 +; IS__TUNIT____-NEXT: ret i64 [[RET]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test12-1 +; IS__CGSCC____-SAME: (i32* nocapture nofree readonly align 16 [[P:%.*]]) +; IS__CGSCC____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* +; IS__CGSCC____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 1 +; IS__CGSCC____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, i64* [[ARRAYIDX0]], i64 3 +; IS__CGSCC____-NEXT: [[RET:%.*]] = load i64, i64* [[ARRAYIDX1]], align 16 +; IS__CGSCC____-NEXT: ret i64 [[RET]] ; %p-cast = bitcast i32* %p to i64* %arrayidx0 = getelementptr i64, i64* %p-cast, i64 1 @@ -507,12 +577,21 @@ } define i64 @test12-2(i32* align 4 %p) { -; CHECK-LABEL: define {{[^@]+}}@test12-2 -; CHECK-SAME: (i32* nocapture nofree nonnull readonly align 16 dereferenceable(8) [[P:%.*]]) -; CHECK-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* -; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 0 -; CHECK-NEXT: [[RET:%.*]] = load i64, i64* [[ARRAYIDX0]], align 16 -; CHECK-NEXT: ret i64 [[RET]] +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test12-2 +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readonly align 16 dereferenceable(8) [[P:%.*]]) +; IS__TUNIT____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* +; IS__TUNIT____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 0 +; IS__TUNIT____-NEXT: [[RET:%.*]] = load i64, i64* [[ARRAYIDX0]], align 16 +; IS__TUNIT____-NEXT: ret i64 [[RET]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test12-2 +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 16 dereferenceable(8) [[P:%.*]]) +; IS__CGSCC____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* +; IS__CGSCC____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 0 +; IS__CGSCC____-NEXT: [[RET:%.*]] = load i64, i64* [[ARRAYIDX0]], align 16 +; IS__CGSCC____-NEXT: ret i64 [[RET]] ; %p-cast = bitcast i32* %p to i64* %arrayidx0 = getelementptr i64, i64* %p-cast, i64 0 @@ -522,13 +601,23 @@ ; FXIME: %p should have nonnull define void @test12-3(i32* align 4 %p) { -; CHECK-LABEL: define {{[^@]+}}@test12-3 -; CHECK-SAME: (i32* nocapture nofree writeonly align 16 [[P:%.*]]) -; CHECK-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* -; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 1 -; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, i64* [[ARRAYIDX0]], i64 3 -; CHECK-NEXT: store i64 0, i64* [[ARRAYIDX1]], align 16 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@test12-3 +; IS__TUNIT____-SAME: (i32* nocapture nofree writeonly align 16 [[P:%.*]]) +; IS__TUNIT____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* +; IS__TUNIT____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 1 +; IS__TUNIT____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, i64* [[ARRAYIDX0]], i64 3 +; IS__TUNIT____-NEXT: store i64 0, i64* [[ARRAYIDX1]], align 16 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@test12-3 +; IS__CGSCC____-SAME: (i32* nocapture nofree writeonly align 16 [[P:%.*]]) +; IS__CGSCC____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* +; IS__CGSCC____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 1 +; IS__CGSCC____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr i64, i64* [[ARRAYIDX0]], i64 3 +; IS__CGSCC____-NEXT: store i64 0, i64* [[ARRAYIDX1]], align 16 +; IS__CGSCC____-NEXT: ret void ; %p-cast = bitcast i32* %p to i64* %arrayidx0 = getelementptr i64, i64* %p-cast, i64 1 @@ -538,12 +627,21 @@ } define void @test12-4(i32* align 4 %p) { -; CHECK-LABEL: define {{[^@]+}}@test12-4 -; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 16 dereferenceable(8) [[P:%.*]]) -; CHECK-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* -; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 0 -; CHECK-NEXT: store i64 0, i64* [[ARRAYIDX0]], align 16 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@test12-4 +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 16 dereferenceable(8) [[P:%.*]]) +; IS__TUNIT____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* +; IS__TUNIT____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 0 +; IS__TUNIT____-NEXT: store i64 0, i64* [[ARRAYIDX0]], align 16 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@test12-4 +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 16 dereferenceable(8) [[P:%.*]]) +; IS__CGSCC____-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* +; IS__CGSCC____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 0 +; IS__CGSCC____-NEXT: store i64 0, i64* [[ARRAYIDX0]], align 16 +; IS__CGSCC____-NEXT: ret void ; %p-cast = bitcast i32* %p to i64* %arrayidx0 = getelementptr i64, i64* %p-cast, i64 0 @@ -554,6 +652,7 @@ declare void @use(i64*) willreturn nounwind define void @test12-5(i32* align 4 %p) { +; CHECK: Function Attrs: nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@test12-5 ; CHECK-SAME: (i32* align 16 [[P:%.*]]) ; CHECK-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* @@ -570,6 +669,7 @@ } define void @test12-6(i32* align 4 %p) { +; CHECK: Function Attrs: nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@test12-6 ; CHECK-SAME: (i32* align 16 [[P:%.*]]) ; CHECK-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* @@ -584,17 +684,31 @@ } define void @test13(i1 %c, i32* align 32 %dst) #0 { -; CHECK-LABEL: define {{[^@]+}}@test13 -; CHECK-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) -; CHECK-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] -; CHECK: truebb: -; CHECK-NEXT: br label [[END:%.*]] -; CHECK: falsebb: -; CHECK-NEXT: br label [[END]] -; CHECK: end: -; CHECK-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ null, [[FALSEBB]] ] -; CHECK-NEXT: store i32 0, i32* [[PTR]], align 32 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree noinline nosync nounwind uwtable willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@test13 +; IS__TUNIT____-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) +; IS__TUNIT____-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] +; IS__TUNIT____: truebb: +; IS__TUNIT____-NEXT: br label [[END:%.*]] +; IS__TUNIT____: falsebb: +; IS__TUNIT____-NEXT: br label [[END]] +; IS__TUNIT____: end: +; IS__TUNIT____-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ null, [[FALSEBB]] ] +; IS__TUNIT____-NEXT: store i32 0, i32* [[PTR]], align 32 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind uwtable willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@test13 +; IS__CGSCC____-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) +; IS__CGSCC____-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] +; IS__CGSCC____: truebb: +; IS__CGSCC____-NEXT: br label [[END:%.*]] +; IS__CGSCC____: falsebb: +; IS__CGSCC____-NEXT: br label [[END]] +; IS__CGSCC____: end: +; IS__CGSCC____-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ null, [[FALSEBB]] ] +; IS__CGSCC____-NEXT: store i32 0, i32* [[PTR]], align 32 +; IS__CGSCC____-NEXT: ret void ; br i1 %c, label %truebb, label %falsebb truebb: @@ -608,17 +722,31 @@ } define void @test13-1(i1 %c, i32* align 32 %dst) { -; CHECK-LABEL: define {{[^@]+}}@test13-1 -; CHECK-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) -; CHECK-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] -; CHECK: truebb: -; CHECK-NEXT: br label [[END:%.*]] -; CHECK: falsebb: -; CHECK-NEXT: br label [[END]] -; CHECK: end: -; CHECK-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 48 to i32*), [[FALSEBB]] ] -; CHECK-NEXT: store i32 0, i32* [[PTR]], align 16 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@test13-1 +; IS__TUNIT____-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) +; IS__TUNIT____-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] +; IS__TUNIT____: truebb: +; IS__TUNIT____-NEXT: br label [[END:%.*]] +; IS__TUNIT____: falsebb: +; IS__TUNIT____-NEXT: br label [[END]] +; IS__TUNIT____: end: +; IS__TUNIT____-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 48 to i32*), [[FALSEBB]] ] +; IS__TUNIT____-NEXT: store i32 0, i32* [[PTR]], align 16 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@test13-1 +; IS__CGSCC____-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) +; IS__CGSCC____-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] +; IS__CGSCC____: truebb: +; IS__CGSCC____-NEXT: br label [[END:%.*]] +; IS__CGSCC____: falsebb: +; IS__CGSCC____-NEXT: br label [[END]] +; IS__CGSCC____: end: +; IS__CGSCC____-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 48 to i32*), [[FALSEBB]] ] +; IS__CGSCC____-NEXT: store i32 0, i32* [[PTR]], align 16 +; IS__CGSCC____-NEXT: ret void ; br i1 %c, label %truebb, label %falsebb truebb: @@ -632,17 +760,31 @@ } define void @test13-2(i1 %c, i32* align 32 %dst) { -; CHECK-LABEL: define {{[^@]+}}@test13-2 -; CHECK-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) -; CHECK-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] -; CHECK: truebb: -; CHECK-NEXT: br label [[END:%.*]] -; CHECK: falsebb: -; CHECK-NEXT: br label [[END]] -; CHECK: end: -; CHECK-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 160 to i32*), [[FALSEBB]] ] -; CHECK-NEXT: store i32 0, i32* [[PTR]], align 32 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@test13-2 +; IS__TUNIT____-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) +; IS__TUNIT____-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] +; IS__TUNIT____: truebb: +; IS__TUNIT____-NEXT: br label [[END:%.*]] +; IS__TUNIT____: falsebb: +; IS__TUNIT____-NEXT: br label [[END]] +; IS__TUNIT____: end: +; IS__TUNIT____-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 160 to i32*), [[FALSEBB]] ] +; IS__TUNIT____-NEXT: store i32 0, i32* [[PTR]], align 32 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@test13-2 +; IS__CGSCC____-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) +; IS__CGSCC____-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] +; IS__CGSCC____: truebb: +; IS__CGSCC____-NEXT: br label [[END:%.*]] +; IS__CGSCC____: falsebb: +; IS__CGSCC____-NEXT: br label [[END]] +; IS__CGSCC____: end: +; IS__CGSCC____-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 160 to i32*), [[FALSEBB]] ] +; IS__CGSCC____-NEXT: store i32 0, i32* [[PTR]], align 32 +; IS__CGSCC____-NEXT: ret void ; br i1 %c, label %truebb, label %falsebb truebb: @@ -656,17 +798,31 @@ } define void @test13-3(i1 %c, i32* align 32 %dst) { -; CHECK-LABEL: define {{[^@]+}}@test13-3 -; CHECK-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) -; CHECK-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] -; CHECK: truebb: -; CHECK-NEXT: br label [[END:%.*]] -; CHECK: falsebb: -; CHECK-NEXT: br label [[END]] -; CHECK: end: -; CHECK-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 128 to i32*), [[FALSEBB]] ] -; CHECK-NEXT: store i32 0, i32* [[PTR]], align 32 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@test13-3 +; IS__TUNIT____-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) +; IS__TUNIT____-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] +; IS__TUNIT____: truebb: +; IS__TUNIT____-NEXT: br label [[END:%.*]] +; IS__TUNIT____: falsebb: +; IS__TUNIT____-NEXT: br label [[END]] +; IS__TUNIT____: end: +; IS__TUNIT____-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 128 to i32*), [[FALSEBB]] ] +; IS__TUNIT____-NEXT: store i32 0, i32* [[PTR]], align 32 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@test13-3 +; IS__CGSCC____-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) +; IS__CGSCC____-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] +; IS__CGSCC____: truebb: +; IS__CGSCC____-NEXT: br label [[END:%.*]] +; IS__CGSCC____: falsebb: +; IS__CGSCC____-NEXT: br label [[END]] +; IS__CGSCC____: end: +; IS__CGSCC____-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ inttoptr (i64 128 to i32*), [[FALSEBB]] ] +; IS__CGSCC____-NEXT: store i32 0, i32* [[PTR]], align 32 +; IS__CGSCC____-NEXT: ret void ; br i1 %c, label %truebb, label %falsebb truebb: @@ -681,19 +837,33 @@ ; Don't crash on ptr2int/int2ptr uses. define i64 @ptr2int(i32* %p) { -; CHECK-LABEL: define {{[^@]+}}@ptr2int -; CHECK-SAME: (i32* nofree readnone [[P:%.*]]) -; CHECK-NEXT: [[P2I:%.*]] = ptrtoint i32* [[P]] to i64 -; CHECK-NEXT: ret i64 [[P2I]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@ptr2int +; IS__TUNIT____-SAME: (i32* nofree readnone [[P:%.*]]) +; IS__TUNIT____-NEXT: [[P2I:%.*]] = ptrtoint i32* [[P]] to i64 +; IS__TUNIT____-NEXT: ret i64 [[P2I]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@ptr2int +; IS__CGSCC____-SAME: (i32* nofree readnone [[P:%.*]]) +; IS__CGSCC____-NEXT: [[P2I:%.*]] = ptrtoint i32* [[P]] to i64 +; IS__CGSCC____-NEXT: ret i64 [[P2I]] ; %p2i = ptrtoint i32* %p to i64 ret i64 %p2i } define i64* @int2ptr(i64 %i) { -; CHECK-LABEL: define {{[^@]+}}@int2ptr -; CHECK-SAME: (i64 [[I:%.*]]) -; CHECK-NEXT: [[I2P:%.*]] = inttoptr i64 [[I]] to i64* -; CHECK-NEXT: ret i64* [[I2P]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@int2ptr +; IS__TUNIT____-SAME: (i64 [[I:%.*]]) +; IS__TUNIT____-NEXT: [[I2P:%.*]] = inttoptr i64 [[I]] to i64* +; IS__TUNIT____-NEXT: ret i64* [[I2P]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@int2ptr +; IS__CGSCC____-SAME: (i64 [[I:%.*]]) +; IS__CGSCC____-NEXT: [[I2P:%.*]] = inttoptr i64 [[I]] to i64* +; IS__CGSCC____-NEXT: ret i64* [[I2P]] ; %i2p = inttoptr i64 %i to i64* ret i64* %i2p @@ -701,10 +871,17 @@ ; Use the store alignment only for the pointer operand. define void @aligned_store(i8* %Value, i8** %Ptr) { -; CHECK-LABEL: define {{[^@]+}}@aligned_store -; CHECK-SAME: (i8* nofree writeonly [[VALUE:%.*]], i8** nocapture nofree nonnull writeonly align 32 dereferenceable(8) [[PTR:%.*]]) -; CHECK-NEXT: store i8* [[VALUE]], i8** [[PTR]], align 32 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@aligned_store +; IS__TUNIT____-SAME: (i8* nofree writeonly [[VALUE:%.*]], i8** nocapture nofree nonnull writeonly align 32 dereferenceable(8) [[PTR:%.*]]) +; IS__TUNIT____-NEXT: store i8* [[VALUE]], i8** [[PTR]], align 32 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@aligned_store +; IS__CGSCC____-SAME: (i8* nofree writeonly [[VALUE:%.*]], i8** nocapture nofree nonnull writeonly align 32 dereferenceable(8) [[PTR:%.*]]) +; IS__CGSCC____-NEXT: store i8* [[VALUE]], i8** [[PTR]], align 32 +; IS__CGSCC____-NEXT: ret void ; store i8* %Value, i8** %Ptr, align 32 ret void @@ -724,11 +901,19 @@ } define void @align_store_after_bc(i32* align 2048 %arg) { ; -; CHECK-LABEL: define {{[^@]+}}@align_store_after_bc -; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 2048 dereferenceable(1) [[ARG:%.*]]) -; CHECK-NEXT: [[BC:%.*]] = bitcast i32* [[ARG]] to i8* -; CHECK-NEXT: store i8 0, i8* [[BC]], align 2048 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@align_store_after_bc +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 2048 dereferenceable(1) [[ARG:%.*]]) +; IS__TUNIT____-NEXT: [[BC:%.*]] = bitcast i32* [[ARG]] to i8* +; IS__TUNIT____-NEXT: store i8 0, i8* [[BC]], align 2048 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@align_store_after_bc +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 2048 dereferenceable(1) [[ARG:%.*]]) +; IS__CGSCC____-NEXT: [[BC:%.*]] = bitcast i32* [[ARG]] to i8* +; IS__CGSCC____-NEXT: store i8 0, i8* [[BC]], align 2048 +; IS__CGSCC____-NEXT: ret void ; %bc = bitcast i32* %arg to i8* store i8 0, i8* %bc @@ -739,15 +924,23 @@ ; we cannot also put on the caller. @cnd = external global i1 define i32 @musttail_callee_1(i32* %p) { -; CHECK-LABEL: define {{[^@]+}}@musttail_callee_1 -; CHECK-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[P:%.*]]) -; CHECK-NEXT: [[V:%.*]] = load i32, i32* [[P]], align 32 -; CHECK-NEXT: ret i32 [[V]] +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@musttail_callee_1 +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[P:%.*]]) +; IS__TUNIT____-NEXT: [[V:%.*]] = load i32, i32* [[P]], align 32 +; IS__TUNIT____-NEXT: ret i32 [[V]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@musttail_callee_1 +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[P:%.*]]) +; IS__CGSCC____-NEXT: [[V:%.*]] = load i32, i32* [[P]], align 32 +; IS__CGSCC____-NEXT: ret i32 [[V]] ; %v = load i32, i32* %p, align 32 ret i32 %v } define i32 @musttail_caller_1(i32* %p) { +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readonly willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@musttail_caller_1 ; IS__TUNIT____-SAME: (i32* nocapture nofree readonly [[P:%.*]]) ; IS__TUNIT____-NEXT: [[C:%.*]] = load i1, i1* @cnd, align 1 @@ -758,6 +951,7 @@ ; IS__TUNIT____: exit: ; IS__TUNIT____-NEXT: ret i32 0 ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@musttail_caller_1 ; IS__CGSCC____-SAME: (i32* nocapture nofree readonly [[P:%.*]]) ; IS__CGSCC____-NEXT: [[C:%.*]] = load i1, i1* @cnd, align 1 diff --git a/llvm/test/Transforms/Attributor/allow_list.ll b/llvm/test/Transforms/Attributor/allow_list.ll --- a/llvm/test/Transforms/Attributor/allow_list.ll +++ b/llvm/test/Transforms/Attributor/allow_list.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -S -passes=attributor --attributor-seed-allow-list asd < %s | FileCheck %s --check-prefixes=CHECK_DISABLED ; RUN: opt -S -passes=attributor --attributor-seed-allow-list AAValueSimplify < %s | FileCheck %s --check-prefixes=CHECK_ENABLED @@ -6,6 +6,7 @@ ; Function Attrs: nounwind uwtable define internal i32 @range_test(i32 %a) #0 { +; CHECK_DISABLED: Function Attrs: noinline nounwind uwtable ; CHECK_DISABLED-LABEL: define {{[^@]+}}@range_test ; CHECK_DISABLED-SAME: (i32 [[A:%.*]]) ; CHECK_DISABLED-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[A]], 100 @@ -19,10 +20,12 @@ ; Function Attrs: nounwind uwtable define i32 @range_use() #0 { +; CHECK_DISABLED: Function Attrs: noinline nounwind uwtable ; CHECK_DISABLED-LABEL: define {{[^@]+}}@range_use() ; CHECK_DISABLED-NEXT: [[TMP1:%.*]] = call i32 @range_test(i32 123) ; CHECK_DISABLED-NEXT: ret i32 [[TMP1]] ; +; CHECK_ENABLED: Function Attrs: noinline nounwind uwtable ; CHECK_ENABLED-LABEL: define {{[^@]+}}@range_use() ; CHECK_ENABLED-NEXT: ret i32 1 ; @@ -30,4 +33,4 @@ ret i32 %1 } -attributes #0 = { nounwind uwtable noinline } \ No newline at end of file +attributes #0 = { nounwind uwtable noinline } diff --git a/llvm/test/Transforms/Attributor/alwaysinline.ll b/llvm/test/Transforms/Attributor/alwaysinline.ll --- a/llvm/test/Transforms/Attributor/alwaysinline.ll +++ b/llvm/test/Transforms/Attributor/alwaysinline.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -9,23 +9,31 @@ ; the function is not exactly defined, and marked alwaysinline and can be inlined, ; so the function can be analyzed -; CHECK: Function Attrs: alwaysinline -; CHECK-SAME: willreturn define linkonce void @inner1() alwaysinline { -; CHECK-LABEL: define {{[^@]+}}@inner1() -; CHECK-NEXT: entry: -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: alwaysinline nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@inner1() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: alwaysinline nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@inner1() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret void ; entry: ret void } -; CHECK: Function Attrs: -; CHECK-SAME: willreturn define void @outer1() { -; CHECK-LABEL: define {{[^@]+}}@outer1() -; CHECK-NEXT: entry: -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@outer1() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@outer1() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret void ; entry: call void @inner1() @@ -34,7 +42,6 @@ ; The function is not alwaysinline and is not exactly defined ; so it will not be analyzed -; CHECK-NOT: Function Attrs: define linkonce i32 @inner2() { ; CHECK-LABEL: define {{[^@]+}}@inner2() ; CHECK-NEXT: entry: @@ -59,12 +66,8 @@ ; This function cannot be inlined although it is marked alwaysinline ; it is `unexactly defined` and alwaysinline but cannot be inlined. ; so it will not be analyzed -; CHECK: Function Attrs: -; CHECK-NOT: nofree -; CHECK-NOT: nosync -; CHECK-NOT: nounwind -; CHECK-NOT: readnone define linkonce i32 @inner3(i8* %addr) alwaysinline { +; CHECK: Function Attrs: alwaysinline ; CHECK-LABEL: define {{[^@]+}}@inner3 ; CHECK-SAME: (i8* [[ADDR:%.*]]) ; CHECK-NEXT: entry: @@ -84,7 +87,6 @@ ret i32 44 } -; CHECK-NOT: Function Attrs: define i32 @outer3(i32 %x) { ; CHECK-LABEL: define {{[^@]+}}@outer3 ; CHECK-SAME: (i32 [[X:%.*]]) diff --git a/llvm/test/Transforms/Attributor/callbacks.ll b/llvm/test/Transforms/Attributor/callbacks.ll --- a/llvm/test/Transforms/Attributor/callbacks.ll +++ b/llvm/test/Transforms/Attributor/callbacks.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -178,6 +178,7 @@ ; The others are annotated with alignment information, amongst others, or even replaced by the constants passed to the call. define internal void @t1_callback_callee(i32* %is_not_null, i32* %ptr, i32* %a, i64 %b, i32** %c) { ; +; NOT_TUNIT_NPM: Function Attrs: nosync ; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@t1_callback_callee ; NOT_TUNIT_NPM-SAME: (i32* nocapture nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* nocapture align 256 [[A:%.*]], i64 [[B:%.*]], i32** nocapture nonnull readonly align 64 dereferenceable(8) [[C:%.*]]) ; NOT_TUNIT_NPM-NEXT: entry: @@ -187,6 +188,7 @@ ; NOT_TUNIT_NPM-NEXT: tail call void @t1_check(i32* nocapture align 256 [[A]], i64 99, i32* nocapture [[TMP0]]) ; NOT_TUNIT_NPM-NEXT: ret void ; +; IS__TUNIT_NPM: Function Attrs: nosync ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@t1_callback_callee ; IS__TUNIT_NPM-SAME: (i32* nocapture nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* noalias nocapture align 256 [[A:%.*]], i64 [[B:%.*]], i32** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C:%.*]]) ; IS__TUNIT_NPM-NEXT: entry: diff --git a/llvm/test/Transforms/Attributor/dereferenceable-1.ll b/llvm/test/Transforms/Attributor/dereferenceable-1.ll --- a/llvm/test/Transforms/Attributor/dereferenceable-1.ll +++ b/llvm/test/Transforms/Attributor/dereferenceable-1.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=16 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=16 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -11,11 +11,19 @@ ; take mininimum of return values ; define i32* @test1(i32* dereferenceable(4) %0, double* dereferenceable(8) %1, i1 zeroext %2) local_unnamed_addr { -; CHECK-LABEL: define {{[^@]+}}@test1 -; CHECK-SAME: (i32* nofree nonnull readnone dereferenceable(4) "no-capture-maybe-returned" [[TMP0:%.*]], double* nofree nonnull readnone dereferenceable(8) "no-capture-maybe-returned" [[TMP1:%.*]], i1 zeroext [[TMP2:%.*]]) local_unnamed_addr -; CHECK-NEXT: [[TMP4:%.*]] = bitcast double* [[TMP1]] to i32* -; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP2]], i32* [[TMP0]], i32* [[TMP4]] -; CHECK-NEXT: ret i32* [[TMP5]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test1 +; IS__TUNIT____-SAME: (i32* nofree nonnull readnone dereferenceable(4) "no-capture-maybe-returned" [[TMP0:%.*]], double* nofree nonnull readnone dereferenceable(8) "no-capture-maybe-returned" [[TMP1:%.*]], i1 zeroext [[TMP2:%.*]]) local_unnamed_addr +; IS__TUNIT____-NEXT: [[TMP4:%.*]] = bitcast double* [[TMP1]] to i32* +; IS__TUNIT____-NEXT: [[TMP5:%.*]] = select i1 [[TMP2]], i32* [[TMP0]], i32* [[TMP4]] +; IS__TUNIT____-NEXT: ret i32* [[TMP5]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test1 +; IS__CGSCC____-SAME: (i32* nofree nonnull readnone dereferenceable(4) "no-capture-maybe-returned" [[TMP0:%.*]], double* nofree nonnull readnone dereferenceable(8) "no-capture-maybe-returned" [[TMP1:%.*]], i1 zeroext [[TMP2:%.*]]) local_unnamed_addr +; IS__CGSCC____-NEXT: [[TMP4:%.*]] = bitcast double* [[TMP1]] to i32* +; IS__CGSCC____-NEXT: [[TMP5:%.*]] = select i1 [[TMP2]], i32* [[TMP0]], i32* [[TMP4]] +; IS__CGSCC____-NEXT: ret i32* [[TMP5]] ; %4 = bitcast double* %1 to i32* %5 = select i1 %2, i32* %0, i32* %4 @@ -24,11 +32,19 @@ ; TEST 2 define i32* @test2(i32* dereferenceable_or_null(4) %0, double* dereferenceable(8) %1, i1 zeroext %2) local_unnamed_addr { -; CHECK-LABEL: define {{[^@]+}}@test2 -; CHECK-SAME: (i32* nofree readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[TMP0:%.*]], double* nofree nonnull readnone dereferenceable(8) "no-capture-maybe-returned" [[TMP1:%.*]], i1 zeroext [[TMP2:%.*]]) local_unnamed_addr -; CHECK-NEXT: [[TMP4:%.*]] = bitcast double* [[TMP1]] to i32* -; CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP2]], i32* [[TMP0]], i32* [[TMP4]] -; CHECK-NEXT: ret i32* [[TMP5]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test2 +; IS__TUNIT____-SAME: (i32* nofree readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[TMP0:%.*]], double* nofree nonnull readnone dereferenceable(8) "no-capture-maybe-returned" [[TMP1:%.*]], i1 zeroext [[TMP2:%.*]]) local_unnamed_addr +; IS__TUNIT____-NEXT: [[TMP4:%.*]] = bitcast double* [[TMP1]] to i32* +; IS__TUNIT____-NEXT: [[TMP5:%.*]] = select i1 [[TMP2]], i32* [[TMP0]], i32* [[TMP4]] +; IS__TUNIT____-NEXT: ret i32* [[TMP5]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test2 +; IS__CGSCC____-SAME: (i32* nofree readnone dereferenceable_or_null(4) "no-capture-maybe-returned" [[TMP0:%.*]], double* nofree nonnull readnone dereferenceable(8) "no-capture-maybe-returned" [[TMP1:%.*]], i1 zeroext [[TMP2:%.*]]) local_unnamed_addr +; IS__CGSCC____-NEXT: [[TMP4:%.*]] = bitcast double* [[TMP1]] to i32* +; IS__CGSCC____-NEXT: [[TMP5:%.*]] = select i1 [[TMP2]], i32* [[TMP0]], i32* [[TMP4]] +; IS__CGSCC____-NEXT: ret i32* [[TMP5]] ; %4 = bitcast double* %1 to i32* %5 = select i1 %2, i32* %0, i32* %4 @@ -38,32 +54,55 @@ ; TEST 3 ; GEP inbounds define i32* @test3_1(i32* dereferenceable(8) %0) local_unnamed_addr { -; CHECK-LABEL: define {{[^@]+}}@test3_1 -; CHECK-SAME: (i32* nofree nonnull readnone dereferenceable(8) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr -; CHECK-NEXT: [[RET:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 1 -; CHECK-NEXT: ret i32* [[RET]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test3_1 +; IS__TUNIT____-SAME: (i32* nofree nonnull readnone dereferenceable(8) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr +; IS__TUNIT____-NEXT: [[RET:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 1 +; IS__TUNIT____-NEXT: ret i32* [[RET]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test3_1 +; IS__CGSCC____-SAME: (i32* nofree nonnull readnone dereferenceable(8) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr +; IS__CGSCC____-NEXT: [[RET:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 1 +; IS__CGSCC____-NEXT: ret i32* [[RET]] ; %ret = getelementptr inbounds i32, i32* %0, i64 1 ret i32* %ret } define i32* @test3_2(i32* dereferenceable_or_null(32) %0) local_unnamed_addr { -; CHECK-LABEL: define {{[^@]+}}@test3_2 -; CHECK-SAME: (i32* nofree readnone dereferenceable_or_null(32) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr -; CHECK-NEXT: [[RET:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 4 -; CHECK-NEXT: ret i32* [[RET]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test3_2 +; IS__TUNIT____-SAME: (i32* nofree readnone dereferenceable_or_null(32) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr +; IS__TUNIT____-NEXT: [[RET:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 4 +; IS__TUNIT____-NEXT: ret i32* [[RET]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test3_2 +; IS__CGSCC____-SAME: (i32* nofree readnone dereferenceable_or_null(32) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr +; IS__CGSCC____-NEXT: [[RET:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 4 +; IS__CGSCC____-NEXT: ret i32* [[RET]] ; %ret = getelementptr inbounds i32, i32* %0, i64 4 ret i32* %ret } define i32* @test3_3(i32* dereferenceable(8) %0, i32* dereferenceable(16) %1, i1 %2) local_unnamed_addr { -; CHECK-LABEL: define {{[^@]+}}@test3_3 -; CHECK-SAME: (i32* nofree nonnull readnone dereferenceable(8) "no-capture-maybe-returned" [[TMP0:%.*]], i32* nofree nonnull readnone dereferenceable(16) "no-capture-maybe-returned" [[TMP1:%.*]], i1 [[TMP2:%.*]]) local_unnamed_addr -; CHECK-NEXT: [[RET1:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 1 -; CHECK-NEXT: [[RET2:%.*]] = getelementptr inbounds i32, i32* [[TMP1]], i64 2 -; CHECK-NEXT: [[RET:%.*]] = select i1 [[TMP2]], i32* [[RET1]], i32* [[RET2]] -; CHECK-NEXT: ret i32* [[RET]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test3_3 +; IS__TUNIT____-SAME: (i32* nofree nonnull readnone dereferenceable(8) "no-capture-maybe-returned" [[TMP0:%.*]], i32* nofree nonnull readnone dereferenceable(16) "no-capture-maybe-returned" [[TMP1:%.*]], i1 [[TMP2:%.*]]) local_unnamed_addr +; IS__TUNIT____-NEXT: [[RET1:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 1 +; IS__TUNIT____-NEXT: [[RET2:%.*]] = getelementptr inbounds i32, i32* [[TMP1]], i64 2 +; IS__TUNIT____-NEXT: [[RET:%.*]] = select i1 [[TMP2]], i32* [[RET1]], i32* [[RET2]] +; IS__TUNIT____-NEXT: ret i32* [[RET]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test3_3 +; IS__CGSCC____-SAME: (i32* nofree nonnull readnone dereferenceable(8) "no-capture-maybe-returned" [[TMP0:%.*]], i32* nofree nonnull readnone dereferenceable(16) "no-capture-maybe-returned" [[TMP1:%.*]], i1 [[TMP2:%.*]]) local_unnamed_addr +; IS__CGSCC____-NEXT: [[RET1:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 1 +; IS__CGSCC____-NEXT: [[RET2:%.*]] = getelementptr inbounds i32, i32* [[TMP1]], i64 2 +; IS__CGSCC____-NEXT: [[RET:%.*]] = select i1 [[TMP2]], i32* [[RET1]], i32* [[RET2]] +; IS__CGSCC____-NEXT: ret i32* [[RET]] ; %ret1 = getelementptr inbounds i32, i32* %0, i64 1 %ret2 = getelementptr inbounds i32, i32* %1, i64 2 @@ -75,9 +114,15 @@ ; Better than known in IR. define dereferenceable(4) i32* @test4(i32* dereferenceable(8) %0) local_unnamed_addr { -; CHECK-LABEL: define {{[^@]+}}@test4 -; CHECK-SAME: (i32* nofree nonnull readnone returned dereferenceable(8) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr -; CHECK-NEXT: ret i32* [[TMP0]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test4 +; IS__TUNIT____-SAME: (i32* nofree nonnull readnone returned dereferenceable(8) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr +; IS__TUNIT____-NEXT: ret i32* [[TMP0]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test4 +; IS__CGSCC____-SAME: (i32* nofree nonnull readnone returned dereferenceable(8) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr +; IS__CGSCC____-NEXT: ret i32* [[TMP0]] ; ret i32* %0 } @@ -189,6 +234,7 @@ declare i32* @unkown_ptr() willreturn nounwind declare i32 @unkown_f(i32*) willreturn nounwind define i32* @f7_0(i32* %ptr) { +; CHECK: Function Attrs: nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@f7_0 ; CHECK-SAME: (i32* nonnull returned dereferenceable(8) [[PTR:%.*]]) ; CHECK-NEXT: [[T:%.*]] = tail call i32 @unkown_f(i32* nonnull dereferenceable(8) [[PTR]]) @@ -199,6 +245,7 @@ } define void @f7_1(i32* %ptr, i1 %c) { +; CHECK: Function Attrs: nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@f7_1 ; CHECK-SAME: (i32* nonnull align 4 dereferenceable(4) [[PTR:%.*]], i1 [[C:%.*]]) ; CHECK-NEXT: [[A:%.*]] = tail call i32 @unkown_f(i32* nonnull align 4 dereferenceable(4) [[PTR]]) @@ -228,6 +275,7 @@ } define void @f7_2(i1 %c) { +; CHECK: Function Attrs: nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@f7_2 ; CHECK-SAME: (i1 [[C:%.*]]) ; CHECK-NEXT: [[PTR:%.*]] = tail call nonnull align 4 dereferenceable(4) i32* @unkown_ptr() @@ -258,6 +306,7 @@ } define i32* @f7_3() { +; CHECK: Function Attrs: nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@f7_3() ; CHECK-NEXT: [[PTR:%.*]] = tail call nonnull align 16 dereferenceable(4) i32* @unkown_ptr() ; CHECK-NEXT: store i32 10, i32* [[PTR]], align 16 @@ -270,11 +319,19 @@ ; FIXME: This should have a return dereferenceable(8) but we need to make sure it will work in loops as well. define i32* @test_for_minus_index(i32* %p) { -; CHECK-LABEL: define {{[^@]+}}@test_for_minus_index -; CHECK-SAME: (i32* nofree nonnull writeonly align 4 "no-capture-maybe-returned" [[P:%.*]]) -; CHECK-NEXT: [[Q:%.*]] = getelementptr inbounds i32, i32* [[P]], i32 -2 -; CHECK-NEXT: store i32 1, i32* [[Q]], align 4 -; CHECK-NEXT: ret i32* [[Q]] +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@test_for_minus_index +; IS__TUNIT____-SAME: (i32* nofree nonnull writeonly align 4 "no-capture-maybe-returned" [[P:%.*]]) +; IS__TUNIT____-NEXT: [[Q:%.*]] = getelementptr inbounds i32, i32* [[P]], i32 -2 +; IS__TUNIT____-NEXT: store i32 1, i32* [[Q]], align 4 +; IS__TUNIT____-NEXT: ret i32* [[Q]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@test_for_minus_index +; IS__CGSCC____-SAME: (i32* nofree nonnull writeonly align 4 "no-capture-maybe-returned" [[P:%.*]]) +; IS__CGSCC____-NEXT: [[Q:%.*]] = getelementptr inbounds i32, i32* [[P]], i32 -2 +; IS__CGSCC____-NEXT: store i32 1, i32* [[Q]], align 4 +; IS__CGSCC____-NEXT: ret i32* [[Q]] ; %q = getelementptr inbounds i32, i32* %p, i32 -2 store i32 1, i32* %q @@ -282,10 +339,17 @@ } define void @deref_or_null_and_nonnull(i32* dereferenceable_or_null(100) %0) { -; CHECK-LABEL: define {{[^@]+}}@deref_or_null_and_nonnull -; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(100) [[TMP0:%.*]]) -; CHECK-NEXT: store i32 1, i32* [[TMP0]], align 4 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@deref_or_null_and_nonnull +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(100) [[TMP0:%.*]]) +; IS__TUNIT____-NEXT: store i32 1, i32* [[TMP0]], align 4 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@deref_or_null_and_nonnull +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(100) [[TMP0:%.*]]) +; IS__CGSCC____-NEXT: store i32 1, i32* [[TMP0]], align 4 +; IS__CGSCC____-NEXT: ret void ; store i32 1, i32* %0 ret void @@ -300,37 +364,73 @@ ; FIXME: %ptr should be dereferenceable(31) define void @test8(i8* %ptr) #0 { -; IS________OPM-LABEL: define {{[^@]+}}@test8 -; IS________OPM-SAME: (i8* nocapture nofree nonnull writeonly [[PTR:%.*]]) -; IS________OPM-NEXT: br label [[TMP1:%.*]] -; IS________OPM: 1: -; IS________OPM-NEXT: [[I_0:%.*]] = phi i32 [ 20, [[TMP0:%.*]] ], [ [[TMP4:%.*]], [[TMP5:%.*]] ] -; IS________OPM-NEXT: [[TMP2:%.*]] = sext i32 [[I_0]] to i64 -; IS________OPM-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[TMP2]] -; IS________OPM-NEXT: store i8 32, i8* [[TMP3]], align 1 -; IS________OPM-NEXT: [[TMP4]] = add nsw i32 [[I_0]], 1 -; IS________OPM-NEXT: br label [[TMP5]] -; IS________OPM: 5: -; IS________OPM-NEXT: [[TMP6:%.*]] = icmp slt i32 [[TMP4]], 30 -; IS________OPM-NEXT: br i1 [[TMP6]], label [[TMP1]], label [[TMP7:%.*]] -; IS________OPM: 7: -; IS________OPM-NEXT: ret void -; -; IS________NPM-LABEL: define {{[^@]+}}@test8 -; IS________NPM-SAME: (i8* nocapture nofree nonnull writeonly dereferenceable(21) [[PTR:%.*]]) -; IS________NPM-NEXT: br label [[TMP1:%.*]] -; IS________NPM: 1: -; IS________NPM-NEXT: [[I_0:%.*]] = phi i32 [ 20, [[TMP0:%.*]] ], [ [[TMP4:%.*]], [[TMP5:%.*]] ] -; IS________NPM-NEXT: [[TMP2:%.*]] = sext i32 [[I_0]] to i64 -; IS________NPM-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[TMP2]] -; IS________NPM-NEXT: store i8 32, i8* [[TMP3]], align 1 -; IS________NPM-NEXT: [[TMP4]] = add nsw i32 [[I_0]], 1 -; IS________NPM-NEXT: br label [[TMP5]] -; IS________NPM: 5: -; IS________NPM-NEXT: [[TMP6:%.*]] = icmp slt i32 [[TMP4]], 30 -; IS________NPM-NEXT: br i1 [[TMP6]], label [[TMP1]], label [[TMP7:%.*]] -; IS________NPM: 7: -; IS________NPM-NEXT: ret void +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind writeonly +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test8 +; IS__TUNIT_OPM-SAME: (i8* nocapture nofree nonnull writeonly [[PTR:%.*]]) +; IS__TUNIT_OPM-NEXT: br label [[TMP1:%.*]] +; IS__TUNIT_OPM: 1: +; IS__TUNIT_OPM-NEXT: [[I_0:%.*]] = phi i32 [ 20, [[TMP0:%.*]] ], [ [[TMP4:%.*]], [[TMP5:%.*]] ] +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = sext i32 [[I_0]] to i64 +; IS__TUNIT_OPM-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[TMP2]] +; IS__TUNIT_OPM-NEXT: store i8 32, i8* [[TMP3]], align 1 +; IS__TUNIT_OPM-NEXT: [[TMP4]] = add nsw i32 [[I_0]], 1 +; IS__TUNIT_OPM-NEXT: br label [[TMP5]] +; IS__TUNIT_OPM: 5: +; IS__TUNIT_OPM-NEXT: [[TMP6:%.*]] = icmp slt i32 [[TMP4]], 30 +; IS__TUNIT_OPM-NEXT: br i1 [[TMP6]], label [[TMP1]], label [[TMP7:%.*]] +; IS__TUNIT_OPM: 7: +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@test8 +; IS__TUNIT_NPM-SAME: (i8* nocapture nofree nonnull writeonly dereferenceable(21) [[PTR:%.*]]) +; IS__TUNIT_NPM-NEXT: br label [[TMP1:%.*]] +; IS__TUNIT_NPM: 1: +; IS__TUNIT_NPM-NEXT: [[I_0:%.*]] = phi i32 [ 20, [[TMP0:%.*]] ], [ [[TMP4:%.*]], [[TMP5:%.*]] ] +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = sext i32 [[I_0]] to i64 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[TMP2]] +; IS__TUNIT_NPM-NEXT: store i8 32, i8* [[TMP3]], align 1 +; IS__TUNIT_NPM-NEXT: [[TMP4]] = add nsw i32 [[I_0]], 1 +; IS__TUNIT_NPM-NEXT: br label [[TMP5]] +; IS__TUNIT_NPM: 5: +; IS__TUNIT_NPM-NEXT: [[TMP6:%.*]] = icmp slt i32 [[TMP4]], 30 +; IS__TUNIT_NPM-NEXT: br i1 [[TMP6]], label [[TMP1]], label [[TMP7:%.*]] +; IS__TUNIT_NPM: 7: +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind writeonly +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test8 +; IS__CGSCC_OPM-SAME: (i8* nocapture nofree nonnull writeonly [[PTR:%.*]]) +; IS__CGSCC_OPM-NEXT: br label [[TMP1:%.*]] +; IS__CGSCC_OPM: 1: +; IS__CGSCC_OPM-NEXT: [[I_0:%.*]] = phi i32 [ 20, [[TMP0:%.*]] ], [ [[TMP4:%.*]], [[TMP5:%.*]] ] +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = sext i32 [[I_0]] to i64 +; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[TMP2]] +; IS__CGSCC_OPM-NEXT: store i8 32, i8* [[TMP3]], align 1 +; IS__CGSCC_OPM-NEXT: [[TMP4]] = add nsw i32 [[I_0]], 1 +; IS__CGSCC_OPM-NEXT: br label [[TMP5]] +; IS__CGSCC_OPM: 5: +; IS__CGSCC_OPM-NEXT: [[TMP6:%.*]] = icmp slt i32 [[TMP4]], 30 +; IS__CGSCC_OPM-NEXT: br i1 [[TMP6]], label [[TMP1]], label [[TMP7:%.*]] +; IS__CGSCC_OPM: 7: +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test8 +; IS__CGSCC_NPM-SAME: (i8* nocapture nofree nonnull writeonly dereferenceable(21) [[PTR:%.*]]) +; IS__CGSCC_NPM-NEXT: br label [[TMP1:%.*]] +; IS__CGSCC_NPM: 1: +; IS__CGSCC_NPM-NEXT: [[I_0:%.*]] = phi i32 [ 20, [[TMP0:%.*]] ], [ [[TMP4:%.*]], [[TMP5:%.*]] ] +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = sext i32 [[I_0]] to i64 +; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[TMP2]] +; IS__CGSCC_NPM-NEXT: store i8 32, i8* [[TMP3]], align 1 +; IS__CGSCC_NPM-NEXT: [[TMP4]] = add nsw i32 [[I_0]], 1 +; IS__CGSCC_NPM-NEXT: br label [[TMP5]] +; IS__CGSCC_NPM: 5: +; IS__CGSCC_NPM-NEXT: [[TMP6:%.*]] = icmp slt i32 [[TMP4]], 30 +; IS__CGSCC_NPM-NEXT: br i1 [[TMP6]], label [[TMP1]], label [[TMP7:%.*]] +; IS__CGSCC_NPM: 7: +; IS__CGSCC_NPM-NEXT: ret void ; br label %1 1: ; preds = %5, %0 @@ -350,12 +450,21 @@ ; 8.2 (negative case) define void @test8_neg(i32 %i, i8* %ptr) #0 { -; CHECK-LABEL: define {{[^@]+}}@test8_neg -; CHECK-SAME: (i32 [[I:%.*]], i8* nocapture nofree nonnull writeonly [[PTR:%.*]]) -; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[I]] to i64 -; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[TMP1]] -; CHECK-NEXT: store i8 65, i8* [[TMP2]], align 1 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@test8_neg +; IS__TUNIT____-SAME: (i32 [[I:%.*]], i8* nocapture nofree nonnull writeonly [[PTR:%.*]]) +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = sext i32 [[I]] to i64 +; IS__TUNIT____-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[TMP1]] +; IS__TUNIT____-NEXT: store i8 65, i8* [[TMP2]], align 1 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@test8_neg +; IS__CGSCC____-SAME: (i32 [[I:%.*]], i8* nocapture nofree nonnull writeonly [[PTR:%.*]]) +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = sext i32 [[I]] to i64 +; IS__CGSCC____-NEXT: [[TMP2:%.*]] = getelementptr inbounds i8, i8* [[PTR]], i64 [[TMP1]] +; IS__CGSCC____-NEXT: store i8 65, i8* [[TMP2]], align 1 +; IS__CGSCC____-NEXT: ret void ; %1 = sext i32 %i to i64 %2 = getelementptr inbounds i8, i8* %ptr, i64 %1 @@ -372,21 +481,73 @@ ; NOTE: %p should not be dereferenceable define internal void @fill_range_not_inbounds(i32* %p, i64 %start){ -; CHECK-LABEL: define {{[^@]+}}@fill_range_not_inbounds -; CHECK-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64 [[START:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[START]], 9 -; CHECK-NEXT: br label [[FOR_BODY:%.*]] -; CHECK: for.cond.cleanup: -; CHECK-NEXT: ret void -; CHECK: for.body: -; CHECK-NEXT: [[I_06:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] -; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[I_06]] to i32 -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, i32* [[P]], i64 [[I_06]] -; CHECK-NEXT: store i32 [[CONV]], i32* [[ARRAYIDX]], align 4 -; CHECK-NEXT: [[INC]] = add nsw i64 [[I_06]], 1 -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[I_06]], [[TMP0]] -; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]] +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind writeonly +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@fill_range_not_inbounds +; IS__TUNIT_OPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64 [[START:%.*]]) +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = add nsw i64 [[START]], 9 +; IS__TUNIT_OPM-NEXT: br label [[FOR_BODY:%.*]] +; IS__TUNIT_OPM: for.cond.cleanup: +; IS__TUNIT_OPM-NEXT: ret void +; IS__TUNIT_OPM: for.body: +; IS__TUNIT_OPM-NEXT: [[I_06:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] +; IS__TUNIT_OPM-NEXT: [[CONV:%.*]] = trunc i64 [[I_06]] to i32 +; IS__TUNIT_OPM-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, i32* [[P]], i64 [[I_06]] +; IS__TUNIT_OPM-NEXT: store i32 [[CONV]], i32* [[ARRAYIDX]], align 4 +; IS__TUNIT_OPM-NEXT: [[INC]] = add nsw i64 [[I_06]], 1 +; IS__TUNIT_OPM-NEXT: [[CMP:%.*]] = icmp slt i64 [[I_06]], [[TMP0]] +; IS__TUNIT_OPM-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]] +; +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@fill_range_not_inbounds +; IS__TUNIT_NPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64 [[START:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = add nsw i64 [[START]], 9 +; IS__TUNIT_NPM-NEXT: br label [[FOR_BODY:%.*]] +; IS__TUNIT_NPM: for.cond.cleanup: +; IS__TUNIT_NPM-NEXT: ret void +; IS__TUNIT_NPM: for.body: +; IS__TUNIT_NPM-NEXT: [[I_06:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] +; IS__TUNIT_NPM-NEXT: [[CONV:%.*]] = trunc i64 [[I_06]] to i32 +; IS__TUNIT_NPM-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, i32* [[P]], i64 [[I_06]] +; IS__TUNIT_NPM-NEXT: store i32 [[CONV]], i32* [[ARRAYIDX]], align 4 +; IS__TUNIT_NPM-NEXT: [[INC]] = add nsw i64 [[I_06]], 1 +; IS__TUNIT_NPM-NEXT: [[CMP:%.*]] = icmp slt i64 [[I_06]], [[TMP0]] +; IS__TUNIT_NPM-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]] +; +; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind writeonly +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@fill_range_not_inbounds +; IS__CGSCC_OPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64 [[START:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = add nsw i64 [[START]], 9 +; IS__CGSCC_OPM-NEXT: br label [[FOR_BODY:%.*]] +; IS__CGSCC_OPM: for.cond.cleanup: +; IS__CGSCC_OPM-NEXT: ret void +; IS__CGSCC_OPM: for.body: +; IS__CGSCC_OPM-NEXT: [[I_06:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] +; IS__CGSCC_OPM-NEXT: [[CONV:%.*]] = trunc i64 [[I_06]] to i32 +; IS__CGSCC_OPM-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, i32* [[P]], i64 [[I_06]] +; IS__CGSCC_OPM-NEXT: store i32 [[CONV]], i32* [[ARRAYIDX]], align 4 +; IS__CGSCC_OPM-NEXT: [[INC]] = add nsw i64 [[I_06]], 1 +; IS__CGSCC_OPM-NEXT: [[CMP:%.*]] = icmp slt i64 [[I_06]], [[TMP0]] +; IS__CGSCC_OPM-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]] +; +; IS__CGSCC_NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@fill_range_not_inbounds +; IS__CGSCC_NPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64 [[START:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = add nsw i64 [[START]], 9 +; IS__CGSCC_NPM-NEXT: br label [[FOR_BODY:%.*]] +; IS__CGSCC_NPM: for.cond.cleanup: +; IS__CGSCC_NPM-NEXT: ret void +; IS__CGSCC_NPM: for.body: +; IS__CGSCC_NPM-NEXT: [[I_06:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] +; IS__CGSCC_NPM-NEXT: [[CONV:%.*]] = trunc i64 [[I_06]] to i32 +; IS__CGSCC_NPM-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, i32* [[P]], i64 [[I_06]] +; IS__CGSCC_NPM-NEXT: store i32 [[CONV]], i32* [[ARRAYIDX]], align 4 +; IS__CGSCC_NPM-NEXT: [[INC]] = add nsw i64 [[I_06]], 1 +; IS__CGSCC_NPM-NEXT: [[CMP:%.*]] = icmp slt i64 [[I_06]], [[TMP0]] +; IS__CGSCC_NPM-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]] ; entry: %0 = add nsw i64 %start, 9 @@ -407,21 +568,73 @@ ; FIXME: %p should be dereferenceable(40) define internal void @fill_range_inbounds(i32* %p, i64 %start){ -; CHECK-LABEL: define {{[^@]+}}@fill_range_inbounds -; CHECK-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64 [[START:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = add nsw i64 [[START]], 9 -; CHECK-NEXT: br label [[FOR_BODY:%.*]] -; CHECK: for.cond.cleanup: -; CHECK-NEXT: ret void -; CHECK: for.body: -; CHECK-NEXT: [[I_06:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] -; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[I_06]] to i32 -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 [[I_06]] -; CHECK-NEXT: store i32 [[CONV]], i32* [[ARRAYIDX]], align 4 -; CHECK-NEXT: [[INC]] = add nsw i64 [[I_06]], 1 -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[I_06]], [[TMP0]] -; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]] +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind writeonly +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@fill_range_inbounds +; IS__TUNIT_OPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64 [[START:%.*]]) +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = add nsw i64 [[START]], 9 +; IS__TUNIT_OPM-NEXT: br label [[FOR_BODY:%.*]] +; IS__TUNIT_OPM: for.cond.cleanup: +; IS__TUNIT_OPM-NEXT: ret void +; IS__TUNIT_OPM: for.body: +; IS__TUNIT_OPM-NEXT: [[I_06:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] +; IS__TUNIT_OPM-NEXT: [[CONV:%.*]] = trunc i64 [[I_06]] to i32 +; IS__TUNIT_OPM-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 [[I_06]] +; IS__TUNIT_OPM-NEXT: store i32 [[CONV]], i32* [[ARRAYIDX]], align 4 +; IS__TUNIT_OPM-NEXT: [[INC]] = add nsw i64 [[I_06]], 1 +; IS__TUNIT_OPM-NEXT: [[CMP:%.*]] = icmp slt i64 [[I_06]], [[TMP0]] +; IS__TUNIT_OPM-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]] +; +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@fill_range_inbounds +; IS__TUNIT_NPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64 [[START:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = add nsw i64 [[START]], 9 +; IS__TUNIT_NPM-NEXT: br label [[FOR_BODY:%.*]] +; IS__TUNIT_NPM: for.cond.cleanup: +; IS__TUNIT_NPM-NEXT: ret void +; IS__TUNIT_NPM: for.body: +; IS__TUNIT_NPM-NEXT: [[I_06:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] +; IS__TUNIT_NPM-NEXT: [[CONV:%.*]] = trunc i64 [[I_06]] to i32 +; IS__TUNIT_NPM-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 [[I_06]] +; IS__TUNIT_NPM-NEXT: store i32 [[CONV]], i32* [[ARRAYIDX]], align 4 +; IS__TUNIT_NPM-NEXT: [[INC]] = add nsw i64 [[I_06]], 1 +; IS__TUNIT_NPM-NEXT: [[CMP:%.*]] = icmp slt i64 [[I_06]], [[TMP0]] +; IS__TUNIT_NPM-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]] +; +; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind writeonly +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@fill_range_inbounds +; IS__CGSCC_OPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64 [[START:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = add nsw i64 [[START]], 9 +; IS__CGSCC_OPM-NEXT: br label [[FOR_BODY:%.*]] +; IS__CGSCC_OPM: for.cond.cleanup: +; IS__CGSCC_OPM-NEXT: ret void +; IS__CGSCC_OPM: for.body: +; IS__CGSCC_OPM-NEXT: [[I_06:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] +; IS__CGSCC_OPM-NEXT: [[CONV:%.*]] = trunc i64 [[I_06]] to i32 +; IS__CGSCC_OPM-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 [[I_06]] +; IS__CGSCC_OPM-NEXT: store i32 [[CONV]], i32* [[ARRAYIDX]], align 4 +; IS__CGSCC_OPM-NEXT: [[INC]] = add nsw i64 [[I_06]], 1 +; IS__CGSCC_OPM-NEXT: [[CMP:%.*]] = icmp slt i64 [[I_06]], [[TMP0]] +; IS__CGSCC_OPM-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]] +; +; IS__CGSCC_NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@fill_range_inbounds +; IS__CGSCC_NPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64 [[START:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = add nsw i64 [[START]], 9 +; IS__CGSCC_NPM-NEXT: br label [[FOR_BODY:%.*]] +; IS__CGSCC_NPM: for.cond.cleanup: +; IS__CGSCC_NPM-NEXT: ret void +; IS__CGSCC_NPM: for.body: +; IS__CGSCC_NPM-NEXT: [[I_06:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] +; IS__CGSCC_NPM-NEXT: [[CONV:%.*]] = trunc i64 [[I_06]] to i32 +; IS__CGSCC_NPM-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 [[I_06]] +; IS__CGSCC_NPM-NEXT: store i32 [[CONV]], i32* [[ARRAYIDX]], align 4 +; IS__CGSCC_NPM-NEXT: [[INC]] = add nsw i64 [[I_06]], 1 +; IS__CGSCC_NPM-NEXT: [[CMP:%.*]] = icmp slt i64 [[I_06]], [[TMP0]] +; IS__CGSCC_NPM-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]] ; entry: %0 = add nsw i64 %start, 9 @@ -441,13 +654,41 @@ } define void @call_fill_range(i32* nocapture %p, i64* nocapture readonly %range) { -; CHECK-LABEL: define {{[^@]+}}@call_fill_range -; CHECK-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[RANGE:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* [[RANGE]], align 8, !range !0 -; CHECK-NEXT: tail call void @fill_range_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) -; CHECK-NEXT: tail call void @fill_range_not_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) -; CHECK-NEXT: ret void +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@call_fill_range +; IS__TUNIT_OPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[RANGE:%.*]]) +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = load i64, i64* [[RANGE]], align 8, !range !0 +; IS__TUNIT_OPM-NEXT: tail call void @fill_range_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) +; IS__TUNIT_OPM-NEXT: tail call void @fill_range_not_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@call_fill_range +; IS__TUNIT_NPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[RANGE:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i64, i64* [[RANGE]], align 8, !range !0 +; IS__TUNIT_NPM-NEXT: tail call void @fill_range_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) +; IS__TUNIT_NPM-NEXT: tail call void @fill_range_not_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@call_fill_range +; IS__CGSCC_OPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[RANGE:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = load i64, i64* [[RANGE]], align 8, !range !0 +; IS__CGSCC_OPM-NEXT: tail call void @fill_range_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) +; IS__CGSCC_OPM-NEXT: tail call void @fill_range_not_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@call_fill_range +; IS__CGSCC_NPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[RANGE:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = load i64, i64* [[RANGE]], align 8, !range !0 +; IS__CGSCC_NPM-NEXT: tail call void @fill_range_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) +; IS__CGSCC_NPM-NEXT: tail call void @fill_range_not_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) +; IS__CGSCC_NPM-NEXT: ret void ; entry: %0 = load i64, i64* %range, align 8, !range !0 @@ -468,6 +709,7 @@ ; fun2(dereferenceable(4) %a, %b) ; We can say that %a is dereferenceable(4) but %b is not. define void @simple-path(i8* %a, i8 * %b, i8 %c) { +; CHECK: Function Attrs: nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@simple-path ; CHECK-SAME: (i8* nonnull dereferenceable(4) [[A:%.*]], i8* [[B:%.*]], i8 [[C:%.*]]) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[C]], 0 @@ -502,6 +744,7 @@ ; } ; %a is dereferenceable(12) define void @complex-path(i8* %a, i8* %b, i8 %c) { +; CHECK: Function Attrs: nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@complex-path ; CHECK-SAME: (i8* nonnull dereferenceable(12) [[A:%.*]], i8* nocapture nofree readnone [[B:%.*]], i8 [[C:%.*]]) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[C]], 0 @@ -547,31 +790,59 @@ ; ; FIXME: %ptr should be dereferenceable(4) define dso_local void @rec-branch-1(i32 %a, i32 %b, i32 %c, i32* %ptr) { -; CHECK-LABEL: define {{[^@]+}}@rec-branch-1 -; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32* nocapture nofree writeonly [[PTR:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A]], 0 -; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_ELSE3:%.*]], label [[IF_THEN:%.*]] -; CHECK: if.then: -; CHECK-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[B]], 0 -; CHECK-NEXT: br i1 [[TOBOOL1]], label [[IF_ELSE:%.*]], label [[IF_THEN2:%.*]] -; CHECK: if.then2: -; CHECK-NEXT: store i32 1, i32* [[PTR]], align 4 -; CHECK-NEXT: br label [[IF_END8:%.*]] -; CHECK: if.else: -; CHECK-NEXT: store i32 2, i32* [[PTR]], align 4 -; CHECK-NEXT: br label [[IF_END8]] -; CHECK: if.else3: -; CHECK-NEXT: [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 0 -; CHECK-NEXT: br i1 [[TOBOOL4]], label [[IF_ELSE6:%.*]], label [[IF_THEN5:%.*]] -; CHECK: if.then5: -; CHECK-NEXT: store i32 3, i32* [[PTR]], align 4 -; CHECK-NEXT: br label [[IF_END8]] -; CHECK: if.else6: -; CHECK-NEXT: store i32 4, i32* [[PTR]], align 4 -; CHECK-NEXT: br label [[IF_END8]] -; CHECK: if.end8: -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@rec-branch-1 +; IS__TUNIT____-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32* nocapture nofree writeonly [[PTR:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A]], 0 +; IS__TUNIT____-NEXT: br i1 [[TOBOOL]], label [[IF_ELSE3:%.*]], label [[IF_THEN:%.*]] +; IS__TUNIT____: if.then: +; IS__TUNIT____-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[B]], 0 +; IS__TUNIT____-NEXT: br i1 [[TOBOOL1]], label [[IF_ELSE:%.*]], label [[IF_THEN2:%.*]] +; IS__TUNIT____: if.then2: +; IS__TUNIT____-NEXT: store i32 1, i32* [[PTR]], align 4 +; IS__TUNIT____-NEXT: br label [[IF_END8:%.*]] +; IS__TUNIT____: if.else: +; IS__TUNIT____-NEXT: store i32 2, i32* [[PTR]], align 4 +; IS__TUNIT____-NEXT: br label [[IF_END8]] +; IS__TUNIT____: if.else3: +; IS__TUNIT____-NEXT: [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 0 +; IS__TUNIT____-NEXT: br i1 [[TOBOOL4]], label [[IF_ELSE6:%.*]], label [[IF_THEN5:%.*]] +; IS__TUNIT____: if.then5: +; IS__TUNIT____-NEXT: store i32 3, i32* [[PTR]], align 4 +; IS__TUNIT____-NEXT: br label [[IF_END8]] +; IS__TUNIT____: if.else6: +; IS__TUNIT____-NEXT: store i32 4, i32* [[PTR]], align 4 +; IS__TUNIT____-NEXT: br label [[IF_END8]] +; IS__TUNIT____: if.end8: +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@rec-branch-1 +; IS__CGSCC____-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32* nocapture nofree writeonly [[PTR:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[A]], 0 +; IS__CGSCC____-NEXT: br i1 [[TOBOOL]], label [[IF_ELSE3:%.*]], label [[IF_THEN:%.*]] +; IS__CGSCC____: if.then: +; IS__CGSCC____-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[B]], 0 +; IS__CGSCC____-NEXT: br i1 [[TOBOOL1]], label [[IF_ELSE:%.*]], label [[IF_THEN2:%.*]] +; IS__CGSCC____: if.then2: +; IS__CGSCC____-NEXT: store i32 1, i32* [[PTR]], align 4 +; IS__CGSCC____-NEXT: br label [[IF_END8:%.*]] +; IS__CGSCC____: if.else: +; IS__CGSCC____-NEXT: store i32 2, i32* [[PTR]], align 4 +; IS__CGSCC____-NEXT: br label [[IF_END8]] +; IS__CGSCC____: if.else3: +; IS__CGSCC____-NEXT: [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 0 +; IS__CGSCC____-NEXT: br i1 [[TOBOOL4]], label [[IF_ELSE6:%.*]], label [[IF_THEN5:%.*]] +; IS__CGSCC____: if.then5: +; IS__CGSCC____-NEXT: store i32 3, i32* [[PTR]], align 4 +; IS__CGSCC____-NEXT: br label [[IF_END8]] +; IS__CGSCC____: if.else6: +; IS__CGSCC____-NEXT: store i32 4, i32* [[PTR]], align 4 +; IS__CGSCC____-NEXT: br label [[IF_END8]] +; IS__CGSCC____: if.end8: +; IS__CGSCC____-NEXT: ret void ; entry: %tobool = icmp eq i32 %a, 0 @@ -620,6 +891,7 @@ ; } ; FIXME: %ptr should be dereferenceable(4) define dso_local void @rec-branch-2(i32 %a, i32 %b, i32 %c, i32* %ptr) { +; CHECK: Function Attrs: argmemonly nofree nosync nounwind writeonly ; CHECK-LABEL: define {{[^@]+}}@rec-branch-2 ; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[C:%.*]], i32* nocapture nofree writeonly [[PTR:%.*]]) ; CHECK-NEXT: entry: diff --git a/llvm/test/Transforms/Attributor/dereferenceable-2.ll b/llvm/test/Transforms/Attributor/dereferenceable-2.ll --- a/llvm/test/Transforms/Attributor/dereferenceable-2.ll +++ b/llvm/test/Transforms/Attributor/dereferenceable-2.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -8,21 +8,39 @@ ; https://bugs.llvm.org/show_bug.cgi?id=21780 define <4 x double> @PR21780(double* %ptr) { -; CHECK-LABEL: define {{[^@]+}}@PR21780 -; CHECK-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) -; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 1 -; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 2 -; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 3 -; CHECK-NEXT: [[T0:%.*]] = load double, double* [[PTR]], align 8 -; CHECK-NEXT: [[T1:%.*]] = load double, double* [[ARRAYIDX1]], align 8 -; CHECK-NEXT: [[T2:%.*]] = load double, double* [[ARRAYIDX2]], align 8 -; CHECK-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 -; CHECK-NEXT: [[VECINIT0:%.*]] = insertelement <4 x double> undef, double [[T0]], i32 0 -; CHECK-NEXT: [[VECINIT1:%.*]] = insertelement <4 x double> [[VECINIT0]], double [[T1]], i32 1 -; CHECK-NEXT: [[VECINIT2:%.*]] = insertelement <4 x double> [[VECINIT1]], double [[T2]], i32 2 -; CHECK-NEXT: [[VECINIT3:%.*]] = insertelement <4 x double> [[VECINIT2]], double [[T3]], i32 3 -; CHECK-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x double> [[VECINIT3]], <4 x double> [[VECINIT3]], <4 x i32> -; CHECK-NEXT: ret <4 x double> [[SHUFFLE]] +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@PR21780 +; IS__TUNIT____-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) +; IS__TUNIT____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 1 +; IS__TUNIT____-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 2 +; IS__TUNIT____-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 3 +; IS__TUNIT____-NEXT: [[T0:%.*]] = load double, double* [[PTR]], align 8 +; IS__TUNIT____-NEXT: [[T1:%.*]] = load double, double* [[ARRAYIDX1]], align 8 +; IS__TUNIT____-NEXT: [[T2:%.*]] = load double, double* [[ARRAYIDX2]], align 8 +; IS__TUNIT____-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 +; IS__TUNIT____-NEXT: [[VECINIT0:%.*]] = insertelement <4 x double> undef, double [[T0]], i32 0 +; IS__TUNIT____-NEXT: [[VECINIT1:%.*]] = insertelement <4 x double> [[VECINIT0]], double [[T1]], i32 1 +; IS__TUNIT____-NEXT: [[VECINIT2:%.*]] = insertelement <4 x double> [[VECINIT1]], double [[T2]], i32 2 +; IS__TUNIT____-NEXT: [[VECINIT3:%.*]] = insertelement <4 x double> [[VECINIT2]], double [[T3]], i32 3 +; IS__TUNIT____-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x double> [[VECINIT3]], <4 x double> [[VECINIT3]], <4 x i32> +; IS__TUNIT____-NEXT: ret <4 x double> [[SHUFFLE]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@PR21780 +; IS__CGSCC____-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) +; IS__CGSCC____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 1 +; IS__CGSCC____-NEXT: [[ARRAYIDX2:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 2 +; IS__CGSCC____-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 3 +; IS__CGSCC____-NEXT: [[T0:%.*]] = load double, double* [[PTR]], align 8 +; IS__CGSCC____-NEXT: [[T1:%.*]] = load double, double* [[ARRAYIDX1]], align 8 +; IS__CGSCC____-NEXT: [[T2:%.*]] = load double, double* [[ARRAYIDX2]], align 8 +; IS__CGSCC____-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 +; IS__CGSCC____-NEXT: [[VECINIT0:%.*]] = insertelement <4 x double> undef, double [[T0]], i32 0 +; IS__CGSCC____-NEXT: [[VECINIT1:%.*]] = insertelement <4 x double> [[VECINIT0]], double [[T1]], i32 1 +; IS__CGSCC____-NEXT: [[VECINIT2:%.*]] = insertelement <4 x double> [[VECINIT1]], double [[T2]], i32 2 +; IS__CGSCC____-NEXT: [[VECINIT3:%.*]] = insertelement <4 x double> [[VECINIT2]], double [[T3]], i32 3 +; IS__CGSCC____-NEXT: [[SHUFFLE:%.*]] = shufflevector <4 x double> [[VECINIT3]], <4 x double> [[VECINIT3]], <4 x i32> +; IS__CGSCC____-NEXT: ret <4 x double> [[SHUFFLE]] ; ; GEP of index 0 is simplified away. @@ -45,11 +63,19 @@ define double @PR21780_only_access3_with_inbounds(double* %ptr) { -; CHECK-LABEL: define {{[^@]+}}@PR21780_only_access3_with_inbounds -; CHECK-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) -; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 3 -; CHECK-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 -; CHECK-NEXT: ret double [[T3]] +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@PR21780_only_access3_with_inbounds +; IS__TUNIT____-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) +; IS__TUNIT____-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 3 +; IS__TUNIT____-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 +; IS__TUNIT____-NEXT: ret double [[T3]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@PR21780_only_access3_with_inbounds +; IS__CGSCC____-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) +; IS__CGSCC____-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds double, double* [[PTR]], i64 3 +; IS__CGSCC____-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 +; IS__CGSCC____-NEXT: ret double [[T3]] ; %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3 @@ -58,11 +84,19 @@ } define double @PR21780_only_access3_without_inbounds(double* %ptr) { -; CHECK-LABEL: define {{[^@]+}}@PR21780_only_access3_without_inbounds -; CHECK-SAME: (double* nocapture nofree readonly align 8 [[PTR:%.*]]) -; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr double, double* [[PTR]], i64 3 -; CHECK-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 -; CHECK-NEXT: ret double [[T3]] +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@PR21780_only_access3_without_inbounds +; IS__TUNIT____-SAME: (double* nocapture nofree readonly align 8 [[PTR:%.*]]) +; IS__TUNIT____-NEXT: [[ARRAYIDX3:%.*]] = getelementptr double, double* [[PTR]], i64 3 +; IS__TUNIT____-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 +; IS__TUNIT____-NEXT: ret double [[T3]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@PR21780_only_access3_without_inbounds +; IS__CGSCC____-SAME: (double* nocapture nofree readonly align 8 [[PTR:%.*]]) +; IS__CGSCC____-NEXT: [[ARRAYIDX3:%.*]] = getelementptr double, double* [[PTR]], i64 3 +; IS__CGSCC____-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 +; IS__CGSCC____-NEXT: ret double [[T3]] ; %arrayidx3 = getelementptr double, double* %ptr, i64 3 %t3 = load double, double* %arrayidx3, align 8 @@ -70,11 +104,19 @@ } define double @PR21780_without_inbounds(double* %ptr) { -; CHECK-LABEL: define {{[^@]+}}@PR21780_without_inbounds -; CHECK-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) -; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr double, double* [[PTR]], i64 3 -; CHECK-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 -; CHECK-NEXT: ret double [[T3]] +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@PR21780_without_inbounds +; IS__TUNIT____-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) +; IS__TUNIT____-NEXT: [[ARRAYIDX3:%.*]] = getelementptr double, double* [[PTR]], i64 3 +; IS__TUNIT____-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 +; IS__TUNIT____-NEXT: ret double [[T3]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@PR21780_without_inbounds +; IS__CGSCC____-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(32) [[PTR:%.*]]) +; IS__CGSCC____-NEXT: [[ARRAYIDX3:%.*]] = getelementptr double, double* [[PTR]], i64 3 +; IS__CGSCC____-NEXT: [[T3:%.*]] = load double, double* [[ARRAYIDX3]], align 8 +; IS__CGSCC____-NEXT: ret double [[T3]] ; %arrayidx1 = getelementptr double, double* %ptr, i64 1 @@ -92,12 +134,21 @@ ; Unsimplified, but still valid. Also, throw in some bogus arguments. define void @gep0(i8* %unused, i8* %other, i8* %ptr) { -; CHECK-LABEL: define {{[^@]+}}@gep0 -; CHECK-SAME: (i8* nocapture nofree readnone [[UNUSED:%.*]], i8* nocapture nofree nonnull writeonly dereferenceable(1) [[OTHER:%.*]], i8* nocapture nofree nonnull readonly dereferenceable(3) [[PTR:%.*]]) -; CHECK-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, i8* [[PTR]], i64 2 -; CHECK-NEXT: [[T2:%.*]] = load i8, i8* [[ARRAYIDX2]], align 1 -; CHECK-NEXT: store i8 [[T2]], i8* [[OTHER]], align 1 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@gep0 +; IS__TUNIT____-SAME: (i8* nocapture nofree readnone [[UNUSED:%.*]], i8* nocapture nofree nonnull writeonly dereferenceable(1) [[OTHER:%.*]], i8* nocapture nofree nonnull readonly dereferenceable(3) [[PTR:%.*]]) +; IS__TUNIT____-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, i8* [[PTR]], i64 2 +; IS__TUNIT____-NEXT: [[T2:%.*]] = load i8, i8* [[ARRAYIDX2]], align 1 +; IS__TUNIT____-NEXT: store i8 [[T2]], i8* [[OTHER]], align 1 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@gep0 +; IS__CGSCC____-SAME: (i8* nocapture nofree readnone [[UNUSED:%.*]], i8* nocapture nofree nonnull writeonly dereferenceable(1) [[OTHER:%.*]], i8* nocapture nofree nonnull readonly dereferenceable(3) [[PTR:%.*]]) +; IS__CGSCC____-NEXT: [[ARRAYIDX2:%.*]] = getelementptr i8, i8* [[PTR]], i64 2 +; IS__CGSCC____-NEXT: [[T2:%.*]] = load i8, i8* [[ARRAYIDX2]], align 1 +; IS__CGSCC____-NEXT: store i8 [[T2]], i8* [[OTHER]], align 1 +; IS__CGSCC____-NEXT: ret void ; %arrayidx0 = getelementptr i8, i8* %ptr, i64 0 %arrayidx1 = getelementptr i8, i8* %ptr, i64 1 @@ -113,9 +164,15 @@ ; Multiple arguments may be dereferenceable. define void @ordering(i8* %ptr1, i32* %ptr2) { -; CHECK-LABEL: define {{[^@]+}}@ordering -; CHECK-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(3) [[PTR1:%.*]], i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR2:%.*]]) -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@ordering +; IS__TUNIT____-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(3) [[PTR1:%.*]], i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR2:%.*]]) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@ordering +; IS__CGSCC____-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(3) [[PTR1:%.*]], i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR2:%.*]]) +; IS__CGSCC____-NEXT: ret void ; %a20 = getelementptr i32, i32* %ptr2, i64 0 %a12 = getelementptr i8, i8* %ptr1, i64 2 @@ -133,12 +190,21 @@ ; Not in entry block. define void @not_entry_but_guaranteed_to_execute(i8* %ptr) { -; CHECK-LABEL: define {{[^@]+}}@not_entry_but_guaranteed_to_execute -; CHECK-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(3) [[PTR:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[EXIT:%.*]] -; CHECK: exit: -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@not_entry_but_guaranteed_to_execute +; IS__TUNIT____-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(3) [[PTR:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: br label [[EXIT:%.*]] +; IS__TUNIT____: exit: +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@not_entry_but_guaranteed_to_execute +; IS__CGSCC____-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(3) [[PTR:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br label [[EXIT:%.*]] +; IS__CGSCC____: exit: +; IS__CGSCC____-NEXT: ret void ; entry: br label %exit @@ -155,14 +221,25 @@ ; Not in entry block and not guaranteed to execute. define void @not_entry_not_guaranteed_to_execute(i8* %ptr, i1 %cond) { -; CHECK-LABEL: define {{[^@]+}}@not_entry_not_guaranteed_to_execute -; CHECK-SAME: (i8* nocapture nofree readnone [[PTR:%.*]], i1 [[COND:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]] -; CHECK: loads: -; CHECK-NEXT: ret void -; CHECK: exit: -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@not_entry_not_guaranteed_to_execute +; IS__TUNIT____-SAME: (i8* nocapture nofree readnone [[PTR:%.*]], i1 [[COND:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]] +; IS__TUNIT____: loads: +; IS__TUNIT____-NEXT: ret void +; IS__TUNIT____: exit: +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@not_entry_not_guaranteed_to_execute +; IS__CGSCC____-SAME: (i8* nocapture nofree readnone [[PTR:%.*]], i1 [[COND:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]] +; IS__CGSCC____: loads: +; IS__CGSCC____-NEXT: ret void +; IS__CGSCC____: exit: +; IS__CGSCC____-NEXT: ret void ; entry: br i1 %cond, label %loads, label %exit @@ -181,14 +258,25 @@ ; The last load may not execute, so derefenceable bytes only covers the 1st two loads. define void @partial_in_entry(i16* %ptr, i1 %cond) { -; CHECK-LABEL: define {{[^@]+}}@partial_in_entry -; CHECK-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(4) [[PTR:%.*]], i1 [[COND:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]] -; CHECK: loads: -; CHECK-NEXT: ret void -; CHECK: exit: -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@partial_in_entry +; IS__TUNIT____-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(4) [[PTR:%.*]], i1 [[COND:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]] +; IS__TUNIT____: loads: +; IS__TUNIT____-NEXT: ret void +; IS__TUNIT____: exit: +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@partial_in_entry +; IS__CGSCC____-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(4) [[PTR:%.*]], i1 [[COND:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br i1 [[COND]], label [[LOADS:%.*]], label [[EXIT:%.*]] +; IS__CGSCC____: loads: +; IS__CGSCC____-NEXT: ret void +; IS__CGSCC____: exit: +; IS__CGSCC____-NEXT: ret void ; entry: %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 @@ -208,11 +296,19 @@ ; The 2nd and 3rd loads may never execute. define void @volatile_is_not_dereferenceable(i16* %ptr) { -; CHECK-LABEL: define {{[^@]+}}@volatile_is_not_dereferenceable -; CHECK-SAME: (i16* nofree align 2 [[PTR:%.*]]) -; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i16, i16* [[PTR]], i64 0 -; CHECK-NEXT: [[T0:%.*]] = load volatile i16, i16* [[ARRAYIDX0]], align 2 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nounwind willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@volatile_is_not_dereferenceable +; IS__TUNIT____-SAME: (i16* nofree align 2 [[PTR:%.*]]) +; IS__TUNIT____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i16, i16* [[PTR]], i64 0 +; IS__TUNIT____-NEXT: [[T0:%.*]] = load volatile i16, i16* [[ARRAYIDX0]], align 2 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@volatile_is_not_dereferenceable +; IS__CGSCC____-SAME: (i16* nofree align 2 [[PTR:%.*]]) +; IS__CGSCC____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i16, i16* [[PTR]], i64 0 +; IS__CGSCC____-NEXT: [[T0:%.*]] = load volatile i16, i16* [[ARRAYIDX0]], align 2 +; IS__CGSCC____-NEXT: ret void ; %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 @@ -226,9 +322,15 @@ ; TODO: We should allow inference for atomic (but not volatile) ops. define void @atomic_is_alright(i16* %ptr) { -; CHECK-LABEL: define {{[^@]+}}@atomic_is_alright -; CHECK-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(6) [[PTR:%.*]]) -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@atomic_is_alright +; IS__TUNIT____-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(6) [[PTR:%.*]]) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@atomic_is_alright +; IS__CGSCC____-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(6) [[PTR:%.*]]) +; IS__CGSCC____-NEXT: ret void ; %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 @@ -260,9 +362,15 @@ ; We must have consecutive accesses. define void @variable_gep_index(i8* %unused, i8* %ptr, i64 %variable_index) { -; CHECK-LABEL: define {{[^@]+}}@variable_gep_index -; CHECK-SAME: (i8* nocapture nofree readnone [[UNUSED:%.*]], i8* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]], i64 [[VARIABLE_INDEX:%.*]]) -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@variable_gep_index +; IS__TUNIT____-SAME: (i8* nocapture nofree readnone [[UNUSED:%.*]], i8* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]], i64 [[VARIABLE_INDEX:%.*]]) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@variable_gep_index +; IS__CGSCC____-SAME: (i8* nocapture nofree readnone [[UNUSED:%.*]], i8* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]], i64 [[VARIABLE_INDEX:%.*]]) +; IS__CGSCC____-NEXT: ret void ; %arrayidx1 = getelementptr i8, i8* %ptr, i64 %variable_index %arrayidx2 = getelementptr i8, i8* %ptr, i64 2 @@ -276,9 +384,15 @@ define void @multi_index_gep(<4 x i8>* %ptr) { ; FIXME: %ptr should be dereferenceable(4) -; CHECK-LABEL: define {{[^@]+}}@multi_index_gep -; CHECK-SAME: (<4 x i8>* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]]) -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@multi_index_gep +; IS__TUNIT____-SAME: (<4 x i8>* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]]) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@multi_index_gep +; IS__CGSCC____-SAME: (<4 x i8>* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]]) +; IS__CGSCC____-NEXT: ret void ; %arrayidx00 = getelementptr <4 x i8>, <4 x i8>* %ptr, i64 0, i64 0 %t0 = load i8, i8* %arrayidx00 @@ -288,9 +402,15 @@ ; Could round weird bitwidths down? define void @not_byte_multiple(i9* %ptr) { -; CHECK-LABEL: define {{[^@]+}}@not_byte_multiple -; CHECK-SAME: (i9* nocapture nofree nonnull readnone align 2 dereferenceable(2) [[PTR:%.*]]) -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@not_byte_multiple +; IS__TUNIT____-SAME: (i9* nocapture nofree nonnull readnone align 2 dereferenceable(2) [[PTR:%.*]]) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@not_byte_multiple +; IS__CGSCC____-SAME: (i9* nocapture nofree nonnull readnone align 2 dereferenceable(2) [[PTR:%.*]]) +; IS__CGSCC____-NEXT: ret void ; %arrayidx0 = getelementptr i9, i9* %ptr, i64 0 %t0 = load i9, i9* %arrayidx0 @@ -300,9 +420,15 @@ ; Missing direct access from the pointer. define void @no_pointer_deref(i16* %ptr) { -; CHECK-LABEL: define {{[^@]+}}@no_pointer_deref -; CHECK-SAME: (i16* nocapture nofree readnone align 2 [[PTR:%.*]]) -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@no_pointer_deref +; IS__TUNIT____-SAME: (i16* nocapture nofree readnone align 2 [[PTR:%.*]]) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@no_pointer_deref +; IS__CGSCC____-SAME: (i16* nocapture nofree readnone align 2 [[PTR:%.*]]) +; IS__CGSCC____-NEXT: ret void ; %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 @@ -314,9 +440,15 @@ ; Out-of-order is ok, but missing access concludes dereferenceable range. define void @non_consecutive(i32* %ptr) { -; CHECK-LABEL: define {{[^@]+}}@non_consecutive -; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR:%.*]]) -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@non_consecutive +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR:%.*]]) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@non_consecutive +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR:%.*]]) +; IS__CGSCC____-NEXT: ret void ; %arrayidx1 = getelementptr i32, i32* %ptr, i64 1 %arrayidx0 = getelementptr i32, i32* %ptr, i64 0 @@ -330,9 +462,15 @@ ; Improve on existing dereferenceable attribute. define void @more_bytes(i32* dereferenceable(8) %ptr) { -; CHECK-LABEL: define {{[^@]+}}@more_bytes -; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@more_bytes +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@more_bytes +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) +; IS__CGSCC____-NEXT: ret void ; %arrayidx3 = getelementptr i32, i32* %ptr, i64 3 %arrayidx1 = getelementptr i32, i32* %ptr, i64 1 @@ -348,9 +486,15 @@ ; Improve on existing dereferenceable_or_null attribute. define void @more_bytes_and_not_null(i32* dereferenceable_or_null(8) %ptr) { -; CHECK-LABEL: define {{[^@]+}}@more_bytes_and_not_null -; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@more_bytes_and_not_null +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@more_bytes_and_not_null +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) +; IS__CGSCC____-NEXT: ret void ; %arrayidx3 = getelementptr i32, i32* %ptr, i64 3 %arrayidx1 = getelementptr i32, i32* %ptr, i64 1 @@ -366,9 +510,15 @@ ; But don't pessimize existing dereferenceable attribute. define void @better_bytes(i32* dereferenceable(100) %ptr) { -; CHECK-LABEL: define {{[^@]+}}@better_bytes -; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(100) [[PTR:%.*]]) -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@better_bytes +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(100) [[PTR:%.*]]) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@better_bytes +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(100) [[PTR:%.*]]) +; IS__CGSCC____-NEXT: ret void ; %arrayidx3 = getelementptr i32, i32* %ptr, i64 3 %arrayidx1 = getelementptr i32, i32* %ptr, i64 1 @@ -382,9 +532,15 @@ } define void @bitcast(i32* %arg) { -; CHECK-LABEL: define {{[^@]+}}@bitcast -; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[ARG:%.*]]) -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@bitcast +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[ARG:%.*]]) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@bitcast +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[ARG:%.*]]) +; IS__CGSCC____-NEXT: ret void ; %ptr = bitcast i32* %arg to float* %arrayidx0 = getelementptr float, float* %ptr, i64 0 @@ -395,9 +551,15 @@ } define void @bitcast_different_sizes(double* %arg1, i8* %arg2) { -; CHECK-LABEL: define {{[^@]+}}@bitcast_different_sizes -; CHECK-SAME: (double* nocapture nofree nonnull readnone align 4 dereferenceable(12) [[ARG1:%.*]], i8* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[ARG2:%.*]]) -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@bitcast_different_sizes +; IS__TUNIT____-SAME: (double* nocapture nofree nonnull readnone align 4 dereferenceable(12) [[ARG1:%.*]], i8* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[ARG2:%.*]]) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@bitcast_different_sizes +; IS__CGSCC____-SAME: (double* nocapture nofree nonnull readnone align 4 dereferenceable(12) [[ARG1:%.*]], i8* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[ARG2:%.*]]) +; IS__CGSCC____-NEXT: ret void ; %ptr1 = bitcast double* %arg1 to float* %a10 = getelementptr float, float* %ptr1, i64 0 @@ -416,9 +578,15 @@ } define void @negative_offset(i32* %arg) { -; CHECK-LABEL: define {{[^@]+}}@negative_offset -; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[ARG:%.*]]) -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@negative_offset +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[ARG:%.*]]) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@negative_offset +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[ARG:%.*]]) +; IS__CGSCC____-NEXT: ret void ; %ptr = bitcast i32* %arg to float* %arrayidx0 = getelementptr float, float* %ptr, i64 0 @@ -429,14 +597,25 @@ } define void @stores(i32* %arg) { -; CHECK-LABEL: define {{[^@]+}}@stores -; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) -; CHECK-NEXT: [[PTR:%.*]] = bitcast i32* [[ARG]] to float* -; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr float, float* [[PTR]], i64 0 -; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1 -; CHECK-NEXT: store float 1.000000e+00, float* [[ARRAYIDX0]], align 4 -; CHECK-NEXT: store float 2.000000e+00, float* [[ARRAYIDX1]], align 4 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@stores +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) +; IS__TUNIT____-NEXT: [[PTR:%.*]] = bitcast i32* [[ARG]] to float* +; IS__TUNIT____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr float, float* [[PTR]], i64 0 +; IS__TUNIT____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1 +; IS__TUNIT____-NEXT: store float 1.000000e+00, float* [[ARRAYIDX0]], align 4 +; IS__TUNIT____-NEXT: store float 2.000000e+00, float* [[ARRAYIDX1]], align 4 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@stores +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) +; IS__CGSCC____-NEXT: [[PTR:%.*]] = bitcast i32* [[ARG]] to float* +; IS__CGSCC____-NEXT: [[ARRAYIDX0:%.*]] = getelementptr float, float* [[PTR]], i64 0 +; IS__CGSCC____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1 +; IS__CGSCC____-NEXT: store float 1.000000e+00, float* [[ARRAYIDX0]], align 4 +; IS__CGSCC____-NEXT: store float 2.000000e+00, float* [[ARRAYIDX1]], align 4 +; IS__CGSCC____-NEXT: ret void ; %ptr = bitcast i32* %arg to float* %arrayidx0 = getelementptr float, float* %ptr, i64 0 @@ -447,12 +626,21 @@ } define void @load_store(i32* %arg) { -; CHECK-LABEL: define {{[^@]+}}@load_store -; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) -; CHECK-NEXT: [[PTR:%.*]] = bitcast i32* [[ARG]] to float* -; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1 -; CHECK-NEXT: store float 2.000000e+00, float* [[ARRAYIDX1]], align 4 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@load_store +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) +; IS__TUNIT____-NEXT: [[PTR:%.*]] = bitcast i32* [[ARG]] to float* +; IS__TUNIT____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1 +; IS__TUNIT____-NEXT: store float 2.000000e+00, float* [[ARRAYIDX1]], align 4 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@load_store +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) [[ARG:%.*]]) +; IS__CGSCC____-NEXT: [[PTR:%.*]] = bitcast i32* [[ARG]] to float* +; IS__CGSCC____-NEXT: [[ARRAYIDX1:%.*]] = getelementptr float, float* [[PTR]], i64 1 +; IS__CGSCC____-NEXT: store float 2.000000e+00, float* [[ARRAYIDX1]], align 4 +; IS__CGSCC____-NEXT: ret void ; %ptr = bitcast i32* %arg to float* %arrayidx0 = getelementptr float, float* %ptr, i64 0 @@ -463,12 +651,21 @@ } define void @different_size1(i32* %arg) { -; CHECK-LABEL: define {{[^@]+}}@different_size1 -; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) -; CHECK-NEXT: [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double* -; CHECK-NEXT: store double 0.000000e+00, double* [[ARG_CAST]], align 8 -; CHECK-NEXT: store i32 0, i32* [[ARG]], align 8 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@different_size1 +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) +; IS__TUNIT____-NEXT: [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double* +; IS__TUNIT____-NEXT: store double 0.000000e+00, double* [[ARG_CAST]], align 8 +; IS__TUNIT____-NEXT: store i32 0, i32* [[ARG]], align 8 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@different_size1 +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) +; IS__CGSCC____-NEXT: [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double* +; IS__CGSCC____-NEXT: store double 0.000000e+00, double* [[ARG_CAST]], align 8 +; IS__CGSCC____-NEXT: store i32 0, i32* [[ARG]], align 8 +; IS__CGSCC____-NEXT: ret void ; %arg-cast = bitcast i32* %arg to double* store double 0.000000e+00, double* %arg-cast @@ -477,12 +674,21 @@ } define void @different_size2(i32* %arg) { -; CHECK-LABEL: define {{[^@]+}}@different_size2 -; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) -; CHECK-NEXT: store i32 0, i32* [[ARG]], align 8 -; CHECK-NEXT: [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double* -; CHECK-NEXT: store double 0.000000e+00, double* [[ARG_CAST]], align 8 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@different_size2 +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) +; IS__TUNIT____-NEXT: store i32 0, i32* [[ARG]], align 8 +; IS__TUNIT____-NEXT: [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double* +; IS__TUNIT____-NEXT: store double 0.000000e+00, double* [[ARG_CAST]], align 8 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@different_size2 +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[ARG:%.*]]) +; IS__CGSCC____-NEXT: store i32 0, i32* [[ARG]], align 8 +; IS__CGSCC____-NEXT: [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double* +; IS__CGSCC____-NEXT: store double 0.000000e+00, double* [[ARG_CAST]], align 8 +; IS__CGSCC____-NEXT: ret void ; store i32 0, i32* %arg %arg-cast = bitcast i32* %arg to double* @@ -509,56 +715,111 @@ ; ; ATTRIBUTOR_CGSCC_NPM-LABEL: define i32 @require_cfg_analysis(i32 %c, i32* {{.*}} dereferenceable(4) %p) define i32 @require_cfg_analysis(i32 %c, i32* %p) { -; IS________OPM-LABEL: define {{[^@]+}}@require_cfg_analysis -; IS________OPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree writeonly [[P:%.*]]) -; IS________OPM-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0 -; IS________OPM-NEXT: br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]] -; IS________OPM: l1: -; IS________OPM-NEXT: [[TOBOOL2:%.*]] = icmp eq i32 [[C]], 1 -; IS________OPM-NEXT: br i1 [[TOBOOL2]], label [[L3:%.*]], label [[L4:%.*]] -; IS________OPM: l2: -; IS________OPM-NEXT: [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2 -; IS________OPM-NEXT: br i1 [[TOBOOL3]], label [[L3]], label [[L4]] -; IS________OPM: l3: -; IS________OPM-NEXT: br label [[L5:%.*]] -; IS________OPM: l4: -; IS________OPM-NEXT: br label [[L5]] -; IS________OPM: l5: -; IS________OPM-NEXT: [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4 -; IS________OPM-NEXT: br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]] -; IS________OPM: l6: -; IS________OPM-NEXT: store i32 0, i32* [[P]], align 4 -; IS________OPM-NEXT: br label [[END:%.*]] -; IS________OPM: l7: -; IS________OPM-NEXT: store i32 1, i32* [[P]], align 4 -; IS________OPM-NEXT: br label [[END]] -; IS________OPM: end: -; IS________OPM-NEXT: ret i32 1 -; -; IS________NPM-LABEL: define {{[^@]+}}@require_cfg_analysis -; IS________NPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) -; IS________NPM-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0 -; IS________NPM-NEXT: br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]] -; IS________NPM: l1: -; IS________NPM-NEXT: br label [[L4:%.*]] -; IS________NPM: l2: -; IS________NPM-NEXT: [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2 -; IS________NPM-NEXT: br i1 [[TOBOOL3]], label [[L3:%.*]], label [[L4]] -; IS________NPM: l3: -; IS________NPM-NEXT: br label [[L5:%.*]] -; IS________NPM: l4: -; IS________NPM-NEXT: br label [[L5]] -; IS________NPM: l5: -; IS________NPM-NEXT: [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4 -; IS________NPM-NEXT: br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]] -; IS________NPM: l6: -; IS________NPM-NEXT: store i32 0, i32* [[P]], align 4 -; IS________NPM-NEXT: br label [[END:%.*]] -; IS________NPM: l7: -; IS________NPM-NEXT: store i32 1, i32* [[P]], align 4 -; IS________NPM-NEXT: br label [[END]] -; IS________NPM: end: -; IS________NPM-NEXT: ret i32 1 +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@require_cfg_analysis +; IS__TUNIT_OPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree writeonly [[P:%.*]]) +; IS__TUNIT_OPM-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0 +; IS__TUNIT_OPM-NEXT: br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]] +; IS__TUNIT_OPM: l1: +; IS__TUNIT_OPM-NEXT: [[TOBOOL2:%.*]] = icmp eq i32 [[C]], 1 +; IS__TUNIT_OPM-NEXT: br i1 [[TOBOOL2]], label [[L3:%.*]], label [[L4:%.*]] +; IS__TUNIT_OPM: l2: +; IS__TUNIT_OPM-NEXT: [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2 +; IS__TUNIT_OPM-NEXT: br i1 [[TOBOOL3]], label [[L3]], label [[L4]] +; IS__TUNIT_OPM: l3: +; IS__TUNIT_OPM-NEXT: br label [[L5:%.*]] +; IS__TUNIT_OPM: l4: +; IS__TUNIT_OPM-NEXT: br label [[L5]] +; IS__TUNIT_OPM: l5: +; IS__TUNIT_OPM-NEXT: [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4 +; IS__TUNIT_OPM-NEXT: br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]] +; IS__TUNIT_OPM: l6: +; IS__TUNIT_OPM-NEXT: store i32 0, i32* [[P]], align 4 +; IS__TUNIT_OPM-NEXT: br label [[END:%.*]] +; IS__TUNIT_OPM: l7: +; IS__TUNIT_OPM-NEXT: store i32 1, i32* [[P]], align 4 +; IS__TUNIT_OPM-NEXT: br label [[END]] +; IS__TUNIT_OPM: end: +; IS__TUNIT_OPM-NEXT: ret i32 1 +; +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@require_cfg_analysis +; IS__TUNIT_NPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) +; IS__TUNIT_NPM-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0 +; IS__TUNIT_NPM-NEXT: br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]] +; IS__TUNIT_NPM: l1: +; IS__TUNIT_NPM-NEXT: br label [[L4:%.*]] +; IS__TUNIT_NPM: l2: +; IS__TUNIT_NPM-NEXT: [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2 +; IS__TUNIT_NPM-NEXT: br i1 [[TOBOOL3]], label [[L3:%.*]], label [[L4]] +; IS__TUNIT_NPM: l3: +; IS__TUNIT_NPM-NEXT: br label [[L5:%.*]] +; IS__TUNIT_NPM: l4: +; IS__TUNIT_NPM-NEXT: br label [[L5]] +; IS__TUNIT_NPM: l5: +; IS__TUNIT_NPM-NEXT: [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4 +; IS__TUNIT_NPM-NEXT: br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]] +; IS__TUNIT_NPM: l6: +; IS__TUNIT_NPM-NEXT: store i32 0, i32* [[P]], align 4 +; IS__TUNIT_NPM-NEXT: br label [[END:%.*]] +; IS__TUNIT_NPM: l7: +; IS__TUNIT_NPM-NEXT: store i32 1, i32* [[P]], align 4 +; IS__TUNIT_NPM-NEXT: br label [[END]] +; IS__TUNIT_NPM: end: +; IS__TUNIT_NPM-NEXT: ret i32 1 +; +; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@require_cfg_analysis +; IS__CGSCC_OPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree writeonly [[P:%.*]]) +; IS__CGSCC_OPM-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0 +; IS__CGSCC_OPM-NEXT: br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]] +; IS__CGSCC_OPM: l1: +; IS__CGSCC_OPM-NEXT: [[TOBOOL2:%.*]] = icmp eq i32 [[C]], 1 +; IS__CGSCC_OPM-NEXT: br i1 [[TOBOOL2]], label [[L3:%.*]], label [[L4:%.*]] +; IS__CGSCC_OPM: l2: +; IS__CGSCC_OPM-NEXT: [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2 +; IS__CGSCC_OPM-NEXT: br i1 [[TOBOOL3]], label [[L3]], label [[L4]] +; IS__CGSCC_OPM: l3: +; IS__CGSCC_OPM-NEXT: br label [[L5:%.*]] +; IS__CGSCC_OPM: l4: +; IS__CGSCC_OPM-NEXT: br label [[L5]] +; IS__CGSCC_OPM: l5: +; IS__CGSCC_OPM-NEXT: [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4 +; IS__CGSCC_OPM-NEXT: br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]] +; IS__CGSCC_OPM: l6: +; IS__CGSCC_OPM-NEXT: store i32 0, i32* [[P]], align 4 +; IS__CGSCC_OPM-NEXT: br label [[END:%.*]] +; IS__CGSCC_OPM: l7: +; IS__CGSCC_OPM-NEXT: store i32 1, i32* [[P]], align 4 +; IS__CGSCC_OPM-NEXT: br label [[END]] +; IS__CGSCC_OPM: end: +; IS__CGSCC_OPM-NEXT: ret i32 1 +; +; IS__CGSCC_NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@require_cfg_analysis +; IS__CGSCC_NPM-SAME: (i32 [[C:%.*]], i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) +; IS__CGSCC_NPM-NEXT: [[TOBOOL1:%.*]] = icmp eq i32 [[C]], 0 +; IS__CGSCC_NPM-NEXT: br i1 [[TOBOOL1]], label [[L1:%.*]], label [[L2:%.*]] +; IS__CGSCC_NPM: l1: +; IS__CGSCC_NPM-NEXT: br label [[L4:%.*]] +; IS__CGSCC_NPM: l2: +; IS__CGSCC_NPM-NEXT: [[TOBOOL3:%.*]] = icmp eq i32 [[C]], 2 +; IS__CGSCC_NPM-NEXT: br i1 [[TOBOOL3]], label [[L3:%.*]], label [[L4]] +; IS__CGSCC_NPM: l3: +; IS__CGSCC_NPM-NEXT: br label [[L5:%.*]] +; IS__CGSCC_NPM: l4: +; IS__CGSCC_NPM-NEXT: br label [[L5]] +; IS__CGSCC_NPM: l5: +; IS__CGSCC_NPM-NEXT: [[TOBOOL4:%.*]] = icmp eq i32 [[C]], 4 +; IS__CGSCC_NPM-NEXT: br i1 [[TOBOOL4]], label [[L6:%.*]], label [[L7:%.*]] +; IS__CGSCC_NPM: l6: +; IS__CGSCC_NPM-NEXT: store i32 0, i32* [[P]], align 4 +; IS__CGSCC_NPM-NEXT: br label [[END:%.*]] +; IS__CGSCC_NPM: l7: +; IS__CGSCC_NPM-NEXT: store i32 1, i32* [[P]], align 4 +; IS__CGSCC_NPM-NEXT: br label [[END]] +; IS__CGSCC_NPM: end: +; IS__CGSCC_NPM-NEXT: ret i32 1 ; %tobool1 = icmp eq i32 %c, 0 br i1 %tobool1, label %l1, label %l2 diff --git a/llvm/test/Transforms/Attributor/heap_to_stack.ll b/llvm/test/Transforms/Attributor/heap_to_stack.ll --- a/llvm/test/Transforms/Attributor/heap_to_stack.ll +++ b/llvm/test/Transforms/Attributor/heap_to_stack.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -287,11 +287,13 @@ ; TEST 7 - free is dead. define void @test7() { +; IS________OPM: Function Attrs: noreturn ; IS________OPM-LABEL: define {{[^@]+}}@test7() ; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) ; IS________OPM-NEXT: [[TMP2:%.*]] = tail call i32 @no_return_call() ; IS________OPM-NEXT: unreachable ; +; IS________NPM: Function Attrs: noreturn ; IS________NPM-LABEL: define {{[^@]+}}@test7() ; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4, align 1 ; IS________NPM-NEXT: [[TMP2:%.*]] = tail call i32 @no_return_call() diff --git a/llvm/test/Transforms/Attributor/internal-noalias.ll b/llvm/test/Transforms/Attributor/internal-noalias.ll --- a/llvm/test/Transforms/Attributor/internal-noalias.ll +++ b/llvm/test/Transforms/Attributor/internal-noalias.ll @@ -1,10 +1,11 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM define dso_local i32 @visible(i32* noalias %A, i32* noalias %B) #0 { +; IS__TUNIT____: Function Attrs: argmemonly nofree noinline nosync nounwind readonly uwtable willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@visible ; IS__TUNIT____-SAME: (i32* noalias nocapture nofree readonly [[A:%.*]], i32* noalias nocapture nofree readonly [[B:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -13,6 +14,7 @@ ; IS__TUNIT____-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL1]], [[CALL2]] ; IS__TUNIT____-NEXT: ret i32 [[ADD]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly uwtable willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@visible ; IS__CGSCC____-SAME: (i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A:%.*]], i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -29,6 +31,7 @@ } define private i32 @noalias_args(i32* %A, i32* %B) #0 { +; IS__TUNIT____: Function Attrs: argmemonly nofree noinline nosync nounwind readonly uwtable willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@noalias_args ; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A:%.*]], i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -39,6 +42,7 @@ ; IS__TUNIT____-NEXT: [[ADD2:%.*]] = add nsw i32 [[ADD]], [[CALL]] ; IS__TUNIT____-NEXT: ret i32 [[ADD2]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly uwtable willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@noalias_args ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A:%.*]], i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -60,6 +64,7 @@ define internal i32 @noalias_args_argmem(i32* %A, i32* %B) #1 { +; IS__TUNIT____: Function Attrs: argmemonly nofree noinline nosync nounwind readonly uwtable willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@noalias_args_argmem ; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A:%.*]], i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -68,6 +73,7 @@ ; IS__TUNIT____-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]] ; IS__TUNIT____-NEXT: ret i32 [[ADD]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly uwtable willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@noalias_args_argmem ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A:%.*]], i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -84,6 +90,7 @@ } define dso_local i32 @visible_local(i32* %A) #0 { +; IS__TUNIT____: Function Attrs: argmemonly nofree noinline nosync nounwind uwtable willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@visible_local ; IS__TUNIT____-SAME: (i32* nocapture nofree readonly [[A:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -94,6 +101,7 @@ ; IS__TUNIT____-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL1]], [[CALL2]] ; IS__TUNIT____-NEXT: ret i32 [[ADD]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind uwtable willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@visible_local ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -114,6 +122,7 @@ } define internal i32 @noalias_args_argmem_ro(i32* %A, i32* %B) #1 { +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree noinline nosync nounwind readonly uwtable willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@noalias_args_argmem_ro ; IS__TUNIT_OPM-SAME: (i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A:%.*]], i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B:%.*]]) ; IS__TUNIT_OPM-NEXT: [[T0:%.*]] = load i32, i32* [[A]], align 4 @@ -121,6 +130,7 @@ ; IS__TUNIT_OPM-NEXT: [[ADD:%.*]] = add nsw i32 [[T0]], [[T1]] ; IS__TUNIT_OPM-NEXT: ret i32 [[ADD]] ; +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree noinline nosync nounwind readonly uwtable willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@noalias_args_argmem_ro ; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) ; IS__TUNIT_NPM-NEXT: [[B_PRIV:%.*]] = alloca i32, align 4 @@ -132,6 +142,7 @@ ; IS__TUNIT_NPM-NEXT: [[ADD:%.*]] = add nsw i32 [[T0]], [[T1]] ; IS__TUNIT_NPM-NEXT: ret i32 [[ADD]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly uwtable willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@noalias_args_argmem_ro ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A:%.*]], i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B:%.*]]) ; IS__CGSCC____-NEXT: [[T0:%.*]] = load i32, i32* [[A]], align 4 @@ -146,12 +157,14 @@ } define i32 @visible_local_2() { -; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@visible_local_2() -; NOT_TUNIT_NPM-NEXT: [[B:%.*]] = alloca i32, align 4 -; NOT_TUNIT_NPM-NEXT: store i32 5, i32* [[B]], align 4 -; NOT_TUNIT_NPM-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem_ro(i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B]], i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B]]) -; NOT_TUNIT_NPM-NEXT: ret i32 [[CALL]] -; +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@visible_local_2() +; IS__TUNIT_OPM-NEXT: [[B:%.*]] = alloca i32, align 4 +; IS__TUNIT_OPM-NEXT: store i32 5, i32* [[B]], align 4 +; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem_ro(i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B]], i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B]]) +; IS__TUNIT_OPM-NEXT: ret i32 [[CALL]] +; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@visible_local_2() ; IS__TUNIT_NPM-NEXT: [[B:%.*]] = alloca i32, align 4 ; IS__TUNIT_NPM-NEXT: store i32 5, i32* [[B]], align 4 @@ -159,6 +172,13 @@ ; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[B]], align 4 ; IS__TUNIT_NPM-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem_ro(i32 [[TMP1]], i32 [[TMP2]]) ; IS__TUNIT_NPM-NEXT: ret i32 [[CALL]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@visible_local_2() +; IS__CGSCC____-NEXT: [[B:%.*]] = alloca i32, align 4 +; IS__CGSCC____-NEXT: store i32 5, i32* [[B]], align 4 +; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem_ro(i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B]], i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B]]) +; IS__CGSCC____-NEXT: ret i32 [[CALL]] ; %B = alloca i32, align 4 store i32 5, i32* %B, align 4 @@ -167,12 +187,14 @@ } define internal i32 @noalias_args_argmem_rn(i32* %A, i32* %B) #1 { +; IS__TUNIT____: Function Attrs: argmemonly nofree noinline nosync nounwind uwtable willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@noalias_args_argmem_rn ; IS__TUNIT____-SAME: (i32* noalias nocapture nofree nonnull align 4 dereferenceable(4) [[B:%.*]]) ; IS__TUNIT____-NEXT: [[T0:%.*]] = load i32, i32* [[B]], align 4 ; IS__TUNIT____-NEXT: store i32 0, i32* [[B]], align 4 ; IS__TUNIT____-NEXT: ret i32 [[T0]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind uwtable willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@noalias_args_argmem_rn ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull align 4 dereferenceable(4) [[B:%.*]]) ; IS__CGSCC____-NEXT: [[T0:%.*]] = load i32, i32* [[B]], align 4 @@ -185,11 +207,19 @@ } define i32 @visible_local_3() { -; CHECK-LABEL: define {{[^@]+}}@visible_local_3() -; CHECK-NEXT: [[B:%.*]] = alloca i32, align 4 -; CHECK-NEXT: store i32 5, i32* [[B]], align 4 -; CHECK-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem_rn(i32* noalias nocapture nofree nonnull align 4 dereferenceable(4) [[B]]) -; CHECK-NEXT: ret i32 [[CALL]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@visible_local_3() +; IS__TUNIT____-NEXT: [[B:%.*]] = alloca i32, align 4 +; IS__TUNIT____-NEXT: store i32 5, i32* [[B]], align 4 +; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem_rn(i32* noalias nocapture nofree nonnull align 4 dereferenceable(4) [[B]]) +; IS__TUNIT____-NEXT: ret i32 [[CALL]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@visible_local_3() +; IS__CGSCC____-NEXT: [[B:%.*]] = alloca i32, align 4 +; IS__CGSCC____-NEXT: store i32 5, i32* [[B]], align 4 +; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem_rn(i32* noalias nocapture nofree nonnull align 4 dereferenceable(4) [[B]]) +; IS__CGSCC____-NEXT: ret i32 [[CALL]] ; %B = alloca i32, align 4 store i32 5, i32* %B, align 4 diff --git a/llvm/test/Transforms/Attributor/liveness.ll b/llvm/test/Transforms/Attributor/liveness.ll --- a/llvm/test/Transforms/Attributor/liveness.ll +++ b/llvm/test/Transforms/Attributor/liveness.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=17 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=17 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; TODO: The old pass manager cgscc run is disabled as it causes a crash on windows which is under investigation: http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/23151 @@ -27,6 +27,7 @@ ; and nothing should be deduced for it. define internal i32 @dead_internal_func(i32 %0) { +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@dead_internal_func() ; IS__CGSCC____-NEXT: br label [[TMP2:%.*]] ; IS__CGSCC____: 1: @@ -55,8 +56,8 @@ br i1 %10, label %3, label %5 } -; CHECK: Function Attrs: argmemonly nofree norecurse nounwind uwtable willreturn define i32 @volatile_load(i32*) norecurse nounwind uwtable { +; CHECK: Function Attrs: argmemonly nofree norecurse nounwind uwtable willreturn ; CHECK-LABEL: define {{[^@]+}}@volatile_load ; CHECK-SAME: (i32* nofree align 4 [[TMP0:%.*]]) ; CHECK-NEXT: [[TMP2:%.*]] = load volatile i32, i32* [[TMP0]], align 4 @@ -67,6 +68,7 @@ } define internal i32 @internal_load(i32*) norecurse nounwind uwtable { +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone uwtable willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@internal_load() ; IS__CGSCC____-NEXT: ret i32 undef ; @@ -75,8 +77,8 @@ } ; TEST 1: Only first block is live. -; CHECK: Function Attrs: nofree noreturn nosync nounwind define i32 @first_block_no_return(i32 %a, i32* nonnull %ptr1, i32* %ptr2) #0 { +; CHECK: Function Attrs: nofree noreturn nosync nounwind ; CHECK-LABEL: define {{[^@]+}}@first_block_no_return ; CHECK-SAME: (i32 [[A:%.*]], i32* nocapture nofree nonnull readnone [[PTR1:%.*]], i32* nocapture nofree readnone [[PTR2:%.*]]) ; CHECK-NEXT: entry: @@ -118,8 +120,8 @@ ; This is just an example. For example we can put a sync call in a ; dead block and check if it is deduced. -; CHECK: Function Attrs: nosync define i32 @dead_block_present(i32 %a, i32* %ptr1) #0 { +; CHECK: Function Attrs: nosync ; CHECK-LABEL: define {{[^@]+}}@dead_block_present ; CHECK-SAME: (i32 [[A:%.*]], i32* nocapture nofree readnone [[PTR1:%.*]]) ; CHECK-NEXT: entry: @@ -157,6 +159,7 @@ ; TEST 3: both cond.true and cond.false are dead, therfore cond.end is dead as well. define i32 @all_dead(i32 %a) #0 { +; CHECK: Function Attrs: nofree noreturn nosync nounwind ; CHECK-LABEL: define {{[^@]+}}@all_dead ; CHECK-SAME: (i32 [[A:%.*]]) ; CHECK-NEXT: entry: @@ -478,13 +481,23 @@ ; FIXME: Should be able to detect undefined behavior. define void @ub(i32* %0) { -; CHECK-LABEL: define {{[^@]+}}@ub -; CHECK-SAME: (i32* nocapture nofree writeonly [[TMP0:%.*]]) -; CHECK-NEXT: [[POISON:%.*]] = sub nuw i32 0, 1 -; CHECK-NEXT: [[STILL_POISON:%.*]] = and i32 [[POISON]], 0 -; CHECK-NEXT: [[POISON_YET_AGAIN:%.*]] = getelementptr i32, i32* [[TMP0]], i32 [[STILL_POISON]] -; CHECK-NEXT: store i32 0, i32* [[POISON_YET_AGAIN]], align 4 -; CHECK-NEXT: ret void +; NOT_CGSCC_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@ub +; NOT_CGSCC_NPM-SAME: (i32* nocapture nofree writeonly [[TMP0:%.*]]) +; NOT_CGSCC_NPM-NEXT: [[POISON:%.*]] = sub nuw i32 0, 1 +; NOT_CGSCC_NPM-NEXT: [[STILL_POISON:%.*]] = and i32 [[POISON]], 0 +; NOT_CGSCC_NPM-NEXT: [[POISON_YET_AGAIN:%.*]] = getelementptr i32, i32* [[TMP0]], i32 [[STILL_POISON]] +; NOT_CGSCC_NPM-NEXT: store i32 0, i32* [[POISON_YET_AGAIN]], align 4 +; NOT_CGSCC_NPM-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@ub +; IS__CGSCC____-SAME: (i32* nocapture nofree writeonly [[TMP0:%.*]]) +; IS__CGSCC____-NEXT: [[POISON:%.*]] = sub nuw i32 0, 1 +; IS__CGSCC____-NEXT: [[STILL_POISON:%.*]] = and i32 [[POISON]], 0 +; IS__CGSCC____-NEXT: [[POISON_YET_AGAIN:%.*]] = getelementptr i32, i32* [[TMP0]], i32 [[STILL_POISON]] +; IS__CGSCC____-NEXT: store i32 0, i32* [[POISON_YET_AGAIN]], align 4 +; IS__CGSCC____-NEXT: ret void ; %poison = sub nuw i32 0, 1 ; Results in a poison value. %still_poison = and i32 %poison, 0 ; 0, but also poison. @@ -494,11 +507,19 @@ } define void @inf_loop() #0 { -; CHECK-LABEL: define {{[^@]+}}@inf_loop() -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[WHILE_BODY:%.*]] -; CHECK: while.body: -; CHECK-NEXT: br label [[WHILE_BODY]] +; NOT_CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@inf_loop() +; NOT_CGSCC_NPM-NEXT: entry: +; NOT_CGSCC_NPM-NEXT: br label [[WHILE_BODY:%.*]] +; NOT_CGSCC_NPM: while.body: +; NOT_CGSCC_NPM-NEXT: br label [[WHILE_BODY]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone +; IS__CGSCC____-LABEL: define {{[^@]+}}@inf_loop() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br label [[WHILE_BODY:%.*]] +; IS__CGSCC____: while.body: +; IS__CGSCC____-NEXT: br label [[WHILE_BODY]] ; entry: br label %while.body @@ -511,6 +532,7 @@ ; FIXME: Detect infloops, and mark affected blocks dead. define i32 @test5(i32, i32) #0 { +; CHECK: Function Attrs: nosync readnone ; CHECK-LABEL: define {{[^@]+}}@test5 ; CHECK-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) ; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP0]], [[TMP1]] @@ -547,9 +569,15 @@ } define void @rec() #0 { -; CHECK-LABEL: define {{[^@]+}}@rec() -; CHECK-NEXT: entry: -; CHECK-NEXT: unreachable +; NOT_CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone willreturn +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@rec() +; NOT_CGSCC_NPM-NEXT: entry: +; NOT_CGSCC_NPM-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@rec() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: unreachable ; entry: call void @rec() @@ -561,17 +589,31 @@ ; and unreachable should be put after call to @rec(). define i32 @test6(i32, i32) #0 { -; CHECK-LABEL: define {{[^@]+}}@test6 -; CHECK-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) -; CHECK-NEXT: unreachable -; CHECK: cond.if: -; CHECK-NEXT: unreachable -; CHECK: cond.elseif: -; CHECK-NEXT: unreachable -; CHECK: cond.else: -; CHECK-NEXT: unreachable -; CHECK: cond.end: -; CHECK-NEXT: unreachable +; NOT_CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone willreturn +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test6 +; NOT_CGSCC_NPM-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) +; NOT_CGSCC_NPM-NEXT: unreachable +; NOT_CGSCC_NPM: cond.if: +; NOT_CGSCC_NPM-NEXT: unreachable +; NOT_CGSCC_NPM: cond.elseif: +; NOT_CGSCC_NPM-NEXT: unreachable +; NOT_CGSCC_NPM: cond.else: +; NOT_CGSCC_NPM-NEXT: unreachable +; NOT_CGSCC_NPM: cond.end: +; NOT_CGSCC_NPM-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test6 +; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: cond.if: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: cond.elseif: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: cond.else: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: cond.end: +; IS__CGSCC____-NEXT: unreachable ; call void @rec() %3 = icmp sgt i32 %0, %1 @@ -738,6 +780,7 @@ declare void @sink() nofree nosync nounwind willreturn define void @test_unreachable() { +; CHECK: Function Attrs: nofree noreturn nosync nounwind ; CHECK-LABEL: define {{[^@]+}}@test_unreachable() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: call void @test_unreachable() @@ -929,6 +972,7 @@ } define internal void @non_dead_a0() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_a0() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -937,6 +981,7 @@ ret void } define internal void @non_dead_a1() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_a1() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -945,6 +990,7 @@ ret void } define internal void @non_dead_a2() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_a2() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -953,6 +999,7 @@ ret void } define internal void @non_dead_a3() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_a3() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -961,6 +1008,7 @@ ret void } define internal void @non_dead_a4() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_a4() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -969,6 +1017,7 @@ ret void } define internal void @non_dead_a5() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_a5() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -977,6 +1026,7 @@ ret void } define internal void @non_dead_a6() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_a6() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -985,6 +1035,7 @@ ret void } define internal void @non_dead_a7() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_a7() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -993,6 +1044,7 @@ ret void } define internal void @non_dead_a8() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_a8() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1001,6 +1053,7 @@ ret void } define internal void @non_dead_a9() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_a9() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1009,6 +1062,7 @@ ret void } define internal void @non_dead_a10() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_a10() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1017,6 +1071,7 @@ ret void } define internal void @non_dead_a11() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_a11() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1025,6 +1080,7 @@ ret void } define internal void @non_dead_a12() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_a12() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1033,6 +1089,7 @@ ret void } define internal void @non_dead_a13() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_a13() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1041,6 +1098,7 @@ ret void } define internal void @non_dead_a14() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_a14() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1049,6 +1107,7 @@ ret void } define internal void @non_dead_a15() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_a15() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1057,6 +1116,7 @@ ret void } define internal void @non_dead_b0() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_b0() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1065,6 +1125,7 @@ ret void } define internal void @non_dead_b1() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_b1() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1073,6 +1134,7 @@ ret void } define internal void @non_dead_b2() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_b2() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1081,6 +1143,7 @@ ret void } define internal void @non_dead_b3() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_b3() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1089,6 +1152,7 @@ ret void } define internal void @non_dead_b4() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_b4() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1097,6 +1161,7 @@ ret void } define internal void @non_dead_b5() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_b5() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1105,6 +1170,7 @@ ret void } define internal void @non_dead_b6() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_b6() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1113,6 +1179,7 @@ ret void } define internal void @non_dead_b7() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_b7() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1121,6 +1188,7 @@ ret void } define internal void @non_dead_b8() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_b8() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1129,6 +1197,7 @@ ret void } define internal void @non_dead_b9() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_b9() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1137,6 +1206,7 @@ ret void } define internal void @non_dead_b10() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_b10() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1145,6 +1215,7 @@ ret void } define internal void @non_dead_b11() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_b11() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1153,6 +1224,7 @@ ret void } define internal void @non_dead_b12() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_b12() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1161,6 +1233,7 @@ ret void } define internal void @non_dead_b13() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_b13() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1169,6 +1242,7 @@ ret void } define internal void @non_dead_b14() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_b14() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1177,6 +1251,7 @@ ret void } define internal void @non_dead_b15() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_b15() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1185,6 +1260,7 @@ ret void } define internal void @non_dead_c0() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_c0() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1193,6 +1269,7 @@ ret void } define internal void @non_dead_c1() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_c1() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1201,6 +1278,7 @@ ret void } define internal void @non_dead_c2() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_c2() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1209,6 +1287,7 @@ ret void } define internal void @non_dead_c3() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_c3() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1217,6 +1296,7 @@ ret void } define internal void @non_dead_c4() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_c4() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1225,6 +1305,7 @@ ret void } define internal void @non_dead_c5() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_c5() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1233,6 +1314,7 @@ ret void } define internal void @non_dead_c6() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_c6() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1241,6 +1323,7 @@ ret void } define internal void @non_dead_c7() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_c7() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1249,6 +1332,7 @@ ret void } define internal void @non_dead_c8() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_c8() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1257,6 +1341,7 @@ ret void } define internal void @non_dead_c9() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_c9() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1265,6 +1350,7 @@ ret void } define internal void @non_dead_c10() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_c10() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1273,6 +1359,7 @@ ret void } define internal void @non_dead_c11() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_c11() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1281,6 +1368,7 @@ ret void } define internal void @non_dead_c12() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_c12() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1289,6 +1377,7 @@ ret void } define internal void @non_dead_c13() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_c13() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1297,6 +1386,7 @@ ret void } define internal void @non_dead_c14() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_c14() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1305,6 +1395,7 @@ ret void } define internal void @non_dead_c15() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_c15() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1313,6 +1404,7 @@ ret void } define internal void @non_dead_d0() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_d0() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1321,6 +1413,7 @@ ret void } define internal void @non_dead_d1() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_d1() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1329,6 +1422,7 @@ ret void } define internal void @non_dead_d2() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_d2() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1337,6 +1431,7 @@ ret void } define internal void @non_dead_d3() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_d3() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1345,6 +1440,7 @@ ret void } define internal void @non_dead_d4() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_d4() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1353,6 +1449,7 @@ ret void } define internal void @non_dead_d5() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_d5() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1361,6 +1458,7 @@ ret void } define internal void @non_dead_d6() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_d6() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1369,6 +1467,7 @@ ret void } define internal void @non_dead_d7() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_d7() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1377,6 +1476,7 @@ ret void } define internal void @non_dead_d8() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_d8() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1385,6 +1485,7 @@ ret void } define internal void @non_dead_d9() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_d9() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1393,6 +1494,7 @@ ret void } define internal void @non_dead_d10() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_d10() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1401,6 +1503,7 @@ ret void } define internal void @non_dead_d11() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_d11() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1409,6 +1512,7 @@ ret void } define internal void @non_dead_d12() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_d12() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1417,6 +1521,7 @@ ret void } define internal void @non_dead_d13() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_d13() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1425,6 +1530,7 @@ ret void } define internal void @non_dead_d14() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_d14() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1433,6 +1539,7 @@ ret void } define internal void @non_dead_d15() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@non_dead_d15() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1462,6 +1569,7 @@ } define void @live_with_dead_entry_lp() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +; CHECK: Function Attrs: nounwind ; CHECK-LABEL: define {{[^@]+}}@live_with_dead_entry_lp() #2 personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) ; CHECK-NEXT: entry: ; CHECK-NEXT: invoke void @blowup() @@ -1495,6 +1603,7 @@ } define internal void @useless_arg_sink(i32* %a) { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@useless_arg_sink() ; CHECK-NEXT: call void @sink() ; CHECK-NEXT: ret void @@ -1504,6 +1613,7 @@ } define internal void @useless_arg_almost_sink(i32* %a) { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@useless_arg_almost_sink() ; CHECK-NEXT: call void @useless_arg_sink() ; CHECK-NEXT: ret void @@ -1546,6 +1656,7 @@ ; FIXME: We should fold terminators. define internal i32 @switch_default(i64 %i) nounwind { +; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@switch_default() ; NOT_CGSCC_NPM-NEXT: entry: ; NOT_CGSCC_NPM-NEXT: switch i64 0, label [[SW_DEFAULT:%.*]] [ @@ -1558,6 +1669,7 @@ ; NOT_CGSCC_NPM: return: ; NOT_CGSCC_NPM-NEXT: unreachable ; +; IS__CGSCC____: Function Attrs: nofree nosync nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@switch_default() ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: switch i64 0, label [[SW_DEFAULT:%.*]] [ @@ -1585,6 +1697,7 @@ } define i32 @switch_default_caller() { +; CHECK: Function Attrs: nofree nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@switch_default_caller() ; CHECK-NEXT: [[CALL2:%.*]] = tail call i32 @switch_default() ; CHECK-NEXT: ret i32 123 @@ -1594,6 +1707,7 @@ } define internal i32 @switch_default_dead(i64 %i) nounwind { +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@switch_default_dead() ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: switch i64 0, label [[SW_DEFAULT:%.*]] [ @@ -1619,8 +1733,13 @@ } define i32 @switch_default_dead_caller() { -; CHECK-LABEL: define {{[^@]+}}@switch_default_dead_caller() -; CHECK-NEXT: ret i32 123 +; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@switch_default_dead_caller() +; NOT_CGSCC_NPM-NEXT: ret i32 123 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@switch_default_dead_caller() +; IS__CGSCC____-NEXT: ret i32 123 ; %call2 = tail call i32 @switch_default_dead(i64 0) ret i32 %call2 @@ -1841,9 +1960,15 @@ declare noalias i8* @malloc(i64) define i32 @h(i32 %i) { -; CHECK-LABEL: define {{[^@]+}}@h -; CHECK-SAME: (i32 [[I:%.*]]) -; CHECK-NEXT: ret i32 0 +; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@h +; NOT_CGSCC_NPM-SAME: (i32 [[I:%.*]]) +; NOT_CGSCC_NPM-NEXT: ret i32 0 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@h +; IS__CGSCC____-SAME: (i32 [[I:%.*]]) +; IS__CGSCC____-NEXT: ret i32 0 ; ret i32 0 } @@ -1854,6 +1979,7 @@ @p = global i8 0 define void @bad_gep() { +; CHECK: Function Attrs: nounwind readnone willreturn ; CHECK-LABEL: define {{[^@]+}}@bad_gep() ; CHECK-NEXT: entry: ; CHECK-NEXT: [[N:%.*]] = alloca i8, align 1 diff --git a/llvm/test/Transforms/Attributor/liveness_chains.ll b/llvm/test/Transforms/Attributor/liveness_chains.ll --- a/llvm/test/Transforms/Attributor/liveness_chains.ll +++ b/llvm/test/Transforms/Attributor/liveness_chains.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -9,9 +9,15 @@ declare i32 @source() nounwind readonly define i32 @chain_dead(i32 %arg) { -; CHECK-LABEL: define {{[^@]+}}@chain_dead -; CHECK-SAME: (i32 [[ARG:%.*]]) -; CHECK-NEXT: ret i32 0 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@chain_dead +; IS__TUNIT____-SAME: (i32 [[ARG:%.*]]) +; IS__TUNIT____-NEXT: ret i32 0 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@chain_dead +; IS__CGSCC____-SAME: (i32 [[ARG:%.*]]) +; IS__CGSCC____-NEXT: ret i32 0 ; %init = call i32 @source() %v0 = add i32 %arg, %init @@ -28,6 +34,7 @@ } define i32 @chain_alive(i32 %arg) { +; CHECK: Function Attrs: nounwind readonly ; CHECK-LABEL: define {{[^@]+}}@chain_alive ; CHECK-SAME: (i32 [[ARG:%.*]]) ; CHECK-NEXT: [[INIT:%.*]] = call i32 @source() diff --git a/llvm/test/Transforms/Attributor/lvi-after-jumpthreading.ll b/llvm/test/Transforms/Attributor/lvi-after-jumpthreading.ll --- a/llvm/test/Transforms/Attributor/lvi-after-jumpthreading.ll +++ b/llvm/test/Transforms/Attributor/lvi-after-jumpthreading.ll @@ -1,38 +1,71 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM define i8 @test1(i32 %a, i32 %length) { -; IS________OPM-LABEL: define {{[^@]+}}@test1 -; IS________OPM-SAME: (i32 [[A:%.*]], i32 [[LENGTH:%.*]]) -; IS________OPM-NEXT: entry: -; IS________OPM-NEXT: br label [[LOOP:%.*]] -; IS________OPM: loop: -; IS________OPM-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] -; IS________OPM-NEXT: [[CND:%.*]] = icmp sge i32 [[IV]], 0 -; IS________OPM-NEXT: br i1 [[CND]], label [[BACKEDGE]], label [[EXIT:%.*]] -; IS________OPM: backedge: -; IS________OPM-NEXT: [[IV_NEXT]] = add nsw i32 [[IV]], 1 -; IS________OPM-NEXT: [[CONT:%.*]] = icmp slt i32 [[IV_NEXT]], 400 -; IS________OPM-NEXT: br i1 [[CONT]], label [[LOOP]], label [[EXIT]] -; IS________OPM: exit: -; IS________OPM-NEXT: ret i8 0 +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test1 +; IS__TUNIT_OPM-SAME: (i32 [[A:%.*]], i32 [[LENGTH:%.*]]) +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: br label [[LOOP:%.*]] +; IS__TUNIT_OPM: loop: +; IS__TUNIT_OPM-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; IS__TUNIT_OPM-NEXT: [[CND:%.*]] = icmp sge i32 [[IV]], 0 +; IS__TUNIT_OPM-NEXT: br i1 [[CND]], label [[BACKEDGE]], label [[EXIT:%.*]] +; IS__TUNIT_OPM: backedge: +; IS__TUNIT_OPM-NEXT: [[IV_NEXT]] = add nsw i32 [[IV]], 1 +; IS__TUNIT_OPM-NEXT: [[CONT:%.*]] = icmp slt i32 [[IV_NEXT]], 400 +; IS__TUNIT_OPM-NEXT: br i1 [[CONT]], label [[LOOP]], label [[EXIT]] +; IS__TUNIT_OPM: exit: +; IS__TUNIT_OPM-NEXT: ret i8 0 ; -; IS________NPM-LABEL: define {{[^@]+}}@test1 -; IS________NPM-SAME: (i32 [[A:%.*]], i32 [[LENGTH:%.*]]) -; IS________NPM-NEXT: entry: -; IS________NPM-NEXT: br label [[LOOP:%.*]] -; IS________NPM: loop: -; IS________NPM-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] -; IS________NPM-NEXT: br label [[BACKEDGE]] -; IS________NPM: backedge: -; IS________NPM-NEXT: [[IV_NEXT]] = add nsw i32 [[IV]], 1 -; IS________NPM-NEXT: [[CONT:%.*]] = icmp slt i32 [[IV_NEXT]], 400 -; IS________NPM-NEXT: br i1 [[CONT]], label [[LOOP]], label [[EXIT:%.*]] -; IS________NPM: exit: -; IS________NPM-NEXT: ret i8 0 +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@test1 +; IS__TUNIT_NPM-SAME: (i32 [[A:%.*]], i32 [[LENGTH:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: br label [[LOOP:%.*]] +; IS__TUNIT_NPM: loop: +; IS__TUNIT_NPM-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; IS__TUNIT_NPM-NEXT: br label [[BACKEDGE]] +; IS__TUNIT_NPM: backedge: +; IS__TUNIT_NPM-NEXT: [[IV_NEXT]] = add nsw i32 [[IV]], 1 +; IS__TUNIT_NPM-NEXT: [[CONT:%.*]] = icmp slt i32 [[IV_NEXT]], 400 +; IS__TUNIT_NPM-NEXT: br i1 [[CONT]], label [[LOOP]], label [[EXIT:%.*]] +; IS__TUNIT_NPM: exit: +; IS__TUNIT_NPM-NEXT: ret i8 0 +; +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test1 +; IS__CGSCC_OPM-SAME: (i32 [[A:%.*]], i32 [[LENGTH:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: br label [[LOOP:%.*]] +; IS__CGSCC_OPM: loop: +; IS__CGSCC_OPM-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; IS__CGSCC_OPM-NEXT: [[CND:%.*]] = icmp sge i32 [[IV]], 0 +; IS__CGSCC_OPM-NEXT: br i1 [[CND]], label [[BACKEDGE]], label [[EXIT:%.*]] +; IS__CGSCC_OPM: backedge: +; IS__CGSCC_OPM-NEXT: [[IV_NEXT]] = add nsw i32 [[IV]], 1 +; IS__CGSCC_OPM-NEXT: [[CONT:%.*]] = icmp slt i32 [[IV_NEXT]], 400 +; IS__CGSCC_OPM-NEXT: br i1 [[CONT]], label [[LOOP]], label [[EXIT]] +; IS__CGSCC_OPM: exit: +; IS__CGSCC_OPM-NEXT: ret i8 0 +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test1 +; IS__CGSCC_NPM-SAME: (i32 [[A:%.*]], i32 [[LENGTH:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: br label [[LOOP:%.*]] +; IS__CGSCC_NPM: loop: +; IS__CGSCC_NPM-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; IS__CGSCC_NPM-NEXT: br label [[BACKEDGE]] +; IS__CGSCC_NPM: backedge: +; IS__CGSCC_NPM-NEXT: [[IV_NEXT]] = add nsw i32 [[IV]], 1 +; IS__CGSCC_NPM-NEXT: [[CONT:%.*]] = icmp slt i32 [[IV_NEXT]], 400 +; IS__CGSCC_NPM-NEXT: br i1 [[CONT]], label [[LOOP]], label [[EXIT:%.*]] +; IS__CGSCC_NPM: exit: +; IS__CGSCC_NPM-NEXT: ret i8 0 ; entry: br label %loop @@ -52,26 +85,93 @@ } define i8 @test2(i32 %n) { -; CHECK-LABEL: define {{[^@]+}}@test2 -; CHECK-SAME: (i32 [[N:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[LOOP:%.*]] -; CHECK: loop: -; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] -; CHECK-NEXT: [[IV2:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ [[IV2_NEXT:%.*]], [[BACKEDGE]] ] -; CHECK-NEXT: [[CND1:%.*]] = icmp sge i32 [[IV]], 0 -; CHECK-NEXT: [[CND2:%.*]] = icmp sgt i32 [[IV2]], 0 -; CHECK-NEXT: [[CND:%.*]] = and i1 [[CND1]], [[CND2]] -; CHECK-NEXT: br i1 [[CND]], label [[BACKEDGE]], label [[EXIT:%.*]] -; CHECK: backedge: -; CHECK-NEXT: [[IV_NEXT]] = add nsw i32 [[IV]], 1 -; CHECK-NEXT: [[IV2_NEXT]] = sub nsw i32 [[IV2]], 1 -; CHECK-NEXT: [[CONT1:%.*]] = icmp slt i32 [[IV_NEXT]], 400 -; CHECK-NEXT: [[CONT2:%.*]] = icmp sgt i32 [[IV2_NEXT]], 0 -; CHECK-NEXT: [[CONT:%.*]] = and i1 [[CONT1]], [[CONT2]] -; CHECK-NEXT: br i1 [[CONT]], label [[LOOP]], label [[EXIT]] -; CHECK: exit: -; CHECK-NEXT: ret i8 0 +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test2 +; IS__TUNIT_OPM-SAME: (i32 [[N:%.*]]) +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: br label [[LOOP:%.*]] +; IS__TUNIT_OPM: loop: +; IS__TUNIT_OPM-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; IS__TUNIT_OPM-NEXT: [[IV2:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ [[IV2_NEXT:%.*]], [[BACKEDGE]] ] +; IS__TUNIT_OPM-NEXT: [[CND1:%.*]] = icmp sge i32 [[IV]], 0 +; IS__TUNIT_OPM-NEXT: [[CND2:%.*]] = icmp sgt i32 [[IV2]], 0 +; IS__TUNIT_OPM-NEXT: [[CND:%.*]] = and i1 [[CND1]], [[CND2]] +; IS__TUNIT_OPM-NEXT: br i1 [[CND]], label [[BACKEDGE]], label [[EXIT:%.*]] +; IS__TUNIT_OPM: backedge: +; IS__TUNIT_OPM-NEXT: [[IV_NEXT]] = add nsw i32 [[IV]], 1 +; IS__TUNIT_OPM-NEXT: [[IV2_NEXT]] = sub nsw i32 [[IV2]], 1 +; IS__TUNIT_OPM-NEXT: [[CONT1:%.*]] = icmp slt i32 [[IV_NEXT]], 400 +; IS__TUNIT_OPM-NEXT: [[CONT2:%.*]] = icmp sgt i32 [[IV2_NEXT]], 0 +; IS__TUNIT_OPM-NEXT: [[CONT:%.*]] = and i1 [[CONT1]], [[CONT2]] +; IS__TUNIT_OPM-NEXT: br i1 [[CONT]], label [[LOOP]], label [[EXIT]] +; IS__TUNIT_OPM: exit: +; IS__TUNIT_OPM-NEXT: ret i8 0 +; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@test2 +; IS__TUNIT_NPM-SAME: (i32 [[N:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: br label [[LOOP:%.*]] +; IS__TUNIT_NPM: loop: +; IS__TUNIT_NPM-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; IS__TUNIT_NPM-NEXT: [[IV2:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ [[IV2_NEXT:%.*]], [[BACKEDGE]] ] +; IS__TUNIT_NPM-NEXT: [[CND1:%.*]] = icmp sge i32 [[IV]], 0 +; IS__TUNIT_NPM-NEXT: [[CND2:%.*]] = icmp sgt i32 [[IV2]], 0 +; IS__TUNIT_NPM-NEXT: [[CND:%.*]] = and i1 [[CND1]], [[CND2]] +; IS__TUNIT_NPM-NEXT: br i1 [[CND]], label [[BACKEDGE]], label [[EXIT:%.*]] +; IS__TUNIT_NPM: backedge: +; IS__TUNIT_NPM-NEXT: [[IV_NEXT]] = add nsw i32 [[IV]], 1 +; IS__TUNIT_NPM-NEXT: [[IV2_NEXT]] = sub nsw i32 [[IV2]], 1 +; IS__TUNIT_NPM-NEXT: [[CONT1:%.*]] = icmp slt i32 [[IV_NEXT]], 400 +; IS__TUNIT_NPM-NEXT: [[CONT2:%.*]] = icmp sgt i32 [[IV2_NEXT]], 0 +; IS__TUNIT_NPM-NEXT: [[CONT:%.*]] = and i1 [[CONT1]], [[CONT2]] +; IS__TUNIT_NPM-NEXT: br i1 [[CONT]], label [[LOOP]], label [[EXIT]] +; IS__TUNIT_NPM: exit: +; IS__TUNIT_NPM-NEXT: ret i8 0 +; +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test2 +; IS__CGSCC_OPM-SAME: (i32 [[N:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: br label [[LOOP:%.*]] +; IS__CGSCC_OPM: loop: +; IS__CGSCC_OPM-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; IS__CGSCC_OPM-NEXT: [[IV2:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ [[IV2_NEXT:%.*]], [[BACKEDGE]] ] +; IS__CGSCC_OPM-NEXT: [[CND1:%.*]] = icmp sge i32 [[IV]], 0 +; IS__CGSCC_OPM-NEXT: [[CND2:%.*]] = icmp sgt i32 [[IV2]], 0 +; IS__CGSCC_OPM-NEXT: [[CND:%.*]] = and i1 [[CND1]], [[CND2]] +; IS__CGSCC_OPM-NEXT: br i1 [[CND]], label [[BACKEDGE]], label [[EXIT:%.*]] +; IS__CGSCC_OPM: backedge: +; IS__CGSCC_OPM-NEXT: [[IV_NEXT]] = add nsw i32 [[IV]], 1 +; IS__CGSCC_OPM-NEXT: [[IV2_NEXT]] = sub nsw i32 [[IV2]], 1 +; IS__CGSCC_OPM-NEXT: [[CONT1:%.*]] = icmp slt i32 [[IV_NEXT]], 400 +; IS__CGSCC_OPM-NEXT: [[CONT2:%.*]] = icmp sgt i32 [[IV2_NEXT]], 0 +; IS__CGSCC_OPM-NEXT: [[CONT:%.*]] = and i1 [[CONT1]], [[CONT2]] +; IS__CGSCC_OPM-NEXT: br i1 [[CONT]], label [[LOOP]], label [[EXIT]] +; IS__CGSCC_OPM: exit: +; IS__CGSCC_OPM-NEXT: ret i8 0 +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test2 +; IS__CGSCC_NPM-SAME: (i32 [[N:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: br label [[LOOP:%.*]] +; IS__CGSCC_NPM: loop: +; IS__CGSCC_NPM-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[BACKEDGE:%.*]] ] +; IS__CGSCC_NPM-NEXT: [[IV2:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ [[IV2_NEXT:%.*]], [[BACKEDGE]] ] +; IS__CGSCC_NPM-NEXT: [[CND1:%.*]] = icmp sge i32 [[IV]], 0 +; IS__CGSCC_NPM-NEXT: [[CND2:%.*]] = icmp sgt i32 [[IV2]], 0 +; IS__CGSCC_NPM-NEXT: [[CND:%.*]] = and i1 [[CND1]], [[CND2]] +; IS__CGSCC_NPM-NEXT: br i1 [[CND]], label [[BACKEDGE]], label [[EXIT:%.*]] +; IS__CGSCC_NPM: backedge: +; IS__CGSCC_NPM-NEXT: [[IV_NEXT]] = add nsw i32 [[IV]], 1 +; IS__CGSCC_NPM-NEXT: [[IV2_NEXT]] = sub nsw i32 [[IV2]], 1 +; IS__CGSCC_NPM-NEXT: [[CONT1:%.*]] = icmp slt i32 [[IV_NEXT]], 400 +; IS__CGSCC_NPM-NEXT: [[CONT2:%.*]] = icmp sgt i32 [[IV2_NEXT]], 0 +; IS__CGSCC_NPM-NEXT: [[CONT:%.*]] = and i1 [[CONT1]], [[CONT2]] +; IS__CGSCC_NPM-NEXT: br i1 [[CONT]], label [[LOOP]], label [[EXIT]] +; IS__CGSCC_NPM: exit: +; IS__CGSCC_NPM-NEXT: ret i8 0 ; entry: br label %loop diff --git a/llvm/test/Transforms/Attributor/lvi-for-ashr.ll b/llvm/test/Transforms/Attributor/lvi-for-ashr.ll --- a/llvm/test/Transforms/Attributor/lvi-for-ashr.ll +++ b/llvm/test/Transforms/Attributor/lvi-for-ashr.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -7,25 +7,47 @@ ; FIXME: DOT should be replaced with 3 define i32 @test-ashr(i32 %c) { -; CHECK-LABEL: define {{[^@]+}}@test-ashr -; CHECK-SAME: (i32 [[C:%.*]]) -; CHECK-NEXT: chk65: -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[C]], 65 -; CHECK-NEXT: br i1 [[CMP]], label [[RETURN:%.*]], label [[CHK0:%.*]] -; CHECK: chk0: -; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[C]], 0 -; CHECK-NEXT: br i1 [[CMP]], label [[RETURN]], label [[BB_IF:%.*]] -; CHECK: bb_if: -; CHECK-NEXT: [[ASHR_VAL:%.*]] = ashr exact i32 [[C]], 2 -; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[ASHR_VAL]], 15 -; CHECK-NEXT: br i1 [[CMP2]], label [[BB_THEN:%.*]], label [[RETURN]] -; CHECK: bb_then: -; CHECK-NEXT: [[CMP3:%.*]] = icmp eq i32 [[ASHR_VAL]], 16 -; CHECK-NEXT: [[DOT:%.*]] = select i1 [[CMP3]], i32 3, i32 2 -; CHECK-NEXT: br label [[RETURN]] -; CHECK: return: -; CHECK-NEXT: [[RETVAL:%.*]] = phi i32 [ 0, [[CHK65:%.*]] ], [ 1, [[CHK0]] ], [ [[DOT]], [[BB_THEN]] ], [ 4, [[BB_IF]] ] -; CHECK-NEXT: ret i32 [[RETVAL]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test-ashr +; IS__TUNIT____-SAME: (i32 [[C:%.*]]) +; IS__TUNIT____-NEXT: chk65: +; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[C]], 65 +; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[RETURN:%.*]], label [[CHK0:%.*]] +; IS__TUNIT____: chk0: +; IS__TUNIT____-NEXT: [[CMP1:%.*]] = icmp slt i32 [[C]], 0 +; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[RETURN]], label [[BB_IF:%.*]] +; IS__TUNIT____: bb_if: +; IS__TUNIT____-NEXT: [[ASHR_VAL:%.*]] = ashr exact i32 [[C]], 2 +; IS__TUNIT____-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[ASHR_VAL]], 15 +; IS__TUNIT____-NEXT: br i1 [[CMP2]], label [[BB_THEN:%.*]], label [[RETURN]] +; IS__TUNIT____: bb_then: +; IS__TUNIT____-NEXT: [[CMP3:%.*]] = icmp eq i32 [[ASHR_VAL]], 16 +; IS__TUNIT____-NEXT: [[DOT:%.*]] = select i1 [[CMP3]], i32 3, i32 2 +; IS__TUNIT____-NEXT: br label [[RETURN]] +; IS__TUNIT____: return: +; IS__TUNIT____-NEXT: [[RETVAL:%.*]] = phi i32 [ 0, [[CHK65:%.*]] ], [ 1, [[CHK0]] ], [ [[DOT]], [[BB_THEN]] ], [ 4, [[BB_IF]] ] +; IS__TUNIT____-NEXT: ret i32 [[RETVAL]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test-ashr +; IS__CGSCC____-SAME: (i32 [[C:%.*]]) +; IS__CGSCC____-NEXT: chk65: +; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[C]], 65 +; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[RETURN:%.*]], label [[CHK0:%.*]] +; IS__CGSCC____: chk0: +; IS__CGSCC____-NEXT: [[CMP1:%.*]] = icmp slt i32 [[C]], 0 +; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[RETURN]], label [[BB_IF:%.*]] +; IS__CGSCC____: bb_if: +; IS__CGSCC____-NEXT: [[ASHR_VAL:%.*]] = ashr exact i32 [[C]], 2 +; IS__CGSCC____-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[ASHR_VAL]], 15 +; IS__CGSCC____-NEXT: br i1 [[CMP2]], label [[BB_THEN:%.*]], label [[RETURN]] +; IS__CGSCC____: bb_then: +; IS__CGSCC____-NEXT: [[CMP3:%.*]] = icmp eq i32 [[ASHR_VAL]], 16 +; IS__CGSCC____-NEXT: [[DOT:%.*]] = select i1 [[CMP3]], i32 3, i32 2 +; IS__CGSCC____-NEXT: br label [[RETURN]] +; IS__CGSCC____: return: +; IS__CGSCC____-NEXT: [[RETVAL:%.*]] = phi i32 [ 0, [[CHK65:%.*]] ], [ 1, [[CHK0]] ], [ [[DOT]], [[BB_THEN]] ], [ 4, [[BB_IF]] ] +; IS__CGSCC____-NEXT: ret i32 [[RETVAL]] ; chk65: %cmp = icmp sgt i32 %c, 65 diff --git a/llvm/test/Transforms/Attributor/memory_locations.ll b/llvm/test/Transforms/Attributor/memory_locations.ll --- a/llvm/test/Transforms/Attributor/memory_locations.ll +++ b/llvm/test/Transforms/Attributor/memory_locations.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=11 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=11 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -10,8 +10,8 @@ ; CHECK: Function Attrs: inaccessiblememonly declare noalias i8* @malloc(i64) inaccessiblememonly -; CHECK: Function Attrs: inaccessiblememonly define dso_local i8* @internal_only(i32 %arg) { +; CHECK: Function Attrs: inaccessiblememonly ; CHECK-LABEL: define {{[^@]+}}@internal_only ; CHECK-SAME: (i32 [[ARG:%.*]]) ; CHECK-NEXT: entry: @@ -25,8 +25,8 @@ ret i8* %call } -; CHECK: Function Attrs: inaccessiblememonly define dso_local i8* @internal_only_rec(i32 %arg) { +; CHECK: Function Attrs: inaccessiblememonly ; CHECK-LABEL: define {{[^@]+}}@internal_only_rec ; CHECK-SAME: (i32 [[ARG:%.*]]) ; CHECK-NEXT: entry: @@ -65,8 +65,8 @@ ret i8* %retval.0 } -; CHECK: Function Attrs: inaccessiblememonly define dso_local i8* @internal_only_rec_static_helper(i32 %arg) { +; CHECK: Function Attrs: inaccessiblememonly ; CHECK-LABEL: define {{[^@]+}}@internal_only_rec_static_helper ; CHECK-SAME: (i32 [[ARG:%.*]]) ; CHECK-NEXT: entry: @@ -78,8 +78,8 @@ ret i8* %call } -; CHECK: Function Attrs: inaccessiblememonly define internal i8* @internal_only_rec_static(i32 %arg) { +; CHECK: Function Attrs: inaccessiblememonly ; CHECK-LABEL: define {{[^@]+}}@internal_only_rec_static ; CHECK-SAME: (i32 [[ARG:%.*]]) ; CHECK-NEXT: entry: @@ -173,8 +173,8 @@ ret i8* %retval.0 } -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly define dso_local i8* @internal_argmem_only_read(i32* %arg) { +; CHECK: Function Attrs: inaccessiblemem_or_argmemonly ; CHECK-LABEL: define {{[^@]+}}@internal_argmem_only_read ; CHECK-SAME: (i32* nocapture nonnull readonly align 4 dereferenceable(4) [[ARG:%.*]]) ; CHECK-NEXT: entry: @@ -190,8 +190,8 @@ ret i8* %call } -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly define dso_local i8* @internal_argmem_only_write(i32* %arg) { +; CHECK: Function Attrs: inaccessiblemem_or_argmemonly ; CHECK-LABEL: define {{[^@]+}}@internal_argmem_only_write ; CHECK-SAME: (i32* nocapture nonnull writeonly align 4 dereferenceable(4) [[ARG:%.*]]) ; CHECK-NEXT: entry: @@ -205,14 +205,15 @@ ret i8* %call } -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly define dso_local i8* @internal_argmem_only_rec(i32* %arg) { +; IS__TUNIT____: Function Attrs: inaccessiblemem_or_argmemonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@internal_argmem_only_rec ; IS__TUNIT____-SAME: (i32* nocapture [[ARG:%.*]]) ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: [[CALL:%.*]] = call noalias i8* @internal_argmem_only_rec_1(i32* nocapture align 4 [[ARG]]) ; IS__TUNIT____-NEXT: ret i8* [[CALL]] ; +; IS__CGSCC____: Function Attrs: inaccessiblemem_or_argmemonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@internal_argmem_only_rec ; IS__CGSCC____-SAME: (i32* nocapture nonnull align 4 dereferenceable(4) [[ARG:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -224,8 +225,8 @@ ret i8* %call } -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly define internal i8* @internal_argmem_only_rec_1(i32* %arg) { +; CHECK: Function Attrs: inaccessiblemem_or_argmemonly ; CHECK-LABEL: define {{[^@]+}}@internal_argmem_only_rec_1 ; CHECK-SAME: (i32* nocapture nonnull align 4 dereferenceable(4) [[ARG:%.*]]) ; CHECK-NEXT: entry: @@ -280,8 +281,8 @@ ret i8* %retval.0 } -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly define internal i8* @internal_argmem_only_rec_2(i32* %arg) { +; CHECK: Function Attrs: inaccessiblemem_or_argmemonly ; CHECK-LABEL: define {{[^@]+}}@internal_argmem_only_rec_2 ; CHECK-SAME: (i32* nocapture nonnull align 4 dereferenceable(4) [[ARG:%.*]]) ; CHECK-NEXT: entry: @@ -302,8 +303,8 @@ declare i8* @inaccesible_argmem_only_decl(i8* %arg) inaccessiblemem_or_argmemonly declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) nounwind argmemonly willreturn -; CHECK: Function Attrs: argmemonly define void @callerA1(i8* %arg) { +; CHECK: Function Attrs: argmemonly ; CHECK-LABEL: define {{[^@]+}}@callerA1 ; CHECK-SAME: (i8* [[ARG:%.*]]) ; CHECK-NEXT: [[TMP1:%.*]] = call i8* @argmem_only(i8* [[ARG]]) @@ -312,8 +313,8 @@ call i8* @argmem_only(i8* %arg) ret void } -; CHECK: Function Attrs: inaccessiblemem_or_argmemonly define void @callerA2(i8* %arg) { +; CHECK: Function Attrs: inaccessiblemem_or_argmemonly ; CHECK-LABEL: define {{[^@]+}}@callerA2 ; CHECK-SAME: (i8* [[ARG:%.*]]) ; CHECK-NEXT: [[TMP1:%.*]] = call i8* @inaccesible_argmem_only_decl(i8* [[ARG]]) @@ -322,8 +323,8 @@ call i8* @inaccesible_argmem_only_decl(i8* %arg) ret void } -; CHECK: Function Attrs: readnone define void @callerB1() { +; CHECK: Function Attrs: readnone ; CHECK-LABEL: define {{[^@]+}}@callerB1() ; CHECK-NEXT: [[STACK:%.*]] = alloca i8, align 1 ; CHECK-NEXT: [[TMP1:%.*]] = call i8* @argmem_only(i8* nonnull dereferenceable(1) [[STACK]]) @@ -333,8 +334,8 @@ call i8* @argmem_only(i8* %stack) ret void } -; CHECK: Function Attrs: inaccessiblememonly define void @callerB2() { +; CHECK: Function Attrs: inaccessiblememonly ; CHECK-LABEL: define {{[^@]+}}@callerB2() ; CHECK-NEXT: [[STACK:%.*]] = alloca i8, align 1 ; CHECK-NEXT: [[TMP1:%.*]] = call i8* @inaccesible_argmem_only_decl(i8* nonnull dereferenceable(1) [[STACK]]) @@ -344,7 +345,6 @@ call i8* @inaccesible_argmem_only_decl(i8* %stack) ret void } -; CHECK-NOT: Function Attrs define void @callerC1() { ; CHECK-LABEL: define {{[^@]+}}@callerC1() ; CHECK-NEXT: [[UNKNOWN:%.*]] = call i8* @unknown_ptr() @@ -355,7 +355,6 @@ call i8* @argmem_only(i8* %unknown) ret void } -; CHECK-NOT: Function Attrs define void @callerC2() { ; CHECK-LABEL: define {{[^@]+}}@callerC2() ; CHECK-NEXT: [[UNKNOWN:%.*]] = call i8* @unknown_ptr() @@ -366,7 +365,6 @@ call i8* @inaccesible_argmem_only_decl(i8* %unknown) ret void } -; CHECK-NOT: Function Attrs define void @callerD1() { ; CHECK-LABEL: define {{[^@]+}}@callerD1() ; CHECK-NEXT: [[UNKNOWN:%.*]] = call i8* @argmem_only(i8* noalias nocapture align 536870912 null) @@ -377,7 +375,6 @@ store i8 0, i8* %unknown ret void } -; CHECK-NOT: Function Attrs define void @callerD2() { ; CHECK-LABEL: define {{[^@]+}}@callerD2() ; CHECK-NEXT: [[UNKNOWN:%.*]] = call i8* @inaccesible_argmem_only_decl(i8* noalias nocapture align 536870912 null) @@ -389,91 +386,114 @@ ret void } -; CHECK: Function Attrs: nofree {{(norecurse )?}}nosync nounwind readnone willreturn define void @callerE(i8* %arg) { -; CHECK-LABEL: define {{[^@]+}}@callerE -; CHECK-SAME: (i8* nocapture nofree readnone [[ARG:%.*]]) -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@callerE +; IS__TUNIT____-SAME: (i8* nocapture nofree readnone [[ARG:%.*]]) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@callerE +; IS__CGSCC____-SAME: (i8* nocapture nofree readnone [[ARG:%.*]]) +; IS__CGSCC____-NEXT: ret void ; call void @llvm.lifetime.start.p0i8(i64 4, i8* %arg) ret void } -; CHECK: Function Attrs: -; CHECK-SAME: writeonly define void @write_global() { -; CHECK-LABEL: define {{[^@]+}}@write_global() -; CHECK-NEXT: store i32 0, i32* @G, align 4 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@write_global() +; IS__TUNIT____-NEXT: store i32 0, i32* @G, align 4 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@write_global() +; IS__CGSCC____-NEXT: store i32 0, i32* @G, align 4 +; IS__CGSCC____-NEXT: ret void ; store i32 0, i32* @G, align 4 ret void } -; CHECK: Function Attrs: argmemonly -; CHECK-SAME: writeonly define void @write_global_via_arg(i32* %GPtr) { -; CHECK-LABEL: define {{[^@]+}}@write_global_via_arg -; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[GPTR:%.*]]) -; CHECK-NEXT: store i32 0, i32* [[GPTR]], align 4 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@write_global_via_arg +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[GPTR:%.*]]) +; IS__TUNIT____-NEXT: store i32 0, i32* [[GPTR]], align 4 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@write_global_via_arg +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[GPTR:%.*]]) +; IS__CGSCC____-NEXT: store i32 0, i32* [[GPTR]], align 4 +; IS__CGSCC____-NEXT: ret void ; store i32 0, i32* %GPtr, align 4 ret void } -; CHECK: Function Attrs: -; CHECK-NOT: argmemonly -; CHECK-SAME: writeonly -; CHECK-NOT: argmemonly define internal void @write_global_via_arg_internal(i32* %GPtr) { -; CHECK-LABEL: define {{[^@]+}}@write_global_via_arg_internal() -; CHECK-NEXT: store i32 0, i32* @G, align 4 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@write_global_via_arg_internal() +; IS__TUNIT____-NEXT: store i32 0, i32* @G, align 4 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@write_global_via_arg_internal() +; IS__CGSCC____-NEXT: store i32 0, i32* @G, align 4 +; IS__CGSCC____-NEXT: ret void ; store i32 0, i32* %GPtr, align 4 ret void } - -; CHECK: Function Attrs: -; CHECK-SAME: writeonly define void @writeonly_global() { -; CHECK-LABEL: define {{[^@]+}}@writeonly_global() -; CHECK-NEXT: call void @write_global() -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@writeonly_global() +; IS__TUNIT____-NEXT: call void @write_global() +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@writeonly_global() +; IS__CGSCC____-NEXT: call void @write_global() +; IS__CGSCC____-NEXT: ret void ; call void @write_global() ret void } -; CHECK: Function Attrs: -; CHECK-SAME: writeonly define void @writeonly_global_via_arg() { -; CHECK-LABEL: define {{[^@]+}}@writeonly_global_via_arg() -; CHECK-NEXT: call void @write_global_via_arg(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) @G) -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@writeonly_global_via_arg() +; IS__TUNIT____-NEXT: call void @write_global_via_arg(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) @G) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@writeonly_global_via_arg() +; IS__CGSCC____-NEXT: call void @write_global_via_arg(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) @G) +; IS__CGSCC____-NEXT: ret void ; call void @write_global_via_arg(i32* @G) ret void } -; CHECK: Function Attrs: -; CHECK-SAME: writeonly define void @writeonly_global_via_arg_internal() { ; -; CHECK-LABEL: define {{[^@]+}}@writeonly_global_via_arg_internal() -; CHECK-NEXT: call void @write_global_via_arg_internal() -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@writeonly_global_via_arg_internal() +; IS__TUNIT____-NEXT: call void @write_global_via_arg_internal() +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@writeonly_global_via_arg_internal() +; IS__CGSCC____-NEXT: call void @write_global_via_arg_internal() +; IS__CGSCC____-NEXT: ret void ; call void @write_global_via_arg_internal(i32* @G) ret void } - -; CHECK: Function Attrs: -; CHECK-NOT: readnone -; CHECK-SAME: argmemonly -; CHECK-NOT: readnone define i8 @recursive_not_readnone(i8* %ptr, i1 %c) { +; CHECK: Function Attrs: argmemonly nofree nosync nounwind ; CHECK-LABEL: define {{[^@]+}}@recursive_not_readnone ; CHECK-SAME: (i8* nocapture nofree writeonly [[PTR:%.*]], i1 [[C:%.*]]) ; CHECK-NEXT: [[ALLOC:%.*]] = alloca i8, align 1 @@ -497,11 +517,8 @@ ret i8 0 } -; CHECK: Function Attrs: -; CHECK-NOT: readnone -; CHECK-SAME: argmemonly -; CHECK-NOT: readnone define internal i8 @recursive_not_readnone_internal(i8* %ptr, i1 %c) { +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind ; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_not_readnone_internal ; IS__TUNIT____-SAME: (i8* noalias nocapture nofree nonnull writeonly dereferenceable(1) [[PTR:%.*]], i1 [[C:%.*]]) ; IS__TUNIT____-NEXT: [[ALLOC:%.*]] = alloca i8, align 1 @@ -514,6 +531,7 @@ ; IS__TUNIT____-NEXT: store i8 1, i8* [[PTR]], align 1 ; IS__TUNIT____-NEXT: ret i8 0 ; +; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_not_readnone_internal ; IS__CGSCC____-SAME: (i8* nocapture nofree nonnull writeonly dereferenceable(1) [[PTR:%.*]], i1 [[C:%.*]]) ; IS__CGSCC____-NEXT: [[ALLOC:%.*]] = alloca i8, align 1 @@ -537,9 +555,8 @@ ret i8 0 } -; CHECK: Function Attrs: -; CHECK-SAME: readnone define i8 @readnone_caller(i1 %c) { +; CHECK: Function Attrs: nofree nosync nounwind readnone ; CHECK-LABEL: define {{[^@]+}}@readnone_caller ; CHECK-SAME: (i1 [[C:%.*]]) ; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1 @@ -551,11 +568,8 @@ ret i8 %r } -; CHECK: Function Attrs: -; CHECK-NOT: readnone -; CHECK-SAME: argmemonly -; CHECK-NOT: readnone define internal i8 @recursive_not_readnone_internal2(i8* %ptr, i1 %c) { +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind ; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_not_readnone_internal2 ; IS__TUNIT____-SAME: (i8* noalias nocapture nofree nonnull writeonly [[PTR:%.*]], i1 [[C:%.*]]) ; IS__TUNIT____-NEXT: [[ALLOC:%.*]] = alloca i8, align 1 @@ -568,6 +582,7 @@ ; IS__TUNIT____-NEXT: store i8 1, i8* [[PTR]], align 1 ; IS__TUNIT____-NEXT: ret i8 0 ; +; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_not_readnone_internal2 ; IS__CGSCC____-SAME: (i8* nocapture nofree nonnull writeonly [[PTR:%.*]], i1 [[C:%.*]]) ; IS__CGSCC____-NEXT: [[ALLOC:%.*]] = alloca i8, align 1 @@ -591,9 +606,8 @@ ret i8 0 } -; CHECK: Function Attrs: -; CHECK-SAME: readnone define i8 @readnone_caller2(i1 %c) { +; CHECK: Function Attrs: nofree nosync nounwind readnone ; CHECK-LABEL: define {{[^@]+}}@readnone_caller2 ; CHECK-SAME: (i1 [[C:%.*]]) ; CHECK-NEXT: [[R:%.*]] = call i8 @recursive_not_readnone_internal2(i8* undef, i1 [[C]]) @@ -603,23 +617,31 @@ ret i8 %r } -; CHECK: Function Attrs: -; CHECK-NOT: argmemonly define internal void @argmemonly_before_ipconstprop(i32* %p) argmemonly { -; CHECK-LABEL: define {{[^@]+}}@argmemonly_before_ipconstprop() -; CHECK-NEXT: store i32 0, i32* @G, align 4 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@argmemonly_before_ipconstprop() +; IS__TUNIT____-NEXT: store i32 0, i32* @G, align 4 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@argmemonly_before_ipconstprop() +; IS__CGSCC____-NEXT: store i32 0, i32* @G, align 4 +; IS__CGSCC____-NEXT: ret void ; store i32 0, i32* %p ret void } -; CHECK: Function Attrs: -; CHECK-NOT: argmemonly define void @argmemonky_caller() { -; CHECK-LABEL: define {{[^@]+}}@argmemonky_caller() -; CHECK-NEXT: call void @argmemonly_before_ipconstprop() -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@argmemonky_caller() +; IS__TUNIT____-NEXT: call void @argmemonly_before_ipconstprop() +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@argmemonky_caller() +; IS__CGSCC____-NEXT: call void @argmemonly_before_ipconstprop() +; IS__CGSCC____-NEXT: ret void ; call void @argmemonly_before_ipconstprop(i32* @G) ret void diff --git a/llvm/test/Transforms/Attributor/misc.ll b/llvm/test/Transforms/Attributor/misc.ll --- a/llvm/test/Transforms/Attributor/misc.ll +++ b/llvm/test/Transforms/Attributor/misc.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -95,11 +95,19 @@ define internal void @foo(i32* %a) { ; -; CHECK-LABEL: define {{[^@]+}}@foo -; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: store i32 0, i32* [[A]], align 4 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@foo +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: store i32 0, i32* [[A]], align 4 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@foo +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: store i32 0, i32* [[A]], align 4 +; IS__CGSCC____-NEXT: ret void ; entry: store i32 0, i32* %a diff --git a/llvm/test/Transforms/Attributor/misc_crash.ll b/llvm/test/Transforms/Attributor/misc_crash.ll --- a/llvm/test/Transforms/Attributor/misc_crash.ll +++ b/llvm/test/Transforms/Attributor/misc_crash.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -S %s | FileCheck %s ; RUN: opt -passes=attributor -S %s | FileCheck %s @@ -6,8 +6,9 @@ @var2 = internal global i32 0 define i32 addrspace(1)* @foo(i32 addrspace(4)* %arg) { +; CHECK: Function Attrs: nofree nosync nounwind readnone willreturn ; CHECK-LABEL: define {{[^@]+}}@foo -; CHECK-SAME: (i32 addrspace(4)* nofree readnone [[ARG:%.*]]) #0 +; CHECK-SAME: (i32 addrspace(4)* nofree readnone [[ARG:%.*]]) ; CHECK-NEXT: entry: ; CHECK-NEXT: [[TMP0:%.*]] = addrspacecast i32 addrspace(4)* [[ARG]] to i32 addrspace(1)* ; CHECK-NEXT: ret i32 addrspace(1)* [[TMP0]] @@ -18,8 +19,9 @@ } define i32* @func1() { -; CHECK-LABEL: define {{[^@]+}}@func1() #0 -; CHECK-NEXT: [[PTR:%.*]] = call i32* @func1a() #0 +; CHECK: Function Attrs: nofree nosync nounwind readnone willreturn +; CHECK-LABEL: define {{[^@]+}}@func1() +; CHECK-NEXT: [[PTR:%.*]] = call i32* @func1a() ; CHECK-NEXT: ret i32* [[PTR]] ; %ptr = call i32* @func1a([1 x i32]* @var1) @@ -36,8 +38,9 @@ ; UTC_ARGS: --enable define internal void @func2a(i32* %0) { +; CHECK: Function Attrs: nofree nosync nounwind willreturn writeonly ; CHECK-LABEL: define {{[^@]+}}@func2a -; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[TMP0:%.*]]) #1 +; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[TMP0:%.*]]) ; CHECK-NEXT: store i32 0, i32* @var2, align 4 ; CHECK-NEXT: ret void ; diff --git a/llvm/test/Transforms/Attributor/new_attributes.ll b/llvm/test/Transforms/Attributor/new_attributes.ll --- a/llvm/test/Transforms/Attributor/new_attributes.ll +++ b/llvm/test/Transforms/Attributor/new_attributes.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt < %s -attributor -attributor-annotate-decl-cs -attributor-max-iterations=2 -S | FileCheck %s ; RUN: opt < %s -attributor -attributor-annotate-decl-cs -attributor-max-iterations=3 -S | FileCheck %s ; RUN: opt < %s -attributor -attributor-annotate-decl-cs -attributor-max-iterations=4 -S | FileCheck %s @@ -13,26 +14,24 @@ declare i32 @foo2() declare i32 @foo3() -; CHECK-NOT: Function -; CHECK: define internal i32 @bar() { -; CHECK-NEXT: %1 = call i32 @foo1() -; CHECK-NEXT: %2 = call i32 @foo2() -; CHECK-NEXT: %3 = call i32 @foo3() -; CHECK-NEXT: ret i32 undef -; CHECK-NEXT: } define internal i32 @bar() { +; CHECK-LABEL: define {{[^@]+}}@bar() +; CHECK-NEXT: [[TMP1:%.*]] = call i32 @foo1() +; CHECK-NEXT: [[TMP2:%.*]] = call i32 @foo2() +; CHECK-NEXT: [[TMP3:%.*]] = call i32 @foo3() +; CHECK-NEXT: ret i32 undef +; %1 = call i32 @foo1() %2 = call i32 @foo2() %3 = call i32 @foo3() ret i32 1 } -; CHECK-NOT: Function -; CHECK: define i32 @baz() { -; CHECK-NEXT: %1 = call i32 @bar() -; CHECK-NEXT: ret i32 0 -; CHECK-NEXT: } define i32 @baz() { +; CHECK-LABEL: define {{[^@]+}}@baz() +; CHECK-NEXT: [[TMP1:%.*]] = call i32 @bar() +; CHECK-NEXT: ret i32 0 +; %1 = call i32 @bar() ret i32 0 } diff --git a/llvm/test/Transforms/Attributor/noalias.ll b/llvm/test/Transforms/Attributor/noalias.ll --- a/llvm/test/Transforms/Attributor/noalias.ll +++ b/llvm/test/Transforms/Attributor/noalias.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; TODO: The old pass manager cgscc run is disabled as it causes a crash on windows which is under investigation: http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/23151 @@ -42,9 +42,15 @@ } define void @nocapture(i8* %a){ -; CHECK-LABEL: define {{[^@]+}}@nocapture -; CHECK-SAME: (i8* nocapture nofree readnone [[A:%.*]]) -; CHECK-NEXT: ret void +; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@nocapture +; NOT_CGSCC_NPM-SAME: (i8* nocapture nofree readnone [[A:%.*]]) +; NOT_CGSCC_NPM-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@nocapture +; IS__CGSCC____-SAME: (i8* nocapture nofree readnone [[A:%.*]]) +; IS__CGSCC____-NEXT: ret void ; ret void } @@ -98,6 +104,7 @@ ; } define i8* @bar() nounwind uwtable { +; CHECK: Function Attrs: nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@bar() ; CHECK-NEXT: [[TMP1:%.*]] = tail call i8* (...) @baz() ; CHECK-NEXT: ret i8* [[TMP1]] @@ -107,6 +114,7 @@ } define i8* @foo1(i32 %0) nounwind uwtable { +; CHECK: Function Attrs: nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@foo1 ; CHECK-SAME: (i32 [[TMP0:%.*]]) ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 0 @@ -136,16 +144,26 @@ ; Returning global pointer. Should not be noalias. define i8** @getter() { -; CHECK-LABEL: define {{[^@]+}}@getter() -; CHECK-NEXT: ret i8** @G +; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@getter() +; NOT_CGSCC_NPM-NEXT: ret i8** @G +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@getter() +; IS__CGSCC____-NEXT: ret i8** @G ; ret i8** @G } ; Returning global pointer. Should not be noalias. define i8** @calle1(){ -; CHECK-LABEL: define {{[^@]+}}@calle1() -; CHECK-NEXT: ret i8** @G +; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@calle1() +; NOT_CGSCC_NPM-NEXT: ret i8** @G +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@calle1() +; IS__CGSCC____-NEXT: ret i8** @G ; %1 = call i8** @getter() ret i8** %1 @@ -155,6 +173,7 @@ declare noalias i8* @strdup(i8* nocapture) nounwind define i8* @test6() nounwind uwtable ssp { +; CHECK: Function Attrs: nounwind ssp uwtable ; CHECK-LABEL: define {{[^@]+}}@test6() ; CHECK-NEXT: [[X:%.*]] = alloca [2 x i8], align 1 ; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i8], [2 x i8]* [[X]], i64 0, i64 0 @@ -176,6 +195,7 @@ ; TEST 7 define i8* @test7() nounwind { +; CHECK: Function Attrs: nounwind ; CHECK-LABEL: define {{[^@]+}}@test7() ; CHECK-NEXT: entry: ; CHECK-NEXT: [[A:%.*]] = call noalias i8* @malloc(i64 4) @@ -205,6 +225,7 @@ ; TEST 8 define i8* @test8(i32* %0) nounwind uwtable { +; CHECK: Function Attrs: nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@test8 ; CHECK-SAME: (i32* [[TMP0:%.*]]) ; CHECK-NEXT: [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 4) @@ -476,11 +497,13 @@ ; TEST 14 i2p casts define internal i32 @p2i(i32* %arg) { +; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@p2i ; NOT_CGSCC_NPM-SAME: (i32* noalias nofree readnone [[ARG:%.*]]) ; NOT_CGSCC_NPM-NEXT: [[P2I:%.*]] = ptrtoint i32* [[ARG]] to i32 ; NOT_CGSCC_NPM-NEXT: ret i32 [[P2I]] ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@p2i ; IS__CGSCC____-SAME: (i32* nofree readnone [[ARG:%.*]]) ; IS__CGSCC____-NEXT: [[P2I:%.*]] = ptrtoint i32* [[ARG]] to i32 @@ -491,6 +514,7 @@ } define i32 @i2p(i32* %arg) { +; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind readonly willreturn ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@i2p ; NOT_CGSCC_NPM-SAME: (i32* nofree readonly [[ARG:%.*]]) ; NOT_CGSCC_NPM-NEXT: [[C:%.*]] = call i32 @p2i(i32* noalias nofree readnone [[ARG]]) @@ -499,6 +523,7 @@ ; NOT_CGSCC_NPM-NEXT: [[CALL:%.*]] = call i32 @ret(i32* nocapture nofree readonly align 4 [[BC]]) ; NOT_CGSCC_NPM-NEXT: ret i32 [[CALL]] ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@i2p ; IS__CGSCC____-SAME: (i32* nofree readonly [[ARG:%.*]]) ; IS__CGSCC____-NEXT: [[C:%.*]] = call i32 @p2i(i32* noalias nofree readnone [[ARG]]) @@ -514,10 +539,17 @@ ret i32 %call } define internal i32 @ret(i32* %arg) { -; CHECK-LABEL: define {{[^@]+}}@ret -; CHECK-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[ARG:%.*]]) -; CHECK-NEXT: [[L:%.*]] = load i32, i32* [[ARG]], align 4 -; CHECK-NEXT: ret i32 [[L]] +; NOT_CGSCC_NPM: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@ret +; NOT_CGSCC_NPM-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[ARG:%.*]]) +; NOT_CGSCC_NPM-NEXT: [[L:%.*]] = load i32, i32* [[ARG]], align 4 +; NOT_CGSCC_NPM-NEXT: ret i32 [[L]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@ret +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[ARG:%.*]]) +; IS__CGSCC____-NEXT: [[L:%.*]] = load i32, i32* [[ARG]], align 4 +; IS__CGSCC____-NEXT: ret i32 [[L]] ; %l = load i32, i32* %arg ret i32 %l @@ -591,26 +623,41 @@ @alias_of_p = external global i32* define void @make_alias(i32* %p) { -; CHECK-LABEL: define {{[^@]+}}@make_alias -; CHECK-SAME: (i32* nofree writeonly [[P:%.*]]) -; CHECK-NEXT: store i32* [[P]], i32** @alias_of_p, align 8 -; CHECK-NEXT: ret void +; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn writeonly +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@make_alias +; NOT_CGSCC_NPM-SAME: (i32* nofree writeonly [[P:%.*]]) +; NOT_CGSCC_NPM-NEXT: store i32* [[P]], i32** @alias_of_p, align 8 +; NOT_CGSCC_NPM-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@make_alias +; IS__CGSCC____-SAME: (i32* nofree writeonly [[P:%.*]]) +; IS__CGSCC____-NEXT: store i32* [[P]], i32** @alias_of_p, align 8 +; IS__CGSCC____-NEXT: ret void ; store i32* %p, i32** @alias_of_p ret void } define void @only_store(i32* %p) { -; CHECK-LABEL: define {{[^@]+}}@only_store -; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) -; CHECK-NEXT: store i32 0, i32* [[P]], align 4 -; CHECK-NEXT: ret void +; NOT_CGSCC_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@only_store +; NOT_CGSCC_NPM-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) +; NOT_CGSCC_NPM-NEXT: store i32 0, i32* [[P]], align 4 +; NOT_CGSCC_NPM-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@only_store +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[P:%.*]]) +; IS__CGSCC____-NEXT: store i32 0, i32* [[P]], align 4 +; IS__CGSCC____-NEXT: ret void ; store i32 0, i32* %p ret void } define void @test15_caller(i32* noalias %p, i32 %c) { +; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn writeonly ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test15_caller ; NOT_CGSCC_NPM-SAME: (i32* noalias nofree writeonly [[P:%.*]], i32 [[C:%.*]]) ; NOT_CGSCC_NPM-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0 @@ -622,6 +669,7 @@ ; NOT_CGSCC_NPM-NEXT: tail call void @make_alias(i32* nofree writeonly [[P]]) ; NOT_CGSCC_NPM-NEXT: ret void ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@test15_caller ; IS__CGSCC____-SAME: (i32* noalias nofree writeonly [[P:%.*]], i32 [[C:%.*]]) ; IS__CGSCC____-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C]], 0 @@ -666,6 +714,7 @@ ; Therefore, only one of the two conditions of if statementes will be fulfilled. define internal void @test16_sub(i32* noalias %p, i32 %c1, i32 %c2) { +; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn writeonly ; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test16_sub ; NOT_CGSCC_NPM-SAME: (i32* noalias nofree writeonly [[P:%.*]], i32 [[C1:%.*]], i32 [[C2:%.*]]) ; NOT_CGSCC_NPM-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C1]], 0 @@ -683,6 +732,7 @@ ; NOT_CGSCC_NPM: if.end3: ; NOT_CGSCC_NPM-NEXT: ret void ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@test16_sub ; IS__CGSCC____-SAME: (i32* noalias nofree writeonly [[P:%.*]], i32 [[C1:%.*]], i32 [[C2:%.*]]) ; IS__CGSCC____-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[C1]], 0 @@ -721,10 +771,17 @@ } define void @test16_caller(i32* %p, i32 %c) { -; CHECK-LABEL: define {{[^@]+}}@test16_caller -; CHECK-SAME: (i32* nofree writeonly [[P:%.*]], i32 [[C:%.*]]) -; CHECK-NEXT: tail call void @test16_sub(i32* noalias nofree writeonly [[P]], i32 [[C]], i32 [[C]]) -; CHECK-NEXT: ret void +; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind willreturn writeonly +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test16_caller +; NOT_CGSCC_NPM-SAME: (i32* nofree writeonly [[P:%.*]], i32 [[C:%.*]]) +; NOT_CGSCC_NPM-NEXT: tail call void @test16_sub(i32* noalias nofree writeonly [[P]], i32 [[C]], i32 [[C]]) +; NOT_CGSCC_NPM-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@test16_caller +; IS__CGSCC____-SAME: (i32* nofree writeonly [[P:%.*]], i32 [[C:%.*]]) +; IS__CGSCC____-NEXT: tail call void @test16_sub(i32* noalias nofree writeonly [[P]], i32 [[C]], i32 [[C]]) +; IS__CGSCC____-NEXT: ret void ; tail call void @test16_sub(i32* %p, i32 %c, i32 %c) ret void 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 @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -7,45 +7,78 @@ @g = global i32* null ; [#uses=1] define i32* @c1(i32* %q) { -; CHECK-LABEL: define {{[^@]+}}@c1 -; CHECK-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[Q:%.*]]) -; CHECK-NEXT: ret i32* [[Q]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@c1 +; IS__TUNIT____-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[Q:%.*]]) +; IS__TUNIT____-NEXT: ret i32* [[Q]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@c1 +; IS__CGSCC____-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[Q:%.*]]) +; IS__CGSCC____-NEXT: ret i32* [[Q]] ; ret i32* %q } ; It would also be acceptable to mark %q as readnone. Update @c3 too. define void @c2(i32* %q) { -; CHECK-LABEL: define {{[^@]+}}@c2 -; CHECK-SAME: (i32* nofree writeonly [[Q:%.*]]) -; CHECK-NEXT: store i32* [[Q]], i32** @g, align 8 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@c2 +; IS__TUNIT____-SAME: (i32* nofree writeonly [[Q:%.*]]) +; IS__TUNIT____-NEXT: store i32* [[Q]], i32** @g, align 8 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@c2 +; IS__CGSCC____-SAME: (i32* nofree writeonly [[Q:%.*]]) +; IS__CGSCC____-NEXT: store i32* [[Q]], i32** @g, align 8 +; IS__CGSCC____-NEXT: ret void ; store i32* %q, i32** @g ret void } define void @c3(i32* %q) { -; CHECK-LABEL: define {{[^@]+}}@c3 -; CHECK-SAME: (i32* nofree writeonly [[Q:%.*]]) -; CHECK-NEXT: call void @c2(i32* nofree writeonly [[Q]]) -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@c3 +; IS__TUNIT____-SAME: (i32* nofree writeonly [[Q:%.*]]) +; IS__TUNIT____-NEXT: call void @c2(i32* nofree writeonly [[Q]]) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@c3 +; IS__CGSCC____-SAME: (i32* nofree writeonly [[Q:%.*]]) +; IS__CGSCC____-NEXT: call void @c2(i32* nofree writeonly [[Q]]) +; IS__CGSCC____-NEXT: ret void ; call void @c2(i32* %q) ret void } define i1 @c4(i32* %q, i32 %bitno) { -; CHECK-LABEL: define {{[^@]+}}@c4 -; CHECK-SAME: (i32* nofree readnone [[Q:%.*]], i32 [[BITNO:%.*]]) -; CHECK-NEXT: [[TMP:%.*]] = ptrtoint i32* [[Q]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]] -; CHECK-NEXT: [[BIT:%.*]] = trunc i32 [[TMP2]] to i1 -; CHECK-NEXT: br i1 [[BIT]], label [[L1:%.*]], label [[L0:%.*]] -; CHECK: l0: -; CHECK-NEXT: ret i1 false -; CHECK: l1: -; CHECK-NEXT: ret i1 true +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@c4 +; IS__TUNIT____-SAME: (i32* nofree readnone [[Q:%.*]], i32 [[BITNO:%.*]]) +; IS__TUNIT____-NEXT: [[TMP:%.*]] = ptrtoint i32* [[Q]] to i32 +; IS__TUNIT____-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]] +; IS__TUNIT____-NEXT: [[BIT:%.*]] = trunc i32 [[TMP2]] to i1 +; IS__TUNIT____-NEXT: br i1 [[BIT]], label [[L1:%.*]], label [[L0:%.*]] +; IS__TUNIT____: l0: +; IS__TUNIT____-NEXT: ret i1 false +; IS__TUNIT____: l1: +; IS__TUNIT____-NEXT: ret i1 true +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@c4 +; IS__CGSCC____-SAME: (i32* nofree readnone [[Q:%.*]], i32 [[BITNO:%.*]]) +; IS__CGSCC____-NEXT: [[TMP:%.*]] = ptrtoint i32* [[Q]] to i32 +; IS__CGSCC____-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]] +; IS__CGSCC____-NEXT: [[BIT:%.*]] = trunc i32 [[TMP2]] to i1 +; IS__CGSCC____-NEXT: br i1 [[BIT]], label [[L1:%.*]], label [[L0:%.*]] +; IS__CGSCC____: l0: +; IS__CGSCC____-NEXT: ret i1 false +; IS__CGSCC____: l1: +; IS__CGSCC____-NEXT: ret i1 true ; %tmp = ptrtoint i32* %q to i32 %tmp2 = lshr i32 %tmp, %bitno @@ -59,16 +92,29 @@ ; c4b is c4 but without the escaping part define i1 @c4b(i32* %q, i32 %bitno) { -; CHECK-LABEL: define {{[^@]+}}@c4b -; CHECK-SAME: (i32* nocapture nofree readnone [[Q:%.*]], i32 [[BITNO:%.*]]) -; CHECK-NEXT: [[TMP:%.*]] = ptrtoint i32* [[Q]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]] -; CHECK-NEXT: [[BIT:%.*]] = trunc i32 [[TMP2]] to i1 -; CHECK-NEXT: br i1 [[BIT]], label [[L1:%.*]], label [[L0:%.*]] -; CHECK: l0: -; CHECK-NEXT: ret i1 false -; CHECK: l1: -; CHECK-NEXT: ret i1 false +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@c4b +; IS__TUNIT____-SAME: (i32* nocapture nofree readnone [[Q:%.*]], i32 [[BITNO:%.*]]) +; IS__TUNIT____-NEXT: [[TMP:%.*]] = ptrtoint i32* [[Q]] to i32 +; IS__TUNIT____-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]] +; IS__TUNIT____-NEXT: [[BIT:%.*]] = trunc i32 [[TMP2]] to i1 +; IS__TUNIT____-NEXT: br i1 [[BIT]], label [[L1:%.*]], label [[L0:%.*]] +; IS__TUNIT____: l0: +; IS__TUNIT____-NEXT: ret i1 false +; IS__TUNIT____: l1: +; IS__TUNIT____-NEXT: ret i1 false +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@c4b +; IS__CGSCC____-SAME: (i32* nocapture nofree readnone [[Q:%.*]], i32 [[BITNO:%.*]]) +; IS__CGSCC____-NEXT: [[TMP:%.*]] = ptrtoint i32* [[Q]] to i32 +; IS__CGSCC____-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]] +; IS__CGSCC____-NEXT: [[BIT:%.*]] = trunc i32 [[TMP2]] to i1 +; IS__CGSCC____-NEXT: br i1 [[BIT]], label [[L1:%.*]], label [[L0:%.*]] +; IS__CGSCC____: l0: +; IS__CGSCC____-NEXT: ret i1 false +; IS__CGSCC____: l1: +; IS__CGSCC____-NEXT: ret i1 false ; %tmp = ptrtoint i32* %q to i32 %tmp2 = lshr i32 %tmp, %bitno @@ -83,14 +129,25 @@ @lookup_table = global [2 x i1] [ i1 0, i1 1 ] define i1 @c5(i32* %q, i32 %bitno) { -; CHECK-LABEL: define {{[^@]+}}@c5 -; CHECK-SAME: (i32* nofree readonly [[Q:%.*]], i32 [[BITNO:%.*]]) -; CHECK-NEXT: [[TMP:%.*]] = ptrtoint i32* [[Q]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]] -; CHECK-NEXT: [[BIT:%.*]] = and i32 [[TMP2]], 1 -; CHECK-NEXT: [[LOOKUP:%.*]] = getelementptr [2 x i1], [2 x i1]* @lookup_table, i32 0, i32 [[BIT]] -; CHECK-NEXT: [[VAL:%.*]] = load i1, i1* [[LOOKUP]], align 1 -; CHECK-NEXT: ret i1 [[VAL]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@c5 +; IS__TUNIT____-SAME: (i32* nofree readonly [[Q:%.*]], i32 [[BITNO:%.*]]) +; IS__TUNIT____-NEXT: [[TMP:%.*]] = ptrtoint i32* [[Q]] to i32 +; IS__TUNIT____-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]] +; IS__TUNIT____-NEXT: [[BIT:%.*]] = and i32 [[TMP2]], 1 +; IS__TUNIT____-NEXT: [[LOOKUP:%.*]] = getelementptr [2 x i1], [2 x i1]* @lookup_table, i32 0, i32 [[BIT]] +; IS__TUNIT____-NEXT: [[VAL:%.*]] = load i1, i1* [[LOOKUP]], align 1 +; IS__TUNIT____-NEXT: ret i1 [[VAL]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@c5 +; IS__CGSCC____-SAME: (i32* nofree readonly [[Q:%.*]], i32 [[BITNO:%.*]]) +; IS__CGSCC____-NEXT: [[TMP:%.*]] = ptrtoint i32* [[Q]] to i32 +; IS__CGSCC____-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]] +; IS__CGSCC____-NEXT: [[BIT:%.*]] = and i32 [[TMP2]], 1 +; IS__CGSCC____-NEXT: [[LOOKUP:%.*]] = getelementptr [2 x i1], [2 x i1]* @lookup_table, i32 0, i32 [[BIT]] +; IS__CGSCC____-NEXT: [[VAL:%.*]] = load i1, i1* [[LOOKUP]], align 1 +; IS__CGSCC____-NEXT: ret i1 [[VAL]] ; %tmp = ptrtoint i32* %q to i32 %tmp2 = lshr i32 %tmp, %bitno @@ -104,6 +161,7 @@ declare void @throw_if_bit_set(i8*, i8) readonly define i1 @c6(i8* %q, i8 %bit) personality i32 (...)* @__gxx_personality_v0 { +; CHECK: Function Attrs: nounwind readonly ; CHECK-LABEL: define {{[^@]+}}@c6 ; CHECK-SAME: (i8* readonly [[Q:%.*]], i8 [[BIT:%.*]]) #4 personality i32 (...)* @__gxx_personality_v0 ; CHECK-NEXT: invoke void @throw_if_bit_set(i8* readonly [[Q]], i8 [[BIT]]) @@ -128,13 +186,23 @@ declare i32 @__gxx_personality_v0(...) define i1* @lookup_bit(i32* %q, i32 %bitno) readnone nounwind { -; CHECK-LABEL: define {{[^@]+}}@lookup_bit -; CHECK-SAME: (i32* nofree readnone [[Q:%.*]], i32 [[BITNO:%.*]]) -; CHECK-NEXT: [[TMP:%.*]] = ptrtoint i32* [[Q]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]] -; CHECK-NEXT: [[BIT:%.*]] = and i32 [[TMP2]], 1 -; CHECK-NEXT: [[LOOKUP:%.*]] = getelementptr [2 x i1], [2 x i1]* @lookup_table, i32 0, i32 [[BIT]] -; CHECK-NEXT: ret i1* [[LOOKUP]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@lookup_bit +; IS__TUNIT____-SAME: (i32* nofree readnone [[Q:%.*]], i32 [[BITNO:%.*]]) +; IS__TUNIT____-NEXT: [[TMP:%.*]] = ptrtoint i32* [[Q]] to i32 +; IS__TUNIT____-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]] +; IS__TUNIT____-NEXT: [[BIT:%.*]] = and i32 [[TMP2]], 1 +; IS__TUNIT____-NEXT: [[LOOKUP:%.*]] = getelementptr [2 x i1], [2 x i1]* @lookup_table, i32 0, i32 [[BIT]] +; IS__TUNIT____-NEXT: ret i1* [[LOOKUP]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@lookup_bit +; IS__CGSCC____-SAME: (i32* nofree readnone [[Q:%.*]], i32 [[BITNO:%.*]]) +; IS__CGSCC____-NEXT: [[TMP:%.*]] = ptrtoint i32* [[Q]] to i32 +; IS__CGSCC____-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP]], [[BITNO]] +; IS__CGSCC____-NEXT: [[BIT:%.*]] = and i32 [[TMP2]], 1 +; IS__CGSCC____-NEXT: [[LOOKUP:%.*]] = getelementptr [2 x i1], [2 x i1]* @lookup_table, i32 0, i32 [[BIT]] +; IS__CGSCC____-NEXT: ret i1* [[LOOKUP]] ; %tmp = ptrtoint i32* %q to i32 %tmp2 = lshr i32 %tmp, %bitno @@ -144,11 +212,19 @@ } define i1 @c7(i32* %q, i32 %bitno) { -; CHECK-LABEL: define {{[^@]+}}@c7 -; CHECK-SAME: (i32* nofree readonly [[Q:%.*]], i32 [[BITNO:%.*]]) -; CHECK-NEXT: [[PTR:%.*]] = call i1* @lookup_bit(i32* noalias nofree readnone [[Q]], i32 [[BITNO]]) -; CHECK-NEXT: [[VAL:%.*]] = load i1, i1* [[PTR]], align 1 -; CHECK-NEXT: ret i1 [[VAL]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@c7 +; IS__TUNIT____-SAME: (i32* nofree readonly [[Q:%.*]], i32 [[BITNO:%.*]]) +; IS__TUNIT____-NEXT: [[PTR:%.*]] = call i1* @lookup_bit(i32* noalias nofree readnone [[Q]], i32 [[BITNO]]) +; IS__TUNIT____-NEXT: [[VAL:%.*]] = load i1, i1* [[PTR]], align 1 +; IS__TUNIT____-NEXT: ret i1 [[VAL]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@c7 +; IS__CGSCC____-SAME: (i32* nofree readonly [[Q:%.*]], i32 [[BITNO:%.*]]) +; IS__CGSCC____-NEXT: [[PTR:%.*]] = call i1* @lookup_bit(i32* noalias nofree readnone [[Q]], i32 [[BITNO]]) +; IS__CGSCC____-NEXT: [[VAL:%.*]] = load i1, i1* [[PTR]], align 1 +; IS__CGSCC____-NEXT: ret i1 [[VAL]] ; %ptr = call i1* @lookup_bit(i32* %q, i32 %bitno) %val = load i1, i1* %ptr @@ -157,19 +233,35 @@ define i32 @nc1(i32* %q, i32* %p, i1 %b) { -; CHECK-LABEL: define {{[^@]+}}@nc1 -; CHECK-SAME: (i32* nofree [[Q:%.*]], i32* nocapture nofree [[P:%.*]], i1 [[B:%.*]]) -; CHECK-NEXT: e: -; CHECK-NEXT: br label [[L:%.*]] -; CHECK: l: -; CHECK-NEXT: [[X:%.*]] = phi i32* [ [[P]], [[E:%.*]] ] -; CHECK-NEXT: [[Y:%.*]] = phi i32* [ [[Q]], [[E]] ] -; CHECK-NEXT: [[TMP:%.*]] = bitcast i32* [[X]] to i32* -; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[B]], i32* [[TMP]], i32* [[Y]] -; CHECK-NEXT: [[VAL:%.*]] = load i32, i32* [[TMP2]], align 4 -; CHECK-NEXT: store i32 0, i32* [[TMP]], align 4 -; CHECK-NEXT: store i32* [[Y]], i32** @g, align 8 -; CHECK-NEXT: ret i32 [[VAL]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@nc1 +; IS__TUNIT____-SAME: (i32* nofree [[Q:%.*]], i32* nocapture nofree [[P:%.*]], i1 [[B:%.*]]) +; IS__TUNIT____-NEXT: e: +; IS__TUNIT____-NEXT: br label [[L:%.*]] +; IS__TUNIT____: l: +; IS__TUNIT____-NEXT: [[X:%.*]] = phi i32* [ [[P]], [[E:%.*]] ] +; IS__TUNIT____-NEXT: [[Y:%.*]] = phi i32* [ [[Q]], [[E]] ] +; IS__TUNIT____-NEXT: [[TMP:%.*]] = bitcast i32* [[X]] to i32* +; IS__TUNIT____-NEXT: [[TMP2:%.*]] = select i1 [[B]], i32* [[TMP]], i32* [[Y]] +; IS__TUNIT____-NEXT: [[VAL:%.*]] = load i32, i32* [[TMP2]], align 4 +; IS__TUNIT____-NEXT: store i32 0, i32* [[TMP]], align 4 +; IS__TUNIT____-NEXT: store i32* [[Y]], i32** @g, align 8 +; IS__TUNIT____-NEXT: ret i32 [[VAL]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@nc1 +; IS__CGSCC____-SAME: (i32* nofree [[Q:%.*]], i32* nocapture nofree [[P:%.*]], i1 [[B:%.*]]) +; IS__CGSCC____-NEXT: e: +; IS__CGSCC____-NEXT: br label [[L:%.*]] +; IS__CGSCC____: l: +; IS__CGSCC____-NEXT: [[X:%.*]] = phi i32* [ [[P]], [[E:%.*]] ] +; IS__CGSCC____-NEXT: [[Y:%.*]] = phi i32* [ [[Q]], [[E]] ] +; IS__CGSCC____-NEXT: [[TMP:%.*]] = bitcast i32* [[X]] to i32* +; IS__CGSCC____-NEXT: [[TMP2:%.*]] = select i1 [[B]], i32* [[TMP]], i32* [[Y]] +; IS__CGSCC____-NEXT: [[VAL:%.*]] = load i32, i32* [[TMP2]], align 4 +; IS__CGSCC____-NEXT: store i32 0, i32* [[TMP]], align 4 +; IS__CGSCC____-NEXT: store i32* [[Y]], i32** @g, align 8 +; IS__CGSCC____-NEXT: ret i32 [[VAL]] ; e: br label %l @@ -185,19 +277,35 @@ } define i32 @nc1_addrspace(i32* %q, i32 addrspace(1)* %p, i1 %b) { -; CHECK-LABEL: define {{[^@]+}}@nc1_addrspace -; CHECK-SAME: (i32* nofree [[Q:%.*]], i32 addrspace(1)* nocapture nofree [[P:%.*]], i1 [[B:%.*]]) -; CHECK-NEXT: e: -; CHECK-NEXT: br label [[L:%.*]] -; CHECK: l: -; CHECK-NEXT: [[X:%.*]] = phi i32 addrspace(1)* [ [[P]], [[E:%.*]] ] -; CHECK-NEXT: [[Y:%.*]] = phi i32* [ [[Q]], [[E]] ] -; CHECK-NEXT: [[TMP:%.*]] = addrspacecast i32 addrspace(1)* [[X]] to i32* -; CHECK-NEXT: [[TMP2:%.*]] = select i1 [[B]], i32* [[TMP]], i32* [[Y]] -; CHECK-NEXT: [[VAL:%.*]] = load i32, i32* [[TMP2]], align 4 -; CHECK-NEXT: store i32 0, i32* [[TMP]], align 4 -; CHECK-NEXT: store i32* [[Y]], i32** @g, align 8 -; CHECK-NEXT: ret i32 [[VAL]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@nc1_addrspace +; IS__TUNIT____-SAME: (i32* nofree [[Q:%.*]], i32 addrspace(1)* nocapture nofree [[P:%.*]], i1 [[B:%.*]]) +; IS__TUNIT____-NEXT: e: +; IS__TUNIT____-NEXT: br label [[L:%.*]] +; IS__TUNIT____: l: +; IS__TUNIT____-NEXT: [[X:%.*]] = phi i32 addrspace(1)* [ [[P]], [[E:%.*]] ] +; IS__TUNIT____-NEXT: [[Y:%.*]] = phi i32* [ [[Q]], [[E]] ] +; IS__TUNIT____-NEXT: [[TMP:%.*]] = addrspacecast i32 addrspace(1)* [[X]] to i32* +; IS__TUNIT____-NEXT: [[TMP2:%.*]] = select i1 [[B]], i32* [[TMP]], i32* [[Y]] +; IS__TUNIT____-NEXT: [[VAL:%.*]] = load i32, i32* [[TMP2]], align 4 +; IS__TUNIT____-NEXT: store i32 0, i32* [[TMP]], align 4 +; IS__TUNIT____-NEXT: store i32* [[Y]], i32** @g, align 8 +; IS__TUNIT____-NEXT: ret i32 [[VAL]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@nc1_addrspace +; IS__CGSCC____-SAME: (i32* nofree [[Q:%.*]], i32 addrspace(1)* nocapture nofree [[P:%.*]], i1 [[B:%.*]]) +; IS__CGSCC____-NEXT: e: +; IS__CGSCC____-NEXT: br label [[L:%.*]] +; IS__CGSCC____: l: +; IS__CGSCC____-NEXT: [[X:%.*]] = phi i32 addrspace(1)* [ [[P]], [[E:%.*]] ] +; IS__CGSCC____-NEXT: [[Y:%.*]] = phi i32* [ [[Q]], [[E]] ] +; IS__CGSCC____-NEXT: [[TMP:%.*]] = addrspacecast i32 addrspace(1)* [[X]] to i32* +; IS__CGSCC____-NEXT: [[TMP2:%.*]] = select i1 [[B]], i32* [[TMP]], i32* [[Y]] +; IS__CGSCC____-NEXT: [[VAL:%.*]] = load i32, i32* [[TMP2]], align 4 +; IS__CGSCC____-NEXT: store i32 0, i32* [[TMP]], align 4 +; IS__CGSCC____-NEXT: store i32* [[Y]], i32** @g, align 8 +; IS__CGSCC____-NEXT: ret i32 [[VAL]] ; e: br label %l @@ -213,10 +321,17 @@ } define void @nc2(i32* %p, i32* %q) { -; CHECK-LABEL: define {{[^@]+}}@nc2 -; CHECK-SAME: (i32* nocapture nofree [[P:%.*]], i32* nofree [[Q:%.*]]) -; CHECK-NEXT: [[TMP1:%.*]] = call i32 @nc1(i32* nofree [[Q]], i32* nocapture nofree [[P]], i1 false) -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@nc2 +; IS__TUNIT____-SAME: (i32* nocapture nofree [[P:%.*]], i32* nofree [[Q:%.*]]) +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = call i32 @nc1(i32* nofree [[Q]], i32* nocapture nofree [[P]], i1 false) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@nc2 +; IS__CGSCC____-SAME: (i32* nocapture nofree [[P:%.*]], i32* nofree [[Q:%.*]]) +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @nc1(i32* nofree [[Q]], i32* nocapture nofree [[P]], i1 false) +; IS__CGSCC____-NEXT: ret void ; %1 = call i32 @nc1(i32* %q, i32* %p, i1 0) ; [#uses=0] ret void @@ -237,6 +352,7 @@ ; FIXME: readonly and nocapture missing on the pointer. declare void @external(i8* readonly) nounwind argmemonly define void @nc4(i8* %p) { +; CHECK: Function Attrs: argmemonly nounwind ; CHECK-LABEL: define {{[^@]+}}@nc4 ; CHECK-SAME: (i8* [[P:%.*]]) ; CHECK-NEXT: call void @external(i8* readonly [[P]]) @@ -259,6 +375,7 @@ ; It would be acceptable to add readnone to %y1_1 and %y1_2. define void @test1_1(i8* %x1_1, i8* %y1_1, i1 %c) { +; CHECK: Function Attrs: nofree nosync nounwind writeonly ; CHECK-LABEL: define {{[^@]+}}@test1_1 ; CHECK-SAME: (i8* nocapture nofree readnone [[X1_1:%.*]], i8* nocapture nofree readnone [[Y1_1:%.*]], i1 [[C:%.*]]) ; CHECK-NEXT: [[TMP1:%.*]] = call i8* @test1_2(i8* noalias nocapture nofree readnone undef, i8* noalias nofree readnone "no-capture-maybe-returned" [[Y1_1]], i1 [[C]]) @@ -271,6 +388,7 @@ } define i8* @test1_2(i8* %x1_2, i8* %y1_2, i1 %c) { +; CHECK: Function Attrs: nofree nosync nounwind writeonly ; CHECK-LABEL: define {{[^@]+}}@test1_2 ; CHECK-SAME: (i8* nocapture nofree readnone [[X1_2:%.*]], i8* nofree readnone returned "no-capture-maybe-returned" [[Y1_2:%.*]], i1 [[C:%.*]]) ; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] @@ -291,9 +409,15 @@ } define void @test2(i8* %x2) { -; CHECK-LABEL: define {{[^@]+}}@test2 -; CHECK-SAME: (i8* nocapture nofree readnone [[X2:%.*]]) -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree noreturn nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test2 +; IS__TUNIT____-SAME: (i8* nocapture nofree readnone [[X2:%.*]]) +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test2 +; IS__CGSCC____-SAME: (i8* nocapture nofree readnone [[X2:%.*]]) +; IS__CGSCC____-NEXT: unreachable ; call void @test2(i8* %x2) store i32* null, i32** @g @@ -301,9 +425,15 @@ } define void @test3(i8* %x3, i8* %y3, i8* %z3) { -; CHECK-LABEL: define {{[^@]+}}@test3 -; CHECK-SAME: (i8* nocapture nofree readnone [[X3:%.*]], i8* nocapture nofree readnone [[Y3:%.*]], i8* nocapture nofree readnone [[Z3:%.*]]) -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree noreturn nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test3 +; IS__TUNIT____-SAME: (i8* nocapture nofree readnone [[X3:%.*]], i8* nocapture nofree readnone [[Y3:%.*]], i8* nocapture nofree readnone [[Z3:%.*]]) +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test3 +; IS__CGSCC____-SAME: (i8* nocapture nofree readnone [[X3:%.*]], i8* nocapture nofree readnone [[Y3:%.*]], i8* nocapture nofree readnone [[Z3:%.*]]) +; IS__CGSCC____-NEXT: unreachable ; call void @test3(i8* %z3, i8* %y3, i8* %x3) store i32* null, i32** @g @@ -311,6 +441,7 @@ } define void @test4_1(i8* %x4_1, i1 %c) { +; CHECK: Function Attrs: nofree nosync nounwind writeonly ; CHECK-LABEL: define {{[^@]+}}@test4_1 ; CHECK-SAME: (i8* nocapture nofree readnone [[X4_1:%.*]], i1 [[C:%.*]]) ; CHECK-NEXT: [[TMP1:%.*]] = call i8* @test4_2(i8* noalias nocapture nofree readnone undef, i8* noalias nofree readnone "no-capture-maybe-returned" [[X4_1]], i8* noalias nocapture nofree readnone undef, i1 [[C]]) @@ -323,6 +454,7 @@ } define i8* @test4_2(i8* %x4_2, i8* %y4_2, i8* %z4_2, i1 %c) { +; CHECK: Function Attrs: nofree nosync nounwind writeonly ; CHECK-LABEL: define {{[^@]+}}@test4_2 ; CHECK-SAME: (i8* nocapture nofree readnone [[X4_2:%.*]], i8* nofree readnone returned "no-capture-maybe-returned" [[Y4_2:%.*]], i8* nocapture nofree readnone [[Z4_2:%.*]], i1 [[C:%.*]]) ; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] @@ -371,42 +503,72 @@ } define void @test_cmpxchg(i32* %p) { -; CHECK-LABEL: define {{[^@]+}}@test_cmpxchg -; CHECK-SAME: (i32* nocapture nofree nonnull dereferenceable(4) [[P:%.*]]) -; CHECK-NEXT: [[TMP1:%.*]] = cmpxchg i32* [[P]], i32 0, i32 1 acquire monotonic -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nounwind willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test_cmpxchg +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull dereferenceable(4) [[P:%.*]]) +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = cmpxchg i32* [[P]], i32 0, i32 1 acquire monotonic +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test_cmpxchg +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull dereferenceable(4) [[P:%.*]]) +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = cmpxchg i32* [[P]], i32 0, i32 1 acquire monotonic +; IS__CGSCC____-NEXT: ret void ; cmpxchg i32* %p, i32 0, i32 1 acquire monotonic ret void } define void @test_cmpxchg_ptr(i32** %p, i32* %q) { -; CHECK-LABEL: define {{[^@]+}}@test_cmpxchg_ptr -; CHECK-SAME: (i32** nocapture nofree nonnull dereferenceable(8) [[P:%.*]], i32* nofree [[Q:%.*]]) -; CHECK-NEXT: [[TMP1:%.*]] = cmpxchg i32** [[P]], i32* null, i32* [[Q]] acquire monotonic -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nounwind willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test_cmpxchg_ptr +; IS__TUNIT____-SAME: (i32** nocapture nofree nonnull dereferenceable(8) [[P:%.*]], i32* nofree [[Q:%.*]]) +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = cmpxchg i32** [[P]], i32* null, i32* [[Q]] acquire monotonic +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test_cmpxchg_ptr +; IS__CGSCC____-SAME: (i32** nocapture nofree nonnull dereferenceable(8) [[P:%.*]], i32* nofree [[Q:%.*]]) +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = cmpxchg i32** [[P]], i32* null, i32* [[Q]] acquire monotonic +; IS__CGSCC____-NEXT: ret void ; cmpxchg i32** %p, i32* null, i32* %q acquire monotonic ret void } define void @test_atomicrmw(i32* %p) { -; CHECK-LABEL: define {{[^@]+}}@test_atomicrmw -; CHECK-SAME: (i32* nocapture nofree nonnull dereferenceable(4) [[P:%.*]]) -; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw add i32* [[P]], i32 1 seq_cst -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nounwind willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test_atomicrmw +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull dereferenceable(4) [[P:%.*]]) +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = atomicrmw add i32* [[P]], i32 1 seq_cst +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test_atomicrmw +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull dereferenceable(4) [[P:%.*]]) +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = atomicrmw add i32* [[P]], i32 1 seq_cst +; IS__CGSCC____-NEXT: ret void ; atomicrmw add i32* %p, i32 1 seq_cst ret void } define void @test_volatile(i32* %x) { -; CHECK-LABEL: define {{[^@]+}}@test_volatile -; CHECK-SAME: (i32* nofree align 4 [[X:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, i32* [[X]], i64 1 -; CHECK-NEXT: store volatile i32 0, i32* [[GEP]], align 4 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nounwind willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test_volatile +; IS__TUNIT____-SAME: (i32* nofree align 4 [[X:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[GEP:%.*]] = getelementptr i32, i32* [[X]], i64 1 +; IS__TUNIT____-NEXT: store volatile i32 0, i32* [[GEP]], align 4 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test_volatile +; IS__CGSCC____-SAME: (i32* nofree align 4 [[X:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[GEP:%.*]] = getelementptr i32, i32* [[X]], i64 1 +; IS__CGSCC____-NEXT: store volatile i32 0, i32* [[GEP]], align 4 +; IS__CGSCC____-NEXT: ret void ; entry: %gep = getelementptr i32, i32* %x, i64 1 @@ -415,6 +577,7 @@ } define void @nocaptureLaunder(i8* %p) { +; CHECK: Function Attrs: nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@nocaptureLaunder ; CHECK-SAME: (i8* nocapture [[P:%.*]]) ; CHECK-NEXT: entry: @@ -430,6 +593,7 @@ @g2 = global i8* null define void @captureLaunder(i8* %p) { +; CHECK: Function Attrs: nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@captureLaunder ; CHECK-SAME: (i8* [[P:%.*]]) ; CHECK-NEXT: [[B:%.*]] = call i8* @llvm.launder.invariant.group.p0i8(i8* [[P]]) @@ -442,6 +606,7 @@ } define void @nocaptureStrip(i8* %p) { +; CHECK: Function Attrs: nosync nounwind willreturn writeonly ; CHECK-LABEL: define {{[^@]+}}@nocaptureStrip ; CHECK-SAME: (i8* nocapture writeonly [[P:%.*]]) ; CHECK-NEXT: entry: @@ -457,6 +622,7 @@ @g3 = global i8* null define void @captureStrip(i8* %p) { +; CHECK: Function Attrs: nosync nounwind willreturn writeonly ; CHECK-LABEL: define {{[^@]+}}@captureStrip ; CHECK-SAME: (i8* writeonly [[P:%.*]]) ; CHECK-NEXT: [[B:%.*]] = call i8* @llvm.strip.invariant.group.p0i8(i8* noalias readnone [[P]]) @@ -469,32 +635,55 @@ } define i1 @captureICmp(i32* %x) { -; CHECK-LABEL: define {{[^@]+}}@captureICmp -; CHECK-SAME: (i32* nofree readnone [[X:%.*]]) -; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32* [[X]], null -; CHECK-NEXT: ret i1 [[TMP1]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@captureICmp +; IS__TUNIT____-SAME: (i32* nofree readnone [[X:%.*]]) +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = icmp eq i32* [[X]], null +; IS__TUNIT____-NEXT: ret i1 [[TMP1]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@captureICmp +; IS__CGSCC____-SAME: (i32* nofree readnone [[X:%.*]]) +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = icmp eq i32* [[X]], null +; IS__CGSCC____-NEXT: ret i1 [[TMP1]] ; %1 = icmp eq i32* %x, null ret i1 %1 } define i1 @captureICmpRev(i32* %x) { -; CHECK-LABEL: define {{[^@]+}}@captureICmpRev -; CHECK-SAME: (i32* nofree readnone [[X:%.*]]) -; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32* null, [[X]] -; CHECK-NEXT: ret i1 [[TMP1]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@captureICmpRev +; IS__TUNIT____-SAME: (i32* nofree readnone [[X:%.*]]) +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = icmp eq i32* null, [[X]] +; IS__TUNIT____-NEXT: ret i1 [[TMP1]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@captureICmpRev +; IS__CGSCC____-SAME: (i32* nofree readnone [[X:%.*]]) +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = icmp eq i32* null, [[X]] +; IS__CGSCC____-NEXT: ret i1 [[TMP1]] ; %1 = icmp eq i32* null, %x ret i1 %1 } define i1 @nocaptureInboundsGEPICmp(i32* %x) { -; CHECK-LABEL: define {{[^@]+}}@nocaptureInboundsGEPICmp -; CHECK-SAME: (i32* nocapture nofree readnone [[X:%.*]]) -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, i32* [[X]], i32 5 -; CHECK-NEXT: [[TMP2:%.*]] = bitcast i32* [[TMP1]] to i8* -; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i8* [[TMP2]], null -; CHECK-NEXT: ret i1 [[TMP3]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@nocaptureInboundsGEPICmp +; IS__TUNIT____-SAME: (i32* nocapture nofree readnone [[X:%.*]]) +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, i32* [[X]], i32 5 +; IS__TUNIT____-NEXT: [[TMP2:%.*]] = bitcast i32* [[TMP1]] to i8* +; IS__TUNIT____-NEXT: [[TMP3:%.*]] = icmp eq i8* [[TMP2]], null +; IS__TUNIT____-NEXT: ret i1 [[TMP3]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@nocaptureInboundsGEPICmp +; IS__CGSCC____-SAME: (i32* nocapture nofree readnone [[X:%.*]]) +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, i32* [[X]], i32 5 +; IS__CGSCC____-NEXT: [[TMP2:%.*]] = bitcast i32* [[TMP1]] to i8* +; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp eq i8* [[TMP2]], null +; IS__CGSCC____-NEXT: ret i1 [[TMP3]] ; %1 = getelementptr inbounds i32, i32* %x, i32 5 %2 = bitcast i32* %1 to i8* @@ -503,12 +692,21 @@ } define i1 @nocaptureInboundsGEPICmpRev(i32* %x) { -; CHECK-LABEL: define {{[^@]+}}@nocaptureInboundsGEPICmpRev -; CHECK-SAME: (i32* nocapture nofree readnone [[X:%.*]]) -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, i32* [[X]], i32 5 -; CHECK-NEXT: [[TMP2:%.*]] = bitcast i32* [[TMP1]] to i8* -; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i8* null, [[TMP2]] -; CHECK-NEXT: ret i1 [[TMP3]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@nocaptureInboundsGEPICmpRev +; IS__TUNIT____-SAME: (i32* nocapture nofree readnone [[X:%.*]]) +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, i32* [[X]], i32 5 +; IS__TUNIT____-NEXT: [[TMP2:%.*]] = bitcast i32* [[TMP1]] to i8* +; IS__TUNIT____-NEXT: [[TMP3:%.*]] = icmp eq i8* null, [[TMP2]] +; IS__TUNIT____-NEXT: ret i1 [[TMP3]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@nocaptureInboundsGEPICmpRev +; IS__CGSCC____-SAME: (i32* nocapture nofree readnone [[X:%.*]]) +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, i32* [[X]], i32 5 +; IS__CGSCC____-NEXT: [[TMP2:%.*]] = bitcast i32* [[TMP1]] to i8* +; IS__CGSCC____-NEXT: [[TMP3:%.*]] = icmp eq i8* null, [[TMP2]] +; IS__CGSCC____-NEXT: ret i1 [[TMP3]] ; %1 = getelementptr inbounds i32, i32* %x, i32 5 %2 = bitcast i32* %1 to i8* @@ -517,11 +715,19 @@ } define i1 @nocaptureDereferenceableOrNullICmp(i32* dereferenceable_or_null(4) %x) { -; CHECK-LABEL: define {{[^@]+}}@nocaptureDereferenceableOrNullICmp -; CHECK-SAME: (i32* nocapture nofree readnone dereferenceable_or_null(4) [[X:%.*]]) -; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[X]] to i8* -; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP1]], null -; CHECK-NEXT: ret i1 [[TMP2]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@nocaptureDereferenceableOrNullICmp +; IS__TUNIT____-SAME: (i32* nocapture nofree readnone dereferenceable_or_null(4) [[X:%.*]]) +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = bitcast i32* [[X]] to i8* +; IS__TUNIT____-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP1]], null +; IS__TUNIT____-NEXT: ret i1 [[TMP2]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@nocaptureDereferenceableOrNullICmp +; IS__CGSCC____-SAME: (i32* nocapture nofree readnone dereferenceable_or_null(4) [[X:%.*]]) +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = bitcast i32* [[X]] to i8* +; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP1]], null +; IS__CGSCC____-NEXT: ret i1 [[TMP2]] ; %1 = bitcast i32* %x to i8* %2 = icmp eq i8* %1, null @@ -529,11 +735,19 @@ } define i1 @captureDereferenceableOrNullICmp(i32* dereferenceable_or_null(4) %x) null_pointer_is_valid { -; CHECK-LABEL: define {{[^@]+}}@captureDereferenceableOrNullICmp -; CHECK-SAME: (i32* nofree readnone dereferenceable_or_null(4) [[X:%.*]]) -; CHECK-NEXT: [[TMP1:%.*]] = bitcast i32* [[X]] to i8* -; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP1]], null -; CHECK-NEXT: ret i1 [[TMP2]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind null_pointer_is_valid readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@captureDereferenceableOrNullICmp +; IS__TUNIT____-SAME: (i32* nofree readnone dereferenceable_or_null(4) [[X:%.*]]) +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = bitcast i32* [[X]] to i8* +; IS__TUNIT____-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP1]], null +; IS__TUNIT____-NEXT: ret i1 [[TMP2]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@captureDereferenceableOrNullICmp +; IS__CGSCC____-SAME: (i32* nofree readnone dereferenceable_or_null(4) [[X:%.*]]) +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = bitcast i32* [[X]] to i8* +; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP1]], null +; IS__CGSCC____-NEXT: ret i1 [[TMP2]] ; %1 = bitcast i32* %x to i8* %2 = icmp eq i8* %1, null @@ -555,6 +769,7 @@ declare i8* @unknownpi8pi8(i8*,i8* returned) define i8* @test_returned1(i8* %A, i8* returned %B) nounwind readonly { +; CHECK: Function Attrs: nounwind readonly ; CHECK-LABEL: define {{[^@]+}}@test_returned1 ; CHECK-SAME: (i8* nocapture readonly [[A:%.*]], i8* readonly returned [[B:%.*]]) ; CHECK-NEXT: entry: @@ -567,6 +782,7 @@ } define i8* @test_returned2(i8* %A, i8* %B) { +; CHECK: Function Attrs: nounwind readonly ; CHECK-LABEL: define {{[^@]+}}@test_returned2 ; CHECK-SAME: (i8* nocapture readonly [[A:%.*]], i8* readonly returned [[B:%.*]]) ; CHECK-NEXT: entry: @@ -584,6 +800,7 @@ ; FIXME: Both pointers should be nocapture define void @ptr_uses(i8* %ptr, i8* %wptr) { +; CHECK: Function Attrs: nounwind ; CHECK-LABEL: define {{[^@]+}}@ptr_uses ; CHECK-SAME: (i8* [[PTR:%.*]], i8* nocapture nonnull writeonly dereferenceable(1) [[WPTR:%.*]]) ; CHECK-NEXT: store i8 0, i8* [[WPTR]], align 1 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 @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=10 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=10 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -18,12 +18,21 @@ ; ; no-capture is missing on %p because it is not dereferenceable define i32 @is_null_return(i32* %p) #0 { -; CHECK-LABEL: define {{[^@]+}}@is_null_return -; CHECK-SAME: (i32* nofree readnone [[P:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32* [[P]], null -; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 -; CHECK-NEXT: ret i32 [[CONV]] +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@is_null_return +; IS__TUNIT____-SAME: (i32* nofree readnone [[P:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp eq i32* [[P]], null +; IS__TUNIT____-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 +; IS__TUNIT____-NEXT: ret i32 [[CONV]] +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@is_null_return +; IS__CGSCC____-SAME: (i32* nofree readnone [[P:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq i32* [[P]], null +; IS__CGSCC____-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 +; IS__CGSCC____-NEXT: ret i32 [[CONV]] ; entry: %cmp = icmp eq i32* %p, null @@ -43,27 +52,51 @@ ; ; no-capture is missing on %p because it is not dereferenceable define i32 @is_null_control(i32* %p) #0 { -; CHECK-LABEL: define {{[^@]+}}@is_null_control -; CHECK-SAME: (i32* nofree [[P:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32* [[P]], null -; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] -; CHECK: if.then: -; CHECK-NEXT: store i32 1, i32* [[RETVAL]], align 4 -; CHECK-NEXT: br label [[RETURN:%.*]] -; CHECK: if.end: -; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32* null, [[P]] -; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[IF_END3:%.*]] -; CHECK: if.then2: -; CHECK-NEXT: store i32 1, i32* [[RETVAL]], align 4 -; CHECK-NEXT: br label [[RETURN]] -; CHECK: if.end3: -; CHECK-NEXT: store i32 0, i32* [[RETVAL]], align 4 -; CHECK-NEXT: br label [[RETURN]] -; CHECK: return: -; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[RETVAL]], align 4 -; CHECK-NEXT: ret i32 [[TMP0]] +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@is_null_control +; IS__TUNIT____-SAME: (i32* nofree [[P:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp eq i32* [[P]], null +; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] +; IS__TUNIT____: if.then: +; IS__TUNIT____-NEXT: store i32 1, i32* [[RETVAL]], align 4 +; IS__TUNIT____-NEXT: br label [[RETURN:%.*]] +; IS__TUNIT____: if.end: +; IS__TUNIT____-NEXT: [[CMP1:%.*]] = icmp eq i32* null, [[P]] +; IS__TUNIT____-NEXT: br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[IF_END3:%.*]] +; IS__TUNIT____: if.then2: +; IS__TUNIT____-NEXT: store i32 1, i32* [[RETVAL]], align 4 +; IS__TUNIT____-NEXT: br label [[RETURN]] +; IS__TUNIT____: if.end3: +; IS__TUNIT____-NEXT: store i32 0, i32* [[RETVAL]], align 4 +; IS__TUNIT____-NEXT: br label [[RETURN]] +; IS__TUNIT____: return: +; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32, i32* [[RETVAL]], align 4 +; IS__TUNIT____-NEXT: ret i32 [[TMP0]] +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@is_null_control +; IS__CGSCC____-SAME: (i32* nofree [[P:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[RETVAL:%.*]] = alloca i32, align 4 +; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq i32* [[P]], null +; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] +; IS__CGSCC____: if.then: +; IS__CGSCC____-NEXT: store i32 1, i32* [[RETVAL]], align 4 +; IS__CGSCC____-NEXT: br label [[RETURN:%.*]] +; IS__CGSCC____: if.end: +; IS__CGSCC____-NEXT: [[CMP1:%.*]] = icmp eq i32* null, [[P]] +; IS__CGSCC____-NEXT: br i1 [[CMP1]], label [[IF_THEN2:%.*]], label [[IF_END3:%.*]] +; IS__CGSCC____: if.then2: +; IS__CGSCC____-NEXT: store i32 1, i32* [[RETVAL]], align 4 +; IS__CGSCC____-NEXT: br label [[RETURN]] +; IS__CGSCC____: if.end3: +; IS__CGSCC____-NEXT: store i32 0, i32* [[RETVAL]], align 4 +; IS__CGSCC____-NEXT: br label [[RETURN]] +; IS__CGSCC____: return: +; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* [[RETVAL]], align 4 +; IS__CGSCC____-NEXT: ret i32 [[TMP0]] ; entry: %retval = alloca i32, align 4 @@ -99,10 +132,17 @@ ; } ; define double* @srec0(double* %a) #0 { -; CHECK-LABEL: define {{[^@]+}}@srec0 -; CHECK-SAME: (double* nocapture nofree readnone [[A:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@srec0 +; IS__TUNIT____-SAME: (double* nocapture nofree readnone [[A:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@srec0 +; IS__CGSCC____-SAME: (double* nocapture nofree readnone [[A:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: unreachable ; entry: %call = call double* @srec0(double* %a) @@ -123,10 +163,17 @@ ; Other arguments are possible here due to the no-return behavior. ; define i32* @srec16(i32* %a) #0 { -; CHECK-LABEL: define {{[^@]+}}@srec16 -; CHECK-SAME: (i32* nocapture nofree readnone [[A:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@srec16 +; IS__TUNIT____-SAME: (i32* nocapture nofree readnone [[A:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@srec16 +; IS__CGSCC____-SAME: (i32* nocapture nofree readnone [[A:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: unreachable ; entry: %call = call i32* @srec16(i32* %a) @@ -162,6 +209,7 @@ ; return scc_A((int*)(scc_A(a) ? scc_B((double*)a) : scc_C(a))); ; } define float* @scc_A(i32* dereferenceable_or_null(4) %a) { +; CHECK: Function Attrs: nofree nosync nounwind readnone ; CHECK-LABEL: define {{[^@]+}}@scc_A ; CHECK-SAME: (i32* nofree readnone returned dereferenceable_or_null(4) "no-capture-maybe-returned" [[A:%.*]]) ; CHECK-NEXT: entry: @@ -207,6 +255,7 @@ } define i64* @scc_B(double* dereferenceable_or_null(8) %a) { +; CHECK: Function Attrs: nofree nosync nounwind readnone ; CHECK-LABEL: define {{[^@]+}}@scc_B ; CHECK-SAME: (double* nofree readnone returned dereferenceable_or_null(8) "no-capture-maybe-returned" [[A:%.*]]) ; CHECK-NEXT: entry: @@ -252,6 +301,7 @@ } define i8* @scc_C(i16* dereferenceable_or_null(2) %a) { +; CHECK: Function Attrs: nofree nosync nounwind readnone ; CHECK-LABEL: define {{[^@]+}}@scc_C ; CHECK-SAME: (i16* nofree readnone returned dereferenceable_or_null(4) "no-capture-maybe-returned" [[A:%.*]]) ; CHECK-NEXT: entry: @@ -311,6 +361,7 @@ declare void @external_no_capture(i32* nocapture) define void @test_external_no_capture(i32* %p) #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@test_external_no_capture ; CHECK-SAME: (i32* nocapture [[P:%.*]]) ; CHECK-NEXT: entry: @@ -329,6 +380,7 @@ ; } ; define void @test_var_arg_call(i8* %p, i32 %a) #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@test_var_arg_call ; CHECK-SAME: (i8* nocapture [[P:%.*]], i32 [[A:%.*]]) ; CHECK-NEXT: entry: @@ -352,11 +404,19 @@ ; ; There should *not* be a no-capture attribute on %a define i64* @not_captured_but_returned_0(i64* %a) #0 { -; CHECK-LABEL: define {{[^@]+}}@not_captured_but_returned_0 -; CHECK-SAME: (i64* nofree nonnull returned writeonly align 8 dereferenceable(8) "no-capture-maybe-returned" [[A:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: store i64 0, i64* [[A]], align 8 -; CHECK-NEXT: ret i64* [[A]] +; IS__TUNIT____: Function Attrs: argmemonly nofree noinline nosync nounwind uwtable willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@not_captured_but_returned_0 +; IS__TUNIT____-SAME: (i64* nofree nonnull returned writeonly align 8 dereferenceable(8) "no-capture-maybe-returned" [[A:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: store i64 0, i64* [[A]], align 8 +; IS__TUNIT____-NEXT: ret i64* [[A]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind uwtable willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@not_captured_but_returned_0 +; IS__CGSCC____-SAME: (i64* nofree nonnull returned writeonly align 8 dereferenceable(8) "no-capture-maybe-returned" [[A:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: store i64 0, i64* [[A]], align 8 +; IS__CGSCC____-NEXT: ret i64* [[A]] ; entry: store i64 0, i64* %a, align 8 @@ -372,12 +432,21 @@ ; ; There should *not* be a no-capture attribute on %a define i64* @not_captured_but_returned_1(i64* %a) #0 { -; CHECK-LABEL: define {{[^@]+}}@not_captured_but_returned_1 -; CHECK-SAME: (i64* nofree nonnull writeonly align 8 dereferenceable(16) "no-capture-maybe-returned" [[A:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i64, i64* [[A]], i64 1 -; CHECK-NEXT: store i64 1, i64* [[ADD_PTR]], align 8 -; CHECK-NEXT: ret i64* [[ADD_PTR]] +; IS__TUNIT____: Function Attrs: argmemonly nofree noinline nosync nounwind uwtable willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@not_captured_but_returned_1 +; IS__TUNIT____-SAME: (i64* nofree nonnull writeonly align 8 dereferenceable(16) "no-capture-maybe-returned" [[A:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i64, i64* [[A]], i64 1 +; IS__TUNIT____-NEXT: store i64 1, i64* [[ADD_PTR]], align 8 +; IS__TUNIT____-NEXT: ret i64* [[ADD_PTR]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind uwtable willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@not_captured_but_returned_1 +; IS__CGSCC____-SAME: (i64* nofree nonnull writeonly align 8 dereferenceable(16) "no-capture-maybe-returned" [[A:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i64, i64* [[A]], i64 1 +; IS__CGSCC____-NEXT: store i64 1, i64* [[ADD_PTR]], align 8 +; IS__CGSCC____-NEXT: ret i64* [[ADD_PTR]] ; entry: %add.ptr = getelementptr inbounds i64, i64* %a, i64 1 @@ -393,6 +462,7 @@ ; } ; define void @test_not_captured_but_returned_calls(i64* %a) #0 { +; IS__TUNIT____: Function Attrs: argmemonly nofree noinline nosync nounwind uwtable willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@test_not_captured_but_returned_calls ; IS__TUNIT____-SAME: (i64* nocapture nofree writeonly align 8 [[A:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -400,6 +470,7 @@ ; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call i64* @not_captured_but_returned_1(i64* nofree writeonly align 8 "no-capture-maybe-returned" [[A]]) ; IS__TUNIT____-NEXT: ret void ; +; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind uwtable willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@test_not_captured_but_returned_calls ; IS__CGSCC____-SAME: (i64* nofree nonnull writeonly align 8 dereferenceable(16) [[A:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -421,12 +492,14 @@ ; ; There should *not* be a no-capture attribute on %a define i64* @negative_test_not_captured_but_returned_call_0a(i64* %a) #0 { +; IS__TUNIT____: Function Attrs: argmemonly nofree noinline nosync nounwind uwtable willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@negative_test_not_captured_but_returned_call_0a ; IS__TUNIT____-SAME: (i64* nofree returned writeonly align 8 "no-capture-maybe-returned" [[A:%.*]]) ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i64* @not_captured_but_returned_0(i64* nofree writeonly align 8 "no-capture-maybe-returned" [[A]]) ; IS__TUNIT____-NEXT: ret i64* [[CALL]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind uwtable willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@negative_test_not_captured_but_returned_call_0a ; IS__CGSCC____-SAME: (i64* nofree nonnull returned writeonly align 8 dereferenceable(8) [[A:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -446,6 +519,7 @@ ; ; There should *not* be a no-capture attribute on %a define void @negative_test_not_captured_but_returned_call_0b(i64* %a) #0 { +; IS__TUNIT____: Function Attrs: argmemonly nofree noinline nosync nounwind uwtable willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@negative_test_not_captured_but_returned_call_0b ; IS__TUNIT____-SAME: (i64* nofree writeonly align 8 [[A:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -454,6 +528,7 @@ ; IS__TUNIT____-NEXT: store i64 [[TMP0]], i64* [[A]], align 8 ; IS__TUNIT____-NEXT: ret void ; +; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind uwtable willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@negative_test_not_captured_but_returned_call_0b ; IS__CGSCC____-SAME: (i64* nofree nonnull writeonly align 8 dereferenceable(8) [[A:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -477,12 +552,14 @@ ; ; There should *not* be a no-capture attribute on %a define i64* @negative_test_not_captured_but_returned_call_1a(i64* %a) #0 { +; IS__TUNIT____: Function Attrs: argmemonly nofree noinline nosync nounwind uwtable willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@negative_test_not_captured_but_returned_call_1a ; IS__TUNIT____-SAME: (i64* nofree writeonly align 8 "no-capture-maybe-returned" [[A:%.*]]) ; IS__TUNIT____-NEXT: entry: ; IS__TUNIT____-NEXT: [[CALL:%.*]] = call nonnull align 8 dereferenceable(8) i64* @not_captured_but_returned_1(i64* nofree writeonly align 8 "no-capture-maybe-returned" [[A]]) ; IS__TUNIT____-NEXT: ret i64* [[CALL]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind uwtable willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@negative_test_not_captured_but_returned_call_1a ; IS__CGSCC____-SAME: (i64* nofree nonnull writeonly align 8 dereferenceable(16) [[A:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -502,6 +579,7 @@ ; ; There should *not* be a no-capture attribute on %a define void @negative_test_not_captured_but_returned_call_1b(i64* %a) #0 { +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind uwtable willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@negative_test_not_captured_but_returned_call_1b ; IS__TUNIT____-SAME: (i64* nofree writeonly align 8 [[A:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -510,6 +588,7 @@ ; IS__TUNIT____-NEXT: store i64 [[TMP0]], i64* [[CALL]], align 8 ; IS__TUNIT____-NEXT: ret void ; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind uwtable willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@negative_test_not_captured_but_returned_call_1b ; IS__CGSCC____-SAME: (i64* nofree nonnull writeonly align 8 dereferenceable(16) [[A:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -537,6 +616,7 @@ ; define i32* @ret_arg_or_unknown(i32* %b) #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@ret_arg_or_unknown ; CHECK-SAME: (i32* [[B:%.*]]) ; CHECK-NEXT: entry: @@ -561,6 +641,7 @@ } define i32* @ret_arg_or_unknown_through_phi(i32* %b) #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@ret_arg_or_unknown_through_phi ; CHECK-SAME: (i32* [[B:%.*]]) ; CHECK-NEXT: entry: @@ -597,6 +678,7 @@ declare i32* @readonly_unknown(i32*, i32*) readonly define void @not_captured_by_readonly_call(i32* %b) #0 { +; CHECK: Function Attrs: noinline nounwind readonly uwtable ; CHECK-LABEL: define {{[^@]+}}@not_captured_by_readonly_call ; CHECK-SAME: (i32* nocapture readonly [[B:%.*]]) ; CHECK-NEXT: entry: @@ -614,6 +696,7 @@ ; Make sure the returned flag on %r is strong enough to justify nocapture on %b but **not** on %r. ; define i32* @not_captured_by_readonly_call_not_returned_either1(i32* %b, i32* returned %r) { +; CHECK: Function Attrs: nounwind readonly ; CHECK-LABEL: define {{[^@]+}}@not_captured_by_readonly_call_not_returned_either1 ; CHECK-SAME: (i32* nocapture readonly [[B:%.*]], i32* readonly returned [[R:%.*]]) ; CHECK-NEXT: entry: @@ -627,6 +710,7 @@ declare i32* @readonly_unknown_r1a(i32*, i32* returned) readonly define i32* @not_captured_by_readonly_call_not_returned_either2(i32* %b, i32* %r) { +; CHECK: Function Attrs: nounwind readonly ; CHECK-LABEL: define {{[^@]+}}@not_captured_by_readonly_call_not_returned_either2 ; CHECK-SAME: (i32* nocapture readonly [[B:%.*]], i32* readonly returned [[R:%.*]]) ; CHECK-NEXT: entry: @@ -640,6 +724,7 @@ declare i32* @readonly_unknown_r1b(i32*, i32* returned) readonly nounwind define i32* @not_captured_by_readonly_call_not_returned_either3(i32* %b, i32* %r) { +; CHECK: Function Attrs: nounwind readonly ; CHECK-LABEL: define {{[^@]+}}@not_captured_by_readonly_call_not_returned_either3 ; CHECK-SAME: (i32* nocapture readonly [[B:%.*]], i32* readonly returned [[R:%.*]]) ; CHECK-NEXT: entry: @@ -652,6 +737,7 @@ } define i32* @not_captured_by_readonly_call_not_returned_either4(i32* %b, i32* %r) nounwind { +; CHECK: Function Attrs: nounwind readonly ; CHECK-LABEL: define {{[^@]+}}@not_captured_by_readonly_call_not_returned_either4 ; CHECK-SAME: (i32* nocapture readonly [[B:%.*]], i32* readonly returned [[R:%.*]]) ; CHECK-NEXT: entry: diff --git a/llvm/test/Transforms/Attributor/nofree.ll b/llvm/test/Transforms/Attributor/nofree.ll --- a/llvm/test/Transforms/Attributor/nofree.ll +++ b/llvm/test/Transforms/Attributor/nofree.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=11 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=11 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -16,11 +16,14 @@ ; TEST 1 (positive case) -; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable -; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable define void @only_return() #0 { -; CHECK-LABEL: define {{[^@]+}}@only_return() -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@only_return() +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@only_return() +; IS__CGSCC____-NEXT: ret void ; ret void } @@ -32,9 +35,8 @@ ; free(p); ; } -; CHECK: Function Attrs: noinline nounwind uwtable -; CHECK-NOT: nofree define void @only_free(i8* nocapture %0) local_unnamed_addr #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@only_free ; CHECK-SAME: (i8* nocapture [[TMP0:%.*]]) local_unnamed_addr ; CHECK-NEXT: tail call void @free(i8* nocapture [[TMP0]]) @@ -57,6 +59,7 @@ define void @free_in_scc1(i8* nocapture %0) local_unnamed_addr #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@free_in_scc1 ; CHECK-SAME: (i8* nocapture [[TMP0:%.*]]) local_unnamed_addr ; CHECK-NEXT: tail call void @free_in_scc2(i8* nocapture [[TMP0]]) @@ -67,9 +70,8 @@ } -; CHECK: Function Attrs: noinline nounwind uwtable -; CHECK-NOT: nofree define void @free_in_scc2(i8* nocapture %0) local_unnamed_addr #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@free_in_scc2 ; CHECK-SAME: (i8* nocapture [[TMP0:%.*]]) local_unnamed_addr ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8* [[TMP0]], null @@ -106,21 +108,27 @@ ; } -; NOT_CGSCC_NPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable -; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable define void @mutual_recursion1() #0 { -; CHECK-LABEL: define {{[^@]+}}@mutual_recursion1() -; CHECK-NEXT: unreachable +; NOT_CGSCC_NPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable willreturn +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@mutual_recursion1() +; NOT_CGSCC_NPM-NEXT: unreachable +; +; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@mutual_recursion1() +; IS__CGSCC_NPM-NEXT: unreachable ; call void @mutual_recursion2() ret void } -; NOT_CGSCC_NPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable -; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable define void @mutual_recursion2() #0 { -; CHECK-LABEL: define {{[^@]+}}@mutual_recursion2() -; CHECK-NEXT: unreachable +; NOT_CGSCC_NPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable willreturn +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@mutual_recursion2() +; NOT_CGSCC_NPM-NEXT: unreachable +; +; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@mutual_recursion2() +; IS__CGSCC_NPM-NEXT: unreachable ; call void @mutual_recursion1() ret void @@ -133,9 +141,8 @@ ; delete [] p; ; } -; CHECK: Function Attrs: noinline nounwind uwtable -; CHECK-NOT: nofree define void @_Z9delete_opPc(i8* %0) local_unnamed_addr #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@_Z9delete_opPc ; CHECK-SAME: (i8* [[TMP0:%.*]]) local_unnamed_addr ; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null @@ -160,9 +167,8 @@ ; TEST 6 (negative case) ; Call realloc -; CHECK: Function Attrs: noinline nounwind uwtable -; CHECK-NOT: nofree define noalias i8* @call_realloc(i8* nocapture %0, i64 %1) local_unnamed_addr #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@call_realloc ; CHECK-SAME: (i8* nocapture [[TMP0:%.*]], i64 [[TMP1:%.*]]) local_unnamed_addr ; CHECK-NEXT: [[RET:%.*]] = tail call i8* @realloc(i8* nocapture [[TMP0]], i64 [[TMP1]]) @@ -181,11 +187,14 @@ ; CHECK-NEXT: declare void @nofree_function() declare void @nofree_function() nofree readnone #0 -; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable -; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable define void @call_nofree_function() #0 { -; CHECK-LABEL: define {{[^@]+}}@call_nofree_function() -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@call_nofree_function() +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@call_nofree_function() +; IS__CGSCC____-NEXT: ret void ; tail call void @nofree_function() ret void @@ -200,9 +209,8 @@ declare void @maybe_free() #0 -; CHECK: Function Attrs: noinline nounwind uwtable -; CHECK-NOT: nofree define void @call_maybe_free() #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@call_maybe_free() ; CHECK-NEXT: tail call void @maybe_free() ; CHECK-NEXT: ret void @@ -215,9 +223,8 @@ ; TEST 9 (negative case) ; Call both of above functions -; CHECK: Function Attrs: noinline nounwind uwtable -; CHECK-NOT: nofree define void @call_both() #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@call_both() ; CHECK-NEXT: tail call void @maybe_free() ; CHECK-NEXT: ret void @@ -234,20 +241,24 @@ ; CHECK-NEXT: declare float @llvm.floor.f32(float) declare float @llvm.floor.f32(float) -; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable -; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable define void @call_floor(float %a) #0 { -; CHECK-LABEL: define {{[^@]+}}@call_floor -; CHECK-SAME: (float [[A:%.*]]) -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@call_floor +; IS__TUNIT____-SAME: (float [[A:%.*]]) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@call_floor +; IS__CGSCC____-SAME: (float [[A:%.*]]) +; IS__CGSCC____-NEXT: ret void ; tail call float @llvm.floor.f32(float %a) ret void } ; FIXME: missing nofree -; CHECK: Function Attrs: noinline nosync nounwind readnone uwtable define float @call_floor2(float %a) #0 { +; CHECK: Function Attrs: noinline nosync nounwind readnone uwtable willreturn ; CHECK-LABEL: define {{[^@]+}}@call_floor2 ; CHECK-SAME: (float [[A:%.*]]) ; CHECK-NEXT: [[C:%.*]] = tail call float @llvm.floor.f32(float [[A]]) @@ -260,21 +271,27 @@ ; TEST 11 (positive case) ; Check propagation. -; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable -; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable define void @f1() #0 { -; CHECK-LABEL: define {{[^@]+}}@f1() -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@f1() +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@f1() +; IS__CGSCC____-NEXT: ret void ; tail call void @nofree_function() ret void } -; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable -; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable define void @f2() #0 { -; CHECK-LABEL: define {{[^@]+}}@f2() -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@f2() +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@f2() +; IS__CGSCC____-NEXT: ret void ; tail call void @f1() ret void @@ -282,6 +299,7 @@ ; TEST 12 NoFree argument - positive. define double @test12(double* nocapture readonly %a) { +; CHECK: Function Attrs: nofree nounwind ; CHECK-LABEL: define {{[^@]+}}@test12 ; CHECK-SAME: (double* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[A:%.*]]) ; CHECK-NEXT: entry: @@ -300,6 +318,7 @@ ; FIXME: %a should be nofree. ; TEST 13 NoFree argument - positive. define noalias i32* @test13(i64* nocapture readonly %a) { +; CHECK: Function Attrs: nounwind ; CHECK-LABEL: define {{[^@]+}}@test13 ; CHECK-SAME: (i64* nocapture nonnull readonly align 8 dereferenceable(8) [[A:%.*]]) ; CHECK-NEXT: entry: @@ -316,6 +335,7 @@ } define void @test14(i8* nocapture %0, i8* nocapture %1) { +; CHECK: Function Attrs: nounwind ; CHECK-LABEL: define {{[^@]+}}@test14 ; CHECK-SAME: (i8* nocapture [[TMP0:%.*]], i8* nocapture nofree readnone [[TMP1:%.*]]) ; CHECK-NEXT: tail call void @free(i8* nocapture [[TMP0]]) 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 @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -22,15 +22,22 @@ ; Return a pointer trivially nonnull (argument attribute) define i8* @test2(i8* nonnull %p) { -; CHECK-LABEL: define {{[^@]+}}@test2 -; CHECK-SAME: (i8* nofree nonnull readnone returned "no-capture-maybe-returned" [[P:%.*]]) -; CHECK-NEXT: ret i8* [[P]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test2 +; IS__TUNIT____-SAME: (i8* nofree nonnull readnone returned "no-capture-maybe-returned" [[P:%.*]]) +; IS__TUNIT____-NEXT: ret i8* [[P]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test2 +; IS__CGSCC____-SAME: (i8* nofree nonnull readnone returned "no-capture-maybe-returned" [[P:%.*]]) +; IS__CGSCC____-NEXT: ret i8* [[P]] ; ret i8* %p } define i8* @test2A(i1 %c, i8* %ret) { ; ATTRIBUTOR: define nonnull i8* @test2A(i1 %c, i8* nofree nonnull readnone returned %ret) +; NOT_CGSCC_OPM: Function Attrs: nounwind willreturn ; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@test2A ; NOT_CGSCC_OPM-SAME: (i1 [[C:%.*]], i8* nofree nonnull readnone returned "no-capture-maybe-returned" [[RET:%.*]]) ; NOT_CGSCC_OPM-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]] @@ -41,6 +48,7 @@ ; NOT_CGSCC_OPM-NEXT: call void @llvm.assume(i1 true) #11 [ "nonnull"(i8* [[RET]]) ] ; NOT_CGSCC_OPM-NEXT: ret i8* [[RET]] ; +; IS__CGSCC_OPM: Function Attrs: nounwind willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test2A ; IS__CGSCC_OPM-SAME: (i1 [[C:%.*]], i8* nofree nonnull readnone returned "no-capture-maybe-returned" [[RET:%.*]]) ; IS__CGSCC_OPM-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]] @@ -62,6 +70,7 @@ define i8* @test2B(i1 %c, i8* %ret) { ; ATTRIBUTOR: define nonnull dereferenceable(4) i8* @test2B(i1 %c, i8* nofree nonnull readnone returned dereferenceable(4) %ret) +; NOT_CGSCC_OPM: Function Attrs: nounwind willreturn ; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@test2B ; NOT_CGSCC_OPM-SAME: (i1 [[C:%.*]], i8* nofree nonnull readnone returned dereferenceable(4) "no-capture-maybe-returned" [[RET:%.*]]) ; NOT_CGSCC_OPM-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]] @@ -72,6 +81,7 @@ ; NOT_CGSCC_OPM-NEXT: call void @llvm.assume(i1 true) #11 [ "dereferenceable"(i8* [[RET]], i32 4) ] ; NOT_CGSCC_OPM-NEXT: ret i8* [[RET]] ; +; IS__CGSCC_OPM: Function Attrs: nounwind willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test2B ; IS__CGSCC_OPM-SAME: (i1 [[C:%.*]], i8* nofree nonnull readnone returned dereferenceable(4) "no-capture-maybe-returned" [[RET:%.*]]) ; IS__CGSCC_OPM-NEXT: br i1 [[C]], label [[A:%.*]], label [[B:%.*]] @@ -127,16 +137,26 @@ ; nonnull if neither can ever return null. (In this case, they ; just never return period.) define i8* @test4_helper() { -; CHECK-LABEL: define {{[^@]+}}@test4_helper() -; CHECK-NEXT: unreachable +; NOT_CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test4_helper() +; 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-NEXT: unreachable ; %ret = call i8* @test4() ret i8* %ret } define i8* @test4() { -; CHECK-LABEL: define {{[^@]+}}@test4() -; CHECK-NEXT: unreachable +; NOT_CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test4() +; 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-NEXT: unreachable ; %ret = call i8* @test4_helper() ret i8* %ret @@ -145,13 +165,23 @@ ; Given a mutual recursive set of functions which *can* return null ; make sure we haven't marked them as nonnull. define i8* @test5_helper(i1 %c) { -; CHECK-LABEL: define {{[^@]+}}@test5_helper -; CHECK-SAME: (i1 [[C:%.*]]) -; CHECK-NEXT: br i1 [[C]], label [[REC:%.*]], label [[END:%.*]] -; CHECK: rec: -; CHECK-NEXT: br label [[END]] -; CHECK: end: -; CHECK-NEXT: ret i8* null +; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test5_helper +; NOT_CGSCC_NPM-SAME: (i1 [[C:%.*]]) +; NOT_CGSCC_NPM-NEXT: br i1 [[C]], label [[REC:%.*]], label [[END:%.*]] +; NOT_CGSCC_NPM: rec: +; NOT_CGSCC_NPM-NEXT: br label [[END]] +; NOT_CGSCC_NPM: end: +; NOT_CGSCC_NPM-NEXT: ret i8* null +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test5_helper +; IS__CGSCC_NPM-SAME: (i1 [[C:%.*]]) +; IS__CGSCC_NPM-NEXT: br i1 [[C]], label [[REC:%.*]], label [[END:%.*]] +; IS__CGSCC_NPM: rec: +; IS__CGSCC_NPM-NEXT: br label [[END]] +; IS__CGSCC_NPM: end: +; IS__CGSCC_NPM-NEXT: ret i8* null ; br i1 %c, label %rec, label %end rec: @@ -162,17 +192,23 @@ } define i8* @test5(i1 %c) { -; CHECK-LABEL: define {{[^@]+}}@test5 -; CHECK-SAME: (i1 [[C:%.*]]) -; CHECK-NEXT: ret i8* null +; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@test5 +; NOT_CGSCC_NPM-SAME: (i1 [[C:%.*]]) +; NOT_CGSCC_NPM-NEXT: ret i8* null +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test5 +; IS__CGSCC_NPM-SAME: (i1 [[C:%.*]]) +; IS__CGSCC_NPM-NEXT: ret i8* null ; %ret = call i8* @test5_helper(i1 %c) ret i8* %ret } ; Local analysis, but going through a self recursive phi -; CHECK: Function Attrs: noreturn define i8* @test6a() { +; CHECK: Function Attrs: noreturn ; CHECK-LABEL: define {{[^@]+}}@test6a() ; CHECK-NEXT: entry: ; CHECK-NEXT: [[RET:%.*]] = call i8* @ret_nonnull() @@ -215,30 +251,51 @@ } define i8* @test7(i8* %a) { -; CHECK-LABEL: define {{[^@]+}}@test7 -; CHECK-SAME: (i8* nofree readnone returned "no-capture-maybe-returned" [[A:%.*]]) -; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, i8* [[A]], i64 0 -; CHECK-NEXT: ret i8* [[B]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test7 +; IS__TUNIT____-SAME: (i8* nofree readnone returned "no-capture-maybe-returned" [[A:%.*]]) +; IS__TUNIT____-NEXT: [[B:%.*]] = getelementptr inbounds i8, i8* [[A]], i64 0 +; IS__TUNIT____-NEXT: ret i8* [[B]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test7 +; IS__CGSCC____-SAME: (i8* nofree readnone returned "no-capture-maybe-returned" [[A:%.*]]) +; IS__CGSCC____-NEXT: [[B:%.*]] = getelementptr inbounds i8, i8* [[A]], i64 0 +; IS__CGSCC____-NEXT: ret i8* [[B]] ; %b = getelementptr inbounds i8, i8* %a, i64 0 ret i8* %b } define i8* @test8(i8* %a) { -; CHECK-LABEL: define {{[^@]+}}@test8 -; CHECK-SAME: (i8* nofree readnone "no-capture-maybe-returned" [[A:%.*]]) -; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, i8* [[A]], i64 1 -; CHECK-NEXT: ret i8* [[B]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test8 +; IS__TUNIT____-SAME: (i8* nofree readnone "no-capture-maybe-returned" [[A:%.*]]) +; IS__TUNIT____-NEXT: [[B:%.*]] = getelementptr inbounds i8, i8* [[A]], i64 1 +; IS__TUNIT____-NEXT: ret i8* [[B]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test8 +; IS__CGSCC____-SAME: (i8* nofree readnone "no-capture-maybe-returned" [[A:%.*]]) +; IS__CGSCC____-NEXT: [[B:%.*]] = getelementptr inbounds i8, i8* [[A]], i64 1 +; IS__CGSCC____-NEXT: ret i8* [[B]] ; %b = getelementptr inbounds i8, i8* %a, i64 1 ret i8* %b } define i8* @test9(i8* %a, i64 %n) { -; CHECK-LABEL: define {{[^@]+}}@test9 -; CHECK-SAME: (i8* nofree readnone "no-capture-maybe-returned" [[A:%.*]], i64 [[N:%.*]]) -; CHECK-NEXT: [[B:%.*]] = getelementptr inbounds i8, i8* [[A]], i64 [[N]] -; CHECK-NEXT: ret i8* [[B]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test9 +; IS__TUNIT____-SAME: (i8* nofree readnone "no-capture-maybe-returned" [[A:%.*]], i64 [[N:%.*]]) +; IS__TUNIT____-NEXT: [[B:%.*]] = getelementptr inbounds i8, i8* [[A]], i64 [[N]] +; IS__TUNIT____-NEXT: ret i8* [[B]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test9 +; IS__CGSCC____-SAME: (i8* nofree readnone "no-capture-maybe-returned" [[A:%.*]], i64 [[N:%.*]]) +; IS__CGSCC____-NEXT: [[B:%.*]] = getelementptr inbounds i8, i8* [[A]], i64 [[N]] +; IS__CGSCC____-NEXT: ret i8* [[B]] ; %b = getelementptr inbounds i8, i8* %a, i64 %n ret i8* %b @@ -247,6 +304,7 @@ ; ATTRIBUTOR_OPM: define i8* @test10 ; ATTRIBUTOR_NPM: define nonnull i8* @test10 define i8* @test10(i8* %a, i64 %n) { +; CHECK: Function Attrs: nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@test10 ; CHECK-SAME: (i8* nofree readnone "no-capture-maybe-returned" [[A:%.*]], i64 [[N:%.*]]) ; CHECK-NEXT: call void @llvm.assume(i1 true) @@ -319,6 +377,7 @@ ret void } define internal void @test13(i8* %a, i8* %b, i8* %c) { +; IS__TUNIT____: Function Attrs: nounwind ; IS__TUNIT____-LABEL: define {{[^@]+}}@test13 ; IS__TUNIT____-SAME: (i8* noalias nocapture nofree nonnull readnone [[A:%.*]], i8* noalias nocapture nofree readnone [[B:%.*]], i8* noalias nocapture nofree readnone [[C:%.*]]) ; IS__TUNIT____-NEXT: call void @use_i8_ptr(i8* noalias nocapture nofree nonnull readnone [[A]]) @@ -326,6 +385,7 @@ ; IS__TUNIT____-NEXT: call void @use_i8_ptr(i8* noalias nocapture nofree readnone [[C]]) ; IS__TUNIT____-NEXT: ret void ; +; IS__CGSCC____: Function Attrs: nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@test13 ; IS__CGSCC____-SAME: (i8* nocapture nofree readnone [[A:%.*]], i8* nocapture nofree readnone [[B:%.*]], i8* nocapture nofree readnone [[C:%.*]]) ; IS__CGSCC____-NEXT: call void @use_i8_ptr(i8* noalias nocapture nofree readnone [[A]]) @@ -355,6 +415,7 @@ define internal i32* @f1(i32* %arg) { ; FIXME: missing nonnull It should be nonnull @f1(i32* nonnull readonly %arg) +; CHECK: Function Attrs: argmemonly nofree nosync nounwind readonly ; CHECK-LABEL: define {{[^@]+}}@f1 ; CHECK-SAME: (i32* nofree readonly [[ARG:%.*]]) ; CHECK-NEXT: bb: @@ -402,6 +463,7 @@ } define internal i32* @f2(i32* %arg) { +; CHECK: Function Attrs: argmemonly nofree nosync nounwind readonly ; CHECK-LABEL: define {{[^@]+}}@f2 ; CHECK-SAME: (i32* nofree nonnull readonly align 4 dereferenceable(4) [[ARG:%.*]]) ; CHECK-NEXT: bb: @@ -415,6 +477,7 @@ define dso_local noalias i32* @f3(i32* %arg) { ; FIXME: missing nonnull. It should be nonnull @f3(i32* nonnull readonly %arg) +; CHECK: Function Attrs: argmemonly nofree nosync nounwind readonly ; CHECK-LABEL: define {{[^@]+}}@f3 ; CHECK-SAME: (i32* nofree readonly [[ARG:%.*]]) ; CHECK-NEXT: bb: @@ -450,6 +513,7 @@ ; fun2(nonnull %a, %b) ; We can say that %a is nonnull but %b is not. define void @f16(i8* %a, i8 * %b, i8 %c) { +; CHECK: Function Attrs: nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@f16 ; CHECK-SAME: (i8* nonnull [[A:%.*]], i8* [[B:%.*]], i8 [[C:%.*]]) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[C]], 0 @@ -478,6 +542,7 @@ ; fun1(nonnull %a) ; We can say that %a is nonnull define void @f17(i8* %a, i8 %c) { +; CHECK: Function Attrs: nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@f17 ; CHECK-SAME: (i8* nonnull [[A:%.*]], i8 [[C:%.*]]) ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[C]], 0 @@ -516,6 +581,7 @@ ; fun1(nonnull %a) define void @f18(i8* %a, i8* %b, i8 %c) { +; CHECK: Function Attrs: nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@f18 ; CHECK-SAME: (i8* nonnull [[A:%.*]], i8* [[B:%.*]], i8 [[C:%.*]]) ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i8 [[C]], 0 @@ -564,6 +630,7 @@ ; TEST 19: Loop define void @f19(i8* %a, i8* %b, i8 %c) { +; CHECK: Function Attrs: nounwind ; CHECK-LABEL: define {{[^@]+}}@f19 ; CHECK-SAME: (i8* [[A:%.*]], i8* nonnull [[B:%.*]], i8 [[C:%.*]]) ; CHECK-NEXT: br label [[LOOP_HEADER:%.*]] @@ -727,6 +794,7 @@ declare i32 @esfp(...) define i1 @parent8(i8* %a, i8* %bogus1, i8* %b) personality i8* bitcast (i32 (...)* @esfp to i8*){ +; NOT_CGSCC_OPM: Function Attrs: nounwind ; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@parent8 ; NOT_CGSCC_OPM-SAME: (i8* nonnull [[A:%.*]], i8* nocapture nofree readnone [[BOGUS1:%.*]], i8* nonnull [[B:%.*]]) #4 personality i8* bitcast (i32 (...)* @esfp to i8*) ; NOT_CGSCC_OPM-NEXT: entry: @@ -740,6 +808,7 @@ ; NOT_CGSCC_OPM-NEXT: filter [0 x i8*] zeroinitializer ; NOT_CGSCC_OPM-NEXT: unreachable ; +; IS__CGSCC_OPM: Function Attrs: nounwind ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@parent8 ; IS__CGSCC_OPM-SAME: (i8* nonnull [[A:%.*]], i8* nocapture nofree readnone [[BOGUS1:%.*]], i8* nonnull [[B:%.*]]) #5 personality i8* bitcast (i32 (...)* @esfp to i8*) ; IS__CGSCC_OPM-NEXT: entry: @@ -769,10 +838,17 @@ } define i32* @gep1(i32* %p) { -; CHECK-LABEL: define {{[^@]+}}@gep1 -; CHECK-SAME: (i32* nofree readnone "no-capture-maybe-returned" [[P:%.*]]) -; CHECK-NEXT: [[Q:%.*]] = getelementptr inbounds i32, i32* [[P]], i32 1 -; CHECK-NEXT: ret i32* [[Q]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@gep1 +; IS__TUNIT____-SAME: (i32* nofree readnone "no-capture-maybe-returned" [[P:%.*]]) +; IS__TUNIT____-NEXT: [[Q:%.*]] = getelementptr inbounds i32, i32* [[P]], i32 1 +; IS__TUNIT____-NEXT: ret i32* [[Q]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@gep1 +; IS__CGSCC____-SAME: (i32* nofree readnone "no-capture-maybe-returned" [[P:%.*]]) +; IS__CGSCC____-NEXT: [[Q:%.*]] = getelementptr inbounds i32, i32* [[P]], i32 1 +; IS__CGSCC____-NEXT: ret i32* [[Q]] ; %q = getelementptr inbounds i32, i32* %p, i32 1 ret i32* %q @@ -780,20 +856,34 @@ define i32* @gep1_no_null_opt(i32* %p) #0 { ; Should't be able to derive nonnull based on gep. -; CHECK-LABEL: define {{[^@]+}}@gep1_no_null_opt -; CHECK-SAME: (i32* nofree readnone "no-capture-maybe-returned" [[P:%.*]]) -; CHECK-NEXT: [[Q:%.*]] = getelementptr inbounds i32, i32* [[P]], i32 1 -; CHECK-NEXT: ret i32* [[Q]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind null_pointer_is_valid readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@gep1_no_null_opt +; IS__TUNIT____-SAME: (i32* nofree readnone "no-capture-maybe-returned" [[P:%.*]]) +; IS__TUNIT____-NEXT: [[Q:%.*]] = getelementptr inbounds i32, i32* [[P]], i32 1 +; IS__TUNIT____-NEXT: ret i32* [[Q]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@gep1_no_null_opt +; IS__CGSCC____-SAME: (i32* nofree readnone "no-capture-maybe-returned" [[P:%.*]]) +; IS__CGSCC____-NEXT: [[Q:%.*]] = getelementptr inbounds i32, i32* [[P]], i32 1 +; IS__CGSCC____-NEXT: ret i32* [[Q]] ; %q = getelementptr inbounds i32, i32* %p, i32 1 ret i32* %q } define i32 addrspace(3)* @gep2(i32 addrspace(3)* %p) { -; CHECK-LABEL: define {{[^@]+}}@gep2 -; CHECK-SAME: (i32 addrspace(3)* nofree readnone "no-capture-maybe-returned" [[P:%.*]]) -; CHECK-NEXT: [[Q:%.*]] = getelementptr inbounds i32, i32 addrspace(3)* [[P]], i32 1 -; CHECK-NEXT: ret i32 addrspace(3)* [[Q]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@gep2 +; IS__TUNIT____-SAME: (i32 addrspace(3)* nofree readnone "no-capture-maybe-returned" [[P:%.*]]) +; IS__TUNIT____-NEXT: [[Q:%.*]] = getelementptr inbounds i32, i32 addrspace(3)* [[P]], i32 1 +; IS__TUNIT____-NEXT: ret i32 addrspace(3)* [[Q]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@gep2 +; IS__CGSCC____-SAME: (i32 addrspace(3)* nofree readnone "no-capture-maybe-returned" [[P:%.*]]) +; IS__CGSCC____-NEXT: [[Q:%.*]] = getelementptr inbounds i32, i32 addrspace(3)* [[P]], i32 1 +; IS__CGSCC____-NEXT: ret i32 addrspace(3)* [[Q]] ; %q = getelementptr inbounds i32, i32 addrspace(3)* %p, i32 1 ret i32 addrspace(3)* %q @@ -801,15 +891,22 @@ ; FIXME: We should propagate dereferenceable here but *not* nonnull define i32 addrspace(3)* @as(i32 addrspace(3)* dereferenceable(4) %p) { -; CHECK-LABEL: define {{[^@]+}}@as -; CHECK-SAME: (i32 addrspace(3)* nofree nonnull readnone returned dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) -; CHECK-NEXT: ret i32 addrspace(3)* [[P]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@as +; IS__TUNIT____-SAME: (i32 addrspace(3)* nofree nonnull readnone returned dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) +; IS__TUNIT____-NEXT: ret i32 addrspace(3)* [[P]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@as +; IS__CGSCC____-SAME: (i32 addrspace(3)* nofree nonnull readnone returned dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) +; IS__CGSCC____-NEXT: ret i32 addrspace(3)* [[P]] ; ret i32 addrspace(3)* %p } ; CHECK-NOT: @g2() define internal i32* @g2() { +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@g2() ; IS__CGSCC____-NEXT: ret i32* inttoptr (i64 4 to i32*) ; @@ -817,8 +914,13 @@ } define i32* @g1() { -; CHECK-LABEL: define {{[^@]+}}@g1() -; CHECK-NEXT: ret i32* inttoptr (i64 4 to i32*) +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@g1() +; IS__TUNIT____-NEXT: ret i32* inttoptr (i64 4 to i32*) +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@g1() +; IS__CGSCC____-NEXT: ret i32* inttoptr (i64 4 to i32*) ; %c = call i32* @g2() ret i32* %c @@ -826,11 +928,13 @@ declare void @use_i32_ptr(i32* readnone nocapture) nounwind define internal void @called_by_weak(i32* %a) { +; IS__TUNIT____: Function Attrs: nounwind ; IS__TUNIT____-LABEL: define {{[^@]+}}@called_by_weak ; IS__TUNIT____-SAME: (i32* noalias nocapture nonnull readnone [[A:%.*]]) ; IS__TUNIT____-NEXT: call void @use_i32_ptr(i32* noalias nocapture nonnull readnone [[A]]) ; IS__TUNIT____-NEXT: ret void ; +; IS__CGSCC____: Function Attrs: nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@called_by_weak ; IS__CGSCC____-SAME: (i32* nocapture nonnull readnone [[A:%.*]]) ; IS__CGSCC____-NEXT: call void @use_i32_ptr(i32* noalias nocapture nonnull readnone [[A]]) @@ -853,11 +957,13 @@ ; Expect nonnull define internal void @control(i32* dereferenceable(4) %a) { +; IS__TUNIT____: Function Attrs: nounwind ; IS__TUNIT____-LABEL: define {{[^@]+}}@control ; IS__TUNIT____-SAME: (i32* noalias nocapture nonnull readnone align 16 dereferenceable(8) [[A:%.*]]) ; IS__TUNIT____-NEXT: call void @use_i32_ptr(i32* noalias nocapture nonnull readnone align 16 dereferenceable(8) [[A]]) ; IS__TUNIT____-NEXT: ret void ; +; IS__CGSCC____: Function Attrs: nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@control ; IS__CGSCC____-SAME: (i32* nocapture nonnull readnone align 16 dereferenceable(8) [[A:%.*]]) ; IS__CGSCC____-NEXT: call void @use_i32_ptr(i32* noalias nocapture nonnull readnone align 16 dereferenceable(8) [[A]]) @@ -868,6 +974,7 @@ } ; Avoid nonnull as we do not touch naked functions define internal void @naked(i32* dereferenceable(4) %a) naked { +; CHECK: Function Attrs: naked ; CHECK-LABEL: define {{[^@]+}}@naked ; CHECK-SAME: (i32* dereferenceable(4) [[A:%.*]]) ; CHECK-NEXT: call void @use_i32_ptr(i32* [[A]]) @@ -878,6 +985,7 @@ } ; Avoid nonnull as we do not touch optnone define internal void @optnone(i32* dereferenceable(4) %a) optnone noinline { +; CHECK: Function Attrs: noinline optnone ; CHECK-LABEL: define {{[^@]+}}@optnone ; CHECK-SAME: (i32* dereferenceable(4) [[A:%.*]]) ; CHECK-NEXT: call void @use_i32_ptr(i32* [[A]]) @@ -911,20 +1019,37 @@ declare i32 @g(i32*) willreturn nounwind define i32 @nonnull_exec_ctx_1(i32* %a, i32 %b) { ; -; CHECK-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1 -; CHECK-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) -; CHECK-NEXT: en: -; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 -; CHECK-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] -; CHECK: ex: -; CHECK-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A]]) -; CHECK-NEXT: ret i32 [[TMP5]] -; CHECK: hd: -; CHECK-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] -; CHECK-NEXT: tail call void @h(i32* [[A]]) -; CHECK-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 -; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] -; CHECK-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] +; IS________OPM: Function Attrs: nounwind +; IS________OPM-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1 +; IS________OPM-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) +; IS________OPM-NEXT: en: +; IS________OPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 +; IS________OPM-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] +; IS________OPM: ex: +; IS________OPM-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A]]) +; IS________OPM-NEXT: ret i32 [[TMP5]] +; IS________OPM: hd: +; IS________OPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] +; IS________OPM-NEXT: tail call void @h(i32* [[A]]) +; IS________OPM-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 +; IS________OPM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] +; IS________OPM-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] +; +; IS________NPM: Function Attrs: nounwind willreturn +; IS________NPM-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1 +; IS________NPM-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) +; IS________NPM-NEXT: en: +; IS________NPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 +; IS________NPM-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] +; IS________NPM: ex: +; IS________NPM-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A]]) +; IS________NPM-NEXT: ret i32 [[TMP5]] +; IS________NPM: hd: +; IS________NPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD]] ], [ 0, [[EN:%.*]] ] +; IS________NPM-NEXT: tail call void @h(i32* [[A]]) +; IS________NPM-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 +; IS________NPM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] +; IS________NPM-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] ; en: %tmp3 = icmp eq i32 %b, 0 @@ -944,22 +1069,41 @@ define i32 @nonnull_exec_ctx_1b(i32* %a, i32 %b) { ; -; CHECK-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1b -; CHECK-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) -; CHECK-NEXT: en: -; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 -; CHECK-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] -; CHECK: ex: -; CHECK-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A]]) -; CHECK-NEXT: ret i32 [[TMP5]] -; CHECK: hd: -; CHECK-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] -; CHECK-NEXT: tail call void @h(i32* [[A]]) -; CHECK-NEXT: br label [[HD2]] -; CHECK: hd2: -; CHECK-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 -; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] -; CHECK-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] +; IS________OPM: Function Attrs: nounwind +; IS________OPM-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1b +; IS________OPM-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) +; IS________OPM-NEXT: en: +; IS________OPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 +; IS________OPM-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] +; IS________OPM: ex: +; IS________OPM-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A]]) +; IS________OPM-NEXT: ret i32 [[TMP5]] +; IS________OPM: hd: +; IS________OPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] +; IS________OPM-NEXT: tail call void @h(i32* [[A]]) +; IS________OPM-NEXT: br label [[HD2]] +; IS________OPM: hd2: +; IS________OPM-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 +; IS________OPM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] +; IS________OPM-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] +; +; IS________NPM: Function Attrs: nounwind willreturn +; IS________NPM-LABEL: define {{[^@]+}}@nonnull_exec_ctx_1b +; IS________NPM-SAME: (i32* [[A:%.*]], i32 [[B:%.*]]) +; IS________NPM-NEXT: en: +; IS________NPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[B]], 0 +; IS________NPM-NEXT: br i1 [[TMP3]], label [[EX:%.*]], label [[HD:%.*]] +; IS________NPM: ex: +; IS________NPM-NEXT: [[TMP5:%.*]] = tail call i32 @g(i32* nonnull [[A]]) +; IS________NPM-NEXT: ret i32 [[TMP5]] +; IS________NPM: hd: +; IS________NPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8:%.*]], [[HD2:%.*]] ], [ 0, [[EN:%.*]] ] +; IS________NPM-NEXT: tail call void @h(i32* [[A]]) +; IS________NPM-NEXT: br label [[HD2]] +; IS________NPM: hd2: +; IS________NPM-NEXT: [[TMP8]] = add nuw i32 [[TMP7]], 1 +; IS________NPM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], [[B]] +; IS________NPM-NEXT: br i1 [[TMP9]], label [[EX]], label [[HD]] ; en: %tmp3 = icmp eq i32 %b, 0 @@ -982,6 +1126,7 @@ define i32 @nonnull_exec_ctx_2(i32* %a, i32 %b) willreturn nounwind { ; +; CHECK: Function Attrs: nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2 ; CHECK-SAME: (i32* nonnull [[A:%.*]], i32 [[B:%.*]]) ; CHECK-NEXT: en: @@ -1015,6 +1160,7 @@ define i32 @nonnull_exec_ctx_2b(i32* %a, i32 %b) willreturn nounwind { ; +; CHECK: Function Attrs: nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@nonnull_exec_ctx_2b ; CHECK-SAME: (i32* nonnull [[A:%.*]], i32 [[B:%.*]]) ; CHECK-NEXT: en: @@ -1151,6 +1297,7 @@ ; We should not mark the return of @strrchr as `nonnull`, it may well be NULL! define i8* @mybasename(i8* nofree readonly %str) { +; CHECK: Function Attrs: nofree nounwind readonly ; CHECK-LABEL: define {{[^@]+}}@mybasename ; CHECK-SAME: (i8* nofree readonly [[STR:%.*]]) ; CHECK-NEXT: [[CALL:%.*]] = call i8* @strrchr(i8* nofree readonly [[STR]], i32 47) 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 @@ -1,54 +1,61 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM -; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn -; IS__CGSSA____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn define i32 @leaf() { -; CHECK-LABEL: define {{[^@]+}}@leaf() -; CHECK-NEXT: ret i32 1 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@leaf() +; IS__TUNIT____-NEXT: ret i32 1 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@leaf() +; IS__CGSCC____-NEXT: ret i32 1 ; ret i32 1 } -; CHECK: Function Attrs -; CHECK-SAME: readnone -; CHECK-NOT: norecurse define i32 @self_rec() { -; CHECK-LABEL: define {{[^@]+}}@self_rec() -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree noreturn nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@self_rec() +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@self_rec() +; IS__CGSCC____-NEXT: unreachable ; %a = call i32 @self_rec() ret i32 4 } -; CHECK: Function Attrs -; CHECK-SAME: readnone -; CHECK-NOT: norecurse define i32 @indirect_rec() { -; CHECK-LABEL: define {{[^@]+}}@indirect_rec() -; CHECK-NEXT: unreachable +; NOT_CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@indirect_rec() +; 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-NEXT: unreachable ; %a = call i32 @indirect_rec2() ret i32 %a } -; CHECK: Function Attrs -; CHECK-SAME: readnone -; CHECK-NOT: norecurse define i32 @indirect_rec2() { -; CHECK-LABEL: define {{[^@]+}}@indirect_rec2() -; CHECK-NEXT: unreachable +; NOT_CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@indirect_rec2() +; 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-NEXT: unreachable ; %a = call i32 @indirect_rec() ret i32 %a } -; CHECK: Function Attrs -; CHECK-SAME: readnone -; CHECK-NOT: norecurse define i32 @extern() { +; CHECK: Function Attrs: nosync readnone ; CHECK-LABEL: define {{[^@]+}}@extern() ; CHECK-NEXT: [[A:%.*]] = call i32 @k() ; CHECK-NEXT: ret i32 [[A]] @@ -61,9 +68,8 @@ ; CHECK-NEXT: declare i32 @k() declare i32 @k() readnone -; CHECK: Function Attrs -; CHECK-NOT: norecurse define void @intrinsic(i8* %dest, i8* %src, i32 %len) { +; CHECK: Function Attrs: argmemonly nosync nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@intrinsic ; CHECK-SAME: (i8* nocapture writeonly [[DEST:%.*]], i8* nocapture readonly [[SRC:%.*]], i32 [[LEN:%.*]]) ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture writeonly [[DEST]], i8* noalias nocapture readonly [[SRC]], i32 [[LEN]], i1 false) @@ -77,20 +83,22 @@ ; CHECK-NEXT: declare void @llvm.memcpy.p0i8.p0i8.i32 declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i1) -; IS__TUNIT____: Function Attrs -; IS__TUNIT____-SAME: nosync readnone -; IS__CGSSA____: Function Attrs -; IS__CGSSA____-SAME: norecurse nosync readnone define internal i32 @called_by_norecurse() { -; CHECK-LABEL: define {{[^@]+}}@called_by_norecurse() -; CHECK-NEXT: [[A:%.*]] = call i32 @k() -; CHECK-NEXT: ret i32 undef +; IS__TUNIT____: Function Attrs: nosync readnone +; IS__TUNIT____-LABEL: define {{[^@]+}}@called_by_norecurse() +; IS__TUNIT____-NEXT: [[A:%.*]] = call i32 @k() +; IS__TUNIT____-NEXT: ret i32 undef +; +; IS__CGSCC____: Function Attrs: norecurse nosync readnone +; IS__CGSCC____-LABEL: define {{[^@]+}}@called_by_norecurse() +; IS__CGSCC____-NEXT: [[A:%.*]] = call i32 @k() +; IS__CGSCC____-NEXT: ret i32 undef ; %a = call i32 @k() ret i32 %a } -; CHECK: Function Attrs define void @m() norecurse { +; CHECK: Function Attrs: norecurse nosync readnone ; CHECK-LABEL: define {{[^@]+}}@m() ; CHECK-NEXT: [[A:%.*]] = call i32 @called_by_norecurse() ; CHECK-NEXT: ret void @@ -99,10 +107,8 @@ ret void } -; CHECK: Function Attrs -; FIXME: norecurse missing -; CHECK-SAME: nosync readnone define internal i32 @called_by_norecurse_indirectly() { +; CHECK: Function Attrs: nosync readnone ; CHECK-LABEL: define {{[^@]+}}@called_by_norecurse_indirectly() ; CHECK-NEXT: [[A:%.*]] = call i32 @k() ; CHECK-NEXT: ret i32 [[A]] @@ -110,19 +116,22 @@ %a = call i32 @k() ret i32 %a } -; IS__TUNIT____: Function Attrs -; IS__TUNIT____-SAME: nosync readnone -; IS__CGSSA____: Function Attrs -; IS__CGSSA____-SAME: norecurse nosync readnone define internal i32 @o() { -; CHECK-LABEL: define {{[^@]+}}@o() -; CHECK-NEXT: [[A:%.*]] = call i32 @called_by_norecurse_indirectly() -; CHECK-NEXT: ret i32 [[A]] +; IS__TUNIT____: Function Attrs: nosync readnone +; IS__TUNIT____-LABEL: define {{[^@]+}}@o() +; IS__TUNIT____-NEXT: [[A:%.*]] = call i32 @called_by_norecurse_indirectly() +; IS__TUNIT____-NEXT: ret i32 [[A]] +; +; IS__CGSCC____: Function Attrs: norecurse nosync readnone +; IS__CGSCC____-LABEL: define {{[^@]+}}@o() +; IS__CGSCC____-NEXT: [[A:%.*]] = call i32 @called_by_norecurse_indirectly() +; IS__CGSCC____-NEXT: ret i32 [[A]] ; %a = call i32 @called_by_norecurse_indirectly() ret i32 %a } define i32 @p() norecurse { +; CHECK: Function Attrs: norecurse nosync readnone ; CHECK-LABEL: define {{[^@]+}}@p() ; CHECK-NEXT: [[A:%.*]] = call i32 @o() ; CHECK-NEXT: ret i32 [[A]] @@ -131,9 +140,8 @@ ret i32 %a } -; NOT_CGSCC_NPM: Function Attrs: nofree nosync nounwind -; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn define void @f(i32 %x) { +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone ; IS__TUNIT____-LABEL: define {{[^@]+}}@f ; IS__TUNIT____-SAME: (i32 [[X:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -148,18 +156,33 @@ ; IS__TUNIT____: if.end: ; IS__TUNIT____-NEXT: ret void ; -; IS__CGSCC____-LABEL: define {{[^@]+}}@f -; IS__CGSCC____-SAME: (i32 [[X:%.*]]) -; IS__CGSCC____-NEXT: entry: -; IS__CGSCC____-NEXT: [[X_ADDR:%.*]] = alloca i32, align 4 -; IS__CGSCC____-NEXT: store i32 [[X]], i32* [[X_ADDR]], align 4 -; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* [[X_ADDR]], align 4 -; IS__CGSCC____-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[TMP0]], 0 -; IS__CGSCC____-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] -; IS__CGSCC____: if.then: -; IS__CGSCC____-NEXT: br label [[IF_END]] -; IS__CGSCC____: if.end: -; IS__CGSCC____-NEXT: ret void +; IS__CGSCC_OPM: Function Attrs: nofree nosync nounwind readnone +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f +; IS__CGSCC_OPM-SAME: (i32 [[X:%.*]]) +; 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:%.*]]) +; 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 ; entry: %x.addr = alloca i32, align 4 @@ -177,21 +200,27 @@ } define void @g() norecurse { -; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@g() -; NOT_CGSCC_OPM-NEXT: entry: -; NOT_CGSCC_OPM-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone +; IS__TUNIT____-LABEL: define {{[^@]+}}@g() +; 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-NEXT: entry: ; IS__CGSCC_OPM-NEXT: call void @f(i32 0) ; 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-NEXT: entry: +; IS__CGSCC_NPM-NEXT: ret void +; entry: call void @f(i32 0) ret void } -; CHECK-NOT: Function Attrs define linkonce_odr i32 @leaf_redefinable() { ; CHECK-LABEL: define {{[^@]+}}@leaf_redefinable() ; CHECK-NEXT: ret i32 1 @@ -200,7 +229,6 @@ } ; Call through a function pointer -; CHECK-NOT: Function Attrs define i32 @eval_func1(i32 (i32)* , i32) local_unnamed_addr { ; CHECK-LABEL: define {{[^@]+}}@eval_func1 ; CHECK-SAME: (i32 (i32)* nocapture nofree nonnull [[TMP0:%.*]], i32 [[TMP1:%.*]]) local_unnamed_addr @@ -211,8 +239,8 @@ ret i32 %3 } -; CHECK: Function Attrs: null_pointer_is_valid 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 ; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 [[TMP0]](i32 [[TMP1]]) @@ -223,13 +251,19 @@ } ; Call an unknown function in a dead block. -; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn declare void @unknown() define i32 @call_unknown_in_dead_block() local_unnamed_addr { -; CHECK-LABEL: define {{[^@]+}}@call_unknown_in_dead_block() local_unnamed_addr -; CHECK-NEXT: ret i32 0 -; CHECK: Dead: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@call_unknown_in_dead_block() local_unnamed_addr +; IS__TUNIT____-NEXT: ret i32 0 +; IS__TUNIT____: Dead: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@call_unknown_in_dead_block() local_unnamed_addr +; IS__CGSCC____-NEXT: ret i32 0 +; IS__CGSCC____: Dead: +; IS__CGSCC____-NEXT: unreachable ; ret i32 0 Dead: diff --git a/llvm/test/Transforms/Attributor/noreturn.ll b/llvm/test/Transforms/Attributor/noreturn.ll --- a/llvm/test/Transforms/Attributor/noreturn.ll +++ b/llvm/test/Transforms/Attributor/noreturn.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -16,12 +16,16 @@ ; return srec0(); ; } ; -; IS__TUNIT____: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable -; IS__CGSCC____: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable define void @srec0() #0 { -; CHECK-LABEL: define {{[^@]+}}@srec0() -; CHECK-NEXT: entry: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@srec0() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@srec0() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: unreachable ; entry: call void @srec0() @@ -35,15 +39,22 @@ ; return srec16(srec16(srec16(srec16(srec16(srec16(srec16(srec16(srec16(srec16(srec16(srec16(srec16(srec16(srec16(srec16(a)))))))))))))))); ; } ; -; IS__TUNIT____: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable -; IS__CGSCC____: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable define i32 @srec16(i32 %a) #0 { -; CHECK-LABEL: define {{[^@]+}}@srec16 -; CHECK-SAME: (i32 [[A:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: unreachable -; CHECK: exit: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@srec16 +; IS__TUNIT____-SAME: (i32 [[A:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: exit: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@srec16 +; IS__CGSCC____-SAME: (i32 [[A:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: exit: +; IS__CGSCC____-NEXT: unreachable ; entry: %call = call i32 @srec16(i32 %a) @@ -75,15 +86,22 @@ ; while (1); ; } ; +define i32 @endless_loop(i32 %a) #0 { ; IS__TUNIT____: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable +; IS__TUNIT____-LABEL: define {{[^@]+}}@endless_loop +; IS__TUNIT____-SAME: (i32 [[A:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: br label [[WHILE_BODY:%.*]] +; IS__TUNIT____: while.body: +; IS__TUNIT____-NEXT: br label [[WHILE_BODY]] +; ; IS__CGSCC____: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable -define i32 @endless_loop(i32 %a) #0 { -; CHECK-LABEL: define {{[^@]+}}@endless_loop -; CHECK-SAME: (i32 [[A:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[WHILE_BODY:%.*]] -; CHECK: while.body: -; CHECK-NEXT: br label [[WHILE_BODY]] +; IS__CGSCC____-LABEL: define {{[^@]+}}@endless_loop +; IS__CGSCC____-SAME: (i32 [[A:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br label [[WHILE_BODY:%.*]] +; IS__CGSCC____: while.body: +; IS__CGSCC____-NEXT: br label [[WHILE_BODY]] ; entry: br label %while.body @@ -101,17 +119,26 @@ ; } ; ; FIXME: no-return missing (D65243 should fix this) +define i32 @dead_return(i32 %a) #0 { ; IS__TUNIT____: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable +; IS__TUNIT____-LABEL: define {{[^@]+}}@dead_return +; IS__TUNIT____-SAME: (i32 [[A:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: br label [[WHILE_BODY:%.*]] +; IS__TUNIT____: while.body: +; IS__TUNIT____-NEXT: br label [[WHILE_BODY]] +; IS__TUNIT____: return: +; IS__TUNIT____-NEXT: unreachable +; ; IS__CGSCC____: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable -define i32 @dead_return(i32 %a) #0 { -; CHECK-LABEL: define {{[^@]+}}@dead_return -; CHECK-SAME: (i32 [[A:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[WHILE_BODY:%.*]] -; CHECK: while.body: -; CHECK-NEXT: br label [[WHILE_BODY]] -; CHECK: return: -; CHECK-NEXT: unreachable +; IS__CGSCC____-LABEL: define {{[^@]+}}@dead_return +; IS__CGSCC____-SAME: (i32 [[A:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br label [[WHILE_BODY:%.*]] +; IS__CGSCC____: while.body: +; IS__CGSCC____-NEXT: br label [[WHILE_BODY]] +; IS__CGSCC____: return: +; IS__CGSCC____-NEXT: unreachable ; entry: br label %while.body @@ -130,20 +157,32 @@ ; return a == 0 ? endless_loop(a) : srec16(a); ; } ; -; IS__TUNIT____: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable -; IS__CGSCC____: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable define i32 @multiple_noreturn_calls(i32 %a) #0 { -; CHECK-LABEL: define {{[^@]+}}@multiple_noreturn_calls -; CHECK-SAME: (i32 [[A:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[A]], 0 -; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] -; CHECK: cond.true: -; CHECK-NEXT: unreachable -; CHECK: cond.false: -; CHECK-NEXT: unreachable -; CHECK: cond.end: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@multiple_noreturn_calls +; IS__TUNIT____-SAME: (i32 [[A:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp eq i32 [[A]], 0 +; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] +; IS__TUNIT____: cond.true: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: cond.false: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: cond.end: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@multiple_noreturn_calls +; IS__CGSCC____-SAME: (i32 [[A:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq i32 [[A]], 0 +; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] +; IS__CGSCC____: cond.true: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: cond.false: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: cond.end: +; IS__CGSCC____-NEXT: unreachable ; entry: %cmp = icmp eq i32 %a, 0 @@ -166,14 +205,20 @@ ; TEST 6a: willreturn means *not* no-return or UB ; FIXME: we should derive "UB" as an argument and report it to the user on request. +define i32 @endless_loop_but_willreturn() willreturn { ; IS__TUNIT____: Function Attrs: nofree noreturn nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@endless_loop_but_willreturn() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: br label [[WHILE_BODY:%.*]] +; IS__TUNIT____: while.body: +; IS__TUNIT____-NEXT: br label [[WHILE_BODY]] +; ; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn -define i32 @endless_loop_but_willreturn() willreturn { -; CHECK-LABEL: define {{[^@]+}}@endless_loop_but_willreturn() -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[WHILE_BODY:%.*]] -; CHECK: while.body: -; CHECK-NEXT: br label [[WHILE_BODY]] +; IS__CGSCC____-LABEL: define {{[^@]+}}@endless_loop_but_willreturn() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br label [[WHILE_BODY:%.*]] +; IS__CGSCC____: while.body: +; IS__CGSCC____-NEXT: br label [[WHILE_BODY]] ; entry: br label %while.body @@ -183,12 +228,16 @@ } ; TEST 6b: willreturn means *not* no-return or UB +define i32 @UB_and_willreturn() willreturn { ; IS__TUNIT____: Function Attrs: nofree noreturn nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@UB_and_willreturn() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: unreachable +; ; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn -define i32 @UB_and_willreturn() willreturn { -; CHECK-LABEL: define {{[^@]+}}@UB_and_willreturn() -; CHECK-NEXT: entry: -; CHECK-NEXT: unreachable +; IS__CGSCC____-LABEL: define {{[^@]+}}@UB_and_willreturn() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: unreachable ; entry: unreachable diff --git a/llvm/test/Transforms/Attributor/noreturn_async.ll b/llvm/test/Transforms/Attributor/noreturn_async.ll --- a/llvm/test/Transforms/Attributor/noreturn_async.ll +++ b/llvm/test/Transforms/Attributor/noreturn_async.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s ; ; This file is the same as noreturn_sync.ll but with a personality which diff --git a/llvm/test/Transforms/Attributor/noreturn_sync.ll b/llvm/test/Transforms/Attributor/noreturn_sync.ll --- a/llvm/test/Transforms/Attributor/noreturn_sync.ll +++ b/llvm/test/Transforms/Attributor/noreturn_sync.ll @@ -1,3 +1,4 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s ; ; This file is the same as noreturn_async.ll but with a personality which @@ -41,7 +42,7 @@ entry: %retval = alloca i32, align 4 %__exception_code = alloca i32, align 4 - invoke void @"?overflow@@YAXXZ"() + invoke void @"?overflow@@YAXXZ"() to label %invoke.cont unwind label %catch.dispatch ; CHECK: call void @"?overflow@@YAXXZ"() ; CHECK-NEXT: unreachable @@ -98,9 +99,9 @@ entry: %retval = alloca i32, align 4 %__exception_code = alloca i32, align 4 -; CHECK: invoke void @"?overflow@@YAXXZ_may_throw"() +; CHECK: invoke void @"?overflow@@YAXXZ_may_throw"() ; CHECK: to label %invoke.cont unwind label %catch.dispatch - invoke void @"?overflow@@YAXXZ_may_throw"() + invoke void @"?overflow@@YAXXZ_may_throw"() to label %invoke.cont unwind label %catch.dispatch invoke.cont: ; preds = %entry diff --git a/llvm/test/Transforms/Attributor/nosync.ll b/llvm/test/Transforms/Attributor/nosync.ll --- a/llvm/test/Transforms/Attributor/nosync.ll +++ b/llvm/test/Transforms/Attributor/nosync.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=2 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -28,14 +28,20 @@ %struct.RT = type { i8, [10 x [20 x i32]], i8 } %struct.ST = type { i32, double, %struct.RT } -; IS__TUNIT____: Function Attrs: nofree nosync nounwind optsize readnone ssp uwtable -; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind optsize readnone ssp uwtable define i32* @foo(%struct.ST* %s) nounwind uwtable readnone optsize ssp { -; CHECK-LABEL: define {{[^@]+}}@foo -; CHECK-SAME: (%struct.ST* nofree readnone "no-capture-maybe-returned" [[S:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ST:%.*]], %struct.ST* [[S]], i64 1, i32 2, i32 1, i64 5, i64 13 -; CHECK-NEXT: ret i32* [[ARRAYIDX]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind optsize readnone ssp uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@foo +; IS__TUNIT____-SAME: (%struct.ST* nofree readnone "no-capture-maybe-returned" [[S:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ST:%.*]], %struct.ST* [[S]], i64 1, i32 2, i32 1, i64 5, i64 13 +; IS__TUNIT____-NEXT: ret i32* [[ARRAYIDX]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind optsize readnone ssp uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@foo +; IS__CGSCC____-SAME: (%struct.ST* nofree readnone "no-capture-maybe-returned" [[S:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_ST:%.*]], %struct.ST* [[S]], i64 1, i32 2, i32 1, i64 5, i64 13 +; IS__CGSCC____-NEXT: ret i32* [[ARRAYIDX]] ; entry: %arrayidx = getelementptr inbounds %struct.ST, %struct.ST* %s, i64 1, i32 2, i32 1, i64 5, i64 13 @@ -49,9 +55,8 @@ ; return n; ; } -; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nosync nounwind uwtable -; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind uwtable define i32 @load_monotonic(i32* nocapture readonly %0) norecurse nounwind uwtable { +; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind uwtable willreturn ; CHECK-LABEL: define {{[^@]+}}@load_monotonic ; CHECK-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[TMP0:%.*]]) ; CHECK-NEXT: [[TMP2:%.*]] = load atomic i32, i32* [[TMP0]] monotonic, align 4 @@ -68,9 +73,8 @@ ; atomic_load_explicit(num, memory_order_relaxed); ; } -; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nosync nounwind uwtable -; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind uwtable define void @store_monotonic(i32* nocapture %0) norecurse nounwind uwtable { +; CHECK: Function Attrs: argmemonly nofree norecurse nosync nounwind uwtable willreturn ; CHECK-LABEL: define {{[^@]+}}@store_monotonic ; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[TMP0:%.*]]) ; CHECK-NEXT: store atomic i32 10, i32* [[TMP0]] monotonic, align 4 @@ -87,10 +91,8 @@ ; return n; ; } -; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nounwind uwtable -; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind uwtable -; CHECK-NOT: nosync define i32 @load_acquire(i32* nocapture readonly %0) norecurse nounwind uwtable { +; CHECK: Function Attrs: argmemonly nofree norecurse nounwind uwtable willreturn ; CHECK-LABEL: define {{[^@]+}}@load_acquire ; CHECK-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[TMP0:%.*]]) ; CHECK-NEXT: [[TMP2:%.*]] = load atomic i32, i32* [[TMP0]] acquire, align 4 @@ -106,10 +108,8 @@ ; atomic_store_explicit(num, 10, memory_order_release); ; } -; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nounwind uwtable -; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind uwtable -; CHECK-NOT: nosync define void @load_release(i32* nocapture %0) norecurse nounwind uwtable { +; CHECK: Function Attrs: argmemonly nofree norecurse nounwind uwtable willreturn ; CHECK-LABEL: define {{[^@]+}}@load_release ; CHECK-SAME: (i32* nocapture nofree writeonly align 4 [[TMP0:%.*]]) ; CHECK-NEXT: store atomic volatile i32 10, i32* [[TMP0]] release, align 4 @@ -121,10 +121,8 @@ ; TEST 6 - negative volatile, relaxed atomic -; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nounwind uwtable -; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind uwtable -; CHECK-NOT: nosync define void @load_volatile_release(i32* nocapture %0) norecurse nounwind uwtable { +; CHECK: Function Attrs: argmemonly nofree norecurse nounwind uwtable willreturn ; CHECK-LABEL: define {{[^@]+}}@load_volatile_release ; CHECK-SAME: (i32* nocapture nofree writeonly align 4 [[TMP0:%.*]]) ; CHECK-NEXT: store atomic volatile i32 10, i32* [[TMP0]] release, align 4 @@ -140,10 +138,8 @@ ; *num = 14; ; } -; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nounwind uwtable -; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind uwtable -; CHECK-NOT: nosync define void @volatile_store(i32* %0) norecurse nounwind uwtable { +; CHECK: Function Attrs: argmemonly nofree norecurse nounwind uwtable willreturn ; CHECK-LABEL: define {{[^@]+}}@volatile_store ; CHECK-SAME: (i32* nofree align 4 [[TMP0:%.*]]) ; CHECK-NEXT: store volatile i32 14, i32* [[TMP0]], align 4 @@ -160,10 +156,8 @@ ; return n; ; } -; IS__TUNIT____: Function Attrs: argmemonly nofree norecurse nounwind uwtable -; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind uwtable -; CHECK-NOT: nosync define i32 @volatile_load(i32* %0) norecurse nounwind uwtable { +; CHECK: Function Attrs: argmemonly nofree norecurse nounwind uwtable willreturn ; CHECK-LABEL: define {{[^@]+}}@volatile_load ; CHECK-SAME: (i32* nofree align 4 [[TMP0:%.*]]) ; CHECK-NEXT: [[TMP2:%.*]] = load volatile i32, i32* [[TMP0]], align 4 @@ -179,9 +173,8 @@ ; CHECK-NEXT: declare void @nosync_function() declare void @nosync_function() noinline nounwind uwtable nosync -; IS__TUNIT____: Function Attrs: noinline nosync nounwind uwtable -; IS__CGSCC____: Function Attrs: noinline nosync nounwind uwtable define void @call_nosync_function() nounwind uwtable noinline { +; CHECK: Function Attrs: noinline nosync nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@call_nosync_function() ; CHECK-NEXT: tail call void @nosync_function() ; CHECK-NEXT: ret void @@ -196,10 +189,8 @@ ; CHECK-NEXT: declare void @might_sync() declare void @might_sync() noinline nounwind uwtable -; IS__TUNIT____: Function Attrs: noinline nounwind uwtable -; IS__CGSCC____: Function Attrs: noinline nounwind uwtable -; CHECK-NOT: nosync define void @call_might_sync() nounwind uwtable noinline { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@call_might_sync() ; CHECK-NEXT: tail call void @might_sync() ; CHECK-NEXT: ret void @@ -211,26 +202,32 @@ ; TEST 11 - positive, should deduce nosync ; volatile operation in same scc but dead. Call volatile_load defined in TEST 8. -; IS__TUNIT____: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable -; IS__CGSCC_OPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable -; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable define i32 @scc1(i32* %0) noinline nounwind uwtable { -; CHECK-LABEL: define {{[^@]+}}@scc1 -; CHECK-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]]) -; CHECK-NEXT: unreachable +; NOT_CGSCC_NPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable willreturn +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@scc1 +; NOT_CGSCC_NPM-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]]) +; NOT_CGSCC_NPM-NEXT: unreachable +; +; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@scc1 +; IS__CGSCC_NPM-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]]) +; IS__CGSCC_NPM-NEXT: unreachable ; tail call void @scc2(i32* %0); %val = tail call i32 @volatile_load(i32* %0); ret i32 %val; } -; IS__TUNIT____: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable -; IS__CGSCC_OPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable -; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable define void @scc2(i32* %0) noinline nounwind uwtable { -; CHECK-LABEL: define {{[^@]+}}@scc2 -; CHECK-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]]) -; CHECK-NEXT: unreachable +; NOT_CGSCC_NPM: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable willreturn +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@scc2 +; NOT_CGSCC_NPM-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]]) +; NOT_CGSCC_NPM-NEXT: unreachable +; +; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@scc2 +; IS__CGSCC_NPM-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]]) +; IS__CGSCC_NPM-NEXT: unreachable ; tail call i32 @scc1(i32* %0); ret void; @@ -255,15 +252,24 @@ %"struct.std::atomic" = type { %"struct.std::__atomic_base" } %"struct.std::__atomic_base" = type { i8 } -; CHECK-NOT: nosync define void @foo1(i32* %0, %"struct.std::atomic"* %1) { -; CHECK-LABEL: define {{[^@]+}}@foo1 -; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull writeonly dereferenceable(1) [[TMP1:%.*]]) -; CHECK-NEXT: store i32 100, i32* [[TMP0]], align 4 -; CHECK-NEXT: fence release -; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 -; CHECK-NEXT: store atomic i8 1, i8* [[TMP3]] monotonic, align 1 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nounwind willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@foo1 +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull writeonly dereferenceable(1) [[TMP1:%.*]]) +; IS__TUNIT____-NEXT: store i32 100, i32* [[TMP0]], align 4 +; IS__TUNIT____-NEXT: fence release +; IS__TUNIT____-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 +; IS__TUNIT____-NEXT: store atomic i8 1, i8* [[TMP3]] monotonic, align 1 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nounwind willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@foo1 +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull writeonly dereferenceable(1) [[TMP1:%.*]]) +; IS__CGSCC____-NEXT: store i32 100, i32* [[TMP0]], align 4 +; IS__CGSCC____-NEXT: fence release +; IS__CGSCC____-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 +; IS__CGSCC____-NEXT: store atomic i8 1, i8* [[TMP3]] monotonic, align 1 +; IS__CGSCC____-NEXT: ret void ; store i32 100, i32* %0, align 4 fence release @@ -272,20 +278,34 @@ ret void } -; CHECK-NOT: nosync define void @bar(i32* %0, %"struct.std::atomic"* %1) { -; CHECK-LABEL: define {{[^@]+}}@bar -; CHECK-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull readonly dereferenceable(1) [[TMP1:%.*]]) -; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 -; CHECK-NEXT: br label [[TMP4:%.*]] -; CHECK: 4: -; CHECK-NEXT: [[TMP5:%.*]] = load atomic i8, i8* [[TMP3]] monotonic, align 1 -; CHECK-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 1 -; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i8 [[TMP6]], 0 -; CHECK-NEXT: br i1 [[TMP7]], label [[TMP4]], label [[TMP8:%.*]] -; CHECK: 8: -; CHECK-NEXT: fence acquire -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nounwind +; IS__TUNIT____-LABEL: define {{[^@]+}}@bar +; IS__TUNIT____-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull readonly dereferenceable(1) [[TMP1:%.*]]) +; IS__TUNIT____-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 +; IS__TUNIT____-NEXT: br label [[TMP4:%.*]] +; IS__TUNIT____: 4: +; IS__TUNIT____-NEXT: [[TMP5:%.*]] = load atomic i8, i8* [[TMP3]] monotonic, align 1 +; IS__TUNIT____-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 1 +; IS__TUNIT____-NEXT: [[TMP7:%.*]] = icmp eq i8 [[TMP6]], 0 +; IS__TUNIT____-NEXT: br i1 [[TMP7]], label [[TMP4]], label [[TMP8:%.*]] +; IS__TUNIT____: 8: +; IS__TUNIT____-NEXT: fence acquire +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nounwind +; IS__CGSCC____-LABEL: define {{[^@]+}}@bar +; IS__CGSCC____-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull readonly dereferenceable(1) [[TMP1:%.*]]) +; IS__CGSCC____-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 +; IS__CGSCC____-NEXT: br label [[TMP4:%.*]] +; IS__CGSCC____: 4: +; IS__CGSCC____-NEXT: [[TMP5:%.*]] = load atomic i8, i8* [[TMP3]] monotonic, align 1 +; IS__CGSCC____-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 1 +; IS__CGSCC____-NEXT: [[TMP7:%.*]] = icmp eq i8 [[TMP6]], 0 +; IS__CGSCC____-NEXT: br i1 [[TMP7]], label [[TMP4]], label [[TMP8:%.*]] +; IS__CGSCC____: 8: +; IS__CGSCC____-NEXT: fence acquire +; IS__CGSCC____-NEXT: ret void ; %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0 br label %4 @@ -302,16 +322,24 @@ } ; TEST 13 - Fence syncscope("singlethread") seq_cst +define void @foo1_singlethread(i32* %0, %"struct.std::atomic"* %1) { ; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@foo1_singlethread +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull writeonly dereferenceable(1) [[TMP1:%.*]]) +; IS__TUNIT____-NEXT: store i32 100, i32* [[TMP0]], align 4 +; IS__TUNIT____-NEXT: fence syncscope("singlethread") release +; IS__TUNIT____-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 +; IS__TUNIT____-NEXT: store atomic i8 1, i8* [[TMP3]] monotonic, align 1 +; IS__TUNIT____-NEXT: ret void +; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn -define void @foo1_singlethread(i32* %0, %"struct.std::atomic"* %1) { -; CHECK-LABEL: define {{[^@]+}}@foo1_singlethread -; CHECK-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull writeonly dereferenceable(1) [[TMP1:%.*]]) -; CHECK-NEXT: store i32 100, i32* [[TMP0]], align 4 -; CHECK-NEXT: fence syncscope("singlethread") release -; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 -; CHECK-NEXT: store atomic i8 1, i8* [[TMP3]] monotonic, align 1 -; CHECK-NEXT: ret void +; IS__CGSCC____-LABEL: define {{[^@]+}}@foo1_singlethread +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull writeonly dereferenceable(1) [[TMP1:%.*]]) +; IS__CGSCC____-NEXT: store i32 100, i32* [[TMP0]], align 4 +; IS__CGSCC____-NEXT: fence syncscope("singlethread") release +; IS__CGSCC____-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 +; IS__CGSCC____-NEXT: store atomic i8 1, i8* [[TMP3]] monotonic, align 1 +; IS__CGSCC____-NEXT: ret void ; store i32 100, i32* %0, align 4 fence syncscope("singlethread") release @@ -320,21 +348,34 @@ ret void } +define void @bar_singlethread(i32* %0, %"struct.std::atomic"* %1) { ; IS__TUNIT____: Function Attrs: nofree nosync nounwind +; IS__TUNIT____-LABEL: define {{[^@]+}}@bar_singlethread +; IS__TUNIT____-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull readonly dereferenceable(1) [[TMP1:%.*]]) +; IS__TUNIT____-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 +; IS__TUNIT____-NEXT: br label [[TMP4:%.*]] +; IS__TUNIT____: 4: +; IS__TUNIT____-NEXT: [[TMP5:%.*]] = load atomic i8, i8* [[TMP3]] monotonic, align 1 +; IS__TUNIT____-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 1 +; IS__TUNIT____-NEXT: [[TMP7:%.*]] = icmp eq i8 [[TMP6]], 0 +; IS__TUNIT____-NEXT: br i1 [[TMP7]], label [[TMP4]], label [[TMP8:%.*]] +; IS__TUNIT____: 8: +; IS__TUNIT____-NEXT: fence syncscope("singlethread") acquire +; IS__TUNIT____-NEXT: ret void +; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind -define void @bar_singlethread(i32* %0, %"struct.std::atomic"* %1) { -; CHECK-LABEL: define {{[^@]+}}@bar_singlethread -; CHECK-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull readonly dereferenceable(1) [[TMP1:%.*]]) -; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 -; CHECK-NEXT: br label [[TMP4:%.*]] -; CHECK: 4: -; CHECK-NEXT: [[TMP5:%.*]] = load atomic i8, i8* [[TMP3]] monotonic, align 1 -; CHECK-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 1 -; CHECK-NEXT: [[TMP7:%.*]] = icmp eq i8 [[TMP6]], 0 -; CHECK-NEXT: br i1 [[TMP7]], label [[TMP4]], label [[TMP8:%.*]] -; CHECK: 8: -; CHECK-NEXT: fence syncscope("singlethread") acquire -; CHECK-NEXT: ret void +; IS__CGSCC____-LABEL: define {{[^@]+}}@bar_singlethread +; IS__CGSCC____-SAME: (i32* nocapture nofree readnone [[TMP0:%.*]], %"struct.std::atomic"* nocapture nofree nonnull readonly dereferenceable(1) [[TMP1:%.*]]) +; IS__CGSCC____-NEXT: [[TMP3:%.*]] = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* [[TMP1]], i64 0, i32 0, i32 0 +; IS__CGSCC____-NEXT: br label [[TMP4:%.*]] +; IS__CGSCC____: 4: +; IS__CGSCC____-NEXT: [[TMP5:%.*]] = load atomic i8, i8* [[TMP3]] monotonic, align 1 +; IS__CGSCC____-NEXT: [[TMP6:%.*]] = and i8 [[TMP5]], 1 +; IS__CGSCC____-NEXT: [[TMP7:%.*]] = icmp eq i8 [[TMP6]], 0 +; IS__CGSCC____-NEXT: br i1 [[TMP7]], label [[TMP4]], label [[TMP8:%.*]] +; IS__CGSCC____: 8: +; IS__CGSCC____-NEXT: fence syncscope("singlethread") acquire +; IS__CGSCC____-NEXT: ret void ; %3 = getelementptr inbounds %"struct.std::atomic", %"struct.std::atomic"* %1, i64 0, i32 0, i32 0 br label %4 @@ -357,10 +398,8 @@ ; It is odd to add nocapture but a result of the llvm.memcpy nocapture. ; -; IS__TUNIT____: Function Attrs: argmemonly nounwind -; IS__CGSCC____: Function Attrs: argmemonly nounwind -; CHECK-NOT: nosync define i32 @memcpy_volatile(i8* %ptr1, i8* %ptr2) { +; CHECK: Function Attrs: argmemonly nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@memcpy_volatile ; CHECK-SAME: (i8* nocapture writeonly [[PTR1:%.*]], i8* nocapture readonly [[PTR2:%.*]]) ; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i32(i8* noalias nocapture writeonly [[PTR1]], i8* noalias nocapture readonly [[PTR2]], i32 8, i1 true) @@ -374,9 +413,8 @@ ; It is odd to add nocapture but a result of the llvm.memset nocapture. ; -; IS__TUNIT____: Function Attrs: argmemonly nosync -; IS__CGSCC____: Function Attrs: argmemonly nosync define i32 @memset_non_volatile(i8* %ptr1, i8 %val) { +; CHECK: Function Attrs: argmemonly nosync nounwind willreturn writeonly ; CHECK-LABEL: define {{[^@]+}}@memset_non_volatile ; CHECK-SAME: (i8* nocapture writeonly [[PTR1:%.*]], i8 [[VAL:%.*]]) ; CHECK-NEXT: call void @llvm.memset.p0i8.i32(i8* nocapture writeonly [[PTR1]], i8 [[VAL]], i32 8, i1 false) @@ -402,6 +440,7 @@ ; TEST 17 - negative. Convergent define void @convergent_readnone(){ +; CHECK: Function Attrs: readnone ; CHECK-LABEL: define {{[^@]+}}@convergent_readnone() ; CHECK-NEXT: call void @readnone_test() ; CHECK-NEXT: ret void @@ -417,10 +456,8 @@ ; TEST 18 - negative. Synchronizing intrinsic -; IS__TUNIT____: Function Attrs: nounwind -; IS__CGSCC____: Function Attrs: nounwind -; CHECK-NOT: nosync define void @i_totally_sync() { +; CHECK: Function Attrs: nounwind ; CHECK-LABEL: define {{[^@]+}}@i_totally_sync() ; CHECK-NEXT: tail call void @llvm.x86.sse2.clflush(i8* nonnull align 4 dereferenceable(4) bitcast (i32* @a to i8*)) ; CHECK-NEXT: ret void @@ -433,20 +470,23 @@ ; TEST 19 - positive, readnone & non-convergent intrinsic. +define i32 @cos_test(float %x) { ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@cos_test +; IS__TUNIT____-SAME: (float [[X:%.*]]) +; IS__TUNIT____-NEXT: ret i32 4 +; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -define i32 @cos_test(float %x) { -; CHECK-LABEL: define {{[^@]+}}@cos_test -; CHECK-SAME: (float [[X:%.*]]) -; CHECK-NEXT: ret i32 4 +; IS__CGSCC____-LABEL: define {{[^@]+}}@cos_test +; IS__CGSCC____-SAME: (float [[X:%.*]]) +; IS__CGSCC____-NEXT: ret i32 4 ; call float @llvm.cos(float %x) ret i32 4 } -; IS__TUNIT____: Function Attrs: nosync nounwind -; IS__CGSCC____: Function Attrs: nosync nounwind define float @cos_test2(float %x) { +; CHECK: Function Attrs: nosync nounwind readnone willreturn ; CHECK-LABEL: define {{[^@]+}}@cos_test2 ; CHECK-SAME: (float [[X:%.*]]) ; CHECK-NEXT: [[C:%.*]] = call float @llvm.cos.f32(float [[X]]) diff --git a/llvm/test/Transforms/Attributor/nounwind.ll b/llvm/test/Transforms/Attributor/nounwind.ll --- a/llvm/test/Transforms/Attributor/nounwind.ll +++ b/llvm/test/Transforms/Attributor/nounwind.ll @@ -1,26 +1,31 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=3 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM ; TEST 1 -; IS__TUNIT____: Function Attrs: nofree nosync nounwind -; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind define i32 @foo1() { -; CHECK-LABEL: define {{[^@]+}}@foo1() -; CHECK-NEXT: ret i32 1 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@foo1() +; IS__TUNIT____-NEXT: ret i32 1 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@foo1() +; IS__CGSCC____-NEXT: ret i32 1 ; ret i32 1 } ; TEST 2 -; IS__TUNIT____: Function Attrs: nofree noreturn nosync nounwind -; IS__CGSCC_OPM: Function Attrs: nofree noreturn nosync nounwind -; IS__CGSCC_NPM: Function Attrs: nofree norecurse noreturn nosync nounwind define i32 @scc1_foo() { -; CHECK-LABEL: define {{[^@]+}}@scc1_foo() -; CHECK-NEXT: unreachable +; NOT_CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone willreturn +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@scc1_foo() +; NOT_CGSCC_NPM-NEXT: unreachable +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@scc1_foo() +; IS__CGSCC_NPM-NEXT: unreachable ; %1 = call i32 @scc1_bar() ret i32 1 @@ -28,12 +33,14 @@ ; TEST 3 -; IS__TUNIT____: Function Attrs: nofree noreturn nosync nounwind -; IS__CGSCC_OPM: Function Attrs: nofree noreturn nosync nounwind -; IS__CGSCC_NPM: Function Attrs: nofree norecurse noreturn nosync nounwind define i32 @scc1_bar() { -; CHECK-LABEL: define {{[^@]+}}@scc1_bar() -; CHECK-NEXT: unreachable +; NOT_CGSCC_NPM: Function Attrs: nofree noreturn nosync nounwind readnone willreturn +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@scc1_bar() +; NOT_CGSCC_NPM-NEXT: unreachable +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@scc1_bar() +; IS__CGSCC_NPM-NEXT: unreachable ; %1 = call i32 @scc1_foo() ret i32 1 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 @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=17 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=17 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -7,26 +7,36 @@ ; FIXME: CGSCC is not looking at callees and calleers even though it could be allowed. define i32 @test0(i32* %p) { -; CHECK-LABEL: define {{[^@]+}}@test0 -; CHECK-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) -; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[P]], align 4, !range !0 -; CHECK-NEXT: ret i32 [[A]] +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test0 +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) +; IS__TUNIT____-NEXT: [[A:%.*]] = load i32, i32* [[P]], align 4, !range !0 +; IS__TUNIT____-NEXT: ret i32 [[A]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test0 +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) +; IS__CGSCC____-NEXT: [[A:%.*]] = load i32, i32* [[P]], align 4, !range !0 +; IS__CGSCC____-NEXT: ret i32 [[A]] ; %a = load i32, i32* %p, !range !0 ret i32 %a } define i32 @test0-range-check(i32* %p) { +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test0-range-check ; IS__TUNIT_OPM-SAME: (i32* nocapture nofree readonly align 4 [[P:%.*]]) ; IS__TUNIT_OPM-NEXT: [[A:%.*]] = tail call i32 @test0(i32* nocapture nofree readonly align 4 [[P]]) #3, !range !0 ; IS__TUNIT_OPM-NEXT: ret i32 [[A]] ; +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@test0-range-check ; IS__TUNIT_NPM-SAME: (i32* nocapture nofree readonly align 4 [[P:%.*]]) ; IS__TUNIT_NPM-NEXT: [[A:%.*]] = tail call i32 @test0(i32* nocapture nofree readonly align 4 [[P]]) #2, !range !0 ; IS__TUNIT_NPM-NEXT: ret i32 [[A]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@test0-range-check ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) ; IS__CGSCC____-NEXT: [[A:%.*]] = tail call i32 @test0(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P]]) @@ -296,12 +306,21 @@ ret void } define i32 @test1(i32* %p) { -; CHECK-LABEL: define {{[^@]+}}@test1 -; CHECK-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) -; CHECK-NEXT: [[LOAD_10_100:%.*]] = load i32, i32* [[P]], align 4, !range !1 -; CHECK-NEXT: [[ADD_10_THEN_20_110:%.*]] = add i32 [[LOAD_10_100]], 10 -; CHECK-NEXT: [[MUL_10_THEN_200_1091:%.*]] = mul i32 [[ADD_10_THEN_20_110]], 10 -; CHECK-NEXT: ret i32 [[MUL_10_THEN_200_1091]] +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test1 +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) +; IS__TUNIT____-NEXT: [[LOAD_10_100:%.*]] = load i32, i32* [[P]], align 4, !range !1 +; IS__TUNIT____-NEXT: [[ADD_10_THEN_20_110:%.*]] = add i32 [[LOAD_10_100]], 10 +; IS__TUNIT____-NEXT: [[MUL_10_THEN_200_1091:%.*]] = mul i32 [[ADD_10_THEN_20_110]], 10 +; IS__TUNIT____-NEXT: ret i32 [[MUL_10_THEN_200_1091]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test1 +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) +; IS__CGSCC____-NEXT: [[LOAD_10_100:%.*]] = load i32, i32* [[P]], align 4, !range !1 +; IS__CGSCC____-NEXT: [[ADD_10_THEN_20_110:%.*]] = add i32 [[LOAD_10_100]], 10 +; IS__CGSCC____-NEXT: [[MUL_10_THEN_200_1091:%.*]] = mul i32 [[ADD_10_THEN_20_110]], 10 +; IS__CGSCC____-NEXT: ret i32 [[MUL_10_THEN_200_1091]] ; %load-10-100 = load i32, i32* %p, !range !1 %add-10-then-20-110 = add i32 %load-10-100, 10 @@ -311,18 +330,21 @@ define i1 @test1-check(i32* %p) { ; +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test1-check ; IS__TUNIT_OPM-SAME: (i32* nocapture nofree readonly align 4 [[P:%.*]]) ; IS__TUNIT_OPM-NEXT: [[RES:%.*]] = tail call i32 @test1(i32* nocapture nofree readonly align 4 [[P]]) #3, !range !2 ; IS__TUNIT_OPM-NEXT: [[CMP:%.*]] = icmp eq i32 [[RES]], 500 ; IS__TUNIT_OPM-NEXT: ret i1 [[CMP]] ; +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@test1-check ; IS__TUNIT_NPM-SAME: (i32* nocapture nofree readonly align 4 [[P:%.*]]) ; IS__TUNIT_NPM-NEXT: [[RES:%.*]] = tail call i32 @test1(i32* nocapture nofree readonly align 4 [[P]]) #2, !range !2 ; IS__TUNIT_NPM-NEXT: [[CMP:%.*]] = icmp eq i32 [[RES]], 500 ; IS__TUNIT_NPM-NEXT: ret i1 [[CMP]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@test1-check ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) ; IS__CGSCC____-NEXT: [[RES:%.*]] = tail call i32 @test1(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P]]) @@ -347,13 +369,23 @@ ; } define i32 @test2(i32* %p) { -; CHECK-LABEL: define {{[^@]+}}@test2 -; CHECK-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[P]], align 4 -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[TMP0]], 0 -; CHECK-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 4, i32 3 -; CHECK-NEXT: ret i32 [[COND]] +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test2 +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32, i32* [[P]], align 4 +; IS__TUNIT____-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[TMP0]], 0 +; IS__TUNIT____-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 4, i32 3 +; IS__TUNIT____-NEXT: ret i32 [[COND]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test2 +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* [[P]], align 4 +; IS__CGSCC____-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[TMP0]], 0 +; IS__CGSCC____-NEXT: [[COND:%.*]] = select i1 [[TOBOOL]], i32 4, i32 3 +; IS__CGSCC____-NEXT: ret i32 [[COND]] ; entry: %0 = load i32, i32* %p, align 4 @@ -363,6 +395,7 @@ } define i32 @test2_check(i32* %p) { +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind readonly willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@test2_check ; IS__TUNIT____-SAME: (i32* nocapture nofree readonly align 4 [[P:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -374,6 +407,7 @@ ; IS__TUNIT____: return: ; IS__TUNIT____-NEXT: ret i32 2 ; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind readonly willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@test2_check ; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -432,23 +466,43 @@ declare dso_local void @unkown() define internal i32 @r1(i32) local_unnamed_addr { -; IS________OPM-LABEL: define {{[^@]+}}@r1() local_unnamed_addr -; IS________OPM-NEXT: br label [[TMP4:%.*]] -; IS________OPM: 1: -; IS________OPM-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[TMP7:%.*]], 10000 -; IS________OPM-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[F:%.*]] -; IS________OPM: 3: -; IS________OPM-NEXT: ret i32 20 -; IS________OPM: f: -; IS________OPM-NEXT: ret i32 10 -; IS________OPM: 4: -; IS________OPM-NEXT: [[TMP5:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[TMP8:%.*]], [[TMP4]] ] -; IS________OPM-NEXT: [[TMP6:%.*]] = phi i32 [ 0, [[TMP0]] ], [ [[TMP7]], [[TMP4]] ] -; IS________OPM-NEXT: [[TMP7]] = add nuw nsw i32 [[TMP5]], [[TMP6]] -; IS________OPM-NEXT: [[TMP8]] = add nuw nsw i32 [[TMP5]], 1 -; IS________OPM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 100 -; IS________OPM-NEXT: br i1 [[TMP9]], label [[TMP1:%.*]], label [[TMP4]] -; +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@r1() local_unnamed_addr +; IS__TUNIT_OPM-NEXT: br label [[TMP4:%.*]] +; IS__TUNIT_OPM: 1: +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[TMP7:%.*]], 10000 +; IS__TUNIT_OPM-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[F:%.*]] +; IS__TUNIT_OPM: 3: +; IS__TUNIT_OPM-NEXT: ret i32 20 +; IS__TUNIT_OPM: f: +; IS__TUNIT_OPM-NEXT: ret i32 10 +; IS__TUNIT_OPM: 4: +; IS__TUNIT_OPM-NEXT: [[TMP5:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[TMP8:%.*]], [[TMP4]] ] +; IS__TUNIT_OPM-NEXT: [[TMP6:%.*]] = phi i32 [ 0, [[TMP0]] ], [ [[TMP7]], [[TMP4]] ] +; IS__TUNIT_OPM-NEXT: [[TMP7]] = add nuw nsw i32 [[TMP5]], [[TMP6]] +; IS__TUNIT_OPM-NEXT: [[TMP8]] = add nuw nsw i32 [[TMP5]], 1 +; IS__TUNIT_OPM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 100 +; IS__TUNIT_OPM-NEXT: br i1 [[TMP9]], label [[TMP1:%.*]], label [[TMP4]] +; +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@r1() local_unnamed_addr +; IS__CGSCC_OPM-NEXT: br label [[TMP4:%.*]] +; IS__CGSCC_OPM: 1: +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[TMP7:%.*]], 10000 +; IS__CGSCC_OPM-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[F:%.*]] +; IS__CGSCC_OPM: 3: +; IS__CGSCC_OPM-NEXT: ret i32 20 +; IS__CGSCC_OPM: f: +; IS__CGSCC_OPM-NEXT: ret i32 10 +; IS__CGSCC_OPM: 4: +; IS__CGSCC_OPM-NEXT: [[TMP5:%.*]] = phi i32 [ 0, [[TMP0:%.*]] ], [ [[TMP8:%.*]], [[TMP4]] ] +; IS__CGSCC_OPM-NEXT: [[TMP6:%.*]] = phi i32 [ 0, [[TMP0]] ], [ [[TMP7]], [[TMP4]] ] +; IS__CGSCC_OPM-NEXT: [[TMP7]] = add nuw nsw i32 [[TMP5]], [[TMP6]] +; IS__CGSCC_OPM-NEXT: [[TMP8]] = add nuw nsw i32 [[TMP5]], 1 +; IS__CGSCC_OPM-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 100 +; IS__CGSCC_OPM-NEXT: br i1 [[TMP9]], label [[TMP1:%.*]], label [[TMP4]] +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@r1() local_unnamed_addr ; IS__CGSCC_NPM-NEXT: br label [[TMP3:%.*]] ; IS__CGSCC_NPM: 1: @@ -495,13 +549,23 @@ ; IS________OPM: 5: ; IS________OPM-NEXT: ret void ; -; IS________NPM-LABEL: define {{[^@]+}}@f1 -; IS________NPM-SAME: (i32 [[TMP0:%.*]]) -; IS________NPM-NEXT: br label [[TMP3:%.*]] -; IS________NPM: 2: -; IS________NPM-NEXT: unreachable -; IS________NPM: 3: -; IS________NPM-NEXT: ret void +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@f1 +; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]]) +; IS__TUNIT_NPM-NEXT: br label [[TMP3:%.*]] +; IS__TUNIT_NPM: 2: +; IS__TUNIT_NPM-NEXT: unreachable +; IS__TUNIT_NPM: 3: +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f1 +; IS__CGSCC_NPM-SAME: (i32 [[TMP0:%.*]]) +; IS__CGSCC_NPM-NEXT: br label [[TMP3:%.*]] +; IS__CGSCC_NPM: 2: +; IS__CGSCC_NPM-NEXT: unreachable +; IS__CGSCC_NPM: 3: +; IS__CGSCC_NPM-NEXT: ret void ; %2 = tail call i32 @r1(i32 %0) %3 = icmp sgt i32 %2, 15 @@ -526,16 +590,29 @@ ; } ; } define dso_local i32 @test4-f1(i32 %u) { -; CHECK-LABEL: define {{[^@]+}}@test4-f1 -; CHECK-SAME: (i32 [[U:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[U]], -1 -; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]] -; CHECK: if.then: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: return: -; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[U]], [[IF_THEN]] ], [ 0, [[ENTRY:%.*]] ] -; CHECK-NEXT: ret i32 [[RETVAL_0]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test4-f1 +; IS__TUNIT____-SAME: (i32 [[U:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[U]], -1 +; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]] +; IS__TUNIT____: if.then: +; IS__TUNIT____-NEXT: br label [[RETURN]] +; IS__TUNIT____: return: +; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[U]], [[IF_THEN]] ], [ 0, [[ENTRY:%.*]] ] +; IS__TUNIT____-NEXT: ret i32 [[RETVAL_0]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test4-f1 +; IS__CGSCC____-SAME: (i32 [[U:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[U]], -1 +; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]] +; IS__CGSCC____: if.then: +; IS__CGSCC____-NEXT: br label [[RETURN]] +; IS__CGSCC____: return: +; IS__CGSCC____-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[U]], [[IF_THEN]] ], [ 0, [[ENTRY:%.*]] ] +; IS__CGSCC____-NEXT: ret i32 [[RETVAL_0]] ; ; FIXME: RETVAL_0 >= 0 entry: @@ -552,11 +629,19 @@ define dso_local i32 @test4-g1(i32 %u) { -; CHECK-LABEL: define {{[^@]+}}@test4-g1 -; CHECK-SAME: (i32 [[U:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = tail call i32 @test4-f1(i32 [[U]]) -; CHECK-NEXT: ret i32 [[CALL]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test4-g1 +; IS__TUNIT____-SAME: (i32 [[U:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[CALL:%.*]] = tail call i32 @test4-f1(i32 [[U]]) +; IS__TUNIT____-NEXT: ret i32 [[CALL]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test4-g1 +; IS__CGSCC____-SAME: (i32 [[U:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[CALL:%.*]] = tail call i32 @test4-f1(i32 [[U]]) +; IS__CGSCC____-NEXT: ret i32 [[CALL]] ; ; FIXME: %call should have range [0, inf] @@ -574,19 +659,35 @@ ; } ; } define dso_local i32 @test4-f2(i32 %u) { -; CHECK-LABEL: define {{[^@]+}}@test4-f2 -; CHECK-SAME: (i32 [[U:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[U]], -1 -; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] -; CHECK: if.then: -; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[U]], 1 -; CHECK-NEXT: br label [[RETURN:%.*]] -; CHECK: if.else: -; CHECK-NEXT: br label [[RETURN]] -; CHECK: return: -; CHECK-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[ADD]], [[IF_THEN]] ], [ 1, [[IF_ELSE]] ] -; CHECK-NEXT: ret i32 [[RETVAL_0]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test4-f2 +; IS__TUNIT____-SAME: (i32 [[U:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[U]], -1 +; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; IS__TUNIT____: if.then: +; IS__TUNIT____-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[U]], 1 +; IS__TUNIT____-NEXT: br label [[RETURN:%.*]] +; IS__TUNIT____: if.else: +; IS__TUNIT____-NEXT: br label [[RETURN]] +; IS__TUNIT____: return: +; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[ADD]], [[IF_THEN]] ], [ 1, [[IF_ELSE]] ] +; IS__TUNIT____-NEXT: ret i32 [[RETVAL_0]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test4-f2 +; IS__CGSCC____-SAME: (i32 [[U:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[U]], -1 +; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; IS__CGSCC____: if.then: +; IS__CGSCC____-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[U]], 1 +; IS__CGSCC____-NEXT: br label [[RETURN:%.*]] +; IS__CGSCC____: if.else: +; IS__CGSCC____-NEXT: br label [[RETURN]] +; IS__CGSCC____: return: +; IS__CGSCC____-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[ADD]], [[IF_THEN]] ], [ 1, [[IF_ELSE]] ] +; IS__CGSCC____-NEXT: ret i32 [[RETVAL_0]] ; entry: %cmp = icmp sgt i32 %u, -1 @@ -606,18 +707,27 @@ define dso_local i32 @test4-g2(i32 %u) { -; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@test4-g2 -; NOT_TUNIT_NPM-SAME: (i32 [[U:%.*]]) -; NOT_TUNIT_NPM-NEXT: entry: -; NOT_TUNIT_NPM-NEXT: [[CALL:%.*]] = tail call i32 @test4-f2(i32 [[U]]) -; NOT_TUNIT_NPM-NEXT: ret i32 [[CALL]] +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test4-g2 +; IS__TUNIT_OPM-SAME: (i32 [[U:%.*]]) +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = tail call i32 @test4-f2(i32 [[U]]) +; IS__TUNIT_OPM-NEXT: ret i32 [[CALL]] ; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@test4-g2 ; IS__TUNIT_NPM-SAME: (i32 [[U:%.*]]) ; IS__TUNIT_NPM-NEXT: entry: ; IS__TUNIT_NPM-NEXT: [[CALL:%.*]] = tail call i32 @test4-f2(i32 [[U]]) #1, !range !3 ; IS__TUNIT_NPM-NEXT: ret i32 [[CALL]] ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test4-g2 +; IS__CGSCC____-SAME: (i32 [[U:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[CALL:%.*]] = tail call i32 @test4-f2(i32 [[U]]) +; IS__CGSCC____-NEXT: ret i32 [[CALL]] +; entry: %call = tail call i32 @test4-f2(i32 %u) ret i32 %call @@ -700,30 +810,57 @@ ; FIXME: All but the return is not needed anymore define dso_local zeroext i1 @phi(i32 %arg) { -; CHECK-LABEL: define {{[^@]+}}@phi -; CHECK-SAME: (i32 [[ARG:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP:%.*]] = icmp sgt i32 [[ARG]], 5 -; CHECK-NEXT: br i1 [[TMP]], label [[BB1:%.*]], label [[BB2:%.*]] -; CHECK: bb1: -; CHECK-NEXT: br label [[BB3:%.*]] -; CHECK: bb2: -; CHECK-NEXT: br label [[BB3]] -; CHECK: bb3: -; CHECK-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[ARG]], 10 -; CHECK-NEXT: br i1 [[TMP4]], label [[BB5:%.*]], label [[BB7:%.*]] -; CHECK: bb5: -; CHECK-NEXT: br label [[BB9:%.*]] -; CHECK: bb7: -; CHECK-NEXT: br label [[BB9]] -; CHECK: bb9: -; CHECK-NEXT: br label [[BB12:%.*]] -; CHECK: bb11: -; CHECK-NEXT: unreachable -; CHECK: bb12: -; CHECK-NEXT: br label [[BB13:%.*]] -; CHECK: bb13: -; CHECK-NEXT: ret i1 false +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@phi +; IS__TUNIT____-SAME: (i32 [[ARG:%.*]]) +; IS__TUNIT____-NEXT: bb: +; IS__TUNIT____-NEXT: [[TMP:%.*]] = icmp sgt i32 [[ARG]], 5 +; IS__TUNIT____-NEXT: br i1 [[TMP]], label [[BB1:%.*]], label [[BB2:%.*]] +; IS__TUNIT____: bb1: +; IS__TUNIT____-NEXT: br label [[BB3:%.*]] +; IS__TUNIT____: bb2: +; IS__TUNIT____-NEXT: br label [[BB3]] +; IS__TUNIT____: bb3: +; IS__TUNIT____-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[ARG]], 10 +; IS__TUNIT____-NEXT: br i1 [[TMP4]], label [[BB5:%.*]], label [[BB7:%.*]] +; IS__TUNIT____: bb5: +; IS__TUNIT____-NEXT: br label [[BB9:%.*]] +; IS__TUNIT____: bb7: +; IS__TUNIT____-NEXT: br label [[BB9]] +; IS__TUNIT____: bb9: +; IS__TUNIT____-NEXT: br label [[BB12:%.*]] +; IS__TUNIT____: bb11: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: bb12: +; IS__TUNIT____-NEXT: br label [[BB13:%.*]] +; IS__TUNIT____: bb13: +; IS__TUNIT____-NEXT: ret i1 false +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@phi +; IS__CGSCC____-SAME: (i32 [[ARG:%.*]]) +; IS__CGSCC____-NEXT: bb: +; IS__CGSCC____-NEXT: [[TMP:%.*]] = icmp sgt i32 [[ARG]], 5 +; IS__CGSCC____-NEXT: br i1 [[TMP]], label [[BB1:%.*]], label [[BB2:%.*]] +; IS__CGSCC____: bb1: +; IS__CGSCC____-NEXT: br label [[BB3:%.*]] +; IS__CGSCC____: bb2: +; IS__CGSCC____-NEXT: br label [[BB3]] +; IS__CGSCC____: bb3: +; IS__CGSCC____-NEXT: [[TMP4:%.*]] = icmp sgt i32 [[ARG]], 10 +; IS__CGSCC____-NEXT: br i1 [[TMP4]], label [[BB5:%.*]], label [[BB7:%.*]] +; IS__CGSCC____: bb5: +; IS__CGSCC____-NEXT: br label [[BB9:%.*]] +; IS__CGSCC____: bb7: +; IS__CGSCC____-NEXT: br label [[BB9]] +; IS__CGSCC____: bb9: +; IS__CGSCC____-NEXT: br label [[BB12:%.*]] +; IS__CGSCC____: bb11: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: bb12: +; IS__CGSCC____-NEXT: br label [[BB13:%.*]] +; IS__CGSCC____: bb13: +; IS__CGSCC____-NEXT: ret i1 false ; bb: %tmp = icmp sgt i32 %arg, 5 @@ -765,10 +902,17 @@ } define dso_local i1 @select(i32 %a) local_unnamed_addr #0 { -; CHECK-LABEL: define {{[^@]+}}@select -; CHECK-SAME: (i32 [[A:%.*]]) local_unnamed_addr -; CHECK-NEXT: entry: -; CHECK-NEXT: ret i1 false +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@select +; IS__TUNIT____-SAME: (i32 [[A:%.*]]) local_unnamed_addr +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret i1 false +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@select +; IS__CGSCC____-SAME: (i32 [[A:%.*]]) local_unnamed_addr +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i1 false ; entry: %cmp = icmp sgt i32 %a, 5 @@ -781,10 +925,17 @@ } define dso_local i32 @select_zext(i32 %a) local_unnamed_addr #0 { -; CHECK-LABEL: define {{[^@]+}}@select_zext -; CHECK-SAME: (i32 [[A:%.*]]) local_unnamed_addr -; CHECK-NEXT: entry: -; CHECK-NEXT: ret i32 0 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@select_zext +; IS__TUNIT____-SAME: (i32 [[A:%.*]]) local_unnamed_addr +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret i32 0 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@select_zext +; IS__CGSCC____-SAME: (i32 [[A:%.*]]) local_unnamed_addr +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i32 0 ; entry: %cmp = icmp sgt i32 %a, 5 @@ -799,13 +950,23 @@ ; FIXME: We do not look through the ptr casts here. define dso_local i64 @select_int2ptr_bitcast_ptr2int(i32 %a) local_unnamed_addr #0 { -; CHECK-LABEL: define {{[^@]+}}@select_int2ptr_bitcast_ptr2int -; CHECK-SAME: (i32 [[A:%.*]]) local_unnamed_addr -; CHECK-NEXT: entry: -; CHECK-NEXT: [[I2P:%.*]] = inttoptr i1 false to i1* -; CHECK-NEXT: [[BC:%.*]] = bitcast i1* [[I2P]] to i32* -; CHECK-NEXT: [[P2I:%.*]] = ptrtoint i32* [[BC]] to i64 -; CHECK-NEXT: ret i64 [[P2I]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@select_int2ptr_bitcast_ptr2int +; IS__TUNIT____-SAME: (i32 [[A:%.*]]) local_unnamed_addr +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[I2P:%.*]] = inttoptr i1 false to i1* +; IS__TUNIT____-NEXT: [[BC:%.*]] = bitcast i1* [[I2P]] to i32* +; IS__TUNIT____-NEXT: [[P2I:%.*]] = ptrtoint i32* [[BC]] to i64 +; IS__TUNIT____-NEXT: ret i64 [[P2I]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@select_int2ptr_bitcast_ptr2int +; IS__CGSCC____-SAME: (i32 [[A:%.*]]) local_unnamed_addr +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[I2P:%.*]] = inttoptr i1 false to i1* +; IS__CGSCC____-NEXT: [[BC:%.*]] = bitcast i1* [[I2P]] to i32* +; IS__CGSCC____-NEXT: [[P2I:%.*]] = ptrtoint i32* [[BC]] to i64 +; IS__CGSCC____-NEXT: ret i64 [[P2I]] ; entry: %cmp = icmp sgt i32 %a, 5 @@ -823,60 +984,105 @@ ; } define i1 @f_fcmp(float %a, float %b) { -; CHECK-LABEL: define {{[^@]+}}@f_fcmp -; CHECK-SAME: (float [[A:%.*]], float [[B:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fcmp uge float [[A]], [[B]] -; CHECK-NEXT: [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false -; CHECK-NEXT: ret i1 [[S]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@f_fcmp +; IS__TUNIT____-SAME: (float [[A:%.*]], float [[B:%.*]]) +; IS__TUNIT____-NEXT: [[R:%.*]] = fcmp uge float [[A]], [[B]] +; IS__TUNIT____-NEXT: [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false +; IS__TUNIT____-NEXT: ret i1 [[S]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@f_fcmp +; IS__CGSCC____-SAME: (float [[A:%.*]], float [[B:%.*]]) +; IS__CGSCC____-NEXT: [[R:%.*]] = fcmp uge float [[A]], [[B]] +; IS__CGSCC____-NEXT: [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false +; IS__CGSCC____-NEXT: ret i1 [[S]] ; %r = fcmp uge float %a, %b %s = select i1 %r, i1 %r, i1 0 ret i1 %s } define i1 @d_fcmp(double %a, double %b) { -; CHECK-LABEL: define {{[^@]+}}@d_fcmp -; CHECK-SAME: (double [[A:%.*]], double [[B:%.*]]) -; CHECK-NEXT: [[R:%.*]] = fcmp oeq double [[A]], [[B]] -; CHECK-NEXT: [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false -; CHECK-NEXT: ret i1 [[S]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@d_fcmp +; IS__TUNIT____-SAME: (double [[A:%.*]], double [[B:%.*]]) +; IS__TUNIT____-NEXT: [[R:%.*]] = fcmp oeq double [[A]], [[B]] +; IS__TUNIT____-NEXT: [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false +; IS__TUNIT____-NEXT: ret i1 [[S]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@d_fcmp +; IS__CGSCC____-SAME: (double [[A:%.*]], double [[B:%.*]]) +; IS__CGSCC____-NEXT: [[R:%.*]] = fcmp oeq double [[A]], [[B]] +; IS__CGSCC____-NEXT: [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false +; IS__CGSCC____-NEXT: ret i1 [[S]] ; %r = fcmp oeq double %a, %b %s = select i1 %r, i1 %r, i1 0 ret i1 %s } define i1 @dp_icmp(double* %a, double* %b) { -; CHECK-LABEL: define {{[^@]+}}@dp_icmp -; CHECK-SAME: (double* nofree readnone [[A:%.*]], double* nofree readnone [[B:%.*]]) -; CHECK-NEXT: [[R:%.*]] = icmp sge double* [[A]], [[B]] -; CHECK-NEXT: [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false -; CHECK-NEXT: ret i1 [[S]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@dp_icmp +; IS__TUNIT____-SAME: (double* nofree readnone [[A:%.*]], double* nofree readnone [[B:%.*]]) +; IS__TUNIT____-NEXT: [[R:%.*]] = icmp sge double* [[A]], [[B]] +; IS__TUNIT____-NEXT: [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false +; IS__TUNIT____-NEXT: ret i1 [[S]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@dp_icmp +; IS__CGSCC____-SAME: (double* nofree readnone [[A:%.*]], double* nofree readnone [[B:%.*]]) +; IS__CGSCC____-NEXT: [[R:%.*]] = icmp sge double* [[A]], [[B]] +; IS__CGSCC____-NEXT: [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false +; IS__CGSCC____-NEXT: ret i1 [[S]] ; %r = icmp sge double* %a, %b %s = select i1 %r, i1 %r, i1 0 ret i1 %s } define i1 @ip_icmp(i8* %a, i8* %b) { -; CHECK-LABEL: define {{[^@]+}}@ip_icmp -; CHECK-SAME: (i8* nofree readnone [[A:%.*]], i8* nofree readnone [[B:%.*]]) -; CHECK-NEXT: [[R:%.*]] = icmp ult i8* [[A]], [[B]] -; CHECK-NEXT: [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false -; CHECK-NEXT: ret i1 [[S]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@ip_icmp +; IS__TUNIT____-SAME: (i8* nofree readnone [[A:%.*]], i8* nofree readnone [[B:%.*]]) +; IS__TUNIT____-NEXT: [[R:%.*]] = icmp ult i8* [[A]], [[B]] +; IS__TUNIT____-NEXT: [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false +; IS__TUNIT____-NEXT: ret i1 [[S]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@ip_icmp +; IS__CGSCC____-SAME: (i8* nofree readnone [[A:%.*]], i8* nofree readnone [[B:%.*]]) +; IS__CGSCC____-NEXT: [[R:%.*]] = icmp ult i8* [[A]], [[B]] +; IS__CGSCC____-NEXT: [[S:%.*]] = select i1 [[R]], i1 [[R]], i1 false +; IS__CGSCC____-NEXT: ret i1 [[S]] ; %r = icmp ult i8* %a, %b %s = select i1 %r, i1 %r, i1 0 ret i1 %s } define i1 @fcmp_caller(float %fa, float %fb, double %da, double %db, double* %dpa, double* %dpb, i8* %ipa, i8* %ipb) { -; CHECK-LABEL: define {{[^@]+}}@fcmp_caller -; CHECK-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:%.*]]) -; CHECK-NEXT: [[R1:%.*]] = call i1 @f_fcmp(float [[FA]], float [[FB]]) -; CHECK-NEXT: [[R2:%.*]] = call i1 @d_fcmp(double [[DA]], double [[DB]]) -; CHECK-NEXT: [[R3:%.*]] = call i1 @dp_icmp(double* noalias nofree readnone [[DPA]], double* noalias nofree readnone [[DPB]]) -; CHECK-NEXT: [[R4:%.*]] = call i1 @ip_icmp(i8* noalias nofree readnone [[IPA]], i8* noalias nofree readnone [[IPB]]) -; CHECK-NEXT: [[O1:%.*]] = or i1 [[R1]], [[R2]] -; CHECK-NEXT: [[O2:%.*]] = or i1 [[R3]], [[R4]] -; CHECK-NEXT: [[O3:%.*]] = or i1 [[O1]], [[O2]] -; CHECK-NEXT: ret i1 [[O3]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@fcmp_caller +; IS__TUNIT____-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:%.*]]) +; IS__TUNIT____-NEXT: [[R1:%.*]] = call i1 @f_fcmp(float [[FA]], float [[FB]]) +; IS__TUNIT____-NEXT: [[R2:%.*]] = call i1 @d_fcmp(double [[DA]], double [[DB]]) +; IS__TUNIT____-NEXT: [[R3:%.*]] = call i1 @dp_icmp(double* noalias nofree readnone [[DPA]], double* noalias nofree readnone [[DPB]]) +; IS__TUNIT____-NEXT: [[R4:%.*]] = call i1 @ip_icmp(i8* noalias nofree readnone [[IPA]], i8* noalias nofree readnone [[IPB]]) +; IS__TUNIT____-NEXT: [[O1:%.*]] = or i1 [[R1]], [[R2]] +; IS__TUNIT____-NEXT: [[O2:%.*]] = or i1 [[R3]], [[R4]] +; IS__TUNIT____-NEXT: [[O3:%.*]] = or i1 [[O1]], [[O2]] +; IS__TUNIT____-NEXT: ret i1 [[O3]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@fcmp_caller +; IS__CGSCC____-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:%.*]]) +; IS__CGSCC____-NEXT: [[R1:%.*]] = call i1 @f_fcmp(float [[FA]], float [[FB]]) +; IS__CGSCC____-NEXT: [[R2:%.*]] = call i1 @d_fcmp(double [[DA]], double [[DB]]) +; IS__CGSCC____-NEXT: [[R3:%.*]] = call i1 @dp_icmp(double* noalias nofree readnone [[DPA]], double* noalias nofree readnone [[DPB]]) +; IS__CGSCC____-NEXT: [[R4:%.*]] = call i1 @ip_icmp(i8* noalias nofree readnone [[IPA]], i8* noalias nofree readnone [[IPB]]) +; IS__CGSCC____-NEXT: [[O1:%.*]] = or i1 [[R1]], [[R2]] +; IS__CGSCC____-NEXT: [[O2:%.*]] = or i1 [[R3]], [[R4]] +; IS__CGSCC____-NEXT: [[O3:%.*]] = or i1 [[O1]], [[O2]] +; IS__CGSCC____-NEXT: ret i1 [[O3]] ; %r1 = call i1 @f_fcmp(float %fa, float %fb) %r2 = call i1 @d_fcmp(double %da, double %db) @@ -889,22 +1095,37 @@ } define i8 @ret_two() { -; CHECK-LABEL: define {{[^@]+}}@ret_two() -; CHECK-NEXT: ret i8 2 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@ret_two() +; IS__TUNIT____-NEXT: ret i8 2 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@ret_two() +; IS__CGSCC____-NEXT: ret i8 2 ; ret i8 2 } define i8 @ret_undef() { -; CHECK-LABEL: define {{[^@]+}}@ret_undef() -; CHECK-NEXT: ret i8 undef +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@ret_undef() +; IS__TUNIT____-NEXT: ret i8 undef +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@ret_undef() +; IS__CGSCC____-NEXT: ret i8 undef ; ret i8 undef } ; Verify we collapse undef to a value and return something non-undef here. define i8 @undef_collapse_1() { -; CHECK-LABEL: define {{[^@]+}}@undef_collapse_1() -; CHECK-NEXT: ret i8 0 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@undef_collapse_1() +; IS__TUNIT____-NEXT: ret i8 0 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@undef_collapse_1() +; IS__CGSCC____-NEXT: ret i8 0 ; %c = call i8 @ret_undef() %s = shl i8 %c, 2 @@ -913,8 +1134,13 @@ ; Verify we collapse undef to a value and return something non-undef here. define i8 @undef_collapse_2() { -; CHECK-LABEL: define {{[^@]+}}@undef_collapse_2() -; CHECK-NEXT: ret i8 0 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@undef_collapse_2() +; IS__TUNIT____-NEXT: ret i8 0 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@undef_collapse_2() +; IS__CGSCC____-NEXT: ret i8 0 ; %c = call i8 @ret_two() %s = shl i8 undef, %c @@ -923,9 +1149,11 @@ define i8 @undef_collapse_caller() { ; +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@undef_collapse_caller() ; IS__TUNIT____-NEXT: ret i8 0 ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@undef_collapse_caller() ; IS__CGSCC____-NEXT: [[C1:%.*]] = call i8 @undef_collapse_1() ; IS__CGSCC____-NEXT: [[C2:%.*]] = call i8 @undef_collapse_2() @@ -939,20 +1167,29 @@ } define i32 @ret1or2(i1 %c) { -; CHECK-LABEL: define {{[^@]+}}@ret1or2 -; CHECK-SAME: (i1 [[C:%.*]]) -; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i32 1, i32 2 -; CHECK-NEXT: ret i32 [[S]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@ret1or2 +; IS__TUNIT____-SAME: (i1 [[C:%.*]]) +; IS__TUNIT____-NEXT: [[S:%.*]] = select i1 [[C]], i32 1, i32 2 +; IS__TUNIT____-NEXT: ret i32 [[S]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@ret1or2 +; IS__CGSCC____-SAME: (i1 [[C:%.*]]) +; IS__CGSCC____-NEXT: [[S:%.*]] = select i1 [[C]], i32 1, i32 2 +; IS__CGSCC____-NEXT: ret i32 [[S]] ; %s = select i1 %c, i32 1, i32 2 ret i32 %s } define i1 @callee_range_1(i1 %c1, i1 %c2, i1 %c3) { ; +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@callee_range_1 ; IS__TUNIT____-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]]) ; IS__TUNIT____-NEXT: ret i1 true ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@callee_range_1 ; IS__CGSCC____-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]], i1 [[C3:%.*]]) ; IS__CGSCC____-NEXT: [[R1:%.*]] = call i32 @ret1or2(i1 [[C1]]) @@ -976,6 +1213,7 @@ define i1 @callee_range_2(i1 %c1, i1 %c2) { ; +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@callee_range_2 ; IS__TUNIT_OPM-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]]) ; IS__TUNIT_OPM-NEXT: [[R1:%.*]] = call i32 @ret1or2(i1 [[C1]]) #2, !range !4 @@ -986,6 +1224,7 @@ ; IS__TUNIT_OPM-NEXT: [[F:%.*]] = and i1 [[I1]], [[I2]] ; IS__TUNIT_OPM-NEXT: ret i1 [[F]] ; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@callee_range_2 ; IS__TUNIT_NPM-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]]) ; IS__TUNIT_NPM-NEXT: [[R1:%.*]] = call i32 @ret1or2(i1 [[C1]]) #1, !range !5 @@ -996,6 +1235,7 @@ ; IS__TUNIT_NPM-NEXT: [[F:%.*]] = and i1 [[I1]], [[I2]] ; IS__TUNIT_NPM-NEXT: ret i1 [[F]] ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@callee_range_2 ; IS__CGSCC____-SAME: (i1 [[C1:%.*]], i1 [[C2:%.*]]) ; IS__CGSCC____-NEXT: [[R1:%.*]] = call i32 @ret1or2(i1 [[C1]]) @@ -1017,37 +1257,70 @@ define i32 @ret100() { -; CHECK-LABEL: define {{[^@]+}}@ret100() -; CHECK-NEXT: ret i32 100 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@ret100() +; IS__TUNIT____-NEXT: ret i32 100 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@ret100() +; IS__CGSCC____-NEXT: ret i32 100 ; ret i32 100 } define i1 @ctx_adjustment(i32 %V) { ; -; IS________OPM-LABEL: define {{[^@]+}}@ctx_adjustment -; IS________OPM-SAME: (i32 [[V:%.*]]) -; IS________OPM-NEXT: [[C1:%.*]] = icmp sge i32 [[V]], 100 -; IS________OPM-NEXT: br i1 [[C1]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] -; IS________OPM: if.true: -; IS________OPM-NEXT: br label [[END:%.*]] -; IS________OPM: if.false: -; IS________OPM-NEXT: br label [[END]] -; IS________OPM: end: -; IS________OPM-NEXT: [[PHI:%.*]] = phi i32 [ [[V]], [[IF_TRUE]] ], [ 100, [[IF_FALSE]] ] -; IS________OPM-NEXT: [[C2:%.*]] = icmp sge i32 [[PHI]], 100 -; IS________OPM-NEXT: ret i1 [[C2]] -; -; IS________NPM-LABEL: define {{[^@]+}}@ctx_adjustment -; IS________NPM-SAME: (i32 [[V:%.*]]) -; IS________NPM-NEXT: [[C1:%.*]] = icmp sge i32 [[V]], 100 -; IS________NPM-NEXT: br i1 [[C1]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] -; IS________NPM: if.true: -; IS________NPM-NEXT: br label [[END:%.*]] -; IS________NPM: if.false: -; IS________NPM-NEXT: br label [[END]] -; IS________NPM: end: -; IS________NPM-NEXT: ret i1 true +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@ctx_adjustment +; IS__TUNIT_OPM-SAME: (i32 [[V:%.*]]) +; IS__TUNIT_OPM-NEXT: [[C1:%.*]] = icmp sge i32 [[V]], 100 +; IS__TUNIT_OPM-NEXT: br i1 [[C1]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] +; IS__TUNIT_OPM: if.true: +; IS__TUNIT_OPM-NEXT: br label [[END:%.*]] +; IS__TUNIT_OPM: if.false: +; IS__TUNIT_OPM-NEXT: br label [[END]] +; IS__TUNIT_OPM: end: +; IS__TUNIT_OPM-NEXT: [[PHI:%.*]] = phi i32 [ [[V]], [[IF_TRUE]] ], [ 100, [[IF_FALSE]] ] +; IS__TUNIT_OPM-NEXT: [[C2:%.*]] = icmp sge i32 [[PHI]], 100 +; IS__TUNIT_OPM-NEXT: ret i1 [[C2]] +; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@ctx_adjustment +; IS__TUNIT_NPM-SAME: (i32 [[V:%.*]]) +; IS__TUNIT_NPM-NEXT: [[C1:%.*]] = icmp sge i32 [[V]], 100 +; IS__TUNIT_NPM-NEXT: br i1 [[C1]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] +; IS__TUNIT_NPM: if.true: +; IS__TUNIT_NPM-NEXT: br label [[END:%.*]] +; IS__TUNIT_NPM: if.false: +; IS__TUNIT_NPM-NEXT: br label [[END]] +; IS__TUNIT_NPM: end: +; IS__TUNIT_NPM-NEXT: ret i1 true +; +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@ctx_adjustment +; IS__CGSCC_OPM-SAME: (i32 [[V:%.*]]) +; IS__CGSCC_OPM-NEXT: [[C1:%.*]] = icmp sge i32 [[V]], 100 +; IS__CGSCC_OPM-NEXT: br i1 [[C1]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] +; IS__CGSCC_OPM: if.true: +; IS__CGSCC_OPM-NEXT: br label [[END:%.*]] +; IS__CGSCC_OPM: if.false: +; IS__CGSCC_OPM-NEXT: br label [[END]] +; IS__CGSCC_OPM: end: +; IS__CGSCC_OPM-NEXT: [[PHI:%.*]] = phi i32 [ [[V]], [[IF_TRUE]] ], [ 100, [[IF_FALSE]] ] +; IS__CGSCC_OPM-NEXT: [[C2:%.*]] = icmp sge i32 [[PHI]], 100 +; IS__CGSCC_OPM-NEXT: ret i1 [[C2]] +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@ctx_adjustment +; IS__CGSCC_NPM-SAME: (i32 [[V:%.*]]) +; IS__CGSCC_NPM-NEXT: [[C1:%.*]] = icmp sge i32 [[V]], 100 +; IS__CGSCC_NPM-NEXT: br i1 [[C1]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] +; IS__CGSCC_NPM: if.true: +; IS__CGSCC_NPM-NEXT: br label [[END:%.*]] +; IS__CGSCC_NPM: if.false: +; IS__CGSCC_NPM-NEXT: br label [[END]] +; IS__CGSCC_NPM: end: +; IS__CGSCC_NPM-NEXT: ret i1 true ; %c1 = icmp sge i32 %V, 100 br i1 %c1, label %if.true, label %if.false @@ -1064,16 +1337,24 @@ define i32 @func(i1 %c) { -; CHECK-LABEL: define {{[^@]+}}@func -; CHECK-SAME: (i1 [[C:%.*]]) -; CHECK-NEXT: [[RET:%.*]] = select i1 [[C]], i32 0, i32 1 -; CHECK-NEXT: ret i32 [[RET]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@func +; IS__TUNIT____-SAME: (i1 [[C:%.*]]) +; IS__TUNIT____-NEXT: [[RET:%.*]] = select i1 [[C]], i32 0, i32 1 +; IS__TUNIT____-NEXT: ret i32 [[RET]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@func +; IS__CGSCC____-SAME: (i1 [[C:%.*]]) +; IS__CGSCC____-NEXT: [[RET:%.*]] = select i1 [[C]], i32 0, i32 1 +; IS__CGSCC____-NEXT: ret i32 [[RET]] ; %ret = select i1 %c, i32 0, i32 1 ret i32 %ret } define i32 @simplify_callsite_argument(i1 %d) { +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@simplify_callsite_argument ; IS__TUNIT_OPM-SAME: (i1 [[D:%.*]]) ; IS__TUNIT_OPM-NEXT: [[C:%.*]] = select i1 [[D]], i1 true, i1 false @@ -1085,6 +1366,7 @@ ; IS__TUNIT_OPM-NEXT: [[RET2:%.*]] = call i32 @func(i1 false) #2, !range !3 ; IS__TUNIT_OPM-NEXT: ret i32 [[RET2]] ; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@simplify_callsite_argument ; IS__TUNIT_NPM-SAME: (i1 [[D:%.*]]) ; IS__TUNIT_NPM-NEXT: [[C:%.*]] = select i1 [[D]], i1 true, i1 false @@ -1096,6 +1378,7 @@ ; IS__TUNIT_NPM-NEXT: [[RET2:%.*]] = call i32 @func(i1 false) #1, !range !4 ; IS__TUNIT_NPM-NEXT: ret i32 [[RET2]] ; +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@simplify_callsite_argument ; IS__CGSCC_OPM-SAME: (i1 [[D:%.*]]) ; IS__CGSCC_OPM-NEXT: [[C:%.*]] = select i1 [[D]], i1 true, i1 false @@ -1107,6 +1390,7 @@ ; IS__CGSCC_OPM-NEXT: [[RET2:%.*]] = call i32 @func(i1 false) ; IS__CGSCC_OPM-NEXT: ret i32 [[RET2]] ; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@simplify_callsite_argument ; IS__CGSCC_NPM-SAME: (i1 [[D:%.*]]) ; IS__CGSCC_NPM-NEXT: [[C:%.*]] = select i1 [[D]], i1 true, i1 false diff --git a/llvm/test/Transforms/Attributor/read_write_returned_arguments_scc.ll b/llvm/test/Transforms/Attributor/read_write_returned_arguments_scc.ll --- a/llvm/test/Transforms/Attributor/read_write_returned_arguments_scc.ll +++ b/llvm/test/Transforms/Attributor/read_write_returned_arguments_scc.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=16 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=16 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -34,8 +34,8 @@ ; target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" -; CHECK: Function Attrs: argmemonly nofree nosync nounwind define i32* @external_ret2_nrw(i32* %n0, i32* %r0, i32* %w0) { +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind ; IS__TUNIT____-LABEL: define {{[^@]+}}@external_ret2_nrw ; IS__TUNIT____-SAME: (i32* nofree [[N0:%.*]], i32* nofree [[R0:%.*]], i32* nofree returned [[W0:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -45,6 +45,7 @@ ; IS__TUNIT____-NEXT: [[CALL3:%.*]] = call i32* @internal_ret1_rw(i32* nofree align 4 [[R0]], i32* nofree [[W0]]) ; IS__TUNIT____-NEXT: ret i32* [[CALL3]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@external_ret2_nrw ; IS__CGSCC____-SAME: (i32* nofree [[N0:%.*]], i32* nofree align 4 [[R0:%.*]], i32* nofree returned [[W0:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -62,8 +63,8 @@ ret i32* %call3 } -; CHECK: Function Attrs: argmemonly nofree nosync nounwind define internal i32* @internal_ret0_nw(i32* %n0, i32* %w0) { +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind ; IS__TUNIT____-LABEL: define {{[^@]+}}@internal_ret0_nw ; IS__TUNIT____-SAME: (i32* nofree returned [[N0:%.*]], i32* nofree [[W0:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -88,6 +89,7 @@ ; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi i32* [ [[CALL5]], [[IF_END]] ], [ [[N0]], [[IF_THEN]] ] ; IS__TUNIT____-NEXT: ret i32* [[RETVAL_0]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@internal_ret0_nw ; IS__CGSCC____-SAME: (i32* nofree returned [[N0:%.*]], i32* nofree [[W0:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -138,8 +140,8 @@ ret i32* %retval.0 } -; CHECK: Function Attrs: argmemonly nofree nosync nounwind define internal i32* @internal_ret1_rrw(i32* %r0, i32* %r1, i32* %w0) { +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind ; IS__TUNIT____-LABEL: define {{[^@]+}}@internal_ret1_rrw ; IS__TUNIT____-SAME: (i32* nofree nonnull align 4 dereferenceable(4) [[R0:%.*]], i32* nofree returned [[R1:%.*]], i32* nofree [[W0:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -167,6 +169,7 @@ ; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi i32* [ [[CALL8]], [[IF_END]] ], [ [[R1]], [[IF_THEN]] ] ; IS__TUNIT____-NEXT: ret i32* undef ; +; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@internal_ret1_rrw ; IS__CGSCC____-SAME: (i32* nofree nonnull align 4 dereferenceable(4) [[R0:%.*]], i32* nofree returned [[R1:%.*]], i32* nofree [[W0:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -223,22 +226,36 @@ ret i32* %retval.0 } +define i32* @external_sink_ret2_nrw(i32* %n0, i32* %r0, i32* %w0) { ; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@external_sink_ret2_nrw +; IS__TUNIT____-SAME: (i32* nofree [[N0:%.*]], i32* nocapture nofree readonly [[R0:%.*]], i32* nofree returned writeonly "no-capture-maybe-returned" [[W0:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[TOBOOL:%.*]] = icmp ne i32* [[N0]], null +; IS__TUNIT____-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] +; IS__TUNIT____: if.then: +; IS__TUNIT____-NEXT: br label [[RETURN:%.*]] +; IS__TUNIT____: if.end: +; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32, i32* [[R0]], align 4 +; IS__TUNIT____-NEXT: store i32 [[TMP0]], i32* [[W0]], align 4 +; IS__TUNIT____-NEXT: br label [[RETURN]] +; IS__TUNIT____: return: +; IS__TUNIT____-NEXT: ret i32* [[W0]] +; ; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn -define i32* @external_sink_ret2_nrw(i32* %n0, i32* %r0, i32* %w0) { -; CHECK-LABEL: define {{[^@]+}}@external_sink_ret2_nrw -; CHECK-SAME: (i32* nofree [[N0:%.*]], i32* nocapture nofree readonly [[R0:%.*]], i32* nofree returned writeonly "no-capture-maybe-returned" [[W0:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32* [[N0]], null -; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] -; CHECK: if.then: -; CHECK-NEXT: br label [[RETURN:%.*]] -; CHECK: if.end: -; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[R0]], align 4 -; CHECK-NEXT: store i32 [[TMP0]], i32* [[W0]], align 4 -; CHECK-NEXT: br label [[RETURN]] -; CHECK: return: -; CHECK-NEXT: ret i32* [[W0]] +; IS__CGSCC____-LABEL: define {{[^@]+}}@external_sink_ret2_nrw +; IS__CGSCC____-SAME: (i32* nofree [[N0:%.*]], i32* nocapture nofree readonly [[R0:%.*]], i32* nofree returned writeonly "no-capture-maybe-returned" [[W0:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[TOBOOL:%.*]] = icmp ne i32* [[N0]], null +; IS__CGSCC____-NEXT: br i1 [[TOBOOL]], label [[IF_END:%.*]], label [[IF_THEN:%.*]] +; IS__CGSCC____: if.then: +; IS__CGSCC____-NEXT: br label [[RETURN:%.*]] +; IS__CGSCC____: if.end: +; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* [[R0]], align 4 +; IS__CGSCC____-NEXT: store i32 [[TMP0]], i32* [[W0]], align 4 +; IS__CGSCC____-NEXT: br label [[RETURN]] +; IS__CGSCC____: return: +; IS__CGSCC____-NEXT: ret i32* [[W0]] ; entry: %tobool = icmp ne i32* %n0, null @@ -256,8 +273,8 @@ ret i32* %w0 } -; CHECK: Function Attrs: argmemonly nofree nosync nounwind define internal i32* @internal_ret1_rw(i32* %r0, i32* %w0) { +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind ; IS__TUNIT____-LABEL: define {{[^@]+}}@internal_ret1_rw ; IS__TUNIT____-SAME: (i32* nofree nonnull align 4 dereferenceable(4) [[R0:%.*]], i32* nofree returned [[W0:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -279,6 +296,7 @@ ; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi i32* [ [[CALL4]], [[IF_END]] ], [ [[W0]], [[IF_THEN]] ] ; IS__TUNIT____-NEXT: ret i32* [[RETVAL_0]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@internal_ret1_rw ; IS__CGSCC____-SAME: (i32* nofree nonnull align 4 dereferenceable(4) [[R0:%.*]], i32* nofree returned [[W0:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -323,8 +341,8 @@ ret i32* %retval.0 } -; CHECK: Function Attrs: argmemonly nofree nosync nounwind define i32* @external_source_ret2_nrw(i32* %n0, i32* %r0, i32* %w0) { +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind ; IS__TUNIT____-LABEL: define {{[^@]+}}@external_source_ret2_nrw ; IS__TUNIT____-SAME: (i32* nofree [[N0:%.*]], i32* nofree [[R0:%.*]], i32* nofree returned [[W0:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -332,6 +350,7 @@ ; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call i32* @external_ret2_nrw(i32* nofree [[N0]], i32* nofree [[R0]], i32* nofree [[W0]]) ; IS__TUNIT____-NEXT: ret i32* [[CALL1]] ; +; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind ; IS__CGSCC____-LABEL: define {{[^@]+}}@external_source_ret2_nrw ; IS__CGSCC____-SAME: (i32* nofree [[N0:%.*]], i32* nofree align 4 [[R0:%.*]], i32* nofree returned [[W0:%.*]]) ; IS__CGSCC____-NEXT: entry: 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 @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -24,20 +24,34 @@ } define i8* @test2(i8* %p) { -; CHECK-LABEL: define {{[^@]+}}@test2 -; CHECK-SAME: (i8* nofree readnone returned "no-capture-maybe-returned" [[P:%.*]]) -; CHECK-NEXT: store i32 0, i32* @x, align 4 -; CHECK-NEXT: ret i8* [[P]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@test2 +; IS__TUNIT____-SAME: (i8* nofree readnone returned "no-capture-maybe-returned" [[P:%.*]]) +; IS__TUNIT____-NEXT: store i32 0, i32* @x, align 4 +; IS__TUNIT____-NEXT: ret i8* [[P]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@test2 +; IS__CGSCC____-SAME: (i8* nofree readnone returned "no-capture-maybe-returned" [[P:%.*]]) +; IS__CGSCC____-NEXT: store i32 0, i32* @x, align 4 +; IS__CGSCC____-NEXT: ret i8* [[P]] ; store i32 0, i32* @x ret i8* %p } define i1 @test3(i8* %p, i8* %q) { -; CHECK-LABEL: define {{[^@]+}}@test3 -; CHECK-SAME: (i8* nofree readnone [[P:%.*]], i8* nofree readnone [[Q:%.*]]) -; CHECK-NEXT: [[A:%.*]] = icmp ult i8* [[P]], [[Q]] -; CHECK-NEXT: ret i1 [[A]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test3 +; IS__TUNIT____-SAME: (i8* nofree readnone [[P:%.*]], i8* nofree readnone [[Q:%.*]]) +; IS__TUNIT____-NEXT: [[A:%.*]] = icmp ult i8* [[P]], [[Q]] +; IS__TUNIT____-NEXT: ret i1 [[A]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test3 +; IS__CGSCC____-SAME: (i8* nofree readnone [[P:%.*]], i8* nofree readnone [[Q:%.*]]) +; IS__CGSCC____-NEXT: [[A:%.*]] = icmp ult i8* [[P]], [[Q]] +; IS__CGSCC____-NEXT: ret i1 [[A]] ; %A = icmp ult i8* %p, %q ret i1 %A @@ -46,6 +60,7 @@ declare void @test4_1(i8* nocapture) readonly define void @test4_2(i8* %p) { +; CHECK: Function Attrs: readonly ; CHECK-LABEL: define {{[^@]+}}@test4_2 ; CHECK-SAME: (i8* nocapture readonly [[P:%.*]]) ; CHECK-NEXT: call void @test4_1(i8* nocapture readonly [[P]]) @@ -57,10 +72,17 @@ ; Missed optz'n: we could make %q readnone, but don't break test6! define void @test5(i8** %p, i8* %q) { -; CHECK-LABEL: define {{[^@]+}}@test5 -; CHECK-SAME: (i8** nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[P:%.*]], i8* nofree writeonly [[Q:%.*]]) -; CHECK-NEXT: store i8* [[Q]], i8** [[P]], align 8 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@test5 +; IS__TUNIT____-SAME: (i8** nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[P:%.*]], i8* nofree writeonly [[Q:%.*]]) +; IS__TUNIT____-NEXT: store i8* [[Q]], i8** [[P]], align 8 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@test5 +; IS__CGSCC____-SAME: (i8** nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[P:%.*]], i8* nofree writeonly [[Q:%.*]]) +; IS__CGSCC____-NEXT: store i8* [[Q]], i8** [[P]], align 8 +; IS__CGSCC____-NEXT: ret void ; store i8* %q, i8** %p ret void @@ -82,24 +104,38 @@ ; inalloca parameters are always considered written define void @test7_1(i32* inalloca %a) { -; CHECK-LABEL: define {{[^@]+}}@test7_1 -; CHECK-SAME: (i32* inalloca nocapture nofree writeonly [[A:%.*]]) -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test7_1 +; IS__TUNIT____-SAME: (i32* inalloca nocapture nofree writeonly [[A:%.*]]) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test7_1 +; IS__CGSCC____-SAME: (i32* inalloca nocapture nofree writeonly [[A:%.*]]) +; IS__CGSCC____-NEXT: ret void ; ret void } define i32* @test8_1(i32* %p) { -; CHECK-LABEL: define {{[^@]+}}@test8_1 -; CHECK-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[P:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: ret i32* [[P]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test8_1 +; IS__TUNIT____-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[P:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret i32* [[P]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test8_1 +; IS__CGSCC____-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[P:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i32* [[P]] ; entry: ret i32* %p } define void @test8_2(i32* %p) { +; IS__TUNIT____: Function Attrs: nofree nosync nounwind willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@test8_2 ; IS__TUNIT____-SAME: (i32* nocapture nofree writeonly [[P:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -107,6 +143,7 @@ ; IS__TUNIT____-NEXT: store i32 10, i32* [[CALL]], align 4 ; IS__TUNIT____-NEXT: ret void ; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@test8_2 ; IS__CGSCC____-SAME: (i32* nofree writeonly [[P:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -126,6 +163,7 @@ ; CHECK-NOT: readnone ; CHECK-NOT: readonly define void @test9(<4 x i32*> %ptrs, <4 x i32>%val) { +; CHECK: Function Attrs: nounwind willreturn ; CHECK-LABEL: define {{[^@]+}}@test9 ; CHECK-SAME: (<4 x i32*> [[PTRS:%.*]], <4 x i32> [[VAL:%.*]]) ; CHECK-NEXT: call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32> [[VAL]], <4 x i32*> [[PTRS]], i32 4, <4 x i1> ) @@ -137,8 +175,8 @@ ; 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>) -; CHECK: readonly define <4 x i32> @test10(<4 x i32*> %ptrs) { +; CHECK: Function Attrs: nounwind readonly willreturn ; CHECK-LABEL: define {{[^@]+}}@test10 ; CHECK-SAME: (<4 x i32*> [[PTRS:%.*]]) ; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[PTRS]], i32 4, <4 x i1> , <4 x i32> undef) @@ -150,9 +188,8 @@ ; CHECK: declare <4 x i32> @test11_1 declare <4 x i32> @test11_1(<4 x i32*>) argmemonly nounwind readonly -; CHECK: readonly -; CHECK-NOT: readnone define <4 x i32> @test11_2(<4 x i32*> %ptrs) { +; CHECK: Function Attrs: argmemonly nounwind readonly ; CHECK-LABEL: define {{[^@]+}}@test11_2 ; CHECK-SAME: (<4 x i32*> [[PTRS:%.*]]) ; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @test11_1(<4 x i32*> [[PTRS]]) @@ -165,6 +202,7 @@ declare <4 x i32> @test12_1(<4 x i32*>) argmemonly nounwind ; CHECK-NOT: readnone define <4 x i32> @test12_2(<4 x i32*> %ptrs) { +; CHECK: Function Attrs: argmemonly nounwind ; CHECK-LABEL: define {{[^@]+}}@test12_2 ; CHECK-SAME: (<4 x i32*> [[PTRS:%.*]]) ; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @test12_1(<4 x i32*> [[PTRS]]) @@ -175,10 +213,17 @@ } define i32 @volatile_load(i32* %p) { -; CHECK-LABEL: define {{[^@]+}}@volatile_load -; CHECK-SAME: (i32* nofree align 4 [[P:%.*]]) -; CHECK-NEXT: [[LOAD:%.*]] = load volatile i32, i32* [[P]], align 4 -; CHECK-NEXT: ret i32 [[LOAD]] +; IS__TUNIT____: Function Attrs: argmemonly nofree nounwind willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@volatile_load +; IS__TUNIT____-SAME: (i32* nofree align 4 [[P:%.*]]) +; IS__TUNIT____-NEXT: [[LOAD:%.*]] = load volatile i32, i32* [[P]], align 4 +; IS__TUNIT____-NEXT: ret i32 [[LOAD]] +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nounwind willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@volatile_load +; IS__CGSCC____-SAME: (i32* nofree align 4 [[P:%.*]]) +; IS__CGSCC____-NEXT: [[LOAD:%.*]] = load volatile i32, i32* [[P]], align 4 +; IS__CGSCC____-NEXT: ret i32 [[LOAD]] ; %load = load volatile i32, i32* %p ret i32 %load @@ -230,6 +275,7 @@ declare void @escape_i8(i8* %ptr) define void @byval_not_readonly_1(i8* byval %written) readonly { +; CHECK: Function Attrs: readonly ; CHECK-LABEL: define {{[^@]+}}@byval_not_readonly_1 ; CHECK-SAME: (i8* noalias nonnull byval dereferenceable(1) [[WRITTEN:%.*]]) ; CHECK-NEXT: call void @escape_i8(i8* nonnull dereferenceable(1) [[WRITTEN]]) @@ -240,16 +286,24 @@ } define void @byval_not_readonly_2(i8* byval %written) readonly { -; CHECK-LABEL: define {{[^@]+}}@byval_not_readonly_2 -; CHECK-SAME: (i8* noalias nocapture nofree nonnull writeonly byval dereferenceable(1) [[WRITTEN:%.*]]) -; CHECK-NEXT: store i8 0, i8* [[WRITTEN]], align 1 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@byval_not_readonly_2 +; IS__TUNIT____-SAME: (i8* noalias nocapture nofree nonnull writeonly byval dereferenceable(1) [[WRITTEN:%.*]]) +; IS__TUNIT____-NEXT: store i8 0, i8* [[WRITTEN]], align 1 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@byval_not_readonly_2 +; IS__CGSCC____-SAME: (i8* noalias nocapture nofree nonnull writeonly byval dereferenceable(1) [[WRITTEN:%.*]]) +; IS__CGSCC____-NEXT: store i8 0, i8* [[WRITTEN]], align 1 +; IS__CGSCC____-NEXT: ret void ; store i8 0, i8* %written ret void } define void @byval_not_readnone_1(i8* byval %written) readnone { +; CHECK: Function Attrs: readnone ; CHECK-LABEL: define {{[^@]+}}@byval_not_readnone_1 ; CHECK-SAME: (i8* noalias nonnull byval dereferenceable(1) [[WRITTEN:%.*]]) ; CHECK-NEXT: call void @escape_i8(i8* nonnull dereferenceable(1) [[WRITTEN]]) @@ -260,20 +314,34 @@ } define void @byval_not_readnone_2(i8* byval %written) readnone { -; CHECK-LABEL: define {{[^@]+}}@byval_not_readnone_2 -; CHECK-SAME: (i8* noalias nocapture nofree nonnull writeonly byval dereferenceable(1) [[WRITTEN:%.*]]) -; CHECK-NEXT: store i8 0, i8* [[WRITTEN]], align 1 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@byval_not_readnone_2 +; IS__TUNIT____-SAME: (i8* noalias nocapture nofree nonnull writeonly byval dereferenceable(1) [[WRITTEN:%.*]]) +; IS__TUNIT____-NEXT: store i8 0, i8* [[WRITTEN]], align 1 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@byval_not_readnone_2 +; IS__CGSCC____-SAME: (i8* noalias nocapture nofree nonnull writeonly byval dereferenceable(1) [[WRITTEN:%.*]]) +; IS__CGSCC____-NEXT: store i8 0, i8* [[WRITTEN]], align 1 +; IS__CGSCC____-NEXT: ret void ; store i8 0, i8* %written ret void } define void @byval_no_fnarg(i8* byval %written) { -; CHECK-LABEL: define {{[^@]+}}@byval_no_fnarg -; CHECK-SAME: (i8* noalias nocapture nofree nonnull writeonly byval dereferenceable(1) [[WRITTEN:%.*]]) -; CHECK-NEXT: store i8 0, i8* [[WRITTEN]], align 1 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@byval_no_fnarg +; IS__TUNIT____-SAME: (i8* noalias nocapture nofree nonnull writeonly byval dereferenceable(1) [[WRITTEN:%.*]]) +; IS__TUNIT____-NEXT: store i8 0, i8* [[WRITTEN]], align 1 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@byval_no_fnarg +; IS__CGSCC____-SAME: (i8* noalias nocapture nofree nonnull writeonly byval dereferenceable(1) [[WRITTEN:%.*]]) +; IS__CGSCC____-NEXT: store i8 0, i8* [[WRITTEN]], align 1 +; IS__CGSCC____-NEXT: ret void ; store i8 0, i8* %written ret void @@ -286,6 +354,7 @@ ; 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:%.*]]) ; IS__CGSCC____-NEXT: call void @byval_not_readonly_1(i8* noalias nocapture nonnull readonly dereferenceable(1) [[READ_ONLY]]) @@ -306,6 +375,7 @@ 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:%.*]]) ; CHECK-NEXT: ret void diff --git a/llvm/test/Transforms/Attributor/reduced/register_benchmark_test.ll b/llvm/test/Transforms/Attributor/reduced/register_benchmark_test.ll --- a/llvm/test/Transforms/Attributor/reduced/register_benchmark_test.ll +++ b/llvm/test/Transforms/Attributor/reduced/register_benchmark_test.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s ; RUN: opt -attributor-cgscc -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s ; RUN: opt -passes=attributor -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=1 -S < %s diff --git a/llvm/test/Transforms/Attributor/returned.ll b/llvm/test/Transforms/Attributor/returned.ll --- a/llvm/test/Transforms/Attributor/returned.ll +++ b/llvm/test/Transforms/Attributor/returned.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=14 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=14 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -38,16 +38,24 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" define i32 @sink_r0(i32 %r) #0 { -; CHECK-LABEL: define {{[^@]+}}@sink_r0 -; CHECK-SAME: (i32 returned [[R:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: ret i32 [[R]] +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@sink_r0 +; IS__TUNIT____-SAME: (i32 returned [[R:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret i32 [[R]] +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@sink_r0 +; IS__CGSCC____-SAME: (i32 returned [[R:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i32 [[R]] ; entry: ret i32 %r } define i32 @scc_r1(i32 %a, i32 %r, i32 %b) #0 { +; CHECK: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; CHECK-LABEL: define {{[^@]+}}@scc_r1 ; CHECK-SAME: (i32 [[A:%.*]], i32 returned [[R:%.*]], i32 [[B:%.*]]) ; CHECK-NEXT: entry: @@ -62,6 +70,7 @@ } define i32 @scc_r2(i32 %a, i32 %b, i32 %r) #0 { +; CHECK: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; CHECK-LABEL: define {{[^@]+}}@scc_r2 ; CHECK-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 returned [[R:%.*]]) ; CHECK-NEXT: entry: @@ -143,6 +152,7 @@ } define i32 @scc_rX(i32 %a, i32 %b, i32 %r) #0 { +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__TUNIT____-LABEL: define {{[^@]+}}@scc_rX ; IS__TUNIT____-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[R:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -179,6 +189,7 @@ ; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi i32 [ [[CALL1]], [[IF_THEN]] ], [ [[CALL11]], [[IF_THEN3]] ], [ [[COND]], [[COND_END]] ] ; IS__TUNIT____-NEXT: ret i32 [[RETVAL_0]] ; +; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__CGSCC____-LABEL: define {{[^@]+}}@scc_rX ; IS__CGSCC____-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[R:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -282,16 +293,24 @@ ; return a == b ? r : ptr_scc_r2(a, b, r); ; } define double* @ptr_sink_r0(double* %r) #0 { -; CHECK-LABEL: define {{[^@]+}}@ptr_sink_r0 -; CHECK-SAME: (double* nofree readnone returned "no-capture-maybe-returned" [[R:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: ret double* [[R]] +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@ptr_sink_r0 +; IS__TUNIT____-SAME: (double* nofree readnone returned "no-capture-maybe-returned" [[R:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret double* [[R]] +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@ptr_sink_r0 +; IS__CGSCC____-SAME: (double* nofree readnone returned "no-capture-maybe-returned" [[R:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret double* [[R]] ; entry: ret double* %r } define double* @ptr_scc_r1(double* %a, double* %r, double* %b) #0 { +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__TUNIT____-LABEL: define {{[^@]+}}@ptr_scc_r1 ; IS__TUNIT____-SAME: (double* nofree readnone [[A:%.*]], double* nofree readnone returned [[R:%.*]], double* nocapture nofree readnone [[B:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -299,6 +318,7 @@ ; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call double* @ptr_scc_r2(double* noalias nofree readnone [[R]], double* noalias nofree readnone [[A]], double* noalias nofree readnone [[CALL]]) ; IS__TUNIT____-NEXT: ret double* [[CALL1]] ; +; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__CGSCC____-LABEL: define {{[^@]+}}@ptr_scc_r1 ; IS__CGSCC____-SAME: (double* nofree readnone [[A:%.*]], double* nofree readnone returned [[R:%.*]], double* nocapture nofree readnone [[B:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -313,6 +333,7 @@ } define double* @ptr_scc_r2(double* %a, double* %b, double* %r) #0 { +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__TUNIT____-LABEL: define {{[^@]+}}@ptr_scc_r2 ; IS__TUNIT____-SAME: (double* nofree readnone [[A:%.*]], double* nofree readnone [[B:%.*]], double* nofree readnone returned [[R:%.*]]) ; IS__TUNIT____-NEXT: entry: @@ -349,6 +370,7 @@ ; IS__TUNIT____-NEXT: [[RETVAL_0:%.*]] = phi double* [ [[CALL1]], [[IF_THEN]] ], [ [[CALL11]], [[IF_THEN3]] ], [ [[COND]], [[COND_END]] ] ; IS__TUNIT____-NEXT: ret double* [[RETVAL_0]] ; +; IS__CGSCC____: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; IS__CGSCC____-LABEL: define {{[^@]+}}@ptr_scc_r2 ; IS__CGSCC____-SAME: (double* nofree readnone [[A:%.*]], double* nofree readnone [[B:%.*]], double* nofree readnone returned [[R:%.*]]) ; IS__CGSCC____-NEXT: entry: @@ -437,10 +459,17 @@ ; } ; define i32* @rt0(i32* %a) #0 { -; CHECK-LABEL: define {{[^@]+}}@rt0 -; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[A:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@rt0 +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[A:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@rt0 +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[A:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: unreachable ; entry: %v = load i32, i32* %a, align 4 @@ -457,10 +486,17 @@ ; } ; define i32* @rt1(i32* %a) #0 { -; CHECK-LABEL: define {{[^@]+}}@rt1 -; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[A:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@rt1 +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[A:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@rt1 +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[A:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: unreachable ; entry: %v = load i32, i32* %a, align 4 @@ -473,6 +509,7 @@ ; TEST another SCC test ; define i32* @rt2_helper(i32* %a) #0 { +; CHECK: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; CHECK-LABEL: define {{[^@]+}}@rt2_helper ; CHECK-SAME: (i32* nofree readnone returned [[A:%.*]]) ; CHECK-NEXT: entry: @@ -485,6 +522,7 @@ } define i32* @rt2(i32* %a, i32 *%b) #0 { +; CHECK: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; CHECK-LABEL: define {{[^@]+}}@rt2 ; CHECK-SAME: (i32* nofree readnone [[A:%.*]], i32* nofree readnone "no-capture-maybe-returned" [[B:%.*]]) ; CHECK-NEXT: entry: @@ -513,6 +551,7 @@ ; TEST another SCC test ; define i32* @rt3_helper(i32* %a, i32* %b) #0 { +; CHECK: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; CHECK-LABEL: define {{[^@]+}}@rt3_helper ; CHECK-SAME: (i32* nofree readnone [[A:%.*]], i32* nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) ; CHECK-NEXT: entry: @@ -525,6 +564,7 @@ } define i32* @rt3(i32* %a, i32 *%b) #0 { +; CHECK: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; CHECK-LABEL: define {{[^@]+}}@rt3 ; CHECK-SAME: (i32* nofree readnone [[A:%.*]], i32* nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) ; CHECK-NEXT: entry: @@ -562,6 +602,7 @@ declare void @unknown_fn(i32* (i32*)*) #0 define i32* @calls_unknown_fn(i32* %r) #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@calls_unknown_fn ; CHECK-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[R:%.*]]) ; CHECK-NEXT: tail call void @unknown_fn(i32* (i32*)* nonnull @calls_unknown_fn) @@ -586,6 +627,7 @@ ; Verify the maybe-redefined function is not annotated: ; define linkonce_odr i32* @maybe_redefined_fn(i32* %r) #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@maybe_redefined_fn ; CHECK-SAME: (i32* [[R:%.*]]) ; CHECK-NEXT: entry: @@ -596,6 +638,7 @@ } define i32* @calls_maybe_redefined_fn(i32* %r) #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@calls_maybe_redefined_fn ; CHECK-SAME: (i32* returned [[R:%.*]]) ; CHECK-NEXT: entry: @@ -620,6 +663,7 @@ ; Verify the maybe-redefined function is not annotated: ; define linkonce_odr i32* @maybe_redefined_fn2(i32* %r) #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@maybe_redefined_fn2 ; CHECK-SAME: (i32* [[R:%.*]]) ; CHECK-NEXT: entry: @@ -630,6 +674,7 @@ } define i32* @calls_maybe_redefined_fn2(i32* %r) #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@calls_maybe_redefined_fn2 ; CHECK-SAME: (i32* [[R:%.*]]) ; CHECK-NEXT: entry: @@ -652,18 +697,33 @@ ; } ; define double @select_and_phi(double %b) #0 { -; CHECK-LABEL: define {{[^@]+}}@select_and_phi -; CHECK-SAME: (double returned [[B:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[B]], 0.000000e+00 -; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] -; CHECK: if.then: -; CHECK-NEXT: br label [[IF_END]] -; CHECK: if.end: -; CHECK-NEXT: [[PHI:%.*]] = phi double [ [[B]], [[IF_THEN]] ], [ [[B]], [[ENTRY:%.*]] ] -; CHECK-NEXT: [[CMP1:%.*]] = fcmp oeq double [[B]], 0.000000e+00 -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], double [[B]], double [[PHI]] -; CHECK-NEXT: ret double [[SEL]] +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@select_and_phi +; IS__TUNIT____-SAME: (double returned [[B:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[CMP:%.*]] = fcmp ogt double [[B]], 0.000000e+00 +; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] +; IS__TUNIT____: if.then: +; IS__TUNIT____-NEXT: br label [[IF_END]] +; IS__TUNIT____: if.end: +; IS__TUNIT____-NEXT: [[PHI:%.*]] = phi double [ [[B]], [[IF_THEN]] ], [ [[B]], [[ENTRY:%.*]] ] +; IS__TUNIT____-NEXT: [[CMP1:%.*]] = fcmp oeq double [[B]], 0.000000e+00 +; IS__TUNIT____-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], double [[B]], double [[PHI]] +; IS__TUNIT____-NEXT: ret double [[SEL]] +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@select_and_phi +; IS__CGSCC____-SAME: (double returned [[B:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[CMP:%.*]] = fcmp ogt double [[B]], 0.000000e+00 +; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] +; IS__CGSCC____: if.then: +; IS__CGSCC____-NEXT: br label [[IF_END]] +; IS__CGSCC____: if.end: +; IS__CGSCC____-NEXT: [[PHI:%.*]] = phi double [ [[B]], [[IF_THEN]] ], [ [[B]], [[ENTRY:%.*]] ] +; IS__CGSCC____-NEXT: [[CMP1:%.*]] = fcmp oeq double [[B]], 0.000000e+00 +; IS__CGSCC____-NEXT: [[SEL:%.*]] = select i1 [[CMP1]], double [[B]], double [[PHI]] +; IS__CGSCC____-NEXT: ret double [[SEL]] ; entry: %cmp = fcmp ogt double %b, 0.000000e+00 @@ -690,6 +750,7 @@ ; } ; define double @recursion_select_and_phi(i32 %a, double %b) #0 { +; CHECK: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; CHECK-LABEL: define {{[^@]+}}@recursion_select_and_phi ; CHECK-SAME: (i32 [[A:%.*]], double returned [[B:%.*]]) ; CHECK-NEXT: entry: @@ -729,11 +790,19 @@ ; } ; define double* @bitcast(i32* %b) #0 { -; CHECK-LABEL: define {{[^@]+}}@bitcast -; CHECK-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[BC0:%.*]] = bitcast i32* [[B]] to double* -; CHECK-NEXT: ret double* [[BC0]] +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@bitcast +; IS__TUNIT____-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[BC0:%.*]] = bitcast i32* [[B]] to double* +; IS__TUNIT____-NEXT: ret double* [[BC0]] +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@bitcast +; IS__CGSCC____-SAME: (i32* nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[BC0:%.*]] = bitcast i32* [[B]] to double* +; IS__CGSCC____-NEXT: ret double* [[BC0]] ; entry: %bc0 = bitcast i32* %b to double* @@ -751,23 +820,43 @@ ; } ; define double* @bitcasts_select_and_phi(i32* %b) #0 { -; CHECK-LABEL: define {{[^@]+}}@bitcasts_select_and_phi -; CHECK-SAME: (i32* nofree readnone returned [[B:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[BC0:%.*]] = bitcast i32* [[B]] to double* -; CHECK-NEXT: [[CMP:%.*]] = icmp eq double* [[BC0]], null -; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] -; CHECK: if.then: -; CHECK-NEXT: [[BC1:%.*]] = bitcast i32* [[B]] to double* -; CHECK-NEXT: br label [[IF_END]] -; CHECK: if.end: -; CHECK-NEXT: [[PHI:%.*]] = phi double* [ [[BC1]], [[IF_THEN]] ], [ [[BC0]], [[ENTRY:%.*]] ] -; CHECK-NEXT: [[BC2:%.*]] = bitcast double* [[PHI]] to i8* -; CHECK-NEXT: [[BC3:%.*]] = bitcast i32* [[B]] to i8* -; CHECK-NEXT: [[CMP2:%.*]] = icmp ne double* [[BC0]], null -; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP2]], i8* [[BC2]], i8* [[BC3]] -; CHECK-NEXT: [[BC4:%.*]] = bitcast i8* [[SEL]] to double* -; CHECK-NEXT: ret double* [[BC4]] +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@bitcasts_select_and_phi +; IS__TUNIT____-SAME: (i32* nofree readnone returned [[B:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[BC0:%.*]] = bitcast i32* [[B]] to double* +; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp eq double* [[BC0]], null +; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] +; IS__TUNIT____: if.then: +; IS__TUNIT____-NEXT: [[BC1:%.*]] = bitcast i32* [[B]] to double* +; IS__TUNIT____-NEXT: br label [[IF_END]] +; IS__TUNIT____: if.end: +; IS__TUNIT____-NEXT: [[PHI:%.*]] = phi double* [ [[BC1]], [[IF_THEN]] ], [ [[BC0]], [[ENTRY:%.*]] ] +; IS__TUNIT____-NEXT: [[BC2:%.*]] = bitcast double* [[PHI]] to i8* +; IS__TUNIT____-NEXT: [[BC3:%.*]] = bitcast i32* [[B]] to i8* +; IS__TUNIT____-NEXT: [[CMP2:%.*]] = icmp ne double* [[BC0]], null +; IS__TUNIT____-NEXT: [[SEL:%.*]] = select i1 [[CMP2]], i8* [[BC2]], i8* [[BC3]] +; IS__TUNIT____-NEXT: [[BC4:%.*]] = bitcast i8* [[SEL]] to double* +; IS__TUNIT____-NEXT: ret double* [[BC4]] +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@bitcasts_select_and_phi +; IS__CGSCC____-SAME: (i32* nofree readnone returned [[B:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[BC0:%.*]] = bitcast i32* [[B]] to double* +; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq double* [[BC0]], null +; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] +; IS__CGSCC____: if.then: +; IS__CGSCC____-NEXT: [[BC1:%.*]] = bitcast i32* [[B]] to double* +; IS__CGSCC____-NEXT: br label [[IF_END]] +; IS__CGSCC____: if.end: +; IS__CGSCC____-NEXT: [[PHI:%.*]] = phi double* [ [[BC1]], [[IF_THEN]] ], [ [[BC0]], [[ENTRY:%.*]] ] +; IS__CGSCC____-NEXT: [[BC2:%.*]] = bitcast double* [[PHI]] to i8* +; IS__CGSCC____-NEXT: [[BC3:%.*]] = bitcast i32* [[B]] to i8* +; IS__CGSCC____-NEXT: [[CMP2:%.*]] = icmp ne double* [[BC0]], null +; IS__CGSCC____-NEXT: [[SEL:%.*]] = select i1 [[CMP2]], i8* [[BC2]], i8* [[BC3]] +; IS__CGSCC____-NEXT: [[BC4:%.*]] = bitcast i8* [[SEL]] to double* +; IS__CGSCC____-NEXT: ret double* [[BC4]] ; entry: %bc0 = bitcast i32* %b to double* @@ -800,21 +889,39 @@ ; } ; define double* @ret_arg_arg_undef(i32* %b) #0 { -; CHECK-LABEL: define {{[^@]+}}@ret_arg_arg_undef -; CHECK-SAME: (i32* nofree readnone returned [[B:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[BC0:%.*]] = bitcast i32* [[B]] to double* -; CHECK-NEXT: [[CMP:%.*]] = icmp eq double* [[BC0]], null -; CHECK-NEXT: br i1 [[CMP]], label [[RET_ARG0:%.*]], label [[IF_END:%.*]] -; CHECK: ret_arg0: -; CHECK-NEXT: [[BC1:%.*]] = bitcast i32* [[B]] to double* -; CHECK-NEXT: ret double* [[BC1]] -; CHECK: if.end: -; CHECK-NEXT: br i1 [[CMP]], label [[RET_ARG1:%.*]], label [[RET_UNDEF:%.*]] -; CHECK: ret_arg1: -; CHECK-NEXT: ret double* [[BC0]] -; CHECK: ret_undef: -; CHECK-NEXT: ret double* undef +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@ret_arg_arg_undef +; IS__TUNIT____-SAME: (i32* nofree readnone returned [[B:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[BC0:%.*]] = bitcast i32* [[B]] to double* +; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp eq double* [[BC0]], null +; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[RET_ARG0:%.*]], label [[IF_END:%.*]] +; IS__TUNIT____: ret_arg0: +; IS__TUNIT____-NEXT: [[BC1:%.*]] = bitcast i32* [[B]] to double* +; IS__TUNIT____-NEXT: ret double* [[BC1]] +; IS__TUNIT____: if.end: +; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[RET_ARG1:%.*]], label [[RET_UNDEF:%.*]] +; IS__TUNIT____: ret_arg1: +; IS__TUNIT____-NEXT: ret double* [[BC0]] +; IS__TUNIT____: ret_undef: +; IS__TUNIT____-NEXT: ret double* undef +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@ret_arg_arg_undef +; IS__CGSCC____-SAME: (i32* nofree readnone returned [[B:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[BC0:%.*]] = bitcast i32* [[B]] to double* +; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq double* [[BC0]], null +; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[RET_ARG0:%.*]], label [[IF_END:%.*]] +; IS__CGSCC____: ret_arg0: +; IS__CGSCC____-NEXT: [[BC1:%.*]] = bitcast i32* [[B]] to double* +; IS__CGSCC____-NEXT: ret double* [[BC1]] +; IS__CGSCC____: if.end: +; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[RET_ARG1:%.*]], label [[RET_UNDEF:%.*]] +; IS__CGSCC____: ret_arg1: +; IS__CGSCC____-NEXT: ret double* [[BC0]] +; IS__CGSCC____: ret_undef: +; IS__CGSCC____-NEXT: ret double* undef ; entry: %bc0 = bitcast i32* %b to double* @@ -847,21 +954,39 @@ ; } ; define double* @ret_undef_arg_arg(i32* %b) #0 { -; CHECK-LABEL: define {{[^@]+}}@ret_undef_arg_arg -; CHECK-SAME: (i32* nofree readnone returned [[B:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[BC0:%.*]] = bitcast i32* [[B]] to double* -; CHECK-NEXT: [[CMP:%.*]] = icmp eq double* [[BC0]], null -; CHECK-NEXT: br i1 [[CMP]], label [[RET_UNDEF:%.*]], label [[IF_END:%.*]] -; CHECK: ret_undef: -; CHECK-NEXT: ret double* undef -; CHECK: if.end: -; CHECK-NEXT: br i1 [[CMP]], label [[RET_ARG0:%.*]], label [[RET_ARG1:%.*]] -; CHECK: ret_arg0: -; CHECK-NEXT: ret double* [[BC0]] -; CHECK: ret_arg1: -; CHECK-NEXT: [[BC1:%.*]] = bitcast i32* [[B]] to double* -; CHECK-NEXT: ret double* [[BC1]] +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@ret_undef_arg_arg +; IS__TUNIT____-SAME: (i32* nofree readnone returned [[B:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[BC0:%.*]] = bitcast i32* [[B]] to double* +; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp eq double* [[BC0]], null +; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[RET_UNDEF:%.*]], label [[IF_END:%.*]] +; IS__TUNIT____: ret_undef: +; IS__TUNIT____-NEXT: ret double* undef +; IS__TUNIT____: if.end: +; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[RET_ARG0:%.*]], label [[RET_ARG1:%.*]] +; IS__TUNIT____: ret_arg0: +; IS__TUNIT____-NEXT: ret double* [[BC0]] +; IS__TUNIT____: ret_arg1: +; IS__TUNIT____-NEXT: [[BC1:%.*]] = bitcast i32* [[B]] to double* +; IS__TUNIT____-NEXT: ret double* [[BC1]] +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@ret_undef_arg_arg +; IS__CGSCC____-SAME: (i32* nofree readnone returned [[B:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[BC0:%.*]] = bitcast i32* [[B]] to double* +; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq double* [[BC0]], null +; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[RET_UNDEF:%.*]], label [[IF_END:%.*]] +; IS__CGSCC____: ret_undef: +; IS__CGSCC____-NEXT: ret double* undef +; IS__CGSCC____: if.end: +; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[RET_ARG0:%.*]], label [[RET_ARG1:%.*]] +; IS__CGSCC____: ret_arg0: +; IS__CGSCC____-NEXT: ret double* [[BC0]] +; IS__CGSCC____: ret_arg1: +; IS__CGSCC____-NEXT: [[BC1:%.*]] = bitcast i32* [[B]] to double* +; IS__CGSCC____-NEXT: ret double* [[BC1]] ; entry: %bc0 = bitcast i32* %b to double* @@ -894,20 +1019,37 @@ ; } ; define double* @ret_undef_arg_undef(i32* %b) #0 { -; CHECK-LABEL: define {{[^@]+}}@ret_undef_arg_undef -; CHECK-SAME: (i32* nofree readnone returned [[B:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[BC0:%.*]] = bitcast i32* [[B]] to double* -; CHECK-NEXT: [[CMP:%.*]] = icmp eq double* [[BC0]], null -; CHECK-NEXT: br i1 [[CMP]], label [[RET_UNDEF0:%.*]], label [[IF_END:%.*]] -; CHECK: ret_undef0: -; CHECK-NEXT: ret double* undef -; CHECK: if.end: -; CHECK-NEXT: br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNDEF1:%.*]] -; CHECK: ret_arg: -; CHECK-NEXT: ret double* [[BC0]] -; CHECK: ret_undef1: -; CHECK-NEXT: ret double* undef +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@ret_undef_arg_undef +; IS__TUNIT____-SAME: (i32* nofree readnone returned [[B:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[BC0:%.*]] = bitcast i32* [[B]] to double* +; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp eq double* [[BC0]], null +; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[RET_UNDEF0:%.*]], label [[IF_END:%.*]] +; IS__TUNIT____: ret_undef0: +; IS__TUNIT____-NEXT: ret double* undef +; IS__TUNIT____: if.end: +; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNDEF1:%.*]] +; IS__TUNIT____: ret_arg: +; IS__TUNIT____-NEXT: ret double* [[BC0]] +; IS__TUNIT____: ret_undef1: +; IS__TUNIT____-NEXT: ret double* undef +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@ret_undef_arg_undef +; IS__CGSCC____-SAME: (i32* nofree readnone returned [[B:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[BC0:%.*]] = bitcast i32* [[B]] to double* +; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq double* [[BC0]], null +; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[RET_UNDEF0:%.*]], label [[IF_END:%.*]] +; IS__CGSCC____: ret_undef0: +; IS__CGSCC____-NEXT: ret double* undef +; IS__CGSCC____: if.end: +; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNDEF1:%.*]] +; IS__CGSCC____: ret_arg: +; IS__CGSCC____-NEXT: ret double* [[BC0]] +; IS__CGSCC____: ret_undef1: +; IS__CGSCC____-NEXT: ret double* undef ; entry: %bc0 = bitcast i32* %b to double* @@ -940,6 +1082,7 @@ declare i32* @unknown(i32*) define i32* @ret_arg_or_unknown(i32* %b) #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@ret_arg_or_unknown ; CHECK-SAME: (i32* [[B:%.*]]) ; CHECK-NEXT: entry: @@ -964,6 +1107,7 @@ } define i32* @ret_arg_or_unknown_through_phi(i32* %b) #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@ret_arg_or_unknown_through_phi ; CHECK-SAME: (i32* [[B:%.*]]) ; CHECK-NEXT: entry: @@ -997,12 +1141,21 @@ ; TEST inconsistent IR in dead code. ; define i32 @deadblockcall1(i32 %A) #0 { -; CHECK-LABEL: define {{[^@]+}}@deadblockcall1 -; CHECK-SAME: (i32 returned [[A:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: ret i32 [[A]] -; CHECK: unreachableblock: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@deadblockcall1 +; IS__TUNIT____-SAME: (i32 returned [[A:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret i32 [[A]] +; IS__TUNIT____: unreachableblock: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@deadblockcall1 +; IS__CGSCC____-SAME: (i32 returned [[A:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i32 [[A]] +; IS__CGSCC____: unreachableblock: +; IS__CGSCC____-NEXT: unreachable ; entry: ret i32 %A @@ -1014,14 +1167,25 @@ declare i32 @deadblockcall_helper(i32 returned %A); define i32 @deadblockcall2(i32 %A) #0 { -; CHECK-LABEL: define {{[^@]+}}@deadblockcall2 -; CHECK-SAME: (i32 returned [[A:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: ret i32 [[A]] -; CHECK: unreachableblock1: -; CHECK-NEXT: unreachable -; CHECK: unreachableblock2: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@deadblockcall2 +; IS__TUNIT____-SAME: (i32 returned [[A:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: ret i32 [[A]] +; IS__TUNIT____: unreachableblock1: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: unreachableblock2: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@deadblockcall2 +; IS__CGSCC____-SAME: (i32 returned [[A:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i32 [[A]] +; IS__CGSCC____: unreachableblock1: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: unreachableblock2: +; IS__CGSCC____-NEXT: unreachable ; entry: ret i32 %A @@ -1034,16 +1198,29 @@ } define i32 @deadblockphi1(i32 %A) #0 { -; CHECK-LABEL: define {{[^@]+}}@deadblockphi1 -; CHECK-SAME: (i32 returned [[A:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[R:%.*]] -; CHECK: unreachableblock1: -; CHECK-NEXT: unreachable -; CHECK: unreachableblock2: -; CHECK-NEXT: unreachable -; CHECK: r: -; CHECK-NEXT: ret i32 [[A]] +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@deadblockphi1 +; IS__TUNIT____-SAME: (i32 returned [[A:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: br label [[R:%.*]] +; IS__TUNIT____: unreachableblock1: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: unreachableblock2: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: r: +; IS__TUNIT____-NEXT: ret i32 [[A]] +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@deadblockphi1 +; IS__CGSCC____-SAME: (i32 returned [[A:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br label [[R:%.*]] +; IS__CGSCC____: unreachableblock1: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: unreachableblock2: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: r: +; IS__CGSCC____-NEXT: ret i32 [[A]] ; entry: br label %r @@ -1059,18 +1236,33 @@ } define i32 @deadblockphi2(i32 %A) #0 { -; CHECK-LABEL: define {{[^@]+}}@deadblockphi2 -; CHECK-SAME: (i32 returned [[A:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[R:%.*]] -; CHECK: unreachableblock1: -; CHECK-NEXT: unreachable -; CHECK: unreachableblock2: -; CHECK-NEXT: unreachable -; CHECK: unreachableblock3: -; CHECK-NEXT: unreachable -; CHECK: r: -; CHECK-NEXT: ret i32 [[A]] +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@deadblockphi2 +; IS__TUNIT____-SAME: (i32 returned [[A:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: br label [[R:%.*]] +; IS__TUNIT____: unreachableblock1: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: unreachableblock2: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: unreachableblock3: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: r: +; IS__TUNIT____-NEXT: ret i32 [[A]] +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@deadblockphi2 +; IS__CGSCC____-SAME: (i32 returned [[A:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br label [[R:%.*]] +; IS__CGSCC____: unreachableblock1: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: unreachableblock2: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: unreachableblock3: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: r: +; IS__CGSCC____-NEXT: ret i32 [[A]] ; entry: br label %r @@ -1091,6 +1283,7 @@ declare void @noreturn() noreturn; define i32 @deadblockphi3(i32 %A, i1 %c) #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@deadblockphi3 ; CHECK-SAME: (i32 returned [[A:%.*]], i1 [[C:%.*]]) ; CHECK-NEXT: entry: @@ -1207,25 +1400,38 @@ @G = external global i8 define i32* @ret_const() #0 { -; CHECK-LABEL: define {{[^@]+}}@ret_const() -; CHECK-NEXT: [[BC:%.*]] = bitcast i8* @G to i32* -; CHECK-NEXT: ret i32* [[BC]] +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@ret_const() +; IS__TUNIT____-NEXT: [[BC:%.*]] = bitcast i8* @G to i32* +; IS__TUNIT____-NEXT: ret i32* [[BC]] +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@ret_const() +; IS__CGSCC____-NEXT: [[BC:%.*]] = bitcast i8* @G to i32* +; IS__CGSCC____-NEXT: ret i32* [[BC]] ; %bc = bitcast i8* @G to i32* ret i32* %bc } define i32* @use_const() #0 { -; CHECK-LABEL: define {{[^@]+}}@use_const() -; CHECK-NEXT: ret i32* bitcast (i8* @G to i32*) +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@use_const() +; IS__TUNIT____-NEXT: ret i32* bitcast (i8* @G to i32*) +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@use_const() +; IS__CGSCC____-NEXT: ret i32* bitcast (i8* @G to i32*) ; %c = call i32* @ret_const() ret i32* %c } define i32* @dont_use_const() #0 { +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@dont_use_const() ; IS__TUNIT____-NEXT: [[C:%.*]] = musttail call i32* @ret_const() ; IS__TUNIT____-NEXT: ret i32* [[C]] ; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@dont_use_const() ; IS__CGSCC____-NEXT: [[C:%.*]] = musttail call nonnull dereferenceable(1) i32* @ret_const() ; IS__CGSCC____-NEXT: ret i32* [[C]] diff --git a/llvm/test/Transforms/Attributor/undefined_behavior.ll b/llvm/test/Transforms/Attributor/undefined_behavior.ll --- a/llvm/test/Transforms/Attributor/undefined_behavior.ll +++ b/llvm/test/Transforms/Attributor/undefined_behavior.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -13,16 +13,26 @@ ; -- Load tests -- define void @load_wholly_unreachable() { -; CHECK-LABEL: define {{[^@]+}}@load_wholly_unreachable() -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@load_wholly_unreachable() +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@load_wholly_unreachable() +; IS__CGSCC____-NEXT: unreachable ; %a = load i32, i32* null ret void } define void @loads_wholly_unreachable() { -; CHECK-LABEL: define {{[^@]+}}@loads_wholly_unreachable() -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@loads_wholly_unreachable() +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@loads_wholly_unreachable() +; IS__CGSCC____-NEXT: unreachable ; %a = load i32, i32* null %b = load i32, i32* null @@ -31,13 +41,23 @@ define void @load_single_bb_unreachable(i1 %cond) { -; CHECK-LABEL: define {{[^@]+}}@load_single_bb_unreachable -; CHECK-SAME: (i1 [[COND:%.*]]) -; CHECK-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]] -; CHECK: t: -; CHECK-NEXT: unreachable -; CHECK: e: -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@load_single_bb_unreachable +; IS__TUNIT____-SAME: (i1 [[COND:%.*]]) +; IS__TUNIT____-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]] +; IS__TUNIT____: t: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: e: +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@load_single_bb_unreachable +; IS__CGSCC____-SAME: (i1 [[COND:%.*]]) +; IS__CGSCC____-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]] +; IS__CGSCC____: t: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: e: +; IS__CGSCC____-NEXT: ret void ; br i1 %cond, label %t, label %e t: @@ -50,14 +70,20 @@ ; Note that while the load is removed (because it's unused), the block ; is not changed to unreachable define void @load_null_pointer_is_defined() null_pointer_is_valid { -; CHECK-LABEL: define {{[^@]+}}@load_null_pointer_is_defined() -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind null_pointer_is_valid readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@load_null_pointer_is_defined() +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@load_null_pointer_is_defined() +; IS__CGSCC____-NEXT: ret void ; %a = load i32, i32* null ret void } define internal i32* @ret_null() { +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@ret_null() ; IS__CGSCC____-NEXT: ret i32* null ; @@ -65,8 +91,13 @@ } define void @load_null_propagated() { -; CHECK-LABEL: define {{[^@]+}}@load_null_propagated() -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@load_null_propagated() +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@load_null_propagated() +; IS__CGSCC____-NEXT: unreachable ; %ptr = call i32* @ret_null() %a = load i32, i32* %ptr @@ -76,21 +107,36 @@ ; -- Store tests -- define void @store_wholly_unreachable() { -; CHECK-LABEL: define {{[^@]+}}@store_wholly_unreachable() -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@store_wholly_unreachable() +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@store_wholly_unreachable() +; IS__CGSCC____-NEXT: unreachable ; store i32 5, i32* null ret void } define void @store_single_bb_unreachable(i1 %cond) { -; CHECK-LABEL: define {{[^@]+}}@store_single_bb_unreachable -; CHECK-SAME: (i1 [[COND:%.*]]) -; CHECK-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]] -; CHECK: t: -; CHECK-NEXT: unreachable -; CHECK: e: -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@store_single_bb_unreachable +; IS__TUNIT____-SAME: (i1 [[COND:%.*]]) +; IS__TUNIT____-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]] +; IS__TUNIT____: t: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: e: +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@store_single_bb_unreachable +; IS__CGSCC____-SAME: (i1 [[COND:%.*]]) +; IS__CGSCC____-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]] +; IS__CGSCC____: t: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: e: +; IS__CGSCC____-NEXT: ret void ; br i1 %cond, label %t, label %e t: @@ -101,9 +147,15 @@ } define void @store_null_pointer_is_defined() null_pointer_is_valid { -; CHECK-LABEL: define {{[^@]+}}@store_null_pointer_is_defined() -; CHECK-NEXT: store i32 5, i32* null, align 536870912 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind null_pointer_is_valid willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@store_null_pointer_is_defined() +; IS__TUNIT____-NEXT: store i32 5, i32* null, align 536870912 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@store_null_pointer_is_defined() +; IS__CGSCC____-NEXT: store i32 5, i32* null, align 536870912 +; IS__CGSCC____-NEXT: ret void ; store i32 5, i32* null ret void @@ -113,8 +165,13 @@ ; ATTRIBUTOR-LABEL: @store_null_propagated( ; ATTRIBUTOR-NEXT: unreachable ; -; CHECK-LABEL: define {{[^@]+}}@store_null_propagated() -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@store_null_propagated() +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@store_null_propagated() +; IS__CGSCC____-NEXT: unreachable ; %ptr = call i32* @ret_null() store i32 5, i32* %ptr @@ -124,21 +181,36 @@ ; -- AtomicRMW tests -- define void @atomicrmw_wholly_unreachable() { -; CHECK-LABEL: define {{[^@]+}}@atomicrmw_wholly_unreachable() -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@atomicrmw_wholly_unreachable() +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@atomicrmw_wholly_unreachable() +; IS__CGSCC____-NEXT: unreachable ; %a = atomicrmw add i32* null, i32 1 acquire ret void } define void @atomicrmw_single_bb_unreachable(i1 %cond) { -; CHECK-LABEL: define {{[^@]+}}@atomicrmw_single_bb_unreachable -; CHECK-SAME: (i1 [[COND:%.*]]) -; CHECK-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]] -; CHECK: t: -; CHECK-NEXT: unreachable -; CHECK: e: -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@atomicrmw_single_bb_unreachable +; IS__TUNIT____-SAME: (i1 [[COND:%.*]]) +; IS__TUNIT____-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]] +; IS__TUNIT____: t: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: e: +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@atomicrmw_single_bb_unreachable +; IS__CGSCC____-SAME: (i1 [[COND:%.*]]) +; IS__CGSCC____-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]] +; IS__CGSCC____: t: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: e: +; IS__CGSCC____-NEXT: ret void ; br i1 %cond, label %t, label %e t: @@ -149,9 +221,15 @@ } define void @atomicrmw_null_pointer_is_defined() null_pointer_is_valid { -; CHECK-LABEL: define {{[^@]+}}@atomicrmw_null_pointer_is_defined() -; CHECK-NEXT: [[A:%.*]] = atomicrmw add i32* null, i32 1 acquire -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nounwind null_pointer_is_valid willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@atomicrmw_null_pointer_is_defined() +; IS__TUNIT____-NEXT: [[A:%.*]] = atomicrmw add i32* null, i32 1 acquire +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nounwind null_pointer_is_valid willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@atomicrmw_null_pointer_is_defined() +; IS__CGSCC____-NEXT: [[A:%.*]] = atomicrmw add i32* null, i32 1 acquire +; IS__CGSCC____-NEXT: ret void ; %a = atomicrmw add i32* null, i32 1 acquire ret void @@ -161,8 +239,13 @@ ; ATTRIBUTOR-LABEL: @atomicrmw_null_propagated( ; ATTRIBUTOR-NEXT: unreachable ; -; CHECK-LABEL: define {{[^@]+}}@atomicrmw_null_propagated() -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@atomicrmw_null_propagated() +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@atomicrmw_null_propagated() +; IS__CGSCC____-NEXT: unreachable ; %ptr = call i32* @ret_null() %a = atomicrmw add i32* %ptr, i32 1 acquire @@ -172,21 +255,36 @@ ; -- AtomicCmpXchg tests -- define void @atomiccmpxchg_wholly_unreachable() { -; CHECK-LABEL: define {{[^@]+}}@atomiccmpxchg_wholly_unreachable() -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@atomiccmpxchg_wholly_unreachable() +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@atomiccmpxchg_wholly_unreachable() +; IS__CGSCC____-NEXT: unreachable ; %a = cmpxchg i32* null, i32 2, i32 3 acq_rel monotonic ret void } define void @atomiccmpxchg_single_bb_unreachable(i1 %cond) { -; CHECK-LABEL: define {{[^@]+}}@atomiccmpxchg_single_bb_unreachable -; CHECK-SAME: (i1 [[COND:%.*]]) -; CHECK-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]] -; CHECK: t: -; CHECK-NEXT: unreachable -; CHECK: e: -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@atomiccmpxchg_single_bb_unreachable +; IS__TUNIT____-SAME: (i1 [[COND:%.*]]) +; IS__TUNIT____-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]] +; IS__TUNIT____: t: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: e: +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@atomiccmpxchg_single_bb_unreachable +; IS__CGSCC____-SAME: (i1 [[COND:%.*]]) +; IS__CGSCC____-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]] +; IS__CGSCC____: t: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: e: +; IS__CGSCC____-NEXT: ret void ; br i1 %cond, label %t, label %e t: @@ -197,9 +295,15 @@ } define void @atomiccmpxchg_null_pointer_is_defined() null_pointer_is_valid { -; CHECK-LABEL: define {{[^@]+}}@atomiccmpxchg_null_pointer_is_defined() -; CHECK-NEXT: [[A:%.*]] = cmpxchg i32* null, i32 2, i32 3 acq_rel monotonic -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nounwind null_pointer_is_valid willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@atomiccmpxchg_null_pointer_is_defined() +; IS__TUNIT____-NEXT: [[A:%.*]] = cmpxchg i32* null, i32 2, i32 3 acq_rel monotonic +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nounwind null_pointer_is_valid willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@atomiccmpxchg_null_pointer_is_defined() +; IS__CGSCC____-NEXT: [[A:%.*]] = cmpxchg i32* null, i32 2, i32 3 acq_rel monotonic +; IS__CGSCC____-NEXT: ret void ; %a = cmpxchg i32* null, i32 2, i32 3 acq_rel monotonic ret void @@ -209,8 +313,13 @@ ; ATTRIBUTOR-LABEL: @atomiccmpxchg_null_propagated( ; ATTRIBUTOR-NEXT: unreachable ; -; CHECK-LABEL: define {{[^@]+}}@atomiccmpxchg_null_propagated() -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@atomiccmpxchg_null_propagated() +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@atomiccmpxchg_null_propagated() +; IS__CGSCC____-NEXT: unreachable ; %ptr = call i32* @ret_null() %a = cmpxchg i32* %ptr, i32 2, i32 3 acq_rel monotonic @@ -222,12 +331,21 @@ ; Note: The unreachable on %t and %e is _not_ from AAUndefinedBehavior define i32 @cond_br_on_undef() { -; CHECK-LABEL: define {{[^@]+}}@cond_br_on_undef() -; CHECK-NEXT: unreachable -; CHECK: t: -; CHECK-NEXT: unreachable -; CHECK: e: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree noreturn nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@cond_br_on_undef() +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: t: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: e: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@cond_br_on_undef() +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: t: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: e: +; IS__CGSCC____-NEXT: unreachable ; br i1 undef, label %t, label %e t: @@ -240,17 +358,31 @@ ; Valid branch - verify that this is not converted ; to unreachable. define void @cond_br_on_undef2(i1 %cond) { -; CHECK-LABEL: define {{[^@]+}}@cond_br_on_undef2 -; CHECK-SAME: (i1 [[COND:%.*]]) -; CHECK-NEXT: br i1 [[COND]], label [[T1:%.*]], label [[E1:%.*]] -; CHECK: t1: -; CHECK-NEXT: unreachable -; CHECK: t2: -; CHECK-NEXT: unreachable -; CHECK: e2: -; CHECK-NEXT: unreachable -; CHECK: e1: -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@cond_br_on_undef2 +; IS__TUNIT____-SAME: (i1 [[COND:%.*]]) +; IS__TUNIT____-NEXT: br i1 [[COND]], label [[T1:%.*]], label [[E1:%.*]] +; IS__TUNIT____: t1: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: t2: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: e2: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: e1: +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@cond_br_on_undef2 +; IS__CGSCC____-SAME: (i1 [[COND:%.*]]) +; IS__CGSCC____-NEXT: br i1 [[COND]], label [[T1:%.*]], label [[E1:%.*]] +; IS__CGSCC____: t1: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: t2: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: e2: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: e1: +; IS__CGSCC____-NEXT: ret void ; br i1 %cond, label %t1, label %e1 t1: @@ -264,19 +396,33 @@ } define i1 @ret_undef() { -; CHECK-LABEL: define {{[^@]+}}@ret_undef() -; CHECK-NEXT: ret i1 undef +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@ret_undef() +; IS__TUNIT____-NEXT: ret i1 undef +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@ret_undef() +; IS__CGSCC____-NEXT: ret i1 undef ; ret i1 undef } define void @cond_br_on_undef_interproc() { -; CHECK-LABEL: define {{[^@]+}}@cond_br_on_undef_interproc() -; CHECK-NEXT: unreachable -; CHECK: t: -; CHECK-NEXT: unreachable -; CHECK: e: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree noreturn nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@cond_br_on_undef_interproc() +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: t: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: e: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@cond_br_on_undef_interproc() +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: t: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: e: +; IS__CGSCC____-NEXT: unreachable ; %cond = call i1 @ret_undef() br i1 %cond, label %t, label %e @@ -287,12 +433,21 @@ } define i1 @ret_undef2() { -; CHECK-LABEL: define {{[^@]+}}@ret_undef2() -; CHECK-NEXT: br i1 true, label [[T:%.*]], label [[E:%.*]] -; CHECK: t: -; CHECK-NEXT: ret i1 undef -; CHECK: e: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@ret_undef2() +; IS__TUNIT____-NEXT: br i1 true, label [[T:%.*]], label [[E:%.*]] +; IS__TUNIT____: t: +; IS__TUNIT____-NEXT: ret i1 undef +; IS__TUNIT____: e: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@ret_undef2() +; IS__CGSCC____-NEXT: br i1 true, label [[T:%.*]], label [[E:%.*]] +; IS__CGSCC____: t: +; IS__CGSCC____-NEXT: ret i1 undef +; IS__CGSCC____: e: +; IS__CGSCC____-NEXT: unreachable ; br i1 true, label %t, label %e t: @@ -303,12 +458,21 @@ ; More complicated interproc deduction of undef define void @cond_br_on_undef_interproc2() { -; CHECK-LABEL: define {{[^@]+}}@cond_br_on_undef_interproc2() -; CHECK-NEXT: unreachable -; CHECK: t: -; CHECK-NEXT: unreachable -; CHECK: e: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree noreturn nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@cond_br_on_undef_interproc2() +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: t: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: e: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse noreturn nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@cond_br_on_undef_interproc2() +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: t: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: e: +; IS__CGSCC____-NEXT: unreachable ; %cond = call i1 @ret_undef2() br i1 %cond, label %t, label %e @@ -321,12 +485,21 @@ ; Branch on undef that depends on propagation of ; undef of a previous instruction. define i32 @cond_br_on_undef3() { -; CHECK-LABEL: define {{[^@]+}}@cond_br_on_undef3() -; CHECK-NEXT: br label [[T:%.*]] -; CHECK: t: -; CHECK-NEXT: ret i32 1 -; CHECK: e: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@cond_br_on_undef3() +; IS__TUNIT____-NEXT: br label [[T:%.*]] +; IS__TUNIT____: t: +; IS__TUNIT____-NEXT: ret i32 1 +; IS__TUNIT____: e: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@cond_br_on_undef3() +; IS__CGSCC____-NEXT: br label [[T:%.*]] +; IS__CGSCC____: t: +; IS__CGSCC____-NEXT: ret i32 1 +; IS__CGSCC____: e: +; IS__CGSCC____-NEXT: unreachable ; %cond = icmp ne i32 1, undef br i1 %cond, label %t, label %e @@ -339,14 +512,25 @@ ; Branch on undef because of uninitialized value. ; FIXME: Currently it doesn't propagate the undef. define i32 @cond_br_on_undef_uninit() { -; CHECK-LABEL: define {{[^@]+}}@cond_br_on_undef_uninit() -; CHECK-NEXT: [[ALLOC:%.*]] = alloca i1, align 1 -; CHECK-NEXT: [[COND:%.*]] = load i1, i1* [[ALLOC]], align 1 -; CHECK-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]] -; CHECK: t: -; CHECK-NEXT: ret i32 1 -; CHECK: e: -; CHECK-NEXT: ret i32 2 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@cond_br_on_undef_uninit() +; IS__TUNIT____-NEXT: [[ALLOC:%.*]] = alloca i1, align 1 +; IS__TUNIT____-NEXT: [[COND:%.*]] = load i1, i1* [[ALLOC]], align 1 +; IS__TUNIT____-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]] +; IS__TUNIT____: t: +; IS__TUNIT____-NEXT: ret i32 1 +; IS__TUNIT____: e: +; IS__TUNIT____-NEXT: ret i32 2 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@cond_br_on_undef_uninit() +; IS__CGSCC____-NEXT: [[ALLOC:%.*]] = alloca i1, align 1 +; IS__CGSCC____-NEXT: [[COND:%.*]] = load i1, i1* [[ALLOC]], align 1 +; IS__CGSCC____-NEXT: br i1 [[COND]], label [[T:%.*]], label [[E:%.*]] +; IS__CGSCC____: t: +; IS__CGSCC____-NEXT: ret i32 1 +; IS__CGSCC____: e: +; IS__CGSCC____-NEXT: ret i32 2 ; %alloc = alloca i1 %cond = load i1, i1* %alloc @@ -363,6 +547,7 @@ ; MODULE-NOT: @callee( define internal i32 @callee(i1 %C, i32* %A) { ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@callee() ; IS__CGSCC____-NEXT: entry: ; IS__CGSCC____-NEXT: unreachable @@ -383,8 +568,13 @@ } define i32 @foo() { -; CHECK-LABEL: define {{[^@]+}}@foo() -; CHECK-NEXT: ret i32 1 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@foo() +; IS__TUNIT____-NEXT: ret i32 1 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@foo() +; IS__CGSCC____-NEXT: ret i32 1 ; %X = call i32 @callee(i1 false, i32* null) ret i32 %X diff --git a/llvm/test/Transforms/Attributor/value-simplify.ll b/llvm/test/Transforms/Attributor/value-simplify.ll --- a/llvm/test/Transforms/Attributor/value-simplify.ll +++ b/llvm/test/Transforms/Attributor/value-simplify.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=4 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -30,31 +30,55 @@ ; TEST 2 : Simplify return value define i32 @return0() { -; CHECK-LABEL: define {{[^@]+}}@return0() -; CHECK-NEXT: ret i32 0 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@return0() +; IS__TUNIT____-NEXT: ret i32 0 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@return0() +; IS__CGSCC____-NEXT: ret i32 0 ; ret i32 0 } define i32 @return1() { -; CHECK-LABEL: define {{[^@]+}}@return1() -; CHECK-NEXT: ret i32 1 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@return1() +; IS__TUNIT____-NEXT: ret i32 1 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@return1() +; IS__CGSCC____-NEXT: ret i32 1 ; ret i32 1 } define i32 @test2_1(i1 %c) { -; CHECK-LABEL: define {{[^@]+}}@test2_1 -; CHECK-SAME: (i1 [[C:%.*]]) -; CHECK-NEXT: br i1 [[C]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] -; CHECK: if.true: -; CHECK-NEXT: [[RET0:%.*]] = add i32 0, 1 -; CHECK-NEXT: br label [[END:%.*]] -; CHECK: if.false: -; CHECK-NEXT: br label [[END]] -; CHECK: end: -; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[RET0]], [[IF_TRUE]] ], [ 1, [[IF_FALSE]] ] -; CHECK-NEXT: ret i32 1 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test2_1 +; IS__TUNIT____-SAME: (i1 [[C:%.*]]) +; IS__TUNIT____-NEXT: br i1 [[C]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] +; IS__TUNIT____: if.true: +; IS__TUNIT____-NEXT: [[RET0:%.*]] = add i32 0, 1 +; IS__TUNIT____-NEXT: br label [[END:%.*]] +; IS__TUNIT____: if.false: +; IS__TUNIT____-NEXT: br label [[END]] +; IS__TUNIT____: end: +; IS__TUNIT____-NEXT: [[RET:%.*]] = phi i32 [ [[RET0]], [[IF_TRUE]] ], [ 1, [[IF_FALSE]] ] +; IS__TUNIT____-NEXT: ret i32 1 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test2_1 +; IS__CGSCC____-SAME: (i1 [[C:%.*]]) +; IS__CGSCC____-NEXT: br i1 [[C]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] +; IS__CGSCC____: if.true: +; IS__CGSCC____-NEXT: [[RET0:%.*]] = add i32 0, 1 +; IS__CGSCC____-NEXT: br label [[END:%.*]] +; IS__CGSCC____: if.false: +; IS__CGSCC____-NEXT: br label [[END]] +; IS__CGSCC____: end: +; IS__CGSCC____-NEXT: [[RET:%.*]] = phi i32 [ [[RET0]], [[IF_TRUE]] ], [ 1, [[IF_FALSE]] ] +; IS__CGSCC____-NEXT: ret i32 1 ; br i1 %c, label %if.true, label %if.false if.true: @@ -74,9 +98,15 @@ define i32 @test2_2(i1 %c) { -; CHECK-LABEL: define {{[^@]+}}@test2_2 -; CHECK-SAME: (i1 [[C:%.*]]) -; CHECK-NEXT: ret i32 1 +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test2_2 +; IS__TUNIT____-SAME: (i1 [[C:%.*]]) +; IS__TUNIT____-NEXT: ret i32 1 +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test2_2 +; IS__CGSCC____-SAME: (i1 [[C:%.*]]) +; IS__CGSCC____-NEXT: ret i32 1 ; %ret = tail call i32 @test2_1(i1 %c) ret i32 %ret @@ -167,13 +197,23 @@ } define i32 @ipccp1(i32 %a) { -; CHECK-LABEL: define {{[^@]+}}@ipccp1 -; CHECK-SAME: (i32 returned [[A:%.*]]) -; CHECK-NEXT: br i1 true, label [[T:%.*]], label [[F:%.*]] -; CHECK: t: -; CHECK-NEXT: ret i32 [[A]] -; CHECK: f: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@ipccp1 +; IS__TUNIT____-SAME: (i32 returned [[A:%.*]]) +; IS__TUNIT____-NEXT: br i1 true, label [[T:%.*]], label [[F:%.*]] +; IS__TUNIT____: t: +; IS__TUNIT____-NEXT: ret i32 [[A]] +; IS__TUNIT____: f: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@ipccp1 +; IS__CGSCC____-SAME: (i32 returned [[A:%.*]]) +; IS__CGSCC____-NEXT: br i1 true, label [[T:%.*]], label [[F:%.*]] +; IS__CGSCC____: t: +; IS__CGSCC____-NEXT: ret i32 [[A]] +; IS__CGSCC____: f: +; IS__CGSCC____-NEXT: unreachable ; br i1 true, label %t, label %f t: @@ -184,6 +224,7 @@ } define internal i1 @ipccp2i(i1 %a) { +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@ipccp2i() ; IS__CGSCC____-NEXT: br label [[T:%.*]] ; IS__CGSCC____: t: @@ -200,9 +241,11 @@ } define i1 @ipccp2() { +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@ipccp2() ; IS__TUNIT____-NEXT: ret i1 true ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@ipccp2() ; IS__CGSCC____-NEXT: [[R:%.*]] = call i1 @ipccp2i() ; IS__CGSCC____-NEXT: ret i1 [[R]] @@ -212,6 +255,7 @@ } define internal i1 @ipccp2ib(i1 %a) { +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@ipccp2ib() ; IS__CGSCC____-NEXT: br label [[T:%.*]] ; IS__CGSCC____: t: @@ -228,14 +272,20 @@ } define i1 @ipccp2b() { -; CHECK-LABEL: define {{[^@]+}}@ipccp2b() -; CHECK-NEXT: ret i1 true +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@ipccp2b() +; IS__TUNIT____-NEXT: ret i1 true +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@ipccp2b() +; IS__CGSCC____-NEXT: ret i1 true ; %r = call i1 @ipccp2ib(i1 true) ret i1 %r } define internal i32 @ipccp3i(i32 %a) { +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@ipccp3i() ; IS__CGSCC____-NEXT: br label [[T:%.*]] ; IS__CGSCC____: t: @@ -253,9 +303,11 @@ } define i32 @ipccp3() { +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@ipccp3() ; IS__TUNIT____-NEXT: ret i32 7 ; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@ipccp3() ; IS__CGSCC____-NEXT: [[R:%.*]] = call i32 @ipccp3i() ; IS__CGSCC____-NEXT: ret i32 [[R]] @@ -267,44 +319,66 @@ ; Do not touch complicated arguments (for now) %struct.X = type { i8* } define internal i32* @test_inalloca(i32* inalloca %a) { -; CHECK-LABEL: define {{[^@]+}}@test_inalloca -; CHECK-SAME: (i32* inalloca noalias nofree returned writeonly align 536870912 "no-capture-maybe-returned" [[A:%.*]]) -; CHECK-NEXT: ret i32* [[A]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test_inalloca +; IS__TUNIT____-SAME: (i32* inalloca noalias nofree returned writeonly align 536870912 "no-capture-maybe-returned" [[A:%.*]]) +; IS__TUNIT____-NEXT: ret i32* [[A]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test_inalloca +; IS__CGSCC____-SAME: (i32* inalloca noalias nofree returned writeonly align 536870912 "no-capture-maybe-returned" [[A:%.*]]) +; IS__CGSCC____-NEXT: ret i32* [[A]] ; ret i32* %a } define i32* @complicated_args_inalloca() { -; CHECK-LABEL: define {{[^@]+}}@complicated_args_inalloca() -; CHECK-NEXT: [[CALL:%.*]] = call i32* @test_inalloca(i32* noalias nocapture nofree writeonly align 536870912 null) -; CHECK-NEXT: ret i32* [[CALL]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@complicated_args_inalloca() +; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32* @test_inalloca(i32* noalias nocapture nofree writeonly align 536870912 null) +; IS__TUNIT____-NEXT: ret i32* [[CALL]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@complicated_args_inalloca() +; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32* @test_inalloca(i32* noalias nocapture nofree writeonly align 536870912 null) +; IS__CGSCC____-NEXT: ret i32* [[CALL]] ; %call = call i32* @test_inalloca(i32* null) ret i32* %call } define internal i32* @test_preallocated(i32* preallocated(i32) %a) { -; CHECK-LABEL: define {{[^@]+}}@test_preallocated -; CHECK-SAME: (i32* noalias nofree returned writeonly preallocated(i32) align 536870912 "no-capture-maybe-returned" [[A:%.*]]) -; CHECK-NEXT: ret i32* [[A]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test_preallocated +; IS__TUNIT____-SAME: (i32* noalias nofree returned writeonly preallocated(i32) align 536870912 "no-capture-maybe-returned" [[A:%.*]]) +; IS__TUNIT____-NEXT: ret i32* [[A]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test_preallocated +; IS__CGSCC____-SAME: (i32* noalias nofree returned writeonly preallocated(i32) align 536870912 "no-capture-maybe-returned" [[A:%.*]]) +; IS__CGSCC____-NEXT: ret i32* [[A]] ; ret i32* %a } define i32* @complicated_args_preallocated() { +; IS__TUNIT_OPM: Function Attrs: nounwind ; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@complicated_args_preallocated() ; IS__TUNIT_OPM-NEXT: [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 1) ; IS__TUNIT_OPM-NEXT: [[CALL:%.*]] = call i32* @test_preallocated(i32* noalias nocapture nofree writeonly preallocated(i32) align 536870912 null) #5 [ "preallocated"(token [[C]]) ] ; IS__TUNIT_OPM-NEXT: ret i32* [[CALL]] ; +; IS__TUNIT_NPM: Function Attrs: nounwind ; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@complicated_args_preallocated() ; IS__TUNIT_NPM-NEXT: [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 1) ; IS__TUNIT_NPM-NEXT: [[CALL:%.*]] = call i32* @test_preallocated(i32* noalias nocapture nofree writeonly preallocated(i32) align 536870912 null) #4 [ "preallocated"(token [[C]]) ] ; IS__TUNIT_NPM-NEXT: ret i32* [[CALL]] ; +; IS__CGSCC_OPM: Function Attrs: nounwind ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@complicated_args_preallocated() ; IS__CGSCC_OPM-NEXT: [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 1) ; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call i32* @test_preallocated(i32* noalias nocapture nofree writeonly preallocated(i32) align 536870912 null) #6 [ "preallocated"(token [[C]]) ] ; IS__CGSCC_OPM-NEXT: ret i32* [[CALL]] ; +; IS__CGSCC_NPM: Function Attrs: nounwind ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@complicated_args_preallocated() ; IS__CGSCC_NPM-NEXT: [[C:%.*]] = call token @llvm.call.preallocated.setup(i32 1) ; IS__CGSCC_NPM-NEXT: [[CALL:%.*]] = call i32* @test_preallocated(i32* noalias nocapture nofree writeonly preallocated(i32) align 536870912 null) #5 [ "preallocated"(token [[C]]) ] @@ -317,10 +391,17 @@ define internal void @test_sret(%struct.X* sret %a, %struct.X** %b) { ; -; CHECK-LABEL: define {{[^@]+}}@test_sret -; CHECK-SAME: (%struct.X* noalias nofree nonnull sret writeonly align 536870912 dereferenceable(8) [[A:%.*]], %struct.X** nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[B:%.*]]) -; CHECK-NEXT: store %struct.X* [[A]], %struct.X** [[B]], align 8 -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT____-LABEL: define {{[^@]+}}@test_sret +; IS__TUNIT____-SAME: (%struct.X* noalias nofree nonnull sret writeonly align 536870912 dereferenceable(8) [[A:%.*]], %struct.X** nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[B:%.*]]) +; IS__TUNIT____-NEXT: store %struct.X* [[A]], %struct.X** [[B]], align 8 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC____-LABEL: define {{[^@]+}}@test_sret +; IS__CGSCC____-SAME: (%struct.X* noalias nofree nonnull sret writeonly align 536870912 dereferenceable(8) [[A:%.*]], %struct.X** nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[B:%.*]]) +; IS__CGSCC____-NEXT: store %struct.X* [[A]], %struct.X** [[B]], align 8 +; IS__CGSCC____-NEXT: ret void ; store %struct.X* %a, %struct.X** %b ret void @@ -328,11 +409,13 @@ ; FIXME: Alignment and dereferenceability are not propagated to the argument define void @complicated_args_sret(%struct.X** %b) { ; +; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly ; IS__TUNIT____-LABEL: define {{[^@]+}}@complicated_args_sret ; IS__TUNIT____-SAME: (%struct.X** nocapture nofree writeonly [[B:%.*]]) ; IS__TUNIT____-NEXT: call void @test_sret(%struct.X* noalias nocapture nofree writeonly align 536870912 null, %struct.X** nocapture nofree writeonly align 8 [[B]]) ; IS__TUNIT____-NEXT: ret void ; +; IS__CGSCC____: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly ; IS__CGSCC____-LABEL: define {{[^@]+}}@complicated_args_sret ; IS__CGSCC____-SAME: (%struct.X** nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[B:%.*]]) ; IS__CGSCC____-NEXT: call void @test_sret(%struct.X* noalias nocapture nofree nonnull writeonly align 536870912 dereferenceable(8) null, %struct.X** nocapture nofree nonnull writeonly align 8 dereferenceable(8) [[B]]) @@ -343,16 +426,28 @@ } define internal %struct.X* @test_nest(%struct.X* nest %a) { -; CHECK-LABEL: define {{[^@]+}}@test_nest -; CHECK-SAME: (%struct.X* nest noalias nofree readnone returned align 536870912 "no-capture-maybe-returned" [[A:%.*]]) -; CHECK-NEXT: ret %struct.X* [[A]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test_nest +; IS__TUNIT____-SAME: (%struct.X* nest noalias nofree readnone returned align 536870912 "no-capture-maybe-returned" [[A:%.*]]) +; IS__TUNIT____-NEXT: ret %struct.X* [[A]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test_nest +; IS__CGSCC____-SAME: (%struct.X* nest noalias nofree readnone returned align 536870912 "no-capture-maybe-returned" [[A:%.*]]) +; IS__CGSCC____-NEXT: ret %struct.X* [[A]] ; ret %struct.X* %a } define %struct.X* @complicated_args_nest() { -; CHECK-LABEL: define {{[^@]+}}@complicated_args_nest() -; CHECK-NEXT: [[CALL:%.*]] = call %struct.X* @test_nest(%struct.X* noalias nocapture nofree readnone align 536870912 null) -; CHECK-NEXT: ret %struct.X* [[CALL]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@complicated_args_nest() +; IS__TUNIT____-NEXT: [[CALL:%.*]] = call %struct.X* @test_nest(%struct.X* noalias nocapture nofree readnone align 536870912 null) +; IS__TUNIT____-NEXT: ret %struct.X* [[CALL]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@complicated_args_nest() +; IS__CGSCC____-NEXT: [[CALL:%.*]] = call %struct.X* @test_nest(%struct.X* noalias nocapture nofree readnone align 536870912 null) +; IS__CGSCC____-NEXT: ret %struct.X* [[CALL]] ; %call = call %struct.X* @test_nest(%struct.X* null) ret %struct.X* %call @@ -360,12 +455,14 @@ @S = external global %struct.X define internal void @test_byval(%struct.X* byval %a) { +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test_byval ; IS__CGSCC_OPM-SAME: (%struct.X* noalias nocapture nofree nonnull writeonly byval align 8 dereferenceable(8) [[A:%.*]]) ; IS__CGSCC_OPM-NEXT: [[G0:%.*]] = getelementptr [[STRUCT_X:%.*]], %struct.X* [[A]], i32 0, i32 0 ; IS__CGSCC_OPM-NEXT: store i8* null, i8** [[G0]], align 8 ; IS__CGSCC_OPM-NEXT: ret void ; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test_byval ; IS__CGSCC_NPM-SAME: (i8* nocapture nofree readnone [[TMP0:%.*]]) ; IS__CGSCC_NPM-NEXT: [[A_PRIV:%.*]] = alloca [[STRUCT_X:%.*]], align 8 @@ -380,54 +477,146 @@ ret void } define void @complicated_args_byval() { -; CHECK-LABEL: define {{[^@]+}}@complicated_args_byval() -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@complicated_args_byval() +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@complicated_args_byval() +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@complicated_args_byval() +; IS__CGSCC_NPM-NEXT: ret void ; call void @test_byval(%struct.X* @S) ret void } define internal i8*@test_byval2(%struct.X* byval %a) { -; CHECK-LABEL: define {{[^@]+}}@test_byval2() -; CHECK-NEXT: [[G0:%.*]] = getelementptr [[STRUCT_X:%.*]], %struct.X* @S, i32 0, i32 0 -; CHECK-NEXT: [[L:%.*]] = load i8*, i8** [[G0]], align 8 -; CHECK-NEXT: ret i8* [[L]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@test_byval2() +; IS__TUNIT____-NEXT: [[G0:%.*]] = getelementptr [[STRUCT_X:%.*]], %struct.X* @S, i32 0, i32 0 +; IS__TUNIT____-NEXT: [[L:%.*]] = load i8*, i8** [[G0]], align 8 +; IS__TUNIT____-NEXT: ret i8* [[L]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@test_byval2() +; IS__CGSCC____-NEXT: [[G0:%.*]] = getelementptr [[STRUCT_X:%.*]], %struct.X* @S, i32 0, i32 0 +; IS__CGSCC____-NEXT: [[L:%.*]] = load i8*, i8** [[G0]], align 8 +; IS__CGSCC____-NEXT: ret i8* [[L]] ; %g0 = getelementptr %struct.X, %struct.X* %a, i32 0, i32 0 %l = load i8*, i8** %g0 ret i8* %l } define i8* @complicated_args_byval2() { -; CHECK-LABEL: define {{[^@]+}}@complicated_args_byval2() -; CHECK-NEXT: [[C:%.*]] = call i8* @test_byval2() -; CHECK-NEXT: ret i8* [[C]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readonly willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@complicated_args_byval2() +; IS__TUNIT____-NEXT: [[C:%.*]] = call i8* @test_byval2() +; IS__TUNIT____-NEXT: ret i8* [[C]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readonly willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@complicated_args_byval2() +; IS__CGSCC____-NEXT: [[C:%.*]] = call i8* @test_byval2() +; IS__CGSCC____-NEXT: ret i8* [[C]] ; %c = call i8* @test_byval2(%struct.X* @S) ret i8* %c } define void @fixpoint_changed(i32* %p) { -; CHECK-LABEL: define {{[^@]+}}@fixpoint_changed -; CHECK-SAME: (i32* nocapture nofree writeonly [[P:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[FOR_COND:%.*]] -; CHECK: for.cond: -; CHECK-NEXT: [[J_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[SW_EPILOG:%.*]] ] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[J_0]], 30 -; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] -; CHECK: for.body: -; CHECK-NEXT: switch i32 [[J_0]], label [[SW_EPILOG]] [ -; CHECK-NEXT: i32 1, label [[SW_BB:%.*]] -; CHECK-NEXT: ] -; CHECK: sw.bb: -; CHECK-NEXT: br label [[SW_EPILOG]] -; CHECK: sw.epilog: -; CHECK-NEXT: [[X_0:%.*]] = phi i32 [ 255, [[FOR_BODY]] ], [ 253, [[SW_BB]] ] -; CHECK-NEXT: store i32 [[X_0]], i32* [[P]], align 4 -; CHECK-NEXT: [[INC]] = add nsw i32 [[J_0]], 1 -; CHECK-NEXT: br label [[FOR_COND]] -; CHECK: for.end: -; CHECK-NEXT: ret void +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree nosync nounwind writeonly +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@fixpoint_changed +; IS__TUNIT_OPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]]) +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: br label [[FOR_COND:%.*]] +; IS__TUNIT_OPM: for.cond: +; IS__TUNIT_OPM-NEXT: [[J_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[SW_EPILOG:%.*]] ] +; IS__TUNIT_OPM-NEXT: [[CMP:%.*]] = icmp slt i32 [[J_0]], 30 +; IS__TUNIT_OPM-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] +; IS__TUNIT_OPM: for.body: +; IS__TUNIT_OPM-NEXT: switch i32 [[J_0]], label [[SW_EPILOG]] [ +; IS__TUNIT_OPM-NEXT: i32 1, label [[SW_BB:%.*]] +; IS__TUNIT_OPM-NEXT: ] +; IS__TUNIT_OPM: sw.bb: +; IS__TUNIT_OPM-NEXT: br label [[SW_EPILOG]] +; IS__TUNIT_OPM: sw.epilog: +; IS__TUNIT_OPM-NEXT: [[X_0:%.*]] = phi i32 [ 255, [[FOR_BODY]] ], [ 253, [[SW_BB]] ] +; IS__TUNIT_OPM-NEXT: store i32 [[X_0]], i32* [[P]], align 4 +; IS__TUNIT_OPM-NEXT: [[INC]] = add nsw i32 [[J_0]], 1 +; IS__TUNIT_OPM-NEXT: br label [[FOR_COND]] +; IS__TUNIT_OPM: for.end: +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree nosync nounwind willreturn writeonly +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@fixpoint_changed +; IS__TUNIT_NPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: br label [[FOR_COND:%.*]] +; IS__TUNIT_NPM: for.cond: +; IS__TUNIT_NPM-NEXT: [[J_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[SW_EPILOG:%.*]] ] +; IS__TUNIT_NPM-NEXT: [[CMP:%.*]] = icmp slt i32 [[J_0]], 30 +; IS__TUNIT_NPM-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] +; IS__TUNIT_NPM: for.body: +; IS__TUNIT_NPM-NEXT: switch i32 [[J_0]], label [[SW_EPILOG]] [ +; IS__TUNIT_NPM-NEXT: i32 1, label [[SW_BB:%.*]] +; IS__TUNIT_NPM-NEXT: ] +; IS__TUNIT_NPM: sw.bb: +; IS__TUNIT_NPM-NEXT: br label [[SW_EPILOG]] +; IS__TUNIT_NPM: sw.epilog: +; IS__TUNIT_NPM-NEXT: [[X_0:%.*]] = phi i32 [ 255, [[FOR_BODY]] ], [ 253, [[SW_BB]] ] +; IS__TUNIT_NPM-NEXT: store i32 [[X_0]], i32* [[P]], align 4 +; IS__TUNIT_NPM-NEXT: [[INC]] = add nsw i32 [[J_0]], 1 +; IS__TUNIT_NPM-NEXT: br label [[FOR_COND]] +; IS__TUNIT_NPM: for.end: +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM: Function Attrs: argmemonly nofree norecurse nosync nounwind writeonly +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@fixpoint_changed +; IS__CGSCC_OPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: br label [[FOR_COND:%.*]] +; IS__CGSCC_OPM: for.cond: +; IS__CGSCC_OPM-NEXT: [[J_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[SW_EPILOG:%.*]] ] +; IS__CGSCC_OPM-NEXT: [[CMP:%.*]] = icmp slt i32 [[J_0]], 30 +; IS__CGSCC_OPM-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] +; IS__CGSCC_OPM: for.body: +; IS__CGSCC_OPM-NEXT: switch i32 [[J_0]], label [[SW_EPILOG]] [ +; IS__CGSCC_OPM-NEXT: i32 1, label [[SW_BB:%.*]] +; IS__CGSCC_OPM-NEXT: ] +; IS__CGSCC_OPM: sw.bb: +; IS__CGSCC_OPM-NEXT: br label [[SW_EPILOG]] +; IS__CGSCC_OPM: sw.epilog: +; IS__CGSCC_OPM-NEXT: [[X_0:%.*]] = phi i32 [ 255, [[FOR_BODY]] ], [ 253, [[SW_BB]] ] +; IS__CGSCC_OPM-NEXT: store i32 [[X_0]], i32* [[P]], align 4 +; IS__CGSCC_OPM-NEXT: [[INC]] = add nsw i32 [[J_0]], 1 +; IS__CGSCC_OPM-NEXT: br label [[FOR_COND]] +; IS__CGSCC_OPM: for.end: +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM: Function Attrs: argmemonly nofree norecurse nosync nounwind willreturn writeonly +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@fixpoint_changed +; IS__CGSCC_NPM-SAME: (i32* nocapture nofree writeonly [[P:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: br label [[FOR_COND:%.*]] +; IS__CGSCC_NPM: for.cond: +; IS__CGSCC_NPM-NEXT: [[J_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[SW_EPILOG:%.*]] ] +; IS__CGSCC_NPM-NEXT: [[CMP:%.*]] = icmp slt i32 [[J_0]], 30 +; IS__CGSCC_NPM-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] +; IS__CGSCC_NPM: for.body: +; IS__CGSCC_NPM-NEXT: switch i32 [[J_0]], label [[SW_EPILOG]] [ +; IS__CGSCC_NPM-NEXT: i32 1, label [[SW_BB:%.*]] +; IS__CGSCC_NPM-NEXT: ] +; IS__CGSCC_NPM: sw.bb: +; IS__CGSCC_NPM-NEXT: br label [[SW_EPILOG]] +; IS__CGSCC_NPM: sw.epilog: +; IS__CGSCC_NPM-NEXT: [[X_0:%.*]] = phi i32 [ 255, [[FOR_BODY]] ], [ 253, [[SW_BB]] ] +; IS__CGSCC_NPM-NEXT: store i32 [[X_0]], i32* [[P]], align 4 +; IS__CGSCC_NPM-NEXT: [[INC]] = add nsw i32 [[J_0]], 1 +; IS__CGSCC_NPM-NEXT: br label [[FOR_COND]] +; IS__CGSCC_NPM: for.end: +; IS__CGSCC_NPM-NEXT: ret void ; entry: br label %for.cond @@ -458,57 +647,99 @@ ; Check we merge undef and a constant properly. ; FIXME fold the addition and return the constant. define i8 @caller0() { -; CHECK-LABEL: define {{[^@]+}}@caller0() -; CHECK-NEXT: [[C:%.*]] = call i8 @callee() -; CHECK-NEXT: ret i8 [[C]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@caller0() +; IS__TUNIT____-NEXT: [[C:%.*]] = call i8 @callee() +; IS__TUNIT____-NEXT: ret i8 [[C]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@caller0() +; IS__CGSCC____-NEXT: [[C:%.*]] = call i8 @callee() +; IS__CGSCC____-NEXT: ret i8 [[C]] ; %c = call i8 @callee(i8 undef) ret i8 %c } define i8 @caller1() { -; CHECK-LABEL: define {{[^@]+}}@caller1() -; CHECK-NEXT: [[C:%.*]] = call i8 @callee() -; CHECK-NEXT: ret i8 [[C]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@caller1() +; IS__TUNIT____-NEXT: [[C:%.*]] = call i8 @callee() +; IS__TUNIT____-NEXT: ret i8 [[C]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@caller1() +; IS__CGSCC____-NEXT: [[C:%.*]] = call i8 @callee() +; IS__CGSCC____-NEXT: ret i8 [[C]] ; %c = call i8 @callee(i8 undef) ret i8 %c } define i8 @caller2() { -; CHECK-LABEL: define {{[^@]+}}@caller2() -; CHECK-NEXT: [[C:%.*]] = call i8 @callee() -; CHECK-NEXT: ret i8 [[C]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@caller2() +; IS__TUNIT____-NEXT: [[C:%.*]] = call i8 @callee() +; IS__TUNIT____-NEXT: ret i8 [[C]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@caller2() +; IS__CGSCC____-NEXT: [[C:%.*]] = call i8 @callee() +; IS__CGSCC____-NEXT: ret i8 [[C]] ; %c = call i8 @callee(i8 undef) ret i8 %c } define i8 @caller_middle() { -; CHECK-LABEL: define {{[^@]+}}@caller_middle() -; CHECK-NEXT: [[C:%.*]] = call i8 @callee() -; CHECK-NEXT: ret i8 [[C]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@caller_middle() +; IS__TUNIT____-NEXT: [[C:%.*]] = call i8 @callee() +; IS__TUNIT____-NEXT: ret i8 [[C]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@caller_middle() +; IS__CGSCC____-NEXT: [[C:%.*]] = call i8 @callee() +; IS__CGSCC____-NEXT: ret i8 [[C]] ; %c = call i8 @callee(i8 42) ret i8 %c } define i8 @caller3() { -; CHECK-LABEL: define {{[^@]+}}@caller3() -; CHECK-NEXT: [[C:%.*]] = call i8 @callee() -; CHECK-NEXT: ret i8 [[C]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@caller3() +; IS__TUNIT____-NEXT: [[C:%.*]] = call i8 @callee() +; IS__TUNIT____-NEXT: ret i8 [[C]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@caller3() +; IS__CGSCC____-NEXT: [[C:%.*]] = call i8 @callee() +; IS__CGSCC____-NEXT: ret i8 [[C]] ; %c = call i8 @callee(i8 undef) ret i8 %c } define i8 @caller4() { -; CHECK-LABEL: define {{[^@]+}}@caller4() -; CHECK-NEXT: [[C:%.*]] = call i8 @callee() -; CHECK-NEXT: ret i8 [[C]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@caller4() +; IS__TUNIT____-NEXT: [[C:%.*]] = call i8 @callee() +; IS__TUNIT____-NEXT: ret i8 [[C]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@caller4() +; IS__CGSCC____-NEXT: [[C:%.*]] = call i8 @callee() +; IS__CGSCC____-NEXT: ret i8 [[C]] ; %c = call i8 @callee(i8 undef) ret i8 %c } define internal i8 @callee(i8 %a) { -; CHECK-LABEL: define {{[^@]+}}@callee() -; CHECK-NEXT: [[C:%.*]] = add i8 42, 7 -; CHECK-NEXT: ret i8 [[C]] +; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@callee() +; IS__TUNIT____-NEXT: [[C:%.*]] = add i8 42, 7 +; IS__TUNIT____-NEXT: ret i8 [[C]] +; +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@callee() +; IS__CGSCC____-NEXT: [[C:%.*]] = add i8 42, 7 +; IS__CGSCC____-NEXT: ret i8 [[C]] ; %c = add i8 %a, 7 ret i8 %c diff --git a/llvm/test/Transforms/Attributor/willreturn.ll b/llvm/test/Transforms/Attributor/willreturn.ll --- a/llvm/test/Transforms/Attributor/willreturn.ll +++ b/llvm/test/Transforms/Attributor/willreturn.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes --check-attributes ; RUN: opt -attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=8 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=8 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM ; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM @@ -11,11 +11,14 @@ ; TEST 1 (positive case) +define void @only_return() #0 { ; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@only_return() +; IS__TUNIT____-NEXT: ret void +; ; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn -define void @only_return() #0 { -; CHECK-LABEL: define {{[^@]+}}@only_return() -; CHECK-NEXT: ret void +; IS__CGSCC____-LABEL: define {{[^@]+}}@only_return() +; IS__CGSCC____-NEXT: ret void ; ret void } @@ -29,8 +32,8 @@ ; } ; FIXME: missing willreturn -; CHECK: Function Attrs: nofree noinline nosync nounwind readnone uwtable define i32 @fib(i32 %0) local_unnamed_addr #0 { +; CHECK: Function Attrs: nofree noinline nosync nounwind readnone uwtable ; CHECK-LABEL: define {{[^@]+}}@fib ; CHECK-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr ; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP0]], 2 @@ -70,26 +73,42 @@ ; } ; fact_maybe_not(-1) doesn't stop. +define i32 @fact_maybe_not_halt(i32 %0) local_unnamed_addr #0 { ; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; IS__TUNIT____-LABEL: define {{[^@]+}}@fact_maybe_not_halt +; IS__TUNIT____-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr +; IS__TUNIT____-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 0 +; IS__TUNIT____-NEXT: br i1 [[TMP2]], label [[TMP11:%.*]], label [[TMP3:%.*]] +; IS__TUNIT____: 3: +; IS__TUNIT____-NEXT: [[TMP4:%.*]] = phi i32 [ [[TMP8:%.*]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] +; IS__TUNIT____-NEXT: [[TMP5:%.*]] = phi i32 [ [[TMP9:%.*]], [[TMP3]] ], [ 1, [[TMP1]] ] +; IS__TUNIT____-NEXT: [[TMP6:%.*]] = icmp sgt i32 [[TMP4]], 0 +; IS__TUNIT____-NEXT: [[TMP7:%.*]] = sext i1 [[TMP6]] to i32 +; IS__TUNIT____-NEXT: [[TMP8]] = add nsw i32 [[TMP4]], [[TMP7]] +; IS__TUNIT____-NEXT: [[TMP9]] = mul nsw i32 [[TMP4]], [[TMP5]] +; IS__TUNIT____-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP8]], 0 +; IS__TUNIT____-NEXT: br i1 [[TMP10]], label [[TMP11]], label [[TMP3]] +; IS__TUNIT____: 11: +; IS__TUNIT____-NEXT: [[TMP12:%.*]] = phi i32 [ 1, [[TMP1]] ], [ [[TMP9]], [[TMP3]] ] +; IS__TUNIT____-NEXT: ret i32 [[TMP12]] +; ; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable -; CHECK-NOT: willreturn -define i32 @fact_maybe_not_halt(i32 %0) local_unnamed_addr #0 { -; CHECK-LABEL: define {{[^@]+}}@fact_maybe_not_halt -; CHECK-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr -; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 0 -; CHECK-NEXT: br i1 [[TMP2]], label [[TMP11:%.*]], label [[TMP3:%.*]] -; CHECK: 3: -; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ [[TMP8:%.*]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] -; CHECK-NEXT: [[TMP5:%.*]] = phi i32 [ [[TMP9:%.*]], [[TMP3]] ], [ 1, [[TMP1]] ] -; CHECK-NEXT: [[TMP6:%.*]] = icmp sgt i32 [[TMP4]], 0 -; CHECK-NEXT: [[TMP7:%.*]] = sext i1 [[TMP6]] to i32 -; CHECK-NEXT: [[TMP8]] = add nsw i32 [[TMP4]], [[TMP7]] -; CHECK-NEXT: [[TMP9]] = mul nsw i32 [[TMP4]], [[TMP5]] -; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP8]], 0 -; CHECK-NEXT: br i1 [[TMP10]], label [[TMP11]], label [[TMP3]] -; CHECK: 11: -; CHECK-NEXT: [[TMP12:%.*]] = phi i32 [ 1, [[TMP1]] ], [ [[TMP9]], [[TMP3]] ] -; CHECK-NEXT: ret i32 [[TMP12]] +; IS__CGSCC____-LABEL: define {{[^@]+}}@fact_maybe_not_halt +; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr +; IS__CGSCC____-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP0]], 0 +; IS__CGSCC____-NEXT: br i1 [[TMP2]], label [[TMP11:%.*]], label [[TMP3:%.*]] +; IS__CGSCC____: 3: +; IS__CGSCC____-NEXT: [[TMP4:%.*]] = phi i32 [ [[TMP8:%.*]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] +; IS__CGSCC____-NEXT: [[TMP5:%.*]] = phi i32 [ [[TMP9:%.*]], [[TMP3]] ], [ 1, [[TMP1]] ] +; IS__CGSCC____-NEXT: [[TMP6:%.*]] = icmp sgt i32 [[TMP4]], 0 +; IS__CGSCC____-NEXT: [[TMP7:%.*]] = sext i1 [[TMP6]] to i32 +; IS__CGSCC____-NEXT: [[TMP8]] = add nsw i32 [[TMP4]], [[TMP7]] +; IS__CGSCC____-NEXT: [[TMP9]] = mul nsw i32 [[TMP4]], [[TMP5]] +; IS__CGSCC____-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP8]], 0 +; IS__CGSCC____-NEXT: br i1 [[TMP10]], label [[TMP11]], label [[TMP3]] +; IS__CGSCC____: 11: +; IS__CGSCC____-NEXT: [[TMP12:%.*]] = phi i32 [ 1, [[TMP1]] ], [ [[TMP9]], [[TMP3]] ] +; IS__CGSCC____-NEXT: ret i32 [[TMP12]] ; %2 = icmp eq i32 %0, 0 br i1 %2, label %11, label %3 @@ -120,23 +139,70 @@ ; return ans; ; } -; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable -; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable define i32 @fact_loop(i32 %0) local_unnamed_addr #0 { -; CHECK-LABEL: define {{[^@]+}}@fact_loop -; CHECK-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr -; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP0]], 1 -; CHECK-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] -; CHECK: 3: -; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ 1, [[TMP1:%.*]] ], [ [[TMP8:%.*]], [[TMP5]] ] -; CHECK-NEXT: ret i32 [[TMP4]] -; CHECK: 5: -; CHECK-NEXT: [[TMP6:%.*]] = phi i32 [ [[TMP9:%.*]], [[TMP5]] ], [ 1, [[TMP1]] ] -; CHECK-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8]], [[TMP5]] ], [ 1, [[TMP1]] ] -; CHECK-NEXT: [[TMP8]] = mul nsw i32 [[TMP6]], [[TMP7]] -; CHECK-NEXT: [[TMP9]] = add nuw nsw i32 [[TMP6]], 1 -; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP6]], [[TMP0]] -; CHECK-NEXT: br i1 [[TMP10]], label [[TMP3]], label [[TMP5]] +; IS__TUNIT_OPM: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@fact_loop +; IS__TUNIT_OPM-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP0]], 1 +; IS__TUNIT_OPM-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] +; IS__TUNIT_OPM: 3: +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = phi i32 [ 1, [[TMP1:%.*]] ], [ [[TMP8:%.*]], [[TMP5]] ] +; IS__TUNIT_OPM-NEXT: ret i32 [[TMP4]] +; IS__TUNIT_OPM: 5: +; IS__TUNIT_OPM-NEXT: [[TMP6:%.*]] = phi i32 [ [[TMP9:%.*]], [[TMP5]] ], [ 1, [[TMP1]] ] +; IS__TUNIT_OPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8]], [[TMP5]] ], [ 1, [[TMP1]] ] +; IS__TUNIT_OPM-NEXT: [[TMP8]] = mul nsw i32 [[TMP6]], [[TMP7]] +; IS__TUNIT_OPM-NEXT: [[TMP9]] = add nuw nsw i32 [[TMP6]], 1 +; IS__TUNIT_OPM-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP6]], [[TMP0]] +; IS__TUNIT_OPM-NEXT: br i1 [[TMP10]], label [[TMP3]], label [[TMP5]] +; +; IS__TUNIT_NPM: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@fact_loop +; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP0]], 1 +; IS__TUNIT_NPM-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] +; IS__TUNIT_NPM: 3: +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = phi i32 [ 1, [[TMP1:%.*]] ], [ [[TMP8:%.*]], [[TMP5]] ] +; IS__TUNIT_NPM-NEXT: ret i32 [[TMP4]] +; IS__TUNIT_NPM: 5: +; IS__TUNIT_NPM-NEXT: [[TMP6:%.*]] = phi i32 [ [[TMP9:%.*]], [[TMP5]] ], [ 1, [[TMP1]] ] +; IS__TUNIT_NPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8]], [[TMP5]] ], [ 1, [[TMP1]] ] +; IS__TUNIT_NPM-NEXT: [[TMP8]] = mul nsw i32 [[TMP6]], [[TMP7]] +; IS__TUNIT_NPM-NEXT: [[TMP9]] = add nuw nsw i32 [[TMP6]], 1 +; IS__TUNIT_NPM-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP6]], [[TMP0]] +; IS__TUNIT_NPM-NEXT: br i1 [[TMP10]], label [[TMP3]], label [[TMP5]] +; +; IS__CGSCC_OPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@fact_loop +; IS__CGSCC_OPM-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP0]], 1 +; IS__CGSCC_OPM-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] +; IS__CGSCC_OPM: 3: +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = phi i32 [ 1, [[TMP1:%.*]] ], [ [[TMP8:%.*]], [[TMP5]] ] +; IS__CGSCC_OPM-NEXT: ret i32 [[TMP4]] +; IS__CGSCC_OPM: 5: +; IS__CGSCC_OPM-NEXT: [[TMP6:%.*]] = phi i32 [ [[TMP9:%.*]], [[TMP5]] ], [ 1, [[TMP1]] ] +; IS__CGSCC_OPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8]], [[TMP5]] ], [ 1, [[TMP1]] ] +; IS__CGSCC_OPM-NEXT: [[TMP8]] = mul nsw i32 [[TMP6]], [[TMP7]] +; IS__CGSCC_OPM-NEXT: [[TMP9]] = add nuw nsw i32 [[TMP6]], 1 +; IS__CGSCC_OPM-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP6]], [[TMP0]] +; IS__CGSCC_OPM-NEXT: br i1 [[TMP10]], label [[TMP3]], label [[TMP5]] +; +; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@fact_loop +; IS__CGSCC_NPM-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP0]], 1 +; IS__CGSCC_NPM-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] +; IS__CGSCC_NPM: 3: +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = phi i32 [ 1, [[TMP1:%.*]] ], [ [[TMP8:%.*]], [[TMP5]] ] +; IS__CGSCC_NPM-NEXT: ret i32 [[TMP4]] +; IS__CGSCC_NPM: 5: +; IS__CGSCC_NPM-NEXT: [[TMP6:%.*]] = phi i32 [ [[TMP9:%.*]], [[TMP5]] ], [ 1, [[TMP1]] ] +; IS__CGSCC_NPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8]], [[TMP5]] ], [ 1, [[TMP1]] ] +; IS__CGSCC_NPM-NEXT: [[TMP8]] = mul nsw i32 [[TMP6]], [[TMP7]] +; IS__CGSCC_NPM-NEXT: [[TMP9]] = add nuw nsw i32 [[TMP6]], 1 +; IS__CGSCC_NPM-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP6]], [[TMP0]] +; IS__CGSCC_NPM-NEXT: br i1 [[TMP10]], label [[TMP3]], label [[TMP5]] ; %2 = icmp slt i32 %0, 1 br i1 %2, label %3, label %5 @@ -165,9 +231,8 @@ declare void @sink() nounwind willreturn nosync nofree -; CHECK: Function Attrs: nofree noinline nosync nounwind uwtable -; CHECK-NOT: willreturn define void @mutual_recursion1(i1 %c) #0 { +; CHECK: Function Attrs: nofree noinline nosync nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@mutual_recursion1 ; CHECK-SAME: (i1 [[C:%.*]]) ; CHECK-NEXT: br i1 [[C]], label [[REC:%.*]], label [[END:%.*]] @@ -188,9 +253,8 @@ } -; CHECK: Function Attrs: nofree noinline nosync nounwind uwtable -; CHECK-NOT: willreturn define void @mutual_recursion2(i1 %c) #0 { +; CHECK: Function Attrs: nofree noinline nosync nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@mutual_recursion2 ; CHECK-SAME: (i1 [[C:%.*]]) ; CHECK-NEXT: call void @mutual_recursion1(i1 [[C]]) @@ -207,9 +271,8 @@ ; CHECK-NEXT: declare void @exit(i32) local_unnamed_add declare void @exit(i32 %0) local_unnamed_addr noreturn -; CHECK: Function Attrs: noinline noreturn nounwind uwtable -; CHECK-NOT: willreturn define void @only_exit() local_unnamed_addr #0 { +; CHECK: Function Attrs: noinline noreturn nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@only_exit() local_unnamed_addr ; CHECK-NEXT: tail call void @exit(i32 0) ; CHECK-NEXT: unreachable @@ -228,9 +291,8 @@ ; } ; return; ; } -; CHECK: Function Attrs: noinline nounwind uwtable -; CHECK-NOT: willreturn define void @conditional_exit(i32 %0, i32* nocapture readonly %1) local_unnamed_addr #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@conditional_exit ; CHECK-SAME: (i32 [[TMP0:%.*]], i32* nocapture readonly [[TMP1:%.*]]) local_unnamed_addr ; CHECK-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0 @@ -274,19 +336,23 @@ ; CHECK-NEXT: declare float @llvm.floor.f32(float) declare float @llvm.floor.f32(float) -; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn -; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn define void @call_floor(float %a) #0 { -; CHECK-LABEL: define {{[^@]+}}@call_floor -; CHECK-SAME: (float [[A:%.*]]) -; CHECK-NEXT: ret void +; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@call_floor +; IS__TUNIT____-SAME: (float [[A:%.*]]) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@call_floor +; IS__CGSCC____-SAME: (float [[A:%.*]]) +; IS__CGSCC____-NEXT: ret void ; tail call float @llvm.floor.f32(float %a) ret void } -; CHECK: Function Attrs: noinline nosync nounwind readnone uwtable willreturn define float @call_floor2(float %a) #0 { +; CHECK: Function Attrs: noinline nosync nounwind readnone uwtable willreturn ; CHECK-LABEL: define {{[^@]+}}@call_floor2 ; CHECK-SAME: (float [[A:%.*]]) ; CHECK-NEXT: [[C:%.*]] = tail call float @llvm.floor.f32(float [[A]]) @@ -305,9 +371,8 @@ ; CHECK-NEXT: declare void @maybe_noreturn() declare void @maybe_noreturn() #0 -; CHECK: Function Attrs: noinline nounwind uwtable -; CHECK-NOT: willreturn define void @call_maybe_noreturn() #0 { +; CHECK: Function Attrs: noinline nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@call_maybe_noreturn() ; CHECK-NEXT: tail call void @maybe_noreturn() ; CHECK-NEXT: ret void @@ -324,23 +389,31 @@ ; CHECK-NEXT: declare void @will_return() declare void @will_return() willreturn norecurse +define void @f1() #0 { ; IS__TUNIT____: Function Attrs: noinline nounwind uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@f1() +; IS__TUNIT____-NEXT: tail call void @will_return() +; IS__TUNIT____-NEXT: ret void +; ; IS__CGSCC____: Function Attrs: noinline norecurse nounwind uwtable willreturn -define void @f1() #0 { -; CHECK-LABEL: define {{[^@]+}}@f1() -; CHECK-NEXT: tail call void @will_return() -; CHECK-NEXT: ret void +; IS__CGSCC____-LABEL: define {{[^@]+}}@f1() +; IS__CGSCC____-NEXT: tail call void @will_return() +; IS__CGSCC____-NEXT: ret void ; tail call void @will_return() ret void } +define void @f2() #0 { ; IS__TUNIT____: Function Attrs: noinline nounwind uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@f2() +; IS__TUNIT____-NEXT: tail call void @f1() +; IS__TUNIT____-NEXT: ret void +; ; IS__CGSCC____: Function Attrs: noinline norecurse nounwind uwtable willreturn -define void @f2() #0 { -; CHECK-LABEL: define {{[^@]+}}@f2() -; CHECK-NEXT: tail call void @f1() -; CHECK-NEXT: ret void +; IS__CGSCC____-LABEL: define {{[^@]+}}@f2() +; IS__CGSCC____-NEXT: tail call void @f1() +; IS__CGSCC____-NEXT: ret void ; tail call void @f1() ret void @@ -350,17 +423,24 @@ ; TEST 9 (negative case) ; call willreturn function in endless loop. +define void @call_will_return_but_has_loop() #0 { ; IS__TUNIT____: Function Attrs: noinline noreturn nounwind uwtable +; IS__TUNIT____-LABEL: define {{[^@]+}}@call_will_return_but_has_loop() +; IS__TUNIT____-NEXT: br label [[LABEL1:%.*]] +; IS__TUNIT____: label1: +; IS__TUNIT____-NEXT: tail call void @will_return() +; IS__TUNIT____-NEXT: br label [[LABEL2:%.*]] +; IS__TUNIT____: label2: +; IS__TUNIT____-NEXT: br label [[LABEL1]] +; ; IS__CGSCC____: Function Attrs: noinline norecurse noreturn nounwind uwtable -; CHECK-NOT: willreturn -define void @call_will_return_but_has_loop() #0 { -; CHECK-LABEL: define {{[^@]+}}@call_will_return_but_has_loop() -; CHECK-NEXT: br label [[LABEL1:%.*]] -; CHECK: label1: -; CHECK-NEXT: tail call void @will_return() -; CHECK-NEXT: br label [[LABEL2:%.*]] -; CHECK: label2: -; CHECK-NEXT: br label [[LABEL1]] +; IS__CGSCC____-LABEL: define {{[^@]+}}@call_will_return_but_has_loop() +; IS__CGSCC____-NEXT: br label [[LABEL1:%.*]] +; IS__CGSCC____: label1: +; IS__CGSCC____-NEXT: tail call void @will_return() +; IS__CGSCC____-NEXT: br label [[LABEL2:%.*]] +; IS__CGSCC____: label2: +; IS__CGSCC____-NEXT: br label [[LABEL1]] ; br label %label1 label1: @@ -378,8 +458,8 @@ ; CHECK-NEXT: declare i1 @maybe_raise_exception() declare i1 @maybe_raise_exception() #1 willreturn -; CHECK: Function Attrs: nounwind willreturn define void @invoke_test() personality i32 (...)* @__gxx_personality_v0 { +; IS__TUNIT____: Function Attrs: nounwind willreturn ; IS__TUNIT____-LABEL: define {{[^@]+}}@invoke_test() #12 personality i32 (...)* @__gxx_personality_v0 ; IS__TUNIT____-NEXT: [[TMP1:%.*]] = invoke i1 @maybe_raise_exception() ; IS__TUNIT____-NEXT: to label [[N:%.*]] unwind label [[F:%.*]] @@ -390,6 +470,7 @@ ; IS__TUNIT____-NEXT: catch i8* null ; IS__TUNIT____-NEXT: ret void ; +; IS__CGSCC____: Function Attrs: nounwind willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@invoke_test() #14 personality i32 (...)* @__gxx_personality_v0 ; IS__CGSCC____-NEXT: [[TMP1:%.*]] = invoke i1 @maybe_raise_exception() ; IS__CGSCC____-NEXT: to label [[N:%.*]] unwind label [[F:%.*]] @@ -423,38 +504,70 @@ ; return ans; ; } -; IS__TUNIT____: Function Attrs: argmemonly nofree noinline nosync nounwind readonly uwtable -; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly uwtable define i32 @loop_constant_trip_count(i32* nocapture readonly %0) #0 { -; IS________OPM-LABEL: define {{[^@]+}}@loop_constant_trip_count -; IS________OPM-SAME: (i32* nocapture nofree readonly [[TMP0:%.*]]) -; IS________OPM-NEXT: br label [[TMP3:%.*]] -; IS________OPM: 2: -; IS________OPM-NEXT: ret i32 [[TMP8:%.*]] -; IS________OPM: 3: -; IS________OPM-NEXT: [[TMP4:%.*]] = phi i64 [ 0, [[TMP1:%.*]] ], [ [[TMP9:%.*]], [[TMP3]] ] -; IS________OPM-NEXT: [[TMP5:%.*]] = phi i32 [ 0, [[TMP1]] ], [ [[TMP8]], [[TMP3]] ] -; IS________OPM-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP4]] -; IS________OPM-NEXT: [[TMP7:%.*]] = load i32, i32* [[TMP6]], align 4 -; IS________OPM-NEXT: [[TMP8]] = add nsw i32 [[TMP7]], [[TMP5]] -; IS________OPM-NEXT: [[TMP9]] = add nuw nsw i64 [[TMP4]], 1 -; IS________OPM-NEXT: [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 10 -; IS________OPM-NEXT: br i1 [[TMP10]], label [[TMP2:%.*]], label [[TMP3]] +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree noinline nosync nounwind readonly uwtable +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@loop_constant_trip_count +; IS__TUNIT_OPM-SAME: (i32* nocapture nofree readonly [[TMP0:%.*]]) +; IS__TUNIT_OPM-NEXT: br label [[TMP3:%.*]] +; IS__TUNIT_OPM: 2: +; IS__TUNIT_OPM-NEXT: ret i32 [[TMP8:%.*]] +; IS__TUNIT_OPM: 3: +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = phi i64 [ 0, [[TMP1:%.*]] ], [ [[TMP9:%.*]], [[TMP3]] ] +; IS__TUNIT_OPM-NEXT: [[TMP5:%.*]] = phi i32 [ 0, [[TMP1]] ], [ [[TMP8]], [[TMP3]] ] +; IS__TUNIT_OPM-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP4]] +; IS__TUNIT_OPM-NEXT: [[TMP7:%.*]] = load i32, i32* [[TMP6]], align 4 +; IS__TUNIT_OPM-NEXT: [[TMP8]] = add nsw i32 [[TMP7]], [[TMP5]] +; IS__TUNIT_OPM-NEXT: [[TMP9]] = add nuw nsw i64 [[TMP4]], 1 +; IS__TUNIT_OPM-NEXT: [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 10 +; IS__TUNIT_OPM-NEXT: br i1 [[TMP10]], label [[TMP2:%.*]], label [[TMP3]] +; +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree noinline nosync nounwind readonly uwtable willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@loop_constant_trip_count +; IS__TUNIT_NPM-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[TMP0:%.*]]) +; IS__TUNIT_NPM-NEXT: br label [[TMP3:%.*]] +; IS__TUNIT_NPM: 2: +; IS__TUNIT_NPM-NEXT: ret i32 [[TMP8:%.*]] +; IS__TUNIT_NPM: 3: +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = phi i64 [ 0, [[TMP1:%.*]] ], [ [[TMP9:%.*]], [[TMP3]] ] +; IS__TUNIT_NPM-NEXT: [[TMP5:%.*]] = phi i32 [ 0, [[TMP1]] ], [ [[TMP8]], [[TMP3]] ] +; IS__TUNIT_NPM-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP4]] +; IS__TUNIT_NPM-NEXT: [[TMP7:%.*]] = load i32, i32* [[TMP6]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP8]] = add nsw i32 [[TMP7]], [[TMP5]] +; IS__TUNIT_NPM-NEXT: [[TMP9]] = add nuw nsw i64 [[TMP4]], 1 +; IS__TUNIT_NPM-NEXT: [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 10 +; IS__TUNIT_NPM-NEXT: br i1 [[TMP10]], label [[TMP2:%.*]], label [[TMP3]] +; +; IS__CGSCC_OPM: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly uwtable +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@loop_constant_trip_count +; IS__CGSCC_OPM-SAME: (i32* nocapture nofree readonly [[TMP0:%.*]]) +; IS__CGSCC_OPM-NEXT: br label [[TMP3:%.*]] +; IS__CGSCC_OPM: 2: +; IS__CGSCC_OPM-NEXT: ret i32 [[TMP8:%.*]] +; IS__CGSCC_OPM: 3: +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = phi i64 [ 0, [[TMP1:%.*]] ], [ [[TMP9:%.*]], [[TMP3]] ] +; IS__CGSCC_OPM-NEXT: [[TMP5:%.*]] = phi i32 [ 0, [[TMP1]] ], [ [[TMP8]], [[TMP3]] ] +; IS__CGSCC_OPM-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP4]] +; IS__CGSCC_OPM-NEXT: [[TMP7:%.*]] = load i32, i32* [[TMP6]], align 4 +; IS__CGSCC_OPM-NEXT: [[TMP8]] = add nsw i32 [[TMP7]], [[TMP5]] +; IS__CGSCC_OPM-NEXT: [[TMP9]] = add nuw nsw i64 [[TMP4]], 1 +; IS__CGSCC_OPM-NEXT: [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 10 +; IS__CGSCC_OPM-NEXT: br i1 [[TMP10]], label [[TMP2:%.*]], label [[TMP3]] ; -; IS________NPM-LABEL: define {{[^@]+}}@loop_constant_trip_count -; IS________NPM-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[TMP0:%.*]]) -; IS________NPM-NEXT: br label [[TMP3:%.*]] -; IS________NPM: 2: -; IS________NPM-NEXT: ret i32 [[TMP8:%.*]] -; IS________NPM: 3: -; IS________NPM-NEXT: [[TMP4:%.*]] = phi i64 [ 0, [[TMP1:%.*]] ], [ [[TMP9:%.*]], [[TMP3]] ] -; IS________NPM-NEXT: [[TMP5:%.*]] = phi i32 [ 0, [[TMP1]] ], [ [[TMP8]], [[TMP3]] ] -; IS________NPM-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP4]] -; IS________NPM-NEXT: [[TMP7:%.*]] = load i32, i32* [[TMP6]], align 4 -; IS________NPM-NEXT: [[TMP8]] = add nsw i32 [[TMP7]], [[TMP5]] -; IS________NPM-NEXT: [[TMP9]] = add nuw nsw i64 [[TMP4]], 1 -; IS________NPM-NEXT: [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 10 -; IS________NPM-NEXT: br i1 [[TMP10]], label [[TMP2:%.*]], label [[TMP3]] +; IS__CGSCC_NPM: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly uwtable willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@loop_constant_trip_count +; IS__CGSCC_NPM-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[TMP0:%.*]]) +; IS__CGSCC_NPM-NEXT: br label [[TMP3:%.*]] +; IS__CGSCC_NPM: 2: +; IS__CGSCC_NPM-NEXT: ret i32 [[TMP8:%.*]] +; IS__CGSCC_NPM: 3: +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = phi i64 [ 0, [[TMP1:%.*]] ], [ [[TMP9:%.*]], [[TMP3]] ] +; IS__CGSCC_NPM-NEXT: [[TMP5:%.*]] = phi i32 [ 0, [[TMP1]] ], [ [[TMP8]], [[TMP3]] ] +; IS__CGSCC_NPM-NEXT: [[TMP6:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 [[TMP4]] +; IS__CGSCC_NPM-NEXT: [[TMP7:%.*]] = load i32, i32* [[TMP6]], align 4 +; IS__CGSCC_NPM-NEXT: [[TMP8]] = add nsw i32 [[TMP7]], [[TMP5]] +; IS__CGSCC_NPM-NEXT: [[TMP9]] = add nuw nsw i64 [[TMP4]], 1 +; IS__CGSCC_NPM-NEXT: [[TMP10:%.*]] = icmp eq i64 [[TMP9]], 10 +; IS__CGSCC_NPM-NEXT: br i1 [[TMP10]], label [[TMP2:%.*]], label [[TMP3]] ; br label %3 @@ -483,27 +596,44 @@ ; } ; return ans; ; } +define i32 @loop_trip_count_unbound(i32 %0, i32 %1, i32* nocapture readonly %2, i32 %3) local_unnamed_addr #0 { ; IS__TUNIT____: Function Attrs: argmemonly nofree noinline nosync nounwind readonly uwtable +; IS__TUNIT____-LABEL: define {{[^@]+}}@loop_trip_count_unbound +; IS__TUNIT____-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]], i32* nocapture nofree readonly [[TMP2:%.*]], i32 [[TMP3:%.*]]) local_unnamed_addr +; IS__TUNIT____-NEXT: [[TMP5:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] +; IS__TUNIT____-NEXT: br i1 [[TMP5]], label [[TMP6:%.*]], label [[TMP8:%.*]] +; IS__TUNIT____: 6: +; IS__TUNIT____-NEXT: [[TMP7:%.*]] = phi i32 [ 0, [[TMP4:%.*]] ], [ [[TMP14:%.*]], [[TMP8]] ] +; IS__TUNIT____-NEXT: ret i32 [[TMP7]] +; IS__TUNIT____: 8: +; IS__TUNIT____-NEXT: [[TMP9:%.*]] = phi i32 [ [[TMP15:%.*]], [[TMP8]] ], [ [[TMP0]], [[TMP4]] ] +; IS__TUNIT____-NEXT: [[TMP10:%.*]] = phi i32 [ [[TMP14]], [[TMP8]] ], [ 0, [[TMP4]] ] +; IS__TUNIT____-NEXT: [[TMP11:%.*]] = zext i32 [[TMP9]] to i64 +; IS__TUNIT____-NEXT: [[TMP12:%.*]] = getelementptr inbounds i32, i32* [[TMP2]], i64 [[TMP11]] +; IS__TUNIT____-NEXT: [[TMP13:%.*]] = load i32, i32* [[TMP12]], align 4 +; IS__TUNIT____-NEXT: [[TMP14]] = add nsw i32 [[TMP13]], [[TMP10]] +; IS__TUNIT____-NEXT: [[TMP15]] = add i32 [[TMP9]], [[TMP3]] +; IS__TUNIT____-NEXT: [[TMP16:%.*]] = icmp eq i32 [[TMP15]], [[TMP1]] +; IS__TUNIT____-NEXT: br i1 [[TMP16]], label [[TMP6]], label [[TMP8]] +; ; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly uwtable -; CHECK-NOT: willreturn -define i32 @loop_trip_count_unbound(i32 %0, i32 %1, i32* nocapture readonly %2, i32 %3) local_unnamed_addr #0 { -; CHECK-LABEL: define {{[^@]+}}@loop_trip_count_unbound -; CHECK-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]], i32* nocapture nofree readonly [[TMP2:%.*]], i32 [[TMP3:%.*]]) local_unnamed_addr -; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] -; CHECK-NEXT: br i1 [[TMP5]], label [[TMP6:%.*]], label [[TMP8:%.*]] -; CHECK: 6: -; CHECK-NEXT: [[TMP7:%.*]] = phi i32 [ 0, [[TMP4:%.*]] ], [ [[TMP14:%.*]], [[TMP8]] ] -; CHECK-NEXT: ret i32 [[TMP7]] -; CHECK: 8: -; CHECK-NEXT: [[TMP9:%.*]] = phi i32 [ [[TMP15:%.*]], [[TMP8]] ], [ [[TMP0]], [[TMP4]] ] -; CHECK-NEXT: [[TMP10:%.*]] = phi i32 [ [[TMP14]], [[TMP8]] ], [ 0, [[TMP4]] ] -; CHECK-NEXT: [[TMP11:%.*]] = zext i32 [[TMP9]] to i64 -; CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds i32, i32* [[TMP2]], i64 [[TMP11]] -; CHECK-NEXT: [[TMP13:%.*]] = load i32, i32* [[TMP12]], align 4 -; CHECK-NEXT: [[TMP14]] = add nsw i32 [[TMP13]], [[TMP10]] -; CHECK-NEXT: [[TMP15]] = add i32 [[TMP9]], [[TMP3]] -; CHECK-NEXT: [[TMP16:%.*]] = icmp eq i32 [[TMP15]], [[TMP1]] -; CHECK-NEXT: br i1 [[TMP16]], label [[TMP6]], label [[TMP8]] +; IS__CGSCC____-LABEL: define {{[^@]+}}@loop_trip_count_unbound +; IS__CGSCC____-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]], i32* nocapture nofree readonly [[TMP2:%.*]], i32 [[TMP3:%.*]]) local_unnamed_addr +; IS__CGSCC____-NEXT: [[TMP5:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] +; IS__CGSCC____-NEXT: br i1 [[TMP5]], label [[TMP6:%.*]], label [[TMP8:%.*]] +; IS__CGSCC____: 6: +; IS__CGSCC____-NEXT: [[TMP7:%.*]] = phi i32 [ 0, [[TMP4:%.*]] ], [ [[TMP14:%.*]], [[TMP8]] ] +; IS__CGSCC____-NEXT: ret i32 [[TMP7]] +; IS__CGSCC____: 8: +; IS__CGSCC____-NEXT: [[TMP9:%.*]] = phi i32 [ [[TMP15:%.*]], [[TMP8]] ], [ [[TMP0]], [[TMP4]] ] +; IS__CGSCC____-NEXT: [[TMP10:%.*]] = phi i32 [ [[TMP14]], [[TMP8]] ], [ 0, [[TMP4]] ] +; IS__CGSCC____-NEXT: [[TMP11:%.*]] = zext i32 [[TMP9]] to i64 +; IS__CGSCC____-NEXT: [[TMP12:%.*]] = getelementptr inbounds i32, i32* [[TMP2]], i64 [[TMP11]] +; IS__CGSCC____-NEXT: [[TMP13:%.*]] = load i32, i32* [[TMP12]], align 4 +; IS__CGSCC____-NEXT: [[TMP14]] = add nsw i32 [[TMP13]], [[TMP10]] +; IS__CGSCC____-NEXT: [[TMP15]] = add i32 [[TMP9]], [[TMP3]] +; IS__CGSCC____-NEXT: [[TMP16:%.*]] = icmp eq i32 [[TMP15]], [[TMP1]] +; IS__CGSCC____-NEXT: br i1 [[TMP16]], label [[TMP6]], label [[TMP8]] ; %5 = icmp eq i32 %0, %1 br i1 %5, label %6, label %8 @@ -536,28 +666,90 @@ ; } -; IS__TUNIT____: Function Attrs: argmemonly nofree noinline nosync nounwind readonly uwtable -; IS__CGSCC____: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly uwtable define i32 @loop_trip_dec(i32 %0, i32* nocapture readonly %1) local_unnamed_addr #0 { -; CHECK-LABEL: define {{[^@]+}}@loop_trip_dec -; CHECK-SAME: (i32 [[TMP0:%.*]], i32* nocapture nofree readonly [[TMP1:%.*]]) local_unnamed_addr -; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP0]], -1 -; CHECK-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP14:%.*]] -; CHECK: 4: -; CHECK-NEXT: [[TMP5:%.*]] = sext i32 [[TMP0]] to i64 -; CHECK-NEXT: br label [[TMP6:%.*]] -; CHECK: 6: -; CHECK-NEXT: [[TMP7:%.*]] = phi i64 [ [[TMP5]], [[TMP4]] ], [ [[TMP12:%.*]], [[TMP6]] ] -; CHECK-NEXT: [[TMP8:%.*]] = phi i32 [ 0, [[TMP4]] ], [ [[TMP11:%.*]], [[TMP6]] ] -; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, i32* [[TMP1]], i64 [[TMP7]] -; CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* [[TMP9]], align 4 -; CHECK-NEXT: [[TMP11]] = add nsw i32 [[TMP10]], [[TMP8]] -; CHECK-NEXT: [[TMP12]] = add nsw i64 [[TMP7]], -1 -; CHECK-NEXT: [[TMP13:%.*]] = icmp sgt i64 [[TMP7]], 0 -; CHECK-NEXT: br i1 [[TMP13]], label [[TMP6]], label [[TMP14]] -; CHECK: 14: -; CHECK-NEXT: [[TMP15:%.*]] = phi i32 [ 0, [[TMP2:%.*]] ], [ [[TMP11]], [[TMP6]] ] -; CHECK-NEXT: ret i32 [[TMP15]] +; IS__TUNIT_OPM: Function Attrs: argmemonly nofree noinline nosync nounwind readonly uwtable +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@loop_trip_dec +; IS__TUNIT_OPM-SAME: (i32 [[TMP0:%.*]], i32* nocapture nofree readonly [[TMP1:%.*]]) local_unnamed_addr +; IS__TUNIT_OPM-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP0]], -1 +; IS__TUNIT_OPM-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP14:%.*]] +; IS__TUNIT_OPM: 4: +; IS__TUNIT_OPM-NEXT: [[TMP5:%.*]] = sext i32 [[TMP0]] to i64 +; IS__TUNIT_OPM-NEXT: br label [[TMP6:%.*]] +; IS__TUNIT_OPM: 6: +; IS__TUNIT_OPM-NEXT: [[TMP7:%.*]] = phi i64 [ [[TMP5]], [[TMP4]] ], [ [[TMP12:%.*]], [[TMP6]] ] +; IS__TUNIT_OPM-NEXT: [[TMP8:%.*]] = phi i32 [ 0, [[TMP4]] ], [ [[TMP11:%.*]], [[TMP6]] ] +; IS__TUNIT_OPM-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, i32* [[TMP1]], i64 [[TMP7]] +; IS__TUNIT_OPM-NEXT: [[TMP10:%.*]] = load i32, i32* [[TMP9]], align 4 +; IS__TUNIT_OPM-NEXT: [[TMP11]] = add nsw i32 [[TMP10]], [[TMP8]] +; IS__TUNIT_OPM-NEXT: [[TMP12]] = add nsw i64 [[TMP7]], -1 +; IS__TUNIT_OPM-NEXT: [[TMP13:%.*]] = icmp sgt i64 [[TMP7]], 0 +; IS__TUNIT_OPM-NEXT: br i1 [[TMP13]], label [[TMP6]], label [[TMP14]] +; IS__TUNIT_OPM: 14: +; IS__TUNIT_OPM-NEXT: [[TMP15:%.*]] = phi i32 [ 0, [[TMP2:%.*]] ], [ [[TMP11]], [[TMP6]] ] +; IS__TUNIT_OPM-NEXT: ret i32 [[TMP15]] +; +; IS__TUNIT_NPM: Function Attrs: argmemonly nofree noinline nosync nounwind readonly uwtable willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@loop_trip_dec +; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]], i32* nocapture nofree readonly [[TMP1:%.*]]) local_unnamed_addr +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP0]], -1 +; IS__TUNIT_NPM-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP14:%.*]] +; IS__TUNIT_NPM: 4: +; IS__TUNIT_NPM-NEXT: [[TMP5:%.*]] = sext i32 [[TMP0]] to i64 +; IS__TUNIT_NPM-NEXT: br label [[TMP6:%.*]] +; IS__TUNIT_NPM: 6: +; IS__TUNIT_NPM-NEXT: [[TMP7:%.*]] = phi i64 [ [[TMP5]], [[TMP4]] ], [ [[TMP12:%.*]], [[TMP6]] ] +; IS__TUNIT_NPM-NEXT: [[TMP8:%.*]] = phi i32 [ 0, [[TMP4]] ], [ [[TMP11:%.*]], [[TMP6]] ] +; IS__TUNIT_NPM-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, i32* [[TMP1]], i64 [[TMP7]] +; IS__TUNIT_NPM-NEXT: [[TMP10:%.*]] = load i32, i32* [[TMP9]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP11]] = add nsw i32 [[TMP10]], [[TMP8]] +; IS__TUNIT_NPM-NEXT: [[TMP12]] = add nsw i64 [[TMP7]], -1 +; IS__TUNIT_NPM-NEXT: [[TMP13:%.*]] = icmp sgt i64 [[TMP7]], 0 +; IS__TUNIT_NPM-NEXT: br i1 [[TMP13]], label [[TMP6]], label [[TMP14]] +; IS__TUNIT_NPM: 14: +; IS__TUNIT_NPM-NEXT: [[TMP15:%.*]] = phi i32 [ 0, [[TMP2:%.*]] ], [ [[TMP11]], [[TMP6]] ] +; IS__TUNIT_NPM-NEXT: ret i32 [[TMP15]] +; +; IS__CGSCC_OPM: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly uwtable +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@loop_trip_dec +; IS__CGSCC_OPM-SAME: (i32 [[TMP0:%.*]], i32* nocapture nofree readonly [[TMP1:%.*]]) local_unnamed_addr +; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP0]], -1 +; IS__CGSCC_OPM-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP14:%.*]] +; IS__CGSCC_OPM: 4: +; IS__CGSCC_OPM-NEXT: [[TMP5:%.*]] = sext i32 [[TMP0]] to i64 +; IS__CGSCC_OPM-NEXT: br label [[TMP6:%.*]] +; IS__CGSCC_OPM: 6: +; IS__CGSCC_OPM-NEXT: [[TMP7:%.*]] = phi i64 [ [[TMP5]], [[TMP4]] ], [ [[TMP12:%.*]], [[TMP6]] ] +; IS__CGSCC_OPM-NEXT: [[TMP8:%.*]] = phi i32 [ 0, [[TMP4]] ], [ [[TMP11:%.*]], [[TMP6]] ] +; IS__CGSCC_OPM-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, i32* [[TMP1]], i64 [[TMP7]] +; IS__CGSCC_OPM-NEXT: [[TMP10:%.*]] = load i32, i32* [[TMP9]], align 4 +; IS__CGSCC_OPM-NEXT: [[TMP11]] = add nsw i32 [[TMP10]], [[TMP8]] +; IS__CGSCC_OPM-NEXT: [[TMP12]] = add nsw i64 [[TMP7]], -1 +; IS__CGSCC_OPM-NEXT: [[TMP13:%.*]] = icmp sgt i64 [[TMP7]], 0 +; IS__CGSCC_OPM-NEXT: br i1 [[TMP13]], label [[TMP6]], label [[TMP14]] +; IS__CGSCC_OPM: 14: +; IS__CGSCC_OPM-NEXT: [[TMP15:%.*]] = phi i32 [ 0, [[TMP2:%.*]] ], [ [[TMP11]], [[TMP6]] ] +; IS__CGSCC_OPM-NEXT: ret i32 [[TMP15]] +; +; IS__CGSCC_NPM: Function Attrs: argmemonly nofree noinline norecurse nosync nounwind readonly uwtable willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@loop_trip_dec +; IS__CGSCC_NPM-SAME: (i32 [[TMP0:%.*]], i32* nocapture nofree readonly [[TMP1:%.*]]) local_unnamed_addr +; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP0]], -1 +; IS__CGSCC_NPM-NEXT: br i1 [[TMP3]], label [[TMP4:%.*]], label [[TMP14:%.*]] +; IS__CGSCC_NPM: 4: +; IS__CGSCC_NPM-NEXT: [[TMP5:%.*]] = sext i32 [[TMP0]] to i64 +; IS__CGSCC_NPM-NEXT: br label [[TMP6:%.*]] +; IS__CGSCC_NPM: 6: +; IS__CGSCC_NPM-NEXT: [[TMP7:%.*]] = phi i64 [ [[TMP5]], [[TMP4]] ], [ [[TMP12:%.*]], [[TMP6]] ] +; IS__CGSCC_NPM-NEXT: [[TMP8:%.*]] = phi i32 [ 0, [[TMP4]] ], [ [[TMP11:%.*]], [[TMP6]] ] +; IS__CGSCC_NPM-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, i32* [[TMP1]], i64 [[TMP7]] +; IS__CGSCC_NPM-NEXT: [[TMP10:%.*]] = load i32, i32* [[TMP9]], align 4 +; IS__CGSCC_NPM-NEXT: [[TMP11]] = add nsw i32 [[TMP10]], [[TMP8]] +; IS__CGSCC_NPM-NEXT: [[TMP12]] = add nsw i64 [[TMP7]], -1 +; IS__CGSCC_NPM-NEXT: [[TMP13:%.*]] = icmp sgt i64 [[TMP7]], 0 +; IS__CGSCC_NPM-NEXT: br i1 [[TMP13]], label [[TMP6]], label [[TMP14]] +; IS__CGSCC_NPM: 14: +; IS__CGSCC_NPM-NEXT: [[TMP15:%.*]] = phi i32 [ 0, [[TMP2:%.*]] ], [ [[TMP11]], [[TMP6]] ] +; IS__CGSCC_NPM-NEXT: ret i32 [[TMP15]] ; %3 = icmp sgt i32 %0, -1 br i1 %3, label %4, label %14 @@ -584,17 +776,26 @@ ; TEST 14 (positive case) ; multiple return +define i32 @multiple_return(i32 %a) #0 { ; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@multiple_return +; IS__TUNIT____-SAME: (i32 [[A:%.*]]) +; IS__TUNIT____-NEXT: [[B:%.*]] = icmp eq i32 [[A]], 0 +; IS__TUNIT____-NEXT: br i1 [[B]], label [[T:%.*]], label [[F:%.*]] +; IS__TUNIT____: t: +; IS__TUNIT____-NEXT: ret i32 1 +; IS__TUNIT____: f: +; IS__TUNIT____-NEXT: ret i32 0 +; ; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn -define i32 @multiple_return(i32 %a) #0 { -; CHECK-LABEL: define {{[^@]+}}@multiple_return -; CHECK-SAME: (i32 [[A:%.*]]) -; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[A]], 0 -; CHECK-NEXT: br i1 [[B]], label [[T:%.*]], label [[F:%.*]] -; CHECK: t: -; CHECK-NEXT: ret i32 1 -; CHECK: f: -; CHECK-NEXT: ret i32 0 +; IS__CGSCC____-LABEL: define {{[^@]+}}@multiple_return +; IS__CGSCC____-SAME: (i32 [[A:%.*]]) +; IS__CGSCC____-NEXT: [[B:%.*]] = icmp eq i32 [[A]], 0 +; IS__CGSCC____-NEXT: br i1 [[B]], label [[T:%.*]], label [[F:%.*]] +; IS__CGSCC____: t: +; IS__CGSCC____-NEXT: ret i32 1 +; IS__CGSCC____: f: +; IS__CGSCC____-NEXT: ret i32 0 ; %b = icmp eq i32 %a, 0 br i1 %b, label %t, label %f @@ -609,14 +810,20 @@ ; unreachable exit ; 15.1 (positive case) -; IS__TUNIT____: Function Attrs: noinline nounwind uwtable -; IS__CGSCC____: Function Attrs: noinline norecurse nounwind uwtable willreturn define void @unreachable_exit_positive1() #0 { -; CHECK-LABEL: define {{[^@]+}}@unreachable_exit_positive1() -; CHECK-NEXT: tail call void @will_return() -; CHECK-NEXT: ret void -; CHECK: unreachable_label: -; CHECK-NEXT: unreachable +; IS__TUNIT____: Function Attrs: noinline nounwind uwtable willreturn +; IS__TUNIT____-LABEL: define {{[^@]+}}@unreachable_exit_positive1() +; IS__TUNIT____-NEXT: tail call void @will_return() +; IS__TUNIT____-NEXT: ret void +; IS__TUNIT____: unreachable_label: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____: Function Attrs: noinline norecurse nounwind uwtable willreturn +; IS__CGSCC____-LABEL: define {{[^@]+}}@unreachable_exit_positive1() +; IS__CGSCC____-NEXT: tail call void @will_return() +; IS__CGSCC____-NEXT: ret void +; IS__CGSCC____: unreachable_label: +; IS__CGSCC____-NEXT: unreachable ; tail call void @will_return() ret void @@ -626,25 +833,78 @@ unreachable } -; IS__TUNIT____: Function Attrs: nofree noinline nosync nounwind readnone uwtable -; IS__CGSCC____: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable define i32 @unreachable_exit_positive2(i32) local_unnamed_addr #0 { -; CHECK-LABEL: define {{[^@]+}}@unreachable_exit_positive2 -; CHECK-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr -; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP0]], 1 -; CHECK-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] -; CHECK: 3: -; CHECK-NEXT: [[TMP4:%.*]] = phi i32 [ 1, [[TMP1:%.*]] ], [ [[TMP8:%.*]], [[TMP5]] ] -; CHECK-NEXT: ret i32 [[TMP4]] -; CHECK: 5: -; CHECK-NEXT: [[TMP6:%.*]] = phi i32 [ [[TMP9:%.*]], [[TMP5]] ], [ 1, [[TMP1]] ] -; CHECK-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8]], [[TMP5]] ], [ 1, [[TMP1]] ] -; CHECK-NEXT: [[TMP8]] = mul nsw i32 [[TMP6]], [[TMP7]] -; CHECK-NEXT: [[TMP9]] = add nuw nsw i32 [[TMP6]], 1 -; CHECK-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP6]], [[TMP0]] -; CHECK-NEXT: br i1 [[TMP10]], label [[TMP3]], label [[TMP5]] -; CHECK: unreachable_label: -; CHECK-NEXT: unreachable +; IS__TUNIT_OPM: Function Attrs: nofree noinline nosync nounwind readnone uwtable +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@unreachable_exit_positive2 +; IS__TUNIT_OPM-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP0]], 1 +; IS__TUNIT_OPM-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] +; IS__TUNIT_OPM: 3: +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = phi i32 [ 1, [[TMP1:%.*]] ], [ [[TMP8:%.*]], [[TMP5]] ] +; IS__TUNIT_OPM-NEXT: ret i32 [[TMP4]] +; IS__TUNIT_OPM: 5: +; IS__TUNIT_OPM-NEXT: [[TMP6:%.*]] = phi i32 [ [[TMP9:%.*]], [[TMP5]] ], [ 1, [[TMP1]] ] +; IS__TUNIT_OPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8]], [[TMP5]] ], [ 1, [[TMP1]] ] +; IS__TUNIT_OPM-NEXT: [[TMP8]] = mul nsw i32 [[TMP6]], [[TMP7]] +; IS__TUNIT_OPM-NEXT: [[TMP9]] = add nuw nsw i32 [[TMP6]], 1 +; IS__TUNIT_OPM-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP6]], [[TMP0]] +; IS__TUNIT_OPM-NEXT: br i1 [[TMP10]], label [[TMP3]], label [[TMP5]] +; IS__TUNIT_OPM: unreachable_label: +; IS__TUNIT_OPM-NEXT: unreachable +; +; IS__TUNIT_NPM: Function Attrs: nofree noinline nosync nounwind readnone uwtable willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@unreachable_exit_positive2 +; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP0]], 1 +; IS__TUNIT_NPM-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] +; IS__TUNIT_NPM: 3: +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = phi i32 [ 1, [[TMP1:%.*]] ], [ [[TMP8:%.*]], [[TMP5]] ] +; IS__TUNIT_NPM-NEXT: ret i32 [[TMP4]] +; IS__TUNIT_NPM: 5: +; IS__TUNIT_NPM-NEXT: [[TMP6:%.*]] = phi i32 [ [[TMP9:%.*]], [[TMP5]] ], [ 1, [[TMP1]] ] +; IS__TUNIT_NPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8]], [[TMP5]] ], [ 1, [[TMP1]] ] +; IS__TUNIT_NPM-NEXT: [[TMP8]] = mul nsw i32 [[TMP6]], [[TMP7]] +; IS__TUNIT_NPM-NEXT: [[TMP9]] = add nuw nsw i32 [[TMP6]], 1 +; IS__TUNIT_NPM-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP6]], [[TMP0]] +; IS__TUNIT_NPM-NEXT: br i1 [[TMP10]], label [[TMP3]], label [[TMP5]] +; IS__TUNIT_NPM: unreachable_label: +; IS__TUNIT_NPM-NEXT: unreachable +; +; IS__CGSCC_OPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@unreachable_exit_positive2 +; IS__CGSCC_OPM-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP0]], 1 +; IS__CGSCC_OPM-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] +; IS__CGSCC_OPM: 3: +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = phi i32 [ 1, [[TMP1:%.*]] ], [ [[TMP8:%.*]], [[TMP5]] ] +; IS__CGSCC_OPM-NEXT: ret i32 [[TMP4]] +; IS__CGSCC_OPM: 5: +; IS__CGSCC_OPM-NEXT: [[TMP6:%.*]] = phi i32 [ [[TMP9:%.*]], [[TMP5]] ], [ 1, [[TMP1]] ] +; IS__CGSCC_OPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8]], [[TMP5]] ], [ 1, [[TMP1]] ] +; IS__CGSCC_OPM-NEXT: [[TMP8]] = mul nsw i32 [[TMP6]], [[TMP7]] +; IS__CGSCC_OPM-NEXT: [[TMP9]] = add nuw nsw i32 [[TMP6]], 1 +; IS__CGSCC_OPM-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP6]], [[TMP0]] +; IS__CGSCC_OPM-NEXT: br i1 [[TMP10]], label [[TMP3]], label [[TMP5]] +; IS__CGSCC_OPM: unreachable_label: +; IS__CGSCC_OPM-NEXT: unreachable +; +; IS__CGSCC_NPM: Function Attrs: nofree noinline norecurse nosync nounwind readnone uwtable willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@unreachable_exit_positive2 +; IS__CGSCC_NPM-SAME: (i32 [[TMP0:%.*]]) local_unnamed_addr +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = icmp slt i32 [[TMP0]], 1 +; IS__CGSCC_NPM-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] +; IS__CGSCC_NPM: 3: +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = phi i32 [ 1, [[TMP1:%.*]] ], [ [[TMP8:%.*]], [[TMP5]] ] +; IS__CGSCC_NPM-NEXT: ret i32 [[TMP4]] +; IS__CGSCC_NPM: 5: +; IS__CGSCC_NPM-NEXT: [[TMP6:%.*]] = phi i32 [ [[TMP9:%.*]], [[TMP5]] ], [ 1, [[TMP1]] ] +; IS__CGSCC_NPM-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP8]], [[TMP5]] ], [ 1, [[TMP1]] ] +; IS__CGSCC_NPM-NEXT: [[TMP8]] = mul nsw i32 [[TMP6]], [[TMP7]] +; IS__CGSCC_NPM-NEXT: [[TMP9]] = add nuw nsw i32 [[TMP6]], 1 +; IS__CGSCC_NPM-NEXT: [[TMP10:%.*]] = icmp eq i32 [[TMP6]], [[TMP0]] +; IS__CGSCC_NPM-NEXT: br i1 [[TMP10]], label [[TMP3]], label [[TMP5]] +; IS__CGSCC_NPM: unreachable_label: +; IS__CGSCC_NPM-NEXT: unreachable ; %2 = icmp slt i32 %0, 1 br i1 %2, label %3, label %5 @@ -669,9 +929,8 @@ ;15.2 -; CHECK: Function Attrs: noinline noreturn nounwind uwtable -; CHECK-NOT: willreturn define void @unreachable_exit_negative1() #0 { +; CHECK: Function Attrs: noinline noreturn nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@unreachable_exit_negative1() ; CHECK-NEXT: tail call void @exit(i32 0) ; CHECK-NEXT: unreachable @@ -686,18 +945,26 @@ unreachable } +define void @unreachable_exit_negative2() #0 { ; IS__TUNIT____: Function Attrs: nofree noinline noreturn nosync nounwind readnone uwtable +; IS__TUNIT____-LABEL: define {{[^@]+}}@unreachable_exit_negative2() +; IS__TUNIT____-NEXT: br label [[L1:%.*]] +; IS__TUNIT____: L1: +; IS__TUNIT____-NEXT: br label [[L2:%.*]] +; IS__TUNIT____: L2: +; IS__TUNIT____-NEXT: br label [[L1]] +; IS__TUNIT____: unreachable_label: +; IS__TUNIT____-NEXT: unreachable +; ; IS__CGSCC____: Function Attrs: nofree noinline norecurse noreturn nosync nounwind readnone uwtable -; CHECK-NOT: willreturn -define void @unreachable_exit_negative2() #0 { -; CHECK-LABEL: define {{[^@]+}}@unreachable_exit_negative2() -; CHECK-NEXT: br label [[L1:%.*]] -; CHECK: L1: -; CHECK-NEXT: br label [[L2:%.*]] -; CHECK: L2: -; CHECK-NEXT: br label [[L1]] -; CHECK: unreachable_label: -; CHECK-NEXT: unreachable +; IS__CGSCC____-LABEL: define {{[^@]+}}@unreachable_exit_negative2() +; IS__CGSCC____-NEXT: br label [[L1:%.*]] +; IS__CGSCC____: L1: +; IS__CGSCC____-NEXT: br label [[L2:%.*]] +; IS__CGSCC____: L2: +; IS__CGSCC____-NEXT: br label [[L1]] +; IS__CGSCC____: unreachable_label: +; IS__CGSCC____-NEXT: unreachable ; br label %L1 L1: @@ -714,9 +981,8 @@ ; CHECK-NEXT: declare void @llvm.eh.sjlj.longjmp(i8*) declare void @llvm.eh.sjlj.longjmp(i8*) -; CHECK: Function Attrs: noinline noreturn nounwind uwtable -; CHECK-NOT: willreturn define void @call_longjmp(i8* nocapture readnone %0) local_unnamed_addr #0 { +; CHECK: Function Attrs: noinline noreturn nounwind uwtable ; CHECK-LABEL: define {{[^@]+}}@call_longjmp ; CHECK-SAME: (i8* nocapture readnone [[TMP0:%.*]]) local_unnamed_addr ; CHECK-NEXT: tail call void @llvm.eh.sjlj.longjmp(i8* noalias readnone [[TMP0]]) @@ -737,29 +1003,48 @@ ; return ans; ; } +define i32 @infinite_loop_inside_bounded_loop(i32 %n) { ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone +; IS__TUNIT____-LABEL: define {{[^@]+}}@infinite_loop_inside_bounded_loop +; IS__TUNIT____-SAME: (i32 [[N:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: br label [[FOR_COND:%.*]] +; IS__TUNIT____: for.cond: +; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N]], 0 +; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; IS__TUNIT____: for.cond.cleanup: +; IS__TUNIT____-NEXT: br label [[FOR_END:%.*]] +; IS__TUNIT____: for.body: +; IS__TUNIT____-NEXT: br label [[WHILE_COND:%.*]] +; IS__TUNIT____: while.cond: +; IS__TUNIT____-NEXT: br label [[WHILE_BODY:%.*]] +; IS__TUNIT____: while.body: +; IS__TUNIT____-NEXT: br label [[WHILE_COND]] +; IS__TUNIT____: for.inc: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: for.end: +; IS__TUNIT____-NEXT: ret i32 0 +; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone -; CHECK-NOT: willreturn -define i32 @infinite_loop_inside_bounded_loop(i32 %n) { -; CHECK-LABEL: define {{[^@]+}}@infinite_loop_inside_bounded_loop -; CHECK-SAME: (i32 [[N:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[FOR_COND:%.*]] -; CHECK: for.cond: -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N]], 0 -; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]] -; CHECK: for.cond.cleanup: -; CHECK-NEXT: br label [[FOR_END:%.*]] -; CHECK: for.body: -; CHECK-NEXT: br label [[WHILE_COND:%.*]] -; CHECK: while.cond: -; CHECK-NEXT: br label [[WHILE_BODY:%.*]] -; CHECK: while.body: -; CHECK-NEXT: br label [[WHILE_COND]] -; CHECK: for.inc: -; CHECK-NEXT: unreachable -; CHECK: for.end: -; CHECK-NEXT: ret i32 0 +; IS__CGSCC____-LABEL: define {{[^@]+}}@infinite_loop_inside_bounded_loop +; IS__CGSCC____-SAME: (i32 [[N:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br label [[FOR_COND:%.*]] +; IS__CGSCC____: for.cond: +; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[N]], 0 +; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; IS__CGSCC____: for.cond.cleanup: +; IS__CGSCC____-NEXT: br label [[FOR_END:%.*]] +; IS__CGSCC____: for.body: +; IS__CGSCC____-NEXT: br label [[WHILE_COND:%.*]] +; IS__CGSCC____: while.cond: +; IS__CGSCC____-NEXT: br label [[WHILE_BODY:%.*]] +; IS__CGSCC____: while.body: +; IS__CGSCC____-NEXT: br label [[WHILE_COND]] +; IS__CGSCC____: for.inc: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: for.end: +; IS__CGSCC____-NEXT: ret i32 0 ; entry: br label %for.cond @@ -800,36 +1085,122 @@ ; return ans; ; } -; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone -; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone define i32 @bounded_nested_loops(i32 %n) { -; CHECK-LABEL: define {{[^@]+}}@bounded_nested_loops -; CHECK-SAME: (i32 [[N:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[FOR_COND:%.*]] -; CHECK: for.cond: -; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC1:%.*]], [[FOR_INC:%.*]] ] -; CHECK-NEXT: [[ANS_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[TMP:%.*]], [[FOR_INC]] ] -; CHECK-NEXT: [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ -1, [[FOR_INC]] ] -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], [[N_ADDR_0]] -; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]] -; CHECK: for.cond.cleanup: -; CHECK-NEXT: [[ANS_0_LCSSA:%.*]] = phi i32 [ [[ANS_0]], [[FOR_COND]] ] -; CHECK-NEXT: br label [[FOR_END:%.*]] -; CHECK: for.body: -; CHECK-NEXT: br label [[WHILE_COND:%.*]] -; CHECK: while.cond: -; CHECK-NEXT: br i1 true, label [[WHILE_END:%.*]], label [[WHILE_BODY:%.*]] -; CHECK: while.body: -; CHECK-NEXT: unreachable -; CHECK: while.end: -; CHECK-NEXT: [[TMP]] = add i32 [[N_ADDR_0]], [[ANS_0]] -; CHECK-NEXT: br label [[FOR_INC]] -; CHECK: for.inc: -; CHECK-NEXT: [[INC1]] = add nuw nsw i32 [[I_0]], 1 -; CHECK-NEXT: br label [[FOR_COND]] -; CHECK: for.end: -; CHECK-NEXT: ret i32 [[ANS_0_LCSSA]] +; IS__TUNIT_OPM: Function Attrs: nofree nosync nounwind readnone +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@bounded_nested_loops +; IS__TUNIT_OPM-SAME: (i32 [[N:%.*]]) +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: br label [[FOR_COND:%.*]] +; IS__TUNIT_OPM: for.cond: +; IS__TUNIT_OPM-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC1:%.*]], [[FOR_INC:%.*]] ] +; IS__TUNIT_OPM-NEXT: [[ANS_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[TMP:%.*]], [[FOR_INC]] ] +; IS__TUNIT_OPM-NEXT: [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ -1, [[FOR_INC]] ] +; IS__TUNIT_OPM-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], [[N_ADDR_0]] +; IS__TUNIT_OPM-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; IS__TUNIT_OPM: for.cond.cleanup: +; IS__TUNIT_OPM-NEXT: [[ANS_0_LCSSA:%.*]] = phi i32 [ [[ANS_0]], [[FOR_COND]] ] +; IS__TUNIT_OPM-NEXT: br label [[FOR_END:%.*]] +; IS__TUNIT_OPM: for.body: +; IS__TUNIT_OPM-NEXT: br label [[WHILE_COND:%.*]] +; IS__TUNIT_OPM: while.cond: +; IS__TUNIT_OPM-NEXT: br i1 true, label [[WHILE_END:%.*]], label [[WHILE_BODY:%.*]] +; IS__TUNIT_OPM: while.body: +; IS__TUNIT_OPM-NEXT: unreachable +; IS__TUNIT_OPM: while.end: +; IS__TUNIT_OPM-NEXT: [[TMP]] = add i32 [[N_ADDR_0]], [[ANS_0]] +; IS__TUNIT_OPM-NEXT: br label [[FOR_INC]] +; IS__TUNIT_OPM: for.inc: +; IS__TUNIT_OPM-NEXT: [[INC1]] = add nuw nsw i32 [[I_0]], 1 +; IS__TUNIT_OPM-NEXT: br label [[FOR_COND]] +; IS__TUNIT_OPM: for.end: +; IS__TUNIT_OPM-NEXT: ret i32 [[ANS_0_LCSSA]] +; +; IS__TUNIT_NPM: Function Attrs: nofree nosync nounwind readnone willreturn +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@bounded_nested_loops +; IS__TUNIT_NPM-SAME: (i32 [[N:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: br label [[FOR_COND:%.*]] +; IS__TUNIT_NPM: for.cond: +; IS__TUNIT_NPM-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC1:%.*]], [[FOR_INC:%.*]] ] +; IS__TUNIT_NPM-NEXT: [[ANS_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[TMP:%.*]], [[FOR_INC]] ] +; IS__TUNIT_NPM-NEXT: [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ -1, [[FOR_INC]] ] +; IS__TUNIT_NPM-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], [[N_ADDR_0]] +; IS__TUNIT_NPM-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; IS__TUNIT_NPM: for.cond.cleanup: +; IS__TUNIT_NPM-NEXT: [[ANS_0_LCSSA:%.*]] = phi i32 [ [[ANS_0]], [[FOR_COND]] ] +; IS__TUNIT_NPM-NEXT: br label [[FOR_END:%.*]] +; IS__TUNIT_NPM: for.body: +; IS__TUNIT_NPM-NEXT: br label [[WHILE_COND:%.*]] +; IS__TUNIT_NPM: while.cond: +; IS__TUNIT_NPM-NEXT: br i1 true, label [[WHILE_END:%.*]], label [[WHILE_BODY:%.*]] +; IS__TUNIT_NPM: while.body: +; IS__TUNIT_NPM-NEXT: unreachable +; IS__TUNIT_NPM: while.end: +; IS__TUNIT_NPM-NEXT: [[TMP]] = add i32 [[N_ADDR_0]], [[ANS_0]] +; IS__TUNIT_NPM-NEXT: br label [[FOR_INC]] +; IS__TUNIT_NPM: for.inc: +; IS__TUNIT_NPM-NEXT: [[INC1]] = add nuw nsw i32 [[I_0]], 1 +; IS__TUNIT_NPM-NEXT: br label [[FOR_COND]] +; IS__TUNIT_NPM: for.end: +; IS__TUNIT_NPM-NEXT: ret i32 [[ANS_0_LCSSA]] +; +; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@bounded_nested_loops +; IS__CGSCC_OPM-SAME: (i32 [[N:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: br label [[FOR_COND:%.*]] +; IS__CGSCC_OPM: for.cond: +; IS__CGSCC_OPM-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC1:%.*]], [[FOR_INC:%.*]] ] +; IS__CGSCC_OPM-NEXT: [[ANS_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[TMP:%.*]], [[FOR_INC]] ] +; IS__CGSCC_OPM-NEXT: [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ -1, [[FOR_INC]] ] +; IS__CGSCC_OPM-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], [[N_ADDR_0]] +; IS__CGSCC_OPM-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; IS__CGSCC_OPM: for.cond.cleanup: +; IS__CGSCC_OPM-NEXT: [[ANS_0_LCSSA:%.*]] = phi i32 [ [[ANS_0]], [[FOR_COND]] ] +; IS__CGSCC_OPM-NEXT: br label [[FOR_END:%.*]] +; IS__CGSCC_OPM: for.body: +; IS__CGSCC_OPM-NEXT: br label [[WHILE_COND:%.*]] +; IS__CGSCC_OPM: while.cond: +; IS__CGSCC_OPM-NEXT: br i1 true, label [[WHILE_END:%.*]], label [[WHILE_BODY:%.*]] +; IS__CGSCC_OPM: while.body: +; IS__CGSCC_OPM-NEXT: unreachable +; IS__CGSCC_OPM: while.end: +; IS__CGSCC_OPM-NEXT: [[TMP]] = add i32 [[N_ADDR_0]], [[ANS_0]] +; IS__CGSCC_OPM-NEXT: br label [[FOR_INC]] +; IS__CGSCC_OPM: for.inc: +; IS__CGSCC_OPM-NEXT: [[INC1]] = add nuw nsw i32 [[I_0]], 1 +; IS__CGSCC_OPM-NEXT: br label [[FOR_COND]] +; IS__CGSCC_OPM: for.end: +; IS__CGSCC_OPM-NEXT: ret i32 [[ANS_0_LCSSA]] +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@bounded_nested_loops +; IS__CGSCC_NPM-SAME: (i32 [[N:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: br label [[FOR_COND:%.*]] +; IS__CGSCC_NPM: for.cond: +; IS__CGSCC_NPM-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC1:%.*]], [[FOR_INC:%.*]] ] +; IS__CGSCC_NPM-NEXT: [[ANS_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[TMP:%.*]], [[FOR_INC]] ] +; IS__CGSCC_NPM-NEXT: [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ -1, [[FOR_INC]] ] +; IS__CGSCC_NPM-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], [[N_ADDR_0]] +; IS__CGSCC_NPM-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; IS__CGSCC_NPM: for.cond.cleanup: +; IS__CGSCC_NPM-NEXT: [[ANS_0_LCSSA:%.*]] = phi i32 [ [[ANS_0]], [[FOR_COND]] ] +; IS__CGSCC_NPM-NEXT: br label [[FOR_END:%.*]] +; IS__CGSCC_NPM: for.body: +; IS__CGSCC_NPM-NEXT: br label [[WHILE_COND:%.*]] +; IS__CGSCC_NPM: while.cond: +; IS__CGSCC_NPM-NEXT: br i1 true, label [[WHILE_END:%.*]], label [[WHILE_BODY:%.*]] +; IS__CGSCC_NPM: while.body: +; IS__CGSCC_NPM-NEXT: unreachable +; IS__CGSCC_NPM: while.end: +; IS__CGSCC_NPM-NEXT: [[TMP]] = add i32 [[N_ADDR_0]], [[ANS_0]] +; IS__CGSCC_NPM-NEXT: br label [[FOR_INC]] +; IS__CGSCC_NPM: for.inc: +; IS__CGSCC_NPM-NEXT: [[INC1]] = add nuw nsw i32 [[I_0]], 1 +; IS__CGSCC_NPM-NEXT: br label [[FOR_COND]] +; IS__CGSCC_NPM: for.end: +; IS__CGSCC_NPM-NEXT: ret i32 [[ANS_0_LCSSA]] ; entry: br label %for.cond @@ -878,39 +1249,68 @@ ; return ans; ; } +define i32 @bounded_loop_inside_unbounded_loop(i32 %n) { ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone +; IS__TUNIT____-LABEL: define {{[^@]+}}@bounded_loop_inside_unbounded_loop +; IS__TUNIT____-SAME: (i32 [[N:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: br label [[WHILE_COND:%.*]] +; IS__TUNIT____: while.cond: +; IS__TUNIT____-NEXT: [[ANS_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2:%.*]], [[FOR_END:%.*]] ] +; IS__TUNIT____-NEXT: [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ [[INC:%.*]], [[FOR_END]] ] +; IS__TUNIT____-NEXT: [[TMP:%.*]] = icmp sgt i32 [[N_ADDR_0]], -1 +; IS__TUNIT____-NEXT: [[SMAX:%.*]] = select i1 [[TMP]], i32 [[N_ADDR_0]], i32 -1 +; IS__TUNIT____-NEXT: [[INC]] = add nsw i32 [[N_ADDR_0]], 1 +; IS__TUNIT____-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[N_ADDR_0]], 0 +; IS__TUNIT____-NEXT: br i1 [[TOBOOL]], label [[WHILE_END:%.*]], label [[WHILE_BODY:%.*]] +; IS__TUNIT____: while.body: +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = add i32 [[ANS_0]], 1 +; IS__TUNIT____-NEXT: br label [[FOR_COND:%.*]] +; IS__TUNIT____: for.cond: +; IS__TUNIT____-NEXT: br i1 true, label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY:%.*]] +; IS__TUNIT____: for.cond.cleanup: +; IS__TUNIT____-NEXT: [[TMP2]] = add i32 [[TMP1]], [[SMAX]] +; IS__TUNIT____-NEXT: br label [[FOR_END]] +; IS__TUNIT____: for.body: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: for.inc: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: for.end: +; IS__TUNIT____-NEXT: br label [[WHILE_COND]] +; IS__TUNIT____: while.end: +; IS__TUNIT____-NEXT: [[ANS_0_LCSSA:%.*]] = phi i32 [ [[ANS_0]], [[WHILE_COND]] ] +; IS__TUNIT____-NEXT: ret i32 [[ANS_0_LCSSA]] +; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone -; CHECK-NOT: willreturn -define i32 @bounded_loop_inside_unbounded_loop(i32 %n) { -; CHECK-LABEL: define {{[^@]+}}@bounded_loop_inside_unbounded_loop -; CHECK-SAME: (i32 [[N:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[WHILE_COND:%.*]] -; CHECK: while.cond: -; CHECK-NEXT: [[ANS_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2:%.*]], [[FOR_END:%.*]] ] -; CHECK-NEXT: [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ [[INC:%.*]], [[FOR_END]] ] -; CHECK-NEXT: [[TMP:%.*]] = icmp sgt i32 [[N_ADDR_0]], -1 -; CHECK-NEXT: [[SMAX:%.*]] = select i1 [[TMP]], i32 [[N_ADDR_0]], i32 -1 -; CHECK-NEXT: [[INC]] = add nsw i32 [[N_ADDR_0]], 1 -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[N_ADDR_0]], 0 -; CHECK-NEXT: br i1 [[TOBOOL]], label [[WHILE_END:%.*]], label [[WHILE_BODY:%.*]] -; CHECK: while.body: -; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[ANS_0]], 1 -; CHECK-NEXT: br label [[FOR_COND:%.*]] -; CHECK: for.cond: -; CHECK-NEXT: br i1 true, label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY:%.*]] -; CHECK: for.cond.cleanup: -; CHECK-NEXT: [[TMP2]] = add i32 [[TMP1]], [[SMAX]] -; CHECK-NEXT: br label [[FOR_END]] -; CHECK: for.body: -; CHECK-NEXT: unreachable -; CHECK: for.inc: -; CHECK-NEXT: unreachable -; CHECK: for.end: -; CHECK-NEXT: br label [[WHILE_COND]] -; CHECK: while.end: -; CHECK-NEXT: [[ANS_0_LCSSA:%.*]] = phi i32 [ [[ANS_0]], [[WHILE_COND]] ] -; CHECK-NEXT: ret i32 [[ANS_0_LCSSA]] +; IS__CGSCC____-LABEL: define {{[^@]+}}@bounded_loop_inside_unbounded_loop +; IS__CGSCC____-SAME: (i32 [[N:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br label [[WHILE_COND:%.*]] +; IS__CGSCC____: while.cond: +; IS__CGSCC____-NEXT: [[ANS_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP2:%.*]], [[FOR_END:%.*]] ] +; IS__CGSCC____-NEXT: [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ [[INC:%.*]], [[FOR_END]] ] +; IS__CGSCC____-NEXT: [[TMP:%.*]] = icmp sgt i32 [[N_ADDR_0]], -1 +; IS__CGSCC____-NEXT: [[SMAX:%.*]] = select i1 [[TMP]], i32 [[N_ADDR_0]], i32 -1 +; IS__CGSCC____-NEXT: [[INC]] = add nsw i32 [[N_ADDR_0]], 1 +; IS__CGSCC____-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[N_ADDR_0]], 0 +; IS__CGSCC____-NEXT: br i1 [[TOBOOL]], label [[WHILE_END:%.*]], label [[WHILE_BODY:%.*]] +; IS__CGSCC____: while.body: +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = add i32 [[ANS_0]], 1 +; IS__CGSCC____-NEXT: br label [[FOR_COND:%.*]] +; IS__CGSCC____: for.cond: +; IS__CGSCC____-NEXT: br i1 true, label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY:%.*]] +; IS__CGSCC____: for.cond.cleanup: +; IS__CGSCC____-NEXT: [[TMP2]] = add i32 [[TMP1]], [[SMAX]] +; IS__CGSCC____-NEXT: br label [[FOR_END]] +; IS__CGSCC____: for.body: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: for.inc: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: for.end: +; IS__CGSCC____-NEXT: br label [[WHILE_COND]] +; IS__CGSCC____: while.end: +; IS__CGSCC____-NEXT: [[ANS_0_LCSSA:%.*]] = phi i32 [ [[ANS_0]], [[WHILE_COND]] ] +; IS__CGSCC____-NEXT: ret i32 [[ANS_0_LCSSA]] ; entry: br label %while.cond @@ -964,38 +1364,66 @@ ; return ans; ; } +define i32 @nested_unbounded_loops(i32 %n) { ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone +; IS__TUNIT____-LABEL: define {{[^@]+}}@nested_unbounded_loops +; IS__TUNIT____-SAME: (i32 [[N:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: br label [[WHILE_COND:%.*]] +; IS__TUNIT____: while.cond: +; IS__TUNIT____-NEXT: [[ANS_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP1:%.*]], [[WHILE_END10:%.*]] ] +; IS__TUNIT____-NEXT: [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ -1, [[WHILE_END10]] ] +; IS__TUNIT____-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[N_ADDR_0]], 0 +; IS__TUNIT____-NEXT: br i1 [[TOBOOL]], label [[WHILE_END11:%.*]], label [[WHILE_BODY:%.*]] +; IS__TUNIT____: while.body: +; IS__TUNIT____-NEXT: br label [[WHILE_COND1:%.*]] +; IS__TUNIT____: while.cond1: +; IS__TUNIT____-NEXT: br i1 true, label [[WHILE_END:%.*]], label [[WHILE_BODY4:%.*]] +; IS__TUNIT____: while.body4: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: while.end: +; IS__TUNIT____-NEXT: [[TMP:%.*]] = add i32 [[N_ADDR_0]], -2 +; IS__TUNIT____-NEXT: br label [[WHILE_COND5:%.*]] +; IS__TUNIT____: while.cond5: +; IS__TUNIT____-NEXT: br i1 true, label [[WHILE_END10]], label [[WHILE_BODY8:%.*]] +; IS__TUNIT____: while.body8: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: while.end10: +; IS__TUNIT____-NEXT: [[TMP1]] = add i32 [[TMP]], [[ANS_0]] +; IS__TUNIT____-NEXT: br label [[WHILE_COND]] +; IS__TUNIT____: while.end11: +; IS__TUNIT____-NEXT: [[ANS_0_LCSSA:%.*]] = phi i32 [ [[ANS_0]], [[WHILE_COND]] ] +; IS__TUNIT____-NEXT: ret i32 [[ANS_0_LCSSA]] +; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone -; CHECK-NOT: willreturn -define i32 @nested_unbounded_loops(i32 %n) { -; CHECK-LABEL: define {{[^@]+}}@nested_unbounded_loops -; CHECK-SAME: (i32 [[N:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[WHILE_COND:%.*]] -; CHECK: while.cond: -; CHECK-NEXT: [[ANS_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP1:%.*]], [[WHILE_END10:%.*]] ] -; CHECK-NEXT: [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ -1, [[WHILE_END10]] ] -; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[N_ADDR_0]], 0 -; CHECK-NEXT: br i1 [[TOBOOL]], label [[WHILE_END11:%.*]], label [[WHILE_BODY:%.*]] -; CHECK: while.body: -; CHECK-NEXT: br label [[WHILE_COND1:%.*]] -; CHECK: while.cond1: -; CHECK-NEXT: br i1 true, label [[WHILE_END:%.*]], label [[WHILE_BODY4:%.*]] -; CHECK: while.body4: -; CHECK-NEXT: unreachable -; CHECK: while.end: -; CHECK-NEXT: [[TMP:%.*]] = add i32 [[N_ADDR_0]], -2 -; CHECK-NEXT: br label [[WHILE_COND5:%.*]] -; CHECK: while.cond5: -; CHECK-NEXT: br i1 true, label [[WHILE_END10]], label [[WHILE_BODY8:%.*]] -; CHECK: while.body8: -; CHECK-NEXT: unreachable -; CHECK: while.end10: -; CHECK-NEXT: [[TMP1]] = add i32 [[TMP]], [[ANS_0]] -; CHECK-NEXT: br label [[WHILE_COND]] -; CHECK: while.end11: -; CHECK-NEXT: [[ANS_0_LCSSA:%.*]] = phi i32 [ [[ANS_0]], [[WHILE_COND]] ] -; CHECK-NEXT: ret i32 [[ANS_0_LCSSA]] +; IS__CGSCC____-LABEL: define {{[^@]+}}@nested_unbounded_loops +; IS__CGSCC____-SAME: (i32 [[N:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br label [[WHILE_COND:%.*]] +; IS__CGSCC____: while.cond: +; IS__CGSCC____-NEXT: [[ANS_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[TMP1:%.*]], [[WHILE_END10:%.*]] ] +; IS__CGSCC____-NEXT: [[N_ADDR_0:%.*]] = phi i32 [ [[N]], [[ENTRY]] ], [ -1, [[WHILE_END10]] ] +; IS__CGSCC____-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[N_ADDR_0]], 0 +; IS__CGSCC____-NEXT: br i1 [[TOBOOL]], label [[WHILE_END11:%.*]], label [[WHILE_BODY:%.*]] +; IS__CGSCC____: while.body: +; IS__CGSCC____-NEXT: br label [[WHILE_COND1:%.*]] +; IS__CGSCC____: while.cond1: +; IS__CGSCC____-NEXT: br i1 true, label [[WHILE_END:%.*]], label [[WHILE_BODY4:%.*]] +; IS__CGSCC____: while.body4: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: while.end: +; IS__CGSCC____-NEXT: [[TMP:%.*]] = add i32 [[N_ADDR_0]], -2 +; IS__CGSCC____-NEXT: br label [[WHILE_COND5:%.*]] +; IS__CGSCC____: while.cond5: +; IS__CGSCC____-NEXT: br i1 true, label [[WHILE_END10]], label [[WHILE_BODY8:%.*]] +; IS__CGSCC____: while.body8: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: while.end10: +; IS__CGSCC____-NEXT: [[TMP1]] = add i32 [[TMP]], [[ANS_0]] +; IS__CGSCC____-NEXT: br label [[WHILE_COND]] +; IS__CGSCC____: while.end11: +; IS__CGSCC____-NEXT: [[ANS_0_LCSSA:%.*]] = phi i32 [ [[ANS_0]], [[WHILE_COND]] ] +; IS__CGSCC____-NEXT: ret i32 [[ANS_0_LCSSA]] ; entry: br label %while.cond @@ -1056,38 +1484,66 @@ ; return; ; } +define void @non_loop_cycle(i32 %n) { ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone +; IS__TUNIT____-LABEL: define {{[^@]+}}@non_loop_cycle +; IS__TUNIT____-SAME: (i32 [[N:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32 @fact_loop(i32 [[N]]) +; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[CALL]], 5 +; IS__TUNIT____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; IS__TUNIT____: if.then: +; IS__TUNIT____-NEXT: br label [[ENTRY1:%.*]] +; IS__TUNIT____: if.else: +; IS__TUNIT____-NEXT: br label [[ENTRY2:%.*]] +; IS__TUNIT____: entry1: +; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call i32 @fact_loop(i32 [[N]]) +; IS__TUNIT____-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[CALL1]], 5 +; IS__TUNIT____-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_ELSE4:%.*]] +; IS__TUNIT____: if.then3: +; IS__TUNIT____-NEXT: br label [[EXIT:%.*]] +; IS__TUNIT____: if.else4: +; IS__TUNIT____-NEXT: br label [[ENTRY2]] +; IS__TUNIT____: entry2: +; IS__TUNIT____-NEXT: [[CALL5:%.*]] = call i32 @fact_loop(i32 [[N]]) +; IS__TUNIT____-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[CALL5]], 5 +; IS__TUNIT____-NEXT: br i1 [[CMP6]], label [[IF_THEN7:%.*]], label [[IF_ELSE8:%.*]] +; IS__TUNIT____: if.then7: +; IS__TUNIT____-NEXT: br label [[EXIT]] +; IS__TUNIT____: if.else8: +; IS__TUNIT____-NEXT: br label [[ENTRY1]] +; IS__TUNIT____: exit: +; IS__TUNIT____-NEXT: ret void +; ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone -; CHECK-NOT: willreturn -define void @non_loop_cycle(i32 %n) { -; CHECK-LABEL: define {{[^@]+}}@non_loop_cycle -; CHECK-SAME: (i32 [[N:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL:%.*]] = call i32 @fact_loop(i32 [[N]]) -; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[CALL]], 5 -; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] -; CHECK: if.then: -; CHECK-NEXT: br label [[ENTRY1:%.*]] -; CHECK: if.else: -; CHECK-NEXT: br label [[ENTRY2:%.*]] -; CHECK: entry1: -; CHECK-NEXT: [[CALL1:%.*]] = call i32 @fact_loop(i32 [[N]]) -; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[CALL1]], 5 -; CHECK-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_ELSE4:%.*]] -; CHECK: if.then3: -; CHECK-NEXT: br label [[EXIT:%.*]] -; CHECK: if.else4: -; CHECK-NEXT: br label [[ENTRY2]] -; CHECK: entry2: -; CHECK-NEXT: [[CALL5:%.*]] = call i32 @fact_loop(i32 [[N]]) -; CHECK-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[CALL5]], 5 -; CHECK-NEXT: br i1 [[CMP6]], label [[IF_THEN7:%.*]], label [[IF_ELSE8:%.*]] -; CHECK: if.then7: -; CHECK-NEXT: br label [[EXIT]] -; CHECK: if.else8: -; CHECK-NEXT: br label [[ENTRY1]] -; CHECK: exit: -; CHECK-NEXT: ret void +; IS__CGSCC____-LABEL: define {{[^@]+}}@non_loop_cycle +; IS__CGSCC____-SAME: (i32 [[N:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @fact_loop(i32 [[N]]) +; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp sgt i32 [[CALL]], 5 +; IS__CGSCC____-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; IS__CGSCC____: if.then: +; IS__CGSCC____-NEXT: br label [[ENTRY1:%.*]] +; IS__CGSCC____: if.else: +; IS__CGSCC____-NEXT: br label [[ENTRY2:%.*]] +; IS__CGSCC____: entry1: +; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32 @fact_loop(i32 [[N]]) +; IS__CGSCC____-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[CALL1]], 5 +; IS__CGSCC____-NEXT: br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_ELSE4:%.*]] +; IS__CGSCC____: if.then3: +; IS__CGSCC____-NEXT: br label [[EXIT:%.*]] +; IS__CGSCC____: if.else4: +; IS__CGSCC____-NEXT: br label [[ENTRY2]] +; IS__CGSCC____: entry2: +; IS__CGSCC____-NEXT: [[CALL5:%.*]] = call i32 @fact_loop(i32 [[N]]) +; IS__CGSCC____-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[CALL5]], 5 +; IS__CGSCC____-NEXT: br i1 [[CMP6]], label [[IF_THEN7:%.*]], label [[IF_ELSE8:%.*]] +; IS__CGSCC____: if.then7: +; IS__CGSCC____-NEXT: br label [[EXIT]] +; IS__CGSCC____: if.else8: +; IS__CGSCC____-NEXT: br label [[ENTRY1]] +; IS__CGSCC____: exit: +; IS__CGSCC____-NEXT: ret void ; entry: %call = call i32 @fact_loop(i32 %n)