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,34 @@ ; 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=2 -S < %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 ; 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-NEXT: entry: -; CHECK-NEXT: [[A_0:%.*]] = load i32, i32* null, align 536870912 -; CHECK-NEXT: br label [[F:%.*]] -; CHECK: T: -; CHECK-NEXT: unreachable -; CHECK: F: -; CHECK-NEXT: [[A_2:%.*]] = getelementptr i32, i32* null, i32 2 -; CHECK-NEXT: [[R:%.*]] = load i32, i32* [[A_2]] -; CHECK-NEXT: ret i32 [[R]] +; IS__TUNIT____-LABEL: define {{[^@]+}}@callee() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[A_0:%.*]] = load i32, i32* null, align 536870912 +; IS__TUNIT____-NEXT: br label [[F:%.*]] +; IS__TUNIT____: T: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: F: +; IS__TUNIT____-NEXT: [[A_2:%.*]] = getelementptr i32, i32* null, i32 2 +; IS__TUNIT____-NEXT: [[R:%.*]] = load i32, i32* [[A_2]] +; IS__TUNIT____-NEXT: ret i32 [[R]] +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@callee() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[A_0:%.*]] = load i32, i32* null +; IS__CGSCC____-NEXT: br label [[F:%.*]] +; IS__CGSCC____: T: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: F: +; IS__CGSCC____-NEXT: [[A_2:%.*]] = getelementptr i32, i32* null, i32 2 +; IS__CGSCC____-NEXT: [[R:%.*]] = load i32, i32* [[A_2]] +; IS__CGSCC____-NEXT: ret i32 [[R]] ; entry: ; Unconditonally load the element at %A diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-07-CGUpdate.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-07-CGUpdate.ll --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-07-CGUpdate.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-07-CGUpdate.ll @@ -1,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,34 @@ ; 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=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 +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@no_promote_avx2 +; IS__TUNIT_OPM-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:%.*]]) +; IS__TUNIT_OPM-NEXT: bb: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = load <4 x i64>, <4 x i64>* [[ARG1]], align 32 +; IS__TUNIT_OPM-NEXT: store <4 x i64> [[TMP]], <4 x i64>* [[ARG]], align 32 +; IS__TUNIT_OPM-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 +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@no_promote_avx2 +; IS__CGSCC____-SAME: (<4 x i64>* nocapture nofree nonnull writeonly dereferenceable(32) [[ARG:%.*]], <4 x i64>* nocapture nofree nonnull readonly dereferenceable(32) [[ARG1:%.*]]) +; IS__CGSCC____-NEXT: bb: +; IS__CGSCC____-NEXT: [[TMP:%.*]] = load <4 x i64>, <4 x i64>* [[ARG1]] +; IS__CGSCC____-NEXT: store <4 x i64> [[TMP]], <4 x i64>* [[ARG]] +; IS__CGSCC____-NEXT: ret void ; bb: %tmp = load <4 x i64>, <4 x i64>* %arg1 @@ -20,17 +37,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 +97,28 @@ } 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 +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@promote_avx2 +; IS__TUNIT_OPM-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:%.*]]) +; IS__TUNIT_OPM-NEXT: bb: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = load <4 x i64>, <4 x i64>* [[ARG1]], align 32 +; IS__TUNIT_OPM-NEXT: store <4 x i64> [[TMP]], <4 x i64>* [[ARG]], align 32 +; IS__TUNIT_OPM-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 +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@promote_avx2 +; IS__CGSCC____-SAME: (<4 x i64>* nocapture nofree nonnull writeonly dereferenceable(32) [[ARG:%.*]], <4 x i64>* nocapture nofree nonnull readonly dereferenceable(32) [[ARG1:%.*]]) +; IS__CGSCC____-NEXT: bb: +; IS__CGSCC____-NEXT: [[TMP:%.*]] = load <4 x i64>, <4 x i64>* [[ARG1]] +; IS__CGSCC____-NEXT: store <4 x i64> [[TMP]], <4 x i64>* [[ARG]] +; IS__CGSCC____-NEXT: ret void ; bb: %tmp = load <4 x i64>, <4 x i64>* %arg1 @@ -60,18 +127,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=2 < %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,28 @@ ; 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 32 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 32 -; CHECK-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 -; CHECK-NEXT: ret void +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512 +; IS__TUNIT_OPM-SAME: (<8 x i64>* nocapture nofree nonnull writeonly align 32 dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly align 32 dereferenceable(64) [[ARG1:%.*]]) +; IS__TUNIT_OPM-NEXT: bb: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 32 +; IS__TUNIT_OPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 +; IS__TUNIT_OPM-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 32 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 32 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512 +; IS__CGSCC____-SAME: (<8 x i64>* nocapture nofree nonnull writeonly dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly dereferenceable(64) [[ARG1:%.*]]) +; IS__CGSCC____-NEXT: bb: +; IS__CGSCC____-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]] +; IS__CGSCC____-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]] +; IS__CGSCC____-NEXT: ret void ; bb: %tmp = load <8 x i64>, <8 x i64>* %arg1 @@ -23,18 +40,54 @@ } 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 32 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) -; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 -; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* nocapture nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 +102,28 @@ ; 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 32 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 32 -; CHECK-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 -; CHECK-NEXT: ret void +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256 +; IS__TUNIT_OPM-SAME: (<8 x i64>* nocapture nofree nonnull writeonly align 32 dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly align 32 dereferenceable(64) [[ARG1:%.*]]) +; IS__TUNIT_OPM-NEXT: bb: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 32 +; IS__TUNIT_OPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 +; IS__TUNIT_OPM-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 32 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 32 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256 +; IS__CGSCC____-SAME: (<8 x i64>* nocapture nofree nonnull writeonly dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly dereferenceable(64) [[ARG1:%.*]]) +; IS__CGSCC____-NEXT: bb: +; IS__CGSCC____-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]] +; IS__CGSCC____-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]] +; IS__CGSCC____-NEXT: ret void ; bb: %tmp = load <8 x i64>, <8 x i64>* %arg1 @@ -65,18 +132,54 @@ } 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 32 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) -; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 -; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* nocapture nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 +194,28 @@ ; 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 32 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 32 -; CHECK-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 -; CHECK-NEXT: ret void +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256 +; IS__TUNIT_OPM-SAME: (<8 x i64>* nocapture nofree nonnull writeonly align 32 dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly align 32 dereferenceable(64) [[ARG1:%.*]]) +; IS__TUNIT_OPM-NEXT: bb: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 32 +; IS__TUNIT_OPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 +; IS__TUNIT_OPM-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 32 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 32 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256 +; IS__CGSCC____-SAME: (<8 x i64>* nocapture nofree nonnull writeonly dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly dereferenceable(64) [[ARG1:%.*]]) +; IS__CGSCC____-NEXT: bb: +; IS__CGSCC____-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]] +; IS__CGSCC____-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]] +; IS__CGSCC____-NEXT: ret void ; bb: %tmp = load <8 x i64>, <8 x i64>* %arg1 @@ -107,18 +224,54 @@ } 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 32 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) -; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 -; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* nocapture nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 +286,28 @@ ; 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 32 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 32 -; CHECK-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 -; CHECK-NEXT: ret void +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512 +; IS__TUNIT_OPM-SAME: (<8 x i64>* nocapture nofree nonnull writeonly align 32 dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly align 32 dereferenceable(64) [[ARG1:%.*]]) +; IS__TUNIT_OPM-NEXT: bb: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 32 +; IS__TUNIT_OPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 +; IS__TUNIT_OPM-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 32 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 32 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512 +; IS__CGSCC____-SAME: (<8 x i64>* nocapture nofree nonnull writeonly dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly dereferenceable(64) [[ARG1:%.*]]) +; IS__CGSCC____-NEXT: bb: +; IS__CGSCC____-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]] +; IS__CGSCC____-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]] +; IS__CGSCC____-NEXT: ret void ; bb: %tmp = load <8 x i64>, <8 x i64>* %arg1 @@ -149,18 +316,54 @@ } 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 32 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) -; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 -; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* nocapture nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 +378,26 @@ ; 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 32 dereferenceable(64) [[ARG:%.*]], <8 x i64>* noalias nocapture nofree nonnull readonly align 32 dereferenceable(64) [[ARG1:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 32 -; CHECK-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 -; CHECK-NEXT: ret void +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256 +; IS__TUNIT_OPM-SAME: (<8 x i64>* nocapture nofree nonnull writeonly align 32 dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly align 32 dereferenceable(64) [[ARG1:%.*]]) +; IS__TUNIT_OPM-NEXT: bb: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 32 +; IS__TUNIT_OPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 +; IS__TUNIT_OPM-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 32 dereferenceable(64) [[ARG:%.*]], <8 x i64>* noalias nocapture nofree nonnull readonly align 32 dereferenceable(64) [[ARG1:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 32 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256 +; IS__CGSCC____-SAME: (<8 x i64>* nocapture nofree nonnull writeonly dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly dereferenceable(64) [[ARG1:%.*]]) +; IS__CGSCC____-NEXT: bb: +; IS__CGSCC____-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]] +; IS__CGSCC____-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]] +; IS__CGSCC____-NEXT: ret void ; bb: %tmp = load <8 x i64>, <8 x i64>* %arg1 @@ -189,17 +406,53 @@ } 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nocapture nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) -; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 -; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* nocapture nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nocapture nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 +467,26 @@ ; 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 32 dereferenceable(64) [[ARG:%.*]], <8 x i64>* noalias nocapture nofree nonnull readonly align 32 dereferenceable(64) [[ARG1:%.*]]) -; CHECK-NEXT: bb: -; CHECK-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 32 -; CHECK-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 -; CHECK-NEXT: ret void +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256 +; IS__TUNIT_OPM-SAME: (<8 x i64>* nocapture nofree nonnull writeonly align 32 dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly align 32 dereferenceable(64) [[ARG1:%.*]]) +; IS__TUNIT_OPM-NEXT: bb: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 32 +; IS__TUNIT_OPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 +; IS__TUNIT_OPM-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 32 dereferenceable(64) [[ARG:%.*]], <8 x i64>* noalias nocapture nofree nonnull readonly align 32 dereferenceable(64) [[ARG1:%.*]]) +; IS__TUNIT_NPM-NEXT: bb: +; IS__TUNIT_NPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 32 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256 +; IS__CGSCC____-SAME: (<8 x i64>* nocapture nofree nonnull writeonly dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly dereferenceable(64) [[ARG1:%.*]]) +; IS__CGSCC____-NEXT: bb: +; IS__CGSCC____-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]] +; IS__CGSCC____-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]] +; IS__CGSCC____-NEXT: ret void ; bb: %tmp = load <8 x i64>, <8 x i64>* %arg1 @@ -228,17 +495,53 @@ } 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nocapture nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) -; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 -; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* nocapture nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nocapture nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 +556,28 @@ ; 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 32 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 32 -; CHECK-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 -; CHECK-NEXT: ret void +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256 +; IS__TUNIT_OPM-SAME: (<8 x i64>* nocapture nofree nonnull writeonly align 32 dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly align 32 dereferenceable(64) [[ARG1:%.*]]) +; IS__TUNIT_OPM-NEXT: bb: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 32 +; IS__TUNIT_OPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 +; IS__TUNIT_OPM-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 32 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 32 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256 +; IS__CGSCC____-SAME: (<8 x i64>* nocapture nofree nonnull writeonly dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly dereferenceable(64) [[ARG1:%.*]]) +; IS__CGSCC____-NEXT: bb: +; IS__CGSCC____-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]] +; IS__CGSCC____-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]] +; IS__CGSCC____-NEXT: ret void ; bb: %tmp = load <8 x i64>, <8 x i64>* %arg1 @@ -269,18 +586,54 @@ } 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 32 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) -; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 -; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* nocapture nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 +648,28 @@ ; 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 32 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 32 -; CHECK-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 -; CHECK-NEXT: ret void +; IS__TUNIT_OPM-LABEL: define {{[^@]+}}@callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256 +; IS__TUNIT_OPM-SAME: (<8 x i64>* nocapture nofree nonnull writeonly align 32 dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly align 32 dereferenceable(64) [[ARG1:%.*]]) +; IS__TUNIT_OPM-NEXT: bb: +; IS__TUNIT_OPM-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]], align 32 +; IS__TUNIT_OPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 +; IS__TUNIT_OPM-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 32 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 32 +; IS__TUNIT_NPM-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]], align 32 +; IS__TUNIT_NPM-NEXT: ret void +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256 +; IS__CGSCC____-SAME: (<8 x i64>* nocapture nofree nonnull writeonly dereferenceable(64) [[ARG:%.*]], <8 x i64>* nocapture nofree nonnull readonly dereferenceable(64) [[ARG1:%.*]]) +; IS__CGSCC____-NEXT: bb: +; IS__CGSCC____-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]] +; IS__CGSCC____-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]] +; IS__CGSCC____-NEXT: ret void ; bb: %tmp = load <8 x i64>, <8 x i64>* %arg1 @@ -311,18 +678,54 @@ } 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 32 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) -; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 -; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* nocapture nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__TUNIT_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64> [[TMP0]]) +; IS__TUNIT_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__CGSCC_OPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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 32 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 32 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nofree nonnull readonly align 32 dereferenceable(64) [[TMP]]) +; IS__CGSCC_NPM-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32 +; 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]] +; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[B_GEP]] +; 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=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 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,74 @@ ; 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]] -; CHECK-NEXT: [[L:%.*]] = load i32, i32* [[X_PRIV]] -; 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 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]] +; IS__TUNIT_OPM-NEXT: [[L:%.*]] = load i32, i32* [[X]] +; 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]] +; IS__TUNIT_NPM-NEXT: [[L:%.*]] = load i32, i32* [[X_PRIV]] +; 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 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]] +; IS__CGSCC_OPM-NEXT: [[L:%.*]] = load i32, i32* [[X]] +; 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]] +; IS__CGSCC_NPM-NEXT: [[L:%.*]] = load i32, i32* [[X_PRIV]] +; IS__CGSCC_NPM-NEXT: [[A:%.*]] = add i32 [[L]], [[TMP2]] +; IS__CGSCC_NPM-NEXT: ret i32 [[A]] ; entry: @@ -39,21 +85,59 @@ ; 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 [[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 [[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 [[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 [[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 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 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 dereferenceable(4) [[X:%.*]], i32* nocapture nofree nonnull readonly dereferenceable(4) [[Y:%.*]]) +; IS__CGSCC____-NEXT: [[A:%.*]] = load i32, i32* [[X]] +; IS__CGSCC____-NEXT: [[B:%.*]] = load i32, i32* [[Y]] +; 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 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 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 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]] +; 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]] +; 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,35 @@ } define i32 @test(i32* %X) { -; CHECK-LABEL: define {{[^@]+}}@test -; CHECK-SAME: (i32* nocapture nofree readonly [[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 [[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 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_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: [[C0:%.*]] = call i32 @f(i32 [[TMP0]], i64 [[TMP1]]) +; IS__TUNIT_NPM-NEXT: [[S_CAST1:%.*]] = bitcast %struct.ss* [[S]] to i32* +; IS__TUNIT_NPM-NEXT: [[TMP2:%.*]] = 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: [[TMP3:%.*]] = load i64, i64* [[S_0_12]], 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,15 +1,24 @@ ; 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 -; CHECK-NEXT: [[Z:%.*]] = load i32, i32* [[Y]] -; CHECK-NEXT: ret i32 [[Z]] +; IS__TUNIT____-LABEL: define {{[^@]+}}@test() +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: [[Y:%.*]] = load i32*, i32** @G2, align 8 +; IS__TUNIT____-NEXT: [[Z:%.*]] = load i32, i32* [[Y]] +; IS__TUNIT____-NEXT: ret i32 [[Z]] +; +; IS__CGSCC____-LABEL: define {{[^@]+}}@test() +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: [[Y:%.*]] = load i32*, i32** @G2 +; IS__CGSCC____-NEXT: [[Z:%.*]] = load i32, i32* [[Y]] +; IS__CGSCC____-NEXT: ret i32 [[Z]] ; entry: %y = load i32*, i32** %x 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=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 ; 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=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-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]] +; IS__CGSCC____-NEXT: [[B:%.*]] = load i32, i32* [[B_GEP]] +; 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 --- a/llvm/test/Transforms/Attributor/ArgumentPromotion/pr3085.ll +++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/pr3085.ll @@ -1,10 +1,34 @@ ; 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 ; PR 3085 %struct.Lit = type { i8 } define fastcc %struct.Lit* @import_lit(i32 %lit) nounwind { +; CHECK-LABEL: define {{[^@]+}}@import_lit +; CHECK-SAME: (i32 [[LIT:%.*]]) +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 false, label [[BB:%.*]], label [[BB1:%.*]] +; CHECK: bb: +; CHECK-NEXT: unreachable +; CHECK: bb1: +; CHECK-NEXT: br label [[BB3:%.*]] +; CHECK: bb2: +; CHECK-NEXT: unreachable +; CHECK: bb3: +; CHECK-NEXT: br i1 false, label [[BB2:%.*]], label [[BB6:%.*]] +; CHECK: bb6: +; CHECK-NEXT: br i1 false, label [[BB_I_I:%.*]], label [[BB1_I_I:%.*]] +; CHECK: bb.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i.i: +; CHECK-NEXT: br label [[INT2LIT_EXIT:%.*]] +; CHECK: int2lit.exit: +; CHECK-NEXT: ret %struct.Lit* null +; entry: br i1 false, label %bb, label %bb1 @@ -34,6 +58,1243 @@ } define fastcc i32 @picosat_main(i32 %argc, i8** %argv) nounwind { +; CHECK-LABEL: define {{[^@]+}}@picosat_main +; CHECK-SAME: (i32 [[ARGC:%.*]], i8** nocapture nofree readnone [[ARGV:%.*]]) +; CHECK-NEXT: entry: +; CHECK-NEXT: br i1 false, label [[BB_I:%.*]], label [[PICOSAT_TIME_STAMP_EXIT:%.*]] +; CHECK: bb.i: +; CHECK-NEXT: unreachable +; CHECK: picosat_time_stamp.exit: +; CHECK-NEXT: br label [[BB108:%.*]] +; CHECK: bb: +; CHECK-NEXT: unreachable +; CHECK: bb1: +; CHECK-NEXT: unreachable +; CHECK: bb2: +; CHECK-NEXT: unreachable +; CHECK: bb3: +; CHECK-NEXT: unreachable +; CHECK: bb4: +; CHECK-NEXT: unreachable +; CHECK: bb5: +; CHECK-NEXT: unreachable +; CHECK: bb6: +; CHECK-NEXT: unreachable +; CHECK: bb7: +; CHECK-NEXT: unreachable +; CHECK: bb8: +; CHECK-NEXT: unreachable +; CHECK: bb10: +; CHECK-NEXT: unreachable +; CHECK: bb12: +; CHECK-NEXT: unreachable +; CHECK: bb14: +; CHECK-NEXT: unreachable +; CHECK: bb15: +; CHECK-NEXT: unreachable +; CHECK: bb16: +; CHECK-NEXT: unreachable +; CHECK: bb17: +; CHECK-NEXT: unreachable +; CHECK: bb19: +; CHECK-NEXT: unreachable +; CHECK: bb20: +; CHECK-NEXT: unreachable +; CHECK: bb21: +; CHECK-NEXT: unreachable +; CHECK: bb22: +; CHECK-NEXT: unreachable +; CHECK: bb24: +; CHECK-NEXT: unreachable +; CHECK: bb26: +; CHECK-NEXT: unreachable +; CHECK: bb28: +; CHECK-NEXT: unreachable +; CHECK: bb29: +; CHECK-NEXT: unreachable +; CHECK: bb30: +; CHECK-NEXT: unreachable +; CHECK: bb31: +; CHECK-NEXT: unreachable +; CHECK: bb32: +; CHECK-NEXT: unreachable +; CHECK: bb33: +; CHECK-NEXT: unreachable +; CHECK: bb35: +; CHECK-NEXT: unreachable +; CHECK: bb36: +; CHECK-NEXT: unreachable +; CHECK: bb37: +; CHECK-NEXT: unreachable +; CHECK: bb38: +; CHECK-NEXT: unreachable +; CHECK: bb40: +; CHECK-NEXT: unreachable +; CHECK: bb41: +; CHECK-NEXT: unreachable +; CHECK: bb42: +; CHECK-NEXT: unreachable +; CHECK: bb43: +; CHECK-NEXT: unreachable +; CHECK: bb44: +; CHECK-NEXT: unreachable +; CHECK: bb45: +; CHECK-NEXT: unreachable +; CHECK: bb46: +; CHECK-NEXT: unreachable +; CHECK: bb47: +; CHECK-NEXT: unreachable +; CHECK: bb49: +; CHECK-NEXT: unreachable +; CHECK: bb50: +; CHECK-NEXT: unreachable +; CHECK: bb51: +; CHECK-NEXT: unreachable +; CHECK: bb52: +; CHECK-NEXT: unreachable +; CHECK: bb53: +; CHECK-NEXT: unreachable +; CHECK: bb54: +; CHECK-NEXT: unreachable +; CHECK: bb56: +; CHECK-NEXT: unreachable +; CHECK: bb57: +; CHECK-NEXT: unreachable +; CHECK: bb58: +; CHECK-NEXT: unreachable +; CHECK: bb59: +; CHECK-NEXT: unreachable +; CHECK: bb60: +; CHECK-NEXT: unreachable +; CHECK: bb61: +; CHECK-NEXT: unreachable +; CHECK: bb63: +; CHECK-NEXT: unreachable +; CHECK: bb64: +; CHECK-NEXT: unreachable +; CHECK: bb65: +; CHECK-NEXT: unreachable +; CHECK: bb66: +; CHECK-NEXT: unreachable +; CHECK: bb67: +; CHECK-NEXT: unreachable +; CHECK: bb68: +; CHECK-NEXT: unreachable +; CHECK: bb70: +; CHECK-NEXT: unreachable +; CHECK: bb71: +; CHECK-NEXT: unreachable +; CHECK: bb72: +; CHECK-NEXT: unreachable +; CHECK: bb73: +; CHECK-NEXT: unreachable +; CHECK: bb74: +; CHECK-NEXT: unreachable +; CHECK: bb75: +; CHECK-NEXT: unreachable +; CHECK: bb76: +; CHECK-NEXT: unreachable +; CHECK: bb77: +; CHECK-NEXT: unreachable +; CHECK: bb79: +; CHECK-NEXT: unreachable +; CHECK: bb80: +; CHECK-NEXT: unreachable +; CHECK: bb81: +; CHECK-NEXT: unreachable +; CHECK: bb82: +; CHECK-NEXT: unreachable +; CHECK: bb83: +; CHECK-NEXT: unreachable +; CHECK: bb84: +; CHECK-NEXT: unreachable +; CHECK: bb86: +; CHECK-NEXT: unreachable +; CHECK: bb87: +; CHECK-NEXT: unreachable +; CHECK: bb88: +; CHECK-NEXT: unreachable +; CHECK: bb89: +; CHECK-NEXT: unreachable +; CHECK: bb90: +; CHECK-NEXT: unreachable +; CHECK: bb91: +; CHECK-NEXT: unreachable +; CHECK: bb93: +; CHECK-NEXT: unreachable +; CHECK: bb94: +; CHECK-NEXT: unreachable +; CHECK: bb95: +; CHECK-NEXT: unreachable +; CHECK: bb97: +; CHECK-NEXT: unreachable +; CHECK: bb98: +; CHECK-NEXT: unreachable +; CHECK: bb1.i24: +; CHECK-NEXT: unreachable +; CHECK: bb99: +; CHECK-NEXT: unreachable +; CHECK: bb100: +; CHECK-NEXT: unreachable +; CHECK: bb101: +; CHECK-NEXT: unreachable +; CHECK: bb102: +; CHECK-NEXT: unreachable +; CHECK: bb103: +; CHECK-NEXT: unreachable +; CHECK: bb104: +; CHECK-NEXT: unreachable +; CHECK: bb105: +; CHECK-NEXT: unreachable +; CHECK: bb106: +; CHECK-NEXT: unreachable +; CHECK: bb108: +; CHECK-NEXT: br i1 false, label [[BB:%.*]], label [[BB110:%.*]] +; CHECK: bb110: +; CHECK-NEXT: br i1 false, label [[BB112:%.*]], label [[BB171:%.*]] +; CHECK: bb112: +; CHECK-NEXT: unreachable +; CHECK: bb113: +; CHECK-NEXT: unreachable +; CHECK: bb114: +; CHECK-NEXT: unreachable +; CHECK: bb.i.i35: +; CHECK-NEXT: unreachable +; CHECK: bb1.i.i36: +; CHECK-NEXT: unreachable +; CHECK: bb5.i.i.i41: +; CHECK-NEXT: unreachable +; CHECK: bb6.i.i.i42: +; CHECK-NEXT: unreachable +; CHECK: bb7.i.i.i43: +; CHECK-NEXT: unreachable +; CHECK: bb8.i.i.i44: +; CHECK-NEXT: unreachable +; CHECK: bb14.i.i: +; CHECK-NEXT: unreachable +; CHECK: picosat_init.exit: +; CHECK-NEXT: unreachable +; CHECK: bb115: +; CHECK-NEXT: unreachable +; CHECK: bb116: +; CHECK-NEXT: unreachable +; CHECK: bb118: +; CHECK-NEXT: unreachable +; CHECK: bb119: +; CHECK-NEXT: unreachable +; CHECK: bb120: +; CHECK-NEXT: unreachable +; CHECK: bb121: +; CHECK-NEXT: unreachable +; CHECK: bb122: +; CHECK-NEXT: unreachable +; CHECK: bb126: +; CHECK-NEXT: unreachable +; CHECK: bb127: +; CHECK-NEXT: unreachable +; CHECK: bb128: +; CHECK-NEXT: unreachable +; CHECK: SKIP_COMMENTS.i.loopexit: +; CHECK-NEXT: unreachable +; CHECK: SKIP_COMMENTS.i: +; CHECK-NEXT: unreachable +; CHECK: bb.i149.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb.i149: +; CHECK-NEXT: unreachable +; CHECK: bb3.i152: +; CHECK-NEXT: unreachable +; CHECK: SKIP_COMMENTS.i.backedge: +; CHECK-NEXT: unreachable +; CHECK: bb4.i153: +; CHECK-NEXT: unreachable +; CHECK: bb5.i154: +; CHECK-NEXT: unreachable +; CHECK: bb6.i155.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb6.i155: +; CHECK-NEXT: unreachable +; CHECK: bb7.i156: +; CHECK-NEXT: unreachable +; CHECK: bb8.i157: +; CHECK-NEXT: unreachable +; CHECK: bb9.i158: +; CHECK-NEXT: unreachable +; CHECK: bb10.i159: +; CHECK-NEXT: unreachable +; CHECK: bb11.i160.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb11.i160: +; CHECK-NEXT: unreachable +; CHECK: bb12.i161: +; CHECK-NEXT: unreachable +; CHECK: bb15.i165.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb14.i163: +; CHECK-NEXT: unreachable +; CHECK: bb15.i165: +; CHECK-NEXT: unreachable +; CHECK: bb16.i166: +; CHECK-NEXT: unreachable +; CHECK: bb17.i167.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb17.i167: +; CHECK-NEXT: unreachable +; CHECK: bb18.i168: +; CHECK-NEXT: unreachable +; CHECK: bb21.i172.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb20.i170: +; CHECK-NEXT: unreachable +; CHECK: bb21.i172: +; CHECK-NEXT: unreachable +; CHECK: bb22.i173: +; CHECK-NEXT: unreachable +; CHECK: bb24.i175: +; CHECK-NEXT: unreachable +; CHECK: bb25.i176: +; CHECK-NEXT: unreachable +; CHECK: bb26.i180: +; CHECK-NEXT: unreachable +; CHECK: bb.i.i181: +; CHECK-NEXT: unreachable +; CHECK: bb3.i.i184.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb2.i.i183: +; CHECK-NEXT: unreachable +; CHECK: bb3.i.i184: +; CHECK-NEXT: unreachable +; CHECK: bb4.i.i185: +; CHECK-NEXT: unreachable +; CHECK: bb.i.i.i186: +; CHECK-NEXT: unreachable +; CHECK: picosat_adjust.exit.i: +; CHECK-NEXT: unreachable +; CHECK: bb27.i187: +; CHECK-NEXT: unreachable +; CHECK: bb28.i188: +; CHECK-NEXT: unreachable +; CHECK: READ_LITERAL.i.outer: +; CHECK-NEXT: unreachable +; CHECK: READ_LITERAL.i.loopexit: +; CHECK-NEXT: unreachable +; CHECK: READ_LITERAL.i: +; CHECK-NEXT: unreachable +; CHECK: bb29.i189.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb29.i189: +; CHECK-NEXT: unreachable +; CHECK: bb33.i193: +; CHECK-NEXT: unreachable +; CHECK: bb35.i195: +; CHECK-NEXT: unreachable +; CHECK: bb38.i198: +; CHECK-NEXT: unreachable +; CHECK: bb39.i199: +; CHECK-NEXT: unreachable +; CHECK: READ_LITERAL.i.backedge: +; CHECK-NEXT: unreachable +; CHECK: bb40.i200: +; CHECK-NEXT: unreachable +; CHECK: bb41.i201: +; CHECK-NEXT: unreachable +; CHECK: bb42.i202: +; CHECK-NEXT: unreachable +; CHECK: bb46.i.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb45.i: +; CHECK-NEXT: unreachable +; CHECK: bb46.i: +; CHECK-NEXT: unreachable +; CHECK: bb47.i: +; CHECK-NEXT: unreachable +; CHECK: bb50.i: +; CHECK-NEXT: unreachable +; CHECK: bb51.i: +; CHECK-NEXT: unreachable +; CHECK: bb54.i: +; CHECK-NEXT: unreachable +; CHECK: bb55.i: +; CHECK-NEXT: unreachable +; CHECK: bb56.i: +; CHECK-NEXT: unreachable +; CHECK: bb.i8.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i9.i: +; CHECK-NEXT: unreachable +; CHECK: bb2.i10.i: +; CHECK-NEXT: unreachable +; CHECK: bb3.i11.i: +; CHECK-NEXT: unreachable +; CHECK: bb6.i.i207: +; CHECK-NEXT: unreachable +; CHECK: bb7.i.i208: +; CHECK-NEXT: unreachable +; CHECK: bb.i.i.i.i210.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb.i.i.i.i210: +; CHECK-NEXT: unreachable +; CHECK: bb17.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb18.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb19.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb20.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb21.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb22.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb23.i.i.i.i.outer: +; CHECK-NEXT: unreachable +; CHECK: bb23.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb26.i.i.i.i.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb26.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb27.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb28.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb29.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb33.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb34.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb35.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb37.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb38.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb39.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb40.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb42.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb43.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb.i.i.i.i210.backedge: +; CHECK-NEXT: unreachable +; CHECK: bb44.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb46.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb53.i.i.i.i.preheader.loopexit: +; CHECK-NEXT: unreachable +; CHECK: bb53.i.i.i.i.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb47.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb50.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb51.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb52.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb53.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb59.i.i.i.i.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb55.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb56.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb57.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb58.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb59.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb60.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb61.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb62.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb63.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb65.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb67.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb68.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb69.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb70.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb.i.i12.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i.i.i213: +; CHECK-NEXT: unreachable +; CHECK: bb2.i.i.i214: +; CHECK-NEXT: unreachable +; CHECK: bb4.i.i.i217: +; CHECK-NEXT: unreachable +; CHECK: bb5.i.i.i218: +; CHECK-NEXT: unreachable +; CHECK: READ_LITERAL.i.outer.backedge: +; CHECK-NEXT: unreachable +; CHECK: parse.exit.loopexit: +; CHECK-NEXT: unreachable +; CHECK: parse.exit: +; CHECK-NEXT: unreachable +; CHECK: bb129: +; CHECK-NEXT: unreachable +; CHECK: bb130: +; CHECK-NEXT: unreachable +; CHECK: bb142.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb132: +; CHECK-NEXT: unreachable +; CHECK: bb133: +; CHECK-NEXT: unreachable +; CHECK: bb134: +; CHECK-NEXT: unreachable +; CHECK: bb135: +; CHECK-NEXT: unreachable +; CHECK: bb136: +; CHECK-NEXT: unreachable +; CHECK: bb137: +; CHECK-NEXT: unreachable +; CHECK: bb138: +; CHECK-NEXT: unreachable +; CHECK: bb139: +; CHECK-NEXT: unreachable +; CHECK: bb2.i126: +; CHECK-NEXT: unreachable +; CHECK: bb3.i127: +; CHECK-NEXT: unreachable +; CHECK: bb5.i130: +; CHECK-NEXT: unreachable +; CHECK: picosat_assume.exit: +; CHECK-NEXT: unreachable +; CHECK: bb140: +; CHECK-NEXT: unreachable +; CHECK: bb141: +; CHECK-NEXT: unreachable +; CHECK: bb142: +; CHECK-NEXT: unreachable +; CHECK: bb143.loopexit: +; CHECK-NEXT: unreachable +; CHECK: bb143: +; CHECK-NEXT: unreachable +; CHECK: bb144: +; CHECK-NEXT: unreachable +; CHECK: bb5.i114: +; CHECK-NEXT: unreachable +; CHECK: bb11.i: +; CHECK-NEXT: unreachable +; CHECK: bb12.i: +; CHECK-NEXT: unreachable +; CHECK: bb.i.i.i118: +; CHECK-NEXT: unreachable +; CHECK: bb1.i.i.i119: +; CHECK-NEXT: unreachable +; CHECK: int2lit.exit.i: +; CHECK-NEXT: unreachable +; CHECK: bb13.i: +; CHECK-NEXT: unreachable +; CHECK: bb14.i: +; CHECK-NEXT: unreachable +; CHECK: bb17.i: +; CHECK-NEXT: unreachable +; CHECK: bb18.i: +; CHECK-NEXT: unreachable +; CHECK: bb19.i: +; CHECK-NEXT: unreachable +; CHECK: bb20.i: +; CHECK-NEXT: unreachable +; CHECK: bb24.i: +; CHECK-NEXT: unreachable +; CHECK: bb25.i: +; CHECK-NEXT: unreachable +; CHECK: bb26.i: +; CHECK-NEXT: unreachable +; CHECK: bb27.i: +; CHECK-NEXT: unreachable +; CHECK: bb28.i: +; CHECK-NEXT: unreachable +; CHECK: bb29.i: +; CHECK-NEXT: unreachable +; CHECK: bb33.i: +; CHECK-NEXT: unreachable +; CHECK: bb34.i: +; CHECK-NEXT: unreachable +; CHECK: bb.i.i58.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i.i59.i: +; CHECK-NEXT: unreachable +; CHECK: int2lit.exit63.i: +; CHECK-NEXT: unreachable +; CHECK: bb35.i: +; CHECK-NEXT: unreachable +; CHECK: bb36.i: +; CHECK-NEXT: unreachable +; CHECK: bb37.i: +; CHECK-NEXT: unreachable +; CHECK: bb38.i: +; CHECK-NEXT: unreachable +; CHECK: bb39.i: +; CHECK-NEXT: unreachable +; CHECK: bb40.i: +; CHECK-NEXT: unreachable +; CHECK: bb41.i: +; CHECK-NEXT: unreachable +; CHECK: bb42.i: +; CHECK-NEXT: unreachable +; CHECK: bb43.i: +; CHECK-NEXT: unreachable +; CHECK: bb44.i: +; CHECK-NEXT: unreachable +; CHECK: picosat_print.exit: +; CHECK-NEXT: unreachable +; CHECK: bb145: +; CHECK-NEXT: unreachable +; CHECK: bb146: +; CHECK-NEXT: unreachable +; CHECK: bb147: +; CHECK-NEXT: unreachable +; CHECK: bb148: +; CHECK-NEXT: unreachable +; CHECK: bb149: +; CHECK-NEXT: unreachable +; CHECK: bb.i54: +; CHECK-NEXT: unreachable +; CHECK: bb1.i55: +; CHECK-NEXT: unreachable +; CHECK: bb.i.i56: +; CHECK-NEXT: unreachable +; CHECK: bb1.i.i57: +; CHECK-NEXT: unreachable +; CHECK: bb2.i.i58: +; CHECK-NEXT: unreachable +; CHECK: bb3.i.i59: +; CHECK-NEXT: unreachable +; CHECK: bb5.i.i61: +; CHECK-NEXT: unreachable +; CHECK: bb1.i.i.i63: +; CHECK-NEXT: unreachable +; CHECK: bb6.i.i65: +; CHECK-NEXT: unreachable +; CHECK: bb7.i.i66: +; CHECK-NEXT: unreachable +; CHECK: bb8.i.i67: +; CHECK-NEXT: unreachable +; CHECK: bb10.i.i69: +; CHECK-NEXT: unreachable +; CHECK: bb1.i61.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb11.i.i70: +; CHECK-NEXT: unreachable +; CHECK: bb13.i.i71.outer: +; CHECK-NEXT: unreachable +; CHECK: bb13.i.i71: +; CHECK-NEXT: unreachable +; CHECK: bb14.i.i72: +; CHECK-NEXT: unreachable +; CHECK: bb15.i.i73: +; CHECK-NEXT: unreachable +; CHECK: bb16.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb.i.i79.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb.i.i.i80.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i.i.i81.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb2.i.i.i82.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb3.i.i.i83.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb4.i.i.i85.i.i: +; CHECK-NEXT: unreachable +; CHECK: crescore.exit.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: incincs.exit.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb13.i.i71.backedge: +; CHECK-NEXT: unreachable +; CHECK: bb19.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i68.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb20.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb21.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb22.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb23.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb24.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb26.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb27.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb28.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i55.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb29.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb31.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i48.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb33.i.i.loopexit: +; CHECK-NEXT: unreachable +; CHECK: bb33.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb34.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb2.i44.i.i76: +; CHECK-NEXT: unreachable +; CHECK: bb35.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb.i35.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i37.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb36.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb.i18.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb22.i19.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb24.i22.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb25.i23.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb26.i24.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb27.i25.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb32.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb33.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb34.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb38.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb39.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb40.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb45.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb48.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb53.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb58.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb59.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb60.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb64.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb65.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb66.i.i.i.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb66.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb67.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb68.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb69.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb70.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb71.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb72.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb73.i.i.i.outer: +; CHECK-NEXT: unreachable +; CHECK: bb73.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb76.i.i.i.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb76.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb77.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb78.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb79.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb83.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb84.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb85.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb87.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb88.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb89.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb90.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb92.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb93.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb66.i.i.i.backedge: +; CHECK-NEXT: unreachable +; CHECK: bb94.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb96.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb103.i.i.i.preheader.loopexit: +; CHECK-NEXT: unreachable +; CHECK: bb103.i.i.i.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb97.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb100.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb101.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb102.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb103.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb109.i.i.i.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb105.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb106.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb107.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb108.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb109.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb110.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb111.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb113.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb114.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb116.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb122.i.i.i.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb117.i.i.i.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb117.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb118.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb122.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb123.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb124.i.i.i.loopexit: +; CHECK-NEXT: unreachable +; CHECK: bb124.i.i.i.loopexit1: +; CHECK-NEXT: unreachable +; CHECK: bb124.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb125.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb130.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb132.i.i.i.outer: +; CHECK-NEXT: unreachable +; CHECK: bb132.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb133.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb134.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb135.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb136.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb137.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb37.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb38.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb39.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb3.i12.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb5.i14.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb6.i15.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb7.i.i.i78: +; CHECK-NEXT: unreachable +; CHECK: bb8.i.i.i79: +; CHECK-NEXT: unreachable +; CHECK: bb9.i.i.i80: +; CHECK-NEXT: unreachable +; CHECK: bb10.i.i.i81: +; CHECK-NEXT: unreachable +; CHECK: bb11.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb15.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb16.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb17.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb18.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb23.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb24.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb25.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb27.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb28.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb.i4.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb4.i.i16.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb29.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb40.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb9.i.i.i.i.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb.i.i.i.i84: +; CHECK-NEXT: unreachable +; CHECK: bb1.i.i.i.i85: +; CHECK-NEXT: unreachable +; CHECK: bb5.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb8.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb9.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb10.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb2.i.i.i87: +; CHECK-NEXT: unreachable +; CHECK: bb3.i.i.i88: +; CHECK-NEXT: unreachable +; CHECK: bb1.i23.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb4.i.i.i90: +; CHECK-NEXT: unreachable +; CHECK: bb1.i9.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb.i.i27.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i.i28.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: int2lit.exit32.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb2.i.i.i.i91: +; CHECK-NEXT: unreachable +; CHECK: bb3.i.i.i.i92: +; CHECK-NEXT: unreachable +; CHECK: bb4.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb2.i.i12.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb3.i.i13.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: gcd.exit.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb5.i14.i.i.i.preheader: +; CHECK-NEXT: unreachable +; CHECK: bb5.i14.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb.i.i.i17.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i.i.i18.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: int2lit.exit.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb8.i19.i.i.i.loopexit: +; CHECK-NEXT: unreachable +; CHECK: bb8.i19.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb5.i.i.i94: +; CHECK-NEXT: unreachable +; CHECK: bb.i2.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb2.i.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb3.i.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i.i.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb3.i.i.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb4.i.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb5.i.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i21.i.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb3.i24.i.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb6.i.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb8.i.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb9.i.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i8.i.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb3.i11.i.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb11.i.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb12.i.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: hpop.exit.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: sdecide.exit.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb6.i.i.i95: +; CHECK-NEXT: unreachable +; CHECK: decide.exit.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb42.i.i: +; CHECK-NEXT: unreachable +; CHECK: sat.exit.i.loopexit.loopexit: +; CHECK-NEXT: unreachable +; CHECK: sat.exit.i.loopexit.loopexit2: +; CHECK-NEXT: unreachable +; CHECK: sat.exit.i.loopexit: +; CHECK-NEXT: unreachable +; CHECK: sat.exit.i: +; CHECK-NEXT: unreachable +; CHECK: bb2.i96: +; CHECK-NEXT: unreachable +; CHECK: bb4.i98: +; CHECK-NEXT: unreachable +; CHECK: bb5.i99: +; CHECK-NEXT: unreachable +; CHECK: bb6.i100: +; CHECK-NEXT: unreachable +; CHECK: bb7.i: +; CHECK-NEXT: unreachable +; CHECK: bb.i1.i: +; CHECK-NEXT: unreachable +; CHECK: picosat_sat.exit: +; CHECK-NEXT: unreachable +; CHECK: bb150: +; CHECK-NEXT: unreachable +; CHECK: bb151: +; CHECK-NEXT: unreachable +; CHECK: bb152: +; CHECK-NEXT: unreachable +; CHECK: bb153: +; CHECK-NEXT: unreachable +; CHECK: bb154: +; CHECK-NEXT: unreachable +; CHECK: bb156: +; CHECK-NEXT: unreachable +; CHECK: bb157: +; CHECK-NEXT: unreachable +; CHECK: bb158: +; CHECK-NEXT: unreachable +; CHECK: bb159: +; CHECK-NEXT: unreachable +; CHECK: bb160: +; CHECK-NEXT: unreachable +; CHECK: bb163: +; CHECK-NEXT: unreachable +; CHECK: bb164: +; CHECK-NEXT: unreachable +; CHECK: bb.i11: +; CHECK-NEXT: unreachable +; CHECK: bb.i.i12: +; CHECK-NEXT: unreachable +; CHECK: bb1.i.i14: +; CHECK-NEXT: unreachable +; CHECK: bb2.i.i15: +; CHECK-NEXT: unreachable +; CHECK: bb3.i.i16: +; CHECK-NEXT: unreachable +; CHECK: bb7.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb.i.i.i.i17: +; CHECK-NEXT: unreachable +; CHECK: bb1.i.i.i.i18: +; CHECK-NEXT: unreachable +; CHECK: int2lit.exit.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb9.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb3.i: +; CHECK-NEXT: unreachable +; CHECK: bb4.i: +; CHECK-NEXT: unreachable +; CHECK: bb5.i: +; CHECK-NEXT: unreachable +; CHECK: bb6.i: +; CHECK-NEXT: unreachable +; CHECK: bb166: +; CHECK-NEXT: unreachable +; CHECK: bb167: +; CHECK-NEXT: unreachable +; CHECK: bb168: +; CHECK-NEXT: unreachable +; CHECK: bb169: +; CHECK-NEXT: unreachable +; CHECK: bb.i7: +; CHECK-NEXT: unreachable +; CHECK: picosat_time_stamp.exit9: +; CHECK-NEXT: unreachable +; CHECK: bb170: +; CHECK-NEXT: unreachable +; CHECK: bb.i.i3: +; CHECK-NEXT: unreachable +; CHECK: picosat_leave.exit: +; CHECK-NEXT: unreachable +; CHECK: bb.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb3.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb4.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb5.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb9.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb10.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: delete.exit.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i7.i.i.i: +; CHECK-NEXT: unreachable +; CHECK: delete_clauses.exit.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb2.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i.i23.i.i: +; CHECK-NEXT: unreachable +; CHECK: lrelease.exit.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb3.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb4.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i208.i.i: +; CHECK-NEXT: unreachable +; CHECK: delete.exit214.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i197.i.i: +; CHECK-NEXT: unreachable +; CHECK: delete.exit203.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i186.i.i: +; CHECK-NEXT: unreachable +; CHECK: delete.exit192.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i175.i.i: +; CHECK-NEXT: unreachable +; CHECK: delete.exit181.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i164.i.i: +; CHECK-NEXT: unreachable +; CHECK: delete.exit170.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i153.i.i: +; CHECK-NEXT: unreachable +; CHECK: delete.exit159.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i142.i.i: +; CHECK-NEXT: unreachable +; CHECK: delete.exit148.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i131.i.i: +; CHECK-NEXT: unreachable +; CHECK: delete.exit137.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i120.i.i: +; CHECK-NEXT: unreachable +; CHECK: delete.exit126.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i109.i.i: +; CHECK-NEXT: unreachable +; CHECK: delete.exit115.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i98.i.i: +; CHECK-NEXT: unreachable +; CHECK: delete.exit104.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i87.i.i: +; CHECK-NEXT: unreachable +; CHECK: delete.exit93.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i76.i.i: +; CHECK-NEXT: unreachable +; CHECK: delete.exit82.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i65.i.i: +; CHECK-NEXT: unreachable +; CHECK: delete.exit71.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i54.i.i: +; CHECK-NEXT: unreachable +; CHECK: delete.exit60.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i32.i.i: +; CHECK-NEXT: unreachable +; CHECK: delete.exit38.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i12.i.i: +; CHECK-NEXT: unreachable +; CHECK: delete.exit18.i.i: +; CHECK-NEXT: unreachable +; CHECK: bb1.i2.i.i: +; CHECK-NEXT: unreachable +; CHECK: picosat_reset.exit: +; CHECK-NEXT: unreachable +; CHECK: bb171: +; CHECK-NEXT: br i1 false, label [[BB173:%.*]], label [[BB172:%.*]] +; CHECK: bb172: +; CHECK-NEXT: br label [[BB173]] +; CHECK: bb173: +; CHECK-NEXT: br i1 false, label [[BB175:%.*]], label [[BB174:%.*]] +; CHECK: bb174: +; CHECK-NEXT: br label [[BB175]] +; CHECK: bb175: +; CHECK-NEXT: br i1 false, label [[BB177:%.*]], label [[BB176:%.*]] +; CHECK: bb176: +; CHECK-NEXT: br label [[BB177]] +; CHECK: bb177: +; CHECK-NEXT: br i1 false, label [[BB179:%.*]], label [[BB178:%.*]] +; CHECK: bb178: +; CHECK-NEXT: ret i32 0 +; CHECK: bb179: +; CHECK-NEXT: unreachable +; entry: br i1 false, label %bb.i, label %picosat_time_stamp.exit @@ -1915,6 +3176,27 @@ } define i32 @main(i32 %argc, i8** %argv) nounwind { +; CHECK-LABEL: define {{[^@]+}}@main +; CHECK-SAME: (i32 [[ARGC:%.*]], i8** nocapture nofree readnone [[ARGV:%.*]]) +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[BB2:%.*]] +; CHECK: bb: +; CHECK-NEXT: br i1 false, label [[BB3:%.*]], label [[BB2]] +; CHECK: bb2: +; CHECK-NEXT: br i1 false, label [[BB5_LOOPEXIT:%.*]], label [[BB:%.*]] +; CHECK: bb3: +; CHECK-NEXT: unreachable +; CHECK: bb4: +; CHECK-NEXT: unreachable +; CHECK: bb5.loopexit: +; CHECK-NEXT: unreachable +; CHECK: bb5: +; CHECK-NEXT: unreachable +; CHECK: bb6: +; CHECK-NEXT: unreachable +; CHECK: bb7: +; CHECK-NEXT: unreachable +; entry: br label %bb2 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=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" ; 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 dereferenceable(4) [[XP:%.*]]) +; IS__CGSCC____-NEXT: [[X:%.*]] = load i32, i32* [[XP]] +; 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=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 ; 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,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=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-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]] -; 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]] +; 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]] +; 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 dereferenceable(8) [[THIS:%.*]], i32* nocapture nofree nonnull sret writeonly 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]] +; IS__CGSCC____-NEXT: [[B:%.*]] = load i32, i32* [[BP]] +; IS__CGSCC____-NEXT: [[AB:%.*]] = add i32 [[A]], [[B]] +; IS__CGSCC____-NEXT: store i32 [[AB]], i32* [[R]] +; 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 +48,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=5 < %s | FileCheck %s +; RUN: opt -attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM +; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-disable=false -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=5 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM +; RUN: opt -attributor-cgscc -attributor-manifest-internal -attributor-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]] +; 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]] +; 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]] +; 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]] +; 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]] +; 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]] +; 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]] +; 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,26 @@ ; 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: [[CONV:%.*]] = sext i32 undef 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 {{[^@]+}}@fn2() +; IS__TUNIT_NPM-NEXT: entry: +; IS__TUNIT_NPM-NEXT: [[CONV:%.*]] = sext i32 undef 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 undef to i64 @@ -18,13 +30,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 +54,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________OPM-LABEL: define {{[^@]+}}@fn2c() +; IS________OPM-NEXT: entry: +; IS________OPM-NEXT: [[CONV:%.*]] = sext i32 undef to i64 +; IS________OPM-NEXT: [[ADD:%.*]] = add i64 42, [[CONV]] +; IS________OPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 [[ADD]]) +; IS________OPM-NEXT: ret i64 [[CALL2]] +; +; IS________NPM-LABEL: define {{[^@]+}}@fn2c() +; IS________NPM-NEXT: entry: +; IS________NPM-NEXT: [[CONV:%.*]] = sext i32 undef to i64 +; IS________NPM-NEXT: [[ADD:%.*]] = add i64 42, [[CONV]] +; IS________NPM-NEXT: [[CALL2:%.*]] = call i64 @fn1(i64 [[ADD]]) #1, !range !0 +; IS________NPM-NEXT: ret i64 [[CALL2]] ; 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,20 +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=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) { -; CHECK-LABEL: define {{[^@]+}}@fn2 -; CHECK-SAME: (i32* nocapture nofree writeonly [[P:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[IF_END:%.*]] -; CHECK: for.cond1: -; CHECK-NEXT: unreachable -; CHECK: if.end: -; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* undef, 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 writeonly [[P:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: br label [[IF_END:%.*]] +; IS__TUNIT____: for.cond1: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: if.end: +; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32, i32* undef, 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__CGSCC____-LABEL: define {{[^@]+}}@fn2 +; IS__CGSCC____-SAME: (i32* nocapture nofree nonnull writeonly dereferenceable(4) [[P:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br label [[IF_END:%.*]] +; IS__CGSCC____: for.cond1: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: if.end: +; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* undef, align 4 +; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @fn1(i32 [[TMP0]]) +; IS__CGSCC____-NEXT: store i32 [[CALL]], i32* [[P]] +; IS__CGSCC____-NEXT: br label [[FOR_COND1:%.*]] ; entry: br label %if.end @@ -45,17 +60,29 @@ } define void @fn_no_null_opt(i32* %P) #0 { -; CHECK-LABEL: define {{[^@]+}}@fn_no_null_opt -; CHECK-SAME: (i32* nocapture nofree writeonly [[P:%.*]]) -; CHECK-NEXT: entry: -; CHECK-NEXT: br label [[IF_END:%.*]] -; CHECK: for.cond1: -; CHECK-NEXT: unreachable -; CHECK: if.end: -; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* undef, 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:%.*]]) +; IS__TUNIT____-NEXT: entry: +; IS__TUNIT____-NEXT: br label [[IF_END:%.*]] +; IS__TUNIT____: for.cond1: +; IS__TUNIT____-NEXT: unreachable +; IS__TUNIT____: if.end: +; IS__TUNIT____-NEXT: [[TMP0:%.*]] = load i32, i32* undef, 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__CGSCC____-LABEL: define {{[^@]+}}@fn_no_null_opt +; IS__CGSCC____-SAME: (i32* nocapture nofree writeonly dereferenceable_or_null(4) [[P:%.*]]) +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br label [[IF_END:%.*]] +; IS__CGSCC____: for.cond1: +; IS__CGSCC____-NEXT: unreachable +; IS__CGSCC____: if.end: +; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* undef, align 4 +; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @fn0(i32 [[TMP0]]) +; IS__CGSCC____-NEXT: store i32 [[CALL]], i32* [[P]] +; IS__CGSCC____-NEXT: br label [[FOR_COND1:%.*]] ; 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=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=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 ; ; 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 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 dereferenceable(4) "no-capture-maybe-returned" [[V:%.*]]) +; IS__CGSCC____-NEXT: [[X:%.*]] = load i32, i32* [[V]] +; 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]] +; 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]] +; 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 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]] +; 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 @@ -9,7 +12,8 @@ ; CHECK-NEXT: [[X:%.*]] = call i32 @foo(i1 [[C]]) ; CHECK-NEXT: br label [[OK:%.*]] ; CHECK: OK: -; CHECK-NEXT: ret i1 true +; CHECK-NEXT: [[Y:%.*]] = icmp ne i32 52, 0 +; CHECK-NEXT: ret i1 [[Y]] ; CHECK: FAIL: ; CHECK-NEXT: unreachable ; @@ -24,13 +28,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 @@ -44,7 +56,8 @@ define i1 @caller(i1 %C) { ; CHECK-LABEL: define {{[^@]+}}@caller ; CHECK-SAME: (i1 [[C:%.*]]) -; CHECK-NEXT: ret i1 true +; CHECK-NEXT: [[Y:%.*]] = icmp ne i32 52, 0 +; CHECK-NEXT: ret i1 [[Y]] ; %X = call i32 @foo( i1 %C ) ; [#uses=1] %Y = icmp ne i32 %X, 0 ; [#uses=1] diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/return-constants.ll b/llvm/test/Transforms/Attributor/IPConstantProp/return-constants.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/return-constants.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/return-constants.ll @@ -1,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,18 @@ } define internal i32 @test1(i1 %c) { +; CHECK-LABEL: define {{[^@]+}}@test1 +; CHECK-SAME: (i1 [[C:%.*]]) +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[IF_THEN:%.*]] +; CHECK: if.then: +; CHECK-NEXT: [[RES:%.*]] = icmp eq i32 10, 10 +; CHECK-NEXT: br i1 [[RES]], label [[RET1:%.*]], label [[RET2:%.*]] +; CHECK: ret1: +; CHECK-NEXT: ret i32 99 +; CHECK: ret2: +; CHECK-NEXT: ret i32 0 +; entry: br label %if.then @@ -34,7 +60,8 @@ define i32 @main(i1 %c) { ; CHECK-LABEL: define {{[^@]+}}@main ; CHECK-SAME: (i1 [[C:%.*]]) -; CHECK-NEXT: ret i32 99 +; CHECK-NEXT: [[RES:%.*]] = call i32 @test1(i1 [[C]]) +; CHECK-NEXT: ret i32 [[RES]] ; %res = call i32 @test1(i1 %c) ret i32 %res diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/thread_local_acs.ll b/llvm/test/Transforms/Attributor/IPConstantProp/thread_local_acs.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/thread_local_acs.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/thread_local_acs.ll @@ -1,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]] +; 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]] +; 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,17 +719,16 @@ } 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 ret void } -; 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,32 @@ ; 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 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]] -; 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 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]] +; 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 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]] +; 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 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]] +; 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 +123,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 +185,32 @@ ; 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 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]] -; 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 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]] +; 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 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]] +; 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 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]] +; 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 +229,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 +293,32 @@ ; ; 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 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]] -; 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 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]] +; 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 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]] +; 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 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]] +; 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 +337,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 +406,32 @@ ; ; 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 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]] -; 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 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]] +; 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 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]] +; 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 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]] +; 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,33 +189,43 @@ 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 dereferenceable(4) %ptr, i1 %c) define void @f7_1(i32* %ptr, i1 %c) { - -; ATTRIBUTOR: %A = tail call i32 @unkown_f(i32* nonnull dereferenceable(4) %ptr) +; CHECK-LABEL: define {{[^@]+}}@f7_1 +; CHECK-SAME: (i32* nonnull dereferenceable(4) [[PTR:%.*]], i1 [[C:%.*]]) +; CHECK-NEXT: [[A:%.*]] = tail call i32 @unkown_f(i32* nonnull dereferenceable(4) [[PTR]]) +; CHECK-NEXT: [[B:%.*]] = tail call i32 @unkown_f(i32* nonnull 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 dereferenceable(8) [[PTR]]) +; CHECK-NEXT: [[D:%.*]] = tail call i32 @unkown_f(i32* nonnull dereferenceable(8) [[PTR]]) +; CHECK-NEXT: [[E:%.*]] = tail call i32 @unkown_f(i32* nonnull 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 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 dereferenceable(8) %ptr) %C = tail call i32 @unkown_f(i32* %ptr) -; ATTRIBUTOR: %D = tail call i32 @unkown_f(i32* nonnull dereferenceable(8) %ptr) %D = tail call i32 @unkown_f(i32* dereferenceable(8) %ptr) -; ATTRIBUTOR: %E = tail call i32 @unkown_f(i32* nonnull dereferenceable(8) %ptr) %E = tail call i32 @unkown_f(i32* %ptr) ret void @@ -154,31 +234,38 @@ 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 dereferenceable(4) i32* @unkown_ptr() +; CHECK-NEXT: [[A:%.*]] = tail call i32 @unkown_f(i32* nonnull dereferenceable(4) [[PTR]]) +; CHECK-NEXT: [[B:%.*]] = tail call i32 @unkown_f(i32* nonnull 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 dereferenceable(8) [[PTR]]) +; CHECK-NEXT: [[D:%.*]] = tail call i32 @unkown_f(i32* nonnull dereferenceable(8) [[PTR]]) +; CHECK-NEXT: [[E:%.*]] = tail call i32 @unkown_f(i32* nonnull 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 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 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 dereferenceable(8) %ptr) %C = tail call i32 @unkown_f(i32* %ptr) -; ATTRIBUTOR: %D = tail call i32 @unkown_f(i32* nonnull 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 dereferenceable(8) %ptr) ret void @@ -187,28 +274,39 @@ } 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 i32* @test_for_minus_index(i32* nofree nonnull writeonly "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 "no-capture-maybe-returned" [[P:%.*]]) +; CHECK-NEXT: [[Q:%.*]] = getelementptr inbounds i32, i32* [[P]], i32 -2 +; CHECK-NEXT: store i32 1, i32* [[Q]] +; 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 dereferenceable(100) %0) +; CHECK-LABEL: define {{[^@]+}}@deref_or_null_and_nonnull +; CHECK-SAME: (i32* nocapture nofree nonnull writeonly dereferenceable(100) [[TMP0:%.*]]) +; CHECK-NEXT: store i32 1, i32* [[TMP0]] +; 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 +321,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 +355,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 +392,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 +411,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 +419,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 +439,7 @@ tail call void @use2(i8* dereferenceable(4) %a, i8* %b) ret void } + ; More complex test ; { ; fun1(dereferenceable(4) %a) @@ -341,9 +452,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 +497,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 +570,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 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,11 +1,29 @@ -; RUN: opt < %s -attributor --attributor-disable=false -S | FileCheck %s --check-prefix=ATTRIBUTOR -; 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 @@ -27,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 @@ -35,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 @@ -59,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 @@ -74,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 dereferenceable(8) %ptr2) +; CHECK-LABEL: define {{[^@]+}}@ordering +; CHECK-SAME: (i8* nocapture nofree nonnull readnone dereferenceable(3) [[PTR1:%.*]], i32* nocapture nofree nonnull readnone 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 @@ -91,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: @@ -107,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: @@ -125,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 dereferenceable(4) %ptr, i1 %cond) +; CHECK-LABEL: define {{[^@]+}}@partial_in_entry +; CHECK-SAME: (i16* nocapture nofree nonnull readnone 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 @@ -144,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 %ptr) +; CHECK-LABEL: define {{[^@]+}}@volatile_is_not_dereferenceable +; CHECK-SAME: (i16* nofree [[PTR:%.*]]) +; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr i16, i16* [[PTR]], i64 0 +; CHECK-NEXT: [[T0:%.*]] = load volatile i16, i16* [[ARRAYIDX0]] +; 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 @@ -157,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 @@ -170,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 dereferenceable(2) %ptr) +; CHECK-LABEL: define {{[^@]+}}@not_guaranteed_to_transfer_execution +; CHECK-SAME: (i16* nocapture nofree nonnull readnone 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 @@ -184,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 @@ -197,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 @@ -206,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 dereferenceable(2) %ptr) +; CHECK-LABEL: define {{[^@]+}}@not_byte_multiple +; CHECK-SAME: (i9* nocapture nofree nonnull readnone dereferenceable(2) [[PTR:%.*]]) +; CHECK-NEXT: ret void +; %arrayidx0 = getelementptr i9, i9* %ptr, i64 0 %t0 = load i9, i9* %arrayidx0 ret void @@ -215,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 %ptr) +; CHECK-LABEL: define {{[^@]+}}@no_pointer_deref +; CHECK-SAME: (i16* nocapture nofree readnone [[PTR:%.*]]) +; CHECK-NEXT: ret void +; %arrayidx1 = getelementptr i16, i16* %ptr, i64 1 %arrayidx2 = getelementptr i16, i16* %ptr, i64 2 %t1 = load i16, i16* %arrayidx1 @@ -226,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 dereferenceable(8) %ptr) +; CHECK-LABEL: define {{[^@]+}}@non_consecutive +; CHECK-SAME: (i32* nocapture nofree nonnull readnone 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 @@ -239,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 dereferenceable(16) %ptr) +; CHECK-LABEL: define {{[^@]+}}@more_bytes +; CHECK-SAME: (i32* nocapture nofree nonnull readnone 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 @@ -254,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 dereferenceable(16) %ptr) +; CHECK-LABEL: define {{[^@]+}}@more_bytes_and_not_null +; CHECK-SAME: (i32* nocapture nofree nonnull readnone 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 @@ -269,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 dereferenceable(100) %ptr) +; CHECK-LABEL: define {{[^@]+}}@better_bytes +; CHECK-SAME: (i32* nocapture nofree nonnull readnone 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 @@ -282,7 +382,10 @@ } define void @bitcast(i32* %arg) { -; ATTRIBUTOR-LABEL: @bitcast(i32* nocapture nofree nonnull readnone dereferenceable(8) %arg) +; CHECK-LABEL: define {{[^@]+}}@bitcast +; CHECK-SAME: (i32* nocapture nofree nonnull readnone 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 @@ -292,7 +395,10 @@ } define void @bitcast_different_sizes(double* %arg1, i8* %arg2) { -; ATTRIBUTOR-LABEL: @bitcast_different_sizes(double* nocapture nofree nonnull readnone dereferenceable(12) %arg1, i8* nocapture nofree nonnull readnone dereferenceable(16) %arg2) +; CHECK-LABEL: define {{[^@]+}}@bitcast_different_sizes +; CHECK-SAME: (double* nocapture nofree nonnull readnone dereferenceable(12) [[ARG1:%.*]], i8* nocapture nofree nonnull readnone 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 @@ -310,7 +416,10 @@ } define void @negative_offset(i32* %arg) { -; ATTRIBUTOR-LABEL: @negative_offset(i32* nocapture nofree nonnull readnone dereferenceable(4) %arg) +; CHECK-LABEL: define {{[^@]+}}@negative_offset +; CHECK-SAME: (i32* nocapture nofree nonnull readnone 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 @@ -320,7 +429,15 @@ } define void @stores(i32* %arg) { -; ATTRIBUTOR-LABEL: @stores(i32* nocapture nofree nonnull writeonly dereferenceable(8) %arg) +; CHECK-LABEL: define {{[^@]+}}@stores +; CHECK-SAME: (i32* nocapture nofree nonnull writeonly 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]] +; CHECK-NEXT: store float 2.000000e+00, float* [[ARRAYIDX1]] +; CHECK-NEXT: ret void +; %ptr = bitcast i32* %arg to float* %arrayidx0 = getelementptr float, float* %ptr, i64 0 %arrayidx1 = getelementptr float, float* %ptr, i64 1 @@ -330,7 +447,13 @@ } define void @load_store(i32* %arg) { -; ATTRIBUTOR-LABEL: @load_store(i32* nocapture nofree nonnull writeonly dereferenceable(8) %arg) +; CHECK-LABEL: define {{[^@]+}}@load_store +; CHECK-SAME: (i32* nocapture nofree nonnull writeonly 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]] +; CHECK-NEXT: ret void +; %ptr = bitcast i32* %arg to float* %arrayidx0 = getelementptr float, float* %ptr, i64 0 %arrayidx1 = getelementptr float, float* %ptr, i64 1 @@ -340,7 +463,13 @@ } define void @different_size1(i32* %arg) { -; ATTRIBUTOR-LABEL: @different_size1(i32* nocapture nofree nonnull writeonly dereferenceable(8) %arg) +; CHECK-LABEL: define {{[^@]+}}@different_size1 +; CHECK-SAME: (i32* nocapture nofree nonnull writeonly dereferenceable(8) [[ARG:%.*]]) +; CHECK-NEXT: [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double* +; CHECK-NEXT: store double 0.000000e+00, double* [[ARG_CAST]] +; CHECK-NEXT: store i32 0, i32* [[ARG]] +; CHECK-NEXT: ret void +; %arg-cast = bitcast i32* %arg to double* store double 0.000000e+00, double* %arg-cast store i32 0, i32* %arg @@ -348,7 +477,13 @@ } define void @different_size2(i32* %arg) { -; ATTRIBUTOR-LABEL: @different_size2(i32* nocapture nofree nonnull writeonly dereferenceable(8) %arg) +; CHECK-LABEL: define {{[^@]+}}@different_size2 +; CHECK-SAME: (i32* nocapture nofree nonnull writeonly dereferenceable(8) [[ARG:%.*]]) +; CHECK-NEXT: store i32 0, i32* [[ARG]] +; CHECK-NEXT: [[ARG_CAST:%.*]] = bitcast i32* [[ARG]] to double* +; CHECK-NEXT: store double 0.000000e+00, double* [[ARG_CAST]] +; CHECK-NEXT: ret void +; store i32 0, i32* %arg %arg-cast = bitcast i32* %arg to double* store double 0.000000e+00, double* %arg-cast 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,22 +129,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 +; 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 } @@ -103,9 +169,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 @@ -116,7 +224,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 @@ -126,21 +233,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 @@ -150,11 +281,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 } @@ -162,30 +300,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* nocapture nofree [[TMP1]]) +; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +; CHECK-NEXT: store i32 10, i32* [[TMP2]] +; CHECK-NEXT: tail call void @foo(i32* [[TMP2]]) +; CHECK-NEXT: tail call void @free(i8* nonnull 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* 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 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* nocapture nofree [[TMP1]]) +; CHECK-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +; CHECK-NEXT: store i32 10, i32* [[TMP2]] +; CHECK-NEXT: tail call void @foo_nounw(i32* nofree [[TMP2]]) +; CHECK-NEXT: tail call void @free(i8* nonnull 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* 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 dereferenceable(4) %1) tail call void @free(i8* %1) ret void } @@ -193,39 +343,77 @@ ; 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]] +; IS________OPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]] +; IS________OPM-NEXT: tail call void @free(i8* noalias nonnull 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]] +; IS________NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]] +; 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 dereferenceable(4) [[TMP1]]) +; IS________OPM-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +; IS________OPM-NEXT: store i32 10, i32* [[TMP2]] +; IS________OPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]] +; IS________OPM-NEXT: tail call void @free(i8* noalias nonnull 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 dereferenceable(4) [[TMP1]]) +; IS________NPM-NEXT: [[TMP2:%.*]] = bitcast i8* [[TMP1]] to i32* +; IS________NPM-NEXT: store i32 10, i32* [[TMP2]] +; IS________NPM-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]] +; 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 } -; TEST 11 +; 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 @@ -233,8 +421,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 @@ -274,6 +521,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 @@ -288,7 +575,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 @@ -299,104 +585,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]] +; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]] +; CHECK-NEXT: tail call void @free(i8* noalias nonnull 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 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]] +; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]] +; CHECK-NEXT: tail call void @free(i8* noalias nonnull 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 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]] +; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]] +; CHECK-NEXT: tail call void @free(i8* noalias nonnull 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 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=6 < %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=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 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,12 @@ ; 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 +; 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 ; 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*)] +; 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 +26,21 @@ ; 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: [[TMP1:%.*]] = icmp slt i32 10, 1 +; IS__CGSCC____-NEXT: br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP4:%.*]] +; IS__CGSCC____: 2: +; IS__CGSCC____-NEXT: [[TMP3:%.*]] = phi i32 [ 1, [[TMP0:%.*]] ], [ [[TMP7:%.*]], [[TMP4]] ] +; IS__CGSCC____-NEXT: ret i32 undef +; IS__CGSCC____: 4: +; IS__CGSCC____-NEXT: [[TMP5:%.*]] = phi i32 [ [[TMP8:%.*]], [[TMP4]] ], [ 1, [[TMP0]] ] +; IS__CGSCC____-NEXT: [[TMP6:%.*]] = phi i32 [ [[TMP7]], [[TMP4]] ], [ 1, [[TMP0]] ] +; IS__CGSCC____-NEXT: [[TMP7]] = mul nsw i32 [[TMP5]], [[TMP6]] +; IS__CGSCC____-NEXT: [[TMP8]] = add nuw nsw i32 [[TMP5]], 1 +; IS__CGSCC____-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP5]], 10 +; IS__CGSCC____-NEXT: br i1 [[TMP9]], label [[TMP2]], label [[TMP4]] +; %2 = icmp slt i32 %0, 1 br i1 %2, label %3, label %5 @@ -49,26 +59,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 +121,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 +152,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 +159,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 +198,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 +236,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 +266,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 +278,6 @@ ret i32 %cond continue: - ; CHECK: continue: - ; CHECK-NEXT: unreachable br label %cond.end cleanup: @@ -213,8 +289,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 +317,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 +341,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 +388,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 +476,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]] +; 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 +496,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 +513,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 +549,10 @@ } define void @rec() #0 { +; CHECK-LABEL: define {{[^@]+}}@rec() +; CHECK-NEXT: entry: +; CHECK-NEXT: unreachable +; entry: call void @rec() ret void @@ -432,6 +563,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 +600,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 +659,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 ;