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,14 +1,29 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=6 -S < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 { -; CHECK-LABEL: define {{[^@]+}}@deref -; CHECK-SAME: (i32 [[TMP0:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[X_PRIV:%.*]] = alloca i32 -; CHECK-NEXT: store i32 [[TMP0]], i32* [[X_PRIV]] -; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[X_PRIV]], align 4 -; CHECK-NEXT: ret i32 [[TMP2]] +; 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-LABEL: define {{[^@]+}}@deref +; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[X_PRIV:%.*]] = alloca i32 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP0]], i32* [[X_PRIV]] +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[X_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: ret i32 [[TMP2]] +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@deref +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[X:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[TMP2:%.*]] = load i32, i32* [[X]], align 4 +; IS__CGSCC____-NEXT: ret i32 [[TMP2]] ; entry: %tmp2 = load i32, i32* %x, align 4 @@ -16,14 +31,30 @@ } define i32 @f(i32 %x) { -; CHECK-LABEL: define {{[^@]+}}@f -; CHECK-SAME: (i32 [[X:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32 -; CHECK-NEXT: store i32 [[X]], i32* [[X_ADDR]], align 4 -; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[X_ADDR]], align 1 -; CHECK-NEXT: [[TMP1:%.*]] = call i32 @deref(i32 [[TMP0]]) -; CHECK-NEXT: ret i32 [[TMP1]] +; 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 +; 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-LABEL: define {{[^@]+}}@f +; IS__TUNIT_NPM-SAME: (i32 [[X:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[X_ADDR:%.*]] = alloca i32 +; IS__TUNIT_NPM-NEXT: store i32 [[X]], i32* [[X_ADDR]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[X_ADDR]], align 1 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = call i32 @deref(i32 [[TMP0]]) +; IS__TUNIT_NPM-NEXT: ret i32 [[TMP1]] +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@f +; IS__CGSCC____-SAME: (i32 [[X:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[X_ADDR:%.*]] = alloca i32 +; IS__CGSCC____-NEXT: store i32 [[X]], i32* [[X_ADDR]], align 4 +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = call i32 @deref(i32* noalias nofree nonnull readonly align 4 dereferenceable(4) [[X_ADDR]]) +; IS__CGSCC____-NEXT: ret i32 [[TMP1]] ; entry: %x_addr = alloca i32 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,20 +1,24 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=3 -S < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; PR2498 ; This test tries to convince CHECK about promoting the load from %A + 2, ; 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 +; 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]] +; 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]] ; entry: @@ -33,9 +37,15 @@ } define i32 @foo(i32* %A) { -; CHECK-LABEL: define {{[^@]+}}@foo( -; CHECK-NEXT: [[X:%.*]] = call i32 @callee(i32* nocapture nofree readonly align 4 %A) -; CHECK-NEXT: ret i32 [[X]] +; 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____-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]]) +; IS__CGSCC____-NEXT: ret i32 [[X]] ; %X = call i32 @callee(i1 false, i32* %A) ; [#uses=1] ret i32 %X 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,12 +1,24 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -disable-output -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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____-LABEL: define {{[^@]+}}@hash() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: unreachable +; entry: unreachable } 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 +; entry: %0 = call fastcc i32 @hash( i32* %ts, i32 0 ) nounwind ; [#uses=0] unreachable 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,7 +1,18 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -disable-output -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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__CGSCC____-LABEL: define {{[^@]+}}@term_SharingList() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br i1 false, label [[BB:%.*]], label [[BB5:%.*]] +; IS__CGSCC____: bb: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: bb5: +; IS__CGSCC____-NEXT: ret i32 undef +; entry: br i1 false, label %bb, label %bb5 @@ -14,6 +25,15 @@ } 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 +; entry: br i1 false, label %bb.i, label %bb14 diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/attributes.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/attributes.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/attributes.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/attributes.ll @@ -1,17 +1,27 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=3 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 that we only promote arguments when the caller/callee have compatible ; function attrubtes. target triple = "x86_64-unknown-linux-gnu" define internal fastcc void @no_promote_avx2(<4 x i64>* %arg, <4 x i64>* readonly %arg1) #0 { -; CHECK-LABEL: define {{[^@]+}}@no_promote_avx2 -; CHECK-SAME: (<4 x i64>* noalias nocapture nofree nonnull writeonly align 32 dereferenceable(32) [[ARG:%.*]], <4 x i64>* noalias nocapture nofree nonnull readonly align 32 dereferenceable(32) [[ARG1:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP:%.*]] = load <4 x i64>, <4 x i64>* [[ARG1]], align 32 -; CHECK-NEXT: store <4 x i64> [[TMP]], <4 x i64>* [[ARG]], align 32 -; CHECK-NEXT: ret void +; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@no_promote_avx2 +; NOT_TUNIT_NPM-SAME: (<4 x i64>* nocapture nofree nonnull writeonly align 32 dereferenceable(32) [[ARG:%.*]], <4 x i64>* nocapture nofree nonnull readonly align 32 dereferenceable(32) [[ARG1:%.*]]) +; NOT_TUNIT_NPM-NEXT: bb: +; NOT_TUNIT_NPM-NEXT: [[TMP:%.*]] = load <4 x i64>, <4 x i64>* [[ARG1]], align 32 +; NOT_TUNIT_NPM-NEXT: store <4 x i64> [[TMP]], <4 x i64>* [[ARG]], align 32 +; NOT_TUNIT_NPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@no_promote_avx2 +; IS__TUNIT_NPM-SAME: (<4 x i64>* noalias nocapture nofree nonnull writeonly align 32 dereferenceable(32) [[ARG:%.*]], <4 x i64>* noalias nocapture nofree nonnull readonly align 32 dereferenceable(32) [[ARG1:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = load <4 x i64>, <4 x i64>* [[ARG1]], align 32 +; IS__TUNIT_NPM-NEXT: store <4 x i64> [[TMP]], <4 x i64>* [[ARG]], align 32 +; IS__TUNIT_NPM-NEXT: ret void ; bb: %tmp = load <4 x i64>, <4 x i64>* %arg1 @@ -20,17 +30,53 @@ } define void @no_promote(<4 x i64>* %arg) #1 { -; CHECK-LABEL: define {{[^@]+}}@no_promote -; CHECK-SAME: (<4 x i64>* nocapture writeonly [[ARG:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP:%.*]] = alloca <4 x i64>, align 32 -; CHECK-NEXT: [[TMP2:%.*]] = alloca <4 x i64>, align 32 -; CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x i64>* [[TMP]] to i8* -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 32 dereferenceable(32) [[TMP3]], i8 0, i64 32, i1 false) -; CHECK-NEXT: call fastcc void @no_promote_avx2(<4 x i64>* noalias nocapture nofree nonnull writeonly align 32 dereferenceable(32) [[TMP2]], <4 x i64>* noalias nocapture nofree nonnull readonly align 32 dereferenceable(32) [[TMP]]) -; CHECK-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP2]], align 32 -; CHECK-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[ARG]], align 2 -; CHECK-NEXT: ret void +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@no_promote +; IS__TUNIT_OPM-SAME: (<4 x i64>* nocapture writeonly [[ARG:%.*]]) +; IS__TUNIT_OPM-NEXT: bb: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = alloca <4 x i64>, align 32 +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = alloca <4 x i64>, align 32 +; IS__TUNIT_OPM-NEXT: [[TMP3:%.*]] = bitcast <4 x i64>* [[TMP]] to i8* +; IS__TUNIT_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 32 dereferenceable(32) [[TMP3]], i8 0, i64 32, i1 false) +; IS__TUNIT_OPM-NEXT: call fastcc void @no_promote_avx2(<4 x i64>* nocapture nofree nonnull writeonly align 32 dereferenceable(32) [[TMP2]], <4 x i64>* nocapture nofree nonnull readonly align 32 dereferenceable(32) [[TMP]]) +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP2]], align 32 +; IS__TUNIT_OPM-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[ARG]], align 2 +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@no_promote +; IS__TUNIT_NPM-SAME: (<4 x i64>* nocapture writeonly [[ARG:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = alloca <4 x i64>, align 32 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = alloca <4 x i64>, align 32 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = bitcast <4 x i64>* [[TMP]] to i8* +; IS__TUNIT_NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 32 dereferenceable(32) [[TMP3]], i8 0, i64 32, i1 false) +; IS__TUNIT_NPM-NEXT: call fastcc void @no_promote_avx2(<4 x i64>* noalias nocapture nofree nonnull writeonly align 32 dereferenceable(32) [[TMP2]], <4 x i64>* noalias nocapture nofree nonnull readonly align 32 dereferenceable(32) [[TMP]]) +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP2]], align 32 +; IS__TUNIT_NPM-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[ARG]], align 2 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@no_promote +; IS__CGSCC_OPM-SAME: (<4 x i64>* nocapture nonnull writeonly align 2 dereferenceable(32) [[ARG:%.*]]) +; IS__CGSCC_OPM-NEXT: bb: +; IS__CGSCC_OPM-NEXT: [[TMP:%.*]] = alloca <4 x i64>, align 32 +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = alloca <4 x i64>, align 32 +; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = bitcast <4 x i64>* [[TMP]] to i8* +; IS__CGSCC_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 32 dereferenceable(32) [[TMP3]], i8 0, i64 32, i1 false) +; IS__CGSCC_OPM-NEXT: call fastcc void @no_promote_avx2(<4 x i64>* nofree nonnull writeonly align 32 dereferenceable(32) [[TMP2]], <4 x i64>* nofree nonnull readonly align 32 dereferenceable(32) [[TMP]]) +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP2]], align 32 +; IS__CGSCC_OPM-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[ARG]], align 2 +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@no_promote +; IS__CGSCC_NPM-SAME: (<4 x i64>* nocapture nonnull writeonly align 2 dereferenceable(32) [[ARG:%.*]]) +; IS__CGSCC_NPM-NEXT: bb: +; IS__CGSCC_NPM-NEXT: [[TMP:%.*]] = alloca <4 x i64>, align 32 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = alloca <4 x i64>, align 32 +; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = bitcast <4 x i64>* [[TMP]] to i8* +; IS__CGSCC_NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 32 dereferenceable(32) [[TMP3]], i8 0, i64 32, i1 false) +; IS__CGSCC_NPM-NEXT: call fastcc void @no_promote_avx2(<4 x i64>* noalias nofree nonnull writeonly align 32 dereferenceable(32) [[TMP2]], <4 x i64>* noalias nofree nonnull readonly align 32 dereferenceable(32) [[TMP]]) +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP2]], align 32 +; IS__CGSCC_NPM-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[ARG]], align 2 +; IS__CGSCC_NPM-NEXT: ret void ; bb: %tmp = alloca <4 x i64>, align 32 @@ -44,14 +90,21 @@ } define internal fastcc void @promote_avx2(<4 x i64>* %arg, <4 x i64>* readonly %arg1) #0 { -; CHECK-LABEL: define {{[^@]+}}@promote_avx2 -; CHECK-SAME: (<4 x i64>* noalias nocapture nofree nonnull writeonly align 32 dereferenceable(32) [[ARG:%.*]], <4 x i64> [[TMP0:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[ARG1_PRIV:%.*]] = alloca <4 x i64> -; CHECK-NEXT: store <4 x i64> [[TMP0]], <4 x i64>* [[ARG1_PRIV]] -; CHECK-NEXT: [[TMP:%.*]] = load <4 x i64>, <4 x i64>* [[ARG1_PRIV]], align 32 -; CHECK-NEXT: store <4 x i64> [[TMP]], <4 x i64>* [[ARG]], align 32 -; CHECK-NEXT: ret void +; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@promote_avx2 +; NOT_TUNIT_NPM-SAME: (<4 x i64>* nocapture nofree nonnull writeonly align 32 dereferenceable(32) [[ARG:%.*]], <4 x i64>* nocapture nofree nonnull readonly align 32 dereferenceable(32) [[ARG1:%.*]]) +; NOT_TUNIT_NPM-NEXT: bb: +; NOT_TUNIT_NPM-NEXT: [[TMP:%.*]] = load <4 x i64>, <4 x i64>* [[ARG1]], align 32 +; NOT_TUNIT_NPM-NEXT: store <4 x i64> [[TMP]], <4 x i64>* [[ARG]], align 32 +; NOT_TUNIT_NPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@promote_avx2 +; IS__TUNIT_NPM-SAME: (<4 x i64>* noalias nocapture nofree nonnull writeonly align 32 dereferenceable(32) [[ARG:%.*]], <4 x i64> [[TMP0:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[ARG1_PRIV:%.*]] = alloca <4 x i64> +; IS__TUNIT_NPM-NEXT: store <4 x i64> [[TMP0]], <4 x i64>* [[ARG1_PRIV]] +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = load <4 x i64>, <4 x i64>* [[ARG1_PRIV]], align 32 +; IS__TUNIT_NPM-NEXT: store <4 x i64> [[TMP]], <4 x i64>* [[ARG]], align 32 +; IS__TUNIT_NPM-NEXT: ret void ; bb: %tmp = load <4 x i64>, <4 x i64>* %arg1 @@ -60,18 +113,54 @@ } define void @promote(<4 x i64>* %arg) #0 { -; CHECK-LABEL: define {{[^@]+}}@promote -; CHECK-SAME: (<4 x i64>* nocapture writeonly [[ARG:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP:%.*]] = alloca <4 x i64>, align 32 -; CHECK-NEXT: [[TMP2:%.*]] = alloca <4 x i64>, align 32 -; CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x i64>* [[TMP]] to i8* -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 32 dereferenceable(32) [[TMP3]], i8 0, i64 32, i1 false) -; CHECK-NEXT: [[TMP0:%.*]] = load <4 x i64>, <4 x i64>* [[TMP]], align 1 -; CHECK-NEXT: call fastcc void @promote_avx2(<4 x i64>* noalias nocapture nofree nonnull writeonly align 32 dereferenceable(32) [[TMP2]], <4 x i64> [[TMP0]]) -; CHECK-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP2]], align 32 -; CHECK-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[ARG]], align 2 -; CHECK-NEXT: ret void +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@promote +; IS__TUNIT_OPM-SAME: (<4 x i64>* nocapture writeonly [[ARG:%.*]]) +; IS__TUNIT_OPM-NEXT: bb: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = alloca <4 x i64>, align 32 +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = alloca <4 x i64>, align 32 +; IS__TUNIT_OPM-NEXT: [[TMP3:%.*]] = bitcast <4 x i64>* [[TMP]] to i8* +; IS__TUNIT_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 32 dereferenceable(32) [[TMP3]], i8 0, i64 32, i1 false) +; IS__TUNIT_OPM-NEXT: call fastcc void @promote_avx2(<4 x i64>* nocapture nofree nonnull writeonly align 32 dereferenceable(32) [[TMP2]], <4 x i64>* nocapture nofree nonnull readonly align 32 dereferenceable(32) [[TMP]]) +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP2]], align 32 +; IS__TUNIT_OPM-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[ARG]], align 2 +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@promote +; IS__TUNIT_NPM-SAME: (<4 x i64>* nocapture writeonly [[ARG:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = alloca <4 x i64>, align 32 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = alloca <4 x i64>, align 32 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = bitcast <4 x i64>* [[TMP]] to i8* +; IS__TUNIT_NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 32 dereferenceable(32) [[TMP3]], i8 0, i64 32, i1 false) +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load <4 x i64>, <4 x i64>* [[TMP]], align 1 +; IS__TUNIT_NPM-NEXT: call fastcc void @promote_avx2(<4 x i64>* noalias nocapture nofree nonnull writeonly align 32 dereferenceable(32) [[TMP2]], <4 x i64> [[TMP0]]) +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP2]], align 32 +; IS__TUNIT_NPM-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[ARG]], align 2 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@promote +; IS__CGSCC_OPM-SAME: (<4 x i64>* nocapture nonnull writeonly align 2 dereferenceable(32) [[ARG:%.*]]) +; IS__CGSCC_OPM-NEXT: bb: +; IS__CGSCC_OPM-NEXT: [[TMP:%.*]] = alloca <4 x i64>, align 32 +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = alloca <4 x i64>, align 32 +; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = bitcast <4 x i64>* [[TMP]] to i8* +; IS__CGSCC_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 32 dereferenceable(32) [[TMP3]], i8 0, i64 32, i1 false) +; IS__CGSCC_OPM-NEXT: call fastcc void @promote_avx2(<4 x i64>* nofree nonnull writeonly align 32 dereferenceable(32) [[TMP2]], <4 x i64>* nofree nonnull readonly align 32 dereferenceable(32) [[TMP]]) +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP2]], align 32 +; IS__CGSCC_OPM-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[ARG]], align 2 +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@promote +; IS__CGSCC_NPM-SAME: (<4 x i64>* nocapture nonnull writeonly align 2 dereferenceable(32) [[ARG:%.*]]) +; IS__CGSCC_NPM-NEXT: bb: +; IS__CGSCC_NPM-NEXT: [[TMP:%.*]] = alloca <4 x i64>, align 32 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = alloca <4 x i64>, align 32 +; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = bitcast <4 x i64>* [[TMP]] to i8* +; IS__CGSCC_NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 32 dereferenceable(32) [[TMP3]], i8 0, i64 32, i1 false) +; IS__CGSCC_NPM-NEXT: call fastcc void @promote_avx2(<4 x i64>* noalias nofree nonnull writeonly align 32 dereferenceable(32) [[TMP2]], <4 x i64>* noalias nofree nonnull readonly align 32 dereferenceable(32) [[TMP]]) +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP2]], align 32 +; IS__CGSCC_NPM-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[ARG]], align 2 +; IS__CGSCC_NPM-NEXT: ret void ; bb: %tmp = alloca <4 x i64>, align 32 diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/min-legal-vector-width.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/min-legal-vector-width.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/min-legal-vector-width.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/min-legal-vector-width.ll @@ -1,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=3 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 that we only promote arguments when the caller/callee have compatible ; function attrubtes. @@ -7,14 +10,22 @@ ; This should promote define internal fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512(<8 x i64>* %arg, <8 x i64>* readonly %arg1) #0 { -; CHECK-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512 -; CHECK-SAME: (<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[ARG1_PRIV:%.*]] = alloca <8 x i64> -; CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[ARG1_PRIV]] -; CHECK-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1_PRIV]], align 64 -; CHECK-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 -; CHECK-NEXT: ret void +; +; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512 +; NOT_TUNIT_NPM-SAME: (<8 x i64>* nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly align 64 dereferenceable(64) [[ARG1:%.*]]) +; NOT_TUNIT_NPM-NEXT: bb: +; NOT_TUNIT_NPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 64 +; NOT_TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 +; NOT_TUNIT_NPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512 +; IS__TUNIT_NPM-SAME: (<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[ARG1_PRIV:%.*]] = alloca <8 x i64> +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[ARG1_PRIV]] +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1_PRIV]], align 64 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 +; IS__TUNIT_NPM-NEXT: ret void ; bb: %tmp = load <8 x i64>, <8 x i64>* %arg1 @@ -23,18 +34,55 @@ } define void @avx512_legal512_prefer512_call_avx512_legal512_prefer512(<8 x i64>* %arg) #0 { -; CHECK-LABEL: define {{[^@]+}}@avx512_legal512_prefer512_call_avx512_legal512_prefer512 -; CHECK-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 -; CHECK-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 -; CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 32 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) -; CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[TMP]], align 1 -; CHECK-NEXT: call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512(<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) -; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 -; CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 -; CHECK-NEXT: ret void +; +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@avx512_legal512_prefer512_call_avx512_legal512_prefer512 +; IS__TUNIT_OPM-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) +; IS__TUNIT_OPM-NEXT: bb: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_OPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__TUNIT_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__TUNIT_OPM-NEXT: call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512(<8 x i64>* nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* nocapture nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__TUNIT_OPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@avx512_legal512_prefer512_call_avx512_legal512_prefer512 +; IS__TUNIT_NPM-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__TUNIT_NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[TMP]], align 1 +; IS__TUNIT_NPM-NEXT: call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512(<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@avx512_legal512_prefer512_call_avx512_legal512_prefer512 +; IS__CGSCC_OPM-SAME: (<8 x i64>* nocapture nonnull writeonly align 2 dereferenceable(64) [[ARG:%.*]]) +; IS__CGSCC_OPM-NEXT: bb: +; IS__CGSCC_OPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__CGSCC_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__CGSCC_OPM-NEXT: call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512(<8 x i64>* nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__CGSCC_OPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@avx512_legal512_prefer512_call_avx512_legal512_prefer512 +; IS__CGSCC_NPM-SAME: (<8 x i64>* nocapture nonnull writeonly align 2 dereferenceable(64) [[ARG:%.*]]) +; IS__CGSCC_NPM-NEXT: bb: +; IS__CGSCC_NPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__CGSCC_NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__CGSCC_NPM-NEXT: call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512(<8 x i64>* noalias nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__CGSCC_NPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__CGSCC_NPM-NEXT: ret void ; bb: %tmp = alloca <8 x i64>, align 32 @@ -49,14 +97,22 @@ ; This should promote define internal fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256(<8 x i64>* %arg, <8 x i64>* readonly %arg1) #1 { -; CHECK-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256 -; CHECK-SAME: (<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[ARG1_PRIV:%.*]] = alloca <8 x i64> -; CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[ARG1_PRIV]] -; CHECK-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1_PRIV]], align 64 -; CHECK-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 -; CHECK-NEXT: ret void +; +; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256 +; NOT_TUNIT_NPM-SAME: (<8 x i64>* nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly align 64 dereferenceable(64) [[ARG1:%.*]]) +; NOT_TUNIT_NPM-NEXT: bb: +; NOT_TUNIT_NPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 64 +; NOT_TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 +; NOT_TUNIT_NPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256 +; IS__TUNIT_NPM-SAME: (<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[ARG1_PRIV:%.*]] = alloca <8 x i64> +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[ARG1_PRIV]] +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1_PRIV]], align 64 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 +; IS__TUNIT_NPM-NEXT: ret void ; bb: %tmp = load <8 x i64>, <8 x i64>* %arg1 @@ -65,18 +121,55 @@ } define void @avx512_legal512_prefer256_call_avx512_legal512_prefer256(<8 x i64>* %arg) #1 { -; CHECK-LABEL: define {{[^@]+}}@avx512_legal512_prefer256_call_avx512_legal512_prefer256 -; CHECK-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 -; CHECK-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 -; CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 32 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) -; CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[TMP]], align 1 -; CHECK-NEXT: call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256(<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) -; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 -; CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 -; CHECK-NEXT: ret void +; +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@avx512_legal512_prefer256_call_avx512_legal512_prefer256 +; IS__TUNIT_OPM-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) +; IS__TUNIT_OPM-NEXT: bb: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_OPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__TUNIT_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__TUNIT_OPM-NEXT: call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256(<8 x i64>* nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* nocapture nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__TUNIT_OPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@avx512_legal512_prefer256_call_avx512_legal512_prefer256 +; IS__TUNIT_NPM-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__TUNIT_NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[TMP]], align 1 +; IS__TUNIT_NPM-NEXT: call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256(<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@avx512_legal512_prefer256_call_avx512_legal512_prefer256 +; IS__CGSCC_OPM-SAME: (<8 x i64>* nocapture nonnull writeonly align 2 dereferenceable(64) [[ARG:%.*]]) +; IS__CGSCC_OPM-NEXT: bb: +; IS__CGSCC_OPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__CGSCC_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__CGSCC_OPM-NEXT: call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256(<8 x i64>* nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__CGSCC_OPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@avx512_legal512_prefer256_call_avx512_legal512_prefer256 +; IS__CGSCC_NPM-SAME: (<8 x i64>* nocapture nonnull writeonly align 2 dereferenceable(64) [[ARG:%.*]]) +; IS__CGSCC_NPM-NEXT: bb: +; IS__CGSCC_NPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__CGSCC_NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__CGSCC_NPM-NEXT: call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256(<8 x i64>* noalias nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__CGSCC_NPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__CGSCC_NPM-NEXT: ret void ; bb: %tmp = alloca <8 x i64>, align 32 @@ -91,14 +184,22 @@ ; This should promote define internal fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256(<8 x i64>* %arg, <8 x i64>* readonly %arg1) #1 { -; CHECK-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256 -; CHECK-SAME: (<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[ARG1_PRIV:%.*]] = alloca <8 x i64> -; CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[ARG1_PRIV]] -; CHECK-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1_PRIV]], align 64 -; CHECK-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 -; CHECK-NEXT: ret void +; +; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256 +; NOT_TUNIT_NPM-SAME: (<8 x i64>* nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly align 64 dereferenceable(64) [[ARG1:%.*]]) +; NOT_TUNIT_NPM-NEXT: bb: +; NOT_TUNIT_NPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 64 +; NOT_TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 +; NOT_TUNIT_NPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256 +; IS__TUNIT_NPM-SAME: (<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[ARG1_PRIV:%.*]] = alloca <8 x i64> +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[ARG1_PRIV]] +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1_PRIV]], align 64 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 +; IS__TUNIT_NPM-NEXT: ret void ; bb: %tmp = load <8 x i64>, <8 x i64>* %arg1 @@ -107,18 +208,55 @@ } define void @avx512_legal512_prefer512_call_avx512_legal512_prefer256(<8 x i64>* %arg) #0 { -; CHECK-LABEL: define {{[^@]+}}@avx512_legal512_prefer512_call_avx512_legal512_prefer256 -; CHECK-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 -; CHECK-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 -; CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 32 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) -; CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[TMP]], align 1 -; CHECK-NEXT: call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256(<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) -; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 -; CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 -; CHECK-NEXT: ret void +; +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@avx512_legal512_prefer512_call_avx512_legal512_prefer256 +; IS__TUNIT_OPM-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) +; IS__TUNIT_OPM-NEXT: bb: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_OPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__TUNIT_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__TUNIT_OPM-NEXT: call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256(<8 x i64>* nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* nocapture nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__TUNIT_OPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@avx512_legal512_prefer512_call_avx512_legal512_prefer256 +; IS__TUNIT_NPM-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__TUNIT_NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[TMP]], align 1 +; IS__TUNIT_NPM-NEXT: call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256(<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@avx512_legal512_prefer512_call_avx512_legal512_prefer256 +; IS__CGSCC_OPM-SAME: (<8 x i64>* nocapture nonnull writeonly align 2 dereferenceable(64) [[ARG:%.*]]) +; IS__CGSCC_OPM-NEXT: bb: +; IS__CGSCC_OPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__CGSCC_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__CGSCC_OPM-NEXT: call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256(<8 x i64>* nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__CGSCC_OPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@avx512_legal512_prefer512_call_avx512_legal512_prefer256 +; IS__CGSCC_NPM-SAME: (<8 x i64>* nocapture nonnull writeonly align 2 dereferenceable(64) [[ARG:%.*]]) +; IS__CGSCC_NPM-NEXT: bb: +; IS__CGSCC_NPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__CGSCC_NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__CGSCC_NPM-NEXT: call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256(<8 x i64>* noalias nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__CGSCC_NPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__CGSCC_NPM-NEXT: ret void ; bb: %tmp = alloca <8 x i64>, align 32 @@ -133,14 +271,22 @@ ; This should promote define internal fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512(<8 x i64>* %arg, <8 x i64>* readonly %arg1) #0 { -; CHECK-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512 -; CHECK-SAME: (<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[ARG1_PRIV:%.*]] = alloca <8 x i64> -; CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[ARG1_PRIV]] -; CHECK-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1_PRIV]], align 64 -; CHECK-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 -; CHECK-NEXT: ret void +; +; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512 +; NOT_TUNIT_NPM-SAME: (<8 x i64>* nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly align 64 dereferenceable(64) [[ARG1:%.*]]) +; NOT_TUNIT_NPM-NEXT: bb: +; NOT_TUNIT_NPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 64 +; NOT_TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 +; NOT_TUNIT_NPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512 +; IS__TUNIT_NPM-SAME: (<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[ARG1_PRIV:%.*]] = alloca <8 x i64> +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[ARG1_PRIV]] +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1_PRIV]], align 64 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 +; IS__TUNIT_NPM-NEXT: ret void ; bb: %tmp = load <8 x i64>, <8 x i64>* %arg1 @@ -149,18 +295,55 @@ } define void @avx512_legal512_prefer256_call_avx512_legal512_prefer512(<8 x i64>* %arg) #1 { -; CHECK-LABEL: define {{[^@]+}}@avx512_legal512_prefer256_call_avx512_legal512_prefer512 -; CHECK-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 -; CHECK-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 -; CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 32 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) -; CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[TMP]], align 1 -; CHECK-NEXT: call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512(<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) -; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 -; CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 -; CHECK-NEXT: ret void +; +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@avx512_legal512_prefer256_call_avx512_legal512_prefer512 +; IS__TUNIT_OPM-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) +; IS__TUNIT_OPM-NEXT: bb: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_OPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__TUNIT_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__TUNIT_OPM-NEXT: call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512(<8 x i64>* nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* nocapture nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__TUNIT_OPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@avx512_legal512_prefer256_call_avx512_legal512_prefer512 +; IS__TUNIT_NPM-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__TUNIT_NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[TMP]], align 1 +; IS__TUNIT_NPM-NEXT: call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512(<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@avx512_legal512_prefer256_call_avx512_legal512_prefer512 +; IS__CGSCC_OPM-SAME: (<8 x i64>* nocapture nonnull writeonly align 2 dereferenceable(64) [[ARG:%.*]]) +; IS__CGSCC_OPM-NEXT: bb: +; IS__CGSCC_OPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__CGSCC_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__CGSCC_OPM-NEXT: call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512(<8 x i64>* nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__CGSCC_OPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@avx512_legal512_prefer256_call_avx512_legal512_prefer512 +; IS__CGSCC_NPM-SAME: (<8 x i64>* nocapture nonnull writeonly align 2 dereferenceable(64) [[ARG:%.*]]) +; IS__CGSCC_NPM-NEXT: bb: +; IS__CGSCC_NPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__CGSCC_NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__CGSCC_NPM-NEXT: call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512(<8 x i64>* noalias nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__CGSCC_NPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__CGSCC_NPM-NEXT: ret void ; bb: %tmp = alloca <8 x i64>, align 32 @@ -175,12 +358,20 @@ ; This should not promote define internal fastcc void @callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256(<8 x i64>* %arg, <8 x i64>* readonly %arg1) #1 { -; CHECK-LABEL: define {{[^@]+}}@callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256 -; CHECK-SAME: (<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64>* noalias nocapture nofree nonnull readonly align 64 dereferenceable(64) [[ARG1:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 64 -; CHECK-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 -; CHECK-NEXT: ret void +; +; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256 +; NOT_TUNIT_NPM-SAME: (<8 x i64>* nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly align 64 dereferenceable(64) [[ARG1:%.*]]) +; NOT_TUNIT_NPM-NEXT: bb: +; NOT_TUNIT_NPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 64 +; NOT_TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 +; NOT_TUNIT_NPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256 +; IS__TUNIT_NPM-SAME: (<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64>* noalias nocapture nofree nonnull readonly align 64 dereferenceable(64) [[ARG1:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 64 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 +; IS__TUNIT_NPM-NEXT: ret void ; bb: %tmp = load <8 x i64>, <8 x i64>* %arg1 @@ -189,17 +380,54 @@ } define void @avx512_legal256_prefer256_call_avx512_legal512_prefer256(<8 x i64>* %arg) #2 { -; CHECK-LABEL: define {{[^@]+}}@avx512_legal256_prefer256_call_avx512_legal512_prefer256 -; CHECK-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 -; CHECK-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 -; CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 32 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) -; CHECK-NEXT: call fastcc void @callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256(<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nocapture nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) -; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 -; CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 -; CHECK-NEXT: ret void +; +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@avx512_legal256_prefer256_call_avx512_legal512_prefer256 +; IS__TUNIT_OPM-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) +; IS__TUNIT_OPM-NEXT: bb: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_OPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__TUNIT_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__TUNIT_OPM-NEXT: call fastcc void @callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256(<8 x i64>* nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* nocapture nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__TUNIT_OPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@avx512_legal256_prefer256_call_avx512_legal512_prefer256 +; IS__TUNIT_NPM-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__TUNIT_NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__TUNIT_NPM-NEXT: call fastcc void @callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256(<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nocapture nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@avx512_legal256_prefer256_call_avx512_legal512_prefer256 +; IS__CGSCC_OPM-SAME: (<8 x i64>* nocapture nonnull writeonly align 2 dereferenceable(64) [[ARG:%.*]]) +; IS__CGSCC_OPM-NEXT: bb: +; IS__CGSCC_OPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__CGSCC_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__CGSCC_OPM-NEXT: call fastcc void @callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256(<8 x i64>* nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__CGSCC_OPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@avx512_legal256_prefer256_call_avx512_legal512_prefer256 +; IS__CGSCC_NPM-SAME: (<8 x i64>* nocapture nonnull writeonly align 2 dereferenceable(64) [[ARG:%.*]]) +; IS__CGSCC_NPM-NEXT: bb: +; IS__CGSCC_NPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__CGSCC_NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__CGSCC_NPM-NEXT: call fastcc void @callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256(<8 x i64>* noalias nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__CGSCC_NPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__CGSCC_NPM-NEXT: ret void ; bb: %tmp = alloca <8 x i64>, align 32 @@ -214,12 +442,20 @@ ; This should not promote define internal fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256(<8 x i64>* %arg, <8 x i64>* readonly %arg1) #2 { -; CHECK-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256 -; CHECK-SAME: (<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64>* noalias nocapture nofree nonnull readonly align 64 dereferenceable(64) [[ARG1:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 64 -; CHECK-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 -; CHECK-NEXT: ret void +; +; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256 +; NOT_TUNIT_NPM-SAME: (<8 x i64>* nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly align 64 dereferenceable(64) [[ARG1:%.*]]) +; NOT_TUNIT_NPM-NEXT: bb: +; NOT_TUNIT_NPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 64 +; NOT_TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 +; NOT_TUNIT_NPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256 +; IS__TUNIT_NPM-SAME: (<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64>* noalias nocapture nofree nonnull readonly align 64 dereferenceable(64) [[ARG1:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 64 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 +; IS__TUNIT_NPM-NEXT: ret void ; bb: %tmp = load <8 x i64>, <8 x i64>* %arg1 @@ -228,17 +464,54 @@ } define void @avx512_legal512_prefer256_call_avx512_legal256_prefer256(<8 x i64>* %arg) #1 { -; CHECK-LABEL: define {{[^@]+}}@avx512_legal512_prefer256_call_avx512_legal256_prefer256 -; CHECK-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 -; CHECK-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 -; CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 32 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) -; CHECK-NEXT: call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256(<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nocapture nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) -; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 -; CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 -; CHECK-NEXT: ret void +; +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@avx512_legal512_prefer256_call_avx512_legal256_prefer256 +; IS__TUNIT_OPM-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) +; IS__TUNIT_OPM-NEXT: bb: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_OPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__TUNIT_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__TUNIT_OPM-NEXT: call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256(<8 x i64>* nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* nocapture nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__TUNIT_OPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@avx512_legal512_prefer256_call_avx512_legal256_prefer256 +; IS__TUNIT_NPM-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__TUNIT_NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__TUNIT_NPM-NEXT: call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256(<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nocapture nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@avx512_legal512_prefer256_call_avx512_legal256_prefer256 +; IS__CGSCC_OPM-SAME: (<8 x i64>* nocapture nonnull writeonly align 2 dereferenceable(64) [[ARG:%.*]]) +; IS__CGSCC_OPM-NEXT: bb: +; IS__CGSCC_OPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__CGSCC_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__CGSCC_OPM-NEXT: call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256(<8 x i64>* nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__CGSCC_OPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@avx512_legal512_prefer256_call_avx512_legal256_prefer256 +; IS__CGSCC_NPM-SAME: (<8 x i64>* nocapture nonnull writeonly align 2 dereferenceable(64) [[ARG:%.*]]) +; IS__CGSCC_NPM-NEXT: bb: +; IS__CGSCC_NPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__CGSCC_NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__CGSCC_NPM-NEXT: call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256(<8 x i64>* noalias nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__CGSCC_NPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__CGSCC_NPM-NEXT: ret void ; bb: %tmp = alloca <8 x i64>, align 32 @@ -253,14 +526,22 @@ ; This should promote define internal fastcc void @callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256(<8 x i64>* %arg, <8 x i64>* readonly %arg1) #3 { -; CHECK-LABEL: define {{[^@]+}}@callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256 -; CHECK-SAME: (<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[ARG1_PRIV:%.*]] = alloca <8 x i64> -; CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[ARG1_PRIV]] -; CHECK-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1_PRIV]], align 64 -; CHECK-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 -; CHECK-NEXT: ret void +; +; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256 +; NOT_TUNIT_NPM-SAME: (<8 x i64>* nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly align 64 dereferenceable(64) [[ARG1:%.*]]) +; NOT_TUNIT_NPM-NEXT: bb: +; NOT_TUNIT_NPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 64 +; NOT_TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 +; NOT_TUNIT_NPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256 +; IS__TUNIT_NPM-SAME: (<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[ARG1_PRIV:%.*]] = alloca <8 x i64> +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[ARG1_PRIV]] +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1_PRIV]], align 64 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 +; IS__TUNIT_NPM-NEXT: ret void ; bb: %tmp = load <8 x i64>, <8 x i64>* %arg1 @@ -269,18 +550,55 @@ } define void @avx2_legal256_prefer256_call_avx2_legal512_prefer256(<8 x i64>* %arg) #4 { -; CHECK-LABEL: define {{[^@]+}}@avx2_legal256_prefer256_call_avx2_legal512_prefer256 -; CHECK-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 -; CHECK-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 -; CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 32 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) -; CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[TMP]], align 1 -; CHECK-NEXT: call fastcc void @callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256(<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) -; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 -; CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 -; CHECK-NEXT: ret void +; +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@avx2_legal256_prefer256_call_avx2_legal512_prefer256 +; IS__TUNIT_OPM-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) +; IS__TUNIT_OPM-NEXT: bb: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_OPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__TUNIT_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__TUNIT_OPM-NEXT: call fastcc void @callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256(<8 x i64>* nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* nocapture nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__TUNIT_OPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@avx2_legal256_prefer256_call_avx2_legal512_prefer256 +; IS__TUNIT_NPM-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__TUNIT_NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[TMP]], align 1 +; IS__TUNIT_NPM-NEXT: call fastcc void @callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256(<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@avx2_legal256_prefer256_call_avx2_legal512_prefer256 +; IS__CGSCC_OPM-SAME: (<8 x i64>* nocapture nonnull writeonly align 2 dereferenceable(64) [[ARG:%.*]]) +; IS__CGSCC_OPM-NEXT: bb: +; IS__CGSCC_OPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__CGSCC_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__CGSCC_OPM-NEXT: call fastcc void @callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256(<8 x i64>* nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__CGSCC_OPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@avx2_legal256_prefer256_call_avx2_legal512_prefer256 +; IS__CGSCC_NPM-SAME: (<8 x i64>* nocapture nonnull writeonly align 2 dereferenceable(64) [[ARG:%.*]]) +; IS__CGSCC_NPM-NEXT: bb: +; IS__CGSCC_NPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__CGSCC_NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__CGSCC_NPM-NEXT: call fastcc void @callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256(<8 x i64>* noalias nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__CGSCC_NPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__CGSCC_NPM-NEXT: ret void ; bb: %tmp = alloca <8 x i64>, align 32 @@ -295,14 +613,22 @@ ; This should promote define internal fastcc void @callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256(<8 x i64>* %arg, <8 x i64>* readonly %arg1) #4 { -; CHECK-LABEL: define {{[^@]+}}@callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256 -; CHECK-SAME: (<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[ARG1_PRIV:%.*]] = alloca <8 x i64> -; CHECK-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[ARG1_PRIV]] -; CHECK-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1_PRIV]], align 64 -; CHECK-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 -; CHECK-NEXT: ret void +; +; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256 +; NOT_TUNIT_NPM-SAME: (<8 x i64>* nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly align 64 dereferenceable(64) [[ARG1:%.*]]) +; NOT_TUNIT_NPM-NEXT: bb: +; NOT_TUNIT_NPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 64 +; NOT_TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 +; NOT_TUNIT_NPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256 +; IS__TUNIT_NPM-SAME: (<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[ARG:%.*]], <8 x i64> [[TMP0:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[ARG1_PRIV:%.*]] = alloca <8 x i64> +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP0]], <8 x i64>* [[ARG1_PRIV]] +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1_PRIV]], align 64 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 64 +; IS__TUNIT_NPM-NEXT: ret void ; bb: %tmp = load <8 x i64>, <8 x i64>* %arg1 @@ -311,18 +637,55 @@ } define void @avx2_legal512_prefer256_call_avx2_legal256_prefer256(<8 x i64>* %arg) #3 { -; CHECK-LABEL: define {{[^@]+}}@avx2_legal512_prefer256_call_avx2_legal256_prefer256 -; CHECK-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 -; CHECK-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 -; CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* -; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 32 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) -; CHECK-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[TMP]], align 1 -; CHECK-NEXT: call fastcc void @callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256(<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) -; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 -; CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 -; CHECK-NEXT: ret void +; +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@avx2_legal512_prefer256_call_avx2_legal256_prefer256 +; IS__TUNIT_OPM-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) +; IS__TUNIT_OPM-NEXT: bb: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_OPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__TUNIT_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__TUNIT_OPM-NEXT: call fastcc void @callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256(<8 x i64>* nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* nocapture nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__TUNIT_OPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@avx2_legal512_prefer256_call_avx2_legal256_prefer256 +; IS__TUNIT_NPM-SAME: (<8 x i64>* nocapture writeonly [[ARG:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__TUNIT_NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load <8 x i64>, <8 x i64>* [[TMP]], align 1 +; IS__TUNIT_NPM-NEXT: call fastcc void @callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256(<8 x i64>* noalias nocapture nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@avx2_legal512_prefer256_call_avx2_legal256_prefer256 +; IS__CGSCC_OPM-SAME: (<8 x i64>* nocapture nonnull writeonly align 2 dereferenceable(64) [[ARG:%.*]]) +; IS__CGSCC_OPM-NEXT: bb: +; IS__CGSCC_OPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__CGSCC_OPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__CGSCC_OPM-NEXT: call fastcc void @callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256(<8 x i64>* nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__CGSCC_OPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@avx2_legal512_prefer256_call_avx2_legal256_prefer256 +; IS__CGSCC_NPM-SAME: (<8 x i64>* nocapture nonnull writeonly align 2 dereferenceable(64) [[ARG:%.*]]) +; IS__CGSCC_NPM-NEXT: bb: +; IS__CGSCC_NPM-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32 +; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8* +; IS__CGSCC_NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* nonnull writeonly align 64 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false) +; IS__CGSCC_NPM-NEXT: call fastcc void @callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256(<8 x i64>* noalias nofree nonnull writeonly align 64 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nofree nonnull readonly align 64 dereferenceable(64) [[TMP]]) +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 64 +; IS__CGSCC_NPM-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2 +; IS__CGSCC_NPM-NEXT: ret void ; bb: %tmp = alloca <8 x i64>, align 32 diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/thiscall.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/thiscall.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/thiscall.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/thiscall.ll @@ -4,8 +4,10 @@ ; we don't do that anymore. It also verifies that the combination of ; globalopt and argpromotion is able to optimize the call safely. ; -; RUN: opt -S -argpromotion %s | FileCheck %s --check-prefix=ARGPROMOTION -; RUN: opt -S -globalopt -argpromotion %s | FileCheck %s --check-prefix=GLOBALOPT_ARGPROMOTION +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" target triple = "i386-pc-windows-msvc19.11.0" @@ -13,25 +15,25 @@ %struct.a = type { i8 } define internal x86_thiscallcc void @internalfun(%struct.a* %this, <{ %struct.a }>* inalloca) { -; ARGPROMOTION-LABEL: define {{[^@]+}}@internalfun -; ARGPROMOTION-SAME: (%struct.a* [[THIS:%.*]], <{ [[STRUCT_A:%.*]] }>* inalloca [[TMP0:%.*]]) -; ARGPROMOTION-NEXT: entry: -; ARGPROMOTION-NEXT: [[A:%.*]] = getelementptr inbounds <{ [[STRUCT_A]] }>, <{ [[STRUCT_A]] }>* [[TMP0]], i32 0, i32 0 -; ARGPROMOTION-NEXT: [[ARGMEM:%.*]] = alloca inalloca <{ [[STRUCT_A]] }>, align 4 -; ARGPROMOTION-NEXT: [[TMP1:%.*]] = getelementptr inbounds <{ [[STRUCT_A]] }>, <{ [[STRUCT_A]] }>* [[ARGMEM]], i32 0, i32 0 -; ARGPROMOTION-NEXT: [[CALL:%.*]] = call x86_thiscallcc %struct.a* @copy_ctor(%struct.a* [[TMP1]], %struct.a* dereferenceable(1) [[A]]) -; ARGPROMOTION-NEXT: call void @ext(<{ [[STRUCT_A]] }>* inalloca [[ARGMEM]]) -; ARGPROMOTION-NEXT: ret void +; IS__TUNIT____-LABEL: define {{[^@]+}}@internalfun +; IS__TUNIT____-SAME: (%struct.a* noalias nocapture nofree readnone [[THIS:%.*]], <{ [[STRUCT_A:%.*]] }>* inalloca nonnull align 4 dereferenceable(1) [[TMP0:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[A:%.*]] = getelementptr inbounds <{ [[STRUCT_A]] }>, <{ [[STRUCT_A]] }>* [[TMP0]], i32 0, i32 0 +; IS__TUNIT____-NEXT: [[ARGMEM:%.*]] = alloca inalloca <{ [[STRUCT_A]] }>, align 4 +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = getelementptr inbounds <{ [[STRUCT_A]] }>, <{ [[STRUCT_A]] }>* [[ARGMEM]], i32 0, i32 0 +; IS__TUNIT____-NEXT: [[CALL:%.*]] = call x86_thiscallcc %struct.a* @copy_ctor(%struct.a* nonnull align 4 dereferenceable(1) [[TMP1]], %struct.a* nonnull align 4 dereferenceable(1) [[A]]) +; IS__TUNIT____-NEXT: call void @ext(<{ [[STRUCT_A]] }>* inalloca nonnull align 4 dereferenceable(1) [[ARGMEM]]) +; IS__TUNIT____-NEXT: ret void ; -; GLOBALOPT_ARGPROMOTION-LABEL: define {{[^@]+}}@internalfun -; GLOBALOPT_ARGPROMOTION-SAME: (<{ [[STRUCT_A:%.*]] }>* [[TMP0:%.*]]) unnamed_addr -; GLOBALOPT_ARGPROMOTION-NEXT: entry: -; GLOBALOPT_ARGPROMOTION-NEXT: [[A:%.*]] = getelementptr inbounds <{ [[STRUCT_A]] }>, <{ [[STRUCT_A]] }>* [[TMP0]], i32 0, i32 0 -; GLOBALOPT_ARGPROMOTION-NEXT: [[ARGMEM:%.*]] = alloca inalloca <{ [[STRUCT_A]] }>, align 4 -; GLOBALOPT_ARGPROMOTION-NEXT: [[TMP1:%.*]] = getelementptr inbounds <{ [[STRUCT_A]] }>, <{ [[STRUCT_A]] }>* [[ARGMEM]], i32 0, i32 0 -; GLOBALOPT_ARGPROMOTION-NEXT: [[CALL:%.*]] = call x86_thiscallcc %struct.a* @copy_ctor(%struct.a* [[TMP1]], %struct.a* dereferenceable(1) [[A]]) -; GLOBALOPT_ARGPROMOTION-NEXT: call void @ext(<{ [[STRUCT_A]] }>* inalloca [[ARGMEM]]) -; GLOBALOPT_ARGPROMOTION-NEXT: ret void +; IS__CGSCC____-LABEL: define {{[^@]+}}@internalfun +; IS__CGSCC____-SAME: (%struct.a* nocapture nofree readnone [[THIS:%.*]], <{ [[STRUCT_A:%.*]] }>* inalloca nonnull dereferenceable(1) [[TMP0:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[A:%.*]] = getelementptr inbounds <{ [[STRUCT_A]] }>, <{ [[STRUCT_A]] }>* [[TMP0]], i32 0, i32 0 +; IS__CGSCC____-NEXT: [[ARGMEM:%.*]] = alloca inalloca <{ [[STRUCT_A]] }>, align 4 +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = getelementptr inbounds <{ [[STRUCT_A]] }>, <{ [[STRUCT_A]] }>* [[ARGMEM]], i32 0, i32 0 +; IS__CGSCC____-NEXT: [[CALL:%.*]] = call x86_thiscallcc %struct.a* @copy_ctor(%struct.a* nonnull align 4 dereferenceable(1) [[TMP1]], %struct.a* nonnull dereferenceable(1) [[A]]) +; IS__CGSCC____-NEXT: call void @ext(<{ [[STRUCT_A]] }>* inalloca nonnull align 4 dereferenceable(1) [[ARGMEM]]) +; IS__CGSCC____-NEXT: ret void ; entry: %a = getelementptr inbounds <{ %struct.a }>, <{ %struct.a }>* %0, i32 0, i32 0 @@ -44,21 +46,21 @@ ; This is here to ensure @internalfun is live. define void @exportedfun(%struct.a* %a) { -; ARGPROMOTION-LABEL: define {{[^@]+}}@exportedfun -; ARGPROMOTION-SAME: (%struct.a* [[A:%.*]]) -; ARGPROMOTION-NEXT: [[INALLOCA_SAVE:%.*]] = tail call i8* @llvm.stacksave() -; ARGPROMOTION-NEXT: [[ARGMEM:%.*]] = alloca inalloca <{ [[STRUCT_A:%.*]] }>, align 4 -; ARGPROMOTION-NEXT: call x86_thiscallcc void @internalfun(%struct.a* [[A]], <{ [[STRUCT_A]] }>* inalloca [[ARGMEM]]) -; ARGPROMOTION-NEXT: call void @llvm.stackrestore(i8* [[INALLOCA_SAVE]]) -; ARGPROMOTION-NEXT: ret void +; IS__TUNIT____-LABEL: define {{[^@]+}}@exportedfun +; IS__TUNIT____-SAME: (%struct.a* nocapture nofree readnone [[A:%.*]]) +; IS__TUNIT____-NEXT: [[INALLOCA_SAVE:%.*]] = tail call i8* @llvm.stacksave() +; IS__TUNIT____-NEXT: [[ARGMEM:%.*]] = alloca inalloca <{ [[STRUCT_A:%.*]] }>, align 4 +; IS__TUNIT____-NEXT: call x86_thiscallcc void @internalfun(%struct.a* noalias nofree readnone undef, <{ [[STRUCT_A]] }>* inalloca nonnull align 4 dereferenceable(1) [[ARGMEM]]) +; IS__TUNIT____-NEXT: call void @llvm.stackrestore(i8* [[INALLOCA_SAVE]]) +; IS__TUNIT____-NEXT: ret void ; -; GLOBALOPT_ARGPROMOTION-LABEL: define {{[^@]+}}@exportedfun -; GLOBALOPT_ARGPROMOTION-SAME: (%struct.a* [[A:%.*]]) local_unnamed_addr -; GLOBALOPT_ARGPROMOTION-NEXT: [[INALLOCA_SAVE:%.*]] = tail call i8* @llvm.stacksave() -; GLOBALOPT_ARGPROMOTION-NEXT: [[ARGMEM:%.*]] = alloca inalloca <{ [[STRUCT_A:%.*]] }>, align 4 -; GLOBALOPT_ARGPROMOTION-NEXT: call fastcc void @internalfun(<{ [[STRUCT_A]] }>* [[ARGMEM]]) -; GLOBALOPT_ARGPROMOTION-NEXT: call void @llvm.stackrestore(i8* [[INALLOCA_SAVE]]) -; GLOBALOPT_ARGPROMOTION-NEXT: ret void +; IS__CGSCC____-LABEL: define {{[^@]+}}@exportedfun +; IS__CGSCC____-SAME: (%struct.a* nocapture nofree readnone [[A:%.*]]) +; IS__CGSCC____-NEXT: [[INALLOCA_SAVE:%.*]] = tail call i8* @llvm.stacksave() +; IS__CGSCC____-NEXT: [[ARGMEM:%.*]] = alloca inalloca <{ [[STRUCT_A:%.*]] }>, align 4 +; IS__CGSCC____-NEXT: call x86_thiscallcc void @internalfun(%struct.a* noalias nocapture nofree readnone [[A]], <{ [[STRUCT_A]] }>* inalloca nonnull align 4 dereferenceable(1) [[ARGMEM]]) +; IS__CGSCC____-NEXT: call void @llvm.stackrestore(i8* [[INALLOCA_SAVE]]) +; IS__CGSCC____-NEXT: ret void ; %inalloca.save = tail call i8* @llvm.stacksave() %argmem = alloca inalloca <{ %struct.a }>, align 4 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,14 +1,20 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -disable-output -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 %T = type { i32, i32, i32, i32 } @G = constant %T { i32 0, i32 0, i32 17, i32 25 } define internal i32 @test(%T* %p) { -; CHECK-LABEL: define {{[^@]+}}@test -; CHECK-SAME: (i32 [[P_0_2_VAL:%.*]], i32 [[P_0_3_VAL:%.*]]) +; CHECK-LABEL: define {{[^@]+}}@test() ; CHECK-NEXT: entry: -; CHECK-NEXT: [[V:%.*]] = add i32 [[P_0_3_VAL]], [[P_0_2_VAL]] +; 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]] ; entry: @@ -23,11 +29,7 @@ define i32 @caller() { ; CHECK-LABEL: define {{[^@]+}}@caller() ; CHECK-NEXT: entry: -; CHECK-NEXT: [[G_IDX:%.*]] = getelementptr [[T:%.*]], %T* @G, i64 0, i32 2 -; CHECK-NEXT: [[G_IDX_VAL:%.*]] = load i32, i32* [[G_IDX]] -; CHECK-NEXT: [[G_IDX1:%.*]] = getelementptr [[T]], %T* @G, i64 0, i32 3 -; CHECK-NEXT: [[G_IDX1_VAL:%.*]] = load i32, i32* [[G_IDX1]] -; CHECK-NEXT: [[V:%.*]] = call i32 @test(i32 [[G_IDX_VAL]], i32 [[G_IDX1_VAL]]) +; CHECK-NEXT: [[V:%.*]] = call i32 @test() ; CHECK-NEXT: ret i32 [[V]] ; entry: 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,13 +1,28 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=3 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 void @f() { -; CHECK-LABEL: define {{[^@]+}}@f() -; CHECK-NEXT: entry: -; CHECK-NEXT: [[A:%.*]] = alloca i32, align 1 -; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[A]], align 1 -; CHECK-NEXT: call void @g(i32 [[TMP0]]) -; CHECK-NEXT: ret void +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@f() +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[A:%.*]] = alloca i32, align 1 +; IS__TUNIT_OPM-NEXT: call void @g(i32* noalias nocapture nonnull readonly dereferenceable(4) [[A]]) +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@f() +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[A:%.*]] = alloca i32, align 1 +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[A]], align 1 +; IS__TUNIT_NPM-NEXT: call void @g(i32 [[TMP0]]) +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@f() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[A:%.*]] = alloca i32, align 1 +; IS__CGSCC____-NEXT: call void @g(i32* noalias nonnull readonly dereferenceable(4) [[A]]) +; IS__CGSCC____-NEXT: ret void ; entry: %a = alloca i32, align 1 @@ -16,13 +31,25 @@ } define internal void @g(i32* %a) { -; CHECK-LABEL: define {{[^@]+}}@g -; CHECK-SAME: (i32 [[TMP0:%.*]]) -; CHECK-NEXT: [[A_PRIV:%.*]] = alloca i32 -; CHECK-NEXT: store i32 [[TMP0]], i32* [[A_PRIV]] -; CHECK-NEXT: [[AA:%.*]] = load i32, i32* [[A_PRIV]], align 1 -; CHECK-NEXT: call void @z(i32 [[AA]]) -; CHECK-NEXT: ret void +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@g +; IS__TUNIT_OPM-SAME: (i32* noalias nocapture nonnull readonly dereferenceable(4) [[A:%.*]]) +; IS__TUNIT_OPM-NEXT: [[AA:%.*]] = load i32, i32* [[A]], align 1 +; IS__TUNIT_OPM-NEXT: call void @z(i32 [[AA]]) +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@g +; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]]) +; IS__TUNIT_NPM-NEXT: [[A_PRIV:%.*]] = alloca i32 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP0]], i32* [[A_PRIV]] +; IS__TUNIT_NPM-NEXT: [[AA:%.*]] = load i32, i32* [[A_PRIV]], align 1 +; IS__TUNIT_NPM-NEXT: call void @z(i32 [[AA]]) +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@g +; IS__CGSCC____-SAME: (i32* nocapture nonnull readonly dereferenceable(4) [[A:%.*]]) +; IS__CGSCC____-NEXT: [[AA:%.*]] = load i32, i32* [[A]], align 1 +; IS__CGSCC____-NEXT: call void @z(i32 [[AA]]) +; IS__CGSCC____-NEXT: ret void ; %aa = load i32, i32* %a, align 1 call void @z(i32 %aa) 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,28 +1,75 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=4 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 %struct.ss = type { i32, i64 } ; Don't drop 'byval' on %X here. define internal i32 @f(%struct.ss* byval %b, i32* byval %X, i32 %i) nounwind { -; CHECK-LABEL: define {{[^@]+}}@f -; CHECK-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]], i32 [[TMP2:%.*]], i32 [[I:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[X_PRIV:%.*]] = alloca i32 -; CHECK-NEXT: store i32 [[TMP2]], i32* [[X_PRIV]] -; CHECK-NEXT: [[B_PRIV:%.*]] = alloca [[STRUCT_SS:%.*]] -; CHECK-NEXT: [[B_PRIV_CAST:%.*]] = bitcast %struct.ss* [[B_PRIV]] to i32* -; CHECK-NEXT: store i32 [[TMP0]], i32* [[B_PRIV_CAST]] -; CHECK-NEXT: [[B_PRIV_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 1 -; CHECK-NEXT: store i64 [[TMP1]], i64* [[B_PRIV_0_1]] -; CHECK-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 0 -; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 8 -; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 -; CHECK-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 8 -; CHECK-NEXT: store i32 0, i32* [[X_PRIV]], align 4 -; CHECK-NEXT: [[L:%.*]] = load i32, i32* [[X_PRIV]], align 4 -; CHECK-NEXT: [[A:%.*]] = add i32 [[L]], [[TMP2]] -; CHECK-NEXT: ret i32 [[A]] +; +; 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: +; 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: store i32 0, i32* [[X]], align 4 +; IS__TUNIT_OPM-NEXT: [[L:%.*]] = load i32, i32* [[X]], align 4 +; IS__TUNIT_OPM-NEXT: [[A:%.*]] = add i32 [[L]], [[TMP2]] +; IS__TUNIT_OPM-NEXT: ret i32 [[A]] +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@f +; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]], i32 [[TMP2:%.*]], i32 [[I:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[X_PRIV:%.*]] = alloca i32 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP2]], i32* [[X_PRIV]] +; IS__TUNIT_NPM-NEXT: [[B_PRIV:%.*]] = alloca [[STRUCT_SS:%.*]] +; 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]] +; 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]] +; 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: store i32 0, i32* [[X_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: [[L:%.*]] = load i32, i32* [[X_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: [[A:%.*]] = add i32 [[L]], [[TMP2]] +; IS__TUNIT_NPM-NEXT: ret i32 [[A]] +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f +; IS__CGSCC_OPM-SAME: (%struct.ss* noalias nocapture nofree nonnull byval align 4 dereferenceable(4) [[B:%.*]], i32* noalias nocapture nofree nonnull byval align 4 dereferenceable(4) [[X:%.*]]) +; 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 4 +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 +; IS__CGSCC_OPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 4 +; IS__CGSCC_OPM-NEXT: store i32 0, i32* [[X]], align 4 +; IS__CGSCC_OPM-NEXT: [[L:%.*]] = load i32, i32* [[X]], align 4 +; IS__CGSCC_OPM-NEXT: [[A:%.*]] = add i32 [[L]], [[TMP2]] +; IS__CGSCC_OPM-NEXT: ret i32 [[A]] +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f +; IS__CGSCC_NPM-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]], i32 [[TMP2:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[X_PRIV:%.*]] = alloca i32 +; IS__CGSCC_NPM-NEXT: store i32 [[TMP2]], i32* [[X_PRIV]] +; IS__CGSCC_NPM-NEXT: [[B_PRIV:%.*]] = alloca [[STRUCT_SS:%.*]] +; 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]] +; 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]] +; 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 4 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 +; IS__CGSCC_NPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 4 +; IS__CGSCC_NPM-NEXT: store i32 0, i32* [[X_PRIV]], align 4 +; IS__CGSCC_NPM-NEXT: [[L:%.*]] = load i32, i32* [[X_PRIV]], align 4 +; IS__CGSCC_NPM-NEXT: [[A:%.*]] = add i32 [[L]], [[TMP2]] +; IS__CGSCC_NPM-NEXT: ret i32 [[A]] ; entry: @@ -39,21 +86,60 @@ ; Also make sure we don't drop the call zeroext attribute. define i32 @test(i32* %X) { -; CHECK-LABEL: define {{[^@]+}}@test -; CHECK-SAME: (i32* nocapture nofree readonly align 4 [[X:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 -; CHECK-NEXT: store i32 1, i32* [[TMP1]], align 8 -; CHECK-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 -; CHECK-NEXT: store i64 2, i64* [[TMP4]], align 4 -; CHECK-NEXT: [[S_CAST:%.*]] = bitcast %struct.ss* [[S]] to i32* -; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[S_CAST]], align 1 -; CHECK-NEXT: [[S_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 -; CHECK-NEXT: [[TMP1:%.*]] = load i64, i64* [[S_0_1]], align 1 -; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[X]], align 1 -; CHECK-NEXT: [[C:%.*]] = call i32 @f(i32 [[TMP0]], i64 [[TMP1]], i32 [[TMP2]], i32 zeroext 0) -; CHECK-NEXT: ret i32 [[C]] +; +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test +; IS__TUNIT_OPM-SAME: (i32* nocapture nofree readonly align 4 [[X:%.*]]) +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]] +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 +; IS__TUNIT_OPM-NEXT: store i32 1, i32* [[TMP1]], align 8 +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__TUNIT_OPM-NEXT: store i64 2, i64* [[TMP4]], align 4 +; 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-LABEL: define {{[^@]+}}@test +; IS__TUNIT_NPM-SAME: (i32* nocapture nofree readonly align 4 [[X:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]] +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 +; IS__TUNIT_NPM-NEXT: store i32 1, i32* [[TMP1]], align 8 +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: store i64 2, i64* [[TMP4]], align 4 +; IS__TUNIT_NPM-NEXT: [[S_CAST:%.*]] = bitcast %struct.ss* [[S]] to i32* +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[S_CAST]], align 1 +; IS__TUNIT_NPM-NEXT: [[S_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i64, i64* [[S_0_1]], align 1 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[X]], align 1 +; 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-LABEL: define {{[^@]+}}@test +; IS__CGSCC_OPM-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[X:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]] +; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 +; IS__CGSCC_OPM-NEXT: store i32 1, i32* [[TMP1]], align 8 +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__CGSCC_OPM-NEXT: store i64 2, i64* [[TMP4]], align 4 +; IS__CGSCC_OPM-NEXT: [[C:%.*]] = call i32 @f(%struct.ss* noalias 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-LABEL: define {{[^@]+}}@test +; IS__CGSCC_NPM-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[X:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]] +; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 +; IS__CGSCC_NPM-NEXT: store i32 1, i32* [[TMP1]], align 8 +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__CGSCC_NPM-NEXT: store i64 2, i64* [[TMP4]], align 4 +; IS__CGSCC_NPM-NEXT: [[S_CAST:%.*]] = bitcast %struct.ss* [[S]] to i32* +; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[S_CAST]], align 8 +; IS__CGSCC_NPM-NEXT: [[S_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = load i64, i64* [[S_0_1]], align 1 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[X]], align 1 +; IS__CGSCC_NPM-NEXT: [[C:%.*]] = call i32 @f(i32 [[TMP0]], i64 [[TMP1]], i32 [[TMP2]]) +; IS__CGSCC_NPM-NEXT: ret i32 [[C]] ; entry: %S = alloca %struct.ss 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,18 +1,35 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=7 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 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) { -; CHECK-LABEL: define {{[^@]+}}@test -; CHECK-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) -; CHECK-NEXT: [[Y_PRIV:%.*]] = alloca i32 -; CHECK-NEXT: store i32 [[TMP1]], i32* [[Y_PRIV]] -; CHECK-NEXT: [[X_PRIV:%.*]] = alloca i32 -; CHECK-NEXT: store i32 [[TMP0]], i32* [[X_PRIV]] -; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[X_PRIV]], align 4 -; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[Y_PRIV]], align 4 -; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[B]] -; CHECK-NEXT: ret i32 [[C]] +; 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 +; IS__TUNIT_OPM-NEXT: [[B:%.*]] = load i32, i32* [[Y]], align 4 +; IS__TUNIT_OPM-NEXT: [[C:%.*]] = add i32 [[A]], [[B]] +; IS__TUNIT_OPM-NEXT: ret i32 [[C]] +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@test +; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) +; IS__TUNIT_NPM-NEXT: [[Y_PRIV:%.*]] = alloca i32 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP1]], i32* [[Y_PRIV]] +; IS__TUNIT_NPM-NEXT: [[X_PRIV:%.*]] = alloca i32 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP0]], i32* [[X_PRIV]] +; IS__TUNIT_NPM-NEXT: [[A:%.*]] = load i32, i32* [[X_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: [[B:%.*]] = load i32, i32* [[Y_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: [[C:%.*]] = add i32 [[A]], [[B]] +; IS__TUNIT_NPM-NEXT: ret i32 [[C]] +; +; 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 +; IS__CGSCC____-NEXT: [[B:%.*]] = load i32, i32* [[Y]], align 4 +; IS__CGSCC____-NEXT: [[C:%.*]] = add i32 [[A]], [[B]] +; IS__CGSCC____-NEXT: ret i32 [[C]] ; %A = load i32, i32* %X %B = load i32, i32* %Y @@ -21,16 +38,30 @@ } define internal i32 @caller(i32* %B) { -; CHECK-LABEL: define {{[^@]+}}@caller -; CHECK-SAME: (i32 [[TMP0:%.*]]) -; CHECK-NEXT: [[B_PRIV:%.*]] = alloca i32 -; CHECK-NEXT: store i32 [[TMP0]], i32* [[B_PRIV]] -; CHECK-NEXT: [[A:%.*]] = alloca i32 -; CHECK-NEXT: store i32 1, i32* [[A]], align 4 -; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[A]], align 1 -; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[B_PRIV]], align 1 -; CHECK-NEXT: [[C:%.*]] = call i32 @test(i32 [[TMP2]], i32 [[TMP3]]) -; CHECK-NEXT: ret i32 [[C]] +; 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 +; IS__TUNIT_OPM-NEXT: store i32 1, i32* [[A]], align 4 +; 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-LABEL: define {{[^@]+}}@caller +; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]]) +; IS__TUNIT_NPM-NEXT: [[B_PRIV:%.*]] = alloca i32 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP0]], i32* [[B_PRIV]] +; IS__TUNIT_NPM-NEXT: [[A:%.*]] = alloca i32 +; IS__TUNIT_NPM-NEXT: store i32 1, i32* [[A]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[A]], align 1 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[B_PRIV]], align 1 +; IS__TUNIT_NPM-NEXT: [[C:%.*]] = call i32 @test(i32 [[TMP2]], i32 [[TMP3]]) +; IS__TUNIT_NPM-NEXT: ret i32 [[C]] +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@caller +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B:%.*]]) +; IS__CGSCC____-NEXT: [[A:%.*]] = alloca i32 +; IS__CGSCC____-NEXT: store i32 1, i32* [[A]], align 4 +; IS__CGSCC____-NEXT: [[C:%.*]] = call i32 @test(i32* noalias nofree nonnull readonly align 4 dereferenceable(4) [[A]], i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B]]) +; IS__CGSCC____-NEXT: ret i32 [[C]] ; %A = alloca i32 store i32 1, i32* %A @@ -39,12 +70,24 @@ } define i32 @callercaller() { -; CHECK-LABEL: define {{[^@]+}}@callercaller() -; CHECK-NEXT: [[B:%.*]] = alloca i32 -; CHECK-NEXT: store i32 2, i32* [[B]], align 4 -; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[B]], align 1 -; CHECK-NEXT: [[X:%.*]] = call i32 @caller(i32 [[TMP1]]) -; CHECK-NEXT: ret i32 [[X]] +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@callercaller() +; IS__TUNIT_OPM-NEXT: [[B:%.*]] = alloca i32 +; 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-LABEL: define {{[^@]+}}@callercaller() +; IS__TUNIT_NPM-NEXT: [[B:%.*]] = alloca i32 +; IS__TUNIT_NPM-NEXT: store i32 2, i32* [[B]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[B]], align 1 +; IS__TUNIT_NPM-NEXT: [[X:%.*]] = call i32 @caller(i32 [[TMP1]]) +; IS__TUNIT_NPM-NEXT: ret i32 [[X]] +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@callercaller() +; IS__CGSCC____-NEXT: [[B:%.*]] = alloca i32 +; IS__CGSCC____-NEXT: store i32 2, i32* [[B]], align 4 +; IS__CGSCC____-NEXT: [[X:%.*]] = call i32 @caller(i32* noalias 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,9 +1,39 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=3 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 %struct.ss = type { i32, i64 } define internal void @f(%struct.ss* byval %b, i32* byval %X) nounwind { +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@f +; IS__CGSCC_OPM-SAME: (%struct.ss* noalias nocapture nofree nonnull byval align 4 dereferenceable(4) [[B:%.*]], i32* noalias nocapture nofree nonnull writeonly byval align 4 dereferenceable(4) [[X:%.*]]) +; 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 4 +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 +; IS__CGSCC_OPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 4 +; IS__CGSCC_OPM-NEXT: store i32 0, i32* [[X]], align 4 +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f +; IS__CGSCC_NPM-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]], i32 [[TMP2:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[X_PRIV:%.*]] = alloca i32 +; IS__CGSCC_NPM-NEXT: store i32 [[TMP2]], i32* [[X_PRIV]] +; IS__CGSCC_NPM-NEXT: [[B_PRIV:%.*]] = alloca [[STRUCT_SS:%.*]] +; 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]] +; 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]] +; 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 4 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 +; IS__CGSCC_NPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 4 +; IS__CGSCC_NPM-NEXT: store i32 0, i32* [[X_PRIV]], align 4 +; IS__CGSCC_NPM-NEXT: ret void +; entry: %tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0 %tmp1 = load i32, i32* %tmp, align 4 @@ -15,15 +45,36 @@ } define i32 @test(i32* %X) { -; CHECK-LABEL: define {{[^@]+}}@test -; CHECK-SAME: (i32* nocapture nofree readonly align 4 [[X:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 -; CHECK-NEXT: store i32 1, i32* [[TMP1]], align 8 -; CHECK-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 -; CHECK-NEXT: store i64 2, i64* [[TMP4]], align 4 -; CHECK-NEXT: ret i32 0 +; +; IS__TUNIT____-LABEL: define {{[^@]+}}@test +; IS__TUNIT____-SAME: (i32* nocapture nofree readonly align 4 [[X:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]] +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 +; IS__TUNIT____-NEXT: store i32 1, i32* [[TMP1]], align 8 +; IS__TUNIT____-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__TUNIT____-NEXT: store i64 2, i64* [[TMP4]], align 4 +; IS__TUNIT____-NEXT: ret i32 0 +; +; 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: +; IS__CGSCC_OPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]] +; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 +; IS__CGSCC_OPM-NEXT: store i32 1, i32* [[TMP1]], align 8 +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__CGSCC_OPM-NEXT: store i64 2, i64* [[TMP4]], align 4 +; IS__CGSCC_OPM-NEXT: ret i32 0 +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@test +; IS__CGSCC_NPM-SAME: (i32* nocapture nofree nonnull readonly dereferenceable(4) [[X:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]] +; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 +; IS__CGSCC_NPM-NEXT: store i32 1, i32* [[TMP1]], align 8 +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__CGSCC_NPM-NEXT: store i64 2, i64* [[TMP4]], align 4 +; IS__CGSCC_NPM-NEXT: ret i32 0 ; entry: %S = alloca %struct.ss 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,24 +1,59 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=2 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 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" %struct.ss = type { i32, i64 } define internal i32 @f(%struct.ss* byval %b) nounwind { -; CHECK-LABEL: define {{[^@]+}}@f -; CHECK-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[B_PRIV:%.*]] = alloca [[STRUCT_SS:%.*]] -; CHECK-NEXT: [[B_PRIV_CAST:%.*]] = bitcast %struct.ss* [[B_PRIV]] to i32* -; CHECK-NEXT: store i32 [[TMP0]], i32* [[B_PRIV_CAST]] -; CHECK-NEXT: [[B_PRIV_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 1 -; CHECK-NEXT: store i64 [[TMP1]], i64* [[B_PRIV_0_1]] -; CHECK-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 0 -; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 8 -; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 -; CHECK-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 8 -; CHECK-NEXT: ret i32 [[TMP1]] +; 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-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:%.*]] +; 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]] +; 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]] +; 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__CGSCC_OPM-LABEL: define {{[^@]+}}@f +; IS__CGSCC_OPM-SAME: (%struct.ss* noalias nocapture nofree nonnull byval align 4 dereferenceable(4) [[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 4 +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 +; IS__CGSCC_OPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 4 +; IS__CGSCC_OPM-NEXT: ret i32 [[TMP1]] +; +; 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:%.*]] +; 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]] +; 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]] +; 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 4 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 +; IS__CGSCC_NPM-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 4 +; IS__CGSCC_NPM-NEXT: ret i32 [[TMP1]] ; entry: %tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0 @@ -30,19 +65,37 @@ define internal i32 @g(%struct.ss* byval align 32 %b) nounwind { -; CHECK-LABEL: define {{[^@]+}}@g -; CHECK-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[B_PRIV:%.*]] = alloca [[STRUCT_SS:%.*]] -; CHECK-NEXT: [[B_PRIV_CAST:%.*]] = bitcast %struct.ss* [[B_PRIV]] to i32* -; CHECK-NEXT: store i32 [[TMP0]], i32* [[B_PRIV_CAST]] -; CHECK-NEXT: [[B_PRIV_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 1 -; CHECK-NEXT: store i64 [[TMP1]], i64* [[B_PRIV_0_1]] -; CHECK-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B_PRIV]], i32 0, i32 0 -; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 32 -; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1 -; CHECK-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 32 -; CHECK-NEXT: ret i32 [[TMP2]] +; 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________NPM-LABEL: define {{[^@]+}}@g +; IS________NPM-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]]) +; IS________NPM-NEXT: entry: +; IS________NPM-NEXT: [[B_PRIV:%.*]] = alloca [[STRUCT_SS:%.*]] +; IS________NPM-NEXT: [[B_PRIV_CAST:%.*]] = bitcast %struct.ss* [[B_PRIV]] to i32* +; IS________NPM-NEXT: store i32 [[TMP0]], i32* [[B_PRIV_CAST]] +; 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]] +; 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-LABEL: define {{[^@]+}}@g +; IS__CGSCC_OPM-SAME: (%struct.ss* noalias nocapture nofree nonnull byval align 32 dereferenceable(4) [[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]] ; entry: %tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0 @@ -54,25 +107,69 @@ define i32 @main() nounwind { -; CHECK-LABEL: define {{[^@]+}}@main() -; CHECK-NEXT: entry: -; CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]] -; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 -; CHECK-NEXT: store i32 1, i32* [[TMP1]], align 8 -; CHECK-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 -; CHECK-NEXT: store i64 2, i64* [[TMP4]], align 4 -; CHECK-NEXT: [[S_CAST:%.*]] = bitcast %struct.ss* [[S]] to i32* -; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[S_CAST]], align 1 -; CHECK-NEXT: [[S_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 -; CHECK-NEXT: [[TMP1:%.*]] = load i64, i64* [[S_0_1]], align 1 -; CHECK-NEXT: [[C0:%.*]] = call i32 @f(i32 [[TMP0]], i64 [[TMP1]]) -; CHECK-NEXT: [[S_CAST1:%.*]] = bitcast %struct.ss* [[S]] to i32* -; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[S_CAST1]], align 1 -; CHECK-NEXT: [[S_0_12:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 -; CHECK-NEXT: [[TMP3:%.*]] = load i64, i64* [[S_0_12]], align 1 -; CHECK-NEXT: [[C1:%.*]] = call i32 @g(i32 [[TMP2]], i64 [[TMP3]]) -; CHECK-NEXT: [[A:%.*]] = add i32 [[C0]], [[C1]] -; CHECK-NEXT: ret i32 [[A]] +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@main() +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]] +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 +; IS__TUNIT_OPM-NEXT: store i32 1, i32* [[TMP1]], align 8 +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__TUNIT_OPM-NEXT: store i64 2, i64* [[TMP4]], align 4 +; IS__TUNIT_OPM-NEXT: [[C0:%.*]] = call i32 @f(%struct.ss* noalias nocapture nofree nonnull readonly byval align 8 dereferenceable(12) [[S]]) +; IS__TUNIT_OPM-NEXT: [[C1:%.*]] = call i32 @g(%struct.ss* noalias nocapture nofree nonnull readonly byval align 32 dereferenceable(12) [[S]]) +; IS__TUNIT_OPM-NEXT: [[A:%.*]] = add i32 [[C0]], [[C1]] +; IS__TUNIT_OPM-NEXT: ret i32 [[A]] +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@main() +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]] +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 +; IS__TUNIT_NPM-NEXT: store i32 1, i32* [[TMP1]], align 8 +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: store i64 2, i64* [[TMP4]], align 4 +; IS__TUNIT_NPM-NEXT: [[S_CAST1:%.*]] = bitcast %struct.ss* [[S]] to i32* +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[S_CAST1]], align 1 +; IS__TUNIT_NPM-NEXT: [[S_0_12:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i64, i64* [[S_0_12]], align 1 +; IS__TUNIT_NPM-NEXT: [[C0:%.*]] = call i32 @f(i32 [[TMP0]], i64 [[TMP1]]) +; IS__TUNIT_NPM-NEXT: [[S_CAST:%.*]] = bitcast %struct.ss* [[S]] to i32* +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[S_CAST]], align 1 +; IS__TUNIT_NPM-NEXT: [[S_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: [[TMP3:%.*]] = load i64, i64* [[S_0_1]], align 1 +; IS__TUNIT_NPM-NEXT: [[C1:%.*]] = call i32 @g(i32 [[TMP2]], i64 [[TMP3]]) +; IS__TUNIT_NPM-NEXT: [[A:%.*]] = add i32 [[C0]], [[C1]] +; IS__TUNIT_NPM-NEXT: ret i32 [[A]] +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@main() +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]] +; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 +; IS__CGSCC_OPM-NEXT: store i32 1, i32* [[TMP1]], align 32 +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__CGSCC_OPM-NEXT: store i64 2, i64* [[TMP4]], align 4 +; IS__CGSCC_OPM-NEXT: [[C0:%.*]] = call i32 @f(%struct.ss* noalias nofree nonnull readnone byval align 32 dereferenceable(12) [[S]]) +; IS__CGSCC_OPM-NEXT: [[C1:%.*]] = call i32 @g(%struct.ss* noalias nofree nonnull readnone byval align 32 dereferenceable(12) [[S]]) +; IS__CGSCC_OPM-NEXT: [[A:%.*]] = add i32 [[C0]], [[C1]] +; IS__CGSCC_OPM-NEXT: ret i32 [[A]] +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@main() +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]] +; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 +; IS__CGSCC_NPM-NEXT: store i32 1, i32* [[TMP1]], align 8 +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__CGSCC_NPM-NEXT: store i64 2, i64* [[TMP4]], align 4 +; IS__CGSCC_NPM-NEXT: [[S_CAST:%.*]] = bitcast %struct.ss* [[S]] to i32* +; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[S_CAST]], align 8 +; IS__CGSCC_NPM-NEXT: [[S_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = load i64, i64* [[S_0_1]], align 1 +; IS__CGSCC_NPM-NEXT: [[C0:%.*]] = call i32 @f(i32 [[TMP0]], i64 [[TMP1]]) +; IS__CGSCC_NPM-NEXT: [[S_CAST1:%.*]] = bitcast %struct.ss* [[S]] to i32* +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[S_CAST1]], align 8 +; IS__CGSCC_NPM-NEXT: [[S_0_12:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 +; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = load i64, i64* [[S_0_12]], align 1 +; IS__CGSCC_NPM-NEXT: [[C1:%.*]] = call i32 @g(i32 [[TMP2]], i64 [[TMP3]]) +; IS__CGSCC_NPM-NEXT: [[A:%.*]] = add i32 [[C0]], [[C1]] +; IS__CGSCC_NPM-NEXT: ret i32 [[A]] ; entry: %S = alloca %struct.ss 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,10 +1,14 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 @G1 = constant i32 0 @G2 = constant i32* @G1 define internal i32 @test(i32** %x) { +; ; CHECK-LABEL: define {{[^@]+}}@test() ; CHECK-NEXT: entry: ; CHECK-NEXT: [[Y:%.*]] = load i32*, i32** @G2, align 8 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=3 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; Don't promote around control flow. define internal 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,19 +1,40 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=7 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 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) { -; CHECK-LABEL: define {{[^@]+}}@callee -; CHECK-SAME: (i1 [[C:%.*]], i32 [[TMP0:%.*]]) -; CHECK-NEXT: [[P_PRIV:%.*]] = alloca i32 -; CHECK-NEXT: store i32 [[TMP0]], i32* [[P_PRIV]] -; CHECK-NEXT: br label [[F:%.*]] -; CHECK: T: -; CHECK-NEXT: unreachable -; CHECK: F: -; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P_PRIV]], align 4 -; CHECK-NEXT: ret i32 [[X]] +; 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:%.*]] +; IS__TUNIT_OPM: T: +; IS__TUNIT_OPM-NEXT: unreachable +; IS__TUNIT_OPM: F: +; IS__TUNIT_OPM-NEXT: [[X:%.*]] = load i32, i32* [[P]], align 4 +; IS__TUNIT_OPM-NEXT: ret i32 [[X]] +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@callee +; IS__TUNIT_NPM-SAME: (i1 [[C:%.*]], i32 [[TMP0:%.*]]) +; IS__TUNIT_NPM-NEXT: [[P_PRIV:%.*]] = alloca i32 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP0]], i32* [[P_PRIV]] +; IS__TUNIT_NPM-NEXT: br label [[F:%.*]] +; IS__TUNIT_NPM: T: +; IS__TUNIT_NPM-NEXT: unreachable +; IS__TUNIT_NPM: F: +; IS__TUNIT_NPM-NEXT: [[X:%.*]] = load i32, i32* [[P_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: ret i32 [[X]] +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@callee +; IS__CGSCC____-SAME: (i32* nocapture nofree readonly [[P:%.*]]) +; IS__CGSCC____-NEXT: br label [[F:%.*]] +; IS__CGSCC____: T: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: F: +; IS__CGSCC____-NEXT: [[X:%.*]] = load i32, i32* [[P]] +; IS__CGSCC____-NEXT: ret i32 [[X]] ; br i1 %C, label %T, label %F @@ -26,12 +47,24 @@ } define i32 @foo() { -; CHECK-LABEL: define {{[^@]+}}@foo() -; CHECK-NEXT: [[A:%.*]] = alloca i32 -; CHECK-NEXT: store i32 17, i32* [[A]], align 4 -; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[A]], align 1 -; CHECK-NEXT: [[X:%.*]] = call i32 @callee(i1 false, i32 [[TMP1]]) -; CHECK-NEXT: ret i32 [[X]] +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@foo() +; IS__TUNIT_OPM-NEXT: [[A:%.*]] = alloca i32 +; 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-LABEL: define {{[^@]+}}@foo() +; IS__TUNIT_NPM-NEXT: [[A:%.*]] = alloca i32 +; IS__TUNIT_NPM-NEXT: store i32 17, i32* [[A]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[A]], align 1 +; IS__TUNIT_NPM-NEXT: [[X:%.*]] = call i32 @callee(i1 false, i32 [[TMP1]]) +; IS__TUNIT_NPM-NEXT: ret i32 [[X]] +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@foo() +; IS__CGSCC____-NEXT: [[A:%.*]] = alloca i32 +; IS__CGSCC____-NEXT: store i32 17, i32* [[A]], align 4 +; IS__CGSCC____-NEXT: [[X:%.*]] = call i32 @callee(i32* noalias nofree nonnull readonly align 4 dereferenceable(4) [[A]]) +; IS__CGSCC____-NEXT: ret i32 [[X]] ; %A = alloca i32 ; [#uses=2] store i32 17, i32* %A 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,30 +1,22 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=3 < %s | FileCheck %s --check-prefixes=CHECK,ATTRIBUTOR -; RUN: opt -S -passes='cgscc(inline),attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=3 < %s | FileCheck %s --check-prefixes=CHECK,INLINE_ATTRIBUTOR +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 %S = type { %S* } ; Inlining should nuke the invoke (and any inlined calls) here even with ; argument promotion running along with it. define void @zot() personality i32 (...)* @wibble { -; ATTRIBUTOR-LABEL: define {{[^@]+}}@zot() #0 personality i32 (...)* @wibble -; ATTRIBUTOR-NEXT: bb: -; ATTRIBUTOR-NEXT: call void @hoge() -; ATTRIBUTOR-NEXT: unreachable -; ATTRIBUTOR: bb1: -; ATTRIBUTOR-NEXT: unreachable -; ATTRIBUTOR: bb2: -; ATTRIBUTOR-NEXT: unreachable -; -; INLINE_ATTRIBUTOR-LABEL: define {{[^@]+}}@zot() #0 personality i32 (...)* @wibble -; INLINE_ATTRIBUTOR-NEXT: bb: -; INLINE_ATTRIBUTOR-NEXT: unreachable -; INLINE_ATTRIBUTOR: hoge.exit: -; INLINE_ATTRIBUTOR-NEXT: unreachable -; INLINE_ATTRIBUTOR: bb1: -; INLINE_ATTRIBUTOR-NEXT: unreachable -; INLINE_ATTRIBUTOR: bb2: -; INLINE_ATTRIBUTOR-NEXT: unreachable +; 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 ; bb: invoke void @hoge() @@ -40,9 +32,9 @@ } define internal void @hoge() { -; ATTRIBUTOR-LABEL: define {{[^@]+}}@hoge() -; ATTRIBUTOR-NEXT: bb: -; ATTRIBUTOR-NEXT: unreachable +; CHECK-LABEL: define {{[^@]+}}@hoge() +; CHECK-NEXT: bb: +; CHECK-NEXT: unreachable ; bb: %tmp = call fastcc i8* @spam(i1 (i8*)* @eggs) @@ -51,6 +43,10 @@ } define internal fastcc i8* @spam(i1 (i8*)* %arg) { +; IS__CGSCC____-LABEL: define {{[^@]+}}@spam() +; IS__CGSCC____-NEXT: bb: +; IS__CGSCC____-NEXT: unreachable +; bb: unreachable } @@ -62,15 +58,26 @@ } define internal i1 @barney(i8* %arg) { +; IS__CGSCC____-LABEL: define {{[^@]+}}@barney() +; IS__CGSCC____-NEXT: bb: +; IS__CGSCC____-NEXT: ret i1 undef +; bb: ret i1 undef } define i32 @test_inf_promote_caller(i32 %arg) { -; CHECK-LABEL: define {{[^@]+}}@test_inf_promote_caller -; CHECK-SAME: (i32 [[ARG:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: unreachable +; IS__TUNIT____-LABEL: define {{[^@]+}}@test_inf_promote_caller +; IS__TUNIT____-SAME: (i32 [[ARG:%.*]]) +; IS__TUNIT____-NEXT: bb: +; IS__TUNIT____-NEXT: unreachable +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@test_inf_promote_caller +; IS__CGSCC____-SAME: (i32 [[ARG:%.*]]) +; IS__CGSCC____-NEXT: bb: +; IS__CGSCC____-NEXT: [[TMP:%.*]] = alloca [[S:%.*]] +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = alloca [[S]] +; IS__CGSCC____-NEXT: unreachable ; bb: %tmp = alloca %S @@ -81,6 +88,10 @@ } define internal i32 @test_inf_promote_callee(%S* %arg, %S* %arg1) { +; IS__CGSCC____-LABEL: define {{[^@]+}}@test_inf_promote_callee() +; IS__CGSCC____-NEXT: bb: +; IS__CGSCC____-NEXT: unreachable +; bb: %tmp = getelementptr %S, %S* %arg1, i32 0, i32 0 %tmp2 = load %S*, %S** %tmp 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=2 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 declare void @sink(i32) @@ -29,11 +32,17 @@ } define void @caller(i32** %Y, %struct.pair* %P) { -; CHECK-LABEL: define {{[^@]+}}@caller -; CHECK-SAME: (i32** nocapture readonly [[Y:%.*]], %struct.pair* nocapture nofree readnone [[P:%.*]]) -; CHECK-NEXT: call void @test(i32** nocapture readonly align 8 [[Y]]), !dbg !4 -; CHECK-NEXT: call void @test_byval(), !dbg !5 -; CHECK-NEXT: ret void +; IS__TUNIT____-LABEL: define {{[^@]+}}@caller +; IS__TUNIT____-SAME: (i32** nocapture readonly [[Y:%.*]], %struct.pair* nocapture nofree readnone [[P:%.*]]) +; IS__TUNIT____-NEXT: call void @test(i32** nocapture readonly align 8 [[Y]]), !dbg !4 +; IS__TUNIT____-NEXT: call void @test_byval(), !dbg !5 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@caller +; IS__CGSCC____-SAME: (i32** nocapture nonnull readonly align 8 dereferenceable(8) [[Y:%.*]], %struct.pair* nocapture nofree readnone [[P:%.*]]) +; IS__CGSCC____-NEXT: call void @test(i32** nocapture nonnull readonly align 8 dereferenceable(8) [[Y]]), !dbg !4 +; IS__CGSCC____-NEXT: call void @test_byval(), !dbg !5 +; IS__CGSCC____-NEXT: ret void ; call void @test(i32** %Y), !dbg !1 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=3 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" @@ -26,6 +29,10 @@ } define internal i8 @UseLongDoubleUnsafely(%union.u* byval align 16 %arg) { +; IS__CGSCC____-LABEL: define {{[^@]+}}@UseLongDoubleUnsafely() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i8 undef +; entry: %bitcast = bitcast %union.u* %arg to %struct.s* %gep = getelementptr inbounds %struct.s, %struct.s* %bitcast, i64 0, i32 2 @@ -34,18 +41,53 @@ } define internal x86_fp80 @UseLongDoubleSafely(%union.u* byval align 16 %arg) { +; IS__CGSCC____-LABEL: define {{[^@]+}}@UseLongDoubleSafely() +; IS__CGSCC____-NEXT: ret x86_fp80 undef +; %gep = getelementptr inbounds %union.u, %union.u* %arg, i64 0, i32 0 %fp80 = load x86_fp80, x86_fp80* %gep ret x86_fp80 %fp80 } define internal i64 @AccessPaddingOfStruct(%struct.Foo* byval %a) { +; IS__CGSCC____-LABEL: define {{[^@]+}}@AccessPaddingOfStruct() +; IS__CGSCC____-NEXT: ret i64 undef +; %p = bitcast %struct.Foo* %a to i64* %v = load i64, i64* %p ret i64 %v } define internal i64 @CaptureAStruct(%struct.Foo* byval %a) { +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@CaptureAStruct +; IS__CGSCC_OPM-SAME: (%struct.Foo* noalias nofree byval [[A:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[A_PTR:%.*]] = alloca %struct.Foo* +; IS__CGSCC_OPM-NEXT: br label [[LOOP:%.*]] +; IS__CGSCC_OPM: loop: +; IS__CGSCC_OPM-NEXT: [[PHI:%.*]] = phi %struct.Foo* [ null, [[ENTRY:%.*]] ], [ [[GEP:%.*]], [[LOOP]] ] +; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = phi %struct.Foo* [ [[A]], [[ENTRY]] ], [ [[TMP0]], [[LOOP]] ] +; IS__CGSCC_OPM-NEXT: store %struct.Foo* [[PHI]], %struct.Foo** [[A_PTR]], align 8 +; IS__CGSCC_OPM-NEXT: [[GEP]] = getelementptr [[STRUCT_FOO:%.*]], %struct.Foo* [[A]], i64 0 +; IS__CGSCC_OPM-NEXT: br label [[LOOP]] +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@CaptureAStruct +; IS__CGSCC_NPM-SAME: (i32 [[TMP0:%.*]], i64 [[TMP1:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[A_PRIV:%.*]] = alloca [[STRUCT_FOO:%.*]] +; IS__CGSCC_NPM-NEXT: [[A_PRIV_CAST:%.*]] = bitcast %struct.Foo* [[A_PRIV]] to i32* +; IS__CGSCC_NPM-NEXT: store i32 [[TMP0]], i32* [[A_PRIV_CAST]] +; IS__CGSCC_NPM-NEXT: [[A_PRIV_0_1:%.*]] = getelementptr [[STRUCT_FOO]], %struct.Foo* [[A_PRIV]], i32 0, i32 1 +; IS__CGSCC_NPM-NEXT: store i64 [[TMP1]], i64* [[A_PRIV_0_1]] +; IS__CGSCC_NPM-NEXT: [[A_PTR:%.*]] = alloca %struct.Foo* +; IS__CGSCC_NPM-NEXT: br label [[LOOP:%.*]] +; IS__CGSCC_NPM: loop: +; IS__CGSCC_NPM-NEXT: [[PHI:%.*]] = phi %struct.Foo* [ null, [[ENTRY:%.*]] ], [ [[GEP:%.*]], [[LOOP]] ] +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = phi %struct.Foo* [ [[A_PRIV]], [[ENTRY]] ], [ [[TMP2]], [[LOOP]] ] +; IS__CGSCC_NPM-NEXT: store %struct.Foo* [[PHI]], %struct.Foo** [[A_PTR]], align 8 +; IS__CGSCC_NPM-NEXT: [[GEP]] = getelementptr [[STRUCT_FOO]], %struct.Foo* [[A_PRIV]], i64 0 +; IS__CGSCC_NPM-NEXT: br label [[LOOP]] +; entry: %a_ptr = alloca %struct.Foo* br label %loop 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,6 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=6 < %s | FileCheck %s --check-prefixes=ATTRIBUTOR -; RUN: opt -S -passes='globalopt,attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=6 < %s | FileCheck %s --check-prefixes=GLOBALOPT_ATTRIBUTOR +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 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" @@ -8,30 +10,25 @@ ; Argpromote + sroa should change this to passing the two integers by value. define internal i32 @f(%struct.ss* inalloca %s) { -; ATTRIBUTOR-LABEL: define {{[^@]+}}@f -; ATTRIBUTOR-SAME: (%struct.ss* inalloca noalias nocapture nofree nonnull align 4 dereferenceable(8) [[S:%.*]]) -; ATTRIBUTOR-NEXT: entry: -; ATTRIBUTOR-NEXT: [[F0:%.*]] = getelementptr [[STRUCT_SS:%.*]], %struct.ss* [[S]], i32 0, i32 0 -; ATTRIBUTOR-NEXT: [[F1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 -; ATTRIBUTOR-NEXT: [[A:%.*]] = load i32, i32* [[F0]], align 4 -; ATTRIBUTOR-NEXT: [[B:%.*]] = load i32, i32* [[F1]], align 4 -; ATTRIBUTOR-NEXT: [[R:%.*]] = add i32 [[A]], [[B]] -; ATTRIBUTOR-NEXT: ret i32 [[R]] +; IS__TUNIT____-LABEL: define {{[^@]+}}@f +; IS__TUNIT____-SAME: (%struct.ss* inalloca noalias nocapture nofree nonnull align 4 dereferenceable(8) [[S:%.*]]) +; IS__TUNIT____-NEXT: entry: +; 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: [[A:%.*]] = load i32, i32* [[F0]], align 4 +; IS__TUNIT____-NEXT: [[B:%.*]] = load i32, i32* [[F1]], align 4 +; IS__TUNIT____-NEXT: [[R:%.*]] = add i32 [[A]], [[B]] +; IS__TUNIT____-NEXT: ret i32 [[R]] ; -; GLOBALOPT_ATTRIBUTOR-LABEL: define {{[^@]+}}@f -; GLOBALOPT_ATTRIBUTOR-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) unnamed_addr -; GLOBALOPT_ATTRIBUTOR-NEXT: entry: -; GLOBALOPT_ATTRIBUTOR-NEXT: [[S_PRIV:%.*]] = alloca [[STRUCT_SS:%.*]] -; GLOBALOPT_ATTRIBUTOR-NEXT: [[S_PRIV_CAST:%.*]] = bitcast %struct.ss* [[S_PRIV]] to i32* -; GLOBALOPT_ATTRIBUTOR-NEXT: store i32 [[TMP0]], i32* [[S_PRIV_CAST]] -; GLOBALOPT_ATTRIBUTOR-NEXT: [[S_PRIV_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S_PRIV]], i32 0, i32 1 -; GLOBALOPT_ATTRIBUTOR-NEXT: store i32 [[TMP1]], i32* [[S_PRIV_0_1]] -; GLOBALOPT_ATTRIBUTOR-NEXT: [[F0:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S_PRIV]], i32 0, i32 0 -; GLOBALOPT_ATTRIBUTOR-NEXT: [[F1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S_PRIV]], i32 0, i32 1 -; GLOBALOPT_ATTRIBUTOR-NEXT: [[A:%.*]] = load i32, i32* [[F0]], align 4 -; GLOBALOPT_ATTRIBUTOR-NEXT: [[B:%.*]] = load i32, i32* [[F1]], align 4 -; GLOBALOPT_ATTRIBUTOR-NEXT: [[R:%.*]] = add i32 [[A]], [[B]] -; GLOBALOPT_ATTRIBUTOR-NEXT: ret i32 [[R]] +; IS__CGSCC____-LABEL: define {{[^@]+}}@f +; IS__CGSCC____-SAME: (%struct.ss* inalloca nocapture nofree nonnull align 4 dereferenceable(8) [[S:%.*]]) +; IS__CGSCC____-NEXT: entry: +; 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: [[A:%.*]] = load i32, i32* [[F0]], align 4 +; IS__CGSCC____-NEXT: [[B:%.*]] = load i32, i32* [[F1]], align 4 +; IS__CGSCC____-NEXT: [[R:%.*]] = add i32 [[A]], [[B]] +; IS__CGSCC____-NEXT: ret i32 [[R]] ; entry: %f0 = getelementptr %struct.ss, %struct.ss* %s, i32 0, i32 0 @@ -43,29 +40,25 @@ } define i32 @main() { -; ATTRIBUTOR-LABEL: define {{[^@]+}}@main() -; ATTRIBUTOR-NEXT: entry: -; ATTRIBUTOR-NEXT: [[S:%.*]] = alloca inalloca [[STRUCT_SS:%.*]] -; ATTRIBUTOR-NEXT: [[F0:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 -; ATTRIBUTOR-NEXT: [[F1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 -; ATTRIBUTOR-NEXT: store i32 1, i32* [[F0]], align 4 -; ATTRIBUTOR-NEXT: store i32 2, i32* [[F1]], align 4 -; ATTRIBUTOR-NEXT: [[R:%.*]] = call i32 @f(%struct.ss* inalloca noalias nocapture nofree nonnull align 4 dereferenceable(8) [[S]]) -; ATTRIBUTOR-NEXT: ret i32 [[R]] +; IS__TUNIT____-LABEL: define {{[^@]+}}@main() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[S:%.*]] = alloca inalloca [[STRUCT_SS:%.*]] +; 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]] ; -; GLOBALOPT_ATTRIBUTOR-LABEL: define {{[^@]+}}@main() local_unnamed_addr -; GLOBALOPT_ATTRIBUTOR-NEXT: entry: -; GLOBALOPT_ATTRIBUTOR-NEXT: [[S:%.*]] = alloca inalloca [[STRUCT_SS:%.*]] -; GLOBALOPT_ATTRIBUTOR-NEXT: [[F0:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0 -; GLOBALOPT_ATTRIBUTOR-NEXT: [[F1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 -; GLOBALOPT_ATTRIBUTOR-NEXT: store i32 1, i32* [[F0]], align 4 -; GLOBALOPT_ATTRIBUTOR-NEXT: store i32 2, i32* [[F1]], align 4 -; GLOBALOPT_ATTRIBUTOR-NEXT: [[S_CAST:%.*]] = bitcast %struct.ss* [[S]] to i32* -; GLOBALOPT_ATTRIBUTOR-NEXT: [[TMP0:%.*]] = load i32, i32* [[S_CAST]], align 1 -; GLOBALOPT_ATTRIBUTOR-NEXT: [[S_0_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1 -; GLOBALOPT_ATTRIBUTOR-NEXT: [[TMP1:%.*]] = load i32, i32* [[S_0_1]], align 1 -; GLOBALOPT_ATTRIBUTOR-NEXT: [[R:%.*]] = call fastcc i32 @f(i32 [[TMP0]], i32 [[TMP1]]) -; GLOBALOPT_ATTRIBUTOR-NEXT: ret i32 [[R]] +; IS__CGSCC____-LABEL: define {{[^@]+}}@main() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[S:%.*]] = alloca inalloca [[STRUCT_SS:%.*]] +; 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 nofree nonnull align 4 dereferenceable(8) [[S]]) +; IS__CGSCC____-NEXT: ret i32 [[R]] ; entry: %S = alloca inalloca %struct.ss @@ -79,19 +72,20 @@ ; Argpromote can't promote %a because of the icmp use. define internal i1 @g(%struct.ss* %a, %struct.ss* inalloca %b) nounwind { +; IS__CGSCC____-LABEL: define {{[^@]+}}@g +; IS__CGSCC____-SAME: (%struct.ss* nocapture nofree readnone [[A:%.*]], %struct.ss* inalloca nocapture nofree writeonly [[B:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i1 undef +; entry: %c = icmp eq %struct.ss* %a, %b ret i1 %c } define i32 @test() { -; ATTRIBUTOR-LABEL: define {{[^@]+}}@test() -; ATTRIBUTOR-NEXT: entry: -; ATTRIBUTOR-NEXT: ret i32 0 -; -; GLOBALOPT_ATTRIBUTOR-LABEL: define {{[^@]+}}@test() local_unnamed_addr -; GLOBALOPT_ATTRIBUTOR-NEXT: entry: -; GLOBALOPT_ATTRIBUTOR-NEXT: ret i32 0 +; CHECK-LABEL: define {{[^@]+}}@test() +; CHECK-NEXT: entry: +; CHECK-NEXT: ret i32 0 ; entry: %S = alloca inalloca %struct.ss 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,13 +1,9 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -basicaa -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=4 < %s | FileCheck %s --check-prefixes=CHECK,OLDPM,OLDPM_MODULE -; RUN: opt -S -basicaa -attributor-cgscc -attributor-disable=false < %s | FileCheck %s --check-prefixes=CHECK,OLDPM,OLDPM_CGSCC -; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=4 < %s | FileCheck %s --check-prefixes=CHECK,NEWPM,NEWPM_MODULE -; RUN: opt -S -passes='attributor-cgscc' -aa-pipeline='basic-aa' -attributor-disable=false < %s | FileCheck %s --check-prefixes=CHECK,NEWPM,NEWPM_CGSCC +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 -; OLDPM_MODULE-NOT: @dead -; NEWPM_MODULE-NOT: @dead -; OLDPM_CGSCC-NOT: @dead -; NEWPM_CGSCC-NOT: @dead define internal void @dead() { call i32 @test(i32* null, i32* null) @@ -15,23 +11,23 @@ } define internal i32 @test(i32* %X, i32* %Y) { -; OLDPM_CGSCC-LABEL: define {{[^@]+}}@test -; OLDPM_CGSCC-SAME: (i32* noalias nocapture nofree writeonly align 4 [[X:%.*]]) -; OLDPM_CGSCC-NEXT: br i1 true, label [[LIVE:%.*]], label [[DEAD:%.*]] -; OLDPM_CGSCC: live: -; OLDPM_CGSCC-NEXT: store i32 0, i32* [[X]], align 4 -; OLDPM_CGSCC-NEXT: ret i32 undef -; OLDPM_CGSCC: dead: -; OLDPM_CGSCC-NEXT: unreachable +; 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:%.*]] +; IS__CGSCC_OPM: live: +; IS__CGSCC_OPM-NEXT: store i32 0, i32* [[X]], align 4 +; IS__CGSCC_OPM-NEXT: ret i32 undef +; IS__CGSCC_OPM: dead: +; IS__CGSCC_OPM-NEXT: unreachable ; -; NEWPM_CGSCC-LABEL: define {{[^@]+}}@test -; NEWPM_CGSCC-SAME: (i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[X:%.*]]) -; NEWPM_CGSCC-NEXT: br i1 true, label [[LIVE:%.*]], label [[DEAD:%.*]] -; NEWPM_CGSCC: live: -; NEWPM_CGSCC-NEXT: store i32 0, i32* [[X]], align 4 -; NEWPM_CGSCC-NEXT: ret i32 undef -; NEWPM_CGSCC: dead: -; NEWPM_CGSCC-NEXT: unreachable +; 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:%.*]] +; IS__CGSCC_NPM: live: +; IS__CGSCC_NPM-NEXT: store i32 0, i32* [[X]], align 4 +; IS__CGSCC_NPM-NEXT: ret i32 undef +; IS__CGSCC_NPM: dead: +; IS__CGSCC_NPM-NEXT: unreachable ; br i1 true, label %live, label %dead live: @@ -44,17 +40,17 @@ } define internal i32 @caller(i32* %B) { -; OLDPM_CGSCC-LABEL: define {{[^@]+}}@caller() -; OLDPM_CGSCC-NEXT: [[A:%.*]] = alloca i32 -; OLDPM_CGSCC-NEXT: store i32 1, i32* [[A]], align 4 -; OLDPM_CGSCC-NEXT: [[C:%.*]] = call i32 @test(i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A]]) -; OLDPM_CGSCC-NEXT: ret i32 0 +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@caller() +; IS__CGSCC_OPM-NEXT: [[A:%.*]] = alloca i32 +; 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 ; -; NEWPM_CGSCC-LABEL: define {{[^@]+}}@caller() -; NEWPM_CGSCC-NEXT: [[A:%.*]] = alloca i32 -; NEWPM_CGSCC-NEXT: store i32 1, i32* [[A]], align 4 -; NEWPM_CGSCC-NEXT: [[C:%.*]] = call i32 @test(i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A]]) -; NEWPM_CGSCC-NEXT: ret i32 undef +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@caller() +; IS__CGSCC_NPM-NEXT: [[A:%.*]] = alloca i32 +; IS__CGSCC_NPM-NEXT: store i32 1, i32* [[A]], align 4 +; IS__CGSCC_NPM-NEXT: [[C:%.*]] = call i32 @test(i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[A]]) +; IS__CGSCC_NPM-NEXT: ret i32 undef ; %A = alloca i32 store i32 1, i32* %A 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,13 +1,9 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -basicaa -attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=7 < %s | FileCheck %s --check-prefixes=CHECK,OLDPM,OLDPM_MODULE -; RUN: opt -S -basicaa -attributor-cgscc -attributor-disable=false < %s | FileCheck %s --check-prefixes=CHECK,OLDPM,OLDPM_CGSCC -; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=7 < %s | FileCheck %s --check-prefixes=CHECK,NEWPM,NEWPM_MODULE -; RUN: opt -S -passes='attributor-cgscc' -aa-pipeline='basic-aa' -attributor-disable=false < %s | FileCheck %s --check-prefixes=CHECK,NEWPM,NEWPM_CGSCC +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 -; OLDPM_MODULE-NOT: @dead -; NEWPM_MODULE-NOT: @dead -; OLDPM_CGSCC-NOT: @dead -; NEWPM_CGSCC-NOT: @dead define internal void @dead() { call i32 @test(i32* null, i32* null) @@ -15,41 +11,23 @@ } define internal i32 @test(i32* %X, i32* %Y) { -; OLDPM_MODULE-LABEL: define {{[^@]+}}@test -; OLDPM_MODULE-SAME: (i32* noalias nocapture nofree writeonly align 4 [[X:%.*]]) -; OLDPM_MODULE-NEXT: br i1 true, label [[LIVE:%.*]], label [[DEAD:%.*]] -; OLDPM_MODULE: live: -; OLDPM_MODULE-NEXT: store i32 0, i32* [[X]], align 4 -; OLDPM_MODULE-NEXT: ret i32 undef -; OLDPM_MODULE: dead: -; OLDPM_MODULE-NEXT: unreachable +; 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:%.*]] +; IS__TUNIT____: live: +; IS__TUNIT____-NEXT: store i32 0, i32* [[X]], align 4 +; IS__TUNIT____-NEXT: ret i32 undef +; IS__TUNIT____: dead: +; IS__TUNIT____-NEXT: unreachable ; -; OLDPM_CGSCC-LABEL: define {{[^@]+}}@test -; OLDPM_CGSCC-SAME: (i32* nocapture nofree writeonly [[X:%.*]]) -; OLDPM_CGSCC-NEXT: br i1 true, label [[LIVE:%.*]], label [[DEAD:%.*]] -; OLDPM_CGSCC: live: -; OLDPM_CGSCC-NEXT: store i32 0, i32* [[X]] -; OLDPM_CGSCC-NEXT: ret i32 undef -; OLDPM_CGSCC: dead: -; OLDPM_CGSCC-NEXT: unreachable -; -; NEWPM_MODULE-LABEL: define {{[^@]+}}@test -; NEWPM_MODULE-SAME: (i32* noalias nocapture nofree writeonly align 4 [[X:%.*]]) -; NEWPM_MODULE-NEXT: br i1 true, label [[LIVE:%.*]], label [[DEAD:%.*]] -; NEWPM_MODULE: live: -; NEWPM_MODULE-NEXT: store i32 0, i32* [[X]], align 4 -; NEWPM_MODULE-NEXT: ret i32 undef -; NEWPM_MODULE: dead: -; NEWPM_MODULE-NEXT: unreachable -; -; NEWPM_CGSCC-LABEL: define {{[^@]+}}@test -; NEWPM_CGSCC-SAME: (i32* nocapture nofree writeonly [[X:%.*]]) -; NEWPM_CGSCC-NEXT: br i1 true, label [[LIVE:%.*]], label [[DEAD:%.*]] -; NEWPM_CGSCC: live: -; NEWPM_CGSCC-NEXT: store i32 0, i32* [[X]] -; NEWPM_CGSCC-NEXT: ret i32 undef -; NEWPM_CGSCC: dead: -; NEWPM_CGSCC-NEXT: unreachable +; IS__CGSCC____-LABEL: define {{[^@]+}}@test +; IS__CGSCC____-SAME: (i32* nocapture nofree writeonly [[X:%.*]]) +; IS__CGSCC____-NEXT: br i1 true, label [[LIVE:%.*]], label [[DEAD:%.*]] +; IS__CGSCC____: live: +; IS__CGSCC____-NEXT: store i32 0, i32* [[X]] +; IS__CGSCC____-NEXT: ret i32 undef +; IS__CGSCC____: dead: +; IS__CGSCC____-NEXT: unreachable ; br i1 true, label %live, label %dead live: @@ -62,33 +40,26 @@ } define internal i32 @caller(i32* %B) { -; OLDPM_MODULE-LABEL: define {{[^@]+}}@caller -; OLDPM_MODULE-SAME: (i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[B:%.*]]) -; OLDPM_MODULE-NEXT: [[A:%.*]] = alloca i32 -; OLDPM_MODULE-NEXT: store i32 1, i32* [[A]], align 4 -; OLDPM_MODULE-NEXT: [[C:%.*]] = call i32 @test(i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[B]]) -; OLDPM_MODULE-NEXT: ret i32 undef -; -; OLDPM_CGSCC-LABEL: define {{[^@]+}}@caller -; OLDPM_CGSCC-SAME: (i32* nocapture nofree writeonly [[B:%.*]]) -; OLDPM_CGSCC-NEXT: [[A:%.*]] = alloca i32 -; OLDPM_CGSCC-NEXT: store i32 1, i32* [[A]], align 4 -; OLDPM_CGSCC-NEXT: [[C:%.*]] = call i32 @test(i32* nocapture nofree writeonly [[B]]) -; OLDPM_CGSCC-NEXT: ret i32 0 +; 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 +; IS__TUNIT____-NEXT: store i32 1, i32* [[A]], align 4 +; IS__TUNIT____-NEXT: [[C:%.*]] = call i32 @test(i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[B]]) +; IS__TUNIT____-NEXT: ret i32 undef ; -; NEWPM_MODULE-LABEL: define {{[^@]+}}@caller -; NEWPM_MODULE-SAME: (i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[B:%.*]]) -; NEWPM_MODULE-NEXT: [[A:%.*]] = alloca i32 -; NEWPM_MODULE-NEXT: store i32 1, i32* [[A]], align 4 -; NEWPM_MODULE-NEXT: [[C:%.*]] = call i32 @test(i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[B]]) -; NEWPM_MODULE-NEXT: ret i32 undef +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@caller +; IS__CGSCC_OPM-SAME: (i32* nocapture nofree writeonly [[B:%.*]]) +; IS__CGSCC_OPM-NEXT: [[A:%.*]] = alloca i32 +; IS__CGSCC_OPM-NEXT: store i32 1, i32* [[A]], align 4 +; IS__CGSCC_OPM-NEXT: [[C:%.*]] = call i32 @test(i32* nocapture nofree writeonly [[B]]) +; IS__CGSCC_OPM-NEXT: ret i32 0 ; -; NEWPM_CGSCC-LABEL: define {{[^@]+}}@caller -; NEWPM_CGSCC-SAME: (i32* nocapture nofree writeonly [[B:%.*]]) -; NEWPM_CGSCC-NEXT: [[A:%.*]] = alloca i32 -; NEWPM_CGSCC-NEXT: store i32 1, i32* [[A]], align 4 -; NEWPM_CGSCC-NEXT: [[C:%.*]] = call i32 @test(i32* nocapture nofree writeonly [[B]]) -; NEWPM_CGSCC-NEXT: ret i32 undef +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@caller +; IS__CGSCC_NPM-SAME: (i32* nocapture nofree writeonly [[B:%.*]]) +; IS__CGSCC_NPM-NEXT: [[A:%.*]] = alloca i32 +; IS__CGSCC_NPM-NEXT: store i32 1, i32* [[A]], align 4 +; IS__CGSCC_NPM-NEXT: [[C:%.*]] = call i32 @test(i32* nocapture nofree writeonly [[B]]) +; IS__CGSCC_NPM-NEXT: ret i32 undef ; %A = alloca i32 store i32 1, i32* %A @@ -97,29 +68,17 @@ } define i32 @callercaller() { -; OLDPM_MODULE-LABEL: define {{[^@]+}}@callercaller() -; OLDPM_MODULE-NEXT: [[B:%.*]] = alloca i32 -; OLDPM_MODULE-NEXT: store i32 2, i32* [[B]], align 4 -; OLDPM_MODULE-NEXT: [[X:%.*]] = call i32 @caller(i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[B]]) -; OLDPM_MODULE-NEXT: ret i32 0 -; -; OLDPM_CGSCC-LABEL: define {{[^@]+}}@callercaller() -; OLDPM_CGSCC-NEXT: [[B:%.*]] = alloca i32 -; OLDPM_CGSCC-NEXT: store i32 2, i32* [[B]], align 4 -; OLDPM_CGSCC-NEXT: [[X:%.*]] = call i32 @caller(i32* noalias nofree nonnull writeonly align 4 dereferenceable(4) [[B]]) -; OLDPM_CGSCC-NEXT: ret i32 0 -; -; NEWPM_MODULE-LABEL: define {{[^@]+}}@callercaller() -; NEWPM_MODULE-NEXT: [[B:%.*]] = alloca i32 -; NEWPM_MODULE-NEXT: store i32 2, i32* [[B]], align 4 -; NEWPM_MODULE-NEXT: [[X:%.*]] = call i32 @caller(i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[B]]) -; NEWPM_MODULE-NEXT: ret i32 0 +; IS__TUNIT____-LABEL: define {{[^@]+}}@callercaller() +; IS__TUNIT____-NEXT: [[B:%.*]] = alloca i32 +; IS__TUNIT____-NEXT: store i32 2, i32* [[B]], align 4 +; IS__TUNIT____-NEXT: [[X:%.*]] = call i32 @caller(i32* noalias nocapture nofree nonnull writeonly align 4 dereferenceable(4) [[B]]) +; IS__TUNIT____-NEXT: ret i32 0 ; -; NEWPM_CGSCC-LABEL: define {{[^@]+}}@callercaller() -; NEWPM_CGSCC-NEXT: [[B:%.*]] = alloca i32 -; NEWPM_CGSCC-NEXT: store i32 2, i32* [[B]], align 4 -; NEWPM_CGSCC-NEXT: [[X:%.*]] = call i32 @caller(i32* noalias nofree nonnull writeonly align 4 dereferenceable(4) [[B]]) -; NEWPM_CGSCC-NEXT: ret i32 0 +; IS__CGSCC____-LABEL: define {{[^@]+}}@callercaller() +; IS__CGSCC____-NEXT: [[B:%.*]] = alloca i32 +; IS__CGSCC____-NEXT: store i32 2, i32* [[B]], align 4 +; IS__CGSCC____-NEXT: [[X:%.*]] = call i32 @caller(i32* noalias nofree nonnull writeonly align 4 dereferenceable(4) [[B]]) +; IS__CGSCC____-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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; PR36543 ; Don't promote arguments of musttail callee @@ -45,6 +48,16 @@ } define internal i32 @test2(%T* %p, i32 %p2) { +; 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 +; 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 @foo(%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 %a = load i32, i32* %a.gep @@ -55,9 +68,14 @@ } define i32 @caller2(%T* %g) { -; CHECK-LABEL: define {{[^@]+}}@caller2 -; CHECK-SAME: (%T* nocapture nofree readnone [[G:%.*]]) -; CHECK-NEXT: ret i32 0 +; IS__TUNIT____-LABEL: define {{[^@]+}}@caller2 +; IS__TUNIT____-SAME: (%T* nocapture nofree readnone [[G:%.*]]) +; IS__TUNIT____-NEXT: ret i32 0 +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@caller2 +; IS__CGSCC____-SAME: (%T* nocapture nofree readonly [[G:%.*]]) +; IS__CGSCC____-NEXT: [[V:%.*]] = call i32 @test2(%T* nocapture nofree readonly [[G]], i32 0) +; IS__CGSCC____-NEXT: ret i32 [[V]] ; %v = call i32 @test2(%T* %g, i32 0) ret i32 %v @@ -100,10 +118,15 @@ } define i32 @caller2b(%T* %g) { -; CHECK-LABEL: define {{[^@]+}}@caller2b -; CHECK-SAME: (%T* nocapture nofree readonly [[G:%.*]]) -; CHECK-NEXT: [[V:%.*]] = call i32 @test2b(%T* nocapture nofree readonly [[G]], i32 undef) -; CHECK-NEXT: ret i32 0 +; 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____-LABEL: define {{[^@]+}}@caller2b +; IS__CGSCC____-SAME: (%T* nocapture nofree readonly [[G:%.*]]) +; IS__CGSCC____-NEXT: [[V:%.*]] = call i32 @test2b(%T* nocapture nofree readonly [[G]], i32 0) +; IS__CGSCC____-NEXT: ret i32 [[V]] ; %v = call i32 @test2b(%T* %g, i32 0) ret i32 %v 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; Don't promote paramaters of/arguments to naked functions 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; ArgumentPromotion should preserve the default function address space ; from the data layout. 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 target triple = "x86_64-pc-windows-msvc" define internal void @callee(i8*) { diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/pr3085.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/pr3085.ll deleted file mode 100644 --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/pr3085.ll +++ /dev/null @@ -1,1945 +0,0 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -disable-output -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s -; PR 3085 - - %struct.Lit = type { i8 } - -define fastcc %struct.Lit* @import_lit(i32 %lit) nounwind { -entry: - br i1 false, label %bb, label %bb1 - -bb: ; preds = %entry - unreachable - -bb1: ; preds = %entry - br label %bb3 - -bb2: ; preds = %bb3 - br label %bb3 - -bb3: ; preds = %bb2, %bb1 - br i1 false, label %bb2, label %bb6 - -bb6: ; preds = %bb3 - br i1 false, label %bb.i.i, label %bb1.i.i - -bb.i.i: ; preds = %bb6 - br label %int2lit.exit - -bb1.i.i: ; preds = %bb6 - br label %int2lit.exit - -int2lit.exit: ; preds = %bb1.i.i, %bb.i.i - ret %struct.Lit* null -} - -define fastcc i32 @picosat_main(i32 %argc, i8** %argv) nounwind { -entry: - br i1 false, label %bb.i, label %picosat_time_stamp.exit - -bb.i: ; preds = %entry - br label %picosat_time_stamp.exit - -picosat_time_stamp.exit: ; preds = %bb.i, %entry - br label %bb108 - -bb: ; preds = %bb108 - br i1 false, label %bb1, label %bb2 - -bb1: ; preds = %bb - br label %bb106 - -bb2: ; preds = %bb - br i1 false, label %bb3, label %bb4 - -bb3: ; preds = %bb2 - br label %bb106 - -bb4: ; preds = %bb2 - br i1 false, label %bb5, label %bb6 - -bb5: ; preds = %bb4 - br label %bb106 - -bb6: ; preds = %bb4 - br i1 false, label %bb7, label %bb8 - -bb7: ; preds = %bb6 - br label %bb106 - -bb8: ; preds = %bb6 - br i1 false, label %bb106, label %bb10 - -bb10: ; preds = %bb8 - br i1 false, label %bb106, label %bb12 - -bb12: ; preds = %bb10 - br i1 false, label %bb106, label %bb14 - -bb14: ; preds = %bb12 - br i1 false, label %bb15, label %bb19 - -bb15: ; preds = %bb14 - br i1 false, label %bb16, label %bb17 - -bb16: ; preds = %bb15 - br label %bb106 - -bb17: ; preds = %bb15 - br label %bb106 - -bb19: ; preds = %bb14 - br i1 false, label %bb20, label %bb28 - -bb20: ; preds = %bb19 - br i1 false, label %bb21, label %bb22 - -bb21: ; preds = %bb20 - br label %bb106 - -bb22: ; preds = %bb20 - br i1 false, label %bb106, label %bb24 - -bb24: ; preds = %bb22 - br i1 false, label %bb106, label %bb26 - -bb26: ; preds = %bb24 - br label %bb106 - -bb28: ; preds = %bb19 - br i1 false, label %bb29, label %bb35 - -bb29: ; preds = %bb28 - br i1 false, label %bb30, label %bb31 - -bb30: ; preds = %bb29 - br label %bb106 - -bb31: ; preds = %bb29 - br i1 false, label %bb32, label %bb33 - -bb32: ; preds = %bb31 - br label %bb106 - -bb33: ; preds = %bb31 - br label %bb106 - -bb35: ; preds = %bb28 - br i1 false, label %bb36, label %bb40 - -bb36: ; preds = %bb35 - br i1 false, label %bb37, label %bb38 - -bb37: ; preds = %bb36 - br label %bb106 - -bb38: ; preds = %bb36 - br label %bb106 - -bb40: ; preds = %bb35 - br i1 false, label %bb41, label %bb49 - -bb41: ; preds = %bb40 - br i1 false, label %bb43, label %bb42 - -bb42: ; preds = %bb41 - br label %bb106 - -bb43: ; preds = %bb41 - br i1 false, label %bb44, label %bb45 - -bb44: ; preds = %bb43 - br label %bb106 - -bb45: ; preds = %bb43 - br i1 false, label %bb46, label %bb47 - -bb46: ; preds = %bb45 - br label %bb106 - -bb47: ; preds = %bb45 - br label %bb106 - -bb49: ; preds = %bb40 - br i1 false, label %bb50, label %bb56 - -bb50: ; preds = %bb49 - br i1 false, label %bb52, label %bb51 - -bb51: ; preds = %bb50 - br label %bb106 - -bb52: ; preds = %bb50 - br i1 false, label %bb53, label %bb54 - -bb53: ; preds = %bb52 - br label %bb106 - -bb54: ; preds = %bb52 - br label %bb106 - -bb56: ; preds = %bb49 - br i1 false, label %bb57, label %bb63 - -bb57: ; preds = %bb56 - br i1 false, label %bb59, label %bb58 - -bb58: ; preds = %bb57 - br label %bb106 - -bb59: ; preds = %bb57 - br i1 false, label %bb60, label %bb61 - -bb60: ; preds = %bb59 - br label %bb106 - -bb61: ; preds = %bb59 - br label %bb106 - -bb63: ; preds = %bb56 - br i1 false, label %bb64, label %bb70 - -bb64: ; preds = %bb63 - br i1 false, label %bb66, label %bb65 - -bb65: ; preds = %bb64 - br label %bb106 - -bb66: ; preds = %bb64 - br i1 false, label %bb67, label %bb68 - -bb67: ; preds = %bb66 - br label %bb106 - -bb68: ; preds = %bb66 - br label %bb106 - -bb70: ; preds = %bb63 - br i1 false, label %bb71, label %bb79 - -bb71: ; preds = %bb70 - br i1 false, label %bb73, label %bb72 - -bb72: ; preds = %bb71 - br label %bb106 - -bb73: ; preds = %bb71 - br i1 false, label %bb74, label %bb75 - -bb74: ; preds = %bb73 - br label %bb106 - -bb75: ; preds = %bb73 - br i1 false, label %bb76, label %bb77 - -bb76: ; preds = %bb75 - br label %bb106 - -bb77: ; preds = %bb75 - br label %bb106 - -bb79: ; preds = %bb70 - br i1 false, label %bb80, label %bb86 - -bb80: ; preds = %bb79 - br i1 false, label %bb82, label %bb81 - -bb81: ; preds = %bb80 - br label %bb106 - -bb82: ; preds = %bb80 - br i1 false, label %bb83, label %bb84 - -bb83: ; preds = %bb82 - br label %bb106 - -bb84: ; preds = %bb82 - br label %bb106 - -bb86: ; preds = %bb79 - br i1 false, label %bb87, label %bb93 - -bb87: ; preds = %bb86 - br i1 false, label %bb89, label %bb88 - -bb88: ; preds = %bb87 - br label %bb106 - -bb89: ; preds = %bb87 - br i1 false, label %bb90, label %bb91 - -bb90: ; preds = %bb89 - br label %bb106 - -bb91: ; preds = %bb89 - br label %bb106 - -bb93: ; preds = %bb86 - br i1 false, label %bb94, label %bb95 - -bb94: ; preds = %bb93 - br label %bb106 - -bb95: ; preds = %bb93 - br i1 false, label %bb98, label %bb97 - -bb97: ; preds = %bb95 - br label %bb106 - -bb98: ; preds = %bb95 - br i1 false, label %bb103, label %bb1.i24 - -bb1.i24: ; preds = %bb98 - br i1 false, label %bb99, label %bb103 - -bb99: ; preds = %bb1.i24 - br i1 false, label %bb101, label %bb100 - -bb100: ; preds = %bb99 - br label %bb102 - -bb101: ; preds = %bb99 - br label %bb102 - -bb102: ; preds = %bb101, %bb100 - br label %bb106 - -bb103: ; preds = %bb1.i24, %bb98 - br i1 false, label %bb104, label %bb105 - -bb104: ; preds = %bb103 - br label %bb106 - -bb105: ; preds = %bb103 - br label %bb106 - -bb106: ; preds = %bb105, %bb104, %bb102, %bb97, %bb94, %bb91, %bb90, %bb88, %bb84, %bb83, %bb81, %bb77, %bb76, %bb74, %bb72, %bb68, %bb67, %bb65, %bb61, %bb60, %bb58, %bb54, %bb53, %bb51, %bb47, %bb46, %bb44, %bb42, %bb38, %bb37, %bb33, %bb32, %bb30, %bb26, %bb24, %bb22, %bb21, %bb17, %bb16, %bb12, %bb10, %bb8, %bb7, %bb5, %bb3, %bb1 - br i1 false, label %bb108, label %bb110 - -bb108: ; preds = %bb106, %picosat_time_stamp.exit - br i1 false, label %bb, label %bb110 - -bb110: ; preds = %bb108, %bb106 - br i1 false, label %bb112, label %bb171 - -bb112: ; preds = %bb110 - br i1 false, label %bb114, label %bb113 - -bb113: ; preds = %bb112 - br label %bb114 - -bb114: ; preds = %bb113, %bb112 - br i1 false, label %bb.i.i35, label %bb1.i.i36 - -bb.i.i35: ; preds = %bb114 - unreachable - -bb1.i.i36: ; preds = %bb114 - br i1 false, label %bb5.i.i.i41, label %bb6.i.i.i42 - -bb5.i.i.i41: ; preds = %bb1.i.i36 - unreachable - -bb6.i.i.i42: ; preds = %bb1.i.i36 - br i1 false, label %bb7.i.i.i43, label %bb8.i.i.i44 - -bb7.i.i.i43: ; preds = %bb6.i.i.i42 - br label %bb8.i.i.i44 - -bb8.i.i.i44: ; preds = %bb7.i.i.i43, %bb6.i.i.i42 - br i1 false, label %picosat_init.exit, label %bb14.i.i - -bb14.i.i: ; preds = %bb8.i.i.i44 - br label %picosat_init.exit - -picosat_init.exit: ; preds = %bb14.i.i, %bb8.i.i.i44 - br i1 false, label %bb116, label %bb115 - -bb115: ; preds = %picosat_init.exit - br label %bb116 - -bb116: ; preds = %bb115, %picosat_init.exit - br i1 false, label %bb119, label %bb118 - -bb118: ; preds = %bb116 - br label %bb119 - -bb119: ; preds = %bb118, %bb116 - br i1 false, label %bb121, label %bb120 - -bb120: ; preds = %bb119 - br label %bb121 - -bb121: ; preds = %bb120, %bb119 - br i1 false, label %bb126, label %bb122 - -bb122: ; preds = %bb121 - br label %bb126 - -bb126: ; preds = %bb122, %bb121 - br i1 false, label %bb128, label %bb127 - -bb127: ; preds = %bb126 - br label %bb128 - -bb128: ; preds = %bb127, %bb126 - br label %SKIP_COMMENTS.i - -SKIP_COMMENTS.i.loopexit: ; preds = %bb.i149, %bb.i149 - br label %SKIP_COMMENTS.i.backedge - -SKIP_COMMENTS.i: ; preds = %SKIP_COMMENTS.i.backedge, %bb128 - br i1 false, label %bb.i149.preheader, label %bb3.i152 - -bb.i149.preheader: ; preds = %SKIP_COMMENTS.i - br label %bb.i149 - -bb.i149: ; preds = %bb.i149, %bb.i149.preheader - switch i32 0, label %bb.i149 [ - i32 -1, label %SKIP_COMMENTS.i.loopexit - i32 10, label %SKIP_COMMENTS.i.loopexit - ] - -bb3.i152: ; preds = %SKIP_COMMENTS.i - br i1 false, label %bb4.i153, label %SKIP_COMMENTS.i.backedge - -SKIP_COMMENTS.i.backedge: ; preds = %bb3.i152, %SKIP_COMMENTS.i.loopexit - br label %SKIP_COMMENTS.i - -bb4.i153: ; preds = %bb3.i152 - br i1 false, label %bb5.i154, label %bb129 - -bb5.i154: ; preds = %bb4.i153 - br i1 false, label %bb129, label %bb6.i155.preheader - -bb6.i155.preheader: ; preds = %bb5.i154 - br label %bb6.i155 - -bb6.i155: ; preds = %bb6.i155, %bb6.i155.preheader - br i1 false, label %bb7.i156, label %bb6.i155 - -bb7.i156: ; preds = %bb6.i155 - br i1 false, label %bb8.i157, label %bb129 - -bb8.i157: ; preds = %bb7.i156 - br i1 false, label %bb9.i158, label %bb129 - -bb9.i158: ; preds = %bb8.i157 - br i1 false, label %bb10.i159, label %bb129 - -bb10.i159: ; preds = %bb9.i158 - br i1 false, label %bb129, label %bb11.i160.preheader - -bb11.i160.preheader: ; preds = %bb10.i159 - br label %bb11.i160 - -bb11.i160: ; preds = %bb11.i160, %bb11.i160.preheader - br i1 false, label %bb12.i161, label %bb11.i160 - -bb12.i161: ; preds = %bb11.i160 - br i1 false, label %bb129, label %bb15.i165.preheader - -bb15.i165.preheader: ; preds = %bb12.i161 - br label %bb15.i165 - -bb14.i163: ; preds = %bb15.i165 - br label %bb15.i165 - -bb15.i165: ; preds = %bb14.i163, %bb15.i165.preheader - br i1 false, label %bb16.i166, label %bb14.i163 - -bb16.i166: ; preds = %bb15.i165 - br i1 false, label %bb129, label %bb17.i167.preheader - -bb17.i167.preheader: ; preds = %bb16.i166 - br label %bb17.i167 - -bb17.i167: ; preds = %bb17.i167, %bb17.i167.preheader - br i1 false, label %bb18.i168, label %bb17.i167 - -bb18.i168: ; preds = %bb17.i167 - br i1 false, label %bb129, label %bb21.i172.preheader - -bb21.i172.preheader: ; preds = %bb18.i168 - br label %bb21.i172 - -bb20.i170: ; preds = %bb21.i172 - br label %bb21.i172 - -bb21.i172: ; preds = %bb20.i170, %bb21.i172.preheader - br i1 false, label %bb22.i173, label %bb20.i170 - -bb22.i173: ; preds = %bb21.i172 - br i1 false, label %bb24.i175, label %bb129 - -bb24.i175: ; preds = %bb22.i173 - br i1 false, label %bb26.i180, label %bb25.i176 - -bb25.i176: ; preds = %bb24.i175 - br label %bb26.i180 - -bb26.i180: ; preds = %bb25.i176, %bb24.i175 - br i1 false, label %bb.i.i181, label %bb3.i.i184.preheader - -bb.i.i181: ; preds = %bb26.i180 - br label %bb3.i.i184.preheader - -bb3.i.i184.preheader: ; preds = %bb.i.i181, %bb26.i180 - br label %bb3.i.i184 - -bb2.i.i183: ; preds = %bb3.i.i184 - br label %bb3.i.i184 - -bb3.i.i184: ; preds = %bb2.i.i183, %bb3.i.i184.preheader - br i1 false, label %bb2.i.i183, label %bb4.i.i185 - -bb4.i.i185: ; preds = %bb3.i.i184 - br i1 false, label %bb.i.i.i186, label %picosat_adjust.exit.i - -bb.i.i.i186: ; preds = %bb4.i.i185 - br label %picosat_adjust.exit.i - -picosat_adjust.exit.i: ; preds = %bb.i.i.i186, %bb4.i.i185 - br i1 false, label %bb28.i188, label %bb27.i187 - -bb27.i187: ; preds = %picosat_adjust.exit.i - br label %bb28.i188 - -bb28.i188: ; preds = %bb27.i187, %picosat_adjust.exit.i - br label %READ_LITERAL.i.outer - -READ_LITERAL.i.outer: ; preds = %READ_LITERAL.i.outer.backedge, %bb28.i188 - br label %READ_LITERAL.i - -READ_LITERAL.i.loopexit: ; preds = %bb29.i189, %bb29.i189 - br label %READ_LITERAL.i.backedge - -READ_LITERAL.i: ; preds = %READ_LITERAL.i.backedge, %READ_LITERAL.i.outer - switch i32 0, label %bb39.i199 [ - i32 99, label %bb29.i189.preheader - i32 -1, label %bb33.i193 - ] - -bb29.i189.preheader: ; preds = %READ_LITERAL.i - br label %bb29.i189 - -bb29.i189: ; preds = %bb29.i189, %bb29.i189.preheader - switch i32 0, label %bb29.i189 [ - i32 -1, label %READ_LITERAL.i.loopexit - i32 10, label %READ_LITERAL.i.loopexit - ] - -bb33.i193: ; preds = %READ_LITERAL.i - br i1 false, label %bb35.i195, label %parse.exit - -bb35.i195: ; preds = %bb33.i193 - br i1 false, label %bb38.i198, label %parse.exit - -bb38.i198: ; preds = %bb35.i195 - br label %parse.exit - -bb39.i199: ; preds = %READ_LITERAL.i - br i1 false, label %bb40.i200, label %READ_LITERAL.i.backedge - -READ_LITERAL.i.backedge: ; preds = %bb39.i199, %READ_LITERAL.i.loopexit - br label %READ_LITERAL.i - -bb40.i200: ; preds = %bb39.i199 - br i1 false, label %bb41.i201, label %bb42.i202 - -bb41.i201: ; preds = %bb40.i200 - br label %bb42.i202 - -bb42.i202: ; preds = %bb41.i201, %bb40.i200 - br i1 false, label %parse.exit.loopexit, label %bb46.i.preheader - -bb46.i.preheader: ; preds = %bb42.i202 - br label %bb46.i - -bb45.i: ; preds = %bb46.i - br label %bb46.i - -bb46.i: ; preds = %bb45.i, %bb46.i.preheader - br i1 false, label %bb47.i, label %bb45.i - -bb47.i: ; preds = %bb46.i - br i1 false, label %parse.exit.loopexit, label %bb50.i - -bb50.i: ; preds = %bb47.i - br i1 false, label %bb55.i, label %bb51.i - -bb51.i: ; preds = %bb50.i - br i1 false, label %parse.exit.loopexit, label %bb54.i - -bb54.i: ; preds = %bb51.i - br label %bb56.i - -bb55.i: ; preds = %bb50.i - br label %bb56.i - -bb56.i: ; preds = %bb55.i, %bb54.i - br i1 false, label %bb3.i11.i, label %bb.i8.i - -bb.i8.i: ; preds = %bb56.i - br i1 false, label %bb1.i9.i, label %bb3.i11.i - -bb1.i9.i: ; preds = %bb.i8.i - br i1 false, label %bb3.i11.i, label %bb2.i10.i - -bb2.i10.i: ; preds = %bb1.i9.i - unreachable - -bb3.i11.i: ; preds = %bb1.i9.i, %bb.i8.i, %bb56.i - br i1 false, label %bb7.i.i208, label %bb6.i.i207 - -bb6.i.i207: ; preds = %bb3.i11.i - br label %READ_LITERAL.i.outer.backedge - -bb7.i.i208: ; preds = %bb3.i11.i - br i1 false, label %bb53.i.i.i.i.preheader, label %bb.i.i.i.i210.preheader - -bb.i.i.i.i210.preheader: ; preds = %bb7.i.i208 - br label %bb.i.i.i.i210 - -bb.i.i.i.i210: ; preds = %bb.i.i.i.i210.backedge, %bb.i.i.i.i210.preheader - br i1 false, label %bb17.i.i.i.i, label %bb18.i.i.i.i - -bb17.i.i.i.i: ; preds = %bb.i.i.i.i210 - br label %bb18.i.i.i.i - -bb18.i.i.i.i: ; preds = %bb17.i.i.i.i, %bb.i.i.i.i210 - br i1 false, label %bb19.i.i.i.i, label %bb20.i.i.i.i - -bb19.i.i.i.i: ; preds = %bb18.i.i.i.i - br label %bb20.i.i.i.i - -bb20.i.i.i.i: ; preds = %bb19.i.i.i.i, %bb18.i.i.i.i - br i1 false, label %bb21.i.i.i.i, label %bb22.i.i.i.i - -bb21.i.i.i.i: ; preds = %bb20.i.i.i.i - br label %bb22.i.i.i.i - -bb22.i.i.i.i: ; preds = %bb21.i.i.i.i, %bb20.i.i.i.i - br label %bb23.i.i.i.i.outer - -bb23.i.i.i.i.outer: ; preds = %bb28.i.i.i.i, %bb22.i.i.i.i - br label %bb23.i.i.i.i - -bb23.i.i.i.i: ; preds = %bb23.i.i.i.i, %bb23.i.i.i.i.outer - br i1 false, label %bb23.i.i.i.i, label %bb26.i.i.i.i.preheader - -bb26.i.i.i.i.preheader: ; preds = %bb23.i.i.i.i - br label %bb26.i.i.i.i - -bb26.i.i.i.i: ; preds = %bb26.i.i.i.i, %bb26.i.i.i.i.preheader - br i1 false, label %bb27.i.i.i.i, label %bb26.i.i.i.i - -bb27.i.i.i.i: ; preds = %bb26.i.i.i.i - br i1 false, label %bb28.i.i.i.i, label %bb29.i.i.i.i - -bb28.i.i.i.i: ; preds = %bb27.i.i.i.i - br label %bb23.i.i.i.i.outer - -bb29.i.i.i.i: ; preds = %bb27.i.i.i.i - br i1 false, label %bb33.i.i.i.i, label %bb44.i.i.i.i - -bb33.i.i.i.i: ; preds = %bb29.i.i.i.i - br i1 false, label %bb34.i.i.i.i, label %bb38.i.i.i.i - -bb34.i.i.i.i: ; preds = %bb33.i.i.i.i - br i1 false, label %bb37.i.i.i.i, label %bb35.i.i.i.i - -bb35.i.i.i.i: ; preds = %bb34.i.i.i.i - br label %bb37.i.i.i.i - -bb37.i.i.i.i: ; preds = %bb35.i.i.i.i, %bb34.i.i.i.i - br label %bb38.i.i.i.i - -bb38.i.i.i.i: ; preds = %bb37.i.i.i.i, %bb33.i.i.i.i - br i1 false, label %bb39.i.i.i.i, label %bb43.i.i.i.i - -bb39.i.i.i.i: ; preds = %bb38.i.i.i.i - br i1 false, label %bb42.i.i.i.i, label %bb40.i.i.i.i - -bb40.i.i.i.i: ; preds = %bb39.i.i.i.i - br label %bb42.i.i.i.i - -bb42.i.i.i.i: ; preds = %bb40.i.i.i.i, %bb39.i.i.i.i - br label %bb43.i.i.i.i - -bb43.i.i.i.i: ; preds = %bb42.i.i.i.i, %bb38.i.i.i.i - br label %bb.i.i.i.i210.backedge - -bb.i.i.i.i210.backedge: ; preds = %bb47.i.i.i.i, %bb44.i.i.i.i, %bb43.i.i.i.i - br label %bb.i.i.i.i210 - -bb44.i.i.i.i: ; preds = %bb29.i.i.i.i - br i1 false, label %bb.i.i.i.i210.backedge, label %bb46.i.i.i.i - -bb46.i.i.i.i: ; preds = %bb44.i.i.i.i - br i1 false, label %bb47.i.i.i.i, label %bb53.i.i.i.i.preheader.loopexit - -bb53.i.i.i.i.preheader.loopexit: ; preds = %bb46.i.i.i.i - br label %bb53.i.i.i.i.preheader - -bb53.i.i.i.i.preheader: ; preds = %bb53.i.i.i.i.preheader.loopexit, %bb7.i.i208 - br label %bb53.i.i.i.i - -bb47.i.i.i.i: ; preds = %bb46.i.i.i.i - br label %bb.i.i.i.i210.backedge - -bb50.i.i.i.i: ; preds = %bb53.i.i.i.i - br i1 false, label %bb51.i.i.i.i, label %bb52.i.i.i.i - -bb51.i.i.i.i: ; preds = %bb50.i.i.i.i - br label %bb52.i.i.i.i - -bb52.i.i.i.i: ; preds = %bb51.i.i.i.i, %bb50.i.i.i.i - br label %bb53.i.i.i.i - -bb53.i.i.i.i: ; preds = %bb52.i.i.i.i, %bb53.i.i.i.i.preheader - br i1 false, label %bb50.i.i.i.i, label %bb59.i.i.i.i.preheader - -bb59.i.i.i.i.preheader: ; preds = %bb53.i.i.i.i - br label %bb59.i.i.i.i - -bb55.i.i.i.i: ; preds = %bb59.i.i.i.i - br label %bb57.i.i.i.i - -bb56.i.i.i.i: ; preds = %bb57.i.i.i.i - br label %bb57.i.i.i.i - -bb57.i.i.i.i: ; preds = %bb56.i.i.i.i, %bb55.i.i.i.i - br i1 false, label %bb56.i.i.i.i, label %bb58.i.i.i.i - -bb58.i.i.i.i: ; preds = %bb57.i.i.i.i - br label %bb59.i.i.i.i - -bb59.i.i.i.i: ; preds = %bb58.i.i.i.i, %bb59.i.i.i.i.preheader - br i1 false, label %bb60.i.i.i.i, label %bb55.i.i.i.i - -bb60.i.i.i.i: ; preds = %bb59.i.i.i.i - br label %bb69.i.i.i.i - -bb61.i.i.i.i: ; preds = %bb69.i.i.i.i - br i1 false, label %bb68.i.i.i.i, label %bb62.i.i.i.i - -bb62.i.i.i.i: ; preds = %bb61.i.i.i.i - br i1 false, label %bb63.i.i.i.i, label %bb65.i.i.i.i - -bb63.i.i.i.i: ; preds = %bb62.i.i.i.i - br i1 false, label %bb.i.i12.i, label %bb65.i.i.i.i - -bb65.i.i.i.i: ; preds = %bb63.i.i.i.i, %bb62.i.i.i.i - br i1 false, label %bb.i.i12.i, label %bb67.i.i.i.i - -bb67.i.i.i.i: ; preds = %bb65.i.i.i.i - br label %bb68.i.i.i.i - -bb68.i.i.i.i: ; preds = %bb67.i.i.i.i, %bb61.i.i.i.i - br label %bb69.i.i.i.i - -bb69.i.i.i.i: ; preds = %bb68.i.i.i.i, %bb60.i.i.i.i - br i1 false, label %bb61.i.i.i.i, label %bb70.i.i.i.i - -bb70.i.i.i.i: ; preds = %bb69.i.i.i.i - br label %READ_LITERAL.i.outer.backedge - -bb.i.i12.i: ; preds = %bb65.i.i.i.i, %bb63.i.i.i.i - br i1 false, label %bb1.i.i.i213, label %bb5.i.i.i218 - -bb1.i.i.i213: ; preds = %bb.i.i12.i - br i1 false, label %bb4.i.i.i217, label %bb2.i.i.i214 - -bb2.i.i.i214: ; preds = %bb1.i.i.i213 - br label %bb4.i.i.i217 - -bb4.i.i.i217: ; preds = %bb2.i.i.i214, %bb1.i.i.i213 - br label %bb5.i.i.i218 - -bb5.i.i.i218: ; preds = %bb4.i.i.i217, %bb.i.i12.i - br label %READ_LITERAL.i.outer.backedge - -READ_LITERAL.i.outer.backedge: ; preds = %bb5.i.i.i218, %bb70.i.i.i.i, %bb6.i.i207 - br label %READ_LITERAL.i.outer - -parse.exit.loopexit: ; preds = %bb51.i, %bb47.i, %bb42.i202 - br label %parse.exit - -parse.exit: ; preds = %parse.exit.loopexit, %bb38.i198, %bb35.i195, %bb33.i193 - br i1 false, label %bb130, label %bb129 - -bb129: ; preds = %parse.exit, %bb22.i173, %bb18.i168, %bb16.i166, %bb12.i161, %bb10.i159, %bb9.i158, %bb8.i157, %bb7.i156, %bb5.i154, %bb4.i153 - br label %bb170 - -bb130: ; preds = %parse.exit - br i1 false, label %bb143, label %bb142.preheader - -bb142.preheader: ; preds = %bb130 - br label %bb142 - -bb132: ; preds = %bb142 - br i1 false, label %bb137, label %bb133 - -bb133: ; preds = %bb132 - br i1 false, label %bb137, label %bb134 - -bb134: ; preds = %bb133 - br i1 false, label %bb137, label %bb135 - -bb135: ; preds = %bb134 - br i1 false, label %bb137, label %bb136 - -bb136: ; preds = %bb135 - br i1 false, label %bb137, label %bb138 - -bb137: ; preds = %bb136, %bb135, %bb134, %bb133, %bb132 - br label %bb141 - -bb138: ; preds = %bb136 - br i1 false, label %bb139, label %bb141 - -bb139: ; preds = %bb138 - br i1 false, label %bb2.i126, label %picosat_assume.exit - -bb2.i126: ; preds = %bb139 - br i1 false, label %bb5.i130, label %bb3.i127 - -bb3.i127: ; preds = %bb2.i126 - br label %bb5.i130 - -bb5.i130: ; preds = %bb3.i127, %bb2.i126 - br label %picosat_assume.exit - -picosat_assume.exit: ; preds = %bb5.i130, %bb139 - br i1 false, label %bb141, label %bb140 - -bb140: ; preds = %picosat_assume.exit - br label %bb141 - -bb141: ; preds = %bb140, %picosat_assume.exit, %bb138, %bb137 - br label %bb142 - -bb142: ; preds = %bb141, %bb142.preheader - br i1 false, label %bb132, label %bb143.loopexit - -bb143.loopexit: ; preds = %bb142 - br label %bb143 - -bb143: ; preds = %bb143.loopexit, %bb130 - br i1 false, label %bb145, label %bb144 - -bb144: ; preds = %bb143 - br label %bb11.i - -bb5.i114: ; preds = %bb11.i - br label %bb11.i - -bb11.i: ; preds = %bb5.i114, %bb144 - br i1 false, label %bb12.i, label %bb5.i114 - -bb12.i: ; preds = %bb11.i - br i1 false, label %bb.i.i.i118, label %bb1.i.i.i119 - -bb.i.i.i118: ; preds = %bb12.i - br label %int2lit.exit.i - -bb1.i.i.i119: ; preds = %bb12.i - br label %int2lit.exit.i - -int2lit.exit.i: ; preds = %bb1.i.i.i119, %bb.i.i.i118 - br label %bb19.i - -bb13.i: ; preds = %bb19.i - br label %bb17.i - -bb14.i: ; preds = %bb17.i - br label %bb17.i - -bb17.i: ; preds = %bb14.i, %bb13.i - br i1 false, label %bb14.i, label %bb18.i - -bb18.i: ; preds = %bb17.i - br label %bb19.i - -bb19.i: ; preds = %bb18.i, %int2lit.exit.i - br i1 false, label %bb20.i, label %bb13.i - -bb20.i: ; preds = %bb19.i - br label %bb33.i - -bb24.i: ; preds = %bb33.i - br i1 false, label %bb29.i, label %bb25.i - -bb25.i: ; preds = %bb24.i - br label %bb27.i - -bb26.i: ; preds = %bb27.i - br label %bb27.i - -bb27.i: ; preds = %bb26.i, %bb25.i - br i1 false, label %bb26.i, label %bb28.i - -bb28.i: ; preds = %bb27.i - br label %bb29.i - -bb29.i: ; preds = %bb28.i, %bb24.i - br label %bb33.i - -bb33.i: ; preds = %bb29.i, %bb20.i - br i1 false, label %bb34.i, label %bb24.i - -bb34.i: ; preds = %bb33.i - br i1 false, label %bb.i.i58.i, label %bb1.i.i59.i - -bb.i.i58.i: ; preds = %bb34.i - br label %int2lit.exit63.i - -bb1.i.i59.i: ; preds = %bb34.i - br label %int2lit.exit63.i - -int2lit.exit63.i: ; preds = %bb1.i.i59.i, %bb.i.i58.i - br label %bb41.i - -bb35.i: ; preds = %bb41.i - br label %bb39.i - -bb36.i: ; preds = %bb39.i - br i1 false, label %bb38.i, label %bb37.i - -bb37.i: ; preds = %bb36.i - br label %bb38.i - -bb38.i: ; preds = %bb37.i, %bb36.i - br label %bb39.i - -bb39.i: ; preds = %bb38.i, %bb35.i - br i1 false, label %bb36.i, label %bb40.i - -bb40.i: ; preds = %bb39.i - br label %bb41.i - -bb41.i: ; preds = %bb40.i, %int2lit.exit63.i - br i1 false, label %bb42.i, label %bb35.i - -bb42.i: ; preds = %bb41.i - br label %bb44.i - -bb43.i: ; preds = %bb44.i - br label %bb44.i - -bb44.i: ; preds = %bb43.i, %bb42.i - br i1 false, label %bb43.i, label %picosat_print.exit - -picosat_print.exit: ; preds = %bb44.i - br label %bb167 - -bb145: ; preds = %bb143 - br i1 false, label %bb147, label %bb146 - -bb146: ; preds = %bb145 - br label %bb147 - -bb147: ; preds = %bb146, %bb145 - br i1 false, label %bb149, label %bb148 - -bb148: ; preds = %bb147 - br label %bb149 - -bb149: ; preds = %bb148, %bb147 - br i1 false, label %bb.i54, label %bb1.i55 - -bb.i54: ; preds = %bb149 - unreachable - -bb1.i55: ; preds = %bb149 - br i1 false, label %bb.i.i56, label %bb1.i.i57 - -bb.i.i56: ; preds = %bb1.i55 - br label %bb1.i.i57 - -bb1.i.i57: ; preds = %bb.i.i56, %bb1.i55 - br i1 false, label %bb3.i.i59, label %bb2.i.i58 - -bb2.i.i58: ; preds = %bb1.i.i57 - br label %bb3.i.i59 - -bb3.i.i59: ; preds = %bb2.i.i58, %bb1.i.i57 - br i1 false, label %bb5.i.i61, label %sat.exit.i - -bb5.i.i61: ; preds = %bb3.i.i59 - br i1 false, label %bb6.i.i65, label %bb1.i.i.i63 - -bb1.i.i.i63: ; preds = %bb5.i.i61 - br i1 false, label %sat.exit.i, label %bb6.i.i65 - -bb6.i.i65: ; preds = %bb1.i.i.i63, %bb5.i.i61 - br i1 false, label %bb8.i.i67, label %bb7.i.i66 - -bb7.i.i66: ; preds = %bb6.i.i65 - br label %bb8.i.i67 - -bb8.i.i67: ; preds = %bb7.i.i66, %bb6.i.i65 - br i1 false, label %bb10.i.i69, label %sat.exit.i - -bb10.i.i69: ; preds = %bb8.i.i67 - br i1 false, label %bb11.i.i70, label %bb1.i61.i.i - -bb1.i61.i.i: ; preds = %bb10.i.i69 - br i1 false, label %sat.exit.i, label %bb11.i.i70 - -bb11.i.i70: ; preds = %bb1.i61.i.i, %bb10.i.i69 - br label %bb13.i.i71.outer - -bb13.i.i71.outer: ; preds = %bb42.i.i, %bb11.i.i70 - br label %bb13.i.i71 - -bb13.i.i71: ; preds = %bb13.i.i71.backedge, %bb13.i.i71.outer - br i1 false, label %bb14.i.i72, label %bb15.i.i73 - -bb14.i.i72: ; preds = %bb13.i.i71 - br label %bb15.i.i73 - -bb15.i.i73: ; preds = %bb14.i.i72, %bb13.i.i71 - br i1 false, label %bb19.i.i, label %bb16.i.i - -bb16.i.i: ; preds = %bb15.i.i73 - br i1 false, label %bb.i.i79.i.i, label %incincs.exit.i.i - -bb.i.i79.i.i: ; preds = %bb16.i.i - br label %bb4.i.i.i85.i.i - -bb.i.i.i80.i.i: ; preds = %bb4.i.i.i85.i.i - br i1 false, label %bb3.i.i.i83.i.i, label %bb1.i.i.i81.i.i - -bb1.i.i.i81.i.i: ; preds = %bb.i.i.i80.i.i - br i1 false, label %bb2.i.i.i82.i.i, label %bb3.i.i.i83.i.i - -bb2.i.i.i82.i.i: ; preds = %bb1.i.i.i81.i.i - br label %bb3.i.i.i83.i.i - -bb3.i.i.i83.i.i: ; preds = %bb2.i.i.i82.i.i, %bb1.i.i.i81.i.i, %bb.i.i.i80.i.i - br label %bb4.i.i.i85.i.i - -bb4.i.i.i85.i.i: ; preds = %bb3.i.i.i83.i.i, %bb.i.i79.i.i - br i1 false, label %crescore.exit.i.i.i.i, label %bb.i.i.i80.i.i - -crescore.exit.i.i.i.i: ; preds = %bb4.i.i.i85.i.i - br label %incincs.exit.i.i - -incincs.exit.i.i: ; preds = %crescore.exit.i.i.i.i, %bb16.i.i - br i1 false, label %bb13.i.i71.backedge, label %sat.exit.i.loopexit.loopexit - -bb13.i.i71.backedge: ; preds = %bb1.i55.i.i, %bb28.i.i, %incincs.exit.i.i - br label %bb13.i.i71 - -bb19.i.i: ; preds = %bb15.i.i73 - br i1 false, label %bb20.i.i, label %bb1.i68.i.i - -bb1.i68.i.i: ; preds = %bb19.i.i - br i1 false, label %sat.exit.i.loopexit.loopexit, label %bb20.i.i - -bb20.i.i: ; preds = %bb1.i68.i.i, %bb19.i.i - br i1 false, label %bb24.i.i, label %bb21.i.i - -bb21.i.i: ; preds = %bb20.i.i - br i1 false, label %bb22.i.i, label %bb24.i.i - -bb22.i.i: ; preds = %bb21.i.i - br i1 false, label %bb23.i.i, label %bb24.i.i - -bb23.i.i: ; preds = %bb22.i.i - br label %bb24.i.i - -bb24.i.i: ; preds = %bb23.i.i, %bb22.i.i, %bb21.i.i, %bb20.i.i - br i1 false, label %bb26.i.i, label %sat.exit.i.loopexit.loopexit - -bb26.i.i: ; preds = %bb24.i.i - br i1 false, label %bb27.i.i, label %bb33.i.i.loopexit - -bb27.i.i: ; preds = %bb26.i.i - br i1 false, label %bb33.i.i.loopexit, label %bb28.i.i - -bb28.i.i: ; preds = %bb27.i.i - br i1 false, label %bb1.i55.i.i, label %bb13.i.i71.backedge - -bb1.i55.i.i: ; preds = %bb28.i.i - br i1 false, label %bb29.i.i, label %bb13.i.i71.backedge - -bb29.i.i: ; preds = %bb1.i55.i.i - br i1 false, label %bb31.i.i, label %sat.exit.i.loopexit.loopexit2 - -bb31.i.i: ; preds = %bb29.i.i - br i1 false, label %bb33.i.i, label %bb1.i48.i.i - -bb1.i48.i.i: ; preds = %bb31.i.i - br i1 false, label %sat.exit.i.loopexit.loopexit2, label %bb33.i.i - -bb33.i.i.loopexit: ; preds = %bb27.i.i, %bb26.i.i - br label %bb33.i.i - -bb33.i.i: ; preds = %bb33.i.i.loopexit, %bb1.i48.i.i, %bb31.i.i - br i1 false, label %bb34.i.i, label %bb35.i.i - -bb34.i.i: ; preds = %bb33.i.i - br i1 false, label %bb35.i.i, label %bb2.i44.i.i76 - -bb2.i44.i.i76: ; preds = %bb34.i.i - br label %bb35.i.i - -bb35.i.i: ; preds = %bb2.i44.i.i76, %bb34.i.i, %bb33.i.i - br i1 false, label %bb1.i37.i.i, label %bb.i35.i.i - -bb.i35.i.i: ; preds = %bb35.i.i - br label %bb36.i.i - -bb1.i37.i.i: ; preds = %bb35.i.i - br i1 false, label %bb37.i.i, label %bb36.i.i - -bb36.i.i: ; preds = %bb1.i37.i.i, %bb.i35.i.i - br label %bb25.i23.i.i - -bb.i18.i.i: ; preds = %bb25.i23.i.i - br i1 false, label %bb24.i22.i.i, label %bb22.i19.i.i - -bb22.i19.i.i: ; preds = %bb.i18.i.i - br label %bb24.i22.i.i - -bb24.i22.i.i: ; preds = %bb22.i19.i.i, %bb.i18.i.i - br label %bb25.i23.i.i - -bb25.i23.i.i: ; preds = %bb24.i22.i.i, %bb36.i.i - br i1 false, label %bb.i18.i.i, label %bb26.i24.i.i - -bb26.i24.i.i: ; preds = %bb25.i23.i.i - br i1 false, label %bb27.i25.i.i, label %bb32.i.i.i - -bb27.i25.i.i: ; preds = %bb26.i24.i.i - br label %bb32.i.i.i - -bb32.i.i.i: ; preds = %bb27.i25.i.i, %bb26.i24.i.i - br label %bb64.i.i.i - -bb33.i.i.i: ; preds = %bb64.i.i.i - br i1 false, label %bb60.i.i.i, label %bb34.i.i.i - -bb34.i.i.i: ; preds = %bb33.i.i.i - br i1 false, label %bb38.i.i.i, label %bb60.i.i.i - -bb38.i.i.i: ; preds = %bb34.i.i.i - br i1 false, label %bb39.i.i.i, label %bb48.i.i.i - -bb39.i.i.i: ; preds = %bb38.i.i.i - br i1 false, label %bb48.i.i.i, label %bb40.i.i.i - -bb40.i.i.i: ; preds = %bb39.i.i.i - br i1 false, label %bb60.i.i.i, label %bb45.i.i.i - -bb45.i.i.i: ; preds = %bb40.i.i.i - br label %bb60.i.i.i - -bb48.i.i.i: ; preds = %bb39.i.i.i, %bb38.i.i.i - br i1 false, label %bb53.i.i.i, label %bb60.i.i.i - -bb53.i.i.i: ; preds = %bb48.i.i.i - br i1 false, label %bb60.i.i.i, label %bb58.i.i.i - -bb58.i.i.i: ; preds = %bb53.i.i.i - br i1 false, label %bb59.i.i.i, label %bb60.i.i.i - -bb59.i.i.i: ; preds = %bb58.i.i.i - br label %bb60.i.i.i - -bb60.i.i.i: ; preds = %bb59.i.i.i, %bb58.i.i.i, %bb53.i.i.i, %bb48.i.i.i, %bb45.i.i.i, %bb40.i.i.i, %bb34.i.i.i, %bb33.i.i.i - %lcollect.i.i.i.1 = phi i32 [ %lcollect.i.i.i.2, %bb34.i.i.i ], [ %lcollect.i.i.i.2, %bb48.i.i.i ], [ %lcollect.i.i.i.2, %bb58.i.i.i ], [ %lcollect.i.i.i.2, %bb59.i.i.i ], [ %lcollect.i.i.i.2, %bb53.i.i.i ], [ %lcollect.i.i.i.2, %bb33.i.i.i ], [ %lcollect.i.i.i.2, %bb40.i.i.i ], [ 0, %bb45.i.i.i ] ; [#uses=1] - br label %bb64.i.i.i - -bb64.i.i.i: ; preds = %bb60.i.i.i, %bb32.i.i.i - %lcollect.i.i.i.2 = phi i32 [ 0, %bb32.i.i.i ], [ %lcollect.i.i.i.1, %bb60.i.i.i ] ; [#uses=8] - br i1 false, label %bb65.i.i.i, label %bb33.i.i.i - -bb65.i.i.i: ; preds = %bb64.i.i.i - br i1 false, label %bb103.i.i.i.preheader, label %bb66.i.i.i.preheader - -bb66.i.i.i.preheader: ; preds = %bb65.i.i.i - br label %bb66.i.i.i - -bb66.i.i.i: ; preds = %bb66.i.i.i.backedge, %bb66.i.i.i.preheader - br i1 false, label %bb67.i.i.i, label %bb68.i.i.i - -bb67.i.i.i: ; preds = %bb66.i.i.i - br label %bb68.i.i.i - -bb68.i.i.i: ; preds = %bb67.i.i.i, %bb66.i.i.i - br i1 false, label %bb69.i.i.i, label %bb70.i.i.i - -bb69.i.i.i: ; preds = %bb68.i.i.i - br label %bb70.i.i.i - -bb70.i.i.i: ; preds = %bb69.i.i.i, %bb68.i.i.i - br i1 false, label %bb71.i.i.i, label %bb72.i.i.i - -bb71.i.i.i: ; preds = %bb70.i.i.i - br label %bb72.i.i.i - -bb72.i.i.i: ; preds = %bb71.i.i.i, %bb70.i.i.i - br label %bb73.i.i.i.outer - -bb73.i.i.i.outer: ; preds = %bb78.i.i.i, %bb72.i.i.i - br label %bb73.i.i.i - -bb73.i.i.i: ; preds = %bb73.i.i.i, %bb73.i.i.i.outer - br i1 false, label %bb73.i.i.i, label %bb76.i.i.i.preheader - -bb76.i.i.i.preheader: ; preds = %bb73.i.i.i - br label %bb76.i.i.i - -bb76.i.i.i: ; preds = %bb76.i.i.i, %bb76.i.i.i.preheader - br i1 false, label %bb77.i.i.i, label %bb76.i.i.i - -bb77.i.i.i: ; preds = %bb76.i.i.i - br i1 false, label %bb78.i.i.i, label %bb79.i.i.i - -bb78.i.i.i: ; preds = %bb77.i.i.i - br label %bb73.i.i.i.outer - -bb79.i.i.i: ; preds = %bb77.i.i.i - br i1 false, label %bb83.i.i.i, label %bb94.i.i.i - -bb83.i.i.i: ; preds = %bb79.i.i.i - br i1 false, label %bb84.i.i.i, label %bb88.i.i.i - -bb84.i.i.i: ; preds = %bb83.i.i.i - br i1 false, label %bb87.i.i.i, label %bb85.i.i.i - -bb85.i.i.i: ; preds = %bb84.i.i.i - br label %bb87.i.i.i - -bb87.i.i.i: ; preds = %bb85.i.i.i, %bb84.i.i.i - br label %bb88.i.i.i - -bb88.i.i.i: ; preds = %bb87.i.i.i, %bb83.i.i.i - br i1 false, label %bb89.i.i.i, label %bb93.i.i.i - -bb89.i.i.i: ; preds = %bb88.i.i.i - br i1 false, label %bb92.i.i.i, label %bb90.i.i.i - -bb90.i.i.i: ; preds = %bb89.i.i.i - br label %bb92.i.i.i - -bb92.i.i.i: ; preds = %bb90.i.i.i, %bb89.i.i.i - br label %bb93.i.i.i - -bb93.i.i.i: ; preds = %bb92.i.i.i, %bb88.i.i.i - br label %bb66.i.i.i.backedge - -bb66.i.i.i.backedge: ; preds = %bb97.i.i.i, %bb94.i.i.i, %bb93.i.i.i - br label %bb66.i.i.i - -bb94.i.i.i: ; preds = %bb79.i.i.i - br i1 false, label %bb66.i.i.i.backedge, label %bb96.i.i.i - -bb96.i.i.i: ; preds = %bb94.i.i.i - br i1 false, label %bb97.i.i.i, label %bb103.i.i.i.preheader.loopexit - -bb103.i.i.i.preheader.loopexit: ; preds = %bb96.i.i.i - br label %bb103.i.i.i.preheader - -bb103.i.i.i.preheader: ; preds = %bb103.i.i.i.preheader.loopexit, %bb65.i.i.i - br label %bb103.i.i.i - -bb97.i.i.i: ; preds = %bb96.i.i.i - br label %bb66.i.i.i.backedge - -bb100.i.i.i: ; preds = %bb103.i.i.i - br i1 false, label %bb101.i.i.i, label %bb102.i.i.i - -bb101.i.i.i: ; preds = %bb100.i.i.i - br label %bb102.i.i.i - -bb102.i.i.i: ; preds = %bb101.i.i.i, %bb100.i.i.i - br label %bb103.i.i.i - -bb103.i.i.i: ; preds = %bb102.i.i.i, %bb103.i.i.i.preheader - br i1 false, label %bb100.i.i.i, label %bb109.i.i.i.preheader - -bb109.i.i.i.preheader: ; preds = %bb103.i.i.i - br label %bb109.i.i.i - -bb105.i.i.i: ; preds = %bb109.i.i.i - br label %bb107.i.i.i - -bb106.i.i.i: ; preds = %bb107.i.i.i - br label %bb107.i.i.i - -bb107.i.i.i: ; preds = %bb106.i.i.i, %bb105.i.i.i - br i1 false, label %bb106.i.i.i, label %bb108.i.i.i - -bb108.i.i.i: ; preds = %bb107.i.i.i - br label %bb109.i.i.i - -bb109.i.i.i: ; preds = %bb108.i.i.i, %bb109.i.i.i.preheader - br i1 false, label %bb110.i.i.i, label %bb105.i.i.i - -bb110.i.i.i: ; preds = %bb109.i.i.i - %0 = sub i32 0, %lcollect.i.i.i.2 ; [#uses=1] - %1 = add i32 %0, 1 ; [#uses=1] - br label %bb113.i.i.i - -bb111.i.i.i: ; preds = %bb113.i.i.i - br i1 false, label %bb114.i.i.i, label %bb113.i.i.i - -bb113.i.i.i: ; preds = %bb111.i.i.i, %bb110.i.i.i - br i1 false, label %bb111.i.i.i, label %bb114.i.i.i - -bb114.i.i.i: ; preds = %bb113.i.i.i, %bb111.i.i.i - %2 = lshr i32 %1, 1 ; [#uses=2] - br i1 false, label %bb116.i.i.i, label %bb124.i.i.i - -bb116.i.i.i: ; preds = %bb114.i.i.i - br i1 false, label %bb117.i.i.i.preheader, label %bb122.i.i.i.preheader - -bb122.i.i.i.preheader: ; preds = %bb116.i.i.i - br label %bb122.i.i.i - -bb117.i.i.i.preheader: ; preds = %bb116.i.i.i - br label %bb117.i.i.i - -bb117.i.i.i: ; preds = %bb118.i.i.i, %bb117.i.i.i.preheader - %target.i.i.i.1 = phi i32 [ %3, %bb118.i.i.i ], [ %2, %bb117.i.i.i.preheader ] ; [#uses=1] - %3 = add i32 %target.i.i.i.1, 1 ; [#uses=2] - br i1 false, label %bb118.i.i.i, label %bb124.i.i.i.loopexit - -bb118.i.i.i: ; preds = %bb117.i.i.i - br i1 false, label %bb117.i.i.i, label %bb124.i.i.i.loopexit - -bb122.i.i.i: ; preds = %bb123.i.i.i, %bb122.i.i.i.preheader - %target.i.i.i.2 = phi i32 [ %4, %bb123.i.i.i ], [ %2, %bb122.i.i.i.preheader ] ; [#uses=2] - br i1 false, label %bb124.i.i.i.loopexit1, label %bb123.i.i.i - -bb123.i.i.i: ; preds = %bb122.i.i.i - %4 = add i32 %target.i.i.i.2, -1 ; [#uses=1] - br i1 false, label %bb122.i.i.i, label %bb124.i.i.i.loopexit1 - -bb124.i.i.i.loopexit: ; preds = %bb118.i.i.i, %bb117.i.i.i - br label %bb124.i.i.i - -bb124.i.i.i.loopexit1: ; preds = %bb123.i.i.i, %bb122.i.i.i - br label %bb124.i.i.i - -bb124.i.i.i: ; preds = %bb124.i.i.i.loopexit1, %bb124.i.i.i.loopexit, %bb114.i.i.i - %target.i.i.i.0 = phi i32 [ 0, %bb114.i.i.i ], [ %3, %bb124.i.i.i.loopexit ], [ %target.i.i.i.2, %bb124.i.i.i.loopexit1 ] ; [#uses=0] - br label %bb132.i.i.i.outer - -bb125.i.i.i: ; preds = %bb132.i.i.i - br i1 false, label %bb132.i.i.i, label %bb130.i.i.i - -bb130.i.i.i: ; preds = %bb125.i.i.i - br label %bb132.i.i.i.outer - -bb132.i.i.i.outer: ; preds = %bb130.i.i.i, %bb124.i.i.i - br label %bb132.i.i.i - -bb132.i.i.i: ; preds = %bb132.i.i.i.outer, %bb125.i.i.i - br i1 false, label %bb125.i.i.i, label %bb133.i.i.i - -bb133.i.i.i: ; preds = %bb132.i.i.i - br i1 false, label %bb136.i.i.i, label %bb134.i.i.i - -bb134.i.i.i: ; preds = %bb133.i.i.i - br i1 false, label %bb136.i.i.i, label %bb135.i.i.i - -bb135.i.i.i: ; preds = %bb134.i.i.i - br label %bb136.i.i.i - -bb136.i.i.i: ; preds = %bb135.i.i.i, %bb134.i.i.i, %bb133.i.i.i - br i1 false, label %bb137.i.i.i, label %bb37.i.i - -bb137.i.i.i: ; preds = %bb136.i.i.i - br label %bb37.i.i - -bb37.i.i: ; preds = %bb137.i.i.i, %bb136.i.i.i, %bb1.i37.i.i - br i1 false, label %bb40.i.i, label %bb38.i.i - -bb38.i.i: ; preds = %bb37.i.i - br i1 false, label %bb39.i.i, label %bb40.i.i - -bb39.i.i: ; preds = %bb38.i.i - br i1 false, label %bb17.i.i.i, label %bb3.i12.i.i - -bb3.i12.i.i: ; preds = %bb39.i.i - br label %bb5.i14.i.i - -bb5.i14.i.i: ; preds = %bb8.i.i.i79, %bb3.i12.i.i - br i1 false, label %bb6.i15.i.i, label %bb9.i.i.i80 - -bb6.i15.i.i: ; preds = %bb5.i14.i.i - br i1 false, label %bb7.i.i.i78, label %bb9.i.i.i80 - -bb7.i.i.i78: ; preds = %bb6.i15.i.i - br i1 false, label %bb9.i.i.i80, label %bb8.i.i.i79 - -bb8.i.i.i79: ; preds = %bb7.i.i.i78 - br i1 false, label %bb9.i.i.i80, label %bb5.i14.i.i - -bb9.i.i.i80: ; preds = %bb8.i.i.i79, %bb7.i.i.i78, %bb6.i15.i.i, %bb5.i14.i.i - br i1 false, label %bb16.i.i.i, label %bb10.i.i.i81 - -bb10.i.i.i81: ; preds = %bb9.i.i.i80 - br i1 false, label %bb11.i.i.i, label %bb15.i.i.i - -bb11.i.i.i: ; preds = %bb10.i.i.i81 - br i1 false, label %bb16.i.i.i, label %bb15.i.i.i - -bb15.i.i.i: ; preds = %bb11.i.i.i, %bb10.i.i.i81 - br label %bb16.i.i.i - -bb16.i.i.i: ; preds = %bb15.i.i.i, %bb11.i.i.i, %bb9.i.i.i80 - br label %bb17.i.i.i - -bb17.i.i.i: ; preds = %bb16.i.i.i, %bb39.i.i - br i1 false, label %bb18.i.i.i, label %bb25.i.i.i - -bb18.i.i.i: ; preds = %bb17.i.i.i - br i1 false, label %bb24.i.i.i, label %bb23.i.i.i - -bb23.i.i.i: ; preds = %bb18.i.i.i - br label %bb24.i.i.i - -bb24.i.i.i: ; preds = %bb23.i.i.i, %bb18.i.i.i - br label %bb29.i.i.i - -bb25.i.i.i: ; preds = %bb17.i.i.i - br i1 false, label %bb29.i.i.i, label %bb27.i.i.i - -bb27.i.i.i: ; preds = %bb25.i.i.i - br i1 false, label %bb29.i.i.i, label %bb28.i.i.i - -bb28.i.i.i: ; preds = %bb27.i.i.i - br i1 false, label %bb29.i.i.i, label %bb.i4.i.i.i - -bb.i4.i.i.i: ; preds = %bb28.i.i.i - br i1 false, label %bb4.i.i16.i.i, label %bb29.i.i.i - -bb4.i.i16.i.i: ; preds = %bb.i4.i.i.i - br label %bb29.i.i.i - -bb29.i.i.i: ; preds = %bb4.i.i16.i.i, %bb.i4.i.i.i, %bb28.i.i.i, %bb27.i.i.i, %bb25.i.i.i, %bb24.i.i.i - br label %bb40.i.i - -bb40.i.i: ; preds = %bb29.i.i.i, %bb38.i.i, %bb37.i.i - br i1 false, label %bb9.i.i.i.i.preheader, label %bb2.i.i.i87 - -bb9.i.i.i.i.preheader: ; preds = %bb40.i.i - br label %bb9.i.i.i.i - -bb.i.i.i.i84: ; preds = %bb9.i.i.i.i - switch i8 0, label %bb8.i.i.i.i [ - i8 -1, label %bb1.i.i.i.i85 - i8 1, label %bb9.i.i.i.i - ] - -bb1.i.i.i.i85: ; preds = %bb.i.i.i.i84 - br i1 false, label %bb5.i.i.i.i, label %bb2.i.i.i87 - -bb5.i.i.i.i: ; preds = %bb1.i.i.i.i85 - br label %bb2.i.i.i87 - -bb8.i.i.i.i: ; preds = %bb.i.i.i.i84 - br i1 false, label %bb2.i.i.i87, label %bb6.i.i.i95 - -bb9.i.i.i.i: ; preds = %bb.i.i.i.i84, %bb9.i.i.i.i.preheader - br i1 false, label %bb.i.i.i.i84, label %bb10.i.i.i.i - -bb10.i.i.i.i: ; preds = %bb9.i.i.i.i - br label %bb2.i.i.i87 - -bb2.i.i.i87: ; preds = %bb10.i.i.i.i, %bb8.i.i.i.i, %bb5.i.i.i.i, %bb1.i.i.i.i85, %bb40.i.i - br i1 false, label %bb3.i.i.i88, label %decide.exit.i.i - -bb3.i.i.i88: ; preds = %bb2.i.i.i87 - br i1 false, label %bb4.i.i.i90, label %bb1.i23.i.i.i - -bb1.i23.i.i.i: ; preds = %bb3.i.i.i88 - br i1 false, label %decide.exit.i.i, label %bb4.i.i.i90 - -bb4.i.i.i90: ; preds = %bb1.i23.i.i.i, %bb3.i.i.i88 - br i1 false, label %bb1.i9.i.i.i, label %bb5.i.i.i94 - -bb1.i9.i.i.i: ; preds = %bb4.i.i.i90 - br i1 false, label %bb.i.i27.i.i.i.i, label %bb1.i.i28.i.i.i.i - -bb.i.i27.i.i.i.i: ; preds = %bb1.i9.i.i.i - br label %int2lit.exit32.i.i.i.i - -bb1.i.i28.i.i.i.i: ; preds = %bb1.i9.i.i.i - br label %int2lit.exit32.i.i.i.i - -int2lit.exit32.i.i.i.i: ; preds = %bb1.i.i28.i.i.i.i, %bb.i.i27.i.i.i.i - br i1 false, label %bb8.i19.i.i.i, label %bb2.i.i.i.i91 - -bb2.i.i.i.i91: ; preds = %int2lit.exit32.i.i.i.i - br label %bb4.i.i.i.i - -bb3.i.i.i.i92: ; preds = %gcd.exit.i.i.i.i - br label %bb4.i.i.i.i - -bb4.i.i.i.i: ; preds = %bb3.i.i.i.i92, %bb2.i.i.i.i91 - br label %bb3.i.i13.i.i.i - -bb2.i.i12.i.i.i: ; preds = %bb3.i.i13.i.i.i - br label %bb3.i.i13.i.i.i - -bb3.i.i13.i.i.i: ; preds = %bb2.i.i12.i.i.i, %bb4.i.i.i.i - br i1 false, label %gcd.exit.i.i.i.i, label %bb2.i.i12.i.i.i - -gcd.exit.i.i.i.i: ; preds = %bb3.i.i13.i.i.i - br i1 false, label %bb5.i14.i.i.i.preheader, label %bb3.i.i.i.i92 - -bb5.i14.i.i.i.preheader: ; preds = %gcd.exit.i.i.i.i - br label %bb5.i14.i.i.i - -bb5.i14.i.i.i: ; preds = %int2lit.exit.i.i.i.i, %bb5.i14.i.i.i.preheader - br i1 false, label %bb.i.i.i17.i.i.i, label %bb1.i.i.i18.i.i.i - -bb.i.i.i17.i.i.i: ; preds = %bb5.i14.i.i.i - br label %int2lit.exit.i.i.i.i - -bb1.i.i.i18.i.i.i: ; preds = %bb5.i14.i.i.i - br label %int2lit.exit.i.i.i.i - -int2lit.exit.i.i.i.i: ; preds = %bb1.i.i.i18.i.i.i, %bb.i.i.i17.i.i.i - br i1 false, label %bb8.i19.i.i.i.loopexit, label %bb5.i14.i.i.i - -bb8.i19.i.i.i.loopexit: ; preds = %int2lit.exit.i.i.i.i - br label %bb8.i19.i.i.i - -bb8.i19.i.i.i: ; preds = %bb8.i19.i.i.i.loopexit, %int2lit.exit32.i.i.i.i - br i1 false, label %bb5.i.i.i94, label %bb6.i.i.i95 - -bb5.i.i.i94: ; preds = %bb8.i19.i.i.i, %bb4.i.i.i90 - br label %bb.i2.i.i.i - -bb.i2.i.i.i: ; preds = %hpop.exit.i.i.i.i, %bb5.i.i.i94 - br i1 false, label %hpop.exit.i.i.i.i, label %bb1.i.i.i.i.i - -bb1.i.i.i.i.i: ; preds = %bb.i2.i.i.i - br label %bb2.i.i.i.i.i - -bb2.i.i.i.i.i: ; preds = %bb11.i.i.i.i.i, %bb1.i.i.i.i.i - br i1 false, label %bb3.i.i.i.i.i, label %bb12.i.i.i.i.i - -bb3.i.i.i.i.i: ; preds = %bb2.i.i.i.i.i - br i1 false, label %bb4.i.i.i.i.i, label %bb1.i.i.i.i.i.i - -bb1.i.i.i.i.i.i: ; preds = %bb3.i.i.i.i.i - br i1 false, label %bb8.i.i.i.i.i, label %bb3.i.i.i.i.i.i - -bb3.i.i.i.i.i.i: ; preds = %bb1.i.i.i.i.i.i - br i1 false, label %bb4.i.i.i.i.i, label %bb8.i.i.i.i.i - -bb4.i.i.i.i.i: ; preds = %bb3.i.i.i.i.i.i, %bb3.i.i.i.i.i - br i1 false, label %bb5.i.i.i.i.i, label %bb11.i.i.i.i.i - -bb5.i.i.i.i.i: ; preds = %bb4.i.i.i.i.i - br i1 false, label %bb6.i.i.i.i.i, label %bb1.i21.i.i.i.i.i - -bb1.i21.i.i.i.i.i: ; preds = %bb5.i.i.i.i.i - br i1 false, label %bb11.i.i.i.i.i, label %bb3.i24.i.i.i.i.i - -bb3.i24.i.i.i.i.i: ; preds = %bb1.i21.i.i.i.i.i - br i1 false, label %bb6.i.i.i.i.i, label %bb11.i.i.i.i.i - -bb6.i.i.i.i.i: ; preds = %bb3.i24.i.i.i.i.i, %bb5.i.i.i.i.i - br label %bb11.i.i.i.i.i - -bb8.i.i.i.i.i: ; preds = %bb3.i.i.i.i.i.i, %bb1.i.i.i.i.i.i - br i1 false, label %bb9.i.i.i.i.i, label %bb12.i.i.i.i.i - -bb9.i.i.i.i.i: ; preds = %bb8.i.i.i.i.i - br i1 false, label %bb11.i.i.i.i.i, label %bb1.i8.i.i.i.i.i - -bb1.i8.i.i.i.i.i: ; preds = %bb9.i.i.i.i.i - br i1 false, label %bb12.i.i.i.i.i, label %bb3.i11.i.i.i.i.i - -bb3.i11.i.i.i.i.i: ; preds = %bb1.i8.i.i.i.i.i - br i1 false, label %bb11.i.i.i.i.i, label %bb12.i.i.i.i.i - -bb11.i.i.i.i.i: ; preds = %bb3.i11.i.i.i.i.i, %bb9.i.i.i.i.i, %bb6.i.i.i.i.i, %bb3.i24.i.i.i.i.i, %bb1.i21.i.i.i.i.i, %bb4.i.i.i.i.i - br label %bb2.i.i.i.i.i - -bb12.i.i.i.i.i: ; preds = %bb3.i11.i.i.i.i.i, %bb1.i8.i.i.i.i.i, %bb8.i.i.i.i.i, %bb2.i.i.i.i.i - br label %hpop.exit.i.i.i.i - -hpop.exit.i.i.i.i: ; preds = %bb12.i.i.i.i.i, %bb.i2.i.i.i - br i1 false, label %sdecide.exit.i.i.i, label %bb.i2.i.i.i - -sdecide.exit.i.i.i: ; preds = %hpop.exit.i.i.i.i - br label %bb6.i.i.i95 - -bb6.i.i.i95: ; preds = %sdecide.exit.i.i.i, %bb8.i19.i.i.i, %bb8.i.i.i.i - br label %decide.exit.i.i - -decide.exit.i.i: ; preds = %bb6.i.i.i95, %bb1.i23.i.i.i, %bb2.i.i.i87 - br i1 false, label %bb42.i.i, label %sat.exit.i.loopexit.loopexit2 - -bb42.i.i: ; preds = %decide.exit.i.i - br label %bb13.i.i71.outer - -sat.exit.i.loopexit.loopexit: ; preds = %bb24.i.i, %bb1.i68.i.i, %incincs.exit.i.i - br label %sat.exit.i.loopexit - -sat.exit.i.loopexit.loopexit2: ; preds = %decide.exit.i.i, %bb1.i48.i.i, %bb29.i.i - br label %sat.exit.i.loopexit - -sat.exit.i.loopexit: ; preds = %sat.exit.i.loopexit.loopexit2, %sat.exit.i.loopexit.loopexit - br label %sat.exit.i - -sat.exit.i: ; preds = %sat.exit.i.loopexit, %bb1.i61.i.i, %bb8.i.i67, %bb1.i.i.i63, %bb3.i.i59 - br i1 false, label %bb7.i, label %bb2.i96 - -bb2.i96: ; preds = %sat.exit.i - switch i32 0, label %bb5.i99 [ - i32 10, label %bb4.i98 - i32 20, label %bb6.i100 - ] - -bb4.i98: ; preds = %bb2.i96 - br label %bb6.i100 - -bb5.i99: ; preds = %bb2.i96 - br label %bb6.i100 - -bb6.i100: ; preds = %bb5.i99, %bb4.i98, %bb2.i96 - br label %bb7.i - -bb7.i: ; preds = %bb6.i100, %sat.exit.i - br i1 false, label %bb.i1.i, label %picosat_sat.exit - -bb.i1.i: ; preds = %bb7.i - br label %picosat_sat.exit - -picosat_sat.exit: ; preds = %bb.i1.i, %bb7.i - switch i32 0, label %bb166 [ - i32 20, label %bb150 - i32 10, label %bb163 - ] - -bb150: ; preds = %picosat_sat.exit - br i1 false, label %bb152, label %bb151 - -bb151: ; preds = %bb150 - br label %bb152 - -bb152: ; preds = %bb151, %bb150 - br i1 false, label %bb154, label %bb153 - -bb153: ; preds = %bb152 - br label %bb154 - -bb154: ; preds = %bb153, %bb152 - br i1 false, label %bb157, label %bb156 - -bb156: ; preds = %bb154 - br label %bb157 - -bb157: ; preds = %bb156, %bb154 - br i1 false, label %bb159, label %bb158 - -bb158: ; preds = %bb157 - br label %bb159 - -bb159: ; preds = %bb158, %bb157 - br i1 false, label %bb167, label %bb160 - -bb160: ; preds = %bb159 - br label %bb167 - -bb163: ; preds = %picosat_sat.exit - br i1 false, label %bb167, label %bb164 - -bb164: ; preds = %bb163 - br label %bb4.i - -bb.i11: ; preds = %bb4.i - br i1 false, label %bb.i.i12, label %bb1.i.i14 - -bb.i.i12: ; preds = %bb.i11 - unreachable - -bb1.i.i14: ; preds = %bb.i11 - br i1 false, label %bb3.i.i16, label %bb2.i.i15 - -bb2.i.i15: ; preds = %bb1.i.i14 - unreachable - -bb3.i.i16: ; preds = %bb1.i.i14 - br i1 false, label %bb3.i, label %bb7.i.i - -bb7.i.i: ; preds = %bb3.i.i16 - br i1 false, label %bb.i.i.i.i17, label %bb1.i.i.i.i18 - -bb.i.i.i.i17: ; preds = %bb7.i.i - br label %int2lit.exit.i.i - -bb1.i.i.i.i18: ; preds = %bb7.i.i - br label %int2lit.exit.i.i - -int2lit.exit.i.i: ; preds = %bb1.i.i.i.i18, %bb.i.i.i.i17 - br i1 false, label %bb3.i, label %bb9.i.i - -bb9.i.i: ; preds = %int2lit.exit.i.i - br label %bb3.i - -bb3.i: ; preds = %bb9.i.i, %int2lit.exit.i.i, %bb3.i.i16 - br label %bb4.i - -bb4.i: ; preds = %bb3.i, %bb164 - br i1 false, label %bb5.i, label %bb.i11 - -bb5.i: ; preds = %bb4.i - br i1 false, label %bb6.i, label %bb167 - -bb6.i: ; preds = %bb5.i - br label %bb167 - -bb166: ; preds = %picosat_sat.exit - br label %bb167 - -bb167: ; preds = %bb166, %bb6.i, %bb5.i, %bb163, %bb160, %bb159, %picosat_print.exit - br i1 false, label %bb168, label %bb170 - -bb168: ; preds = %bb167 - br i1 false, label %bb170, label %bb169 - -bb169: ; preds = %bb168 - br i1 false, label %bb.i7, label %picosat_time_stamp.exit9 - -bb.i7: ; preds = %bb169 - br label %picosat_time_stamp.exit9 - -picosat_time_stamp.exit9: ; preds = %bb.i7, %bb169 - br label %bb170 - -bb170: ; preds = %picosat_time_stamp.exit9, %bb168, %bb167, %bb129 - br i1 false, label %bb.i.i3, label %picosat_leave.exit - -bb.i.i3: ; preds = %bb170 - br label %picosat_leave.exit - -picosat_leave.exit: ; preds = %bb.i.i3, %bb170 - br i1 false, label %bb1.i.i, label %bb.i.i - -bb.i.i: ; preds = %picosat_leave.exit - unreachable - -bb1.i.i: ; preds = %picosat_leave.exit - br label %bb9.i.i.i - -bb3.i.i.i: ; preds = %bb9.i.i.i - br i1 false, label %bb5.i.i.i, label %bb4.i.i.i - -bb4.i.i.i: ; preds = %bb3.i.i.i - br label %bb5.i.i.i - -bb5.i.i.i: ; preds = %bb4.i.i.i, %bb3.i.i.i - br label %bb9.i.i.i - -bb9.i.i.i: ; preds = %bb5.i.i.i, %bb1.i.i - br i1 false, label %bb10.i.i.i, label %bb3.i.i.i - -bb10.i.i.i: ; preds = %bb9.i.i.i - br i1 false, label %delete.exit.i.i.i, label %bb1.i.i.i.i - -bb1.i.i.i.i: ; preds = %bb10.i.i.i - br label %delete.exit.i.i.i - -delete.exit.i.i.i: ; preds = %bb1.i.i.i.i, %bb10.i.i.i - br i1 false, label %delete_clauses.exit.i.i, label %bb1.i7.i.i.i - -bb1.i7.i.i.i: ; preds = %delete.exit.i.i.i - br label %delete_clauses.exit.i.i - -delete_clauses.exit.i.i: ; preds = %bb1.i7.i.i.i, %delete.exit.i.i.i - br label %bb3.i.i - -bb2.i.i: ; preds = %bb3.i.i - br i1 false, label %lrelease.exit.i.i, label %bb1.i.i23.i.i - -bb1.i.i23.i.i: ; preds = %bb2.i.i - br label %lrelease.exit.i.i - -lrelease.exit.i.i: ; preds = %bb1.i.i23.i.i, %bb2.i.i - br label %bb3.i.i - -bb3.i.i: ; preds = %lrelease.exit.i.i, %delete_clauses.exit.i.i - br i1 false, label %bb4.i.i, label %bb2.i.i - -bb4.i.i: ; preds = %bb3.i.i - br i1 false, label %delete.exit214.i.i, label %bb1.i208.i.i - -bb1.i208.i.i: ; preds = %bb4.i.i - br label %delete.exit214.i.i - -delete.exit214.i.i: ; preds = %bb1.i208.i.i, %bb4.i.i - br i1 false, label %delete.exit203.i.i, label %bb1.i197.i.i - -bb1.i197.i.i: ; preds = %delete.exit214.i.i - br label %delete.exit203.i.i - -delete.exit203.i.i: ; preds = %bb1.i197.i.i, %delete.exit214.i.i - br i1 false, label %delete.exit192.i.i, label %bb1.i186.i.i - -bb1.i186.i.i: ; preds = %delete.exit203.i.i - br label %delete.exit192.i.i - -delete.exit192.i.i: ; preds = %bb1.i186.i.i, %delete.exit203.i.i - br i1 false, label %delete.exit181.i.i, label %bb1.i175.i.i - -bb1.i175.i.i: ; preds = %delete.exit192.i.i - br label %delete.exit181.i.i - -delete.exit181.i.i: ; preds = %bb1.i175.i.i, %delete.exit192.i.i - br i1 false, label %delete.exit170.i.i, label %bb1.i164.i.i - -bb1.i164.i.i: ; preds = %delete.exit181.i.i - br label %delete.exit170.i.i - -delete.exit170.i.i: ; preds = %bb1.i164.i.i, %delete.exit181.i.i - br i1 false, label %delete.exit159.i.i, label %bb1.i153.i.i - -bb1.i153.i.i: ; preds = %delete.exit170.i.i - br label %delete.exit159.i.i - -delete.exit159.i.i: ; preds = %bb1.i153.i.i, %delete.exit170.i.i - br i1 false, label %delete.exit148.i.i, label %bb1.i142.i.i - -bb1.i142.i.i: ; preds = %delete.exit159.i.i - br label %delete.exit148.i.i - -delete.exit148.i.i: ; preds = %bb1.i142.i.i, %delete.exit159.i.i - br i1 false, label %delete.exit137.i.i, label %bb1.i131.i.i - -bb1.i131.i.i: ; preds = %delete.exit148.i.i - br label %delete.exit137.i.i - -delete.exit137.i.i: ; preds = %bb1.i131.i.i, %delete.exit148.i.i - br i1 false, label %delete.exit126.i.i, label %bb1.i120.i.i - -bb1.i120.i.i: ; preds = %delete.exit137.i.i - br label %delete.exit126.i.i - -delete.exit126.i.i: ; preds = %bb1.i120.i.i, %delete.exit137.i.i - br i1 false, label %delete.exit115.i.i, label %bb1.i109.i.i - -bb1.i109.i.i: ; preds = %delete.exit126.i.i - br label %delete.exit115.i.i - -delete.exit115.i.i: ; preds = %bb1.i109.i.i, %delete.exit126.i.i - br i1 false, label %delete.exit104.i.i, label %bb1.i98.i.i - -bb1.i98.i.i: ; preds = %delete.exit115.i.i - br label %delete.exit104.i.i - -delete.exit104.i.i: ; preds = %bb1.i98.i.i, %delete.exit115.i.i - br i1 false, label %delete.exit93.i.i, label %bb1.i87.i.i - -bb1.i87.i.i: ; preds = %delete.exit104.i.i - br label %delete.exit93.i.i - -delete.exit93.i.i: ; preds = %bb1.i87.i.i, %delete.exit104.i.i - br i1 false, label %delete.exit82.i.i, label %bb1.i76.i.i - -bb1.i76.i.i: ; preds = %delete.exit93.i.i - br label %delete.exit82.i.i - -delete.exit82.i.i: ; preds = %bb1.i76.i.i, %delete.exit93.i.i - br i1 false, label %delete.exit71.i.i, label %bb1.i65.i.i - -bb1.i65.i.i: ; preds = %delete.exit82.i.i - br label %delete.exit71.i.i - -delete.exit71.i.i: ; preds = %bb1.i65.i.i, %delete.exit82.i.i - br i1 false, label %delete.exit60.i.i, label %bb1.i54.i.i - -bb1.i54.i.i: ; preds = %delete.exit71.i.i - br label %delete.exit60.i.i - -delete.exit60.i.i: ; preds = %bb1.i54.i.i, %delete.exit71.i.i - br i1 false, label %delete.exit38.i.i, label %bb1.i32.i.i - -bb1.i32.i.i: ; preds = %delete.exit60.i.i - br label %delete.exit38.i.i - -delete.exit38.i.i: ; preds = %bb1.i32.i.i, %delete.exit60.i.i - br i1 false, label %delete.exit18.i.i, label %bb1.i12.i.i - -bb1.i12.i.i: ; preds = %delete.exit38.i.i - br label %delete.exit18.i.i - -delete.exit18.i.i: ; preds = %bb1.i12.i.i, %delete.exit38.i.i - br i1 false, label %picosat_reset.exit, label %bb1.i2.i.i - -bb1.i2.i.i: ; preds = %delete.exit18.i.i - br label %picosat_reset.exit - -picosat_reset.exit: ; preds = %bb1.i2.i.i, %delete.exit18.i.i - br label %bb171 - -bb171: ; preds = %picosat_reset.exit, %bb110 - br i1 false, label %bb173, label %bb172 - -bb172: ; preds = %bb171 - br label %bb173 - -bb173: ; preds = %bb172, %bb171 - br i1 false, label %bb175, label %bb174 - -bb174: ; preds = %bb173 - br label %bb175 - -bb175: ; preds = %bb174, %bb173 - br i1 false, label %bb177, label %bb176 - -bb176: ; preds = %bb175 - br label %bb177 - -bb177: ; preds = %bb176, %bb175 - br i1 false, label %bb179, label %bb178 - -bb178: ; preds = %bb177 - ret i32 0 - -bb179: ; preds = %bb177 - ret i32 0 -} - -define i32 @main(i32 %argc, i8** %argv) nounwind { -entry: - br label %bb2 - -bb: ; preds = %bb2 - br i1 false, label %bb3, label %bb2 - -bb2: ; preds = %bb, %entry - br i1 false, label %bb5.loopexit, label %bb - -bb3: ; preds = %bb - br i1 false, label %bb5, label %bb4 - -bb4: ; preds = %bb3 - br label %bb5 - -bb5.loopexit: ; preds = %bb2 - br label %bb5 - -bb5: ; preds = %bb5.loopexit, %bb4, %bb3 - %0 = call fastcc i32 @picosat_main(i32 %argc, i8** %argv) nounwind ; [#uses=2] - br i1 false, label %bb7, label %bb6 - -bb6: ; preds = %bb5 - ret i32 %0 - -bb7: ; preds = %bb5 - ret i32 %0 -} 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,17 +1,27 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=3 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; PR 32917 @b = common local_unnamed_addr global i32 0, align 4 @a = common local_unnamed_addr global i32 0, align 4 define i32 @fn2() local_unnamed_addr { -; CHECK-LABEL: define {{[^@]+}}@fn2() local_unnamed_addr -; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4 -; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[TMP1]] to i64 -; CHECK-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to i32* -; CHECK-NEXT: call fastcc void @fn1(i32* nofree readonly align 4 [[TMP3]]) -; CHECK-NEXT: ret i32 undef +; 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 +; IS__TUNIT____-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to i32* +; IS__TUNIT____-NEXT: call fastcc void @fn1(i32* nofree readonly align 4 [[TMP3]]) +; IS__TUNIT____-NEXT: ret i32 undef +; +; 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 +; IS__CGSCC____-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to i32* +; IS__CGSCC____-NEXT: call fastcc void @fn1(i32* nofree nonnull readonly align 4 [[TMP3]]) +; IS__CGSCC____-NEXT: ret i32 undef ; %1 = load i32, i32* @b, align 4 %2 = sext i32 %1 to i64 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; Fix for PR33641. ArgumentPromotion removed the argument to bar but left the call to ; dbg.value which still used the removed argument. 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,16 +1,31 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=3 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 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" ; Checks if !prof metadata is corret in deadargelim. define void @caller() #0 { -; CHECK-LABEL: define {{[^@]+}}@caller() -; CHECK-NEXT: [[X:%.*]] = alloca i32 -; CHECK-NEXT: store i32 42, i32* [[X]], align 4 -; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[X]], align 1 -; CHECK-NEXT: call void @promote_i32_ptr(i32 [[TMP1]]), !prof !0 -; CHECK-NEXT: ret void +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@caller() +; IS__TUNIT_OPM-NEXT: [[X:%.*]] = alloca i32 +; IS__TUNIT_OPM-NEXT: store i32 42, i32* [[X]], align 4 +; IS__TUNIT_OPM-NEXT: call void @promote_i32_ptr(i32* noalias nocapture nonnull readonly align 4 dereferenceable(4) [[X]]), !prof !0 +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@caller() +; IS__TUNIT_NPM-NEXT: [[X:%.*]] = alloca i32 +; IS__TUNIT_NPM-NEXT: store i32 42, i32* [[X]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[X]], align 1 +; IS__TUNIT_NPM-NEXT: call void @promote_i32_ptr(i32 [[TMP1]]), !prof !0 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@caller() +; IS__CGSCC____-NEXT: [[X:%.*]] = alloca i32 +; IS__CGSCC____-NEXT: store i32 42, i32* [[X]], align 4 +; IS__CGSCC____-NEXT: call void @promote_i32_ptr(i32* noalias nonnull readonly align 4 dereferenceable(4) [[X]]), !prof !0 +; IS__CGSCC____-NEXT: ret void ; %x = alloca i32 store i32 42, i32* %x @@ -19,13 +34,25 @@ } define internal void @promote_i32_ptr(i32* %xp) { -; CHECK-LABEL: define {{[^@]+}}@promote_i32_ptr -; CHECK-SAME: (i32 [[TMP0:%.*]]) -; CHECK-NEXT: [[XP_PRIV:%.*]] = alloca i32 -; CHECK-NEXT: store i32 [[TMP0]], i32* [[XP_PRIV]] -; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[XP_PRIV]], align 4 -; CHECK-NEXT: call void @use_i32(i32 [[X]]) -; CHECK-NEXT: ret void +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@promote_i32_ptr +; IS__TUNIT_OPM-SAME: (i32* noalias nocapture nonnull readonly align 4 dereferenceable(4) [[XP:%.*]]) +; IS__TUNIT_OPM-NEXT: [[X:%.*]] = load i32, i32* [[XP]], align 4 +; IS__TUNIT_OPM-NEXT: call void @use_i32(i32 [[X]]) +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@promote_i32_ptr +; IS__TUNIT_NPM-SAME: (i32 [[TMP0:%.*]]) +; IS__TUNIT_NPM-NEXT: [[XP_PRIV:%.*]] = alloca i32 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP0]], i32* [[XP_PRIV]] +; IS__TUNIT_NPM-NEXT: [[X:%.*]] = load i32, i32* [[XP_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: call void @use_i32(i32 [[X]]) +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@promote_i32_ptr +; IS__CGSCC____-SAME: (i32* nocapture nonnull readonly align 4 dereferenceable(4) [[XP:%.*]]) +; IS__CGSCC____-NEXT: [[X:%.*]] = load i32, i32* [[XP]], align 4 +; IS__CGSCC____-NEXT: call void @use_i32(i32 [[X]]) +; IS__CGSCC____-NEXT: ret void ; %x = load i32, i32* %xp call void @use_i32(i32 %x) 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=3 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; PR17906 ; When we promote two arguments in a single function with different types, @@ -14,13 +17,20 @@ @d = global i8 0, align 1 define internal fastcc void @fn(i32* nocapture readonly %p1, i64* nocapture readonly %p2) { -; CHECK-LABEL: define {{[^@]+}}@fn -; CHECK-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P1:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @g, align 4, !tbaa !0 -; CHECK-NEXT: [[CONV1:%.*]] = trunc i32 [[TMP0]] to i8 -; CHECK-NEXT: store i8 [[CONV1]], i8* @d, align 1, !tbaa !4 -; CHECK-NEXT: ret void +; IS__TUNIT____-LABEL: define {{[^@]+}}@fn +; IS__TUNIT____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P1:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32, i32* @g, align 4, !tbaa !0 +; IS__TUNIT____-NEXT: [[CONV1:%.*]] = trunc i32 [[TMP0]] to i8 +; IS__TUNIT____-NEXT: store i8 [[CONV1]], i8* @d, align 1, !tbaa !4 +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@fn() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* @g, align 4, !tbaa !0 +; IS__CGSCC____-NEXT: [[CONV1:%.*]] = trunc i32 [[TMP0]] to i8 +; IS__CGSCC____-NEXT: store i8 [[CONV1]], i8* @d, align 1, !tbaa !4 +; IS__CGSCC____-NEXT: ret void ; entry: %0 = load i64, i64* %p2, align 8, !tbaa !1 @@ -32,14 +42,23 @@ } define i32 @main() { -; CHECK-LABEL: define {{[^@]+}}@main() -; CHECK-NEXT: entry: -; CHECK-NEXT: [[TMP0:%.*]] = load i32**, i32*** @e, align 8, !tbaa !5 -; CHECK-NEXT: store i32* @g, i32** [[TMP0]], align 8, !tbaa !5 -; CHECK-NEXT: [[TMP1:%.*]] = load i32*, i32** @a, align 8, !tbaa !5 -; CHECK-NEXT: store i32 1, i32* [[TMP1]], align 4, !tbaa !0 -; CHECK-NEXT: call fastcc void @fn(i32* nofree nonnull readonly align 4 dereferenceable(4) @g) -; CHECK-NEXT: ret i32 0 +; IS__TUNIT____-LABEL: define {{[^@]+}}@main() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32**, i32*** @e, align 8, !tbaa !5 +; IS__TUNIT____-NEXT: store i32* @g, i32** [[TMP0]], align 8, !tbaa !5 +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = load i32*, i32** @a, align 8, !tbaa !5 +; IS__TUNIT____-NEXT: store i32 1, i32* [[TMP1]], align 4, !tbaa !0 +; IS__TUNIT____-NEXT: call fastcc void @fn(i32* nofree nonnull readonly align 4 dereferenceable(4) @g) +; IS__TUNIT____-NEXT: ret i32 0 +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@main() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32**, i32*** @e, align 8, !tbaa !5 +; IS__CGSCC____-NEXT: store i32* @g, i32** [[TMP0]], align 8, !tbaa !5 +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = load i32*, i32** @a, align 8, !tbaa !5 +; IS__CGSCC____-NEXT: store i32 1, i32* [[TMP1]], align 4, !tbaa !0 +; IS__CGSCC____-NEXT: call fastcc void @fn() +; IS__CGSCC____-NEXT: ret i32 0 ; entry: %0 = load i32**, i32*** @e, align 8, !tbaa !8 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,19 +1,43 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=4 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-windows-msvc" define internal void @add({i32, i32}* %this, i32* sret %r) { -; CHECK-LABEL: define {{[^@]+}}@add -; CHECK-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:%.*]]) -; CHECK-NEXT: [[AP:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[THIS]], i32 0, i32 0 -; CHECK-NEXT: [[BP:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[THIS]], i32 0, i32 1 -; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[AP]], align 8 -; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[BP]], align 4 -; CHECK-NEXT: [[AB:%.*]] = add i32 [[A]], [[B]] -; CHECK-NEXT: store i32 [[AB]], i32* [[R]], align 4 -; CHECK-NEXT: ret void +; +; 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-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 +; IS__TUNIT_NPM-NEXT: [[BP:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[THIS]], i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: [[A:%.*]] = load i32, i32* [[AP]], align 8 +; IS__TUNIT_NPM-NEXT: [[B:%.*]] = load i32, i32* [[BP]], align 4 +; 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____-LABEL: define {{[^@]+}}@add +; IS__CGSCC____-SAME: ({ i32, i32 }* nocapture nofree nonnull readonly align 4 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 4 +; 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 @@ -25,11 +49,29 @@ } define void @f() { -; CHECK-LABEL: define {{[^@]+}}@f() -; CHECK-NEXT: [[R:%.*]] = alloca i32 -; CHECK-NEXT: [[PAIR:%.*]] = alloca { i32, i32 } -; CHECK-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]]) -; CHECK-NEXT: ret void +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@f() +; IS__TUNIT_OPM-NEXT: [[R:%.*]] = alloca i32 +; IS__TUNIT_OPM-NEXT: [[PAIR:%.*]] = alloca { i32, i32 } +; 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-LABEL: define {{[^@]+}}@f() +; IS__TUNIT_NPM-NEXT: [[R:%.*]] = alloca i32 +; IS__TUNIT_NPM-NEXT: [[PAIR:%.*]] = alloca { i32, i32 } +; 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-LABEL: define {{[^@]+}}@f() +; IS__CGSCC_OPM-NEXT: [[R:%.*]] = alloca i32 +; IS__CGSCC_OPM-NEXT: [[PAIR:%.*]] = alloca { i32, i32 } +; IS__CGSCC_OPM-NEXT: call void @add({ i32, i32 }* nofree nonnull readonly align 8 dereferenceable(8) [[PAIR]], i32* nofree nonnull sret writeonly align 4 dereferenceable(4) [[R]]) +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@f() +; IS__CGSCC_NPM-NEXT: [[R:%.*]] = alloca i32 +; IS__CGSCC_NPM-NEXT: [[PAIR:%.*]] = alloca { i32, i32 } +; IS__CGSCC_NPM-NEXT: call void @add({ i32, i32 }* noalias nofree nonnull readonly align 8 dereferenceable(8) [[PAIR]], i32* noalias 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=4 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; PR14710 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" @@ -9,29 +12,48 @@ declare i8* @foo(%pair*) define internal void @bar(%pair* byval %Data) { -; CHECK-LABEL: define {{[^@]+}}@bar -; CHECK-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) -; CHECK-NEXT: [[DATA_PRIV:%.*]] = alloca [[PAIR:%.*]] -; CHECK-NEXT: [[DATA_PRIV_CAST:%.*]] = bitcast %pair* [[DATA_PRIV]] to i32* -; CHECK-NEXT: store i32 [[TMP0]], i32* [[DATA_PRIV_CAST]] -; CHECK-NEXT: [[DATA_PRIV_0_1:%.*]] = getelementptr [[PAIR]], %pair* [[DATA_PRIV]], i32 0, i32 1 -; CHECK-NEXT: store i32 [[TMP1]], i32* [[DATA_PRIV_0_1]] -; CHECK-NEXT: [[TMP3:%.*]] = call i8* @foo(%pair* [[DATA_PRIV]]) -; CHECK-NEXT: ret void +; IS________OPM-LABEL: define {{[^@]+}}@bar +; IS________OPM-SAME: (%pair* noalias byval [[DATA:%.*]]) +; IS________OPM-NEXT: [[TMP1:%.*]] = tail call i8* @foo(%pair* [[DATA]]) +; IS________OPM-NEXT: ret void +; +; IS________NPM-LABEL: define {{[^@]+}}@bar +; IS________NPM-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) +; IS________NPM-NEXT: [[DATA_PRIV:%.*]] = alloca [[PAIR:%.*]] +; IS________NPM-NEXT: [[DATA_PRIV_CAST:%.*]] = bitcast %pair* [[DATA_PRIV]] to i32* +; IS________NPM-NEXT: store i32 [[TMP0]], i32* [[DATA_PRIV_CAST]] +; IS________NPM-NEXT: [[DATA_PRIV_0_1:%.*]] = getelementptr [[PAIR]], %pair* [[DATA_PRIV]], i32 0, i32 1 +; IS________NPM-NEXT: store i32 [[TMP1]], i32* [[DATA_PRIV_0_1]] +; IS________NPM-NEXT: [[TMP3:%.*]] = call i8* @foo(%pair* [[DATA_PRIV]]) +; IS________NPM-NEXT: ret void ; tail call i8* @foo(%pair* %Data) ret void } define void @zed(%pair* byval %Data) { -; CHECK-LABEL: define {{[^@]+}}@zed -; CHECK-SAME: (%pair* noalias nocapture readonly byval [[DATA:%.*]]) -; CHECK-NEXT: [[DATA_CAST:%.*]] = bitcast %pair* [[DATA]] to i32* -; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[DATA_CAST]], align 1 -; CHECK-NEXT: [[DATA_0_1:%.*]] = getelementptr [[PAIR:%.*]], %pair* [[DATA]], i32 0, i32 1 -; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[DATA_0_1]], align 1 -; CHECK-NEXT: call void @bar(i32 [[TMP1]], i32 [[TMP2]]) -; CHECK-NEXT: ret void +; IS________OPM-LABEL: define {{[^@]+}}@zed +; IS________OPM-SAME: (%pair* noalias nocapture readonly byval [[DATA:%.*]]) +; IS________OPM-NEXT: call void @bar(%pair* noalias nocapture readonly byval [[DATA]]) +; IS________OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@zed +; IS__TUNIT_NPM-SAME: (%pair* noalias nocapture readonly byval [[DATA:%.*]]) +; IS__TUNIT_NPM-NEXT: [[DATA_CAST:%.*]] = bitcast %pair* [[DATA]] to i32* +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[DATA_CAST]], align 1 +; IS__TUNIT_NPM-NEXT: [[DATA_0_1:%.*]] = getelementptr [[PAIR:%.*]], %pair* [[DATA]], i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[DATA_0_1]], align 1 +; IS__TUNIT_NPM-NEXT: call void @bar(i32 [[TMP1]], i32 [[TMP2]]) +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@zed +; IS__CGSCC_NPM-SAME: (%pair* noalias nocapture nonnull readonly byval dereferenceable(8) [[DATA:%.*]]) +; IS__CGSCC_NPM-NEXT: [[DATA_CAST:%.*]] = bitcast %pair* [[DATA]] to i32* +; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[DATA_CAST]], align 1 +; IS__CGSCC_NPM-NEXT: [[DATA_0_1:%.*]] = getelementptr [[PAIR:%.*]], %pair* [[DATA]], i32 0, i32 1 +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[DATA_0_1]], align 1 +; IS__CGSCC_NPM-NEXT: call void @bar(i32 [[TMP1]], i32 [[TMP2]]) +; IS__CGSCC_NPM-NEXT: ret void ; call void @bar(%pair* byval %Data) ret void 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; Unused arguments from variadic functions cannot be eliminated as that changes ; their classiciation according to the SysV amd64 ABI. Clang and other frontends @@ -28,11 +31,17 @@ ; Function Attrs: nounwind uwtable define internal void @callee_t0f(i8* nocapture readnone %tp13, i8* nocapture readnone %tp14, i8* nocapture readnone %tp15, i8* nocapture readnone %tp16, i8* nocapture readnone %tp17, ...) { -; CHECK-LABEL: define {{[^@]+}}@callee_t0f -; CHECK-SAME: (i8* noalias nocapture nofree nonnull readnone [[TP13:%.*]], i8* noalias nocapture nofree nonnull readnone [[TP14:%.*]], i8* noalias nocapture nofree nonnull readnone [[TP15:%.*]], i8* noalias nocapture nofree nonnull readnone [[TP16:%.*]], i8* noalias nocapture nofree nonnull readnone [[TP17:%.*]], ...) -; CHECK-NEXT: entry: -; CHECK-NEXT: call void @sink(i32 0) -; CHECK-NEXT: ret void +; IS__TUNIT____-LABEL: define {{[^@]+}}@callee_t0f +; IS__TUNIT____-SAME: (i8* noalias nocapture nofree nonnull readnone [[TP13:%.*]], i8* noalias nocapture nofree nonnull readnone [[TP14:%.*]], i8* noalias nocapture nofree nonnull readnone [[TP15:%.*]], i8* noalias nocapture nofree nonnull readnone [[TP16:%.*]], i8* noalias nocapture nofree nonnull readnone [[TP17:%.*]], ...) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: call void @sink(i32 0) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@callee_t0f +; IS__CGSCC____-SAME: (i8* nocapture nofree nonnull readnone [[TP13:%.*]], i8* nocapture nofree nonnull readnone [[TP14:%.*]], i8* nocapture nofree nonnull readnone [[TP15:%.*]], i8* nocapture nofree nonnull readnone [[TP16:%.*]], i8* nocapture nofree nonnull readnone [[TP17:%.*]], ...) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: call void @sink(i32 0) +; IS__CGSCC____-NEXT: ret void ; entry: call void @sink(i32 0) 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,5 +1,9 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt < %s -passes=attributor -S | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 + ; Should not propagate the result of a weak function. ; PR2411 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,10 +1,41 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=6 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 + ; Don't constant-propagate byval pointers, since they are not pointers! ; PR5038 %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-LABEL: define {{[^@]+}}@vfu1 +; IS__CGSCC_OPM-SAME: (%struct.MYstr* noalias nocapture nofree nonnull writeonly byval align 4 dereferenceable(1) [[U:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* [[U]], i32 0, i32 1 +; IS__CGSCC_OPM-NEXT: store i32 99, i32* [[TMP0]], align 4 +; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U]], i32 0, i32 0 +; IS__CGSCC_OPM-NEXT: store i8 97, i8* [[TMP1]], align 4 +; IS__CGSCC_OPM-NEXT: br label [[RETURN:%.*]] +; IS__CGSCC_OPM: return: +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@vfu1 +; IS__CGSCC_NPM-SAME: (i8 [[TMP0:%.*]], i32 [[TMP1:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[U_PRIV:%.*]] = alloca [[STRUCT_MYSTR:%.*]] +; 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]] +; 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]] +; IS__CGSCC_NPM-NEXT: [[TMP2:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 1 +; IS__CGSCC_NPM-NEXT: store i32 99, i32* [[TMP2]], align 4 +; IS__CGSCC_NPM-NEXT: [[TMP3:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 0 +; IS__CGSCC_NPM-NEXT: store i8 97, i8* [[TMP3]], align 4 +; IS__CGSCC_NPM-NEXT: br label [[RETURN:%.*]] +; IS__CGSCC_NPM: return: +; IS__CGSCC_NPM-NEXT: ret void +; entry: %0 = getelementptr %struct.MYstr, %struct.MYstr* %u, i32 0, i32 1 ; [#uses=1] store i32 99, i32* %0, align 4 @@ -17,21 +48,42 @@ } define internal i32 @vfu2(%struct.MYstr* byval align 4 %u) nounwind readonly { -; CHECK-LABEL: define {{[^@]+}}@vfu2 -; CHECK-SAME: (i8 [[TMP0:%.*]], i32 [[TMP1:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[U_PRIV:%.*]] = alloca [[STRUCT_MYSTR:%.*]] -; CHECK-NEXT: [[U_PRIV_CAST:%.*]] = bitcast %struct.MYstr* [[U_PRIV]] to i8* -; CHECK-NEXT: store i8 [[TMP0]], i8* [[U_PRIV_CAST]] -; CHECK-NEXT: [[U_PRIV_0_1:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 1 -; CHECK-NEXT: store i32 [[TMP1]], i32* [[U_PRIV_0_1]] -; CHECK-NEXT: [[TMP2:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* @mystr, i32 0, i32 1 -; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* @mystr, i32 0, i32 0 -; CHECK-NEXT: [[TMP5:%.*]] = load i8, i8* [[TMP4]], align 8 -; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 -; CHECK-NEXT: [[TMP7:%.*]] = add i32 [[TMP6]], [[TMP3]] -; CHECK-NEXT: ret i32 [[TMP7]] +; 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: +; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* @mystr, 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* @mystr, 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-LABEL: define {{[^@]+}}@vfu2 +; IS__TUNIT_NPM-SAME: (i8 [[TMP0:%.*]], i32 [[TMP1:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[U_PRIV:%.*]] = alloca [[STRUCT_MYSTR:%.*]] +; 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]] +; 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]] +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* @mystr, 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* @mystr, 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____-LABEL: define {{[^@]+}}@vfu2() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[TMP0:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* @mystr, i32 0, i32 1 +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP0]], align 4 +; IS__CGSCC____-NEXT: [[TMP2:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* @mystr, i32 0, i32 0 +; IS__CGSCC____-NEXT: [[TMP3:%.*]] = load i8, i8* [[TMP2]], align 4 +; IS__CGSCC____-NEXT: [[TMP4:%.*]] = zext i8 [[TMP3]] to i32 +; IS__CGSCC____-NEXT: [[TMP5:%.*]] = add i32 [[TMP4]], [[TMP1]] +; IS__CGSCC____-NEXT: ret i32 [[TMP5]] ; entry: %0 = getelementptr %struct.MYstr, %struct.MYstr* %u, i32 0, i32 1 ; [#uses=1] @@ -44,14 +96,24 @@ } define i32 @unions() nounwind { -; CHECK-LABEL: define {{[^@]+}}@unions() -; CHECK-NEXT: entry: -; CHECK-NEXT: [[MYSTR_CAST:%.*]] = bitcast %struct.MYstr* @mystr to i8* -; CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[MYSTR_CAST]], align 1 -; CHECK-NEXT: [[MYSTR_0_1:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* @mystr, i32 0, i32 1 -; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[MYSTR_0_1]], align 1 -; CHECK-NEXT: [[RESULT:%.*]] = call i32 @vfu2(i8 [[TMP0]], i32 [[TMP1]]) -; CHECK-NEXT: ret i32 [[RESULT]] +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@unions() +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2(%struct.MYstr* nofree nonnull readonly byval align 8 dereferenceable(8) @mystr) +; IS__TUNIT_OPM-NEXT: ret i32 [[RESULT]] +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@unions() +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[MYSTR_CAST:%.*]] = bitcast %struct.MYstr* @mystr to i8* +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i8, i8* [[MYSTR_CAST]], align 1 +; IS__TUNIT_NPM-NEXT: [[MYSTR_0_1:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* @mystr, i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[MYSTR_0_1]], align 1 +; IS__TUNIT_NPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2(i8 [[TMP0]], i32 [[TMP1]]) +; IS__TUNIT_NPM-NEXT: ret i32 [[RESULT]] +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@unions() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[RESULT:%.*]] = call i32 @vfu2() +; IS__CGSCC____-NEXT: ret i32 [[RESULT]] ; entry: call void @vfu1(%struct.MYstr* byval align 4 @mystr) nounwind @@ -60,23 +122,67 @@ } define internal i32 @vfu2_v2(%struct.MYstr* byval align 4 %u) nounwind readonly { -; CHECK-LABEL: define {{[^@]+}}@vfu2_v2 -; CHECK-SAME: (i8 [[TMP0:%.*]], i32 [[TMP1:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[U_PRIV:%.*]] = alloca [[STRUCT_MYSTR:%.*]] -; CHECK-NEXT: [[U_PRIV_CAST:%.*]] = bitcast %struct.MYstr* [[U_PRIV]] to i8* -; CHECK-NEXT: store i8 [[TMP0]], i8* [[U_PRIV_CAST]] -; CHECK-NEXT: [[U_PRIV_0_1:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 1 -; CHECK-NEXT: store i32 [[TMP1]], i32* [[U_PRIV_0_1]] -; CHECK-NEXT: [[Z:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 1 -; CHECK-NEXT: store i32 99, i32* [[Z]], align 4 -; CHECK-NEXT: [[TMP2:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 1 -; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]] -; CHECK-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_MYSTR]], %struct.MYstr* [[U_PRIV]], i32 0, i32 0 -; CHECK-NEXT: [[TMP5:%.*]] = load i8, i8* [[TMP4]], align 8 -; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 -; CHECK-NEXT: [[TMP7:%.*]] = add i32 [[TMP6]], [[TMP3]] -; CHECK-NEXT: ret i32 [[TMP7]] +; 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-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:%.*]] +; 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]] +; 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]] +; 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-LABEL: define {{[^@]+}}@vfu2_v2 +; IS__CGSCC_OPM-SAME: (%struct.MYstr* noalias nocapture nofree nonnull byval align 4 dereferenceable(1) [[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 4 +; 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-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:%.*]] +; 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]] +; 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]] +; 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 4 +; 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 @@ -91,14 +197,33 @@ } define i32 @unions_v2() nounwind { -; CHECK-LABEL: define {{[^@]+}}@unions_v2() -; CHECK-NEXT: entry: -; CHECK-NEXT: [[MYSTR_CAST:%.*]] = bitcast %struct.MYstr* @mystr to i8* -; CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[MYSTR_CAST]], align 1 -; CHECK-NEXT: [[MYSTR_0_1:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* @mystr, i32 0, i32 1 -; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[MYSTR_0_1]], align 1 -; CHECK-NEXT: [[RESULT:%.*]] = call i32 @vfu2_v2(i8 [[TMP0]], i32 [[TMP1]]) -; CHECK-NEXT: ret i32 [[RESULT]] +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@unions_v2() +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2_v2(%struct.MYstr* nofree nonnull readonly byval align 8 dereferenceable(8) @mystr) +; IS__TUNIT_OPM-NEXT: ret i32 [[RESULT]] +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@unions_v2() +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[MYSTR_CAST:%.*]] = bitcast %struct.MYstr* @mystr to i8* +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i8, i8* [[MYSTR_CAST]], align 1 +; IS__TUNIT_NPM-NEXT: [[MYSTR_0_1:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* @mystr, i32 0, i32 1 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[MYSTR_0_1]], align 1 +; IS__TUNIT_NPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2_v2(i8 [[TMP0]], i32 [[TMP1]]) +; IS__TUNIT_NPM-NEXT: ret i32 [[RESULT]] +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@unions_v2() +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2_v2(%struct.MYstr* noalias nofree nonnull readnone byval align 8 dereferenceable(8) @mystr) +; IS__CGSCC_OPM-NEXT: ret i32 [[RESULT]] +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@unions_v2() +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[MYSTR_CAST1:%.*]] = bitcast %struct.MYstr* @mystr to i8* +; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = load i8, i8* [[MYSTR_CAST1]], align 8 +; IS__CGSCC_NPM-NEXT: [[MYSTR_0_12:%.*]] = getelementptr [[STRUCT_MYSTR:%.*]], %struct.MYstr* @mystr, i32 0, i32 1 +; IS__CGSCC_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[MYSTR_0_12]], align 1 +; IS__CGSCC_NPM-NEXT: [[RESULT:%.*]] = call i32 @vfu2_v2(i8 [[TMP0]], i32 [[TMP1]]) +; IS__CGSCC_NPM-NEXT: ret i32 [[RESULT]] ; entry: call void @vfu1(%struct.MYstr* byval align 4 @mystr) nounwind 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,14 +1,22 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=2 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" define i64 @fn2() { -; CHECK-LABEL: define {{[^@]+}}@fn2() -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 undef) #1, !range !0 -; CHECK-NEXT: ret i64 [[CALL2]] +; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@fn2() +; NOT_TUNIT_NPM-NEXT: entry: +; NOT_TUNIT_NPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 undef) +; NOT_TUNIT_NPM-NEXT: ret i64 [[CALL2]] +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@fn2() +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 undef) #1, !range !0 +; IS__TUNIT_NPM-NEXT: ret i64 [[CALL2]] ; entry: %conv = sext i32 undef to i64 @@ -18,13 +26,21 @@ } define i64 @fn2b(i32 %arg) { -; CHECK-LABEL: define {{[^@]+}}@fn2b -; CHECK-SAME: (i32 [[ARG:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[ARG]] to i64 -; CHECK-NEXT: [[DIV:%.*]] = sdiv i64 8, [[CONV]] -; CHECK-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 [[DIV]]) #1, !range !0 -; CHECK-NEXT: ret i64 [[CALL2]] +; NOT_TUNIT_NPM-LABEL: define {{[^@]+}}@fn2b +; NOT_TUNIT_NPM-SAME: (i32 [[ARG:%.*]]) +; NOT_TUNIT_NPM-NEXT: entry: +; NOT_TUNIT_NPM-NEXT: [[CONV:%.*]] = sext i32 [[ARG]] to i64 +; NOT_TUNIT_NPM-NEXT: [[DIV:%.*]] = sdiv i64 8, [[CONV]] +; NOT_TUNIT_NPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 [[DIV]]) +; NOT_TUNIT_NPM-NEXT: ret i64 [[CALL2]] +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@fn2b +; IS__TUNIT_NPM-SAME: (i32 [[ARG:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[CONV:%.*]] = sext i32 [[ARG]] to i64 +; IS__TUNIT_NPM-NEXT: [[DIV:%.*]] = sdiv i64 8, [[CONV]] +; IS__TUNIT_NPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 [[DIV]]) #1, !range !0 +; IS__TUNIT_NPM-NEXT: ret i64 [[CALL2]] ; entry: %conv = sext i32 %arg to i64 @@ -34,10 +50,19 @@ } define i64 @fn2c() { -; CHECK-LABEL: define {{[^@]+}}@fn2c() -; CHECK-NEXT: entry: -; CHECK-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 42) #1, !range !0 -; CHECK-NEXT: ret i64 [[CALL2]] +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@fn2c() +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 42) +; IS__TUNIT_OPM-NEXT: ret i64 [[CALL2]] +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@fn2c() +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 42) #1, !range !0 +; IS__TUNIT_NPM-NEXT: ret i64 [[CALL2]] +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@fn2c() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: ret i64 42 ; entry: %conv = sext i32 undef to i64 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,21 +1,42 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" define void @fn2(i32* %P, i1 %C) { -; CHECK-LABEL: define {{[^@]+}}@fn2 -; CHECK-SAME: (i32* nocapture nofree [[P:%.*]], i1 %C) -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[IF_END:%.*]] -; CHECK: for.cond1: -; CHECK-NEXT: br i1 %C, label %if.end, label %exit -; CHECK: if.end: -; CHECK-NEXT: [[E_2:%.*]] = phi i32* [ %P, %entry ], [ null, %for.cond1 ] -; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[E_2]], align 4 -; CHECK-NEXT: [[CALL:%.*]] = call i32 @fn1(i32 [[TMP0]]) -; CHECK-NEXT: store i32 [[CALL]], i32* [[P]] -; CHECK-NEXT: br label %for.cond1 +; +; IS__TUNIT____-LABEL: define {{[^@]+}}@fn2 +; IS__TUNIT____-SAME: (i32* nocapture nofree [[P:%.*]], i1 [[C:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: br label [[IF_END:%.*]] +; IS__TUNIT____: for.cond1: +; IS__TUNIT____-NEXT: br i1 [[C]], label [[IF_END]], label [[EXIT:%.*]] +; IS__TUNIT____: if.end: +; IS__TUNIT____-NEXT: [[E_2:%.*]] = phi i32* [ [[P]], [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ] +; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32, i32* [[E_2]], align 4 +; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32 @fn1(i32 [[TMP0]]) +; IS__TUNIT____-NEXT: store i32 [[CALL]], i32* [[P]] +; IS__TUNIT____-NEXT: br label [[FOR_COND1]] +; IS__TUNIT____: exit: +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@fn2 +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull align 4 dereferenceable(4) [[P:%.*]], i1 [[C:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br label [[IF_END:%.*]] +; IS__CGSCC____: for.cond1: +; IS__CGSCC____-NEXT: br i1 [[C]], label [[IF_END]], label [[EXIT:%.*]] +; IS__CGSCC____: if.end: +; IS__CGSCC____-NEXT: [[E_2:%.*]] = phi i32* [ [[P]], [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ] +; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* [[E_2]], align 4 +; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @fn1(i32 [[TMP0]]) +; IS__CGSCC____-NEXT: store i32 [[CALL]], i32* [[P]], align 4 +; IS__CGSCC____-NEXT: br label [[FOR_COND1]] +; IS__CGSCC____: exit: +; IS__CGSCC____-NEXT: ret void ; entry: br label %if.end @@ -48,18 +69,51 @@ } define void @fn_no_null_opt(i32* %P, i1 %C) "null-pointer-is-valid"="true" { -; CHECK-LABEL: define {{[^@]+}}@fn_no_null_opt -; CHECK-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i1 %C) -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[IF_END:%.*]] -; CHECK: for.cond1: -; CHECK-NEXT: br i1 %C, label %if.end, label %exit -; CHECK: if.end: -; CHECK-NEXT: [[E_2:%.*]] = phi i32* [ undef, %entry ], [ null, %for.cond1 ] -; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* null, align 4 -; CHECK-NEXT: [[CALL:%.*]] = call i32 @fn0(i32 [[TMP0]]) -; CHECK-NEXT: store i32 [[CALL]], i32* [[P]] -; CHECK-NEXT: br label %for.cond1 +; +; IS__TUNIT____-LABEL: define {{[^@]+}}@fn_no_null_opt +; IS__TUNIT____-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i1 [[C:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: br label [[IF_END:%.*]] +; IS__TUNIT____: for.cond1: +; IS__TUNIT____-NEXT: br i1 [[C]], label [[IF_END]], label [[EXIT:%.*]] +; IS__TUNIT____: if.end: +; IS__TUNIT____-NEXT: [[E_2:%.*]] = phi i32* [ undef, [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ] +; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32, i32* null, align 4 +; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32 @fn0(i32 [[TMP0]]) +; IS__TUNIT____-NEXT: store i32 [[CALL]], i32* [[P]] +; IS__TUNIT____-NEXT: br label [[FOR_COND1]] +; IS__TUNIT____: exit: +; IS__TUNIT____-NEXT: ret void +; +; 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: +; IS__CGSCC_OPM-NEXT: br label [[IF_END:%.*]] +; IS__CGSCC_OPM: for.cond1: +; IS__CGSCC_OPM-NEXT: br i1 [[C]], label [[IF_END]], label [[EXIT:%.*]] +; IS__CGSCC_OPM: if.end: +; IS__CGSCC_OPM-NEXT: [[E_2:%.*]] = phi i32* [ undef, [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ] +; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = load i32, i32* null, align 4 +; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call i32 @fn0(i32 [[TMP0]]) +; IS__CGSCC_OPM-NEXT: store i32 [[CALL]], i32* [[P]], align 4 +; IS__CGSCC_OPM-NEXT: br label [[FOR_COND1]] +; IS__CGSCC_OPM: exit: +; IS__CGSCC_OPM-NEXT: ret void +; +; 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: +; IS__CGSCC_NPM-NEXT: br label [[IF_END:%.*]] +; IS__CGSCC_NPM: for.cond1: +; IS__CGSCC_NPM-NEXT: br i1 [[C]], label [[IF_END]], label [[EXIT:%.*]] +; IS__CGSCC_NPM: if.end: +; IS__CGSCC_NPM-NEXT: [[E_2:%.*]] = phi i32* [ undef, [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ] +; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* null, align 536870912 +; IS__CGSCC_NPM-NEXT: [[CALL:%.*]] = call i32 @fn0(i32 [[TMP0]]) +; IS__CGSCC_NPM-NEXT: store i32 [[CALL]], i32* [[P]], align 4 +; IS__CGSCC_NPM-NEXT: br label [[FOR_COND1]] +; IS__CGSCC_NPM: exit: +; IS__CGSCC_NPM-NEXT: ret void ; entry: br label %if.end 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 %struct.wobble = type { i32 } %struct.zot = type { %struct.wobble, %struct.wobble, %struct.wobble } @@ -17,10 +20,16 @@ } define void @baz(<8 x i32> %arg) local_unnamed_addr { -; CHECK-LABEL: define {{[^@]+}}@baz -; CHECK-SAME: (<8 x i32> [[ARG:%.*]]) local_unnamed_addr -; CHECK-NEXT: bb: -; CHECK-NEXT: ret void +; 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____-LABEL: define {{[^@]+}}@baz +; IS__CGSCC____-SAME: (<8 x i32> [[ARG:%.*]]) local_unnamed_addr +; IS__CGSCC____-NEXT: bb: +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = extractvalue [[STRUCT_ZOT:%.*]] undef, 0, 0 +; IS__CGSCC____-NEXT: ret void ; bb: %tmp = call %struct.zot @widget(<8 x i32> %arg) 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; The original C source looked like this: ; @@ -76,11 +79,18 @@ ; been provided), define dso_local i16 @vararg_tests(i16 %a) { -; CHECK-LABEL: define {{[^@]+}}@vararg_tests -; CHECK-SAME: (i16 [[A:%.*]]) -; CHECK-NEXT: [[CALL2:%.*]] = call i16 bitcast (i16 (i16, i16, ...)* @vararg_no_prop to i16 (i16)*)(i16 7) -; CHECK-NEXT: [[ADD:%.*]] = add i16 7, [[CALL2]] -; CHECK-NEXT: ret i16 [[ADD]] +; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@vararg_tests +; NOT_CGSCC_OPM-SAME: (i16 [[A:%.*]]) +; NOT_CGSCC_OPM-NEXT: [[CALL2:%.*]] = call i16 bitcast (i16 (i16, i16, ...)* @vararg_no_prop to i16 (i16)*)(i16 7) +; NOT_CGSCC_OPM-NEXT: [[ADD:%.*]] = add i16 7, [[CALL2]] +; NOT_CGSCC_OPM-NEXT: ret i16 [[ADD]] +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@vararg_tests +; IS__CGSCC_OPM-SAME: (i16 [[A:%.*]]) +; IS__CGSCC_OPM-NEXT: [[CALL1:%.*]] = call i16 (i16, ...) @vararg_prop(i16 7, i16 8, i16 [[A]]) +; IS__CGSCC_OPM-NEXT: [[CALL2:%.*]] = call i16 bitcast (i16 (i16, i16, ...)* @vararg_no_prop to i16 (i16)*)(i16 7) +; IS__CGSCC_OPM-NEXT: [[ADD:%.*]] = add i16 [[CALL1]], [[CALL2]] +; IS__CGSCC_OPM-NEXT: ret i16 [[ADD]] ; %call1 = call i16 (i16, ...) @vararg_prop(i16 7, i16 8, i16 %a) %call2 = call i16 bitcast (i16 (i16, i16, ...) * @vararg_no_prop to i16 (i16) *) (i16 7) @@ -89,6 +99,10 @@ } define internal i16 @vararg_prop(i16 %p1, ...) { +; IS__CGSCC____-LABEL: define {{[^@]+}}@vararg_prop +; IS__CGSCC____-SAME: (i16 returned [[P1:%.*]], ...) +; 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; This test is just to verify that we do not crash/assert due to mismatch in ; argument type between the caller and callee. 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; See PR26774 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,23 +1,51 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes='internalize,attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; PR5569 ; IPSCCP should prove that the blocks are dead and delete them, and ; properly handle the dangling blockaddress constants. -; CHECK: @bar.l = internal constant [2 x i8*] [i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 1 to i8*)] +; NOT_CGSCC_OPM: @bar.l = internal constant [2 x i8*] [i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 1 to i8*)] +; IS__CGSCC_OPM: @bar.l = internal constant [2 x i8*] [i8* blockaddress(@bar, %lab0), i8* blockaddress(@bar, %end)] @code = global [5 x i32] [i32 0, i32 0, i32 0, i32 0, i32 1], align 4 ; <[5 x i32]*> [#uses=0] @bar.l = internal constant [2 x i8*] [i8* blockaddress(@bar, %lab0), i8* blockaddress(@bar, %end)] ; <[2 x i8*]*> [#uses=1] -define void @foo(i32 %x) nounwind readnone { +define internal void @foo(i32 %x) nounwind readnone { +; IS__CGSCC____-LABEL: define {{[^@]+}}@foo +; IS__CGSCC____-SAME: (i32 [[X:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[B:%.*]] = alloca i32, align 4 +; IS__CGSCC____-NEXT: store volatile i32 -1, i32* [[B]] +; IS__CGSCC____-NEXT: ret void +; entry: %b = alloca i32, align 4 ; [#uses=1] store volatile i32 -1, i32* %b ret void } -define void @bar(i32* nocapture %pc) nounwind readonly { +define internal void @bar(i32* nocapture %pc) nounwind readonly { +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@bar +; IS__CGSCC_OPM-SAME: (i32* nocapture [[PC:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: br label [[INDIRECTGOTO:%.*]] +; IS__CGSCC_OPM: lab0: +; IS__CGSCC_OPM-NEXT: [[INDVAR_NEXT:%.*]] = add i32 [[INDVAR:%.*]], 1 +; IS__CGSCC_OPM-NEXT: br label [[INDIRECTGOTO]] +; IS__CGSCC_OPM: end: +; IS__CGSCC_OPM-NEXT: ret void +; IS__CGSCC_OPM: indirectgoto: +; IS__CGSCC_OPM-NEXT: [[INDVAR]] = phi i32 [ [[INDVAR_NEXT]], [[LAB0:%.*]] ], [ 0, [[ENTRY:%.*]] ] +; IS__CGSCC_OPM-NEXT: [[PC_ADDR_0:%.*]] = getelementptr i32, i32* [[PC]], i32 [[INDVAR]] +; IS__CGSCC_OPM-NEXT: [[TMP1_PN:%.*]] = load i32, i32* [[PC_ADDR_0]] +; IS__CGSCC_OPM-NEXT: [[INDIRECT_GOTO_DEST_IN:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* @bar.l, i32 0, i32 [[TMP1_PN]] +; IS__CGSCC_OPM-NEXT: [[INDIRECT_GOTO_DEST:%.*]] = load i8*, i8** [[INDIRECT_GOTO_DEST_IN]] +; IS__CGSCC_OPM-NEXT: indirectbr i8* [[INDIRECT_GOTO_DEST]], [label [[LAB0]], label %end] +; entry: br label %indirectgoto @@ -38,6 +66,10 @@ } define i32 @main() nounwind readnone { +; CHECK-LABEL: define {{[^@]+}}@main() +; CHECK-NEXT: entry: +; CHECK-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,6 +1,14 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 -disable-output < %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 void @foo(i32 %X) { +; CHECK-LABEL: define {{[^@]+}}@foo +; CHECK-SAME: (i32 [[X:%.*]]) +; CHECK-NEXT: call void @foo(i32 [[X]]) +; CHECK-NEXT: ret void +; call void @foo( i32 %X ) ret void } 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 target datalayout = "E-m:e-i64:64-n32:64" target triple = "powerpc64-bgq-linux" 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 @_ZL6test1g = internal global i32 42, 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; ; ; /---------------------------------------| 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,26 +1,46 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=4 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; PR36485 ; musttail call result can't be replaced with a constant, unless the call can be removed declare i32 @external() define i8* @start(i8 %v) { -; CHECK-LABEL: define {{[^@]+}}@start -; CHECK-SAME: (i8 [[V:%.*]]) -; CHECK-NEXT: [[C1:%.*]] = icmp eq i8 [[V]], 0 -; CHECK-NEXT: br i1 [[C1]], label [[TRUE:%.*]], label [[FALSE:%.*]] -; CHECK: true: -; CHECK-NEXT: [[CA:%.*]] = musttail call i8* @side_effects(i8 [[V]]) -; CHECK-NEXT: ret i8* [[CA]] -; CHECK: false: -; CHECK-NEXT: [[C2:%.*]] = icmp eq i8 [[V]], 1 -; CHECK-NEXT: br i1 [[C2]], label [[C2_TRUE:%.*]], label [[C2_FALSE:%.*]] -; CHECK: c2_true: -; CHECK-NEXT: ret i8* null -; CHECK: c2_false: -; CHECK-NEXT: [[CA2:%.*]] = musttail call i8* @dont_zap_me(i8 undef) -; CHECK-NEXT: ret i8* [[CA2]] +; IS__TUNIT____-LABEL: define {{[^@]+}}@start +; IS__TUNIT____-SAME: (i8 [[V:%.*]]) +; IS__TUNIT____-NEXT: [[C1:%.*]] = icmp eq i8 [[V]], 0 +; IS__TUNIT____-NEXT: br i1 [[C1]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; IS__TUNIT____: true: +; IS__TUNIT____-NEXT: [[CA:%.*]] = musttail call i8* @side_effects(i8 [[V]]) +; IS__TUNIT____-NEXT: ret i8* [[CA]] +; IS__TUNIT____: false: +; IS__TUNIT____-NEXT: [[C2:%.*]] = icmp eq i8 [[V]], 1 +; IS__TUNIT____-NEXT: br i1 [[C2]], label [[C2_TRUE:%.*]], label [[C2_FALSE:%.*]] +; IS__TUNIT____: c2_true: +; IS__TUNIT____-NEXT: ret i8* null +; IS__TUNIT____: c2_false: +; IS__TUNIT____-NEXT: [[CA2:%.*]] = musttail call i8* @dont_zap_me(i8 undef) +; IS__TUNIT____-NEXT: ret i8* [[CA2]] +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@start +; IS__CGSCC____-SAME: (i8 [[V:%.*]]) +; IS__CGSCC____-NEXT: [[C1:%.*]] = icmp eq i8 [[V]], 0 +; IS__CGSCC____-NEXT: br i1 [[C1]], label [[TRUE:%.*]], label [[FALSE:%.*]] +; IS__CGSCC____: true: +; IS__CGSCC____-NEXT: [[CA:%.*]] = musttail call noalias align 536870912 i8* @side_effects(i8 [[V]]) +; IS__CGSCC____-NEXT: ret i8* [[CA]] +; IS__CGSCC____: false: +; IS__CGSCC____-NEXT: [[C2:%.*]] = icmp eq i8 [[V]], 1 +; IS__CGSCC____-NEXT: br i1 [[C2]], label [[C2_TRUE:%.*]], label [[C2_FALSE:%.*]] +; IS__CGSCC____: c2_true: +; IS__CGSCC____-NEXT: [[CA1:%.*]] = musttail call noalias align 536870912 i8* @no_side_effects(i8 [[V]]) +; IS__CGSCC____-NEXT: ret i8* [[CA1]] +; IS__CGSCC____: c2_false: +; IS__CGSCC____-NEXT: [[CA2:%.*]] = musttail call noalias align 536870912 i8* @dont_zap_me(i8 [[V]]) +; IS__CGSCC____-NEXT: ret i8* [[CA2]] ; %c1 = icmp eq i8 %v, 0 br i1 %c1, label %true, label %false @@ -41,11 +61,17 @@ } define internal i8* @side_effects(i8 %v) { -; CHECK-LABEL: define {{[^@]+}}@side_effects -; CHECK-SAME: (i8 [[V:%.*]]) -; CHECK-NEXT: [[I1:%.*]] = call i32 @external() -; CHECK-NEXT: [[CA:%.*]] = musttail call i8* @start(i8 [[V]]) -; CHECK-NEXT: ret i8* [[CA]] +; IS__TUNIT____-LABEL: define {{[^@]+}}@side_effects +; IS__TUNIT____-SAME: (i8 [[V:%.*]]) +; IS__TUNIT____-NEXT: [[I1:%.*]] = call i32 @external() +; IS__TUNIT____-NEXT: [[CA:%.*]] = musttail call i8* @start(i8 [[V]]) +; IS__TUNIT____-NEXT: ret i8* [[CA]] +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@side_effects +; IS__CGSCC____-SAME: (i8 [[V:%.*]]) +; IS__CGSCC____-NEXT: [[I1:%.*]] = call i32 @external() +; IS__CGSCC____-NEXT: [[CA:%.*]] = musttail call noalias align 536870912 i8* @start(i8 [[V]]) +; IS__CGSCC____-NEXT: ret i8* [[CA]] ; %i1 = call i32 @external() @@ -60,14 +86,23 @@ } define internal i8* @no_side_effects(i8 %v) readonly nounwind { +; IS__CGSCC____-LABEL: define {{[^@]+}}@no_side_effects +; IS__CGSCC____-SAME: (i8 [[V:%.*]]) +; IS__CGSCC____-NEXT: ret i8* null +; ret i8* null } define internal i8* @dont_zap_me(i8 %v) { -; CHECK-LABEL: define {{[^@]+}}@dont_zap_me -; CHECK-SAME: (i8 [[V:%.*]]) -; CHECK-NEXT: [[I1:%.*]] = call i32 @external() -; CHECK-NEXT: ret i8* undef +; IS__TUNIT____-LABEL: define {{[^@]+}}@dont_zap_me +; IS__TUNIT____-SAME: (i8 [[V:%.*]]) +; IS__TUNIT____-NEXT: [[I1:%.*]] = call i32 @external() +; IS__TUNIT____-NEXT: ret i8* undef +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@dont_zap_me +; IS__CGSCC____-SAME: (i8 [[V:%.*]]) +; IS__CGSCC____-NEXT: [[I1:%.*]] = call i32 @external() +; IS__CGSCC____-NEXT: ret i8* null ; %i1 = call i32 @external() 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" target triple = "i686-pc-windows-msvc19.0.24215" 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=3 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; ; void bar(int, float, double); ; @@ -25,16 +28,49 @@ @1 = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str, i32 0, i32 0) }, align 8 define dso_local void @foo(i32 %N) { -; CHECK-LABEL: define {{[^@]+}}@foo -; CHECK-SAME: (i32 [[N:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4 -; CHECK-NEXT: [[P:%.*]] = alloca float, align 4 -; CHECK-NEXT: store i32 [[N]], i32* [[N_ADDR]], align 4 -; CHECK-NEXT: store float 3.000000e+00, float* [[P]], align 4 -; CHECK-NEXT: store i32 7, i32* [[N_ADDR]], align 4 -; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* nonnull align 8 dereferenceable(24) @1, i32 3, void (i32*, i32*, ...)* nonnull bitcast (void (i32*, i32*, i32*, float*, i64)* @.omp_outlined. to void (i32*, i32*, ...)*), i32* noalias nocapture nonnull readonly align 4 dereferenceable(4) [[N_ADDR]], float* noalias nocapture nonnull readonly align 4 dereferenceable(4) [[P]], i64 undef) -; CHECK-NEXT: ret void +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@foo +; IS__TUNIT_OPM-SAME: (i32 [[N:%.*]]) +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4 +; IS__TUNIT_OPM-NEXT: [[P:%.*]] = alloca float, align 4 +; IS__TUNIT_OPM-NEXT: store i32 [[N]], i32* [[N_ADDR]], align 4 +; IS__TUNIT_OPM-NEXT: store float 3.000000e+00, float* [[P]], align 4 +; IS__TUNIT_OPM-NEXT: store i32 7, i32* [[N_ADDR]], align 4 +; IS__TUNIT_OPM-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* nonnull align 8 dereferenceable(24) @1, i32 3, void (i32*, i32*, ...)* nonnull bitcast (void (i32*, i32*, i32*, float*, i64)* @.omp_outlined. to void (i32*, i32*, ...)*), i32* nocapture nonnull readonly align 4 dereferenceable(4) [[N_ADDR]], float* nocapture nonnull readonly align 4 dereferenceable(4) [[P]], i64 undef) +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@foo +; IS__TUNIT_NPM-SAME: (i32 [[N:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4 +; IS__TUNIT_NPM-NEXT: [[P:%.*]] = alloca float, align 4 +; IS__TUNIT_NPM-NEXT: store i32 [[N]], i32* [[N_ADDR]], align 4 +; IS__TUNIT_NPM-NEXT: store float 3.000000e+00, float* [[P]], align 4 +; IS__TUNIT_NPM-NEXT: store i32 7, i32* [[N_ADDR]], align 4 +; IS__TUNIT_NPM-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* nonnull align 8 dereferenceable(24) @1, i32 3, void (i32*, i32*, ...)* nonnull bitcast (void (i32*, i32*, i32*, float*, i64)* @.omp_outlined. to void (i32*, i32*, ...)*), i32* noalias nocapture nonnull readonly align 4 dereferenceable(4) [[N_ADDR]], float* noalias nocapture nonnull readonly align 4 dereferenceable(4) [[P]], i64 undef) +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@foo +; IS__CGSCC_OPM-SAME: (i32 [[N:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4 +; IS__CGSCC_OPM-NEXT: [[P:%.*]] = alloca float, align 4 +; IS__CGSCC_OPM-NEXT: store i32 [[N]], i32* [[N_ADDR]], align 4 +; IS__CGSCC_OPM-NEXT: store float 3.000000e+00, float* [[P]], align 4 +; IS__CGSCC_OPM-NEXT: store i32 7, i32* [[N_ADDR]], align 4 +; IS__CGSCC_OPM-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* nonnull align 8 dereferenceable(24) @1, i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, float*, i64)* @.omp_outlined. to void (i32*, i32*, ...)*), i32* nonnull align 4 dereferenceable(4) [[N_ADDR]], float* nonnull align 4 dereferenceable(4) [[P]], i64 4617315517961601024) +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@foo +; IS__CGSCC_NPM-SAME: (i32 [[N:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[N_ADDR:%.*]] = alloca i32, align 4 +; IS__CGSCC_NPM-NEXT: [[P:%.*]] = alloca float, align 4 +; IS__CGSCC_NPM-NEXT: store i32 [[N]], i32* [[N_ADDR]], align 4 +; IS__CGSCC_NPM-NEXT: store float 3.000000e+00, float* [[P]], align 4 +; IS__CGSCC_NPM-NEXT: store i32 7, i32* [[N_ADDR]], align 4 +; IS__CGSCC_NPM-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* nonnull align 8 dereferenceable(24) @1, i32 3, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, float*, i64)* @.omp_outlined. to void (i32*, i32*, ...)*), i32* noalias nocapture nonnull readonly align 4 dereferenceable(4) [[N_ADDR]], float* noalias nocapture nonnull readonly align 4 dereferenceable(4) [[P]], i64 4617315517961601024) +; IS__CGSCC_NPM-NEXT: ret void ; entry: %N.addr = alloca i32, align 4 @@ -47,13 +83,195 @@ } define internal void @.omp_outlined.(i32* noalias %.global_tid., i32* noalias %.bound_tid., i32* dereferenceable(4) %N, float* dereferenceable(4) %p, i64 %q) { +; IS________OPM-LABEL: define {{[^@]+}}@.omp_outlined. +; IS________OPM-SAME: (i32* noalias nocapture readonly [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], i32* nocapture nonnull readonly align 4 dereferenceable(4) [[N:%.*]], float* nocapture nonnull readonly align 4 dereferenceable(4) [[P:%.*]], i64 [[Q:%.*]]) +; IS________OPM-NEXT: entry: +; IS________OPM-NEXT: [[Q_ADDR:%.*]] = alloca i64, align 8 +; IS________OPM-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 +; IS________OPM-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 +; IS________OPM-NEXT: [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4 +; IS________OPM-NEXT: [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4 +; IS________OPM-NEXT: store i64 4617315517961601024, i64* [[Q_ADDR]], align 8 +; IS________OPM-NEXT: [[CONV:%.*]] = bitcast i64* [[Q_ADDR]] to double* +; IS________OPM-NEXT: [[TMP:%.*]] = load i32, i32* [[N]], align 4 +; IS________OPM-NEXT: [[SUB3:%.*]] = add nsw i32 [[TMP]], -3 +; IS________OPM-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP]], 2 +; IS________OPM-NEXT: br i1 [[CMP]], label [[OMP_PRECOND_THEN:%.*]], label [[OMP_PRECOND_END:%.*]] +; IS________OPM: omp.precond.then: +; IS________OPM-NEXT: store i32 0, i32* [[DOTOMP_LB]], align 4 +; IS________OPM-NEXT: store i32 [[SUB3]], i32* [[DOTOMP_UB]], align 4 +; IS________OPM-NEXT: store i32 1, i32* [[DOTOMP_STRIDE]], align 4 +; IS________OPM-NEXT: store i32 0, i32* [[DOTOMP_IS_LAST]], align 4 +; IS________OPM-NEXT: [[TMP5:%.*]] = load i32, i32* [[DOTGLOBAL_TID_]], align 4 +; IS________OPM-NEXT: call void @__kmpc_for_static_init_4(%struct.ident_t* nonnull align 8 dereferenceable(24) @0, i32 [[TMP5]], i32 34, i32* nonnull align 4 dereferenceable(4) [[DOTOMP_IS_LAST]], i32* nonnull align 4 dereferenceable(4) [[DOTOMP_LB]], i32* nonnull align 4 dereferenceable(4) [[DOTOMP_UB]], i32* nonnull align 4 dereferenceable(4) [[DOTOMP_STRIDE]], i32 1, i32 1) +; IS________OPM-NEXT: [[TMP6:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4 +; IS________OPM-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[TMP6]], [[SUB3]] +; IS________OPM-NEXT: br i1 [[CMP6]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] +; IS________OPM: cond.true: +; IS________OPM-NEXT: br label [[COND_END:%.*]] +; IS________OPM: cond.false: +; IS________OPM-NEXT: [[TMP7:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4 +; IS________OPM-NEXT: br label [[COND_END]] +; IS________OPM: cond.end: +; IS________OPM-NEXT: [[COND:%.*]] = phi i32 [ [[SUB3]], [[COND_TRUE]] ], [ [[TMP7]], [[COND_FALSE]] ] +; IS________OPM-NEXT: store i32 [[COND]], i32* [[DOTOMP_UB]], align 4 +; IS________OPM-NEXT: [[TMP8:%.*]] = load i32, i32* [[DOTOMP_LB]], align 4 +; IS________OPM-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] +; IS________OPM: omp.inner.for.cond: +; IS________OPM-NEXT: [[DOTOMP_IV_0:%.*]] = phi i32 [ [[TMP8]], [[COND_END]] ], [ [[ADD11:%.*]], [[OMP_INNER_FOR_INC:%.*]] ] +; IS________OPM-NEXT: [[TMP9:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4 +; IS________OPM-NEXT: [[CMP8:%.*]] = icmp sgt i32 [[DOTOMP_IV_0]], [[TMP9]] +; IS________OPM-NEXT: br i1 [[CMP8]], label [[OMP_INNER_FOR_COND_CLEANUP:%.*]], label [[OMP_INNER_FOR_BODY:%.*]] +; IS________OPM: omp.inner.for.cond.cleanup: +; IS________OPM-NEXT: br label [[OMP_INNER_FOR_END:%.*]] +; IS________OPM: omp.inner.for.body: +; IS________OPM-NEXT: [[ADD10:%.*]] = add nsw i32 [[DOTOMP_IV_0]], 2 +; IS________OPM-NEXT: [[TMP10:%.*]] = load float, float* [[P]], align 4 +; IS________OPM-NEXT: [[TMP11:%.*]] = load double, double* [[CONV]], align 8 +; IS________OPM-NEXT: call void @bar(i32 [[ADD10]], float [[TMP10]], double [[TMP11]]) +; IS________OPM-NEXT: br label [[OMP_BODY_CONTINUE:%.*]] +; IS________OPM: omp.body.continue: +; IS________OPM-NEXT: br label [[OMP_INNER_FOR_INC]] +; IS________OPM: omp.inner.for.inc: +; IS________OPM-NEXT: [[ADD11]] = add nsw i32 [[DOTOMP_IV_0]], 1 +; IS________OPM-NEXT: br label [[OMP_INNER_FOR_COND]] +; IS________OPM: omp.inner.for.end: +; IS________OPM-NEXT: br label [[OMP_LOOP_EXIT:%.*]] +; IS________OPM: omp.loop.exit: +; IS________OPM-NEXT: [[TMP12:%.*]] = load i32, i32* [[DOTGLOBAL_TID_]], align 4 +; IS________OPM-NEXT: call void @__kmpc_for_static_fini(%struct.ident_t* nonnull align 8 dereferenceable(24) @0, i32 [[TMP12]]) +; IS________OPM-NEXT: br label [[OMP_PRECOND_END]] +; IS________OPM: omp.precond.end: +; IS________OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@.omp_outlined. +; IS__TUNIT_NPM-SAME: (i32* noalias nocapture readonly [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], i32* noalias nocapture nonnull readonly align 4 dereferenceable(4) [[N:%.*]], float* noalias nocapture nonnull readonly align 4 dereferenceable(4) [[P:%.*]], i64 [[Q:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[Q_ADDR:%.*]] = alloca i64, align 8 +; IS__TUNIT_NPM-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 +; IS__TUNIT_NPM-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 +; IS__TUNIT_NPM-NEXT: [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4 +; IS__TUNIT_NPM-NEXT: [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4 +; IS__TUNIT_NPM-NEXT: store i64 4617315517961601024, i64* [[Q_ADDR]], align 8 +; IS__TUNIT_NPM-NEXT: [[CONV:%.*]] = bitcast i64* [[Q_ADDR]] to double* +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = load i32, i32* [[N]], align 4 +; IS__TUNIT_NPM-NEXT: [[SUB3:%.*]] = add nsw i32 [[TMP]], -3 +; IS__TUNIT_NPM-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP]], 2 +; IS__TUNIT_NPM-NEXT: br i1 [[CMP]], label [[OMP_PRECOND_THEN:%.*]], label [[OMP_PRECOND_END:%.*]] +; IS__TUNIT_NPM: omp.precond.then: +; IS__TUNIT_NPM-NEXT: store i32 0, i32* [[DOTOMP_LB]], align 4 +; IS__TUNIT_NPM-NEXT: store i32 [[SUB3]], i32* [[DOTOMP_UB]], align 4 +; IS__TUNIT_NPM-NEXT: store i32 1, i32* [[DOTOMP_STRIDE]], align 4 +; IS__TUNIT_NPM-NEXT: store i32 0, i32* [[DOTOMP_IS_LAST]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP5:%.*]] = load i32, i32* [[DOTGLOBAL_TID_]], align 4 +; IS__TUNIT_NPM-NEXT: call void @__kmpc_for_static_init_4(%struct.ident_t* nonnull align 8 dereferenceable(24) @0, i32 [[TMP5]], i32 34, i32* nonnull align 4 dereferenceable(4) [[DOTOMP_IS_LAST]], i32* nonnull align 4 dereferenceable(4) [[DOTOMP_LB]], i32* nonnull align 4 dereferenceable(4) [[DOTOMP_UB]], i32* nonnull align 4 dereferenceable(4) [[DOTOMP_STRIDE]], i32 1, i32 1) +; IS__TUNIT_NPM-NEXT: [[TMP6:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4 +; IS__TUNIT_NPM-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[TMP6]], [[SUB3]] +; IS__TUNIT_NPM-NEXT: br i1 [[CMP6]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] +; IS__TUNIT_NPM: cond.true: +; IS__TUNIT_NPM-NEXT: br label [[COND_END:%.*]] +; IS__TUNIT_NPM: cond.false: +; IS__TUNIT_NPM-NEXT: [[TMP7:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4 +; IS__TUNIT_NPM-NEXT: br label [[COND_END]] +; IS__TUNIT_NPM: cond.end: +; IS__TUNIT_NPM-NEXT: [[COND:%.*]] = phi i32 [ [[SUB3]], [[COND_TRUE]] ], [ [[TMP7]], [[COND_FALSE]] ] +; IS__TUNIT_NPM-NEXT: store i32 [[COND]], i32* [[DOTOMP_UB]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP8:%.*]] = load i32, i32* [[DOTOMP_LB]], align 4 +; IS__TUNIT_NPM-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] +; IS__TUNIT_NPM: omp.inner.for.cond: +; IS__TUNIT_NPM-NEXT: [[DOTOMP_IV_0:%.*]] = phi i32 [ [[TMP8]], [[COND_END]] ], [ [[ADD11:%.*]], [[OMP_INNER_FOR_INC:%.*]] ] +; IS__TUNIT_NPM-NEXT: [[TMP9:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4 +; IS__TUNIT_NPM-NEXT: [[CMP8:%.*]] = icmp sgt i32 [[DOTOMP_IV_0]], [[TMP9]] +; IS__TUNIT_NPM-NEXT: br i1 [[CMP8]], label [[OMP_INNER_FOR_COND_CLEANUP:%.*]], label [[OMP_INNER_FOR_BODY:%.*]] +; IS__TUNIT_NPM: omp.inner.for.cond.cleanup: +; IS__TUNIT_NPM-NEXT: br label [[OMP_INNER_FOR_END:%.*]] +; IS__TUNIT_NPM: omp.inner.for.body: +; IS__TUNIT_NPM-NEXT: [[ADD10:%.*]] = add nsw i32 [[DOTOMP_IV_0]], 2 +; IS__TUNIT_NPM-NEXT: [[TMP10:%.*]] = load float, float* [[P]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP11:%.*]] = load double, double* [[CONV]], align 8 +; IS__TUNIT_NPM-NEXT: call void @bar(i32 [[ADD10]], float [[TMP10]], double [[TMP11]]) +; IS__TUNIT_NPM-NEXT: br label [[OMP_BODY_CONTINUE:%.*]] +; IS__TUNIT_NPM: omp.body.continue: +; IS__TUNIT_NPM-NEXT: br label [[OMP_INNER_FOR_INC]] +; IS__TUNIT_NPM: omp.inner.for.inc: +; IS__TUNIT_NPM-NEXT: [[ADD11]] = add nsw i32 [[DOTOMP_IV_0]], 1 +; IS__TUNIT_NPM-NEXT: br label [[OMP_INNER_FOR_COND]] +; IS__TUNIT_NPM: omp.inner.for.end: +; IS__TUNIT_NPM-NEXT: br label [[OMP_LOOP_EXIT:%.*]] +; IS__TUNIT_NPM: omp.loop.exit: +; IS__TUNIT_NPM-NEXT: [[TMP12:%.*]] = load i32, i32* [[DOTGLOBAL_TID_]], align 4 +; IS__TUNIT_NPM-NEXT: call void @__kmpc_for_static_fini(%struct.ident_t* nonnull align 8 dereferenceable(24) @0, i32 [[TMP12]]) +; IS__TUNIT_NPM-NEXT: br label [[OMP_PRECOND_END]] +; IS__TUNIT_NPM: omp.precond.end: +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@.omp_outlined. +; IS__CGSCC_NPM-SAME: (i32* noalias nocapture readonly [[DOTGLOBAL_TID_:%.*]], i32* noalias nocapture nofree readnone [[DOTBOUND_TID_:%.*]], i32* nocapture nonnull readonly align 4 dereferenceable(4) [[N:%.*]], float* nocapture nonnull readonly dereferenceable(4) [[P:%.*]], i64 [[Q:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[Q_ADDR:%.*]] = alloca i64, align 8 +; IS__CGSCC_NPM-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4 +; IS__CGSCC_NPM-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4 +; IS__CGSCC_NPM-NEXT: [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4 +; IS__CGSCC_NPM-NEXT: [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4 +; IS__CGSCC_NPM-NEXT: store i64 4617315517961601024, i64* [[Q_ADDR]], align 8 +; IS__CGSCC_NPM-NEXT: [[CONV:%.*]] = bitcast i64* [[Q_ADDR]] to double* +; IS__CGSCC_NPM-NEXT: [[TMP:%.*]] = load i32, i32* [[N]], align 4 +; IS__CGSCC_NPM-NEXT: [[SUB3:%.*]] = add nsw i32 [[TMP]], -3 +; IS__CGSCC_NPM-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP]], 2 +; IS__CGSCC_NPM-NEXT: br i1 [[CMP]], label [[OMP_PRECOND_THEN:%.*]], label [[OMP_PRECOND_END:%.*]] +; IS__CGSCC_NPM: omp.precond.then: +; IS__CGSCC_NPM-NEXT: store i32 0, i32* [[DOTOMP_LB]], align 4 +; IS__CGSCC_NPM-NEXT: store i32 [[SUB3]], i32* [[DOTOMP_UB]], align 4 +; IS__CGSCC_NPM-NEXT: store i32 1, i32* [[DOTOMP_STRIDE]], align 4 +; IS__CGSCC_NPM-NEXT: store i32 0, i32* [[DOTOMP_IS_LAST]], align 4 +; IS__CGSCC_NPM-NEXT: [[TMP5:%.*]] = load i32, i32* [[DOTGLOBAL_TID_]], align 4 +; IS__CGSCC_NPM-NEXT: call void @__kmpc_for_static_init_4(%struct.ident_t* nonnull align 8 dereferenceable(24) @0, i32 [[TMP5]], i32 34, i32* nonnull align 4 dereferenceable(4) [[DOTOMP_IS_LAST]], i32* nonnull align 4 dereferenceable(4) [[DOTOMP_LB]], i32* nonnull align 4 dereferenceable(4) [[DOTOMP_UB]], i32* nonnull align 4 dereferenceable(4) [[DOTOMP_STRIDE]], i32 1, i32 1) +; IS__CGSCC_NPM-NEXT: [[TMP6:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4 +; IS__CGSCC_NPM-NEXT: [[CMP6:%.*]] = icmp sgt i32 [[TMP6]], [[SUB3]] +; IS__CGSCC_NPM-NEXT: br i1 [[CMP6]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] +; IS__CGSCC_NPM: cond.true: +; IS__CGSCC_NPM-NEXT: br label [[COND_END:%.*]] +; IS__CGSCC_NPM: cond.false: +; IS__CGSCC_NPM-NEXT: [[TMP7:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4 +; IS__CGSCC_NPM-NEXT: br label [[COND_END]] +; IS__CGSCC_NPM: cond.end: +; IS__CGSCC_NPM-NEXT: [[COND:%.*]] = phi i32 [ [[SUB3]], [[COND_TRUE]] ], [ [[TMP7]], [[COND_FALSE]] ] +; IS__CGSCC_NPM-NEXT: store i32 [[COND]], i32* [[DOTOMP_UB]], align 4 +; IS__CGSCC_NPM-NEXT: [[TMP8:%.*]] = load i32, i32* [[DOTOMP_LB]], align 4 +; IS__CGSCC_NPM-NEXT: br label [[OMP_INNER_FOR_COND:%.*]] +; IS__CGSCC_NPM: omp.inner.for.cond: +; IS__CGSCC_NPM-NEXT: [[DOTOMP_IV_0:%.*]] = phi i32 [ [[TMP8]], [[COND_END]] ], [ [[ADD11:%.*]], [[OMP_INNER_FOR_INC:%.*]] ] +; IS__CGSCC_NPM-NEXT: [[TMP9:%.*]] = load i32, i32* [[DOTOMP_UB]], align 4 +; IS__CGSCC_NPM-NEXT: [[CMP8:%.*]] = icmp sgt i32 [[DOTOMP_IV_0]], [[TMP9]] +; IS__CGSCC_NPM-NEXT: br i1 [[CMP8]], label [[OMP_INNER_FOR_COND_CLEANUP:%.*]], label [[OMP_INNER_FOR_BODY:%.*]] +; IS__CGSCC_NPM: omp.inner.for.cond.cleanup: +; IS__CGSCC_NPM-NEXT: br label [[OMP_INNER_FOR_END:%.*]] +; IS__CGSCC_NPM: omp.inner.for.body: +; IS__CGSCC_NPM-NEXT: [[ADD10:%.*]] = add nsw i32 [[DOTOMP_IV_0]], 2 +; IS__CGSCC_NPM-NEXT: [[TMP10:%.*]] = load float, float* [[P]], align 4 +; IS__CGSCC_NPM-NEXT: [[TMP11:%.*]] = load double, double* [[CONV]], align 8 +; IS__CGSCC_NPM-NEXT: call void @bar(i32 [[ADD10]], float [[TMP10]], double [[TMP11]]) +; IS__CGSCC_NPM-NEXT: br label [[OMP_BODY_CONTINUE:%.*]] +; IS__CGSCC_NPM: omp.body.continue: +; IS__CGSCC_NPM-NEXT: br label [[OMP_INNER_FOR_INC]] +; IS__CGSCC_NPM: omp.inner.for.inc: +; IS__CGSCC_NPM-NEXT: [[ADD11]] = add nsw i32 [[DOTOMP_IV_0]], 1 +; IS__CGSCC_NPM-NEXT: br label [[OMP_INNER_FOR_COND]] +; IS__CGSCC_NPM: omp.inner.for.end: +; IS__CGSCC_NPM-NEXT: br label [[OMP_LOOP_EXIT:%.*]] +; IS__CGSCC_NPM: omp.loop.exit: +; IS__CGSCC_NPM-NEXT: [[TMP12:%.*]] = load i32, i32* [[DOTGLOBAL_TID_]], align 4 +; IS__CGSCC_NPM-NEXT: call void @__kmpc_for_static_fini(%struct.ident_t* nonnull align 8 dereferenceable(24) @0, i32 [[TMP12]]) +; IS__CGSCC_NPM-NEXT: br label [[OMP_PRECOND_END]] +; IS__CGSCC_NPM: omp.precond.end: +; IS__CGSCC_NPM-NEXT: ret void +; entry: %q.addr = alloca i64, align 8 %.omp.lb = alloca i32, align 4 %.omp.ub = alloca i32, align 4 %.omp.stride = alloca i32, align 4 %.omp.is_last = alloca i32, align 4 -; CHECK: store i64 4617315517961601024, i64* %q.addr, align 8 store i64 %q, i64* %q.addr, align 8 %conv = bitcast i64* %q.addr to double* %tmp = load i32, i32* %N, align 4 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,6 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s --check-prefixes=CHECK,MODULE -; RUN: opt -S -passes=attributor-cgscc -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s --check-prefixes=CHECK,CGSCC +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; ; #include ; @@ -29,27 +31,38 @@ ; FIXME: nocapture & noalias for %alloc2 in %call3 define dso_local i32 @main() { -; MODULE-LABEL: define {{[^@]+}}@main() -; MODULE-NEXT: entry: -; MODULE-NEXT: [[ALLOC1:%.*]] = alloca i8, align 8 -; MODULE-NEXT: [[ALLOC2:%.*]] = alloca i8, align 8 -; MODULE-NEXT: [[THREAD:%.*]] = alloca i64, align 8 -; MODULE-NEXT: [[CALL:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @foo, i8* noalias nofree readnone align 536870912 undef) -; MODULE-NEXT: [[CALL1:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @bar, i8* noalias nofree nonnull readnone align 8 dereferenceable(8) undef) -; MODULE-NEXT: [[CALL2:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @baz, i8* noalias nocapture nofree nonnull readnone align 8 dereferenceable(1) [[ALLOC1]]) -; MODULE-NEXT: [[CALL3:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @buz, i8* noalias nofree nonnull readnone align 8 dereferenceable(1) [[ALLOC2]]) -; MODULE-NEXT: ret i32 0 -; -; CGSCC-LABEL: define {{[^@]+}}@main() -; CGSCC-NEXT: entry: -; CGSCC-NEXT: [[ALLOC1:%.*]] = alloca i8, align 8 -; CGSCC-NEXT: [[ALLOC2:%.*]] = alloca i8, align 8 -; CGSCC-NEXT: [[THREAD:%.*]] = alloca i64, align 8 -; CGSCC-NEXT: [[CALL:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @foo, i8* noalias nofree readnone align 536870912 null) -; CGSCC-NEXT: [[CALL1:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @bar, i8* noalias nofree nonnull readnone align 8 dereferenceable(8) bitcast (i8** @GlobalVPtr to i8*)) -; CGSCC-NEXT: [[CALL2:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @baz, i8* noalias nocapture nofree nonnull readnone align 8 dereferenceable(1) [[ALLOC1]]) -; CGSCC-NEXT: [[CALL3:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @buz, i8* noalias nofree nonnull readnone align 8 dereferenceable(1) [[ALLOC2]]) -; CGSCC-NEXT: ret i32 0 +; IS__TUNIT____-LABEL: define {{[^@]+}}@main() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[ALLOC1:%.*]] = alloca i8, align 8 +; IS__TUNIT____-NEXT: [[ALLOC2:%.*]] = alloca i8, align 8 +; IS__TUNIT____-NEXT: [[THREAD:%.*]] = alloca i64, align 8 +; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @foo, i8* noalias nofree readnone align 536870912 undef) +; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @bar, i8* noalias nofree nonnull readnone align 8 dereferenceable(8) undef) +; IS__TUNIT____-NEXT: [[CALL2:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @baz, i8* noalias nocapture nofree nonnull readnone align 8 dereferenceable(1) [[ALLOC1]]) +; IS__TUNIT____-NEXT: [[CALL3:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @buz, i8* noalias nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" [[ALLOC2]]) +; IS__TUNIT____-NEXT: ret i32 0 +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@main() +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[ALLOC1:%.*]] = alloca i8, align 8 +; IS__CGSCC_OPM-NEXT: [[ALLOC2:%.*]] = alloca i8, align 8 +; IS__CGSCC_OPM-NEXT: [[THREAD:%.*]] = alloca i64, align 8 +; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @foo, i8* noalias align 536870912 null) +; IS__CGSCC_OPM-NEXT: [[CALL1:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @bar, i8* nonnull align 8 dereferenceable(8) bitcast (i8** @GlobalVPtr to i8*)) +; IS__CGSCC_OPM-NEXT: [[CALL2:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @baz, i8* nocapture nonnull align 8 dereferenceable(1) [[ALLOC1]]) +; IS__CGSCC_OPM-NEXT: [[CALL3:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @buz, i8* nonnull align 8 dereferenceable(1) [[ALLOC2]]) +; IS__CGSCC_OPM-NEXT: ret i32 0 +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@main() +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[ALLOC1:%.*]] = alloca i8, align 8 +; IS__CGSCC_NPM-NEXT: [[ALLOC2:%.*]] = alloca i8, align 8 +; IS__CGSCC_NPM-NEXT: [[THREAD:%.*]] = alloca i64, align 8 +; IS__CGSCC_NPM-NEXT: [[CALL:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @foo, i8* noalias nofree readnone align 536870912 null) +; IS__CGSCC_NPM-NEXT: [[CALL1:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @bar, i8* noalias nofree nonnull readnone align 8 dereferenceable(8) bitcast (i8** @GlobalVPtr to i8*)) +; IS__CGSCC_NPM-NEXT: [[CALL2:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @baz, i8* noalias nocapture nofree nonnull readnone align 8 dereferenceable(1) [[ALLOC1]]) +; IS__CGSCC_NPM-NEXT: [[CALL3:%.*]] = call i32 @pthread_create(i64* nonnull align 8 dereferenceable(8) [[THREAD]], %union.pthread_attr_t* noalias align 536870912 null, i8* (i8*)* nonnull @buz, i8* noalias nofree nonnull readnone align 8 dereferenceable(1) [[ALLOC2]]) +; IS__CGSCC_NPM-NEXT: ret i32 0 ; entry: %alloc1 = alloca i8, align 8 @@ -65,60 +78,75 @@ declare !callback !0 dso_local i32 @pthread_create(i64*, %union.pthread_attr_t*, i8* (i8*)*, i8*) define internal i8* @foo(i8* %arg) { -; MODULE-LABEL: define {{[^@]+}}@foo -; MODULE-SAME: (i8* noalias nofree readnone returned align 536870912 [[ARG:%.*]]) -; MODULE-NEXT: entry: -; MODULE-NEXT: ret i8* null +; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@foo +; NOT_CGSCC_NPM-SAME: (i8* noalias nofree readnone returned align 536870912 "no-capture-maybe-returned" [[ARG:%.*]]) +; NOT_CGSCC_NPM-NEXT: entry: +; NOT_CGSCC_NPM-NEXT: ret i8* null ; -; CGSCC-LABEL: define {{[^@]+}}@foo -; CGSCC-SAME: (i8* noalias nofree readnone returned [[ARG:%.*]]) -; CGSCC-NEXT: entry: -; CGSCC-NEXT: ret i8* null +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@foo +; IS__CGSCC_NPM-SAME: (i8* noalias nofree readnone returned "no-capture-maybe-returned" [[ARG:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: ret i8* null ; entry: ret i8* %arg } define internal i8* @bar(i8* %arg) { -; MODULE-LABEL: define {{[^@]+}}@bar -; MODULE-SAME: (i8* noalias nofree nonnull readnone returned align 8 dereferenceable(8) [[ARG:%.*]]) -; MODULE-NEXT: entry: -; MODULE-NEXT: ret i8* bitcast (i8** @GlobalVPtr to i8*) +; 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*) ; -; CGSCC-LABEL: define {{[^@]+}}@bar -; CGSCC-SAME: (i8* nofree readnone returned [[ARG:%.*]]) -; CGSCC-NEXT: entry: -; CGSCC-NEXT: ret i8* bitcast (i8** @GlobalVPtr to i8*) +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@bar +; IS__CGSCC_OPM-SAME: (i8* nofree nonnull readnone returned align 8 dereferenceable(8) "no-capture-maybe-returned" [[ARG:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: ret i8* bitcast (i8** @GlobalVPtr to i8*) +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@bar +; IS__CGSCC_NPM-SAME: (i8* nofree readnone returned "no-capture-maybe-returned" [[ARG:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: ret i8* bitcast (i8** @GlobalVPtr to i8*) ; entry: ret i8* %arg } define internal i8* @baz(i8* %arg) { -; MODULE-LABEL: define {{[^@]+}}@baz -; MODULE-SAME: (i8* noalias nofree nonnull readnone returned align 8 dereferenceable(1) [[ARG:%.*]]) -; MODULE-NEXT: entry: -; MODULE-NEXT: ret i8* [[ARG]] +; 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_OPM-LABEL: define {{[^@]+}}@baz +; IS__CGSCC_OPM-SAME: (i8* nofree nonnull readnone returned align 8 dereferenceable(1) "no-capture-maybe-returned" [[ARG:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: ret i8* [[ARG]] ; -; CGSCC-LABEL: define {{[^@]+}}@baz -; CGSCC-SAME: (i8* nofree readnone returned [[ARG:%.*]]) -; CGSCC-NEXT: entry: -; CGSCC-NEXT: ret i8* [[ARG]] +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@baz +; IS__CGSCC_NPM-SAME: (i8* nofree readnone returned "no-capture-maybe-returned" [[ARG:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: ret i8* [[ARG]] ; entry: ret i8* %arg } define internal i8* @buz(i8* %arg) { -; MODULE-LABEL: define {{[^@]+}}@buz -; MODULE-SAME: (i8* noalias nofree nonnull readnone returned align 8 dereferenceable(1) [[ARG:%.*]]) -; MODULE-NEXT: entry: -; MODULE-NEXT: ret i8* [[ARG]] -; -; CGSCC-LABEL: define {{[^@]+}}@buz -; CGSCC-SAME: (i8* nofree readnone returned [[ARG:%.*]]) -; CGSCC-NEXT: entry: -; CGSCC-NEXT: ret i8* [[ARG]] +; 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_OPM-LABEL: define {{[^@]+}}@buz +; IS__CGSCC_OPM-SAME: (i8* nofree nonnull readnone returned align 8 dereferenceable(1) "no-capture-maybe-returned" [[ARG:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: ret i8* [[ARG]] +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@buz +; IS__CGSCC_NPM-SAME: (i8* nofree readnone returned "no-capture-maybe-returned" [[ARG:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: ret i8* [[ARG]] ; entry: ret i8* %arg 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,9 +1,15 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; CHECK-NOT: %X define internal i32 @foo(i32 %X) { +; IS__CGSCC____-LABEL: define {{[^@]+}}@foo() +; IS__CGSCC____-NEXT: unreachable +; %Y = call i32 @foo( i32 %X ) ; [#uses=1] %Z = add i32 %Y, 1 ; [#uses=1] ret i32 %Z 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; PR5596 ; IPSCCP should propagate the 0 argument, eliminate the switch, and propagate @@ -18,6 +21,17 @@ } define internal i32 @wwrite(i64 %i) nounwind readnone { +; IS__CGSCC____-LABEL: define {{[^@]+}}@wwrite() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: switch i64 0, label [[SW_DEFAULT:%.*]] [ +; IS__CGSCC____-NEXT: i64 3, label [[RETURN:%.*]] +; IS__CGSCC____-NEXT: i64 10, label [[RETURN]] +; IS__CGSCC____-NEXT: ] +; IS__CGSCC____: sw.default: +; IS__CGSCC____-NEXT: ret i32 123 +; IS__CGSCC____: return: +; IS__CGSCC____-NEXT: unreachable +; entry: switch i64 %i, label %sw.default [ i64 3, label %return 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,20 +1,36 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=8 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ;; This function returns its second argument on all return statements define internal i32* @incdec(i1 %C, i32* %V) { -; CHECK-LABEL: define {{[^@]+}}@incdec -; CHECK-SAME: (i1 [[C:%.*]], i32* noalias nofree nonnull returned align 4 dereferenceable(4) [[V:%.*]]) -; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[V]], align 4 -; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] -; CHECK: T: -; CHECK-NEXT: [[X1:%.*]] = add i32 [[X]], 1 -; CHECK-NEXT: store i32 [[X1]], i32* [[V]], align 4 -; CHECK-NEXT: ret i32* [[V]] -; CHECK: F: -; CHECK-NEXT: [[X2:%.*]] = sub i32 [[X]], 1 -; CHECK-NEXT: store i32 [[X2]], i32* [[V]], align 4 -; CHECK-NEXT: ret i32* [[V]] +; 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 +; IS__TUNIT____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] +; IS__TUNIT____: T: +; IS__TUNIT____-NEXT: [[X1:%.*]] = add i32 [[X]], 1 +; IS__TUNIT____-NEXT: store i32 [[X1]], i32* [[V]], align 4 +; IS__TUNIT____-NEXT: ret i32* [[V]] +; IS__TUNIT____: F: +; IS__TUNIT____-NEXT: [[X2:%.*]] = sub i32 [[X]], 1 +; IS__TUNIT____-NEXT: store i32 [[X2]], i32* [[V]], align 4 +; IS__TUNIT____-NEXT: ret i32* [[V]] +; +; 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 +; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] +; IS__CGSCC____: T: +; IS__CGSCC____-NEXT: [[X1:%.*]] = add i32 [[X]], 1 +; IS__CGSCC____-NEXT: store i32 [[X1]], i32* [[V]], align 4 +; IS__CGSCC____-NEXT: ret i32* [[V]] +; IS__CGSCC____: F: +; IS__CGSCC____-NEXT: [[X2:%.*]] = sub i32 [[X]], 1 +; IS__CGSCC____-NEXT: store i32 [[X2]], i32* [[V]], align 4 +; IS__CGSCC____-NEXT: ret i32* [[V]] ; %X = load i32, i32* %V br i1 %C, label %T, label %F @@ -47,25 +63,43 @@ } define void @caller(i1 %C) personality i32 (...)* @__gxx_personality_v0 { -; CHECK-LABEL: define {{[^@]+}}@caller -; CHECK-SAME: (i1 [[C:%.*]]) #2 personality i32 (...)* @__gxx_personality_v0 -; CHECK-NEXT: [[Q:%.*]] = alloca i32 -; CHECK-NEXT: [[W:%.*]] = call align 4 i32* @incdec(i1 [[C]], i32* noalias nofree nonnull align 4 dereferenceable(4) [[Q]]) -; CHECK-NEXT: [[S1:%.*]] = call { i32, i32 } @foo(i32 1, i32 2) -; CHECK-NEXT: [[X1:%.*]] = extractvalue { i32, i32 } [[S1]], 0 -; CHECK-NEXT: [[S2:%.*]] = invoke { i32, i32 } @foo(i32 3, i32 4) -; CHECK-NEXT: to label [[OK:%.*]] unwind label [[LPAD:%.*]] -; CHECK: OK: -; CHECK-NEXT: [[X2:%.*]] = extractvalue { i32, i32 } [[S2]], 0 -; CHECK-NEXT: [[Z:%.*]] = add i32 [[X1]], [[X2]] -; CHECK-NEXT: store i32 [[Z]], i32* [[W]], align 4 -; CHECK-NEXT: br label [[RET:%.*]] -; CHECK: LPAD: -; CHECK-NEXT: [[EXN:%.*]] = landingpad { i8*, i32 } -; CHECK-NEXT: cleanup -; CHECK-NEXT: br label [[RET]] -; CHECK: RET: -; CHECK-NEXT: ret void +; IS__TUNIT____-LABEL: define {{[^@]+}}@caller +; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #2 personality i32 (...)* @__gxx_personality_v0 +; IS__TUNIT____-NEXT: [[Q:%.*]] = alloca i32 +; IS__TUNIT____-NEXT: [[W:%.*]] = call align 4 i32* @incdec(i1 [[C]], i32* noalias nofree nonnull align 4 dereferenceable(4) "no-capture-maybe-returned" [[Q]]) +; IS__TUNIT____-NEXT: [[S1:%.*]] = call { i32, i32 } @foo(i32 1, i32 2) +; IS__TUNIT____-NEXT: [[X1:%.*]] = extractvalue { i32, i32 } [[S1]], 0 +; IS__TUNIT____-NEXT: [[S2:%.*]] = invoke { i32, i32 } @foo(i32 3, i32 4) +; IS__TUNIT____-NEXT: to label [[OK:%.*]] unwind label [[LPAD:%.*]] +; IS__TUNIT____: OK: +; IS__TUNIT____-NEXT: [[X2:%.*]] = extractvalue { i32, i32 } [[S2]], 0 +; IS__TUNIT____-NEXT: [[Z:%.*]] = add i32 [[X1]], [[X2]] +; IS__TUNIT____-NEXT: store i32 [[Z]], i32* [[W]], align 4 +; IS__TUNIT____-NEXT: br label [[RET:%.*]] +; IS__TUNIT____: LPAD: +; IS__TUNIT____-NEXT: [[EXN:%.*]] = landingpad { i8*, i32 } +; IS__TUNIT____-NEXT: cleanup +; IS__TUNIT____-NEXT: br label [[RET]] +; IS__TUNIT____: RET: +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@caller +; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #1 personality i32 (...)* @__gxx_personality_v0 +; IS__CGSCC____-NEXT: [[Q:%.*]] = alloca i32 +; IS__CGSCC____-NEXT: [[W:%.*]] = call align 4 i32* @incdec(i1 [[C]], i32* noalias nofree nonnull align 4 dereferenceable(4) [[Q]]) +; IS__CGSCC____-NEXT: [[S1:%.*]] = call { i32, i32 } @foo(i32 1, i32 2) +; IS__CGSCC____-NEXT: [[X1:%.*]] = extractvalue { i32, i32 } [[S1]], 0 +; IS__CGSCC____-NEXT: [[S2:%.*]] = call { i32, i32 } @foo(i32 3, i32 4) +; IS__CGSCC____-NEXT: br label [[OK:%.*]] +; IS__CGSCC____: OK: +; IS__CGSCC____-NEXT: [[X2:%.*]] = extractvalue { i32, i32 } [[S2]], 0 +; IS__CGSCC____-NEXT: [[Z:%.*]] = add i32 [[X1]], [[X2]] +; IS__CGSCC____-NEXT: store i32 [[Z]], i32* [[W]], align 4 +; IS__CGSCC____-NEXT: br label [[RET:%.*]] +; IS__CGSCC____: LPAD: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: RET: +; IS__CGSCC____-NEXT: ret void ; %Q = alloca i32 ;; Call incdec to see if %W is properly replaced by %Q 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; FIXME: icmp folding is missing @@ -24,13 +27,21 @@ } define internal i32 @foo(i1 %C) { -; CHECK-LABEL: define {{[^@]+}}@foo -; CHECK-SAME: (i1 [[C:%.*]]) -; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] -; CHECK: T: -; CHECK-NEXT: ret i32 undef -; CHECK: F: -; CHECK-NEXT: ret i32 undef +; IS__TUNIT____-LABEL: define {{[^@]+}}@foo +; IS__TUNIT____-SAME: (i1 [[C:%.*]]) +; IS__TUNIT____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] +; IS__TUNIT____: T: +; IS__TUNIT____-NEXT: ret i32 undef +; IS__TUNIT____: F: +; IS__TUNIT____-NEXT: ret i32 undef +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@foo +; IS__CGSCC____-SAME: (i1 [[C:%.*]]) +; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] +; IS__CGSCC____: T: +; IS__CGSCC____-NEXT: ret i32 52 +; IS__CGSCC____: F: +; IS__CGSCC____-NEXT: ret i32 52 ; br i1 %C, label %T, label %F 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=7 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ;; FIXME: support for extractvalue and insertvalue missing. 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,7 +1,21 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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____-LABEL: define {{[^@]+}}@testf +; IS__CGSCC____-SAME: (i1 [[C:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br i1 [[C]], label [[IF_COND:%.*]], label [[IF_END:%.*]] +; IS__CGSCC____: if.cond: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: if.then: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: if.end: +; IS__CGSCC____-NEXT: ret i32 10 +; entry: br i1 %c, label %if.cond, label %if.end @@ -16,6 +30,17 @@ } define internal i32 @test1(i1 %c) { +; IS__CGSCC____-LABEL: define {{[^@]+}}@test1 +; IS__CGSCC____-SAME: (i1 [[C:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br label [[IF_THEN:%.*]] +; IS__CGSCC____: if.then: +; IS__CGSCC____-NEXT: br label [[RET1:%.*]] +; IS__CGSCC____: ret1: +; IS__CGSCC____-NEXT: ret i32 99 +; IS__CGSCC____: ret2: +; IS__CGSCC____-NEXT: unreachable +; entry: br label %if.then 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,5 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; ; #include ; thread_local int gtl = 0; @@ -37,10 +40,15 @@ } define dso_local void @caller() { -; CHECK-LABEL: define {{[^@]+}}@caller() -; CHECK-NEXT: entry: -; CHECK-NEXT: call void @broker(i32* nofree nonnull readonly align 4 dereferenceable(4) @gtl, i32 (i32*, i32*)* nonnull @callee, i32* nofree nonnull readonly align 4 dereferenceable(4) undef) -; CHECK-NEXT: ret void +; IS__TUNIT____-LABEL: define {{[^@]+}}@caller() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: call void @broker(i32* nofree nonnull readonly align 4 dereferenceable(4) @gtl, i32 (i32*, i32*)* nonnull @callee, i32* nofree nonnull readonly align 4 dereferenceable(4) undef) +; IS__TUNIT____-NEXT: ret void +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@caller() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: call void @broker(i32* nofree nonnull readonly align 4 dereferenceable(4) @gtl, i32 (i32*, i32*)* nonnull @callee, i32* nofree nonnull readonly align 4 dereferenceable(4) @gsh) +; IS__CGSCC____-NEXT: ret void ; entry: call void @broker(i32* nonnull @gtl, i32 (i32*, i32*)* nonnull @callee, i32* nonnull @gsh) 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,8 +1,8 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --disable --function-signature --scrub-attributes -; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,ATTRIBUTOR_MODULE -; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-disable=false -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,ATTRIBUTOR_CGSCC -; RUN: opt -passes=attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,ATTRIBUTOR_MODULE -; RUN: opt -passes=attributor-cgscc -attributor-manifest-internal -attributor-disable=false -attributor-annotate-decl-cs -attributor-max-iterations=6 -S < %s | FileCheck %s --check-prefixes=ATTRIBUTOR,ATTRIBUTOR_CGSCC +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" @@ -11,27 +11,41 @@ ; TEST 1 -; ATTRIBUTOR: define align 8 i32* @test1(i32* nofree readnone returned align 8 "no-capture-maybe-returned" %0) 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]] +; ret i32* %0 } ; TEST 2 -; ATTRIBUTOR: define i32* @test2(i32* nofree readnone returned "no-capture-maybe-returned" %0) 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]] +; ret i32* %0 } ; TEST 3 -; ATTRIBUTOR: define align 4 i32* @test3(i32* nofree readnone align 8 "no-capture-maybe-returned" %0, i32* nofree readnone align 4 "no-capture-maybe-returned" %1, i1 %2) 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]] +; %ret = select i1 %2, i32* %0, i32* %1 ret i32* %ret } ; TEST 4 -; ATTRIBUTOR: define align 32 i32* @test4(i32* nofree readnone align 32 "no-capture-maybe-returned" %0, i32* nofree readnone align 32 "no-capture-maybe-returned" %1, i1 %2) 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]] +; %ret = select i1 %2, i32* %0, i32* %1 ret i32* %ret } @@ -41,28 +55,38 @@ declare align 8 i32* @align8() -; ATTRIBUTOR: define align 8 i32* @test5_1() define i32* @test5_1() { +; CHECK-LABEL: define {{[^@]+}}@test5_1() +; CHECK-NEXT: [[RET:%.*]] = tail call align 8 i32* @unknown() +; CHECK-NEXT: ret i32* [[RET]] +; %ret = tail call align 8 i32* @unknown() ret i32* %ret } -; ATTRIBUTOR: define align 8 i32* @test5_2() define i32* @test5_2() { +; CHECK-LABEL: define {{[^@]+}}@test5_2() +; CHECK-NEXT: [[RET:%.*]] = tail call align 8 i32* @align8() +; CHECK-NEXT: ret i32* [[RET]] +; %ret = tail call i32* @align8() ret i32* %ret } ; TEST 6 ; SCC -; ATTRIBUTOR: define noalias nonnull align 536870912 dereferenceable(4294967295) i32* @test6_1() define i32* @test6_1() #0 { +; CHECK-LABEL: define {{[^@]+}}@test6_1() +; CHECK-NEXT: unreachable +; %ret = tail call i32* @test6_2() ret i32* %ret } -; ATTRIBUTOR: define noalias nonnull align 536870912 dereferenceable(4294967295) i32* @test6_2() define i32* @test6_2() #0 { +; CHECK-LABEL: define {{[^@]+}}@test6_2() +; CHECK-NEXT: unreachable +; %ret = tail call i32* @test6_1() ret i32* %ret } @@ -87,6 +111,28 @@ ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f1(i8* readnone %0) local_unnamed_addr #0 { +; 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 +; IS__TUNIT____-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] +; IS__TUNIT____: 3: +; IS__TUNIT____-NEXT: [[TMP4:%.*]] = tail call align 8 i8* @f2() +; IS__TUNIT____-NEXT: br label [[TMP5]] +; IS__TUNIT____: 5: +; IS__TUNIT____-NEXT: [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] +; IS__TUNIT____-NEXT: ret i8* [[TMP6]] +; +; 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 +; IS__CGSCC____-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] +; IS__CGSCC____: 3: +; IS__CGSCC____-NEXT: [[TMP4:%.*]] = tail call align 8 i8* @f2() +; IS__CGSCC____-NEXT: br label [[TMP5]] +; IS__CGSCC____: 5: +; IS__CGSCC____-NEXT: [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] +; IS__CGSCC____-NEXT: ret i8* [[TMP6]] +; %2 = icmp eq i8* %0, null br i1 %2, label %3, label %5 @@ -102,6 +148,19 @@ ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f2(i8* readnone %0) local_unnamed_addr #0 { +; CHECK-LABEL: define {{[^@]+}}@f2() local_unnamed_addr +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8* @a1, null +; CHECK-NEXT: br i1 [[TMP1]], label [[TMP4:%.*]], label [[TMP2:%.*]] +; CHECK: 2: +; CHECK-NEXT: [[TMP3:%.*]] = tail call i8* @f1(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" @a1) +; CHECK-NEXT: br label [[TMP6:%.*]] +; CHECK: 4: +; CHECK-NEXT: [[TMP5:%.*]] = tail call i8* @f3() +; CHECK-NEXT: br label [[TMP6]] +; CHECK: 6: +; CHECK-NEXT: [[TMP7:%.*]] = phi i8* [ [[TMP3]], [[TMP2]] ], [ [[TMP5]], [[TMP4]] ] +; CHECK-NEXT: ret i8* [[TMP7]] +; %2 = icmp eq i8* %0, null br i1 %2, label %5, label %3 @@ -121,6 +180,16 @@ ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f3(i8* readnone %0) local_unnamed_addr #0 { +; CHECK-LABEL: define {{[^@]+}}@f3() local_unnamed_addr +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8* @a2, null +; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP4:%.*]] +; CHECK: 2: +; CHECK-NEXT: [[TMP3:%.*]] = tail call i8* @f1(i8* noalias nofree nonnull readnone align 16 dereferenceable(1) @a2) +; CHECK-NEXT: br label [[TMP4]] +; CHECK: 4: +; CHECK-NEXT: [[TMP5:%.*]] = phi i8* [ [[TMP3]], [[TMP2]] ], [ @a1, [[TMP0:%.*]] ] +; CHECK-NEXT: ret i8* [[TMP5]] +; %2 = icmp eq i8* %0, null br i1 %2, label %3, label %5 @@ -133,18 +202,16 @@ ret i8* %6 } -; UTC_ARGS: --enable - ; TEST 7 ; Better than IR information define align 4 i8* @test7() #0 { -; ATTRIBUTOR_MODULE-LABEL: define {{[^@]+}}@test7() -; ATTRIBUTOR_MODULE-NEXT: [[C:%.*]] = tail call i8* @f1(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) @a1) -; ATTRIBUTOR_MODULE-NEXT: ret i8* [[C]] +; IS__TUNIT____-LABEL: define {{[^@]+}}@test7() +; IS__TUNIT____-NEXT: [[C:%.*]] = tail call i8* @f1(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) @a1) +; IS__TUNIT____-NEXT: ret i8* [[C]] ; -; ATTRIBUTOR_CGSCC-LABEL: define {{[^@]+}}@test7() -; ATTRIBUTOR_CGSCC-NEXT: [[C:%.*]] = tail call nonnull align 8 dereferenceable(1) i8* @f1(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) @a1) -; ATTRIBUTOR_CGSCC-NEXT: ret i8* [[C]] +; 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]] ; %c = tail call i8* @f1(i8* align 8 dereferenceable(1) @a1) ret i8* %c @@ -153,31 +220,31 @@ ; TEST 7b ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f1b(i8* readnone %0) local_unnamed_addr #0 { -; ATTRIBUTOR_MODULE-LABEL: define {{[^@]+}}@f1b -; ATTRIBUTOR_MODULE-SAME: (i8* noalias nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr -; ATTRIBUTOR_MODULE-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null -; ATTRIBUTOR_MODULE-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] -; ATTRIBUTOR_MODULE: 3: -; ATTRIBUTOR_MODULE-NEXT: [[TMP4:%.*]] = tail call align 8 i8* @f2b() -; ATTRIBUTOR_MODULE-NEXT: [[L:%.*]] = load i8, i8* [[TMP4]], align 8 -; ATTRIBUTOR_MODULE-NEXT: store i8 [[L]], i8* @a1, align 8 -; ATTRIBUTOR_MODULE-NEXT: br label [[TMP5]] -; ATTRIBUTOR_MODULE: 5: -; ATTRIBUTOR_MODULE-NEXT: [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] -; ATTRIBUTOR_MODULE-NEXT: ret i8* [[TMP6]] -; -; ATTRIBUTOR_CGSCC-LABEL: define {{[^@]+}}@f1b -; ATTRIBUTOR_CGSCC-SAME: (i8* nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" [[TMP0:%.*]]) local_unnamed_addr -; ATTRIBUTOR_CGSCC-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null -; ATTRIBUTOR_CGSCC-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] -; ATTRIBUTOR_CGSCC: 3: -; ATTRIBUTOR_CGSCC-NEXT: [[TMP4:%.*]] = tail call align 8 i8* @f2b() -; ATTRIBUTOR_CGSCC-NEXT: [[L:%.*]] = load i8, i8* [[TMP4]], align 8 -; ATTRIBUTOR_CGSCC-NEXT: store i8 [[L]], i8* @a1, align 8 -; ATTRIBUTOR_CGSCC-NEXT: br label [[TMP5]] -; ATTRIBUTOR_CGSCC: 5: -; ATTRIBUTOR_CGSCC-NEXT: [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] -; ATTRIBUTOR_CGSCC-NEXT: ret i8* [[TMP6]] +; 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 +; IS__TUNIT____-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] +; IS__TUNIT____: 3: +; IS__TUNIT____-NEXT: [[TMP4:%.*]] = tail call align 8 i8* @f2b() +; IS__TUNIT____-NEXT: [[L:%.*]] = load i8, i8* [[TMP4]], align 8 +; IS__TUNIT____-NEXT: store i8 [[L]], i8* @a1, align 8 +; IS__TUNIT____-NEXT: br label [[TMP5]] +; IS__TUNIT____: 5: +; IS__TUNIT____-NEXT: [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] +; IS__TUNIT____-NEXT: ret i8* [[TMP6]] +; +; 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 +; IS__CGSCC____-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] +; IS__CGSCC____: 3: +; IS__CGSCC____-NEXT: [[TMP4:%.*]] = tail call align 8 i8* @f2b() +; IS__CGSCC____-NEXT: [[L:%.*]] = load i8, i8* [[TMP4]], align 8 +; IS__CGSCC____-NEXT: store i8 [[L]], i8* @a1, align 8 +; IS__CGSCC____-NEXT: br label [[TMP5]] +; IS__CGSCC____: 5: +; IS__CGSCC____-NEXT: [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] +; IS__CGSCC____-NEXT: ret i8* [[TMP6]] ; %2 = icmp eq i8* %0, null br i1 %2, label %3, label %5 @@ -196,18 +263,18 @@ ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f2b(i8* readnone %0) local_unnamed_addr #0 { ; -; ATTRIBUTOR-LABEL: define {{[^@]+}}@f2b() local_unnamed_addr -; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = icmp eq i8* @a1, null -; ATTRIBUTOR-NEXT: br i1 [[TMP1]], label [[TMP4:%.*]], label [[TMP2:%.*]] -; ATTRIBUTOR: 2: -; ATTRIBUTOR-NEXT: [[TMP3:%.*]] = tail call i8* @f1b(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" @a1) -; ATTRIBUTOR-NEXT: br label [[TMP6:%.*]] -; ATTRIBUTOR: 4: -; ATTRIBUTOR-NEXT: [[TMP5:%.*]] = tail call i8* @f3b() -; ATTRIBUTOR-NEXT: br label [[TMP6]] -; ATTRIBUTOR: 6: -; ATTRIBUTOR-NEXT: [[TMP7:%.*]] = phi i8* [ [[TMP3]], [[TMP2]] ], [ [[TMP5]], [[TMP4]] ] -; ATTRIBUTOR-NEXT: ret i8* [[TMP7]] +; CHECK-LABEL: define {{[^@]+}}@f2b() local_unnamed_addr +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8* @a1, null +; CHECK-NEXT: br i1 [[TMP1]], label [[TMP4:%.*]], label [[TMP2:%.*]] +; CHECK: 2: +; CHECK-NEXT: [[TMP3:%.*]] = tail call i8* @f1b(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) "no-capture-maybe-returned" @a1) +; CHECK-NEXT: br label [[TMP6:%.*]] +; CHECK: 4: +; CHECK-NEXT: [[TMP5:%.*]] = tail call i8* @f3b() +; CHECK-NEXT: br label [[TMP6]] +; CHECK: 6: +; CHECK-NEXT: [[TMP7:%.*]] = phi i8* [ [[TMP3]], [[TMP2]] ], [ [[TMP5]], [[TMP4]] ] +; CHECK-NEXT: ret i8* [[TMP7]] ; %2 = icmp eq i8* %0, null br i1 %2, label %5, label %3 @@ -229,15 +296,15 @@ ; Function Attrs: nounwind readnone ssp uwtable define internal i8* @f3b(i8* readnone %0) local_unnamed_addr #0 { ; -; ATTRIBUTOR-LABEL: define {{[^@]+}}@f3b() local_unnamed_addr -; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = icmp eq i8* @a2, null -; ATTRIBUTOR-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP4:%.*]] -; ATTRIBUTOR: 2: -; ATTRIBUTOR-NEXT: [[TMP3:%.*]] = tail call i8* @f1b(i8* noalias nofree nonnull readnone align 16 dereferenceable(1) @a2) -; ATTRIBUTOR-NEXT: br label [[TMP4]] -; ATTRIBUTOR: 4: -; ATTRIBUTOR-NEXT: [[TMP5:%.*]] = phi i8* [ [[TMP3]], [[TMP2]] ], [ @a1, [[TMP0:%.*]] ] -; ATTRIBUTOR-NEXT: ret i8* [[TMP5]] +; CHECK-LABEL: define {{[^@]+}}@f3b() local_unnamed_addr +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i8* @a2, null +; CHECK-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP4:%.*]] +; CHECK: 2: +; CHECK-NEXT: [[TMP3:%.*]] = tail call i8* @f1b(i8* noalias nofree nonnull readnone align 16 dereferenceable(1) @a2) +; CHECK-NEXT: br label [[TMP4]] +; CHECK: 4: +; CHECK-NEXT: [[TMP5:%.*]] = phi i8* [ [[TMP3]], [[TMP2]] ], [ @a1, [[TMP0:%.*]] ] +; CHECK-NEXT: ret i8* [[TMP5]] ; %2 = icmp eq i8* %0, null br i1 %2, label %3, label %5 @@ -252,36 +319,52 @@ } define align 4 i32* @test7b(i32* align 32 %p) #0 { -; ATTRIBUTOR-LABEL: define {{[^@]+}}@test7b -; ATTRIBUTOR-SAME: (i32* nofree readnone returned align 32 "no-capture-maybe-returned" [[P:%.*]]) -; ATTRIBUTOR-NEXT: [[TMP1:%.*]] = tail call i8* @f1b(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) @a1) -; ATTRIBUTOR-NEXT: ret i32* [[P]] +; CHECK-LABEL: define {{[^@]+}}@test7b +; CHECK-SAME: (i32* nofree readnone returned align 32 "no-capture-maybe-returned" [[P:%.*]]) +; CHECK-NEXT: [[TMP1:%.*]] = tail call i8* @f1b(i8* noalias nofree nonnull readnone align 8 dereferenceable(1) @a1) +; CHECK-NEXT: ret i32* [[P]] ; tail call i8* @f1b(i8* align 8 dereferenceable(1) @a1) ret i32* %p } -; UTC_ARGS: --disable - ; TEST 8 define void @test8_helper() { +; CHECK-LABEL: define {{[^@]+}}@test8_helper() +; CHECK-NEXT: [[PTR0:%.*]] = tail call i32* @unknown() +; CHECK-NEXT: [[PTR1:%.*]] = tail call align 4 i32* @unknown() +; CHECK-NEXT: [[PTR2:%.*]] = tail call align 8 i32* @unknown() +; CHECK-NEXT: tail call void @test8(i32* noalias readnone align 4 [[PTR1]], i32* noalias readnone align 4 [[PTR1]], i32* noalias readnone [[PTR0]]) +; CHECK-NEXT: tail call void @test8(i32* noalias readnone align 8 [[PTR2]], i32* noalias readnone align 4 [[PTR1]], i32* noalias readnone align 4 [[PTR1]]) +; CHECK-NEXT: tail call void @test8(i32* noalias readnone align 8 [[PTR2]], i32* noalias readnone align 4 [[PTR1]], i32* noalias readnone align 4 [[PTR1]]) +; CHECK-NEXT: ret void +; %ptr0 = tail call i32* @unknown() %ptr1 = tail call align 4 i32* @unknown() %ptr2 = tail call align 8 i32* @unknown() tail call void @test8(i32* %ptr1, i32* %ptr1, i32* %ptr0) -; ATTRIBUTOR: tail call void @test8(i32* noalias readnone align 4 %ptr1, i32* noalias readnone align 4 %ptr1, i32* noalias readnone %ptr0) tail call void @test8(i32* %ptr2, i32* %ptr1, i32* %ptr1) -; ATTRIBUTOR: tail call void @test8(i32* noalias readnone align 8 %ptr2, i32* noalias readnone align 4 %ptr1, i32* noalias readnone align 4 %ptr1) tail call void @test8(i32* %ptr2, i32* %ptr1, i32* %ptr1) -; ATTRIBUTOR: tail call void @test8(i32* noalias readnone align 8 %ptr2, i32* noalias readnone align 4 %ptr1, i32* noalias readnone align 4 %ptr1) ret void } declare void @user_i32_ptr(i32* nocapture readnone) nounwind define internal void @test8(i32* %a, i32* %b, i32* %c) { -; ATTRIBUTOR_MODULE: define internal void @test8(i32* noalias nocapture readnone align 4 %a, i32* noalias nocapture readnone align 4 %b, i32* noalias nocapture readnone %c) -; ATTRIBUTOR_CGSCC: define internal void @test8(i32* nocapture readnone align 4 %a, i32* nocapture readnone align 4 %b, i32* nocapture readnone %c) +; 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]]) +; IS__TUNIT____-NEXT: call void @user_i32_ptr(i32* noalias nocapture readnone align 4 [[B]]) +; IS__TUNIT____-NEXT: call void @user_i32_ptr(i32* noalias nocapture readnone [[C]]) +; IS__TUNIT____-NEXT: ret void +; +; 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]]) +; IS__CGSCC____-NEXT: call void @user_i32_ptr(i32* noalias nocapture readnone align 4 [[B]]) +; IS__CGSCC____-NEXT: call void @user_i32_ptr(i32* noalias nocapture readnone [[C]]) +; IS__CGSCC____-NEXT: ret void +; call void @user_i32_ptr(i32* %a) call void @user_i32_ptr(i32* %b) call void @user_i32_ptr(i32* %c) @@ -289,33 +372,53 @@ } declare void @test9_helper(i32* %A) -define void @test9_traversal(i1 %c, i32* align 4 %B, i32* align 8 %C) { - %sel = select i1 %c, i32* %B, i32* %C +define void @test9_traversal(i1 %cnd, i32* align 4 %B, i32* align 8 %C) { +; CHECK-LABEL: define {{[^@]+}}@test9_traversal +; CHECK-SAME: (i1 [[CND:%.*]], i32* align 4 [[B:%.*]], i32* align 8 [[C:%.*]]) +; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CND]], i32* [[B]], i32* [[C]] +; CHECK-NEXT: call void @test9_helper(i32* align 4 [[SEL]]) +; CHECK-NEXT: ret void +; + %sel = select i1 %cnd, i32* %B, i32* %C call void @test9_helper(i32* %sel) ret void } ; FIXME: This will work with an upcoming patch (D66618 or similar) ; define align 32 i32* @test10a(i32* align 32 "no-capture-maybe-returned" %p) -; ATTRIBUTOR: define i32* @test10a(i32* nofree nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" %p) +; FIXME: This will work with an upcoming patch (D66618 or similar) +; store i32 1, i32* %r, align 32 +; 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) { -; ATTRIBUTOR: %l = load i32, i32* %p, align 32 +; 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 +; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[L]], 0 +; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] +; CHECK: t: +; CHECK-NEXT: [[R:%.*]] = call i32* @test10a(i32* nofree nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) +; CHECK-NEXT: store i32 1, i32* [[R]] +; CHECK-NEXT: [[G0:%.*]] = getelementptr i32, i32* [[P]], i32 8 +; CHECK-NEXT: br label [[E:%.*]] +; CHECK: f: +; CHECK-NEXT: [[G1:%.*]] = getelementptr i32, i32* [[P]], i32 8 +; CHECK-NEXT: store i32 -1, i32* [[G1]], align 4 +; CHECK-NEXT: br label [[E]] +; CHECK: e: +; CHECK-NEXT: [[PHI:%.*]] = phi i32* [ [[G0]], [[T]] ], [ [[G1]], [[F]] ] +; CHECK-NEXT: ret i32* [[PHI]] +; %l = load i32, i32* %p %c = icmp eq i32 %l, 0 br i1 %c, label %t, label %f t: %r = call i32* @test10a(i32* %p) -; FIXME: This will work with an upcoming patch (D66618 or similar) -; store i32 1, i32* %r, align 32 -; ATTRIBUTOR: store i32 1, i32* %r store i32 1, i32* %r %g0 = getelementptr i32, i32* %p, i32 8 br label %e f: %g1 = getelementptr i32, i32* %p, i32 8 -; FIXME: This will work with an upcoming patch (D66618 or similar) -; store i32 -1, i32* %g1, align 32 -; ATTRIBUTOR: store i32 -1, i32* %g1 store i32 -1, i32* %g1 br label %e e: @@ -325,25 +428,39 @@ ; FIXME: This will work with an upcoming patch (D66618 or similar) ; define align 32 i32* @test10b(i32* align 32 "no-capture-maybe-returned" %p) -; ATTRIBUTOR: define i32* @test10b(i32* nofree nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" %p) +; FIXME: This will work with an upcoming patch (D66618 or similar) +; store i32 1, i32* %r, align 32 +; 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) { -; ATTRIBUTOR: %l = load i32, i32* %p, align 32 +; 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 +; CHECK-NEXT: [[C:%.*]] = icmp eq i32 [[L]], 0 +; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]] +; CHECK: t: +; CHECK-NEXT: [[R:%.*]] = call i32* @test10b(i32* nofree nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) +; CHECK-NEXT: store i32 1, i32* [[R]] +; CHECK-NEXT: [[G0:%.*]] = getelementptr i32, i32* [[P]], i32 8 +; CHECK-NEXT: br label [[E:%.*]] +; CHECK: f: +; CHECK-NEXT: [[G1:%.*]] = getelementptr i32, i32* [[P]], i32 -8 +; CHECK-NEXT: store i32 -1, i32* [[G1]], align 4 +; CHECK-NEXT: br label [[E]] +; CHECK: e: +; CHECK-NEXT: [[PHI:%.*]] = phi i32* [ [[G0]], [[T]] ], [ [[G1]], [[F]] ] +; CHECK-NEXT: ret i32* [[PHI]] +; %l = load i32, i32* %p %c = icmp eq i32 %l, 0 br i1 %c, label %t, label %f t: %r = call i32* @test10b(i32* %p) -; FIXME: This will work with an upcoming patch (D66618 or similar) -; store i32 1, i32* %r, align 32 -; ATTRIBUTOR: store i32 1, i32* %r store i32 1, i32* %r %g0 = getelementptr i32, i32* %p, i32 8 br label %e f: %g1 = getelementptr i32, i32* %p, i32 -8 -; FIXME: This will work with an upcoming patch (D66618 or similar) -; store i32 -1, i32* %g1, align 32 -; ATTRIBUTOR: store i32 -1, i32* %g1 store i32 -1, i32* %g1 br label %e e: @@ -352,8 +469,13 @@ } -; ATTRIBUTOR: define i64 @test11(i32* nocapture nofree nonnull readonly align 8 dereferenceable(8) %p) 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]] +; %p-cast = bitcast i32* %p to i64* %ret = load i64, i64* %p-cast, align 8 ret i64 %ret @@ -363,8 +485,15 @@ ; Test for deduction using must-be-executed-context and GEP instruction ; FXIME: %p should have nonnull -; ATTRIBUTOR: define i64 @test12-1(i32* nocapture nofree readonly align 16 %p) 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]] +; %p-cast = bitcast i32* %p to i64* %arrayidx0 = getelementptr i64, i64* %p-cast, i64 1 %arrayidx1 = getelementptr i64, i64* %arrayidx0, i64 3 @@ -372,8 +501,14 @@ ret i64 %ret } -; ATTRIBUTOR: define i64 @test12-2(i32* nocapture nofree nonnull readonly align 16 dereferenceable(8) %p) 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]] +; %p-cast = bitcast i32* %p to i64* %arrayidx0 = getelementptr i64, i64* %p-cast, i64 0 %ret = load i64, i64* %arrayidx0, align 16 @@ -381,8 +516,15 @@ } ; FXIME: %p should have nonnull -; ATTRIBUTOR: define void @test12-3(i32* nocapture nofree writeonly align 16 %p) 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 +; %p-cast = bitcast i32* %p to i64* %arrayidx0 = getelementptr i64, i64* %p-cast, i64 1 %arrayidx1 = getelementptr i64, i64* %arrayidx0, i64 3 @@ -390,8 +532,14 @@ ret void } -; ATTRIBUTOR: define void @test12-4(i32* nocapture nofree nonnull writeonly align 16 dereferenceable(8) %p) 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 +; %p-cast = bitcast i32* %p to i64* %arrayidx0 = getelementptr i64, i64* %p-cast, i64 0 store i64 0, i64* %arrayidx0, align 16 @@ -400,8 +548,15 @@ declare void @use(i64*) willreturn nounwind -; ATTRIBUTOR: define void @test12-5(i32* align 16 %p) define void @test12-5(i32* align 4 %p) { +; CHECK-LABEL: define {{[^@]+}}@test12-5 +; CHECK-SAME: (i32* 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: tail call void @use(i64* align 16 [[ARRAYIDX1]]) +; CHECK-NEXT: ret void +; %p-cast = bitcast i32* %p to i64* %arrayidx0 = getelementptr i64, i64* %p-cast, i64 1 %arrayidx1 = getelementptr i64, i64* %arrayidx0, i64 3 @@ -409,8 +564,14 @@ ret void } -; ATTRIBUTOR: define void @test12-6(i32* align 16 %p) define void @test12-6(i32* align 4 %p) { +; CHECK-LABEL: define {{[^@]+}}@test12-6 +; CHECK-SAME: (i32* align 16 [[P:%.*]]) +; CHECK-NEXT: [[P_CAST:%.*]] = bitcast i32* [[P]] to i64* +; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i64, i64* [[P_CAST]], i64 0 +; CHECK-NEXT: tail call void @use(i64* align 16 [[ARRAYIDX0]]) +; CHECK-NEXT: ret void +; %p-cast = bitcast i32* %p to i64* %arrayidx0 = getelementptr i64, i64* %p-cast, i64 0 tail call void @use(i64* align 16 %arrayidx0) @@ -418,17 +579,17 @@ } define void @test13(i1 %c, i32* align 32 %dst) #0 { -; ATTRIBUTOR-LABEL: define {{[^@]+}}@test13 -; ATTRIBUTOR-SAME: (i1 [[C:%.*]], i32* nocapture nofree writeonly align 32 [[DST:%.*]]) -; ATTRIBUTOR-NEXT: br i1 [[C]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] -; ATTRIBUTOR: truebb: -; ATTRIBUTOR-NEXT: br label [[END:%.*]] -; ATTRIBUTOR: falsebb: -; ATTRIBUTOR-NEXT: br label [[END]] -; ATTRIBUTOR: end: -; ATTRIBUTOR-NEXT: [[PTR:%.*]] = phi i32* [ [[DST]], [[TRUEBB]] ], [ null, [[FALSEBB]] ] -; ATTRIBUTOR-NEXT: store i32 0, i32* [[PTR]], align 32 -; ATTRIBUTOR-NEXT: ret void +; 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 ; br i1 %c, label %truebb, label %falsebb truebb: @@ -442,16 +603,17 @@ } define void @test13-1(i1 %c, i32* align 32 %dst) { -; ATTRIBUTOR-LABEL: @test13-1( -; ATTRIBUTOR-NEXT: br i1 [[C:%.*]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] -; ATTRIBUTOR: truebb: -; ATTRIBUTOR-NEXT: br label [[END:%.*]] -; ATTRIBUTOR: falsebb: -; ATTRIBUTOR-NEXT: br label [[END]] -; ATTRIBUTOR: end: -; ATTRIBUTOR-NEXT: [[PTR:%.*]] = phi i32* [ [[DST:%.*]], [[TRUEBB]] ], [ inttoptr (i64 48 to i32*), [[FALSEBB]] ] -; ATTRIBUTOR-NEXT: store i32 0, i32* [[PTR]], align 16 -; ATTRIBUTOR-NEXT: ret void +; 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 ; br i1 %c, label %truebb, label %falsebb truebb: @@ -465,16 +627,17 @@ } define void @test13-2(i1 %c, i32* align 32 %dst) { -; ATTRIBUTOR-LABEL: @test13-2( -; ATTRIBUTOR-NEXT: br i1 [[C:%.*]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] -; ATTRIBUTOR: truebb: -; ATTRIBUTOR-NEXT: br label [[END:%.*]] -; ATTRIBUTOR: falsebb: -; ATTRIBUTOR-NEXT: br label [[END]] -; ATTRIBUTOR: end: -; ATTRIBUTOR-NEXT: [[PTR:%.*]] = phi i32* [ [[DST:%.*]], [[TRUEBB]] ], [ inttoptr (i64 160 to i32*), [[FALSEBB]] ] -; ATTRIBUTOR-NEXT: store i32 0, i32* [[PTR]], align 32 -; ATTRIBUTOR-NEXT: ret void +; 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 ; br i1 %c, label %truebb, label %falsebb truebb: @@ -488,16 +651,17 @@ } define void @test13-3(i1 %c, i32* align 32 %dst) { -; ATTRIBUTOR-LABEL: @test13-3( -; ATTRIBUTOR-NEXT: br i1 [[C:%.*]], label [[TRUEBB:%.*]], label [[FALSEBB:%.*]] -; ATTRIBUTOR: truebb: -; ATTRIBUTOR-NEXT: br label [[END:%.*]] -; ATTRIBUTOR: falsebb: -; ATTRIBUTOR-NEXT: br label [[END]] -; ATTRIBUTOR: end: -; ATTRIBUTOR-NEXT: [[PTR:%.*]] = phi i32* [ [[DST:%.*]], [[TRUEBB]] ], [ inttoptr (i64 128 to i32*), [[FALSEBB]] ] -; ATTRIBUTOR-NEXT: store i32 0, i32* [[PTR]], align 32 -; ATTRIBUTOR-NEXT: ret void +; 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 ; br i1 %c, label %truebb, label %falsebb truebb: @@ -512,29 +676,42 @@ ; 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]] +; %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]] +; %i2p = inttoptr i64 %i to i64* ret i64* %i2p } ; Use the store alignment only for the pointer operand. define void @aligned_store(i8* %Value, i8** %Ptr) { -; ATTRIBUTOR: define void @aligned_store(i8* nofree writeonly %Value, i8** nocapture nofree nonnull writeonly align 32 dereferenceable(8) %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 +; store i8* %Value, i8** %Ptr, align 32 ret void } -; UTC_ARGS: --enable declare i8* @some_func(i8*) define void @align_call_op_not_store(i8* align 2048 %arg) { -; ATTRIBUTOR-LABEL: define {{[^@]+}}@align_call_op_not_store -; ATTRIBUTOR-SAME: (i8* align 2048 [[ARG:%.*]]) -; ATTRIBUTOR-NEXT: [[UNKNOWN:%.*]] = call i8* @some_func(i8* align 2048 [[ARG]]) -; ATTRIBUTOR-NEXT: store i8 0, i8* [[UNKNOWN]] -; ATTRIBUTOR-NEXT: ret void +; CHECK-LABEL: define {{[^@]+}}@align_call_op_not_store +; CHECK-SAME: (i8* align 2048 [[ARG:%.*]]) +; CHECK-NEXT: [[UNKNOWN:%.*]] = call i8* @some_func(i8* align 2048 [[ARG]]) +; CHECK-NEXT: store i8 0, i8* [[UNKNOWN]] +; CHECK-NEXT: ret void ; %unknown = call i8* @some_func(i8* %arg) store i8 0, i8* %unknown @@ -542,11 +719,11 @@ } define void @align_store_after_bc(i32* align 2048 %arg) { ; -; ATTRIBUTOR-LABEL: define {{[^@]+}}@align_store_after_bc -; ATTRIBUTOR-SAME: (i32* nocapture nofree nonnull writeonly align 2048 dereferenceable(1) [[ARG:%.*]]) -; ATTRIBUTOR-NEXT: [[BC:%.*]] = bitcast i32* [[ARG]] to i8* -; ATTRIBUTOR-NEXT: store i8 0, i8* [[BC]], align 2048 -; ATTRIBUTOR-NEXT: ret void +; 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 ; %bc = bitcast i32* %arg to i8* store i8 0, i8* %bc @@ -557,10 +734,35 @@ ; 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]] +; %v = load i32, i32* %p, align 32 ret i32 %v } define i32 @musttail_caller_1(i32* %p) { +; 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 +; IS__TUNIT____-NEXT: br i1 [[C]], label [[MT:%.*]], label [[EXIT:%.*]] +; IS__TUNIT____: mt: +; IS__TUNIT____-NEXT: [[V:%.*]] = musttail call i32 @musttail_callee_1(i32* nocapture nofree readonly [[P]]) +; IS__TUNIT____-NEXT: ret i32 [[V]] +; IS__TUNIT____: exit: +; IS__TUNIT____-NEXT: ret i32 0 +; +; 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 +; IS__CGSCC____-NEXT: br i1 [[C]], label [[MT:%.*]], label [[EXIT:%.*]] +; IS__CGSCC____: mt: +; IS__CGSCC____-NEXT: [[V:%.*]] = musttail call i32 @musttail_callee_1(i32* nocapture nofree nonnull readonly dereferenceable(4) [[P]]) +; IS__CGSCC____-NEXT: ret i32 [[V]] +; IS__CGSCC____: exit: +; IS__CGSCC____-NEXT: ret i32 0 +; %c = load i1, i1* @cnd br i1 %c, label %mt, label %exit mt: @@ -569,7 +771,6 @@ exit: ret i32 0 } -; UTC_ARGS: --disable attributes #0 = { nounwind uwtable noinline } attributes #1 = { 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,14 +1,18 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt -attributor -attributor-disable=false -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefix=CHECK +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; ; When a function is marked `alwaysinline` and is able to be inlined, ; we can IPO its boundaries ; the function is not exactly defined, and marked alwaysinline and can be inlined, ; so the function can be analyzed -; CHECK: Function Attrs: alwaysinline nofree nosync nounwind readnone willreturn +; CHECK: Function Attrs: alwaysinline +; CHECK-SAME: willreturn define linkonce void @inner1() alwaysinline { -; CHECK-LABEL: @inner1( +; CHECK-LABEL: define {{[^@]+}}@inner1() ; CHECK-NEXT: entry: ; CHECK-NEXT: ret void ; @@ -16,9 +20,10 @@ ret void } -; CHECK: Function Attrs: nofree nosync nounwind readnone willreturn +; CHECK: Function Attrs: +; CHECK-SAME: willreturn define void @outer1() { -; CHECK-LABEL: @outer1( +; CHECK-LABEL: define {{[^@]+}}@outer1() ; CHECK-NEXT: entry: ; CHECK-NEXT: ret void ; @@ -31,7 +36,7 @@ ; so it will not be analyzed ; CHECK-NOT: Function Attrs: define linkonce i32 @inner2() { -; CHECK-LABEL: @inner2( +; CHECK-LABEL: define {{[^@]+}}@inner2() ; CHECK-NEXT: entry: ; CHECK-NEXT: ret i32 1 ; @@ -41,9 +46,9 @@ ; CHECK-NOT: Function Attrs define i32 @outer2() { -; CHECK-LABEL: @outer2( +; CHECK-LABEL: define {{[^@]+}}@outer2() ; CHECK-NEXT: entry: -; CHECK-NEXT: [[R:%.*]] = call i32 @inner2() #2 +; CHECK-NEXT: [[R:%.*]] = call i32 @inner2() ; CHECK-NEXT: ret i32 [[R]] ; entry: @@ -55,11 +60,15 @@ ; it is `unexactly defined` and alwaysinline but cannot be inlined. ; so it will not be analyzed ; CHECK: Function Attrs: -; CHECK-NOT: nofree nosync nounwind readnone +; CHECK-NOT: nofree +; CHECK-NOT: nosync +; CHECK-NOT: nounwind +; CHECK-NOT: readnone define linkonce i32 @inner3(i8* %addr) alwaysinline { -; CHECK-LABEL: @inner3( +; CHECK-LABEL: define {{[^@]+}}@inner3 +; CHECK-SAME: (i8* [[ADDR:%.*]]) ; CHECK-NEXT: entry: -; CHECK-NEXT: indirectbr i8* [[ADDR:%.*]], [label [[ONE:%.*]], label %two] +; CHECK-NEXT: indirectbr i8* [[ADDR]], [label [[ONE:%.*]], label %two] ; CHECK: one: ; CHECK-NEXT: ret i32 42 ; CHECK: two: @@ -77,8 +86,9 @@ ; CHECK-NOT: Function Attrs: define i32 @outer3(i32 %x) { -; CHECK-LABEL: @outer3( -; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 42 +; CHECK-LABEL: define {{[^@]+}}@outer3 +; CHECK-SAME: (i32 [[X:%.*]]) +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X]], 42 ; CHECK-NEXT: [[ADDR:%.*]] = select i1 [[CMP]], i8* blockaddress(@inner3, [[ONE:%.*]]), i8* blockaddress(@inner3, [[TWO:%.*]]) ; CHECK-NEXT: [[CALL:%.*]] = call i32 @inner3(i8* [[ADDR]]) ; CHECK-NEXT: ret i32 [[CALL]] 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,8 +1,9 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; FIXME: Add -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations below. -; This flag was removed because max iterations is 2 in most cases, but in windows it is 1. -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-annotate-decl-cs < %s | FileCheck %s -; ModuleID = 'callback_simple.c' +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 + target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" ; Test 0 @@ -15,19 +16,54 @@ ; transfer in both directions. define void @t0_caller(i32* %a) { -; CHECK-LABEL: define {{[^@]+}}@t0_caller -; CHECK-SAME: (i32* align 256 [[A:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[B:%.*]] = alloca i32, align 32 -; CHECK-NEXT: [[C:%.*]] = alloca i32*, align 64 -; CHECK-NEXT: [[PTR:%.*]] = alloca i32, align 128 -; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* -; CHECK-NEXT: store i32 42, i32* [[B]], align 32 -; CHECK-NEXT: store i32* [[B]], i32** [[C]], align 64 -; CHECK-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t0_callback_broker(i32* noalias align 536870912 null, i32* nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nonnull bitcast (void (i32*, i32*, i32*, i64, i32**)* @t0_callback_callee to void (i32*, i32*, ...)*), i32* align 256 [[A]], i64 undef, i32** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C]]) -; CHECK-NEXT: ret void +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@t0_caller +; IS__TUNIT_OPM-SAME: (i32* align 256 [[A:%.*]]) +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[B:%.*]] = alloca i32, align 32 +; IS__TUNIT_OPM-NEXT: [[C:%.*]] = alloca i32*, align 64 +; IS__TUNIT_OPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 +; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* +; IS__TUNIT_OPM-NEXT: store i32 42, i32* [[B]], align 32 +; IS__TUNIT_OPM-NEXT: store i32* [[B]], i32** [[C]], align 64 +; IS__TUNIT_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t0_callback_broker(i32* noalias align 536870912 null, i32* nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nonnull bitcast (void (i32*, i32*, i32*, i64, i32**)* @t0_callback_callee to void (i32*, i32*, ...)*), i32* align 256 [[A]], i64 undef, i32** nocapture nonnull readonly align 64 dereferenceable(8) [[C]]) +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@t0_caller +; IS__TUNIT_NPM-SAME: (i32* align 256 [[A:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[B:%.*]] = alloca i32, align 32 +; IS__TUNIT_NPM-NEXT: [[C:%.*]] = alloca i32*, align 64 +; IS__TUNIT_NPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* +; IS__TUNIT_NPM-NEXT: store i32 42, i32* [[B]], align 32 +; IS__TUNIT_NPM-NEXT: store i32* [[B]], i32** [[C]], align 64 +; IS__TUNIT_NPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t0_callback_broker(i32* noalias align 536870912 null, i32* nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nonnull bitcast (void (i32*, i32*, i32*, i64, i32**)* @t0_callback_callee to void (i32*, i32*, ...)*), i32* align 256 [[A]], i64 undef, i32** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C]]) +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@t0_caller +; IS__CGSCC_OPM-SAME: (i32* [[A:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[B:%.*]] = alloca i32, align 32 +; IS__CGSCC_OPM-NEXT: [[C:%.*]] = alloca i32*, align 64 +; IS__CGSCC_OPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 +; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* +; IS__CGSCC_OPM-NEXT: store i32 42, i32* [[B]], align 32 +; IS__CGSCC_OPM-NEXT: store i32* [[B]], i32** [[C]], align 64 +; IS__CGSCC_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t0_callback_broker(i32* noalias align 536870912 null, i32* nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i32**)* @t0_callback_callee to void (i32*, i32*, ...)*), i32* [[A]], i64 99, i32** nonnull align 64 dereferenceable(8) [[C]]) +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t0_caller +; IS__CGSCC_NPM-SAME: (i32* align 256 [[A:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[B:%.*]] = alloca i32, align 32 +; IS__CGSCC_NPM-NEXT: [[C:%.*]] = alloca i32*, align 64 +; IS__CGSCC_NPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 +; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* +; IS__CGSCC_NPM-NEXT: store i32 42, i32* [[B]], align 32 +; IS__CGSCC_NPM-NEXT: store i32* [[B]], i32** [[C]], align 64 +; IS__CGSCC_NPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t0_callback_broker(i32* noalias align 536870912 null, i32* nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i32**)* @t0_callback_callee to void (i32*, i32*, ...)*), i32* align 256 [[A]], i64 99, i32** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C]]) +; IS__CGSCC_NPM-NEXT: ret void ; - entry: %b = alloca i32, align 32 %c = alloca i32*, align 64 @@ -42,14 +78,33 @@ ; Note that the first two arguments are provided by the callback_broker according to the callback in !1 below! ; The others are annotated with alignment information, amongst others, or even replaced by the constants passed to the call. define internal void @t0_callback_callee(i32* %is_not_null, i32* %ptr, i32* %a, i64 %b, i32** %c) { -; CHECK-LABEL: define {{[^@]+}}@t0_callback_callee -; CHECK-SAME: (i32* nocapture nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* align 256 [[A:%.*]], i64 [[B:%.*]], i32** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8 -; CHECK-NEXT: store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4 -; CHECK-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C]], align 64 -; CHECK-NEXT: tail call void @t0_check(i32* align 256 [[A]], i64 99, i32* [[TMP0]]) -; CHECK-NEXT: ret void +; +; IS________OPM-LABEL: define {{[^@]+}}@t0_callback_callee +; IS________OPM-SAME: (i32* nocapture nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* align 256 [[A:%.*]], i64 [[B:%.*]], i32** nocapture nonnull readonly align 64 dereferenceable(8) [[C:%.*]]) +; IS________OPM-NEXT: entry: +; IS________OPM-NEXT: [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8 +; IS________OPM-NEXT: store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4 +; IS________OPM-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C]], align 64 +; IS________OPM-NEXT: tail call void @t0_check(i32* align 256 [[A]], i64 99, i32* [[TMP0]]) +; IS________OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@t0_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* align 256 [[A:%.*]], i64 [[B:%.*]], i32** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8 +; IS__TUNIT_NPM-NEXT: store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C]], align 64 +; IS__TUNIT_NPM-NEXT: tail call void @t0_check(i32* align 256 [[A]], i64 99, i32* [[TMP0]]) +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t0_callback_callee +; IS__CGSCC_NPM-SAME: (i32* nocapture nonnull writeonly align 4 dereferenceable(4) [[IS_NOT_NULL:%.*]], i32* nocapture nonnull readonly align 8 dereferenceable(4) [[PTR:%.*]], i32* align 256 [[A:%.*]], i64 [[B:%.*]], i32** nocapture nonnull readonly align 8 dereferenceable(8) [[C:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8 +; IS__CGSCC_NPM-NEXT: store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4 +; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C]], align 8 +; IS__CGSCC_NPM-NEXT: tail call void @t0_check(i32* align 256 [[A]], i64 99, i32* [[TMP0]]) +; IS__CGSCC_NPM-NEXT: ret void ; entry: %ptr_val = load i32, i32* %ptr, align 8 @@ -69,17 +124,53 @@ ; we deduce and propagate noalias and others properly. define void @t1_caller(i32* noalias %a) { -; CHECK-LABEL: define {{[^@]+}}@t1_caller -; CHECK-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[B:%.*]] = alloca i32, align 32 -; CHECK-NEXT: [[C:%.*]] = alloca i32*, align 64 -; CHECK-NEXT: [[PTR:%.*]] = alloca i32, align 128 -; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* -; CHECK-NEXT: store i32 42, i32* [[B]], align 32 -; CHECK-NEXT: store i32* [[B]], i32** [[C]], align 64 -; CHECK-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t1_callback_broker(i32* noalias align 536870912 null, i32* noalias nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nonnull bitcast (void (i32*, i32*, i32*, i64, i32**)* @t1_callback_callee to void (i32*, i32*, ...)*), i32* noalias nocapture align 256 [[A]], i64 undef, i32** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C]]) -; CHECK-NEXT: ret void +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@t1_caller +; IS__TUNIT_OPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[B:%.*]] = alloca i32, align 32 +; IS__TUNIT_OPM-NEXT: [[C:%.*]] = alloca i32*, align 64 +; IS__TUNIT_OPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 +; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* +; IS__TUNIT_OPM-NEXT: store i32 42, i32* [[B]], align 32 +; IS__TUNIT_OPM-NEXT: store i32* [[B]], i32** [[C]], align 64 +; IS__TUNIT_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t1_callback_broker(i32* noalias align 536870912 null, i32* nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nonnull bitcast (void (i32*, i32*, i32*, i64, i32**)* @t1_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 undef, i32** nocapture nonnull readonly align 64 dereferenceable(8) [[C]]) +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@t1_caller +; IS__TUNIT_NPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[B:%.*]] = alloca i32, align 32 +; IS__TUNIT_NPM-NEXT: [[C:%.*]] = alloca i32*, align 64 +; IS__TUNIT_NPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* +; IS__TUNIT_NPM-NEXT: store i32 42, i32* [[B]], align 32 +; IS__TUNIT_NPM-NEXT: store i32* [[B]], i32** [[C]], align 64 +; IS__TUNIT_NPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t1_callback_broker(i32* noalias align 536870912 null, i32* noalias nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nonnull bitcast (void (i32*, i32*, i32*, i64, i32**)* @t1_callback_callee to void (i32*, i32*, ...)*), i32* noalias nocapture align 256 [[A]], i64 undef, i32** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C]]) +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@t1_caller +; IS__CGSCC_OPM-SAME: (i32* noalias [[A:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[B:%.*]] = alloca i32, align 32 +; IS__CGSCC_OPM-NEXT: [[C:%.*]] = alloca i32*, align 64 +; IS__CGSCC_OPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 +; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* +; IS__CGSCC_OPM-NEXT: store i32 42, i32* [[B]], align 32 +; IS__CGSCC_OPM-NEXT: store i32* [[B]], i32** [[C]], align 64 +; IS__CGSCC_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t1_callback_broker(i32* noalias align 536870912 null, i32* nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i32**)* @t1_callback_callee to void (i32*, i32*, ...)*), i32* [[A]], i64 99, i32** nonnull align 64 dereferenceable(8) [[C]]) +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t1_caller +; IS__CGSCC_NPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[B:%.*]] = alloca i32, align 32 +; IS__CGSCC_NPM-NEXT: [[C:%.*]] = alloca i32*, align 64 +; IS__CGSCC_NPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 +; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* +; IS__CGSCC_NPM-NEXT: store i32 42, i32* [[B]], align 32 +; IS__CGSCC_NPM-NEXT: store i32* [[B]], i32** [[C]], align 64 +; IS__CGSCC_NPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t1_callback_broker(i32* noalias align 536870912 null, i32* noalias nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i32**)* @t1_callback_callee to void (i32*, i32*, ...)*), i32* noalias nocapture align 256 [[A]], i64 99, i32** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C]]) +; IS__CGSCC_NPM-NEXT: ret void ; entry: %b = alloca i32, align 32 @@ -95,14 +186,33 @@ ; Note that the first two arguments are provided by the callback_broker according to the callback in !1 below! ; 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) { -; CHECK-LABEL: define {{[^@]+}}@t1_callback_callee -; CHECK-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:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8 -; CHECK-NEXT: store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4 -; CHECK-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C]], align 64 -; CHECK-NEXT: tail call void @t1_check(i32* nocapture align 256 [[A]], i64 99, i32* [[TMP0]]) -; CHECK-NEXT: ret void +; +; IS________OPM-LABEL: define {{[^@]+}}@t1_callback_callee +; IS________OPM-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:%.*]]) +; IS________OPM-NEXT: entry: +; IS________OPM-NEXT: [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8 +; IS________OPM-NEXT: store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4 +; IS________OPM-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C]], align 64 +; IS________OPM-NEXT: tail call void @t1_check(i32* nocapture align 256 [[A]], i64 99, i32* [[TMP0]]) +; IS________OPM-NEXT: ret void +; +; 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: +; IS__TUNIT_NPM-NEXT: [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8 +; IS__TUNIT_NPM-NEXT: store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C]], align 64 +; IS__TUNIT_NPM-NEXT: tail call void @t1_check(i32* nocapture align 256 [[A]], i64 99, i32* [[TMP0]]) +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t1_callback_callee +; IS__CGSCC_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 8 dereferenceable(8) [[C:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8 +; IS__CGSCC_NPM-NEXT: store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4 +; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C]], align 8 +; IS__CGSCC_NPM-NEXT: tail call void @t1_check(i32* nocapture align 256 [[A]], i64 99, i32* [[TMP0]]) +; IS__CGSCC_NPM-NEXT: ret void ; entry: %ptr_val = load i32, i32* %ptr, align 8 @@ -121,17 +231,53 @@ ; Similar to test 1 but checking that the noalias is only placed if potential synchronization through @t2_check is preserved. define void @t2_caller(i32* noalias %a) { -; CHECK-LABEL: define {{[^@]+}}@t2_caller -; CHECK-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[B:%.*]] = alloca i32, align 32 -; CHECK-NEXT: [[C:%.*]] = alloca i32*, align 64 -; CHECK-NEXT: [[PTR:%.*]] = alloca i32, align 128 -; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* -; CHECK-NEXT: store i32 42, i32* [[B]], align 32 -; CHECK-NEXT: store i32* [[B]], i32** [[C]], align 64 -; CHECK-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t2_callback_broker(i32* noalias align 536870912 null, i32* noalias nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nonnull bitcast (void (i32*, i32*, i32*, i64, i32**)* @t2_callback_callee to void (i32*, i32*, ...)*), i32* noalias nocapture align 256 [[A]], i64 undef, i32** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C]]) -; CHECK-NEXT: ret void +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@t2_caller +; IS__TUNIT_OPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[B:%.*]] = alloca i32, align 32 +; IS__TUNIT_OPM-NEXT: [[C:%.*]] = alloca i32*, align 64 +; IS__TUNIT_OPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 +; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* +; IS__TUNIT_OPM-NEXT: store i32 42, i32* [[B]], align 32 +; IS__TUNIT_OPM-NEXT: store i32* [[B]], i32** [[C]], align 64 +; IS__TUNIT_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t2_callback_broker(i32* noalias align 536870912 null, i32* nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nonnull bitcast (void (i32*, i32*, i32*, i64, i32**)* @t2_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 undef, i32** nocapture nonnull readonly align 64 dereferenceable(8) [[C]]) +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@t2_caller +; IS__TUNIT_NPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[B:%.*]] = alloca i32, align 32 +; IS__TUNIT_NPM-NEXT: [[C:%.*]] = alloca i32*, align 64 +; IS__TUNIT_NPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* +; IS__TUNIT_NPM-NEXT: store i32 42, i32* [[B]], align 32 +; IS__TUNIT_NPM-NEXT: store i32* [[B]], i32** [[C]], align 64 +; IS__TUNIT_NPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t2_callback_broker(i32* noalias align 536870912 null, i32* noalias nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nonnull bitcast (void (i32*, i32*, i32*, i64, i32**)* @t2_callback_callee to void (i32*, i32*, ...)*), i32* noalias nocapture align 256 [[A]], i64 undef, i32** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C]]) +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@t2_caller +; IS__CGSCC_OPM-SAME: (i32* noalias [[A:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[B:%.*]] = alloca i32, align 32 +; IS__CGSCC_OPM-NEXT: [[C:%.*]] = alloca i32*, align 64 +; IS__CGSCC_OPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 +; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* +; IS__CGSCC_OPM-NEXT: store i32 42, i32* [[B]], align 32 +; IS__CGSCC_OPM-NEXT: store i32* [[B]], i32** [[C]], align 64 +; IS__CGSCC_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t2_callback_broker(i32* noalias align 536870912 null, i32* nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i32**)* @t2_callback_callee to void (i32*, i32*, ...)*), i32* [[A]], i64 99, i32** nonnull align 64 dereferenceable(8) [[C]]) +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t2_caller +; IS__CGSCC_NPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[B:%.*]] = alloca i32, align 32 +; IS__CGSCC_NPM-NEXT: [[C:%.*]] = alloca i32*, align 64 +; IS__CGSCC_NPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 +; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* +; IS__CGSCC_NPM-NEXT: store i32 42, i32* [[B]], align 32 +; IS__CGSCC_NPM-NEXT: store i32* [[B]], i32** [[C]], align 64 +; IS__CGSCC_NPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t2_callback_broker(i32* noalias align 536870912 null, i32* noalias nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i32**)* @t2_callback_callee to void (i32*, i32*, ...)*), i32* noalias nocapture align 256 [[A]], i64 99, i32** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C]]) +; IS__CGSCC_NPM-NEXT: ret void ; entry: %b = alloca i32, align 32 @@ -149,14 +295,33 @@ ; ; FIXME: We should derive noalias for %a and add a "fake use" of %a in all potentially synchronizing calls. define internal void @t2_callback_callee(i32* %is_not_null, i32* %ptr, i32* %a, i64 %b, i32** %c) { -; CHECK-LABEL: define {{[^@]+}}@t2_callback_callee -; CHECK-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** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8 -; CHECK-NEXT: store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4 -; CHECK-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C]], align 64 -; CHECK-NEXT: tail call void @t2_check(i32* nocapture align 256 [[A]], i64 99, i32* [[TMP0]]) -; CHECK-NEXT: ret void +; +; IS________OPM-LABEL: define {{[^@]+}}@t2_callback_callee +; IS________OPM-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:%.*]]) +; IS________OPM-NEXT: entry: +; IS________OPM-NEXT: [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8 +; IS________OPM-NEXT: store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4 +; IS________OPM-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C]], align 64 +; IS________OPM-NEXT: tail call void @t2_check(i32* nocapture align 256 [[A]], i64 99, i32* [[TMP0]]) +; IS________OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@t2_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* nocapture align 256 [[A:%.*]], i64 [[B:%.*]], i32** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8 +; IS__TUNIT_NPM-NEXT: store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C]], align 64 +; IS__TUNIT_NPM-NEXT: tail call void @t2_check(i32* nocapture align 256 [[A]], i64 99, i32* [[TMP0]]) +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t2_callback_callee +; IS__CGSCC_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 8 dereferenceable(8) [[C:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8 +; IS__CGSCC_NPM-NEXT: store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4 +; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C]], align 8 +; IS__CGSCC_NPM-NEXT: tail call void @t2_check(i32* nocapture align 256 [[A]], i64 99, i32* [[TMP0]]) +; IS__CGSCC_NPM-NEXT: ret void ; entry: %ptr_val = load i32, i32* %ptr, align 8 @@ -175,18 +340,57 @@ ; Basically test 2 with the casted callback callee used twice. define void @t3_caller(i32* noalias %a) { -; CHECK-LABEL: define {{[^@]+}}@t3_caller -; CHECK-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[B:%.*]] = alloca i32, align 32 -; CHECK-NEXT: [[C:%.*]] = alloca i32*, align 64 -; CHECK-NEXT: [[PTR:%.*]] = alloca i32, align 128 -; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* -; CHECK-NEXT: store i32 42, i32* [[B]], align 32 -; CHECK-NEXT: store i32* [[B]], i32** [[C]], align 64 -; CHECK-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias align 536870912 null, i32* noalias nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nonnull bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* noalias nocapture align 256 [[A]], i64 undef, i32** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C]]) -; CHECK-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias align 536870912 null, i32* noalias nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nonnull bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* noalias nocapture align 256 [[A]], i64 undef, i32** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C]]) -; CHECK-NEXT: ret void +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@t3_caller +; IS__TUNIT_OPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) +; IS__TUNIT_OPM-NEXT: entry: +; IS__TUNIT_OPM-NEXT: [[B:%.*]] = alloca i32, align 32 +; IS__TUNIT_OPM-NEXT: [[C:%.*]] = alloca i32*, align 64 +; IS__TUNIT_OPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 +; IS__TUNIT_OPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* +; IS__TUNIT_OPM-NEXT: store i32 42, i32* [[B]], align 32 +; IS__TUNIT_OPM-NEXT: store i32* [[B]], i32** [[C]], align 64 +; IS__TUNIT_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias align 536870912 null, i32* nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nonnull bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 undef, i32** nocapture nonnull readonly align 64 dereferenceable(8) [[C]]) +; IS__TUNIT_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias align 536870912 null, i32* nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nonnull bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* nocapture align 256 [[A]], i64 undef, i32** nocapture nonnull readonly align 64 dereferenceable(8) [[C]]) +; IS__TUNIT_OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@t3_caller +; IS__TUNIT_NPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[B:%.*]] = alloca i32, align 32 +; IS__TUNIT_NPM-NEXT: [[C:%.*]] = alloca i32*, align 64 +; IS__TUNIT_NPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* +; IS__TUNIT_NPM-NEXT: store i32 42, i32* [[B]], align 32 +; IS__TUNIT_NPM-NEXT: store i32* [[B]], i32** [[C]], align 64 +; IS__TUNIT_NPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias align 536870912 null, i32* noalias nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nonnull bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* noalias nocapture align 256 [[A]], i64 undef, i32** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C]]) +; IS__TUNIT_NPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias align 536870912 null, i32* noalias nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* nonnull bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* noalias nocapture align 256 [[A]], i64 undef, i32** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C]]) +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@t3_caller +; IS__CGSCC_OPM-SAME: (i32* noalias [[A:%.*]]) +; IS__CGSCC_OPM-NEXT: entry: +; IS__CGSCC_OPM-NEXT: [[B:%.*]] = alloca i32, align 32 +; IS__CGSCC_OPM-NEXT: [[C:%.*]] = alloca i32*, align 64 +; IS__CGSCC_OPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 +; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* +; IS__CGSCC_OPM-NEXT: store i32 42, i32* [[B]], align 32 +; IS__CGSCC_OPM-NEXT: store i32* [[B]], i32** [[C]], align 64 +; IS__CGSCC_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias align 536870912 null, i32* nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* [[A]], i64 99, i32** nonnull align 64 dereferenceable(8) [[C]]) +; IS__CGSCC_OPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias align 536870912 null, i32* nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* [[A]], i64 99, i32** nonnull align 64 dereferenceable(8) [[C]]) +; IS__CGSCC_OPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t3_caller +; IS__CGSCC_NPM-SAME: (i32* noalias nocapture align 256 [[A:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[B:%.*]] = alloca i32, align 32 +; IS__CGSCC_NPM-NEXT: [[C:%.*]] = alloca i32*, align 64 +; IS__CGSCC_NPM-NEXT: [[PTR:%.*]] = alloca i32, align 128 +; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = bitcast i32* [[B]] to i8* +; IS__CGSCC_NPM-NEXT: store i32 42, i32* [[B]], align 32 +; IS__CGSCC_NPM-NEXT: store i32* [[B]], i32** [[C]], align 64 +; IS__CGSCC_NPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias align 536870912 null, i32* noalias nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* noalias nocapture align 256 [[A]], i64 99, i32** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C]]) +; IS__CGSCC_NPM-NEXT: call void (i32*, i32*, void (i32*, i32*, ...)*, ...) @t3_callback_broker(i32* noalias align 536870912 null, i32* noalias nonnull align 128 dereferenceable(4) [[PTR]], void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i64, i32**)* @t3_callback_callee to void (i32*, i32*, ...)*), i32* noalias nocapture align 256 [[A]], i64 99, i32** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C]]) +; IS__CGSCC_NPM-NEXT: ret void ; entry: %b = alloca i32, align 32 @@ -205,14 +409,33 @@ ; ; FIXME: We should derive noalias for %a and add a "fake use" of %a in all potentially synchronizing calls. define internal void @t3_callback_callee(i32* %is_not_null, i32* %ptr, i32* %a, i64 %b, i32** %c) { -; CHECK-LABEL: define {{[^@]+}}@t3_callback_callee -; CHECK-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** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8 -; CHECK-NEXT: store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4 -; CHECK-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C]], align 64 -; CHECK-NEXT: tail call void @t3_check(i32* nocapture align 256 [[A]], i64 99, i32* [[TMP0]]) -; CHECK-NEXT: ret void +; +; IS________OPM-LABEL: define {{[^@]+}}@t3_callback_callee +; IS________OPM-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:%.*]]) +; IS________OPM-NEXT: entry: +; IS________OPM-NEXT: [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8 +; IS________OPM-NEXT: store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4 +; IS________OPM-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C]], align 64 +; IS________OPM-NEXT: tail call void @t3_check(i32* nocapture align 256 [[A]], i64 99, i32* [[TMP0]]) +; IS________OPM-NEXT: ret void +; +; IS__TUNIT_NPM-LABEL: define {{[^@]+}}@t3_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* nocapture align 256 [[A:%.*]], i64 [[B:%.*]], i32** noalias nocapture nonnull readonly align 64 dereferenceable(8) [[C:%.*]]) +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8 +; IS__TUNIT_NPM-NEXT: store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4 +; IS__TUNIT_NPM-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C]], align 64 +; IS__TUNIT_NPM-NEXT: tail call void @t3_check(i32* nocapture align 256 [[A]], i64 99, i32* [[TMP0]]) +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@t3_callback_callee +; IS__CGSCC_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 8 dereferenceable(8) [[C:%.*]]) +; IS__CGSCC_NPM-NEXT: entry: +; IS__CGSCC_NPM-NEXT: [[PTR_VAL:%.*]] = load i32, i32* [[PTR]], align 8 +; IS__CGSCC_NPM-NEXT: store i32 [[PTR_VAL]], i32* [[IS_NOT_NULL]], align 4 +; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = load i32*, i32** [[C]], align 8 +; IS__CGSCC_NPM-NEXT: tail call void @t3_check(i32* nocapture align 256 [[A]], i64 99, i32* [[TMP0]]) +; IS__CGSCC_NPM-NEXT: ret void ; entry: %ptr_val = load i32, i32* %ptr, align 8 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,16 +1,22 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -attributor -attributor-manifest-internal --attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=16 -S < %s | FileCheck %s --check-prefix=ATTRIBUTOR +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; FIXME: Figure out why we need 16 iterations here. -; UTC_ARGS: --disable - declare void @deref_phi_user(i32* %a); ; TEST 1 ; take mininimum of return values ; define i32* @test1(i32* dereferenceable(4) %0, double* dereferenceable(8) %1, i1 zeroext %2) local_unnamed_addr { -; ATTRIBUTOR: define nonnull dereferenceable(4) i32* @test1(i32* nofree nonnull readnone dereferenceable(4) "no-capture-maybe-returned" %0, double* nofree nonnull readnone dereferenceable(8) "no-capture-maybe-returned" %1, i1 zeroext %2) +; 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]] +; %4 = bitcast double* %1 to i32* %5 = select i1 %2, i32* %0, i32* %4 ret i32* %5 @@ -18,7 +24,12 @@ ; TEST 2 define i32* @test2(i32* dereferenceable_or_null(4) %0, double* dereferenceable(8) %1, i1 zeroext %2) local_unnamed_addr { -; ATTRIBUTOR: define dereferenceable_or_null(4) i32* @test2(i32* nofree readnone dereferenceable_or_null(4) "no-capture-maybe-returned" %0, double* nofree nonnull readnone dereferenceable(8) "no-capture-maybe-returned" %1, i1 zeroext %2) +; 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]] +; %4 = bitcast double* %1 to i32* %5 = select i1 %2, i32* %0, i32* %4 ret i32* %5 @@ -27,19 +38,33 @@ ; TEST 3 ; GEP inbounds define i32* @test3_1(i32* dereferenceable(8) %0) local_unnamed_addr { -; ATTRIBUTOR: define nonnull dereferenceable(4) i32* @test3_1(i32* nofree nonnull readnone dereferenceable(8) "no-capture-maybe-returned" %0) +; 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]] +; %ret = getelementptr inbounds i32, i32* %0, i64 1 ret i32* %ret } define i32* @test3_2(i32* dereferenceable_or_null(32) %0) local_unnamed_addr { -; ATTRIBUTOR: define nonnull dereferenceable(16) i32* @test3_2(i32* nofree readnone dereferenceable_or_null(32) "no-capture-maybe-returned" %0) +; 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]] +; %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 { -; ATTRIBUTOR: define nonnull dereferenceable(4) i32* @test3_3(i32* nofree nonnull readnone dereferenceable(8) "no-capture-maybe-returned" %0, i32* nofree nonnull readnone dereferenceable(16) "no-capture-maybe-returned" %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]] +; %ret1 = getelementptr inbounds i32, i32* %0, i64 1 %ret2 = getelementptr inbounds i32, i32* %1, i64 2 %ret = select i1 %2, i32* %ret1, i32* %ret2 @@ -50,20 +75,44 @@ ; Better than known in IR. define dereferenceable(4) i32* @test4(i32* dereferenceable(8) %0) local_unnamed_addr { -; ATTRIBUTOR: define nonnull dereferenceable(8) i32* @test4(i32* nofree nonnull readnone returned dereferenceable(8) "no-capture-maybe-returned" %0) +; 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]] +; ret i32* %0 } ; TEST 5 ; loop in which dereferenceabily "grows" define void @deref_phi_growing(i32* dereferenceable(4000) %a) { +; CHECK-LABEL: define {{[^@]+}}@deref_phi_growing +; CHECK-SAME: (i32* nonnull dereferenceable(4000) [[A:%.*]]) +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_COND:%.*]] +; CHECK: for.cond: +; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ] +; CHECK-NEXT: [[A_ADDR_0:%.*]] = phi i32* [ [[A]], [[ENTRY]] ], [ [[INCDEC_PTR:%.*]], [[FOR_INC]] ] +; CHECK-NEXT: call void @deref_phi_user(i32* nonnull dereferenceable(4000) [[A_ADDR_0]]) +; CHECK-NEXT: [[TMP:%.*]] = load i32, i32* [[A_ADDR_0]], align 4 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], [[TMP]] +; 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 [[FOR_INC]] +; CHECK: for.inc: +; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i32, i32* [[A_ADDR_0]], i64 -1 +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_0]], 1 +; CHECK-NEXT: br label [[FOR_COND]] +; CHECK: for.end: +; CHECK-NEXT: ret void +; entry: br label %for.cond for.cond: ; preds = %for.inc, %entry %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ] %a.addr.0 = phi i32* [ %a, %entry ], [ %incdec.ptr, %for.inc ] -; ATTRIBUTOR: call void @deref_phi_user(i32* nonnull dereferenceable(4000) %a.addr.0) call void @deref_phi_user(i32* %a.addr.0) %tmp = load i32, i32* %a.addr.0, align 4 %cmp = icmp slt i32 %i.0, %tmp @@ -87,13 +136,34 @@ ; TEST 6 ; loop in which dereferenceabily "shrinks" define void @deref_phi_shrinking(i32* dereferenceable(4000) %a) { +; CHECK-LABEL: define {{[^@]+}}@deref_phi_shrinking +; CHECK-SAME: (i32* nonnull dereferenceable(4000) [[A:%.*]]) +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_COND:%.*]] +; CHECK: for.cond: +; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ] +; CHECK-NEXT: [[A_ADDR_0:%.*]] = phi i32* [ [[A]], [[ENTRY]] ], [ [[INCDEC_PTR:%.*]], [[FOR_INC]] ] +; CHECK-NEXT: call void @deref_phi_user(i32* nonnull [[A_ADDR_0]]) +; CHECK-NEXT: [[TMP:%.*]] = load i32, i32* [[A_ADDR_0]], align 4 +; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], [[TMP]] +; 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 [[FOR_INC]] +; CHECK: for.inc: +; CHECK-NEXT: [[INCDEC_PTR]] = getelementptr inbounds i32, i32* [[A_ADDR_0]], i64 1 +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I_0]], 1 +; CHECK-NEXT: br label [[FOR_COND]] +; CHECK: for.end: +; CHECK-NEXT: ret void +; entry: br label %for.cond for.cond: ; preds = %for.inc, %entry %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ] %a.addr.0 = phi i32* [ %a, %entry ], [ %incdec.ptr, %for.inc ] -; ATTRIBUTOR: call void @deref_phi_user(i32* nonnull %a.addr.0) call void @deref_phi_user(i32* %a.addr.0) %tmp = load i32, i32* %a.addr.0, align 4 %cmp = icmp slt i32 %i.0, %tmp @@ -119,96 +189,108 @@ declare i32* @unkown_ptr() willreturn nounwind declare i32 @unkown_f(i32*) willreturn nounwind define i32* @f7_0(i32* %ptr) { -; ATTRIBUTOR: define nonnull dereferenceable(8) i32* @f7_0(i32* nonnull returned dereferenceable(8) %ptr) +; 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]]) +; CHECK-NEXT: ret i32* [[PTR]] +; %T = tail call i32 @unkown_f(i32* dereferenceable(8) %ptr) ret i32* %ptr } -; ATTRIBUTOR: define void @f7_1(i32* nonnull align 4 dereferenceable(4) %ptr, i1 %c) define void @f7_1(i32* %ptr, i1 %c) { - -; ATTRIBUTOR: %A = tail call i32 @unkown_f(i32* nonnull align 4 dereferenceable(4) %ptr) +; 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]]) +; CHECK-NEXT: [[B:%.*]] = tail call i32 @unkown_f(i32* nonnull align 4 dereferenceable(4) [[PTR]]) +; CHECK-NEXT: br i1 [[C]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] +; CHECK: if.true: +; CHECK-NEXT: [[C:%.*]] = tail call i32 @unkown_f(i32* nonnull align 4 dereferenceable(8) [[PTR]]) +; CHECK-NEXT: [[D:%.*]] = tail call i32 @unkown_f(i32* nonnull align 4 dereferenceable(8) [[PTR]]) +; CHECK-NEXT: [[E:%.*]] = tail call i32 @unkown_f(i32* nonnull align 4 dereferenceable(8) [[PTR]]) +; CHECK-NEXT: ret void +; CHECK: if.false: +; CHECK-NEXT: ret void +; %A = tail call i32 @unkown_f(i32* %ptr) - %ptr.0 = load i32, i32* %ptr ; deref 4 hold - ; FIXME: this should be %B = tail call i32 @unkown_f(i32* nonnull dereferenceable(4) %ptr) -; ATTRIBUTOR: %B = tail call i32 @unkown_f(i32* nonnull align 4 dereferenceable(4) %ptr) %B = tail call i32 @unkown_f(i32* dereferenceable(1) %ptr) - br i1%c, label %if.true, label %if.false if.true: -; ATTRIBUTOR: %C = tail call i32 @unkown_f(i32* nonnull align 4 dereferenceable(8) %ptr) %C = tail call i32 @unkown_f(i32* %ptr) - -; ATTRIBUTOR: %D = tail call i32 @unkown_f(i32* nonnull align 4 dereferenceable(8) %ptr) %D = tail call i32 @unkown_f(i32* dereferenceable(8) %ptr) - -; ATTRIBUTOR: %E = tail call i32 @unkown_f(i32* nonnull align 4 dereferenceable(8) %ptr) %E = tail call i32 @unkown_f(i32* %ptr) - ret void - if.false: ret void } -; ATTRIBUTOR: define void @f7_2(i1 %c) define void @f7_2(i1 %c) { - +; CHECK-LABEL: define {{[^@]+}}@f7_2 +; CHECK-SAME: (i1 [[C:%.*]]) +; CHECK-NEXT: [[PTR:%.*]] = tail call nonnull align 4 dereferenceable(4) i32* @unkown_ptr() +; CHECK-NEXT: [[A:%.*]] = tail call i32 @unkown_f(i32* nonnull align 4 dereferenceable(4) [[PTR]]) +; CHECK-NEXT: [[B:%.*]] = tail call i32 @unkown_f(i32* nonnull align 4 dereferenceable(4) [[PTR]]) +; CHECK-NEXT: br i1 [[C]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]] +; CHECK: if.true: +; CHECK-NEXT: [[C:%.*]] = tail call i32 @unkown_f(i32* nonnull align 4 dereferenceable(8) [[PTR]]) +; CHECK-NEXT: [[D:%.*]] = tail call i32 @unkown_f(i32* nonnull align 4 dereferenceable(8) [[PTR]]) +; CHECK-NEXT: [[E:%.*]] = tail call i32 @unkown_f(i32* nonnull align 4 dereferenceable(8) [[PTR]]) +; CHECK-NEXT: ret void +; CHECK: if.false: +; CHECK-NEXT: ret void +; %ptr = tail call i32* @unkown_ptr() - -; ATTRIBUTOR: %A = tail call i32 @unkown_f(i32* nonnull align 4 dereferenceable(4) %ptr) %A = tail call i32 @unkown_f(i32* %ptr) - %arg_a.0 = load i32, i32* %ptr ; deref 4 hold - -; ATTRIBUTOR: %B = tail call i32 @unkown_f(i32* nonnull align 4 dereferenceable(4) %ptr) %B = tail call i32 @unkown_f(i32* dereferenceable(1) %ptr) - br i1%c, label %if.true, label %if.false if.true: - -; ATTRIBUTOR: %C = tail call i32 @unkown_f(i32* nonnull align 4 dereferenceable(8) %ptr) %C = tail call i32 @unkown_f(i32* %ptr) - -; ATTRIBUTOR: %D = tail call i32 @unkown_f(i32* nonnull align 4 dereferenceable(8) %ptr) %D = tail call i32 @unkown_f(i32* dereferenceable(8) %ptr) - %E = tail call i32 @unkown_f(i32* %ptr) -; ATTRIBUTOR: %E = tail call i32 @unkown_f(i32* nonnull align 4 dereferenceable(8) %ptr) - ret void - if.false: ret void } define i32* @f7_3() { -; ATTRIBUTOR: define nonnull align 16 dereferenceable(4) i32* @f7_3() +; 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 +; CHECK-NEXT: ret i32* [[PTR]] +; %ptr = tail call i32* @unkown_ptr() store i32 10, i32* %ptr, align 16 ret i32* %ptr } -define i32* @test_for_minus_index(i32* %p) { ; FIXME: This should have a return dereferenceable(8) but we need to make sure it will work in loops as well. -; ATTRIBUTOR: define nonnull align 4 i32* @test_for_minus_index(i32* nofree nonnull writeonly align 4 "no-capture-maybe-returned" %p) +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]] +; %q = getelementptr inbounds i32, i32* %p, i32 -2 store i32 1, i32* %q ret i32* %q } define void @deref_or_null_and_nonnull(i32* dereferenceable_or_null(100) %0) { -; ATTRIBUTOR: define void @deref_or_null_and_nonnull(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(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 +; store i32 1, i32* %0 ret void } -; UTC_ARGS: --enable - ; TEST 8 ; Use Constant range in deereferenceable ; void g(int *p, long long int *range){ @@ -223,24 +305,24 @@ ; } ; } +; NOTE: %p should not be dereferenceable define internal void @fill_range_not_inbounds(i32* %p, i64 %start){ -; ATTRIBUTOR-LABEL: define {{[^@]+}}@fill_range_not_inbounds -; ATTRIBUTOR-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64 [[START:%.*]]) -; ATTRIBUTOR-NEXT: entry: -; ATTRIBUTOR-NEXT: [[TMP0:%.*]] = add nsw i64 [[START]], 9 -; ATTRIBUTOR-NEXT: br label [[FOR_BODY:%.*]] -; ATTRIBUTOR: for.cond.cleanup: -; ATTRIBUTOR-NEXT: ret void -; ATTRIBUTOR: for.body: -; ATTRIBUTOR-NEXT: [[I_06:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] -; ATTRIBUTOR-NEXT: [[CONV:%.*]] = trunc i64 [[I_06]] to i32 -; ATTRIBUTOR-NEXT: [[ARRAYIDX:%.*]] = getelementptr i32, i32* [[P]], i64 [[I_06]] -; ATTRIBUTOR-NEXT: store i32 [[CONV]], i32* [[ARRAYIDX]], align 4 -; ATTRIBUTOR-NEXT: [[INC]] = add nsw i64 [[I_06]], 1 -; ATTRIBUTOR-NEXT: [[CMP:%.*]] = icmp slt i64 [[I_06]], [[TMP0]] -; ATTRIBUTOR-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]] +; 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:%.*]] ; -; NOTE: %p should not be dereferenceable entry: %0 = add nsw i64 %start, 9 br label %for.body @@ -257,24 +339,25 @@ %cmp = icmp slt i64 %i.06, %0 br i1 %cmp, label %for.body, label %for.cond.cleanup } + +; FIXME: %p should be dereferenceable(40) define internal void @fill_range_inbounds(i32* %p, i64 %start){ -; ATTRIBUTOR-LABEL: define {{[^@]+}}@fill_range_inbounds -; ATTRIBUTOR-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64 [[START:%.*]]) -; ATTRIBUTOR-NEXT: entry: -; ATTRIBUTOR-NEXT: [[TMP0:%.*]] = add nsw i64 [[START]], 9 -; ATTRIBUTOR-NEXT: br label [[FOR_BODY:%.*]] -; ATTRIBUTOR: for.cond.cleanup: -; ATTRIBUTOR-NEXT: ret void -; ATTRIBUTOR: for.body: -; ATTRIBUTOR-NEXT: [[I_06:%.*]] = phi i64 [ [[START]], [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY]] ] -; ATTRIBUTOR-NEXT: [[CONV:%.*]] = trunc i64 [[I_06]] to i32 -; ATTRIBUTOR-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 [[I_06]] -; ATTRIBUTOR-NEXT: store i32 [[CONV]], i32* [[ARRAYIDX]], align 4 -; ATTRIBUTOR-NEXT: [[INC]] = add nsw i64 [[I_06]], 1 -; ATTRIBUTOR-NEXT: [[CMP:%.*]] = icmp slt i64 [[I_06]], [[TMP0]] -; ATTRIBUTOR-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_CLEANUP:%.*]] +; 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:%.*]] ; -; FIXME: %p should be dereferenceable(40) entry: %0 = add nsw i64 %start, 9 br label %for.body @@ -293,13 +376,13 @@ } define void @call_fill_range(i32* nocapture %p, i64* nocapture readonly %range) { -; ATTRIBUTOR-LABEL: define {{[^@]+}}@call_fill_range -; ATTRIBUTOR-SAME: (i32* nocapture nofree writeonly [[P:%.*]], i64* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[RANGE:%.*]]) -; ATTRIBUTOR-NEXT: entry: -; ATTRIBUTOR-NEXT: [[TMP0:%.*]] = load i64, i64* [[RANGE]], align 8, !range !0 -; ATTRIBUTOR-NEXT: tail call void @fill_range_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) -; ATTRIBUTOR-NEXT: tail call void @fill_range_not_inbounds(i32* nocapture nofree writeonly [[P]], i64 [[TMP0]]) -; ATTRIBUTOR-NEXT: ret void +; 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 ; entry: %0 = load i64, i64* %range, align 8, !range !0 @@ -312,6 +395,7 @@ declare void @use1(i8*) willreturn nounwind declare void @use2(i8*, i8*) willreturn nounwind declare void @use3(i8*, i8*, i8*) willreturn nounwind + ; simple path test ; if(..) ; fun2(dereferenceable(8) %a, dereferenceable(8) %b) @@ -319,7 +403,17 @@ ; 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) { -; ATTRIBUTOR: define void @simple-path(i8* nonnull dereferenceable(4) %a, i8* %b, i8 %c) +; CHECK-LABEL: define {{[^@]+}}@simple-path +; CHECK-SAME: (i8* nonnull dereferenceable(4) [[A:%.*]], i8* [[B:%.*]], i8 [[C:%.*]]) +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[C]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] +; CHECK: if.then: +; CHECK-NEXT: tail call void @use2(i8* nonnull dereferenceable(8) [[A]], i8* nonnull dereferenceable(8) [[B]]) +; CHECK-NEXT: ret void +; CHECK: if.else: +; CHECK-NEXT: tail call void @use2(i8* nonnull dereferenceable(4) [[A]], i8* [[B]]) +; CHECK-NEXT: ret void +; %cmp = icmp eq i8 %c, 0 br i1 %cmp, label %if.then, label %if.else if.then: @@ -329,6 +423,7 @@ tail call void @use2(i8* dereferenceable(4) %a, i8* %b) ret void } + ; More complex test ; { ; fun1(dereferenceable(4) %a) @@ -341,9 +436,22 @@ ; fun1(dereferenceable(8) %a) ; } ; %a is dereferenceable(12) - define void @complex-path(i8* %a, i8* %b, i8 %c) { -; ATTRIBUTOR: define void @complex-path(i8* nonnull dereferenceable(12) %a, i8* nocapture nofree readnone %b, i8 %c) +; 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 +; CHECK-NEXT: tail call void @use1(i8* nonnull dereferenceable(12) [[A]]) +; CHECK-NEXT: br i1 [[CMP]], label [[CONT_THEN:%.*]], label [[CONT_ELSE:%.*]] +; CHECK: cont.then: +; CHECK-NEXT: tail call void @use1(i8* nonnull dereferenceable(12) [[A]]) +; CHECK-NEXT: br label [[CONT2:%.*]] +; CHECK: cont.else: +; CHECK-NEXT: tail call void @use1(i8* nonnull dereferenceable(16) [[A]]) +; CHECK-NEXT: br label [[CONT2]] +; CHECK: cont2: +; CHECK-NEXT: tail call void @use1(i8* nonnull dereferenceable(12) [[A]]) +; CHECK-NEXT: ret void +; %cmp = icmp eq i8 %c, 0 tail call void @use1(i8* dereferenceable(4) %a) br i1 %cmp, label %cont.then, label %cont.else @@ -373,8 +481,33 @@ ; } ; ; FIXME: %ptr should be dereferenceable(4) -; ATTRIBUTOR: define dso_local void @rec-branch-1(i32 %a, i32 %b, i32 %c, i32* nocapture nofree writeonly %ptr) 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 +; entry: %tobool = icmp eq i32 %a, 0 br i1 %tobool, label %if.else3, label %if.then @@ -421,8 +554,33 @@ ; } ; } ; FIXME: %ptr should be dereferenceable(4) -; ATTRIBUTOR: define dso_local void @rec-branch-2(i32 %a, i32 %b, i32 %c, i32* nocapture nofree writeonly %ptr) define dso_local void @rec-branch-2(i32 %a, i32 %b, i32 %c, i32* %ptr) { +; CHECK-LABEL: define {{[^@]+}}@rec-branch-2 +; 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: tail call void @rec-branch-2(i32 1, i32 1, i32 1, i32* nocapture nofree writeonly [[PTR]]) +; CHECK-NEXT: br label [[IF_END8]] +; CHECK: if.end8: +; CHECK-NEXT: ret void +; entry: %tobool = icmp eq i32 %a, 0 br i1 %tobool, label %if.else3, label %if.then @@ -463,6 +621,24 @@ ; ATTRIBUTOR-NEXT: call void @unknown() ; ATTRIBUTOR-NEXT: ret void ; +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@nonnull_assume_pos +; IS__TUNIT_OPM-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(101) [[ARG1:%.*]], i8* nocapture nofree readnone dereferenceable_or_null(31) [[ARG2:%.*]], i8* nocapture nofree nonnull readnone [[ARG3:%.*]], i8* nocapture nofree readnone dereferenceable_or_null(42) [[ARG4:%.*]]) +; IS__TUNIT_OPM-NEXT: call void @llvm.assume(i1 true) #6 [ "nonnull"(i8* undef), "dereferenceable"(i8* undef, i64 1), "dereferenceable"(i8* undef, i64 2), "dereferenceable"(i8* undef, i64 101), "dereferenceable_or_null"(i8* undef, i64 31), "dereferenceable_or_null"(i8* undef, i64 42) ] +; IS__TUNIT_OPM-NEXT: call void @unknown() +; IS__TUNIT_OPM-NEXT: ret void +; +; IS________NPM-LABEL: define {{[^@]+}}@nonnull_assume_pos +; IS________NPM-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(101) [[ARG1:%.*]], i8* nocapture nofree readnone dereferenceable_or_null(31) [[ARG2:%.*]], i8* nocapture nofree nonnull readnone [[ARG3:%.*]], i8* nocapture nofree readnone dereferenceable_or_null(42) [[ARG4:%.*]]) +; IS________NPM-NEXT: call void @llvm.assume(i1 true) #7 [ "nonnull"(i8* undef), "dereferenceable"(i8* undef, i64 1), "dereferenceable"(i8* undef, i64 2), "dereferenceable"(i8* undef, i64 101), "dereferenceable_or_null"(i8* undef, i64 31), "dereferenceable_or_null"(i8* undef, i64 42) ] +; IS________NPM-NEXT: call void @unknown() +; IS________NPM-NEXT: ret void +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@nonnull_assume_pos +; IS__CGSCC_OPM-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(101) [[ARG1:%.*]], i8* nocapture nofree readnone dereferenceable_or_null(31) [[ARG2:%.*]], i8* nocapture nofree nonnull readnone [[ARG3:%.*]], i8* nocapture nofree readnone dereferenceable_or_null(42) [[ARG4:%.*]]) +; IS__CGSCC_OPM-NEXT: call void @llvm.assume(i1 true) #8 [ "nonnull"(i8* undef), "dereferenceable"(i8* undef, i64 1), "dereferenceable"(i8* undef, i64 2), "dereferenceable"(i8* undef, i64 101), "dereferenceable_or_null"(i8* undef, i64 31), "dereferenceable_or_null"(i8* undef, i64 42) ] +; IS__CGSCC_OPM-NEXT: call void @unknown() +; IS__CGSCC_OPM-NEXT: ret void +; call void @llvm.assume(i1 true) [ "nonnull"(i8* %arg3), "dereferenceable"(i8* %arg1, i64 1), "dereferenceable"(i8* %arg1, i64 2), "dereferenceable"(i8* %arg1, i64 101), "dereferenceable_or_null"(i8* %arg2, i64 31), "dereferenceable_or_null"(i8* %arg4, i64 42)] call void @unknown() ret void @@ -474,6 +650,12 @@ ; ATTRIBUTOR-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i8* undef, i64 101), "dereferenceable"(i8* undef, i64 -2), "dereferenceable_or_null"(i8* undef, i64 31) ] ; ATTRIBUTOR-NEXT: ret void ; +; CHECK-LABEL: define {{[^@]+}}@nonnull_assume_neg +; CHECK-SAME: (i8* nocapture nofree readnone [[ARG1:%.*]], i8* nocapture nofree readnone [[ARG2:%.*]], i8* nocapture nofree readnone [[ARG3:%.*]]) +; CHECK-NEXT: call void @unknown() +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i8* undef, i64 101), "dereferenceable"(i8* undef, i64 -2), "dereferenceable_or_null"(i8* undef, i64 31) ] +; CHECK-NEXT: ret void +; call void @unknown() call void @llvm.assume(i1 true) ["dereferenceable"(i8* %arg1, i64 101), "dereferenceable"(i8* %arg2, i64 -2), "dereferenceable_or_null"(i8* %arg3, i64 31)] ret void @@ -497,6 +679,24 @@ ; ATTRIBUTOR-NEXT: call void @unknown() ; ATTRIBUTOR-NEXT: ret void ; +; CHECK-LABEL: define {{[^@]+}}@nonnull_assume_call +; CHECK-SAME: (i8* [[ARG1:%.*]], i8* [[ARG2:%.*]], i8* [[ARG3:%.*]], i8* [[ARG4:%.*]]) +; CHECK-NEXT: call void @unknown() +; CHECK-NEXT: [[P:%.*]] = call nonnull dereferenceable(101) i32* @unkown_ptr() +; CHECK-NEXT: call void @unknown_use32(i32* nonnull dereferenceable(101) [[P]]) +; CHECK-NEXT: call void @unknown_use8(i8* nonnull dereferenceable(42) [[ARG4]]) +; CHECK-NEXT: call void @unknown_use8(i8* nonnull [[ARG3]]) +; CHECK-NEXT: call void @unknown_use8(i8* nonnull dereferenceable(31) [[ARG2]]) +; CHECK-NEXT: call void @unknown_use8(i8* nonnull dereferenceable(2) [[ARG1]]) +; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i8* [[ARG3]]), "dereferenceable"(i8* [[ARG1]], i64 1), "dereferenceable"(i8* [[ARG1]], i64 2), "dereferenceable"(i32* [[P]], i64 101), "dereferenceable_or_null"(i8* [[ARG2]], i64 31), "dereferenceable_or_null"(i8* [[ARG4]], i64 42) ] +; CHECK-NEXT: call void @unknown_use8(i8* nonnull dereferenceable(2) [[ARG1]]) +; CHECK-NEXT: call void @unknown_use8(i8* nonnull dereferenceable(31) [[ARG2]]) +; CHECK-NEXT: call void @unknown_use8(i8* nonnull [[ARG3]]) +; CHECK-NEXT: call void @unknown_use8(i8* nonnull dereferenceable(42) [[ARG4]]) +; CHECK-NEXT: call void @unknown_use32(i32* nonnull dereferenceable(101) [[P]]) +; CHECK-NEXT: call void @unknown() +; CHECK-NEXT: ret void +; call void @unknown() %p = call i32* @unkown_ptr() call void @unknown_use32(i32* %p) 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,12 +1,29 @@ -; RUN: opt < %s -attributor --attributor-disable=false -S | FileCheck %s --check-prefix=ATTRIBUTOR -; RUN: opt < %s -passes=attributor --attributor-disable=false -S | FileCheck %s --check-prefix=ATTRIBUTOR_CGSCC_NPM -; Copied from Transforms/InferFunctionAttrs/dereferenceable.ll +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 ; Determine dereference-ability before unused loads get deleted: ; https://bugs.llvm.org/show_bug.cgi?id=21780 define <4 x double> @PR21780(double* %ptr) { -; ATTRIBUTOR-LABEL: @PR21780(double* nocapture nofree nonnull readonly align 8 dereferenceable(32) %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]] +; ; GEP of index 0 is simplified away. %arrayidx1 = getelementptr inbounds double, double* %ptr, i64 1 @@ -28,7 +45,12 @@ define double @PR21780_only_access3_with_inbounds(double* %ptr) { -; ATTRIBUTOR-LABEL: @PR21780_only_access3_with_inbounds(double* nocapture nofree nonnull readonly align 8 dereferenceable(32) %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]] +; %arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3 %t3 = load double, double* %arrayidx3, align 8 @@ -36,14 +58,24 @@ } define double @PR21780_only_access3_without_inbounds(double* %ptr) { -; ATTRIBUTOR-LABEL: @PR21780_only_access3_without_inbounds(double* nocapture nofree readonly align 8 %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]] +; %arrayidx3 = getelementptr double, double* %ptr, i64 3 %t3 = load double, double* %arrayidx3, align 8 ret double %t3 } define double @PR21780_without_inbounds(double* %ptr) { -; ATTRIBUTOR-LABEL: @PR21780_without_inbounds(double* nocapture nofree nonnull readonly align 8 dereferenceable(32) %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]] +; %arrayidx1 = getelementptr double, double* %ptr, i64 1 %arrayidx2 = getelementptr double, double* %ptr, i64 2 @@ -60,7 +92,13 @@ ; Unsimplified, but still valid. Also, throw in some bogus arguments. define void @gep0(i8* %unused, i8* %other, i8* %ptr) { -; ATTRIBUTOR-LABEL: @gep0(i8* nocapture nofree readnone %unused, i8* nocapture nofree nonnull writeonly dereferenceable(1) %other, i8* nocapture nofree nonnull readonly dereferenceable(3) %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]] +; CHECK-NEXT: store i8 [[T2]], i8* [[OTHER]] +; CHECK-NEXT: ret void +; %arrayidx0 = getelementptr i8, i8* %ptr, i64 0 %arrayidx1 = getelementptr i8, i8* %ptr, i64 1 %arrayidx2 = getelementptr i8, i8* %ptr, i64 2 @@ -75,7 +113,10 @@ ; Multiple arguments may be dereferenceable. define void @ordering(i8* %ptr1, i32* %ptr2) { -; ATTRIBUTOR-LABEL: @ordering(i8* nocapture nofree nonnull readnone dereferenceable(3) %ptr1, i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) %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 +; %a20 = getelementptr i32, i32* %ptr2, i64 0 %a12 = getelementptr i8, i8* %ptr1, i64 2 %t12 = load i8, i8* %a12 @@ -92,7 +133,13 @@ ; Not in entry block. define void @not_entry_but_guaranteed_to_execute(i8* %ptr) { -; ATTRIBUTOR-LABEL: @not_entry_but_guaranteed_to_execute(i8* nocapture nofree nonnull readnone dereferenceable(3) %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 +; entry: br label %exit exit: @@ -108,7 +155,15 @@ ; Not in entry block and not guaranteed to execute. define void @not_entry_not_guaranteed_to_execute(i8* %ptr, i1 %cond) { -; ATTRIBUTOR-LABEL: @not_entry_not_guaranteed_to_execute(i8* nocapture nofree readnone %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 +; entry: br i1 %cond, label %loads, label %exit loads: @@ -126,7 +181,15 @@ ; The last load may not execute, so derefenceable bytes only covers the 1st two loads. define void @partial_in_entry(i16* %ptr, i1 %cond) { -; ATTRIBUTOR-LABEL: @partial_in_entry(i16* nocapture nofree nonnull readnone align 2 dereferenceable(4) %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 +; entry: %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 @@ -145,7 +208,12 @@ ; The 2nd and 3rd loads may never execute. define void @volatile_is_not_dereferenceable(i16* %ptr) { -; ATTRIBUTOR-LABEL: @volatile_is_not_dereferenceable(i16* nofree align 2 %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 +; %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 @@ -158,7 +226,10 @@ ; TODO: We should allow inference for atomic (but not volatile) ops. define void @atomic_is_alright(i16* %ptr) { -; ATTRIBUTOR-LABEL: @atomic_is_alright(i16* nocapture nofree nonnull readnone align 2 dereferenceable(6) %ptr) +; CHECK-LABEL: define {{[^@]+}}@atomic_is_alright +; CHECK-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(6) [[PTR:%.*]]) +; CHECK-NEXT: ret void +; %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 @@ -171,7 +242,11 @@ declare void @may_not_return() define void @not_guaranteed_to_transfer_execution(i16* %ptr) { -; ATTRIBUTOR-LABEL: @not_guaranteed_to_transfer_execution(i16* nocapture nofree nonnull readnone align 2 dereferenceable(2) %ptr) +; CHECK-LABEL: define {{[^@]+}}@not_guaranteed_to_transfer_execution +; CHECK-SAME: (i16* nocapture nofree nonnull readnone align 2 dereferenceable(2) [[PTR:%.*]]) +; CHECK-NEXT: call void @may_not_return() +; CHECK-NEXT: ret void +; %arrayidx0 = getelementptr i16, i16* %ptr, i64 0 %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 @@ -185,7 +260,10 @@ ; We must have consecutive accesses. define void @variable_gep_index(i8* %unused, i8* %ptr, i64 %variable_index) { -; ATTRIBUTOR-LABEL: @variable_gep_index(i8* nocapture nofree readnone %unused, i8* nocapture nofree nonnull readnone dereferenceable(1) %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 +; %arrayidx1 = getelementptr i8, i8* %ptr, i64 %variable_index %arrayidx2 = getelementptr i8, i8* %ptr, i64 2 %t0 = load i8, i8* %ptr @@ -198,7 +276,10 @@ define void @multi_index_gep(<4 x i8>* %ptr) { ; FIXME: %ptr should be dereferenceable(4) -; ATTRIBUTOR-LABEL: @multi_index_gep(<4 x i8>* nocapture nofree nonnull readnone dereferenceable(1) %ptr) +; CHECK-LABEL: define {{[^@]+}}@multi_index_gep +; CHECK-SAME: (<4 x i8>* nocapture nofree nonnull readnone dereferenceable(1) [[PTR:%.*]]) +; CHECK-NEXT: ret void +; %arrayidx00 = getelementptr <4 x i8>, <4 x i8>* %ptr, i64 0, i64 0 %t0 = load i8, i8* %arrayidx00 ret void @@ -207,7 +288,10 @@ ; Could round weird bitwidths down? define void @not_byte_multiple(i9* %ptr) { -; ATTRIBUTOR-LABEL: @not_byte_multiple(i9* nocapture nofree nonnull readnone align 2 dereferenceable(2) %ptr) +; CHECK-LABEL: define {{[^@]+}}@not_byte_multiple +; CHECK-SAME: (i9* nocapture nofree nonnull readnone align 2 dereferenceable(2) [[PTR:%.*]]) +; CHECK-NEXT: ret void +; %arrayidx0 = getelementptr i9, i9* %ptr, i64 0 %t0 = load i9, i9* %arrayidx0 ret void @@ -216,7 +300,10 @@ ; Missing direct access from the pointer. define void @no_pointer_deref(i16* %ptr) { -; ATTRIBUTOR-LABEL: @no_pointer_deref(i16* nocapture nofree readnone align 2 %ptr) +; CHECK-LABEL: define {{[^@]+}}@no_pointer_deref +; CHECK-SAME: (i16* nocapture nofree readnone align 2 [[PTR:%.*]]) +; CHECK-NEXT: ret void +; %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 %t1 = load i16, i16* %arrayidx1 @@ -227,7 +314,10 @@ ; Out-of-order is ok, but missing access concludes dereferenceable range. define void @non_consecutive(i32* %ptr) { -; ATTRIBUTOR-LABEL: @non_consecutive(i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) %ptr) +; CHECK-LABEL: define {{[^@]+}}@non_consecutive +; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[PTR:%.*]]) +; CHECK-NEXT: ret void +; %arrayidx1 = getelementptr i32, i32* %ptr, i64 1 %arrayidx0 = getelementptr i32, i32* %ptr, i64 0 %arrayidx3 = getelementptr i32, i32* %ptr, i64 3 @@ -240,7 +330,10 @@ ; Improve on existing dereferenceable attribute. define void @more_bytes(i32* dereferenceable(8) %ptr) { -; ATTRIBUTOR-LABEL: @more_bytes(i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) %ptr) +; CHECK-LABEL: define {{[^@]+}}@more_bytes +; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) [[PTR:%.*]]) +; CHECK-NEXT: ret void +; %arrayidx3 = getelementptr i32, i32* %ptr, i64 3 %arrayidx1 = getelementptr i32, i32* %ptr, i64 1 %arrayidx0 = getelementptr i32, i32* %ptr, i64 0 @@ -255,7 +348,10 @@ ; Improve on existing dereferenceable_or_null attribute. define void @more_bytes_and_not_null(i32* dereferenceable_or_null(8) %ptr) { -; ATTRIBUTOR-LABEL: @more_bytes_and_not_null(i32* nocapture nofree nonnull readnone align 4 dereferenceable(16) %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 +; %arrayidx3 = getelementptr i32, i32* %ptr, i64 3 %arrayidx1 = getelementptr i32, i32* %ptr, i64 1 %arrayidx0 = getelementptr i32, i32* %ptr, i64 0 @@ -270,7 +366,10 @@ ; But don't pessimize existing dereferenceable attribute. define void @better_bytes(i32* dereferenceable(100) %ptr) { -; ATTRIBUTOR-LABEL: @better_bytes(i32* nocapture nofree nonnull readnone align 4 dereferenceable(100) %ptr) +; CHECK-LABEL: define {{[^@]+}}@better_bytes +; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(100) [[PTR:%.*]]) +; CHECK-NEXT: ret void +; %arrayidx3 = getelementptr i32, i32* %ptr, i64 3 %arrayidx1 = getelementptr i32, i32* %ptr, i64 1 %arrayidx0 = getelementptr i32, i32* %ptr, i64 0 @@ -283,7 +382,10 @@ } define void @bitcast(i32* %arg) { -; ATTRIBUTOR-LABEL: @bitcast(i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) %arg) +; CHECK-LABEL: define {{[^@]+}}@bitcast +; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(8) [[ARG:%.*]]) +; CHECK-NEXT: ret void +; %ptr = bitcast i32* %arg to float* %arrayidx0 = getelementptr float, float* %ptr, i64 0 %arrayidx1 = getelementptr float, float* %ptr, i64 1 @@ -293,7 +395,10 @@ } define void @bitcast_different_sizes(double* %arg1, i8* %arg2) { -; ATTRIBUTOR-LABEL: @bitcast_different_sizes(double* nocapture nofree nonnull readnone align 4 dereferenceable(12) %arg1, i8* nocapture nofree nonnull readnone align 4 dereferenceable(16) %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 +; %ptr1 = bitcast double* %arg1 to float* %a10 = getelementptr float, float* %ptr1, i64 0 %a11 = getelementptr float, float* %ptr1, i64 1 @@ -311,7 +416,10 @@ } define void @negative_offset(i32* %arg) { -; ATTRIBUTOR-LABEL: @negative_offset(i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) %arg) +; CHECK-LABEL: define {{[^@]+}}@negative_offset +; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[ARG:%.*]]) +; CHECK-NEXT: ret void +; %ptr = bitcast i32* %arg to float* %arrayidx0 = getelementptr float, float* %ptr, i64 0 %arrayidx1 = getelementptr float, float* %ptr, i64 -1 @@ -321,7 +429,15 @@ } define void @stores(i32* %arg) { -; ATTRIBUTOR-LABEL: @stores(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) %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 +; %ptr = bitcast i32* %arg to float* %arrayidx0 = getelementptr float, float* %ptr, i64 0 %arrayidx1 = getelementptr float, float* %ptr, i64 1 @@ -331,7 +447,13 @@ } define void @load_store(i32* %arg) { -; ATTRIBUTOR-LABEL: @load_store(i32* nocapture nofree nonnull writeonly align 4 dereferenceable(8) %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 +; %ptr = bitcast i32* %arg to float* %arrayidx0 = getelementptr float, float* %ptr, i64 0 %arrayidx1 = getelementptr float, float* %ptr, i64 1 @@ -341,7 +463,13 @@ } define void @different_size1(i32* %arg) { -; ATTRIBUTOR-LABEL: @different_size1(i32* nocapture nofree nonnull writeonly align 8 dereferenceable(8) %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 +; %arg-cast = bitcast i32* %arg to double* store double 0.000000e+00, double* %arg-cast store i32 0, i32* %arg @@ -349,7 +477,13 @@ } define void @different_size2(i32* %arg) { -; ATTRIBUTOR-LABEL: @different_size2(i32* nocapture nofree nonnull writeonly align 8 dereferenceable(8) %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 +; store i32 0, i32* %arg %arg-cast = bitcast i32* %arg to double* store double 0.000000e+00, double* %arg-cast @@ -375,12 +509,63 @@ ; ; 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]] +; IS________OPM-NEXT: br label [[END:%.*]] +; IS________OPM: l7: +; IS________OPM-NEXT: store i32 1, i32* [[P]] +; 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 +; %tobool1 = icmp eq i32 %c, 0 br i1 %tobool1, label %l1, label %l2 -l1: +l1: %tobool2 = icmp eq i32 %c, 1 br i1 %tobool2, label %l3, label %l4 -l2: +l2: %tobool3 = icmp eq i32 %c, 2 br i1 %tobool3, label %l3, label %l4 l3: 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,8 @@ -; RUN: opt -passes=attributor --attributor-disable=false -attributor-annotate-decl-cs -S < %s | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 declare noalias i8* @malloc(i64) @@ -24,8 +28,13 @@ declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) nounwind -; CHECK: @nofree_arg_only(i8* nocapture nofree %p1, i8* nocapture %p2) define void @nofree_arg_only(i8* %p1, i8* %p2) { +; CHECK-LABEL: define {{[^@]+}}@nofree_arg_only +; CHECK-SAME: (i8* nocapture nofree [[P1:%.*]], i8* nocapture [[P2:%.*]]) +; CHECK-NEXT: tail call void @free(i8* nocapture [[P2]]) +; CHECK-NEXT: tail call void @nofree_func(i8* nocapture nofree [[P1]]) +; CHECK-NEXT: ret void +; tail call void @free(i8* %p2) tail call void @nofree_func(i8* %p1) ret void @@ -34,9 +43,21 @@ ; TEST 1 - negative, pointer freed in another function. define void @test1() { +; IS________OPM-LABEL: define {{[^@]+}}@test1() +; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) +; IS________OPM-NEXT: tail call void @nocapture_func_frees_pointer(i8* noalias [[TMP1]]) +; IS________OPM-NEXT: tail call void (...) @func_throws() +; IS________OPM-NEXT: tail call void @free(i8* noalias [[TMP1]]) +; IS________OPM-NEXT: ret void +; +; IS________NPM-LABEL: define {{[^@]+}}@test1() +; IS________NPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) +; IS________NPM-NEXT: tail call void @nocapture_func_frees_pointer(i8* noalias nocapture [[TMP1]]) +; IS________NPM-NEXT: tail call void (...) @func_throws() +; IS________NPM-NEXT: tail call void @free(i8* noalias [[TMP1]]) +; IS________NPM-NEXT: ret void +; %1 = tail call noalias i8* @malloc(i64 4) - ; CHECK: @malloc(i64 4) - ; CHECK-NEXT: @nocapture_func_frees_pointer(i8* noalias nocapture %1) tail call void @nocapture_func_frees_pointer(i8* %1) tail call void (...) @func_throws() tail call void @free(i8* %1) @@ -46,9 +67,13 @@ ; TEST 2 - negative, call to a sync function. define void @test2() { +; CHECK-LABEL: define {{[^@]+}}@test2() +; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) +; CHECK-NEXT: tail call void @sync_func(i8* [[TMP1]]) +; CHECK-NEXT: tail call void @free(i8* [[TMP1]]) +; CHECK-NEXT: ret void +; %1 = tail call noalias i8* @malloc(i64 4) - ; CHECK: @malloc(i64 4) - ; CHECK-NEXT: @sync_func(i8* %1) tail call void @sync_func(i8* %1) tail call void @free(i8* %1) ret void @@ -57,21 +82,46 @@ ; TEST 3 - 1 malloc, 1 free define void @test3() { +; IS________OPM-LABEL: define {{[^@]+}}@test3() +; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) +; IS________OPM-NEXT: tail call void @no_sync_func(i8* noalias nofree [[TMP1]]) +; IS________OPM-NEXT: tail call void @free(i8* noalias [[TMP1]]) +; IS________OPM-NEXT: ret void +; +; IS________NPM-LABEL: define {{[^@]+}}@test3() +; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4 +; IS________NPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) +; IS________NPM-NEXT: ret void +; %1 = tail call noalias i8* @malloc(i64 4) - ; CHECK: %1 = alloca i8, i64 4 - ; CHECK-NEXT: @no_sync_func(i8* noalias nocapture nofree %1) tail call void @no_sync_func(i8* %1) - ; CHECK-NOT: @free(i8* %1) tail call void @free(i8* %1) ret void } define void @test3a(i8* %p) { +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test3a +; IS__TUNIT_OPM-SAME: (i8* nocapture [[P:%.*]]) +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) +; IS__TUNIT_OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree [[TMP1]], i8* nocapture [[P]]) +; IS__TUNIT_OPM-NEXT: tail call void @free(i8* noalias [[TMP1]]) +; IS__TUNIT_OPM-NEXT: ret void +; +; IS________NPM-LABEL: define {{[^@]+}}@test3a +; IS________NPM-SAME: (i8* nocapture [[P:%.*]]) +; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4 +; IS________NPM-NEXT: tail call void @nofree_arg_only(i8* noalias nocapture nofree [[TMP1]], i8* nocapture [[P]]) +; IS________NPM-NEXT: ret void +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test3a +; IS__CGSCC_OPM-SAME: (i8* nocapture [[P:%.*]]) +; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) +; IS__CGSCC_OPM-NEXT: tail call void @nofree_arg_only(i8* nofree [[TMP1]], i8* nocapture [[P]]) +; IS__CGSCC_OPM-NEXT: tail call void @free(i8* noalias [[TMP1]]) +; IS__CGSCC_OPM-NEXT: ret void +; %1 = tail call noalias i8* @malloc(i64 4) - ; CHECK: %1 = alloca i8, i64 4 - ; CHECK-NEXT: tail call void @nofree_arg_only tail call void @nofree_arg_only(i8* %1, i8* %p) - ; CHECK-NOT: @free(i8* %1) tail call void @free(i8* %1) ret void } @@ -79,19 +129,41 @@ declare noalias i8* @aligned_alloc(i64, i64) define void @test3b(i8* %p) { +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test3b +; IS__TUNIT_OPM-SAME: (i8* nocapture [[P:%.*]]) +; IS__TUNIT_OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 32, i64 128) +; IS__TUNIT_OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree [[TMP1]], i8* nocapture [[P]]) +; IS__TUNIT_OPM-NEXT: tail call void @free(i8* noalias [[TMP1]]) +; IS__TUNIT_OPM-NEXT: ret void +; +; IS________NPM-LABEL: define {{[^@]+}}@test3b +; IS________NPM-SAME: (i8* nocapture [[P:%.*]]) +; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 128, align 32 +; IS________NPM-NEXT: tail call void @nofree_arg_only(i8* noalias nocapture nofree [[TMP1]], i8* nocapture [[P]]) +; IS________NPM-NEXT: ret void +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test3b +; IS__CGSCC_OPM-SAME: (i8* nocapture [[P:%.*]]) +; IS__CGSCC_OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 32, i64 128) +; IS__CGSCC_OPM-NEXT: tail call void @nofree_arg_only(i8* nofree [[TMP1]], i8* nocapture [[P]]) +; IS__CGSCC_OPM-NEXT: tail call void @free(i8* noalias [[TMP1]]) +; IS__CGSCC_OPM-NEXT: ret void +; %1 = tail call noalias i8* @aligned_alloc(i64 32, i64 128) - ; CHECK: %1 = alloca i8, i64 128, align 32 - ; CHECK-NEXT: tail call void @nofree_arg_only tail call void @nofree_arg_only(i8* %1, i8* %p) - ; CHECK-NOT: @free(i8* %1) tail call void @free(i8* %1) ret void } ; leave alone non-constant alignments. define void @test3c(i64 %alignment) { +; CHECK-LABEL: define {{[^@]+}}@test3c +; CHECK-SAME: (i64 [[ALIGNMENT:%.*]]) +; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @aligned_alloc(i64 [[ALIGNMENT]], i64 128) +; CHECK-NEXT: tail call void @free(i8* noalias [[TMP1]]) +; CHECK-NEXT: ret void +; %1 = tail call noalias i8* @aligned_alloc(i64 %alignment, i64 128) - ; CHECK: tail call noalias i8* @aligned_alloc tail call void @free(i8* %1) ret void } @@ -99,22 +171,38 @@ declare noalias i8* @calloc(i64, i64) define void @test0() { +; IS________OPM-LABEL: define {{[^@]+}}@test0() +; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 2, i64 4) +; IS________OPM-NEXT: tail call void @no_sync_func(i8* noalias nofree [[TMP1]]) +; IS________OPM-NEXT: tail call void @free(i8* noalias [[TMP1]]) +; IS________OPM-NEXT: ret void +; +; IS________NPM-LABEL: define {{[^@]+}}@test0() +; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 8 +; IS________NPM-NEXT: [[CALLOC_BC:%.*]] = bitcast i8* [[TMP1]] to i8* +; IS________NPM-NEXT: call void @llvm.memset.p0i8.i64(i8* [[CALLOC_BC]], i8 0, i64 8, i1 false) +; IS________NPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) +; IS________NPM-NEXT: ret void +; %1 = tail call noalias i8* @calloc(i64 2, i64 4) - ; CHECK: %1 = alloca i8, i64 8 - ; CHECK-NEXT: %calloc_bc = bitcast i8* %1 to i8* - ; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* %calloc_bc, i8 0, i64 8, i1 false) - ; CHECK-NEXT: @no_sync_func(i8* noalias nocapture nofree %1) tail call void @no_sync_func(i8* %1) - ; CHECK-NOT: @free(i8* %1) tail call void @free(i8* %1) ret void } ; TEST 4 define void @test4() { +; IS________OPM-LABEL: define {{[^@]+}}@test4() +; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) +; IS________OPM-NEXT: tail call void @nofree_func(i8* noalias nofree [[TMP1]]) +; IS________OPM-NEXT: ret void +; +; IS________NPM-LABEL: define {{[^@]+}}@test4() +; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4 +; IS________NPM-NEXT: tail call void @nofree_func(i8* noalias nocapture nofree [[TMP1]]) +; IS________NPM-NEXT: ret void +; %1 = tail call noalias i8* @malloc(i64 4) - ; CHECK: %1 = alloca i8, i64 4 - ; CHECK-NEXT: @nofree_func(i8* noalias nocapture nofree %1) tail call void @nofree_func(i8* %1) ret void } @@ -123,9 +211,51 @@ ; are in nofree functions and are not captured define void @test5(i32, i8* %p) { +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@test5 +; IS__TUNIT_OPM-SAME: (i32 [[TMP0:%.*]], i8* nocapture [[P:%.*]]) +; IS__TUNIT_OPM-NEXT: [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 4) +; IS__TUNIT_OPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0 +; IS__TUNIT_OPM-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]] +; IS__TUNIT_OPM: 4: +; IS__TUNIT_OPM-NEXT: tail call void @nofree_func(i8* noalias nofree [[TMP2]]) +; IS__TUNIT_OPM-NEXT: br label [[TMP6:%.*]] +; IS__TUNIT_OPM: 5: +; IS__TUNIT_OPM-NEXT: tail call void @nofree_arg_only(i8* nocapture nofree [[TMP2]], i8* nocapture [[P]]) +; IS__TUNIT_OPM-NEXT: tail call void @free(i8* noalias [[TMP2]]) +; IS__TUNIT_OPM-NEXT: br label [[TMP6]] +; IS__TUNIT_OPM: 6: +; IS__TUNIT_OPM-NEXT: ret void +; +; IS________NPM-LABEL: define {{[^@]+}}@test5 +; IS________NPM-SAME: (i32 [[TMP0:%.*]], i8* nocapture [[P:%.*]]) +; IS________NPM-NEXT: [[TMP2:%.*]] = alloca i8, i64 4 +; IS________NPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0 +; IS________NPM-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]] +; IS________NPM: 4: +; IS________NPM-NEXT: tail call void @nofree_func(i8* noalias nocapture nofree [[TMP2]]) +; IS________NPM-NEXT: br label [[TMP6:%.*]] +; IS________NPM: 5: +; IS________NPM-NEXT: tail call void @nofree_arg_only(i8* noalias nocapture nofree [[TMP2]], i8* nocapture [[P]]) +; IS________NPM-NEXT: br label [[TMP6]] +; IS________NPM: 6: +; IS________NPM-NEXT: ret void +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@test5 +; IS__CGSCC_OPM-SAME: (i32 [[TMP0:%.*]], i8* nocapture [[P:%.*]]) +; IS__CGSCC_OPM-NEXT: [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 4) +; IS__CGSCC_OPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0 +; IS__CGSCC_OPM-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]] +; IS__CGSCC_OPM: 4: +; IS__CGSCC_OPM-NEXT: tail call void @nofree_func(i8* noalias nofree [[TMP2]]) +; IS__CGSCC_OPM-NEXT: br label [[TMP6:%.*]] +; IS__CGSCC_OPM: 5: +; IS__CGSCC_OPM-NEXT: tail call void @nofree_arg_only(i8* nofree [[TMP2]], i8* nocapture [[P]]) +; IS__CGSCC_OPM-NEXT: tail call void @free(i8* noalias [[TMP2]]) +; IS__CGSCC_OPM-NEXT: br label [[TMP6]] +; IS__CGSCC_OPM: 6: +; IS__CGSCC_OPM-NEXT: ret void +; %2 = tail call noalias i8* @malloc(i64 4) - ; CHECK: %2 = alloca i8, i64 4 - ; CHECK-NEXT: icmp eq i32 %0, 0 %3 = icmp eq i32 %0, 0 br i1 %3, label %5, label %4 @@ -136,7 +266,6 @@ 5: ; preds = %1 tail call void @nofree_arg_only(i8* %2, i8* %p) tail call void @free(i8* %2) - ; CHECK-NOT: @free(i8* %2) br label %6 6: ; preds = %5, %4 @@ -146,21 +275,45 @@ ; TEST 6 - all exit paths have a call to free define void @test6(i32) { +; IS________OPM-LABEL: define {{[^@]+}}@test6 +; IS________OPM-SAME: (i32 [[TMP0:%.*]]) +; IS________OPM-NEXT: [[TMP2:%.*]] = tail call noalias i8* @malloc(i64 4) +; IS________OPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0 +; IS________OPM-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]] +; IS________OPM: 4: +; IS________OPM-NEXT: tail call void @nofree_func(i8* noalias nofree [[TMP2]]) +; IS________OPM-NEXT: tail call void @free(i8* noalias [[TMP2]]) +; IS________OPM-NEXT: br label [[TMP6:%.*]] +; IS________OPM: 5: +; IS________OPM-NEXT: tail call void @free(i8* noalias [[TMP2]]) +; IS________OPM-NEXT: br label [[TMP6]] +; IS________OPM: 6: +; IS________OPM-NEXT: ret void +; +; IS________NPM-LABEL: define {{[^@]+}}@test6 +; IS________NPM-SAME: (i32 [[TMP0:%.*]]) +; IS________NPM-NEXT: [[TMP2:%.*]] = alloca i8, i64 4 +; IS________NPM-NEXT: [[TMP3:%.*]] = icmp eq i32 [[TMP0]], 0 +; IS________NPM-NEXT: br i1 [[TMP3]], label [[TMP5:%.*]], label [[TMP4:%.*]] +; IS________NPM: 4: +; IS________NPM-NEXT: tail call void @nofree_func(i8* noalias nocapture nofree [[TMP2]]) +; IS________NPM-NEXT: br label [[TMP6:%.*]] +; IS________NPM: 5: +; IS________NPM-NEXT: br label [[TMP6]] +; IS________NPM: 6: +; IS________NPM-NEXT: ret void +; %2 = tail call noalias i8* @malloc(i64 4) - ; CHECK: %2 = alloca i8, i64 4 - ; CHECK-NEXT: icmp eq i32 %0, 0 %3 = icmp eq i32 %0, 0 br i1 %3, label %5, label %4 4: ; preds = %1 tail call void @nofree_func(i8* %2) tail call void @free(i8* %2) - ; CHECK-NOT: @free(i8* %2) br label %6 5: ; preds = %1 tail call void @free(i8* %2) - ; CHECK-NOT: @free(i8* %2) br label %6 6: ; preds = %5, %4 @@ -170,11 +323,18 @@ ; TEST 7 - free is dead. define void @test7() { +; 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-LABEL: define {{[^@]+}}@test7() +; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4 +; IS________NPM-NEXT: [[TMP2:%.*]] = tail call i32 @no_return_call() +; IS________NPM-NEXT: unreachable +; %1 = tail call noalias i8* @malloc(i64 4) - ; CHECK: alloca i8, i64 4 - ; CHECK-NEXT: tail call i32 @no_return_call() tail call i32 @no_return_call() - ; CHECK-NOT: @free(i8* %1) tail call void @free(i8* %1) ret void } @@ -182,30 +342,42 @@ ; TEST 8 - Negative: bitcast pointer used in capture function define void @test8() { +; CHECK-LABEL: define {{[^@]+}}@test8() +; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) +; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) +; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 +; CHECK-NEXT: tail call void @foo(i32* align 4 [[TMP2]]) +; CHECK-NEXT: tail call void @free(i8* nonnull align 4 dereferenceable(4) [[TMP1]]) +; CHECK-NEXT: ret void +; %1 = tail call noalias i8* @malloc(i64 4) - ; CHECK: %1 = tail call noalias i8* @malloc(i64 4) - ; CHECK-NEXT: @no_sync_func(i8* noalias nocapture nofree %1) tail call void @no_sync_func(i8* %1) %2 = bitcast i8* %1 to i32* store i32 10, i32* %2 %3 = load i32, i32* %2 tail call void @foo(i32* %2) - ; CHECK: @free(i8* nonnull align 4 dereferenceable(4) %1) tail call void @free(i8* %1) ret void } ; TEST 9 - FIXME: malloc should be converted. define void @test9() { +; CHECK-LABEL: define {{[^@]+}}@test9() +; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) +; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) +; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 +; CHECK-NEXT: tail call void @foo_nounw(i32* nofree align 4 [[TMP2]]) +; CHECK-NEXT: tail call void @free(i8* nonnull align 4 dereferenceable(4) [[TMP1]]) +; CHECK-NEXT: ret void +; %1 = tail call noalias i8* @malloc(i64 4) - ; CHECK: %1 = tail call noalias i8* @malloc(i64 4) - ; CHECK-NEXT: @no_sync_func(i8* noalias nocapture nofree %1) tail call void @no_sync_func(i8* %1) %2 = bitcast i8* %1 to i32* store i32 10, i32* %2 %3 = load i32, i32* %2 tail call void @foo_nounw(i32* %2) - ; CHECK: @free(i8* nonnull align 4 dereferenceable(4) %1) tail call void @free(i8* %1) ret void } @@ -213,28 +385,58 @@ ; TEST 10 - 1 malloc, 1 free define i32 @test10() { +; IS________OPM-LABEL: define {{[^@]+}}@test10() +; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) +; IS________OPM-NEXT: tail call void @no_sync_func(i8* noalias nofree [[TMP1]]) +; IS________OPM-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +; IS________OPM-NEXT: store i32 10, i32* [[TMP2]], align 4 +; IS________OPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 +; IS________OPM-NEXT: tail call void @free(i8* noalias nonnull align 4 dereferenceable(4) [[TMP1]]) +; IS________OPM-NEXT: ret i32 [[TMP3]] +; +; IS________NPM-LABEL: define {{[^@]+}}@test10() +; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4 +; IS________NPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) +; IS________NPM-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +; IS________NPM-NEXT: store i32 10, i32* [[TMP2]], align 4 +; IS________NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 +; IS________NPM-NEXT: ret i32 [[TMP3]] +; %1 = tail call noalias i8* @malloc(i64 4) - ; CHECK: %1 = alloca i8, i64 4 - ; CHECK-NEXT: @no_sync_func(i8* noalias nocapture nofree %1) tail call void @no_sync_func(i8* %1) %2 = bitcast i8* %1 to i32* store i32 10, i32* %2 %3 = load i32, i32* %2 - ; CHECK-NOT: @free(i8* %1) tail call void @free(i8* %1) ret i32 %3 } define i32 @test_lifetime() { +; IS________OPM-LABEL: define {{[^@]+}}@test_lifetime() +; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) +; IS________OPM-NEXT: tail call void @no_sync_func(i8* noalias nofree [[TMP1]]) +; IS________OPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* noalias nonnull align 4 dereferenceable(4) [[TMP1]]) +; IS________OPM-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +; IS________OPM-NEXT: store i32 10, i32* [[TMP2]], align 4 +; IS________OPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 +; IS________OPM-NEXT: tail call void @free(i8* noalias nonnull align 4 dereferenceable(4) [[TMP1]]) +; IS________OPM-NEXT: ret i32 [[TMP3]] +; +; IS________NPM-LABEL: define {{[^@]+}}@test_lifetime() +; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4 +; IS________NPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree [[TMP1]]) +; IS________NPM-NEXT: call void @llvm.lifetime.start.p0i8(i64 4, i8* noalias nonnull align 4 dereferenceable(4) [[TMP1]]) +; IS________NPM-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +; IS________NPM-NEXT: store i32 10, i32* [[TMP2]], align 4 +; IS________NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 +; IS________NPM-NEXT: ret i32 [[TMP3]] +; %1 = tail call noalias i8* @malloc(i64 4) - ; CHECK: %1 = alloca i8, i64 4 - ; CHECK-NEXT: @no_sync_func(i8* noalias nocapture nofree %1) tail call void @no_sync_func(i8* %1) call void @llvm.lifetime.start.p0i8(i64 4, i8* %1) %2 = bitcast i8* %1 to i32* store i32 10, i32* %2 %3 = load i32, i32* %2 - ; CHECK-NOT: @free(i8* %1) tail call void @free(i8* %1) ret i32 %3 } @@ -242,10 +444,18 @@ ; TEST 11 define void @test11() { +; IS________OPM-LABEL: define {{[^@]+}}@test11() +; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) +; IS________OPM-NEXT: tail call void @sync_will_return(i8* [[TMP1]]) +; IS________OPM-NEXT: tail call void @free(i8* [[TMP1]]) +; IS________OPM-NEXT: ret void +; +; IS________NPM-LABEL: define {{[^@]+}}@test11() +; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4 +; IS________NPM-NEXT: tail call void @sync_will_return(i8* [[TMP1]]) +; IS________NPM-NEXT: ret void +; %1 = tail call noalias i8* @malloc(i64 4) - ; CHECK: test11 - ; CHECK-NEXT: alloc - ; CHECK-NEXT: @sync_will_return(i8* %1) tail call void @sync_will_return(i8* %1) tail call void @free(i8* %1) ret void @@ -253,8 +463,67 @@ ; TEST 12 define i32 @irreducible_cfg(i32 %0) { - ; CHECK: alloca i8, i64 4 - ; CHECK-NEXT: %3 = bitcast +; IS________OPM-LABEL: define {{[^@]+}}@irreducible_cfg +; IS________OPM-SAME: (i32 [[TMP0:%.*]]) +; IS________OPM-NEXT: [[TMP2:%.*]] = call noalias i8* @malloc(i64 4) +; IS________OPM-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP2]] to i32* +; IS________OPM-NEXT: store i32 10, i32* [[TMP3]], align 4 +; IS________OPM-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0]], 1 +; IS________OPM-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP7:%.*]] +; IS________OPM: 5: +; IS________OPM-NEXT: [[TMP6:%.*]] = add nsw i32 [[TMP0]], 5 +; IS________OPM-NEXT: br label [[TMP13:%.*]] +; IS________OPM: 7: +; IS________OPM-NEXT: br label [[TMP8:%.*]] +; IS________OPM: 8: +; IS________OPM-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP14:%.*]], [[TMP13]] ], [ 1, [[TMP7]] ] +; IS________OPM-NEXT: [[TMP9:%.*]] = load i32, i32* [[TMP3]], align 4 +; IS________OPM-NEXT: [[TMP10:%.*]] = add nsw i32 [[TMP9]], -1 +; IS________OPM-NEXT: store i32 [[TMP10]], i32* [[TMP3]], align 4 +; IS________OPM-NEXT: [[TMP11:%.*]] = icmp ne i32 [[TMP9]], 0 +; IS________OPM-NEXT: br i1 [[TMP11]], label [[TMP12:%.*]], label [[TMP15:%.*]] +; IS________OPM: 12: +; IS________OPM-NEXT: br label [[TMP13]] +; IS________OPM: 13: +; IS________OPM-NEXT: [[DOT1:%.*]] = phi i32 [ [[TMP6]], [[TMP5]] ], [ [[DOT0]], [[TMP12]] ] +; IS________OPM-NEXT: [[TMP14]] = add nsw i32 [[DOT1]], 1 +; IS________OPM-NEXT: br label [[TMP8]] +; IS________OPM: 15: +; IS________OPM-NEXT: [[TMP16:%.*]] = bitcast i32* [[TMP3]] to i8* +; IS________OPM-NEXT: call void @free(i8* [[TMP16]]) +; IS________OPM-NEXT: [[TMP17:%.*]] = load i32, i32* [[TMP3]], align 4 +; IS________OPM-NEXT: ret i32 [[TMP17]] +; +; IS________NPM-LABEL: define {{[^@]+}}@irreducible_cfg +; IS________NPM-SAME: (i32 [[TMP0:%.*]]) +; IS________NPM-NEXT: [[TMP2:%.*]] = alloca i8, i64 4 +; IS________NPM-NEXT: [[TMP3:%.*]] = bitcast i8* [[TMP2]] to i32* +; IS________NPM-NEXT: store i32 10, i32* [[TMP3]], align 4 +; IS________NPM-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP0]], 1 +; IS________NPM-NEXT: br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP7:%.*]] +; IS________NPM: 5: +; IS________NPM-NEXT: [[TMP6:%.*]] = add nsw i32 [[TMP0]], 5 +; IS________NPM-NEXT: br label [[TMP13:%.*]] +; IS________NPM: 7: +; IS________NPM-NEXT: br label [[TMP8:%.*]] +; IS________NPM: 8: +; IS________NPM-NEXT: [[DOT0:%.*]] = phi i32 [ [[TMP14:%.*]], [[TMP13]] ], [ 1, [[TMP7]] ] +; IS________NPM-NEXT: [[TMP9:%.*]] = load i32, i32* [[TMP3]], align 4 +; IS________NPM-NEXT: [[TMP10:%.*]] = add nsw i32 [[TMP9]], -1 +; IS________NPM-NEXT: store i32 [[TMP10]], i32* [[TMP3]], align 4 +; IS________NPM-NEXT: [[TMP11:%.*]] = icmp ne i32 [[TMP9]], 0 +; IS________NPM-NEXT: br i1 [[TMP11]], label [[TMP12:%.*]], label [[TMP15:%.*]] +; IS________NPM: 12: +; IS________NPM-NEXT: br label [[TMP13]] +; IS________NPM: 13: +; IS________NPM-NEXT: [[DOT1:%.*]] = phi i32 [ [[TMP6]], [[TMP5]] ], [ [[DOT0]], [[TMP12]] ] +; IS________NPM-NEXT: [[TMP14]] = add nsw i32 [[DOT1]], 1 +; IS________NPM-NEXT: br label [[TMP8]] +; IS________NPM: 15: +; IS________NPM-NEXT: [[TMP16:%.*]] = bitcast i32* [[TMP3]] to i8* +; IS________NPM-NEXT: [[TMP17:%.*]] = load i32, i32* [[TMP3]], align 4 +; IS________NPM-NEXT: ret i32 [[TMP17]] +; %2 = call noalias i8* @malloc(i64 4) %3 = bitcast i8* %2 to i32* store i32 10, i32* %3, align 4 @@ -294,6 +563,46 @@ define i32 @malloc_in_loop(i32 %0) { +; IS________OPM-LABEL: define {{[^@]+}}@malloc_in_loop +; IS________OPM-SAME: (i32 [[TMP0:%.*]]) +; IS________OPM-NEXT: [[TMP2:%.*]] = alloca i32, align 4 +; IS________OPM-NEXT: [[TMP3:%.*]] = alloca i32*, align 8 +; IS________OPM-NEXT: store i32 [[TMP0]], i32* [[TMP2]], align 4 +; IS________OPM-NEXT: br label [[TMP4:%.*]] +; IS________OPM: 4: +; IS________OPM-NEXT: [[TMP5:%.*]] = load i32, i32* [[TMP2]], align 4 +; IS________OPM-NEXT: [[TMP6:%.*]] = add nsw i32 [[TMP5]], -1 +; IS________OPM-NEXT: store i32 [[TMP6]], i32* [[TMP2]], align 4 +; IS________OPM-NEXT: [[TMP7:%.*]] = icmp sgt i32 [[TMP6]], 0 +; IS________OPM-NEXT: br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP11:%.*]] +; IS________OPM: 8: +; IS________OPM-NEXT: [[TMP9:%.*]] = call noalias i8* @malloc(i64 4) +; IS________OPM-NEXT: [[TMP10:%.*]] = bitcast i8* [[TMP9]] to i32* +; IS________OPM-NEXT: store i32 1, i32* [[TMP10]], align 8 +; IS________OPM-NEXT: br label [[TMP4]] +; IS________OPM: 11: +; IS________OPM-NEXT: ret i32 5 +; +; IS________NPM-LABEL: define {{[^@]+}}@malloc_in_loop +; IS________NPM-SAME: (i32 [[TMP0:%.*]]) +; IS________NPM-NEXT: [[TMP2:%.*]] = alloca i32, align 4 +; IS________NPM-NEXT: [[TMP3:%.*]] = alloca i32*, align 8 +; IS________NPM-NEXT: store i32 [[TMP0]], i32* [[TMP2]], align 4 +; IS________NPM-NEXT: br label [[TMP4:%.*]] +; IS________NPM: 4: +; IS________NPM-NEXT: [[TMP5:%.*]] = load i32, i32* [[TMP2]], align 4 +; IS________NPM-NEXT: [[TMP6:%.*]] = add nsw i32 [[TMP5]], -1 +; IS________NPM-NEXT: store i32 [[TMP6]], i32* [[TMP2]], align 4 +; IS________NPM-NEXT: [[TMP7:%.*]] = icmp sgt i32 [[TMP6]], 0 +; IS________NPM-NEXT: br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP11:%.*]] +; IS________NPM: 8: +; IS________NPM-NEXT: [[TMP9:%.*]] = alloca i8, i64 4 +; IS________NPM-NEXT: [[TMP10:%.*]] = bitcast i8* [[TMP9]] to i32* +; IS________NPM-NEXT: store i32 1, i32* [[TMP10]], align 8 +; IS________NPM-NEXT: br label [[TMP4]] +; IS________NPM: 11: +; IS________NPM-NEXT: ret i32 5 +; %2 = alloca i32, align 4 %3 = alloca i32*, align 8 store i32 %0, i32* %2, align 4 @@ -308,7 +617,6 @@ 8: ; preds = %4 %9 = call noalias i8* @malloc(i64 4) - ; CHECK: alloca i8, i64 4 %10 = bitcast i8* %9 to i32* store i32 1, i32* %10, align 8 br label %4 @@ -319,104 +627,167 @@ ; Malloc/Calloc too large define i32 @test13() { +; CHECK-LABEL: define {{[^@]+}}@test13() +; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 256) +; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nofree [[TMP1]]) +; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 +; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 +; CHECK-NEXT: tail call void @free(i8* noalias nonnull align 4 dereferenceable(4) [[TMP1]]) +; CHECK-NEXT: ret i32 [[TMP3]] +; %1 = tail call noalias i8* @malloc(i64 256) - ; CHECK: %1 = tail call noalias i8* @malloc(i64 256) - ; CHECK-NEXT: @no_sync_func(i8* noalias nofree %1) tail call void @no_sync_func(i8* %1) %2 = bitcast i8* %1 to i32* store i32 10, i32* %2 %3 = load i32, i32* %2 tail call void @free(i8* %1) - ; CHECK: tail call void @free(i8* noalias nonnull align 4 dereferenceable(4) %1) ret i32 %3 } define i32 @test_sle() { +; CHECK-LABEL: define {{[^@]+}}@test_sle() +; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 -1) +; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nofree [[TMP1]]) +; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 +; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 +; CHECK-NEXT: tail call void @free(i8* noalias nonnull align 4 dereferenceable(4) [[TMP1]]) +; CHECK-NEXT: ret i32 [[TMP3]] +; %1 = tail call noalias i8* @malloc(i64 -1) - ; CHECK: %1 = tail call noalias i8* @malloc(i64 -1) - ; CHECK-NEXT: @no_sync_func(i8* noalias nofree %1) tail call void @no_sync_func(i8* %1) %2 = bitcast i8* %1 to i32* store i32 10, i32* %2 %3 = load i32, i32* %2 tail call void @free(i8* %1) - ; CHECK: tail call void @free(i8* noalias nonnull align 4 dereferenceable(4) %1) ret i32 %3 } define i32 @test_overflow() { +; CHECK-LABEL: define {{[^@]+}}@test_overflow() +; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 65537, i64 65537) +; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nofree [[TMP1]]) +; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +; CHECK-NEXT: store i32 10, i32* [[TMP2]], align 4 +; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4 +; CHECK-NEXT: tail call void @free(i8* noalias nonnull align 4 dereferenceable(4) [[TMP1]]) +; CHECK-NEXT: ret i32 [[TMP3]] +; %1 = tail call noalias i8* @calloc(i64 65537, i64 65537) - ; CHECK: %1 = tail call noalias i8* @calloc(i64 65537, i64 65537) - ; CHECK-NEXT: @no_sync_func(i8* noalias nofree %1) tail call void @no_sync_func(i8* %1) %2 = bitcast i8* %1 to i32* store i32 10, i32* %2 %3 = load i32, i32* %2 tail call void @free(i8* %1) - ; CHECK: tail call void @free(i8* noalias nonnull align 4 dereferenceable(4) %1) ret i32 %3 } define void @test14() { +; CHECK-LABEL: define {{[^@]+}}@test14() +; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @calloc(i64 64, i64 4) +; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nofree [[TMP1]]) +; CHECK-NEXT: tail call void @free(i8* noalias [[TMP1]]) +; CHECK-NEXT: ret void +; %1 = tail call noalias i8* @calloc(i64 64, i64 4) - ; CHECK: %1 = tail call noalias i8* @calloc(i64 64, i64 4) - ; CHECK-NEXT: @no_sync_func(i8* noalias nofree %1) tail call void @no_sync_func(i8* %1) tail call void @free(i8* %1) - ; CHECK: tail call void @free(i8* noalias %1) ret void } define void @test15(i64 %S) { - ; CHECK: %1 = tail call noalias i8* @malloc(i64 %S) +; CHECK-LABEL: define {{[^@]+}}@test15 +; CHECK-SAME: (i64 [[S:%.*]]) +; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 [[S]]) +; CHECK-NEXT: tail call void @no_sync_func(i8* noalias nofree [[TMP1]]) +; CHECK-NEXT: tail call void @free(i8* noalias [[TMP1]]) +; CHECK-NEXT: ret void +; %1 = tail call noalias i8* @malloc(i64 %S) - ; CHECK-NEXT: @no_sync_func(i8* noalias nofree %1) tail call void @no_sync_func(i8* %1) - ; CHECK-NEXT: @free(i8* noalias %1) tail call void @free(i8* %1) ret void } define void @test16a(i8 %v, i8** %P) { - ; CHECK: %1 = alloca +; IS________OPM-LABEL: define {{[^@]+}}@test16a +; IS________OPM-SAME: (i8 [[V:%.*]], i8** nocapture nofree readnone [[P:%.*]]) +; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) +; IS________OPM-NEXT: store i8 [[V]], i8* [[TMP1]] +; IS________OPM-NEXT: tail call void @no_sync_func(i8* noalias nofree nonnull dereferenceable(1) [[TMP1]]) +; IS________OPM-NEXT: tail call void @free(i8* noalias nonnull dereferenceable(1) [[TMP1]]) +; IS________OPM-NEXT: ret void +; +; IS________NPM-LABEL: define {{[^@]+}}@test16a +; IS________NPM-SAME: (i8 [[V:%.*]], i8** nocapture nofree readnone [[P:%.*]]) +; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4 +; IS________NPM-NEXT: store i8 [[V]], i8* [[TMP1]] +; IS________NPM-NEXT: tail call void @no_sync_func(i8* noalias nocapture nofree nonnull dereferenceable(1) [[TMP1]]) +; IS________NPM-NEXT: ret void +; %1 = tail call noalias i8* @malloc(i64 4) - ; CHECK-NEXT: store i8 %v, i8* %1 store i8 %v, i8* %1 - ; CHECK-NEXT: @no_sync_func(i8* noalias nocapture nofree nonnull dereferenceable(1) %1) tail call void @no_sync_func(i8* %1) - ; CHECK-NOT: @free(i8* %1) tail call void @free(i8* nonnull dereferenceable(1) %1) ret void } define void @test16b(i8 %v, i8** %P) { - ; CHECK: %1 = tail call noalias i8* @malloc(i64 4) +; IS________OPM-LABEL: define {{[^@]+}}@test16b +; IS________OPM-SAME: (i8 [[V:%.*]], i8** nocapture writeonly [[P:%.*]]) +; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) +; IS________OPM-NEXT: store i8* [[TMP1]], i8** [[P]] +; IS________OPM-NEXT: tail call void @no_sync_func(i8* nofree [[TMP1]]) +; IS________OPM-NEXT: tail call void @free(i8* [[TMP1]]) +; IS________OPM-NEXT: ret void +; +; IS________NPM-LABEL: define {{[^@]+}}@test16b +; IS________NPM-SAME: (i8 [[V:%.*]], i8** nocapture writeonly [[P:%.*]]) +; IS________NPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) +; IS________NPM-NEXT: store i8* [[TMP1]], i8** [[P]] +; IS________NPM-NEXT: tail call void @no_sync_func(i8* nocapture nofree [[TMP1]]) +; IS________NPM-NEXT: tail call void @free(i8* [[TMP1]]) +; IS________NPM-NEXT: ret void +; %1 = tail call noalias i8* @malloc(i64 4) - ; CHECK-NEXT: store i8* %1, i8** %P store i8* %1, i8** %P - ; CHECK-NEXT: @no_sync_func(i8* nocapture nofree %1) tail call void @no_sync_func(i8* %1) - ; CHECK-NEXT: @free(i8* %1) tail call void @free(i8* %1) ret void } define void @test16c(i8 %v, i8** %P) { - ; CHECK: %1 = alloca +; IS________OPM-LABEL: define {{[^@]+}}@test16c +; IS________OPM-SAME: (i8 [[V:%.*]], i8** nocapture writeonly [[P:%.*]]) +; IS________OPM-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) +; IS________OPM-NEXT: store i8* [[TMP1]], i8** [[P]] +; IS________OPM-NEXT: tail call void @no_sync_func(i8* nofree [[TMP1]]) +; IS________OPM-NEXT: tail call void @free(i8* [[TMP1]]) +; IS________OPM-NEXT: ret void +; +; IS________NPM-LABEL: define {{[^@]+}}@test16c +; IS________NPM-SAME: (i8 [[V:%.*]], i8** nocapture writeonly [[P:%.*]]) +; IS________NPM-NEXT: [[TMP1:%.*]] = alloca i8, i64 4 +; IS________NPM-NEXT: store i8* [[TMP1]], i8** [[P]] +; IS________NPM-NEXT: tail call void @no_sync_func(i8* nocapture nofree [[TMP1]]) +; IS________NPM-NEXT: ret void +; %1 = tail call noalias i8* @malloc(i64 4) - ; CHECK-NEXT: store i8* %1, i8** %P store i8* %1, i8** %P - ; CHECK-NEXT: @no_sync_func(i8* nocapture nofree %1) tail call void @no_sync_func(i8* %1) nounwind - ; CHECK-NOT: @free tail call void @free(i8* %1) ret void } define void @test16d(i8 %v, i8** %P) { - ; CHECK: %1 = tail call noalias i8* @malloc(i64 4) +; CHECK-LABEL: define {{[^@]+}}@test16d +; CHECK-SAME: (i8 [[V:%.*]], i8** nocapture writeonly [[P:%.*]]) +; CHECK-NEXT: [[TMP1:%.*]] = tail call noalias i8* @malloc(i64 4) +; CHECK-NEXT: store i8* [[TMP1]], i8** [[P]] +; CHECK-NEXT: ret void +; %1 = tail call noalias i8* @malloc(i64 4) - ; CHECK-NEXT: store i8* %1, i8** %P store i8* %1, i8** %P ret void } 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,6 +1,26 @@ -; RUN: opt -S -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=7 < %s | FileCheck %s +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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____-LABEL: define {{[^@]+}}@visible +; IS__TUNIT____-SAME: (i32* noalias nocapture nofree readonly [[A:%.*]], i32* noalias nocapture nofree readonly [[B:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call i32 @noalias_args(i32* noalias nocapture nofree readonly align 4 [[A]], i32* noalias nocapture nofree readonly align 4 [[B]]) +; IS__TUNIT____-NEXT: [[CALL2:%.*]] = call i32 @noalias_args_argmem(i32* noalias nocapture nofree readonly align 4 [[A]], i32* noalias nocapture nofree readonly align 4 [[B]]) +; IS__TUNIT____-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL1]], [[CALL2]] +; IS__TUNIT____-NEXT: ret i32 [[ADD]] +; +; 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: +; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32 @noalias_args(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: [[CALL2:%.*]] = call i32 @noalias_args_argmem(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: [[ADD:%.*]] = add nsw i32 [[CALL1]], [[CALL2]] +; IS__CGSCC____-NEXT: ret i32 [[ADD]] +; entry: %call1 = call i32 @noalias_args(i32* %A, i32* %B) %call2 = call i32 @noalias_args_argmem(i32* %A, i32* %B) @@ -8,9 +28,27 @@ ret i32 %add } -; CHECK: define private i32 @noalias_args(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) %A, i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) %B) - define private i32 @noalias_args(i32* %A, i32* %B) #0 { +; 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: +; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32, i32* [[A]], align 4 +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = load i32, i32* [[B]], align 4 +; IS__TUNIT____-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]] +; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A]], i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B]]) +; IS__TUNIT____-NEXT: [[ADD2:%.*]] = add nsw i32 [[ADD]], [[CALL]] +; IS__TUNIT____-NEXT: ret i32 [[ADD2]] +; +; 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: +; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* [[A]], align 4 +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = load i32, i32* [[B]], align 4 +; IS__CGSCC____-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]] +; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A]], i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B]]) +; IS__CGSCC____-NEXT: [[ADD2:%.*]] = add nsw i32 [[ADD]], [[CALL]] +; IS__CGSCC____-NEXT: ret i32 [[ADD2]] +; entry: %0 = load i32, i32* %A, align 4 %1 = load i32, i32* %B, align 4 @@ -21,8 +59,23 @@ } -; CHECK: define internal i32 @noalias_args_argmem(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) %A, i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) %B) define internal i32 @noalias_args_argmem(i32* %A, i32* %B) #1 { +; 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: +; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32, i32* [[A]], align 4 +; IS__TUNIT____-NEXT: [[TMP1:%.*]] = load i32, i32* [[B]], align 4 +; IS__TUNIT____-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]] +; IS__TUNIT____-NEXT: ret i32 [[ADD]] +; +; 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: +; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* [[A]], align 4 +; IS__CGSCC____-NEXT: [[TMP1:%.*]] = load i32, i32* [[B]], align 4 +; IS__CGSCC____-NEXT: [[ADD:%.*]] = add nsw i32 [[TMP0]], [[TMP1]] +; IS__CGSCC____-NEXT: ret i32 [[ADD]] +; entry: %0 = load i32, i32* %A, align 4 %1 = load i32, i32* %B, align 4 @@ -31,6 +84,26 @@ } define dso_local i32 @visible_local(i32* %A) #0 { +; IS__TUNIT____-LABEL: define {{[^@]+}}@visible_local +; IS__TUNIT____-SAME: (i32* nocapture nofree readonly [[A:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[B:%.*]] = alloca i32, align 4 +; IS__TUNIT____-NEXT: store i32 5, i32* [[B]], align 4 +; IS__TUNIT____-NEXT: [[CALL1:%.*]] = call i32 @noalias_args(i32* nocapture nofree readonly align 4 [[A]], i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B]]) +; IS__TUNIT____-NEXT: [[CALL2:%.*]] = call i32 @noalias_args_argmem(i32* nocapture nofree readonly align 4 [[A]], i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B]]) +; IS__TUNIT____-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL1]], [[CALL2]] +; IS__TUNIT____-NEXT: ret i32 [[ADD]] +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@visible_local +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[B:%.*]] = alloca i32, align 4 +; IS__CGSCC____-NEXT: store i32 5, i32* [[B]], align 4 +; IS__CGSCC____-NEXT: [[CALL1:%.*]] = call i32 @noalias_args(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A]], i32* noalias nofree nonnull readonly align 4 dereferenceable(4) [[B]]) +; IS__CGSCC____-NEXT: [[CALL2:%.*]] = call i32 @noalias_args_argmem(i32* nocapture nofree nonnull readonly align 4 dereferenceable(4) [[A]], i32* noalias nofree nonnull readonly align 4 dereferenceable(4) [[B]]) +; IS__CGSCC____-NEXT: [[ADD:%.*]] = add nsw i32 [[CALL1]], [[CALL2]] +; IS__CGSCC____-NEXT: ret i32 [[ADD]] +; entry: %B = alloca i32, align 4 store i32 5, i32* %B, align 4 @@ -40,8 +113,32 @@ ret i32 %add } -; CHECK: define internal i32 @noalias_args_argmem_ro(i32 %0, i32 %1) define internal i32 @noalias_args_argmem_ro(i32* %A, i32* %B) #1 { +; 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 +; IS__TUNIT_OPM-NEXT: [[T1:%.*]] = load i32, i32* [[B]], align 4 +; IS__TUNIT_OPM-NEXT: [[ADD:%.*]] = add nsw i32 [[T0]], [[T1]] +; IS__TUNIT_OPM-NEXT: ret i32 [[ADD]] +; +; 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 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP1]], i32* [[B_PRIV]] +; IS__TUNIT_NPM-NEXT: [[A_PRIV:%.*]] = alloca i32 +; IS__TUNIT_NPM-NEXT: store i32 [[TMP0]], i32* [[A_PRIV]] +; IS__TUNIT_NPM-NEXT: [[T0:%.*]] = load i32, i32* [[A_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: [[T1:%.*]] = load i32, i32* [[B_PRIV]], align 4 +; IS__TUNIT_NPM-NEXT: [[ADD:%.*]] = add nsw i32 [[T0]], [[T1]] +; IS__TUNIT_NPM-NEXT: ret i32 [[ADD]] +; +; 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 +; IS__CGSCC____-NEXT: [[T1:%.*]] = load i32, i32* [[B]], align 4 +; IS__CGSCC____-NEXT: [[ADD:%.*]] = add nsw i32 [[T0]], [[T1]] +; IS__CGSCC____-NEXT: ret i32 [[ADD]] +; %t0 = load i32, i32* %A, align 4 %t1 = load i32, i32* %B, align 4 %add = add nsw i32 %t0, %t1 @@ -49,20 +146,63 @@ } define i32 @visible_local_2() { +; 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-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 +; IS__TUNIT_NPM-NEXT: [[TMP1:%.*]] = load i32, i32* [[B]], align 1 +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = load i32, i32* [[B]], align 1 +; IS__TUNIT_NPM-NEXT: [[CALL:%.*]] = call i32 @noalias_args_argmem_ro(i32 [[TMP1]], i32 [[TMP2]]) +; IS__TUNIT_NPM-NEXT: ret i32 [[CALL]] +; +; 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 nofree nonnull readonly align 4 dereferenceable(4) [[B]], i32* noalias 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 %call = call i32 @noalias_args_argmem_ro(i32* %B, i32* %B) ret i32 %call } -; CHECK: define internal i32 @noalias_args_argmem_rn(i32* noalias nocapture nofree nonnull align 4 dereferenceable(4) %B) define internal i32 @noalias_args_argmem_rn(i32* %A, i32* %B) #1 { +; 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____-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 +; IS__CGSCC____-NEXT: store i32 0, i32* [[B]], align 4 +; IS__CGSCC____-NEXT: ret i32 [[T0]] +; %t0 = load i32, i32* %B, align 4 store i32 0, i32* %B ret i32 %t0 } define i32 @visible_local_3() { +; 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____-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 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 %call = call i32 @noalias_args_argmem_rn(i32* %B, i32* %B) 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,15 +1,11 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes -; RUN: opt -attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,MODULE,MODULE_OLD -; RUN: opt -attributor-cgscc --attributor-disable=false -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC,CGSCC_OLD -; RUN: opt -passes=attributor --attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,MODULE,MODULE_NEW -; RUN: opt -passes='attributor-cgscc' --attributor-disable=false -attributor-annotate-decl-cs -attributor-max-iterations=7 -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC,CGSCC_NEW -; XFAIL: * -; UTC_ARGS: --disable - -; MODULE_OLD: @dead_with_blockaddress_users.l = constant [2 x i8*] [i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 1 to i8*)] -; MODULE_NEW: @dead_with_blockaddress_users.l = constant [2 x i8*] [i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 1 to i8*)] -; CGSCC_OLD: @dead_with_blockaddress_users.l = constant [2 x i8*] [i8* blockaddress(@dead_with_blockaddress_users, %lab0), i8* blockaddress(@dead_with_blockaddress_users, %end)] -; CGSCC_NEW: @dead_with_blockaddress_users.l = constant [2 x i8*] [i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 1 to i8*)] +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -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-disable=false -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-disable=false -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-disable=false -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 + +; NOT_CGSCC_OPM: @dead_with_blockaddress_users.l = constant [2 x i8*] [i8* inttoptr (i32 1 to i8*), i8* inttoptr (i32 1 to i8*)] +; IS__CGSCC_OPM: @dead_with_blockaddress_users.l = constant [2 x i8*] [i8* blockaddress(@dead_with_blockaddress_users, %lab0), i8* blockaddress(@dead_with_blockaddress_users, %end)] @dead_with_blockaddress_users.l = constant [2 x i8*] [i8* blockaddress(@dead_with_blockaddress_users, %lab0), i8* blockaddress(@dead_with_blockaddress_users, %end)] declare void @no_return_call() nofree noreturn nounwind nosync @@ -29,8 +25,19 @@ ; This internal function has no live call sites, so all its BBs are considered dead, ; and nothing should be deduced for it. -; MODULE-NOT: define internal i32 @dead_internal_func(i32 %0) define internal i32 @dead_internal_func(i32 %0) { +; IS__CGSCC____-LABEL: define {{[^@]+}}@dead_internal_func() +; IS__CGSCC____-NEXT: br label [[TMP2:%.*]] +; IS__CGSCC____: 1: +; IS__CGSCC____-NEXT: ret i32 undef +; IS__CGSCC____: 2: +; IS__CGSCC____-NEXT: [[TMP3:%.*]] = phi i32 [ [[TMP6:%.*]], [[TMP2]] ], [ 1, [[TMP0:%.*]] ] +; IS__CGSCC____-NEXT: [[TMP4:%.*]] = phi i32 [ [[TMP5:%.*]], [[TMP2]] ], [ 1, [[TMP0]] ] +; IS__CGSCC____-NEXT: [[TMP5]] = mul nsw i32 [[TMP3]], [[TMP4]] +; IS__CGSCC____-NEXT: [[TMP6]] = add nuw nsw i32 [[TMP3]], 1 +; IS__CGSCC____-NEXT: [[TMP7:%.*]] = icmp eq i32 [[TMP3]], 10 +; IS__CGSCC____-NEXT: br i1 [[TMP7]], label [[TMP1:%.*]], label [[TMP2]] +; %2 = icmp slt i32 %0, 1 br i1 %2, label %3, label %5 @@ -49,26 +56,41 @@ ; CHECK: Function Attrs: argmemonly nofree norecurse nounwind uwtable willreturn define i32 @volatile_load(i32*) norecurse nounwind uwtable { +; CHECK-LABEL: define {{[^@]+}}@volatile_load +; CHECK-SAME: (i32* nofree align 4 [[TMP0:%.*]]) +; CHECK-NEXT: [[TMP2:%.*]] = load volatile i32, i32* [[TMP0]], align 4 +; CHECK-NEXT: ret i32 [[TMP2]] +; %2 = load volatile i32, i32* %0, align 4 ret i32 %2 } -; MODULE-NOT: internal_load define internal i32 @internal_load(i32*) norecurse nounwind uwtable { +; IS__CGSCC____-LABEL: define {{[^@]+}}@internal_load() +; IS__CGSCC____-NEXT: ret i32 undef +; %2 = load i32, i32* %0, align 4 ret i32 %2 } ; TEST 1: Only first block is live. ; CHECK: Function Attrs: nofree noreturn nosync nounwind -; MODULE-NEXT: define i32 @first_block_no_return(i32 %a, i32* nocapture nofree nonnull readnone %ptr1, i32* nocapture nofree readnone %ptr2) -; CGSCC-NEXT: define i32 @first_block_no_return(i32 %a, i32* nocapture nofree nonnull readnone %ptr1, i32* nocapture nofree readnone %ptr2) define i32 @first_block_no_return(i32 %a, i32* nonnull %ptr1, i32* %ptr2) #0 { +; 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: +; CHECK-NEXT: call void @no_return_call() +; CHECK-NEXT: unreachable +; CHECK: cond.true: +; CHECK-NEXT: unreachable +; CHECK: cond.false: +; CHECK-NEXT: unreachable +; CHECK: cond.end: +; CHECK-NEXT: unreachable +; entry: call i32 @internal_load(i32* %ptr1) call void @no_return_call() - ; CHECK: call void @no_return_call() - ; CHECK-NEXT: unreachable call i32 @dead_internal_func(i32 10) %cmp = icmp eq i32 %a, 0 br i1 %cmp, label %cond.true, label %cond.false @@ -96,16 +118,28 @@ ; dead block and check if it is deduced. ; CHECK: Function Attrs: nosync -; CHECK-NEXT: define i32 @dead_block_present(i32 %a, i32* nocapture nofree readnone %ptr1) define i32 @dead_block_present(i32 %a, i32* %ptr1) #0 { +; CHECK-LABEL: define {{[^@]+}}@dead_block_present +; CHECK-SAME: (i32 [[A:%.*]], i32* nocapture nofree readnone [[PTR1:%.*]]) +; 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: call void @no_return_call() +; CHECK-NEXT: unreachable +; CHECK: cond.false: +; CHECK-NEXT: call void @normal_call() +; CHECK-NEXT: [[CALL1:%.*]] = call i32 @bar() +; CHECK-NEXT: br label [[COND_END:%.*]] +; CHECK: cond.end: +; CHECK-NEXT: ret i32 [[CALL1]] +; entry: %cmp = icmp eq i32 %a, 0 br i1 %cmp, label %cond.true, label %cond.false cond.true: ; preds = %entry call void @no_return_call() - ; CHECK: call void @no_return_call() - ; CHECK-NEXT: unreachable %call = call i32 @volatile_load(i32* %ptr1) br label %cond.end @@ -115,8 +149,6 @@ br label %cond.end cond.end: ; preds = %cond.false, %cond.true -; CHECK: cond.end: -; CHECK-NEXT: ret i32 %call1 %cond = phi i32 [ %call, %cond.true ], [ %call1, %cond.false ] ret i32 %cond } @@ -124,23 +156,32 @@ ; 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-LABEL: define {{[^@]+}}@all_dead +; 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: call void @no_return_call() +; CHECK-NEXT: unreachable +; CHECK: cond.false: +; CHECK-NEXT: call void @no_return_call() +; CHECK-NEXT: unreachable +; CHECK: cond.end: +; CHECK-NEXT: unreachable +; entry: %cmp = icmp eq i32 %a, 0 br i1 %cmp, label %cond.true, label %cond.false cond.true: ; preds = %entry call void @no_return_call() - ; CHECK: call void @no_return_call() - ; CHECK-NEXT: unreachable call i32 @dead_internal_func(i32 10) - ; CHECK-NOT: call %call = call i32 @foo() br label %cond.end cond.false: ; preds = %entry call void @no_return_call() - ; CHECK: call void @no_return_call() - ; CHECK-NEXT: unreachable call i32 @dead_internal_func(i32 10) %call1 = call i32 @bar() br label %cond.end @@ -154,8 +195,23 @@ ; TEST 4: All blocks are live. -; CHECK: define i32 @all_live(i32 %a) define i32 @all_live(i32 %a) #0 { +; CHECK-LABEL: define {{[^@]+}}@all_live +; 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: call void @normal_call() +; CHECK-NEXT: [[CALL:%.*]] = call i32 @foo_noreturn() +; CHECK-NEXT: unreachable +; CHECK: cond.false: +; CHECK-NEXT: call void @normal_call() +; CHECK-NEXT: [[CALL1:%.*]] = call i32 @bar() +; CHECK-NEXT: br label [[COND_END:%.*]] +; CHECK: cond.end: +; CHECK-NEXT: ret i32 [[CALL1]] +; entry: %cmp = icmp eq i32 %a, 0 br i1 %cmp, label %cond.true, label %cond.false @@ -177,8 +233,29 @@ ; TEST 5.1 noreturn invoke instruction with a unreachable normal successor block. -; CHECK: define i32 @invoke_noreturn(i32 %a) define i32 @invoke_noreturn(i32 %a) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +; CHECK-LABEL: define {{[^@]+}}@invoke_noreturn +; CHECK-SAME: (i32 [[A:%.*]]) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) +; 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: call void @normal_call() +; CHECK-NEXT: [[CALL:%.*]] = invoke i32 @foo_noreturn() +; CHECK-NEXT: to label [[CONTINUE:%.*]] unwind label [[CLEANUP:%.*]] +; CHECK: cond.false: +; CHECK-NEXT: call void @normal_call() +; CHECK-NEXT: [[CALL1:%.*]] = call i32 @bar() +; CHECK-NEXT: br label [[COND_END:%.*]] +; CHECK: cond.end: +; CHECK-NEXT: ret i32 [[CALL1]] +; CHECK: continue: +; CHECK-NEXT: unreachable +; CHECK: cleanup: +; CHECK-NEXT: [[RES:%.*]] = landingpad { i8*, i32 } +; CHECK-NEXT: catch i8* null +; CHECK-NEXT: ret i32 0 +; entry: %cmp = icmp eq i32 %a, 0 br i1 %cmp, label %cond.true, label %cond.false @@ -186,9 +263,7 @@ cond.true: ; preds = %entry call void @normal_call() %call = invoke i32 @foo_noreturn() to label %continue - unwind label %cleanup - ; CHECK: %call = invoke i32 @foo_noreturn() - ; CHECK-NEXT: to label %continue unwind label %cleanup + unwind label %cleanup cond.false: ; preds = %entry call void @normal_call() @@ -200,8 +275,6 @@ ret i32 %cond continue: - ; CHECK: continue: - ; CHECK-NEXT: unreachable br label %cond.end cleanup: @@ -213,8 +286,27 @@ ; TEST 5.2 noreturn invoke instruction replaced by a call and an unreachable instruction ; put after it. -; CHECK: define i32 @invoke_noreturn_nounwind(i32 %a) define i32 @invoke_noreturn_nounwind(i32 %a) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { +; CHECK-LABEL: define {{[^@]+}}@invoke_noreturn_nounwind +; CHECK-SAME: (i32 [[A:%.*]]) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) +; 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: call void @normal_call() +; CHECK-NEXT: [[CALL:%.*]] = call i32 @foo_noreturn_nounwind() +; CHECK-NEXT: unreachable +; CHECK: cond.false: +; CHECK-NEXT: call void @normal_call() +; CHECK-NEXT: [[CALL1:%.*]] = call i32 @bar() +; CHECK-NEXT: br label [[COND_END:%.*]] +; CHECK: cond.end: +; CHECK-NEXT: ret i32 [[CALL1]] +; CHECK: continue: +; CHECK-NEXT: unreachable +; CHECK: cleanup: +; CHECK-NEXT: unreachable +; entry: %cmp = icmp eq i32 %a, 0 br i1 %cmp, label %cond.true, label %cond.false @@ -222,12 +314,8 @@ cond.true: ; preds = %entry call void @normal_call() %call = invoke i32 @foo_noreturn_nounwind() to label %continue - unwind label %cleanup - ; CHECK: call void @normal_call() - ; CHECK-NEXT: call i32 @foo_noreturn_nounwind() - ; CHECK-NEXT: unreachable + unwind label %cleanup - ; CHECK-NOT: @foo_noreturn_nounwind() cond.false: ; preds = %entry call void @normal_call() @@ -250,12 +338,25 @@ ; TEST 5.3 unounwind invoke instruction replaced by a call and a branch instruction put after it. define i32 @invoke_nounwind(i32 %a) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { ; CHECK-LABEL: define {{[^@]+}}@invoke_nounwind +; CHECK-SAME: (i32 [[A:%.*]]) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) +; 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: call void @normal_call() ; CHECK-NEXT: [[CALL:%.*]] = call i32 @foo_nounwind() ; CHECK-NEXT: br label [[CONTINUE:%.*]] -; CHECK: continue: +; CHECK: cond.false: +; CHECK-NEXT: call void @normal_call() +; CHECK-NEXT: [[CALL1:%.*]] = call i32 @bar() ; CHECK-NEXT: br label [[COND_END:%.*]] +; CHECK: cond.end: +; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[CALL]], [[CONTINUE]] ], [ [[CALL1]], [[COND_FALSE]] ] +; CHECK-NEXT: ret i32 [[COND]] +; CHECK: continue: +; CHECK-NEXT: br label [[COND_END]] +; CHECK: cleanup: +; CHECK-NEXT: unreachable ; entry: %cmp = icmp eq i32 %a, 0 @@ -284,8 +385,6 @@ ret i32 0 } -; UTC_ARGS: --enable - ; TEST 5.4 unounwind invoke instruction replaced by a call and a branch instruction put after it. define i32 @invoke_nounwind_phi(i32 %a) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { ; CHECK-LABEL: define {{[^@]+}}@invoke_nounwind_phi @@ -374,13 +473,18 @@ ret i32 0 } -; UTC_ARGS: --disable - ; TEST 6: Undefined behvior, taken from LangRef. ; FIXME: Should be able to detect undefined behavior. -; CHECK: define void @ub(i32* nocapture nofree writeonly %0) 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 +; %poison = sub nuw i32 0, 1 ; Results in a poison value. %still_poison = and i32 %poison, 0 ; 0, but also poison. %poison_yet_again = getelementptr i32, i32* %0, i32 %still_poison @@ -389,6 +493,12 @@ } 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]] +; entry: br label %while.body @@ -400,6 +510,20 @@ ; FIXME: Detect infloops, and mark affected blocks dead. define i32 @test5(i32, i32) #0 { +; CHECK-LABEL: define {{[^@]+}}@test5 +; CHECK-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) +; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP0]], [[TMP1]] +; CHECK-NEXT: br i1 [[TMP3]], label [[COND_IF:%.*]], label [[COND_ELSEIF:%.*]] +; CHECK: cond.if: +; CHECK-NEXT: [[TMP4:%.*]] = tail call i32 @bar() +; CHECK-NEXT: br label [[COND_END:%.*]] +; CHECK: cond.elseif: +; CHECK-NEXT: unreachable +; CHECK: cond.else: +; CHECK-NEXT: unreachable +; CHECK: cond.end: +; CHECK-NEXT: ret i32 0 +; %3 = icmp sgt i32 %0, %1 br i1 %3, label %cond.if, label %cond.elseif @@ -422,6 +546,10 @@ } define void @rec() #0 { +; CHECK-LABEL: define {{[^@]+}}@rec() +; CHECK-NEXT: entry: +; CHECK-NEXT: unreachable +; entry: call void @rec() ret void @@ -432,6 +560,18 @@ ; 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 +; call void @rec() %3 = icmp sgt i32 %0, %1 br i1 %3, label %cond.if, label %cond.elseif @@ -457,6 +597,24 @@ ; FIXME: contains recursive call to itself in cond.elseif block define i32 @test7(i32, i32) #0 { +; CHECK-LABEL: define {{[^@]+}}@test7 +; CHECK-SAME: (i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) +; CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i32 [[TMP0]], [[TMP1]] +; CHECK-NEXT: br i1 [[TMP3]], label [[COND_IF:%.*]], label [[COND_ELSEIF:%.*]] +; CHECK: cond.if: +; CHECK-NEXT: [[TMP4:%.*]] = tail call i32 @bar() +; CHECK-NEXT: br label [[COND_END:%.*]] +; CHECK: cond.elseif: +; CHECK-NEXT: [[TMP5:%.*]] = tail call i32 @test7(i32 [[TMP0]], i32 [[TMP1]]) +; CHECK-NEXT: [[TMP6:%.*]] = icmp slt i32 [[TMP0]], [[TMP1]] +; CHECK-NEXT: br i1 [[TMP6]], label [[COND_END]], label [[COND_ELSE:%.*]] +; CHECK: cond.else: +; CHECK-NEXT: [[TMP7:%.*]] = tail call i32 @foo() +; CHECK-NEXT: br label [[COND_END]] +; CHECK: cond.end: +; CHECK-NEXT: [[TMP8:%.*]] = phi i32 [ [[TMP1]], [[COND_ELSEIF]] ], [ 0, [[COND_ELSE]] ], [ 0, [[COND_IF]] ] +; CHECK-NEXT: ret i32 [[TMP8]] +; %3 = icmp sgt i32 %0, %1 br i1 %3, label %cond.if, label %cond.elseif @@ -498,12 +656,21 @@ @a2 = common global i8 0, align 16 define internal i8* @f1(i8* readnone %0) local_unnamed_addr #0 { -; ATTRIBUTOR: define internal i8* @f1(i8* readnone %0) +; CHECK-LABEL: define {{[^@]+}}@f1 +; CHECK-SAME: (i8* readnone [[TMP0:%.*]]) local_unnamed_addr +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8* [[TMP0]], null +; CHECK-NEXT: br i1 [[TMP2]], label [[TMP3:%.*]], label [[TMP5:%.*]] +; CHECK: 3: +; CHECK-NEXT: [[TMP4:%.*]] = tail call i8* @f2(i8* nonnull @a1) +; CHECK-NEXT: br label [[TMP5]] +; CHECK: 5: +; CHECK-NEXT: [[TMP6:%.*]] = phi i8* [ [[TMP4]], [[TMP3]] ], [ [[TMP0]], [[TMP1:%.*]] ] +; CHECK-NEXT: ret i8* [[TMP6]] +; %2 = icmp eq i8* %0, null br i1 %2, label %3, label %5 ;