[llvm] 6cc2b1d - [Attributor][Tests] Copy & use the ArgumentPromotion tests
Johannes Doerfert via llvm-commits
llvm-commits at lists.llvm.org
Fri Dec 13 23:06:40 PST 2019
Author: Johannes Doerfert
Date: 2019-12-14T01:05:36-06:00
New Revision: 6cc2b1d789172143d9eff98412ee477ad8c7cad7
URL: https://github.com/llvm/llvm-project/commit/6cc2b1d789172143d9eff98412ee477ad8c7cad7
DIFF: https://github.com/llvm/llvm-project/commit/6cc2b1d789172143d9eff98412ee477ad8c7cad7.diff
LOG: [Attributor][Tests] Copy & use the ArgumentPromotion tests
Added:
llvm/test/Transforms/Attributor/ArgumentPromotion/2008-02-01-ReturnAttrs.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/2008-07-02-array-indexing.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-07-CGUpdate.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-08-CGUpdateSelfEdge.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/X86/attributes.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/X86/lit.local.cfg
llvm/test/Transforms/Attributor/ArgumentPromotion/X86/min-legal-vector-width.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/X86/thiscall.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/aggregate-promote.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/basictest.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/chained.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow2.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/crash.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/dbg.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/fp80.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/invalidation.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/musttail.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/naked_functions.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/nonzero-address-spaces.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/pr27568.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/pr3085.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/pr32917.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/pr33641_remove_arg_dbgvalue.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/profile.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/reserve-tbaa.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/sret.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/tail.ll
llvm/test/Transforms/Attributor/ArgumentPromotion/variadic.ll
Modified:
Removed:
################################################################################
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-02-01-ReturnAttrs.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-02-01-ReturnAttrs.ll
new file mode 100644
index 000000000000..17e83327c9ea
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-02-01-ReturnAttrs.ll
@@ -0,0 +1,30 @@
+; 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
+
+define internal i32 @deref(i32* %x) nounwind {
+; CHECK-LABEL: define {{[^@]+}}@deref
+; CHECK-SAME: (i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[X:%.*]])
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[X]], align 4
+; CHECK-NEXT: ret i32 [[TMP2]]
+;
+entry:
+ %tmp2 = load i32, i32* %x, align 4
+ ret i32 %tmp2
+}
+
+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: [[TMP1:%.*]] = call i32 @deref(i32* noalias nocapture nofree nonnull align 4 dereferenceable(4) [[X_ADDR]])
+; CHECK-NEXT: ret i32 [[TMP1]]
+;
+entry:
+ %x_addr = alloca i32
+ store i32 %x, i32* %x_addr, align 4
+ %tmp1 = call i32 @deref( i32* %x_addr ) nounwind
+ ret i32 %tmp1
+}
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
new file mode 100644
index 000000000000..0fa282be4442
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-07-02-array-indexing.ll
@@ -0,0 +1,43 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
+; RUN: opt -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=3 -S < %s | FileCheck %s
+; PR2498
+
+; This test tries to convince CHECK about promoting the load from %A + 2,
+; because there is a load of %A in the entry block
+define internal i32 @callee(i1 %C, i32* %A) {
+; CHECK-LABEL: define {{[^@]+}}@callee
+; CHECK-SAME: (i1 [[C:%.*]], i32* noalias nocapture nofree nonnull readonly dereferenceable(4) [[A:%.*]])
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[A_0:%.*]] = load i32, i32* null
+; CHECK-NEXT: br i1 false, label [[T:%.*]], 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]]
+;
+entry:
+ ; Unconditonally load the element at %A
+ %A.0 = load i32, i32* %A
+ br i1 %C, label %T, label %F
+
+T:
+ ret i32 %A.0
+
+F:
+ ; Load the element at offset two from %A. This should not be promoted!
+ %A.2 = getelementptr i32, i32* %A, i32 2
+ %R = load i32, i32* %A.2
+ ret i32 %R
+}
+
+define i32 @foo() {
+; CHECK-LABEL: define {{[^@]+}}@foo()
+; CHECK-NEXT: [[X:%.*]] = call i32 @callee(i1 false, i32* noalias nofree null)
+; CHECK-NEXT: ret i32 [[X]]
+;
+ %X = call i32 @callee(i1 false, i32* null) ; <i32> [#uses=1]
+ ret i32 %X
+}
+
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-07-CGUpdate.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-07-CGUpdate.ll
new file mode 100644
index 000000000000..fd2887ecea60
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-07-CGUpdate.ll
@@ -0,0 +1,13 @@
+; 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
+
+define internal fastcc i32 @hash(i32* %ts, i32 %mod) nounwind {
+entry:
+ unreachable
+}
+
+define void @encode(i32* %m, i32* %ts, i32* %new) nounwind {
+entry:
+ %0 = call fastcc i32 @hash( i32* %ts, i32 0 ) nounwind ; <i32> [#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
new file mode 100644
index 000000000000..fe3f1c697436
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/2008-09-08-CGUpdateSelfEdge.ll
@@ -0,0 +1,26 @@
+; 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
+
+define internal fastcc i32 @term_SharingList(i32* %Term, i32* %List) nounwind {
+entry:
+ br i1 false, label %bb, label %bb5
+
+bb: ; preds = %entry
+ %0 = call fastcc i32 @term_SharingList( i32* null, i32* %List ) nounwind ; <i32> [#uses=0]
+ unreachable
+
+bb5: ; preds = %entry
+ ret i32 0
+}
+
+define i32 @term_Sharing(i32* %Term) nounwind {
+entry:
+ br i1 false, label %bb.i, label %bb14
+
+bb.i: ; preds = %entry
+ %0 = call fastcc i32 @term_SharingList( i32* null, i32* null ) nounwind ; <i32> [#uses=0]
+ ret i32 1
+
+bb14: ; preds = %entry
+ ret i32 0
+}
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/attributes.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/attributes.ll
new file mode 100644
index 000000000000..c4be9d76da31
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/attributes.ll
@@ -0,0 +1,89 @@
+; 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
+; 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
+;
+bb:
+ %tmp = load <4 x i64>, <4 x i64>* %arg1
+ store <4 x i64> %tmp, <4 x i64>* %arg
+ ret void
+}
+
+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 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 align 32 dereferenceable(32) [[TMP2]], <4 x i64>* noalias nocapture nofree nonnull 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
+;
+bb:
+ %tmp = alloca <4 x i64>, align 32
+ %tmp2 = alloca <4 x i64>, align 32
+ %tmp3 = bitcast <4 x i64>* %tmp to i8*
+ call void @llvm.memset.p0i8.i64(i8* align 32 %tmp3, i8 0, i64 32, i1 false)
+ call fastcc void @no_promote_avx2(<4 x i64>* %tmp2, <4 x i64>* %tmp)
+ %tmp4 = load <4 x i64>, <4 x i64>* %tmp2, align 32
+ store <4 x i64> %tmp4, <4 x i64>* %arg, align 2
+ ret void
+}
+
+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>* 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
+;
+bb:
+ %tmp = load <4 x i64>, <4 x i64>* %arg1
+ store <4 x i64> %tmp, <4 x i64>* %arg
+ ret void
+}
+
+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 align 32 dereferenceable(32) [[TMP3]], i8 0, i64 32, i1 false)
+; CHECK-NEXT: call fastcc void @promote_avx2(<4 x i64>* noalias nocapture nofree nonnull align 32 dereferenceable(32) [[TMP2]], <4 x i64>* noalias nocapture nofree nonnull 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
+;
+bb:
+ %tmp = alloca <4 x i64>, align 32
+ %tmp2 = alloca <4 x i64>, align 32
+ %tmp3 = bitcast <4 x i64>* %tmp to i8*
+ call void @llvm.memset.p0i8.i64(i8* align 32 %tmp3, i8 0, i64 32, i1 false)
+ call fastcc void @promote_avx2(<4 x i64>* %tmp2, <4 x i64>* %tmp)
+ %tmp4 = load <4 x i64>, <4 x i64>* %tmp2, align 32
+ store <4 x i64> %tmp4, <4 x i64>* %arg, align 2
+ ret void
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1) #2
+
+attributes #0 = { inlinehint norecurse nounwind uwtable "target-features"="+avx2" }
+attributes #1 = { nounwind uwtable }
+attributes #2 = { argmemonly nounwind }
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/lit.local.cfg b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/lit.local.cfg
new file mode 100644
index 000000000000..c8625f4d9d24
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/lit.local.cfg
@@ -0,0 +1,2 @@
+if not 'X86' in config.root.targets:
+ config.unsupported = True
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
new file mode 100644
index 000000000000..37c6c74cb7e1
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/min-legal-vector-width.ll
@@ -0,0 +1,328 @@
+; 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
+; Test that we only promote arguments when the caller/callee have compatible
+; function attrubtes.
+
+target triple = "x86_64-unknown-linux-gnu"
+
+; 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>* 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
+;
+bb:
+ %tmp = load <8 x i64>, <8 x i64>* %arg1
+ store <8 x i64> %tmp, <8 x i64>* %arg
+ ret void
+}
+
+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 align 32 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false)
+; CHECK-NEXT: call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512(<8 x i64>* noalias nocapture nofree nonnull align 32 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nocapture nofree nonnull 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
+;
+bb:
+ %tmp = alloca <8 x i64>, align 32
+ %tmp2 = alloca <8 x i64>, align 32
+ %tmp3 = bitcast <8 x i64>* %tmp to i8*
+ call void @llvm.memset.p0i8.i64(i8* align 32 %tmp3, i8 0, i64 32, i1 false)
+ call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512(<8 x i64>* %tmp2, <8 x i64>* %tmp)
+ %tmp4 = load <8 x i64>, <8 x i64>* %tmp2, align 32
+ store <8 x i64> %tmp4, <8 x i64>* %arg, align 2
+ ret void
+}
+
+; 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>* 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
+;
+bb:
+ %tmp = load <8 x i64>, <8 x i64>* %arg1
+ store <8 x i64> %tmp, <8 x i64>* %arg
+ ret void
+}
+
+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 align 32 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false)
+; CHECK-NEXT: call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256(<8 x i64>* noalias nocapture nofree nonnull align 32 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nocapture nofree nonnull 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
+;
+bb:
+ %tmp = alloca <8 x i64>, align 32
+ %tmp2 = alloca <8 x i64>, align 32
+ %tmp3 = bitcast <8 x i64>* %tmp to i8*
+ call void @llvm.memset.p0i8.i64(i8* align 32 %tmp3, i8 0, i64 32, i1 false)
+ call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256(<8 x i64>* %tmp2, <8 x i64>* %tmp)
+ %tmp4 = load <8 x i64>, <8 x i64>* %tmp2, align 32
+ store <8 x i64> %tmp4, <8 x i64>* %arg, align 2
+ ret void
+}
+
+; 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>* 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
+;
+bb:
+ %tmp = load <8 x i64>, <8 x i64>* %arg1
+ store <8 x i64> %tmp, <8 x i64>* %arg
+ ret void
+}
+
+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 align 32 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false)
+; CHECK-NEXT: call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256(<8 x i64>* noalias nocapture nofree nonnull align 32 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nocapture nofree nonnull 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
+;
+bb:
+ %tmp = alloca <8 x i64>, align 32
+ %tmp2 = alloca <8 x i64>, align 32
+ %tmp3 = bitcast <8 x i64>* %tmp to i8*
+ call void @llvm.memset.p0i8.i64(i8* align 32 %tmp3, i8 0, i64 32, i1 false)
+ call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256(<8 x i64>* %tmp2, <8 x i64>* %tmp)
+ %tmp4 = load <8 x i64>, <8 x i64>* %tmp2, align 32
+ store <8 x i64> %tmp4, <8 x i64>* %arg, align 2
+ ret void
+}
+
+; 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>* 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
+;
+bb:
+ %tmp = load <8 x i64>, <8 x i64>* %arg1
+ store <8 x i64> %tmp, <8 x i64>* %arg
+ ret void
+}
+
+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 align 32 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false)
+; CHECK-NEXT: call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512(<8 x i64>* noalias nocapture nofree nonnull align 32 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nocapture nofree nonnull 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
+;
+bb:
+ %tmp = alloca <8 x i64>, align 32
+ %tmp2 = alloca <8 x i64>, align 32
+ %tmp3 = bitcast <8 x i64>* %tmp to i8*
+ call void @llvm.memset.p0i8.i64(i8* align 32 %tmp3, i8 0, i64 32, i1 false)
+ call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512(<8 x i64>* %tmp2, <8 x i64>* %tmp)
+ %tmp4 = load <8 x i64>, <8 x i64>* %tmp2, align 32
+ store <8 x i64> %tmp4, <8 x i64>* %arg, align 2
+ ret void
+}
+
+; 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
+;
+bb:
+ %tmp = load <8 x i64>, <8 x i64>* %arg1
+ store <8 x i64> %tmp, <8 x i64>* %arg
+ ret void
+}
+
+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 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 align 32 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nocapture nofree nonnull 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
+;
+bb:
+ %tmp = alloca <8 x i64>, align 32
+ %tmp2 = alloca <8 x i64>, align 32
+ %tmp3 = bitcast <8 x i64>* %tmp to i8*
+ call void @llvm.memset.p0i8.i64(i8* align 32 %tmp3, i8 0, i64 32, i1 false)
+ call fastcc void @callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256(<8 x i64>* %tmp2, <8 x i64>* %tmp)
+ %tmp4 = load <8 x i64>, <8 x i64>* %tmp2, align 32
+ store <8 x i64> %tmp4, <8 x i64>* %arg, align 2
+ ret void
+}
+
+; 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
+;
+bb:
+ %tmp = load <8 x i64>, <8 x i64>* %arg1
+ store <8 x i64> %tmp, <8 x i64>* %arg
+ ret void
+}
+
+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 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 align 32 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nocapture nofree nonnull 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
+;
+bb:
+ %tmp = alloca <8 x i64>, align 32
+ %tmp2 = alloca <8 x i64>, align 32
+ %tmp3 = bitcast <8 x i64>* %tmp to i8*
+ call void @llvm.memset.p0i8.i64(i8* align 32 %tmp3, i8 0, i64 32, i1 false)
+ call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256(<8 x i64>* %tmp2, <8 x i64>* %tmp)
+ %tmp4 = load <8 x i64>, <8 x i64>* %tmp2, align 32
+ store <8 x i64> %tmp4, <8 x i64>* %arg, align 2
+ ret void
+}
+
+; 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>* 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
+;
+bb:
+ %tmp = load <8 x i64>, <8 x i64>* %arg1
+ store <8 x i64> %tmp, <8 x i64>* %arg
+ ret void
+}
+
+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 align 32 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false)
+; CHECK-NEXT: call fastcc void @callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256(<8 x i64>* noalias nocapture nofree nonnull align 32 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nocapture nofree nonnull 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
+;
+bb:
+ %tmp = alloca <8 x i64>, align 32
+ %tmp2 = alloca <8 x i64>, align 32
+ %tmp3 = bitcast <8 x i64>* %tmp to i8*
+ call void @llvm.memset.p0i8.i64(i8* align 32 %tmp3, i8 0, i64 32, i1 false)
+ call fastcc void @callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256(<8 x i64>* %tmp2, <8 x i64>* %tmp)
+ %tmp4 = load <8 x i64>, <8 x i64>* %tmp2, align 32
+ store <8 x i64> %tmp4, <8 x i64>* %arg, align 2
+ ret void
+}
+
+; 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>* 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
+;
+bb:
+ %tmp = load <8 x i64>, <8 x i64>* %arg1
+ store <8 x i64> %tmp, <8 x i64>* %arg
+ ret void
+}
+
+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 align 32 dereferenceable(64) [[TMP3]], i8 0, i64 32, i1 false)
+; CHECK-NEXT: call fastcc void @callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256(<8 x i64>* noalias nocapture nofree nonnull align 32 dereferenceable(64) [[TMP2]], <8 x i64>* noalias nocapture nofree nonnull 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
+;
+bb:
+ %tmp = alloca <8 x i64>, align 32
+ %tmp2 = alloca <8 x i64>, align 32
+ %tmp3 = bitcast <8 x i64>* %tmp to i8*
+ call void @llvm.memset.p0i8.i64(i8* align 32 %tmp3, i8 0, i64 32, i1 false)
+ call fastcc void @callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256(<8 x i64>* %tmp2, <8 x i64>* %tmp)
+ %tmp4 = load <8 x i64>, <8 x i64>* %tmp2, align 32
+ store <8 x i64> %tmp4, <8 x i64>* %arg, align 2
+ ret void
+}
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1) #5
+
+attributes #0 = { inlinehint norecurse nounwind uwtable "target-features"="+avx512vl" "min-legal-vector-width"="512" "prefer-vector-width"="512" }
+attributes #1 = { inlinehint norecurse nounwind uwtable "target-features"="+avx512vl" "min-legal-vector-width"="512" "prefer-vector-width"="256" }
+attributes #2 = { inlinehint norecurse nounwind uwtable "target-features"="+avx512vl" "min-legal-vector-width"="256" "prefer-vector-width"="256" }
+attributes #3 = { inlinehint norecurse nounwind uwtable "target-features"="+avx2" "min-legal-vector-width"="512" "prefer-vector-width"="256" }
+attributes #4 = { inlinehint norecurse nounwind uwtable "target-features"="+avx2" "min-legal-vector-width"="256" "prefer-vector-width"="256" }
+attributes #5 = { argmemonly nounwind }
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/thiscall.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/thiscall.ll
new file mode 100644
index 000000000000..d9f3681ba4ab
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/X86/thiscall.ll
@@ -0,0 +1,73 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
+; In PR41658, argpromotion put an inalloca in a position that per the
+; calling convention is passed in a register. This test verifies that
+; 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
+
+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"
+
+%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
+;
+; 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
+;
+entry:
+ %a = getelementptr inbounds <{ %struct.a }>, <{ %struct.a }>* %0, i32 0, i32 0
+ %argmem = alloca inalloca <{ %struct.a }>, align 4
+ %1 = getelementptr inbounds <{ %struct.a }>, <{ %struct.a }>* %argmem, i32 0, i32 0
+ %call = call x86_thiscallcc %struct.a* @copy_ctor(%struct.a* %1, %struct.a* dereferenceable(1) %a)
+ call void @ext(<{ %struct.a }>* inalloca %argmem)
+ ret void
+}
+
+; 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
+;
+; 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
+;
+ %inalloca.save = tail call i8* @llvm.stacksave()
+ %argmem = alloca inalloca <{ %struct.a }>, align 4
+ call x86_thiscallcc void @internalfun(%struct.a* %a, <{ %struct.a }>* inalloca %argmem)
+ call void @llvm.stackrestore(i8* %inalloca.save)
+ ret void
+}
+
+declare x86_thiscallcc %struct.a* @copy_ctor(%struct.a* returned, %struct.a* dereferenceable(1))
+declare void @ext(<{ %struct.a }>* inalloca)
+declare i8* @llvm.stacksave()
+declare void @llvm.stackrestore(i8*)
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/aggregate-promote.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/aggregate-promote.ll
new file mode 100644
index 000000000000..449b05e4485c
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/aggregate-promote.ll
@@ -0,0 +1,36 @@
+; 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=3 < %s
+
+%T = type { i32, i32, i32, i32 }
+ at 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-NEXT: entry:
+; CHECK-NEXT: [[V:%.*]] = add i32 [[P_0_3_VAL]], [[P_0_2_VAL]]
+; CHECK-NEXT: ret i32 [[V]]
+;
+entry:
+ %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
+ %b = load i32, i32* %b.gep
+ %v = add i32 %a, %b
+ ret i32 %v
+}
+
+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: ret i32 [[V]]
+;
+entry:
+ %v = call i32 @test(%T* @G)
+ ret i32 %v
+}
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll
new file mode 100644
index 000000000000..c2a8bd3a98ba
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/attrs.ll
@@ -0,0 +1,52 @@
+; 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
+
+%struct.ss = type { i32, i64 }
+
+; Don't drop 'byval' on %X here.
+define internal void @f(%struct.ss* byval %b, i32* byval %X, i32 %i) nounwind {
+; CHECK-LABEL: define {{[^@]+}}@f
+; CHECK-SAME: (%struct.ss* noalias nocapture nofree nonnull byval align 8 dereferenceable(12) [[B:%.*]], i32* nocapture nofree nonnull writeonly byval dereferenceable(4) [[X:%.*]], i32 [[I:%.*]])
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS:%.*]], %struct.ss* [[B]], 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]]
+; CHECK-NEXT: ret void
+;
+entry:
+
+ %tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0
+ %tmp1 = load i32, i32* %tmp, align 4
+ %tmp2 = add i32 %tmp1, 1
+ store i32 %tmp2, i32* %tmp, align 4
+
+ store i32 %i, i32* %X
+ ret void
+}
+
+; 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: call void @f(%struct.ss* noalias nocapture nofree nonnull byval align 8 dereferenceable(12) [[S]], i32* nocapture nofree readonly byval [[X]], i32 zeroext 0)
+; CHECK-NEXT: ret i32 0
+;
+entry:
+ %S = alloca %struct.ss
+ %tmp1 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 0
+ store i32 1, i32* %tmp1, align 8
+ %tmp4 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 1
+ store i64 2, i64* %tmp4, align 4
+
+ call void @f( %struct.ss* byval %S, i32* byval %X, i32 zeroext 0)
+
+ ret i32 0
+}
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/basictest.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/basictest.ll
new file mode 100644
index 000000000000..f595631a1e6b
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/basictest.ll
@@ -0,0 +1,45 @@
+; 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
+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* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[X:%.*]], i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[Y:%.*]])
+; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[X]], align 4
+; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[Y]], align 4
+; CHECK-NEXT: [[C:%.*]] = add i32 [[A]], [[B]]
+; CHECK-NEXT: ret i32 [[C]]
+;
+ %A = load i32, i32* %X
+ %B = load i32, i32* %Y
+ %C = add i32 %A, %B
+ ret i32 %C
+}
+
+define internal i32 @caller(i32* %B) {
+; CHECK-LABEL: define {{[^@]+}}@caller
+; CHECK-SAME: (i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B:%.*]])
+; CHECK-NEXT: [[A:%.*]] = alloca i32
+; CHECK-NEXT: store i32 1, i32* [[A]], align 4
+; CHECK-NEXT: [[C:%.*]] = call i32 @test(i32* noalias nocapture nofree nonnull align 4 dereferenceable(4) [[A]], i32* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[B]])
+; CHECK-NEXT: ret i32 [[C]]
+;
+ %A = alloca i32
+ store i32 1, i32* %A
+ %C = call i32 @test(i32* %A, i32* %B)
+ ret i32 %C
+}
+
+define i32 @callercaller() {
+; CHECK-LABEL: define {{[^@]+}}@callercaller()
+; CHECK-NEXT: [[B:%.*]] = alloca i32
+; CHECK-NEXT: store i32 2, i32* [[B]], align 4
+; CHECK-NEXT: [[X:%.*]] = call i32 @caller(i32* noalias nocapture nofree nonnull align 4 dereferenceable(4) [[B]])
+; CHECK-NEXT: ret i32 [[X]]
+;
+ %B = alloca i32
+ store i32 2, i32* %B
+ %X = call i32 @caller(i32* %B)
+ ret i32 %X
+}
+
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll
new file mode 100644
index 000000000000..e7c05d7cd14f
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval-2.ll
@@ -0,0 +1,47 @@
+; 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
+
+%struct.ss = type { i32, i64 }
+
+define internal void @f(%struct.ss* byval %b, i32* byval %X) nounwind {
+; CHECK-LABEL: define {{[^@]+}}@f
+; CHECK-SAME: (%struct.ss* noalias nocapture nofree nonnull byval align 8 dereferenceable(12) [[B:%.*]], i32* nocapture nofree nonnull writeonly byval dereferenceable(4) [[X:%.*]])
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS:%.*]], %struct.ss* [[B]], 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]]
+; CHECK-NEXT: ret void
+;
+entry:
+ %tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0
+ %tmp1 = load i32, i32* %tmp, align 4
+ %tmp2 = add i32 %tmp1, 1
+ store i32 %tmp2, i32* %tmp, align 4
+
+ store i32 0, i32* %X
+ ret void
+}
+
+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: call void @f(%struct.ss* noalias nocapture nofree nonnull byval align 8 dereferenceable(12) [[S]], i32* nocapture nofree readonly byval [[X]])
+; CHECK-NEXT: ret i32 0
+;
+entry:
+ %S = alloca %struct.ss
+ %tmp1 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 0
+ store i32 1, i32* %tmp1, align 8
+ %tmp4 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 1
+ store i64 2, i64* %tmp4, align 4
+ call void @f( %struct.ss* byval %S, i32* byval %X)
+ ret i32 0
+}
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll
new file mode 100644
index 000000000000..05e82d308ae0
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/byval.ll
@@ -0,0 +1,69 @@
+; 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
+
+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 void @f(%struct.ss* byval %b) nounwind {
+; CHECK-LABEL: define {{[^@]+}}@f
+; CHECK-SAME: (%struct.ss* noalias nocapture nofree nonnull byval align 8 dereferenceable(12) [[B:%.*]])
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS:%.*]], %struct.ss* [[B]], 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 void
+;
+entry:
+ %tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0
+ %tmp1 = load i32, i32* %tmp, align 4
+ %tmp2 = add i32 %tmp1, 1
+ store i32 %tmp2, i32* %tmp, align 4
+ ret void
+}
+
+
+define internal void @g(%struct.ss* byval align 32 %b) nounwind {
+; CHECK-LABEL: define {{[^@]+}}@g
+; CHECK-SAME: (%struct.ss* noalias nocapture nofree nonnull byval align 32 dereferenceable(12) [[B:%.*]])
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS:%.*]], %struct.ss* [[B]], 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 void
+;
+entry:
+ %tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0
+ %tmp1 = load i32, i32* %tmp, align 4
+ %tmp2 = add i32 %tmp1, 1
+ store i32 %tmp2, i32* %tmp, align 4
+ ret void
+}
+
+
+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: call void @f(%struct.ss* noalias nocapture nofree nonnull byval align 8 dereferenceable(12) [[S]])
+; CHECK-NEXT: call void @g(%struct.ss* noalias nocapture nofree nonnull byval align 32 dereferenceable(12) [[S]])
+; CHECK-NEXT: ret i32 0
+;
+entry:
+ %S = alloca %struct.ss
+ %tmp1 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 0
+ store i32 1, i32* %tmp1, align 8
+ %tmp4 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 1
+ store i64 2, i64* %tmp4, align 4
+ call void @f(%struct.ss* byval %S) nounwind
+ call void @g(%struct.ss* byval %S) nounwind
+ ret i32 0
+}
+
+
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/chained.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/chained.ll
new file mode 100644
index 000000000000..2ed03622b465
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/chained.ll
@@ -0,0 +1,31 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
+; RUN: opt -S -passes='attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=3 < %s | FileCheck %s
+
+ at G1 = constant i32 0
+ at G2 = constant i32* @G1
+
+define internal i32 @test(i32** %x) {
+; CHECK-LABEL: define {{[^@]+}}@test
+; CHECK-SAME: (i32** nocapture nofree nonnull readonly align 8 dereferenceable(8) [[X:%.*]])
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[Y:%.*]] = load i32*, i32** @G2, align 8
+; CHECK-NEXT: [[Z:%.*]] = load i32, i32* [[Y]]
+; CHECK-NEXT: ret i32 [[Z]]
+;
+entry:
+ %y = load i32*, i32** %x
+ %z = load i32, i32* %y
+ ret i32 %z
+}
+
+define i32 @caller() {
+; CHECK-LABEL: define {{[^@]+}}@caller()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[X:%.*]] = call i32 @test(i32** nofree nonnull align 8 dereferenceable(8) @G2)
+; CHECK-NEXT: ret i32 [[X]]
+;
+entry:
+ %x = call i32 @test(i32** @G2)
+ ret i32 %x
+}
+
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow.ll
new file mode 100644
index 000000000000..cc6868fd4d2e
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow.ll
@@ -0,0 +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=2 < %s | FileCheck %s
+
+; Don't promote around control flow.
+define internal i32 @callee(i1 %C, i32* %P) {
+; CHECK-LABEL: define {{[^@]+}}@callee
+; CHECK-SAME: (i1 [[C:%.*]], i32* noalias nocapture nofree readnone [[P:%.*]])
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 true, label [[T:%.*]], label [[F:%.*]]
+; CHECK: T:
+; CHECK-NEXT: ret i32 17
+; CHECK: F:
+; CHECK-NEXT: unreachable
+;
+entry:
+ br i1 %C, label %T, label %F
+
+T:
+ ret i32 17
+
+F:
+ %X = load i32, i32* %P
+ ret i32 %X
+}
+
+define i32 @foo() {
+; CHECK-LABEL: define {{[^@]+}}@foo()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[X:%.*]] = call i32 @callee(i1 true, i32* noalias nofree undef)
+; CHECK-NEXT: ret i32 17
+;
+entry:
+ %X = call i32 @callee(i1 true, i32* null)
+ ret i32 %X
+}
+
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow2.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow2.ll
new file mode 100644
index 000000000000..4924e2c1518d
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/control-flow2.ll
@@ -0,0 +1,38 @@
+; 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=9 < %s | FileCheck %s
+
+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* noalias nocapture nofree nonnull readonly align 4 dereferenceable(4) [[P:%.*]])
+; CHECK-NEXT: br i1 false, label [[T:%.*]], label [[F:%.*]]
+; CHECK: T:
+; CHECK-NEXT: unreachable
+; CHECK: F:
+; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P]], align 4
+; CHECK-NEXT: ret i32 [[X]]
+;
+ br i1 %C, label %T, label %F
+
+T: ; preds = %0
+ ret i32 17
+
+F: ; preds = %0
+ %X = load i32, i32* %P ; <i32> [#uses=1]
+ ret i32 %X
+}
+
+define i32 @foo() {
+; CHECK-LABEL: define {{[^@]+}}@foo()
+; CHECK-NEXT: [[A:%.*]] = alloca i32
+; CHECK-NEXT: store i32 17, i32* [[A]], align 4
+; CHECK-NEXT: [[X:%.*]] = call i32 @callee(i1 false, i32* noalias nocapture nofree nonnull align 4 dereferenceable(4) [[A]])
+; CHECK-NEXT: ret i32 [[X]]
+;
+ %A = alloca i32 ; <i32*> [#uses=2]
+ store i32 17, i32* %A
+ %X = call i32 @callee( i1 false, i32* %A ) ; <i32> [#uses=1]
+ ret i32 %X
+}
+
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/crash.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/crash.ll
new file mode 100644
index 000000000000..87a3ba5811e1
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/crash.ll
@@ -0,0 +1,102 @@
+; 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
+
+%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: bb.split:
+; ATTRIBUTOR-NEXT: unreachable
+; ATTRIBUTOR: bb1.i2c:
+; 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
+;
+bb:
+ invoke void @hoge()
+ to label %bb1 unwind label %bb2
+
+bb1:
+ unreachable
+
+bb2:
+ %tmp = landingpad { i8*, i32 }
+ cleanup
+ unreachable
+}
+
+define internal void @hoge() {
+; ATTRIBUTOR-LABEL: define {{[^@]+}}@hoge()
+; ATTRIBUTOR-NEXT: bb:
+; ATTRIBUTOR-NEXT: unreachable
+; ATTRIBUTOR: bb.split:
+; ATTRIBUTOR-NEXT: unreachable
+;
+bb:
+ %tmp = call fastcc i8* @spam(i1 (i8*)* @eggs)
+ %tmp1 = call fastcc i8* @spam(i1 (i8*)* @barney)
+ unreachable
+}
+
+define internal fastcc i8* @spam(i1 (i8*)* %arg) {
+bb:
+ unreachable
+}
+
+define internal i1 @eggs(i8* %arg) {
+bb:
+ %tmp = call zeroext i1 @barney(i8* %arg)
+ unreachable
+}
+
+define internal i1 @barney(i8* %arg) {
+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
+; CHECK: bb.split:
+; CHECK-NEXT: unreachable
+;
+bb:
+ %tmp = alloca %S
+ %tmp1 = alloca %S
+ %tmp2 = call i32 @test_inf_promote_callee(%S* %tmp, %S* %tmp1)
+
+ ret i32 0
+}
+
+define internal i32 @test_inf_promote_callee(%S* %arg, %S* %arg1) {
+bb:
+ %tmp = getelementptr %S, %S* %arg1, i32 0, i32 0
+ %tmp2 = load %S*, %S** %tmp
+ %tmp3 = getelementptr %S, %S* %arg, i32 0, i32 0
+ %tmp4 = load %S*, %S** %tmp3
+ %tmp5 = call i32 @test_inf_promote_callee(%S* %tmp4, %S* %tmp2)
+
+ ret i32 0
+}
+
+declare i32 @wibble(...)
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/dbg.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/dbg.ll
new file mode 100644
index 000000000000..c405202d176e
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/dbg.ll
@@ -0,0 +1,52 @@
+; 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
+
+declare void @sink(i32)
+
+define internal void @test(i32** %X) !dbg !2 {
+; CHECK-LABEL: define {{[^@]+}}@test
+; CHECK-SAME: (i32** nocapture nonnull readonly align 8 dereferenceable(8) [[X:%.*]]) !dbg !3
+; CHECK-NEXT: [[TMP1:%.*]] = load i32*, i32** [[X]], align 8
+; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[TMP1]], align 8
+; CHECK-NEXT: call void @sink(i32 [[TMP2]])
+; CHECK-NEXT: ret void
+;
+ %1 = load i32*, i32** %X, align 8
+ %2 = load i32, i32* %1, align 8
+ call void @sink(i32 %2)
+ ret void
+}
+
+%struct.pair = type { i32, i32 }
+
+define internal void @test_byval(%struct.pair* byval %P) {
+; CHECK-LABEL: define {{[^@]+}}@test_byval
+; CHECK-SAME: (%struct.pair* nocapture nofree readnone byval [[P:%.*]])
+; CHECK-NEXT: ret void
+;
+ ret void
+}
+
+define void @caller(i32** %Y, %struct.pair* %P) {
+; CHECK-LABEL: define {{[^@]+}}@caller
+; CHECK-SAME: (i32** nocapture readonly [[Y:%.*]], %struct.pair* nocapture nofree readonly [[P:%.*]])
+; CHECK-NEXT: call void @test(i32** nocapture readonly [[Y]]), !dbg !4
+; CHECK-NEXT: call void @test_byval(%struct.pair* nocapture nofree readonly undef), !dbg !5
+; CHECK-NEXT: ret void
+;
+ call void @test(i32** %Y), !dbg !1
+
+ call void @test_byval(%struct.pair* %P), !dbg !6
+ ret void
+}
+
+
+!llvm.module.flags = !{!0}
+!llvm.dbg.cu = !{!3}
+
+!0 = !{i32 2, !"Debug Info Version", i32 3}
+!1 = !DILocation(line: 8, scope: !2)
+!2 = distinct !DISubprogram(name: "test", file: !5, line: 3, isLocal: true, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !3, scopeLine: 3, scope: null)
+!3 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.5.0 ", isOptimized: false, emissionKind: LineTablesOnly, file: !5)
+!5 = !DIFile(filename: "test.c", directory: "")
+!6 = !DILocation(line: 9, scope: !2)
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/fp80.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/fp80.ll
new file mode 100644
index 000000000000..341ab1de0036
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/fp80.ll
@@ -0,0 +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=2 < %s | FileCheck %s
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%union.u = type { x86_fp80 }
+%struct.s = type { double, i16, i8, [5 x i8] }
+
+ at b = internal global %struct.s { double 3.14, i16 9439, i8 25, [5 x i8] undef }, align 16
+
+%struct.Foo = type { i32, i64 }
+ at a = internal global %struct.Foo { i32 1, i64 2 }, align 8
+
+define void @run() {
+; CHECK-LABEL: define {{[^@]+}}@run()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = call i64 @CaptureAStruct(%struct.Foo* nofree nonnull align 8 dereferenceable(16) @a)
+; CHECK-NEXT: unreachable
+; CHECK: entry.split:
+; CHECK-NEXT: unreachable
+;
+entry:
+ tail call i8 @UseLongDoubleUnsafely(%union.u* byval align 16 bitcast (%struct.s* @b to %union.u*))
+ tail call x86_fp80 @UseLongDoubleSafely(%union.u* byval align 16 bitcast (%struct.s* @b to %union.u*))
+ call i64 @AccessPaddingOfStruct(%struct.Foo* @a)
+ call i64 @CaptureAStruct(%struct.Foo* @a)
+ ret void
+}
+
+define internal i8 @UseLongDoubleUnsafely(%union.u* byval align 16 %arg) {
+entry:
+ %bitcast = bitcast %union.u* %arg to %struct.s*
+ %gep = getelementptr inbounds %struct.s, %struct.s* %bitcast, i64 0, i32 2
+ %result = load i8, i8* %gep
+ ret i8 %result
+}
+
+define internal x86_fp80 @UseLongDoubleSafely(%union.u* byval align 16 %arg) {
+ %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) {
+ %p = bitcast %struct.Foo* %a to i64*
+ %v = load i64, i64* %p
+ ret i64 %v
+}
+
+define internal i64 @CaptureAStruct(%struct.Foo* byval %a) {
+; CHECK-LABEL: define {{[^@]+}}@CaptureAStruct
+; CHECK-SAME: (%struct.Foo* nofree nonnull byval align 8 dereferenceable(16) [[A:%.*]])
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[A_PTR:%.*]] = alloca %struct.Foo*
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: [[PHI:%.*]] = phi %struct.Foo* [ null, [[ENTRY:%.*]] ], [ [[GEP:%.*]], [[LOOP]] ]
+; CHECK-NEXT: [[TMP0:%.*]] = phi %struct.Foo* [ [[A]], [[ENTRY]] ], [ [[TMP0]], [[LOOP]] ]
+; CHECK-NEXT: store %struct.Foo* [[PHI]], %struct.Foo** [[A_PTR]], align 8
+; CHECK-NEXT: [[GEP]] = getelementptr [[STRUCT_FOO:%.*]], %struct.Foo* [[A]], i64 0
+; CHECK-NEXT: br label [[LOOP]]
+;
+entry:
+ %a_ptr = alloca %struct.Foo*
+ br label %loop
+
+loop:
+ %phi = phi %struct.Foo* [ null, %entry ], [ %gep, %loop ]
+ %0 = phi %struct.Foo* [ %a, %entry ], [ %0, %loop ]
+ store %struct.Foo* %phi, %struct.Foo** %a_ptr
+ %gep = getelementptr %struct.Foo, %struct.Foo* %a, i64 0
+ br label %loop
+}
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll
new file mode 100644
index 000000000000..cac8d7a79999
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/inalloca.ll
@@ -0,0 +1,91 @@
+; 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 --check-prefixes=ATTRIBUTOR
+; RUN: opt -S -passes='globalopt,attributor' -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=2 < %s | FileCheck %s --check-prefixes=GLOBALOPT_ATTRIBUTOR
+
+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, i32 }
+
+; 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]]
+;
+; GLOBALOPT_ATTRIBUTOR-LABEL: define {{[^@]+}}@f
+; GLOBALOPT_ATTRIBUTOR-SAME: (%struct.ss* noalias nocapture nofree nonnull readonly align 4 dereferenceable(8) [[S:%.*]]) unnamed_addr
+; GLOBALOPT_ATTRIBUTOR-NEXT: entry:
+; 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: [[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]]
+;
+entry:
+ %f0 = getelementptr %struct.ss, %struct.ss* %s, i32 0, i32 0
+ %f1 = getelementptr %struct.ss, %struct.ss* %s, i32 0, i32 1
+ %a = load i32, i32* %f0, align 4
+ %b = load i32, i32* %f1, align 4
+ %r = add i32 %a, %b
+ ret i32 %r
+}
+
+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]]
+;
+; 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: [[R:%.*]] = call fastcc i32 @f(%struct.ss* noalias nocapture nofree nonnull align 4 dereferenceable(8) [[S]])
+; GLOBALOPT_ATTRIBUTOR-NEXT: ret i32 [[R]]
+;
+entry:
+ %S = alloca inalloca %struct.ss
+ %f0 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 0
+ %f1 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 1
+ store i32 1, i32* %f0, align 4
+ store i32 2, i32* %f1, align 4
+ %r = call i32 @f(%struct.ss* inalloca %S)
+ ret i32 %r
+}
+
+; Argpromote can't promote %a because of the icmp use.
+define internal i1 @g(%struct.ss* %a, %struct.ss* inalloca %b) nounwind {
+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
+;
+entry:
+ %S = alloca inalloca %struct.ss
+ %c = call i1 @g(%struct.ss* %S, %struct.ss* inalloca %S)
+ ret i32 0
+}
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/invalidation.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/invalidation.ll
new file mode 100644
index 000000000000..e49cc7e2ed73
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/invalidation.ll
@@ -0,0 +1,50 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
+; Check that when argument promotion changes a function in some parent node of
+; the call graph, any analyses that happened to be cached for that function are
+; actually invalidated. We are using `demanded-bits` here because when printed
+; it will end up caching a value for every instruction, making it easy to
+; detect the instruction-level changes that will fail here. With improper
+; invalidation this will crash in the second printer as it tries to reuse
+; now-invalid demanded bits.
+;
+; RUN: opt < %s -passes='function(print<demanded-bits>),attributor,function(print<demanded-bits>)' -S | FileCheck %s
+
+ at G = constant i32 0
+
+define internal i32 @a(i32* %x) {
+; CHECK-LABEL: define {{[^@]+}}@a
+; CHECK-SAME: (i32* [[X:%.*]])
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[V:%.*]] = load i32, i32* [[X]]
+; CHECK-NEXT: ret i32 [[V]]
+;
+entry:
+ %v = load i32, i32* %x
+ ret i32 %v
+}
+
+define i32 @b() {
+; CHECK-LABEL: define {{[^@]+}}@b()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[V:%.*]] = call i32 @a(i32* @G)
+; CHECK-NEXT: ret i32 [[V]]
+;
+entry:
+ %v = call i32 @a(i32* @G)
+ ret i32 %v
+}
+
+define i32 @c() {
+; CHECK-LABEL: define {{[^@]+}}@c()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[V1:%.*]] = call i32 @a(i32* @G)
+; CHECK-NEXT: [[V2:%.*]] = call i32 @b()
+; CHECK-NEXT: [[RESULT:%.*]] = add i32 [[V1]], [[V2]]
+; CHECK-NEXT: ret i32 [[RESULT]]
+;
+entry:
+ %v1 = call i32 @a(i32* @G)
+ %v2 = call i32 @b()
+ %result = add i32 %v1, %v2
+ ret i32 %result
+}
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/musttail.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/musttail.ll
new file mode 100644
index 000000000000..2c83cbb4aff4
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/musttail.ll
@@ -0,0 +1,70 @@
+; 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
+; PR36543
+
+; Don't promote arguments of musttail callee
+
+%T = type { i32, i32, i32, i32 }
+
+define internal i32 @test(%T* %p) {
+; CHECK-LABEL: define {{[^@]+}}@test
+; CHECK-SAME: (%T* nocapture nofree readonly [[P:%.*]])
+; CHECK-NEXT: [[A_GEP:%.*]] = getelementptr [[T:%.*]], %T* [[P]], i64 0, i32 3
+; CHECK-NEXT: [[B_GEP:%.*]] = getelementptr [[T]], %T* [[P]], i64 0, i32 2
+; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[A_GEP]]
+; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[B_GEP]]
+; CHECK-NEXT: [[V:%.*]] = add i32 [[A]], [[B]]
+; CHECK-NEXT: ret i32 [[V]]
+;
+ %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
+ %b = load i32, i32* %b.gep
+ %v = add i32 %a, %b
+ ret i32 %v
+}
+
+define i32 @caller(%T* %p) {
+; CHECK-LABEL: define {{[^@]+}}@caller
+; CHECK-SAME: (%T* nocapture nofree readonly [[P:%.*]])
+; CHECK-NEXT: [[V:%.*]] = musttail call i32 @test(%T* nocapture nofree readonly [[P]])
+; CHECK-NEXT: ret i32 [[V]]
+;
+ %v = musttail call i32 @test(%T* %p)
+ ret i32 %v
+}
+
+; Don't promote arguments of musttail caller
+
+define i32 @foo(%T* %p, i32 %v) {
+; CHECK-LABEL: define {{[^@]+}}@foo
+; CHECK-SAME: (%T* nocapture nofree readnone [[P:%.*]], i32 [[V:%.*]])
+; CHECK-NEXT: ret i32 0
+;
+ ret i32 0
+}
+
+define internal i32 @test2(%T* %p, i32 %p2) {
+; CHECK-LABEL: define {{[^@]+}}@test2
+; CHECK-SAME: (%T* nocapture nofree readonly [[P:%.*]], i32 [[P2:%.*]])
+; CHECK-NEXT: [[CA:%.*]] = musttail call i32 @foo(%T* undef, i32 undef)
+; CHECK-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
+ %b = load i32, i32* %b.gep
+ %v = add i32 %a, %b
+ %ca = musttail call i32 @foo(%T* undef, i32 %v)
+ ret i32 %ca
+}
+
+define i32 @caller2(%T* %g) {
+; CHECK-LABEL: define {{[^@]+}}@caller2
+; CHECK-SAME: (%T* nocapture nofree readonly [[G:%.*]])
+; CHECK-NEXT: [[V:%.*]] = call i32 @test2(%T* nocapture nofree readonly undef, i32 undef)
+; CHECK-NEXT: ret i32 0
+;
+ %v = call i32 @test2(%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
new file mode 100644
index 000000000000..4bfe138f4b6e
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/naked_functions.ll
@@ -0,0 +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=1 < %s | FileCheck %s
+
+; Don't promote paramaters of/arguments to naked functions
+
+ at g = common global i32 0, align 4
+
+define i32 @bar() {
+; CHECK-LABEL: define {{[^@]+}}@bar()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CALL:%.*]] = call i32 @foo(i32* nonnull align 4 dereferenceable(4) @g)
+; CHECK-NEXT: ret i32 [[CALL]]
+;
+entry:
+ %call = call i32 @foo(i32* @g)
+ ret i32 %call
+}
+
+define internal i32 @foo(i32*) #0 {
+; CHECK-LABEL: define {{[^@]+}}@foo
+; CHECK-SAME: (i32* [[TMP0:%.*]])
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
+; CHECK-NEXT: call void asm sideeffect "ldr r0, [r0] \0Abx lr \0A", ""()
+; CHECK-NEXT: unreachable
+;
+entry:
+ %retval = alloca i32, align 4
+ call void asm sideeffect "ldr r0, [r0] \0Abx lr \0A", ""()
+ unreachable
+}
+
+
+attributes #0 = { naked }
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/nonzero-address-spaces.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/nonzero-address-spaces.ll
new file mode 100644
index 000000000000..1d0eac00c23e
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/nonzero-address-spaces.ll
@@ -0,0 +1,38 @@
+; 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
+
+; ArgumentPromotion should preserve the default function address space
+; from the data layout.
+
+target datalayout = "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8"
+
+ at g = common global i32 0, align 4
+
+define i32 @bar() {
+; CHECK-LABEL: define {{[^@]+}}@bar() addrspace(1)
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CALL:%.*]] = call addrspace(1) i32 @foo(i32* nofree nonnull align 4 dereferenceable(4) undef)
+; CHECK-NEXT: unreachable
+; CHECK: entry.split:
+; CHECK-NEXT: unreachable
+;
+
+entry:
+ %call = call i32 @foo(i32* @g)
+ ret i32 %call
+}
+
+define internal i32 @foo(i32*) {
+; CHECK-LABEL: define {{[^@]+}}@foo
+; CHECK-SAME: (i32* nocapture nofree nonnull readnone align 4 dereferenceable(4) [[TMP0:%.*]]) addrspace(1)
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
+; CHECK-NEXT: call addrspace(0) void asm sideeffect "ldr r0, [r0] \0Abx lr \0A", ""()
+; CHECK-NEXT: unreachable
+;
+entry:
+ %retval = alloca i32, align 4
+ call void asm sideeffect "ldr r0, [r0] \0Abx lr \0A", ""()
+ unreachable
+}
+
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/pr27568.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/pr27568.ll
new file mode 100644
index 000000000000..0c48d32d5bb6
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/pr27568.ll
@@ -0,0 +1,45 @@
+; 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
+target triple = "x86_64-pc-windows-msvc"
+
+define internal void @callee(i8*) {
+; CHECK-LABEL: define {{[^@]+}}@callee
+; CHECK-SAME: (i8* noalias nocapture nofree readnone [[TMP0:%.*]])
+; CHECK-NEXT: entry:
+; CHECK-NEXT: call void @thunk()
+; CHECK-NEXT: ret void
+;
+entry:
+ call void @thunk()
+ ret void
+}
+
+define void @test1() personality i32 (...)* @__CxxFrameHandler3 {
+; CHECK-LABEL: define {{[^@]+}}@test1() personality i32 (...)* @__CxxFrameHandler3
+; CHECK-NEXT: entry:
+; CHECK-NEXT: invoke void @thunk()
+; CHECK-NEXT: to label [[OUT:%.*]] unwind label [[CPAD:%.*]]
+; CHECK: out:
+; CHECK-NEXT: ret void
+; CHECK: cpad:
+; CHECK-NEXT: [[PAD:%.*]] = cleanuppad within none []
+; CHECK-NEXT: call void @callee(i8* noalias nofree undef) [ "funclet"(token [[PAD]]) ]
+; CHECK-NEXT: cleanupret from [[PAD]] unwind to caller
+;
+entry:
+ invoke void @thunk()
+ to label %out unwind label %cpad
+
+out:
+ ret void
+
+cpad:
+ %pad = cleanuppad within none []
+ call void @callee(i8* null) [ "funclet"(token %pad) ]
+ cleanupret from %pad unwind to caller
+}
+
+
+declare void @thunk()
+
+declare i32 @__CxxFrameHandler3(...)
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/pr3085.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/pr3085.ll
new file mode 100644
index 000000000000..5b8b7da46a47
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/pr3085.ll
@@ -0,0 +1,1945 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
+; RUN: opt -disable-output -passes=attributor -aa-pipeline='basic-aa' -attributor-disable=false -attributor-max-iterations-verify -attributor-max-iterations=1 < %s
+; PR 3085
+
+ %struct.Lit = type { i8 }
+
+define fastcc %struct.Lit* @import_lit(i32 %lit) nounwind {
+entry:
+ br i1 false, label %bb, label %bb1
+
+bb: ; preds = %entry
+ unreachable
+
+bb1: ; preds = %entry
+ br label %bb3
+
+bb2: ; preds = %bb3
+ br label %bb3
+
+bb3: ; preds = %bb2, %bb1
+ br i1 false, label %bb2, label %bb6
+
+bb6: ; preds = %bb3
+ br i1 false, label %bb.i.i, label %bb1.i.i
+
+bb.i.i: ; preds = %bb6
+ br label %int2lit.exit
+
+bb1.i.i: ; preds = %bb6
+ br label %int2lit.exit
+
+int2lit.exit: ; preds = %bb1.i.i, %bb.i.i
+ ret %struct.Lit* null
+}
+
+define fastcc i32 @picosat_main(i32 %argc, i8** %argv) nounwind {
+entry:
+ br i1 false, label %bb.i, label %picosat_time_stamp.exit
+
+bb.i: ; preds = %entry
+ br label %picosat_time_stamp.exit
+
+picosat_time_stamp.exit: ; preds = %bb.i, %entry
+ br label %bb108
+
+bb: ; preds = %bb108
+ br i1 false, label %bb1, label %bb2
+
+bb1: ; preds = %bb
+ br label %bb106
+
+bb2: ; preds = %bb
+ br i1 false, label %bb3, label %bb4
+
+bb3: ; preds = %bb2
+ br label %bb106
+
+bb4: ; preds = %bb2
+ br i1 false, label %bb5, label %bb6
+
+bb5: ; preds = %bb4
+ br label %bb106
+
+bb6: ; preds = %bb4
+ br i1 false, label %bb7, label %bb8
+
+bb7: ; preds = %bb6
+ br label %bb106
+
+bb8: ; preds = %bb6
+ br i1 false, label %bb106, label %bb10
+
+bb10: ; preds = %bb8
+ br i1 false, label %bb106, label %bb12
+
+bb12: ; preds = %bb10
+ br i1 false, label %bb106, label %bb14
+
+bb14: ; preds = %bb12
+ br i1 false, label %bb15, label %bb19
+
+bb15: ; preds = %bb14
+ br i1 false, label %bb16, label %bb17
+
+bb16: ; preds = %bb15
+ br label %bb106
+
+bb17: ; preds = %bb15
+ br label %bb106
+
+bb19: ; preds = %bb14
+ br i1 false, label %bb20, label %bb28
+
+bb20: ; preds = %bb19
+ br i1 false, label %bb21, label %bb22
+
+bb21: ; preds = %bb20
+ br label %bb106
+
+bb22: ; preds = %bb20
+ br i1 false, label %bb106, label %bb24
+
+bb24: ; preds = %bb22
+ br i1 false, label %bb106, label %bb26
+
+bb26: ; preds = %bb24
+ br label %bb106
+
+bb28: ; preds = %bb19
+ br i1 false, label %bb29, label %bb35
+
+bb29: ; preds = %bb28
+ br i1 false, label %bb30, label %bb31
+
+bb30: ; preds = %bb29
+ br label %bb106
+
+bb31: ; preds = %bb29
+ br i1 false, label %bb32, label %bb33
+
+bb32: ; preds = %bb31
+ br label %bb106
+
+bb33: ; preds = %bb31
+ br label %bb106
+
+bb35: ; preds = %bb28
+ br i1 false, label %bb36, label %bb40
+
+bb36: ; preds = %bb35
+ br i1 false, label %bb37, label %bb38
+
+bb37: ; preds = %bb36
+ br label %bb106
+
+bb38: ; preds = %bb36
+ br label %bb106
+
+bb40: ; preds = %bb35
+ br i1 false, label %bb41, label %bb49
+
+bb41: ; preds = %bb40
+ br i1 false, label %bb43, label %bb42
+
+bb42: ; preds = %bb41
+ br label %bb106
+
+bb43: ; preds = %bb41
+ br i1 false, label %bb44, label %bb45
+
+bb44: ; preds = %bb43
+ br label %bb106
+
+bb45: ; preds = %bb43
+ br i1 false, label %bb46, label %bb47
+
+bb46: ; preds = %bb45
+ br label %bb106
+
+bb47: ; preds = %bb45
+ br label %bb106
+
+bb49: ; preds = %bb40
+ br i1 false, label %bb50, label %bb56
+
+bb50: ; preds = %bb49
+ br i1 false, label %bb52, label %bb51
+
+bb51: ; preds = %bb50
+ br label %bb106
+
+bb52: ; preds = %bb50
+ br i1 false, label %bb53, label %bb54
+
+bb53: ; preds = %bb52
+ br label %bb106
+
+bb54: ; preds = %bb52
+ br label %bb106
+
+bb56: ; preds = %bb49
+ br i1 false, label %bb57, label %bb63
+
+bb57: ; preds = %bb56
+ br i1 false, label %bb59, label %bb58
+
+bb58: ; preds = %bb57
+ br label %bb106
+
+bb59: ; preds = %bb57
+ br i1 false, label %bb60, label %bb61
+
+bb60: ; preds = %bb59
+ br label %bb106
+
+bb61: ; preds = %bb59
+ br label %bb106
+
+bb63: ; preds = %bb56
+ br i1 false, label %bb64, label %bb70
+
+bb64: ; preds = %bb63
+ br i1 false, label %bb66, label %bb65
+
+bb65: ; preds = %bb64
+ br label %bb106
+
+bb66: ; preds = %bb64
+ br i1 false, label %bb67, label %bb68
+
+bb67: ; preds = %bb66
+ br label %bb106
+
+bb68: ; preds = %bb66
+ br label %bb106
+
+bb70: ; preds = %bb63
+ br i1 false, label %bb71, label %bb79
+
+bb71: ; preds = %bb70
+ br i1 false, label %bb73, label %bb72
+
+bb72: ; preds = %bb71
+ br label %bb106
+
+bb73: ; preds = %bb71
+ br i1 false, label %bb74, label %bb75
+
+bb74: ; preds = %bb73
+ br label %bb106
+
+bb75: ; preds = %bb73
+ br i1 false, label %bb76, label %bb77
+
+bb76: ; preds = %bb75
+ br label %bb106
+
+bb77: ; preds = %bb75
+ br label %bb106
+
+bb79: ; preds = %bb70
+ br i1 false, label %bb80, label %bb86
+
+bb80: ; preds = %bb79
+ br i1 false, label %bb82, label %bb81
+
+bb81: ; preds = %bb80
+ br label %bb106
+
+bb82: ; preds = %bb80
+ br i1 false, label %bb83, label %bb84
+
+bb83: ; preds = %bb82
+ br label %bb106
+
+bb84: ; preds = %bb82
+ br label %bb106
+
+bb86: ; preds = %bb79
+ br i1 false, label %bb87, label %bb93
+
+bb87: ; preds = %bb86
+ br i1 false, label %bb89, label %bb88
+
+bb88: ; preds = %bb87
+ br label %bb106
+
+bb89: ; preds = %bb87
+ br i1 false, label %bb90, label %bb91
+
+bb90: ; preds = %bb89
+ br label %bb106
+
+bb91: ; preds = %bb89
+ br label %bb106
+
+bb93: ; preds = %bb86
+ br i1 false, label %bb94, label %bb95
+
+bb94: ; preds = %bb93
+ br label %bb106
+
+bb95: ; preds = %bb93
+ br i1 false, label %bb98, label %bb97
+
+bb97: ; preds = %bb95
+ br label %bb106
+
+bb98: ; preds = %bb95
+ br i1 false, label %bb103, label %bb1.i24
+
+bb1.i24: ; preds = %bb98
+ br i1 false, label %bb99, label %bb103
+
+bb99: ; preds = %bb1.i24
+ br i1 false, label %bb101, label %bb100
+
+bb100: ; preds = %bb99
+ br label %bb102
+
+bb101: ; preds = %bb99
+ br label %bb102
+
+bb102: ; preds = %bb101, %bb100
+ br label %bb106
+
+bb103: ; preds = %bb1.i24, %bb98
+ br i1 false, label %bb104, label %bb105
+
+bb104: ; preds = %bb103
+ br label %bb106
+
+bb105: ; preds = %bb103
+ br label %bb106
+
+bb106: ; preds = %bb105, %bb104, %bb102, %bb97, %bb94, %bb91, %bb90, %bb88, %bb84, %bb83, %bb81, %bb77, %bb76, %bb74, %bb72, %bb68, %bb67, %bb65, %bb61, %bb60, %bb58, %bb54, %bb53, %bb51, %bb47, %bb46, %bb44, %bb42, %bb38, %bb37, %bb33, %bb32, %bb30, %bb26, %bb24, %bb22, %bb21, %bb17, %bb16, %bb12, %bb10, %bb8, %bb7, %bb5, %bb3, %bb1
+ br i1 false, label %bb108, label %bb110
+
+bb108: ; preds = %bb106, %picosat_time_stamp.exit
+ br i1 false, label %bb, label %bb110
+
+bb110: ; preds = %bb108, %bb106
+ br i1 false, label %bb112, label %bb171
+
+bb112: ; preds = %bb110
+ br i1 false, label %bb114, label %bb113
+
+bb113: ; preds = %bb112
+ br label %bb114
+
+bb114: ; preds = %bb113, %bb112
+ br i1 false, label %bb.i.i35, label %bb1.i.i36
+
+bb.i.i35: ; preds = %bb114
+ unreachable
+
+bb1.i.i36: ; preds = %bb114
+ br i1 false, label %bb5.i.i.i41, label %bb6.i.i.i42
+
+bb5.i.i.i41: ; preds = %bb1.i.i36
+ unreachable
+
+bb6.i.i.i42: ; preds = %bb1.i.i36
+ br i1 false, label %bb7.i.i.i43, label %bb8.i.i.i44
+
+bb7.i.i.i43: ; preds = %bb6.i.i.i42
+ br label %bb8.i.i.i44
+
+bb8.i.i.i44: ; preds = %bb7.i.i.i43, %bb6.i.i.i42
+ br i1 false, label %picosat_init.exit, label %bb14.i.i
+
+bb14.i.i: ; preds = %bb8.i.i.i44
+ br label %picosat_init.exit
+
+picosat_init.exit: ; preds = %bb14.i.i, %bb8.i.i.i44
+ br i1 false, label %bb116, label %bb115
+
+bb115: ; preds = %picosat_init.exit
+ br label %bb116
+
+bb116: ; preds = %bb115, %picosat_init.exit
+ br i1 false, label %bb119, label %bb118
+
+bb118: ; preds = %bb116
+ br label %bb119
+
+bb119: ; preds = %bb118, %bb116
+ br i1 false, label %bb121, label %bb120
+
+bb120: ; preds = %bb119
+ br label %bb121
+
+bb121: ; preds = %bb120, %bb119
+ br i1 false, label %bb126, label %bb122
+
+bb122: ; preds = %bb121
+ br label %bb126
+
+bb126: ; preds = %bb122, %bb121
+ br i1 false, label %bb128, label %bb127
+
+bb127: ; preds = %bb126
+ br label %bb128
+
+bb128: ; preds = %bb127, %bb126
+ br label %SKIP_COMMENTS.i
+
+SKIP_COMMENTS.i.loopexit: ; preds = %bb.i149, %bb.i149
+ br label %SKIP_COMMENTS.i.backedge
+
+SKIP_COMMENTS.i: ; preds = %SKIP_COMMENTS.i.backedge, %bb128
+ br i1 false, label %bb.i149.preheader, label %bb3.i152
+
+bb.i149.preheader: ; preds = %SKIP_COMMENTS.i
+ br label %bb.i149
+
+bb.i149: ; preds = %bb.i149, %bb.i149.preheader
+ switch i32 0, label %bb.i149 [
+ i32 -1, label %SKIP_COMMENTS.i.loopexit
+ i32 10, label %SKIP_COMMENTS.i.loopexit
+ ]
+
+bb3.i152: ; preds = %SKIP_COMMENTS.i
+ br i1 false, label %bb4.i153, label %SKIP_COMMENTS.i.backedge
+
+SKIP_COMMENTS.i.backedge: ; preds = %bb3.i152, %SKIP_COMMENTS.i.loopexit
+ br label %SKIP_COMMENTS.i
+
+bb4.i153: ; preds = %bb3.i152
+ br i1 false, label %bb5.i154, label %bb129
+
+bb5.i154: ; preds = %bb4.i153
+ br i1 false, label %bb129, label %bb6.i155.preheader
+
+bb6.i155.preheader: ; preds = %bb5.i154
+ br label %bb6.i155
+
+bb6.i155: ; preds = %bb6.i155, %bb6.i155.preheader
+ br i1 false, label %bb7.i156, label %bb6.i155
+
+bb7.i156: ; preds = %bb6.i155
+ br i1 false, label %bb8.i157, label %bb129
+
+bb8.i157: ; preds = %bb7.i156
+ br i1 false, label %bb9.i158, label %bb129
+
+bb9.i158: ; preds = %bb8.i157
+ br i1 false, label %bb10.i159, label %bb129
+
+bb10.i159: ; preds = %bb9.i158
+ br i1 false, label %bb129, label %bb11.i160.preheader
+
+bb11.i160.preheader: ; preds = %bb10.i159
+ br label %bb11.i160
+
+bb11.i160: ; preds = %bb11.i160, %bb11.i160.preheader
+ br i1 false, label %bb12.i161, label %bb11.i160
+
+bb12.i161: ; preds = %bb11.i160
+ br i1 false, label %bb129, label %bb15.i165.preheader
+
+bb15.i165.preheader: ; preds = %bb12.i161
+ br label %bb15.i165
+
+bb14.i163: ; preds = %bb15.i165
+ br label %bb15.i165
+
+bb15.i165: ; preds = %bb14.i163, %bb15.i165.preheader
+ br i1 false, label %bb16.i166, label %bb14.i163
+
+bb16.i166: ; preds = %bb15.i165
+ br i1 false, label %bb129, label %bb17.i167.preheader
+
+bb17.i167.preheader: ; preds = %bb16.i166
+ br label %bb17.i167
+
+bb17.i167: ; preds = %bb17.i167, %bb17.i167.preheader
+ br i1 false, label %bb18.i168, label %bb17.i167
+
+bb18.i168: ; preds = %bb17.i167
+ br i1 false, label %bb129, label %bb21.i172.preheader
+
+bb21.i172.preheader: ; preds = %bb18.i168
+ br label %bb21.i172
+
+bb20.i170: ; preds = %bb21.i172
+ br label %bb21.i172
+
+bb21.i172: ; preds = %bb20.i170, %bb21.i172.preheader
+ br i1 false, label %bb22.i173, label %bb20.i170
+
+bb22.i173: ; preds = %bb21.i172
+ br i1 false, label %bb24.i175, label %bb129
+
+bb24.i175: ; preds = %bb22.i173
+ br i1 false, label %bb26.i180, label %bb25.i176
+
+bb25.i176: ; preds = %bb24.i175
+ br label %bb26.i180
+
+bb26.i180: ; preds = %bb25.i176, %bb24.i175
+ br i1 false, label %bb.i.i181, label %bb3.i.i184.preheader
+
+bb.i.i181: ; preds = %bb26.i180
+ br label %bb3.i.i184.preheader
+
+bb3.i.i184.preheader: ; preds = %bb.i.i181, %bb26.i180
+ br label %bb3.i.i184
+
+bb2.i.i183: ; preds = %bb3.i.i184
+ br label %bb3.i.i184
+
+bb3.i.i184: ; preds = %bb2.i.i183, %bb3.i.i184.preheader
+ br i1 false, label %bb2.i.i183, label %bb4.i.i185
+
+bb4.i.i185: ; preds = %bb3.i.i184
+ br i1 false, label %bb.i.i.i186, label %picosat_adjust.exit.i
+
+bb.i.i.i186: ; preds = %bb4.i.i185
+ br label %picosat_adjust.exit.i
+
+picosat_adjust.exit.i: ; preds = %bb.i.i.i186, %bb4.i.i185
+ br i1 false, label %bb28.i188, label %bb27.i187
+
+bb27.i187: ; preds = %picosat_adjust.exit.i
+ br label %bb28.i188
+
+bb28.i188: ; preds = %bb27.i187, %picosat_adjust.exit.i
+ br label %READ_LITERAL.i.outer
+
+READ_LITERAL.i.outer: ; preds = %READ_LITERAL.i.outer.backedge, %bb28.i188
+ br label %READ_LITERAL.i
+
+READ_LITERAL.i.loopexit: ; preds = %bb29.i189, %bb29.i189
+ br label %READ_LITERAL.i.backedge
+
+READ_LITERAL.i: ; preds = %READ_LITERAL.i.backedge, %READ_LITERAL.i.outer
+ switch i32 0, label %bb39.i199 [
+ i32 99, label %bb29.i189.preheader
+ i32 -1, label %bb33.i193
+ ]
+
+bb29.i189.preheader: ; preds = %READ_LITERAL.i
+ br label %bb29.i189
+
+bb29.i189: ; preds = %bb29.i189, %bb29.i189.preheader
+ switch i32 0, label %bb29.i189 [
+ i32 -1, label %READ_LITERAL.i.loopexit
+ i32 10, label %READ_LITERAL.i.loopexit
+ ]
+
+bb33.i193: ; preds = %READ_LITERAL.i
+ br i1 false, label %bb35.i195, label %parse.exit
+
+bb35.i195: ; preds = %bb33.i193
+ br i1 false, label %bb38.i198, label %parse.exit
+
+bb38.i198: ; preds = %bb35.i195
+ br label %parse.exit
+
+bb39.i199: ; preds = %READ_LITERAL.i
+ br i1 false, label %bb40.i200, label %READ_LITERAL.i.backedge
+
+READ_LITERAL.i.backedge: ; preds = %bb39.i199, %READ_LITERAL.i.loopexit
+ br label %READ_LITERAL.i
+
+bb40.i200: ; preds = %bb39.i199
+ br i1 false, label %bb41.i201, label %bb42.i202
+
+bb41.i201: ; preds = %bb40.i200
+ br label %bb42.i202
+
+bb42.i202: ; preds = %bb41.i201, %bb40.i200
+ br i1 false, label %parse.exit.loopexit, label %bb46.i.preheader
+
+bb46.i.preheader: ; preds = %bb42.i202
+ br label %bb46.i
+
+bb45.i: ; preds = %bb46.i
+ br label %bb46.i
+
+bb46.i: ; preds = %bb45.i, %bb46.i.preheader
+ br i1 false, label %bb47.i, label %bb45.i
+
+bb47.i: ; preds = %bb46.i
+ br i1 false, label %parse.exit.loopexit, label %bb50.i
+
+bb50.i: ; preds = %bb47.i
+ br i1 false, label %bb55.i, label %bb51.i
+
+bb51.i: ; preds = %bb50.i
+ br i1 false, label %parse.exit.loopexit, label %bb54.i
+
+bb54.i: ; preds = %bb51.i
+ br label %bb56.i
+
+bb55.i: ; preds = %bb50.i
+ br label %bb56.i
+
+bb56.i: ; preds = %bb55.i, %bb54.i
+ br i1 false, label %bb3.i11.i, label %bb.i8.i
+
+bb.i8.i: ; preds = %bb56.i
+ br i1 false, label %bb1.i9.i, label %bb3.i11.i
+
+bb1.i9.i: ; preds = %bb.i8.i
+ br i1 false, label %bb3.i11.i, label %bb2.i10.i
+
+bb2.i10.i: ; preds = %bb1.i9.i
+ unreachable
+
+bb3.i11.i: ; preds = %bb1.i9.i, %bb.i8.i, %bb56.i
+ br i1 false, label %bb7.i.i208, label %bb6.i.i207
+
+bb6.i.i207: ; preds = %bb3.i11.i
+ br label %READ_LITERAL.i.outer.backedge
+
+bb7.i.i208: ; preds = %bb3.i11.i
+ br i1 false, label %bb53.i.i.i.i.preheader, label %bb.i.i.i.i210.preheader
+
+bb.i.i.i.i210.preheader: ; preds = %bb7.i.i208
+ br label %bb.i.i.i.i210
+
+bb.i.i.i.i210: ; preds = %bb.i.i.i.i210.backedge, %bb.i.i.i.i210.preheader
+ br i1 false, label %bb17.i.i.i.i, label %bb18.i.i.i.i
+
+bb17.i.i.i.i: ; preds = %bb.i.i.i.i210
+ br label %bb18.i.i.i.i
+
+bb18.i.i.i.i: ; preds = %bb17.i.i.i.i, %bb.i.i.i.i210
+ br i1 false, label %bb19.i.i.i.i, label %bb20.i.i.i.i
+
+bb19.i.i.i.i: ; preds = %bb18.i.i.i.i
+ br label %bb20.i.i.i.i
+
+bb20.i.i.i.i: ; preds = %bb19.i.i.i.i, %bb18.i.i.i.i
+ br i1 false, label %bb21.i.i.i.i, label %bb22.i.i.i.i
+
+bb21.i.i.i.i: ; preds = %bb20.i.i.i.i
+ br label %bb22.i.i.i.i
+
+bb22.i.i.i.i: ; preds = %bb21.i.i.i.i, %bb20.i.i.i.i
+ br label %bb23.i.i.i.i.outer
+
+bb23.i.i.i.i.outer: ; preds = %bb28.i.i.i.i, %bb22.i.i.i.i
+ br label %bb23.i.i.i.i
+
+bb23.i.i.i.i: ; preds = %bb23.i.i.i.i, %bb23.i.i.i.i.outer
+ br i1 false, label %bb23.i.i.i.i, label %bb26.i.i.i.i.preheader
+
+bb26.i.i.i.i.preheader: ; preds = %bb23.i.i.i.i
+ br label %bb26.i.i.i.i
+
+bb26.i.i.i.i: ; preds = %bb26.i.i.i.i, %bb26.i.i.i.i.preheader
+ br i1 false, label %bb27.i.i.i.i, label %bb26.i.i.i.i
+
+bb27.i.i.i.i: ; preds = %bb26.i.i.i.i
+ br i1 false, label %bb28.i.i.i.i, label %bb29.i.i.i.i
+
+bb28.i.i.i.i: ; preds = %bb27.i.i.i.i
+ br label %bb23.i.i.i.i.outer
+
+bb29.i.i.i.i: ; preds = %bb27.i.i.i.i
+ br i1 false, label %bb33.i.i.i.i, label %bb44.i.i.i.i
+
+bb33.i.i.i.i: ; preds = %bb29.i.i.i.i
+ br i1 false, label %bb34.i.i.i.i, label %bb38.i.i.i.i
+
+bb34.i.i.i.i: ; preds = %bb33.i.i.i.i
+ br i1 false, label %bb37.i.i.i.i, label %bb35.i.i.i.i
+
+bb35.i.i.i.i: ; preds = %bb34.i.i.i.i
+ br label %bb37.i.i.i.i
+
+bb37.i.i.i.i: ; preds = %bb35.i.i.i.i, %bb34.i.i.i.i
+ br label %bb38.i.i.i.i
+
+bb38.i.i.i.i: ; preds = %bb37.i.i.i.i, %bb33.i.i.i.i
+ br i1 false, label %bb39.i.i.i.i, label %bb43.i.i.i.i
+
+bb39.i.i.i.i: ; preds = %bb38.i.i.i.i
+ br i1 false, label %bb42.i.i.i.i, label %bb40.i.i.i.i
+
+bb40.i.i.i.i: ; preds = %bb39.i.i.i.i
+ br label %bb42.i.i.i.i
+
+bb42.i.i.i.i: ; preds = %bb40.i.i.i.i, %bb39.i.i.i.i
+ br label %bb43.i.i.i.i
+
+bb43.i.i.i.i: ; preds = %bb42.i.i.i.i, %bb38.i.i.i.i
+ br label %bb.i.i.i.i210.backedge
+
+bb.i.i.i.i210.backedge: ; preds = %bb47.i.i.i.i, %bb44.i.i.i.i, %bb43.i.i.i.i
+ br label %bb.i.i.i.i210
+
+bb44.i.i.i.i: ; preds = %bb29.i.i.i.i
+ br i1 false, label %bb.i.i.i.i210.backedge, label %bb46.i.i.i.i
+
+bb46.i.i.i.i: ; preds = %bb44.i.i.i.i
+ br i1 false, label %bb47.i.i.i.i, label %bb53.i.i.i.i.preheader.loopexit
+
+bb53.i.i.i.i.preheader.loopexit: ; preds = %bb46.i.i.i.i
+ br label %bb53.i.i.i.i.preheader
+
+bb53.i.i.i.i.preheader: ; preds = %bb53.i.i.i.i.preheader.loopexit, %bb7.i.i208
+ br label %bb53.i.i.i.i
+
+bb47.i.i.i.i: ; preds = %bb46.i.i.i.i
+ br label %bb.i.i.i.i210.backedge
+
+bb50.i.i.i.i: ; preds = %bb53.i.i.i.i
+ br i1 false, label %bb51.i.i.i.i, label %bb52.i.i.i.i
+
+bb51.i.i.i.i: ; preds = %bb50.i.i.i.i
+ br label %bb52.i.i.i.i
+
+bb52.i.i.i.i: ; preds = %bb51.i.i.i.i, %bb50.i.i.i.i
+ br label %bb53.i.i.i.i
+
+bb53.i.i.i.i: ; preds = %bb52.i.i.i.i, %bb53.i.i.i.i.preheader
+ br i1 false, label %bb50.i.i.i.i, label %bb59.i.i.i.i.preheader
+
+bb59.i.i.i.i.preheader: ; preds = %bb53.i.i.i.i
+ br label %bb59.i.i.i.i
+
+bb55.i.i.i.i: ; preds = %bb59.i.i.i.i
+ br label %bb57.i.i.i.i
+
+bb56.i.i.i.i: ; preds = %bb57.i.i.i.i
+ br label %bb57.i.i.i.i
+
+bb57.i.i.i.i: ; preds = %bb56.i.i.i.i, %bb55.i.i.i.i
+ br i1 false, label %bb56.i.i.i.i, label %bb58.i.i.i.i
+
+bb58.i.i.i.i: ; preds = %bb57.i.i.i.i
+ br label %bb59.i.i.i.i
+
+bb59.i.i.i.i: ; preds = %bb58.i.i.i.i, %bb59.i.i.i.i.preheader
+ br i1 false, label %bb60.i.i.i.i, label %bb55.i.i.i.i
+
+bb60.i.i.i.i: ; preds = %bb59.i.i.i.i
+ br label %bb69.i.i.i.i
+
+bb61.i.i.i.i: ; preds = %bb69.i.i.i.i
+ br i1 false, label %bb68.i.i.i.i, label %bb62.i.i.i.i
+
+bb62.i.i.i.i: ; preds = %bb61.i.i.i.i
+ br i1 false, label %bb63.i.i.i.i, label %bb65.i.i.i.i
+
+bb63.i.i.i.i: ; preds = %bb62.i.i.i.i
+ br i1 false, label %bb.i.i12.i, label %bb65.i.i.i.i
+
+bb65.i.i.i.i: ; preds = %bb63.i.i.i.i, %bb62.i.i.i.i
+ br i1 false, label %bb.i.i12.i, label %bb67.i.i.i.i
+
+bb67.i.i.i.i: ; preds = %bb65.i.i.i.i
+ br label %bb68.i.i.i.i
+
+bb68.i.i.i.i: ; preds = %bb67.i.i.i.i, %bb61.i.i.i.i
+ br label %bb69.i.i.i.i
+
+bb69.i.i.i.i: ; preds = %bb68.i.i.i.i, %bb60.i.i.i.i
+ br i1 false, label %bb61.i.i.i.i, label %bb70.i.i.i.i
+
+bb70.i.i.i.i: ; preds = %bb69.i.i.i.i
+ br label %READ_LITERAL.i.outer.backedge
+
+bb.i.i12.i: ; preds = %bb65.i.i.i.i, %bb63.i.i.i.i
+ br i1 false, label %bb1.i.i.i213, label %bb5.i.i.i218
+
+bb1.i.i.i213: ; preds = %bb.i.i12.i
+ br i1 false, label %bb4.i.i.i217, label %bb2.i.i.i214
+
+bb2.i.i.i214: ; preds = %bb1.i.i.i213
+ br label %bb4.i.i.i217
+
+bb4.i.i.i217: ; preds = %bb2.i.i.i214, %bb1.i.i.i213
+ br label %bb5.i.i.i218
+
+bb5.i.i.i218: ; preds = %bb4.i.i.i217, %bb.i.i12.i
+ br label %READ_LITERAL.i.outer.backedge
+
+READ_LITERAL.i.outer.backedge: ; preds = %bb5.i.i.i218, %bb70.i.i.i.i, %bb6.i.i207
+ br label %READ_LITERAL.i.outer
+
+parse.exit.loopexit: ; preds = %bb51.i, %bb47.i, %bb42.i202
+ br label %parse.exit
+
+parse.exit: ; preds = %parse.exit.loopexit, %bb38.i198, %bb35.i195, %bb33.i193
+ br i1 false, label %bb130, label %bb129
+
+bb129: ; preds = %parse.exit, %bb22.i173, %bb18.i168, %bb16.i166, %bb12.i161, %bb10.i159, %bb9.i158, %bb8.i157, %bb7.i156, %bb5.i154, %bb4.i153
+ br label %bb170
+
+bb130: ; preds = %parse.exit
+ br i1 false, label %bb143, label %bb142.preheader
+
+bb142.preheader: ; preds = %bb130
+ br label %bb142
+
+bb132: ; preds = %bb142
+ br i1 false, label %bb137, label %bb133
+
+bb133: ; preds = %bb132
+ br i1 false, label %bb137, label %bb134
+
+bb134: ; preds = %bb133
+ br i1 false, label %bb137, label %bb135
+
+bb135: ; preds = %bb134
+ br i1 false, label %bb137, label %bb136
+
+bb136: ; preds = %bb135
+ br i1 false, label %bb137, label %bb138
+
+bb137: ; preds = %bb136, %bb135, %bb134, %bb133, %bb132
+ br label %bb141
+
+bb138: ; preds = %bb136
+ br i1 false, label %bb139, label %bb141
+
+bb139: ; preds = %bb138
+ br i1 false, label %bb2.i126, label %picosat_assume.exit
+
+bb2.i126: ; preds = %bb139
+ br i1 false, label %bb5.i130, label %bb3.i127
+
+bb3.i127: ; preds = %bb2.i126
+ br label %bb5.i130
+
+bb5.i130: ; preds = %bb3.i127, %bb2.i126
+ br label %picosat_assume.exit
+
+picosat_assume.exit: ; preds = %bb5.i130, %bb139
+ br i1 false, label %bb141, label %bb140
+
+bb140: ; preds = %picosat_assume.exit
+ br label %bb141
+
+bb141: ; preds = %bb140, %picosat_assume.exit, %bb138, %bb137
+ br label %bb142
+
+bb142: ; preds = %bb141, %bb142.preheader
+ br i1 false, label %bb132, label %bb143.loopexit
+
+bb143.loopexit: ; preds = %bb142
+ br label %bb143
+
+bb143: ; preds = %bb143.loopexit, %bb130
+ br i1 false, label %bb145, label %bb144
+
+bb144: ; preds = %bb143
+ br label %bb11.i
+
+bb5.i114: ; preds = %bb11.i
+ br label %bb11.i
+
+bb11.i: ; preds = %bb5.i114, %bb144
+ br i1 false, label %bb12.i, label %bb5.i114
+
+bb12.i: ; preds = %bb11.i
+ br i1 false, label %bb.i.i.i118, label %bb1.i.i.i119
+
+bb.i.i.i118: ; preds = %bb12.i
+ br label %int2lit.exit.i
+
+bb1.i.i.i119: ; preds = %bb12.i
+ br label %int2lit.exit.i
+
+int2lit.exit.i: ; preds = %bb1.i.i.i119, %bb.i.i.i118
+ br label %bb19.i
+
+bb13.i: ; preds = %bb19.i
+ br label %bb17.i
+
+bb14.i: ; preds = %bb17.i
+ br label %bb17.i
+
+bb17.i: ; preds = %bb14.i, %bb13.i
+ br i1 false, label %bb14.i, label %bb18.i
+
+bb18.i: ; preds = %bb17.i
+ br label %bb19.i
+
+bb19.i: ; preds = %bb18.i, %int2lit.exit.i
+ br i1 false, label %bb20.i, label %bb13.i
+
+bb20.i: ; preds = %bb19.i
+ br label %bb33.i
+
+bb24.i: ; preds = %bb33.i
+ br i1 false, label %bb29.i, label %bb25.i
+
+bb25.i: ; preds = %bb24.i
+ br label %bb27.i
+
+bb26.i: ; preds = %bb27.i
+ br label %bb27.i
+
+bb27.i: ; preds = %bb26.i, %bb25.i
+ br i1 false, label %bb26.i, label %bb28.i
+
+bb28.i: ; preds = %bb27.i
+ br label %bb29.i
+
+bb29.i: ; preds = %bb28.i, %bb24.i
+ br label %bb33.i
+
+bb33.i: ; preds = %bb29.i, %bb20.i
+ br i1 false, label %bb34.i, label %bb24.i
+
+bb34.i: ; preds = %bb33.i
+ br i1 false, label %bb.i.i58.i, label %bb1.i.i59.i
+
+bb.i.i58.i: ; preds = %bb34.i
+ br label %int2lit.exit63.i
+
+bb1.i.i59.i: ; preds = %bb34.i
+ br label %int2lit.exit63.i
+
+int2lit.exit63.i: ; preds = %bb1.i.i59.i, %bb.i.i58.i
+ br label %bb41.i
+
+bb35.i: ; preds = %bb41.i
+ br label %bb39.i
+
+bb36.i: ; preds = %bb39.i
+ br i1 false, label %bb38.i, label %bb37.i
+
+bb37.i: ; preds = %bb36.i
+ br label %bb38.i
+
+bb38.i: ; preds = %bb37.i, %bb36.i
+ br label %bb39.i
+
+bb39.i: ; preds = %bb38.i, %bb35.i
+ br i1 false, label %bb36.i, label %bb40.i
+
+bb40.i: ; preds = %bb39.i
+ br label %bb41.i
+
+bb41.i: ; preds = %bb40.i, %int2lit.exit63.i
+ br i1 false, label %bb42.i, label %bb35.i
+
+bb42.i: ; preds = %bb41.i
+ br label %bb44.i
+
+bb43.i: ; preds = %bb44.i
+ br label %bb44.i
+
+bb44.i: ; preds = %bb43.i, %bb42.i
+ br i1 false, label %bb43.i, label %picosat_print.exit
+
+picosat_print.exit: ; preds = %bb44.i
+ br label %bb167
+
+bb145: ; preds = %bb143
+ br i1 false, label %bb147, label %bb146
+
+bb146: ; preds = %bb145
+ br label %bb147
+
+bb147: ; preds = %bb146, %bb145
+ br i1 false, label %bb149, label %bb148
+
+bb148: ; preds = %bb147
+ br label %bb149
+
+bb149: ; preds = %bb148, %bb147
+ br i1 false, label %bb.i54, label %bb1.i55
+
+bb.i54: ; preds = %bb149
+ unreachable
+
+bb1.i55: ; preds = %bb149
+ br i1 false, label %bb.i.i56, label %bb1.i.i57
+
+bb.i.i56: ; preds = %bb1.i55
+ br label %bb1.i.i57
+
+bb1.i.i57: ; preds = %bb.i.i56, %bb1.i55
+ br i1 false, label %bb3.i.i59, label %bb2.i.i58
+
+bb2.i.i58: ; preds = %bb1.i.i57
+ br label %bb3.i.i59
+
+bb3.i.i59: ; preds = %bb2.i.i58, %bb1.i.i57
+ br i1 false, label %bb5.i.i61, label %sat.exit.i
+
+bb5.i.i61: ; preds = %bb3.i.i59
+ br i1 false, label %bb6.i.i65, label %bb1.i.i.i63
+
+bb1.i.i.i63: ; preds = %bb5.i.i61
+ br i1 false, label %sat.exit.i, label %bb6.i.i65
+
+bb6.i.i65: ; preds = %bb1.i.i.i63, %bb5.i.i61
+ br i1 false, label %bb8.i.i67, label %bb7.i.i66
+
+bb7.i.i66: ; preds = %bb6.i.i65
+ br label %bb8.i.i67
+
+bb8.i.i67: ; preds = %bb7.i.i66, %bb6.i.i65
+ br i1 false, label %bb10.i.i69, label %sat.exit.i
+
+bb10.i.i69: ; preds = %bb8.i.i67
+ br i1 false, label %bb11.i.i70, label %bb1.i61.i.i
+
+bb1.i61.i.i: ; preds = %bb10.i.i69
+ br i1 false, label %sat.exit.i, label %bb11.i.i70
+
+bb11.i.i70: ; preds = %bb1.i61.i.i, %bb10.i.i69
+ br label %bb13.i.i71.outer
+
+bb13.i.i71.outer: ; preds = %bb42.i.i, %bb11.i.i70
+ br label %bb13.i.i71
+
+bb13.i.i71: ; preds = %bb13.i.i71.backedge, %bb13.i.i71.outer
+ br i1 false, label %bb14.i.i72, label %bb15.i.i73
+
+bb14.i.i72: ; preds = %bb13.i.i71
+ br label %bb15.i.i73
+
+bb15.i.i73: ; preds = %bb14.i.i72, %bb13.i.i71
+ br i1 false, label %bb19.i.i, label %bb16.i.i
+
+bb16.i.i: ; preds = %bb15.i.i73
+ br i1 false, label %bb.i.i79.i.i, label %incincs.exit.i.i
+
+bb.i.i79.i.i: ; preds = %bb16.i.i
+ br label %bb4.i.i.i85.i.i
+
+bb.i.i.i80.i.i: ; preds = %bb4.i.i.i85.i.i
+ br i1 false, label %bb3.i.i.i83.i.i, label %bb1.i.i.i81.i.i
+
+bb1.i.i.i81.i.i: ; preds = %bb.i.i.i80.i.i
+ br i1 false, label %bb2.i.i.i82.i.i, label %bb3.i.i.i83.i.i
+
+bb2.i.i.i82.i.i: ; preds = %bb1.i.i.i81.i.i
+ br label %bb3.i.i.i83.i.i
+
+bb3.i.i.i83.i.i: ; preds = %bb2.i.i.i82.i.i, %bb1.i.i.i81.i.i, %bb.i.i.i80.i.i
+ br label %bb4.i.i.i85.i.i
+
+bb4.i.i.i85.i.i: ; preds = %bb3.i.i.i83.i.i, %bb.i.i79.i.i
+ br i1 false, label %crescore.exit.i.i.i.i, label %bb.i.i.i80.i.i
+
+crescore.exit.i.i.i.i: ; preds = %bb4.i.i.i85.i.i
+ br label %incincs.exit.i.i
+
+incincs.exit.i.i: ; preds = %crescore.exit.i.i.i.i, %bb16.i.i
+ br i1 false, label %bb13.i.i71.backedge, label %sat.exit.i.loopexit.loopexit
+
+bb13.i.i71.backedge: ; preds = %bb1.i55.i.i, %bb28.i.i, %incincs.exit.i.i
+ br label %bb13.i.i71
+
+bb19.i.i: ; preds = %bb15.i.i73
+ br i1 false, label %bb20.i.i, label %bb1.i68.i.i
+
+bb1.i68.i.i: ; preds = %bb19.i.i
+ br i1 false, label %sat.exit.i.loopexit.loopexit, label %bb20.i.i
+
+bb20.i.i: ; preds = %bb1.i68.i.i, %bb19.i.i
+ br i1 false, label %bb24.i.i, label %bb21.i.i
+
+bb21.i.i: ; preds = %bb20.i.i
+ br i1 false, label %bb22.i.i, label %bb24.i.i
+
+bb22.i.i: ; preds = %bb21.i.i
+ br i1 false, label %bb23.i.i, label %bb24.i.i
+
+bb23.i.i: ; preds = %bb22.i.i
+ br label %bb24.i.i
+
+bb24.i.i: ; preds = %bb23.i.i, %bb22.i.i, %bb21.i.i, %bb20.i.i
+ br i1 false, label %bb26.i.i, label %sat.exit.i.loopexit.loopexit
+
+bb26.i.i: ; preds = %bb24.i.i
+ br i1 false, label %bb27.i.i, label %bb33.i.i.loopexit
+
+bb27.i.i: ; preds = %bb26.i.i
+ br i1 false, label %bb33.i.i.loopexit, label %bb28.i.i
+
+bb28.i.i: ; preds = %bb27.i.i
+ br i1 false, label %bb1.i55.i.i, label %bb13.i.i71.backedge
+
+bb1.i55.i.i: ; preds = %bb28.i.i
+ br i1 false, label %bb29.i.i, label %bb13.i.i71.backedge
+
+bb29.i.i: ; preds = %bb1.i55.i.i
+ br i1 false, label %bb31.i.i, label %sat.exit.i.loopexit.loopexit2
+
+bb31.i.i: ; preds = %bb29.i.i
+ br i1 false, label %bb33.i.i, label %bb1.i48.i.i
+
+bb1.i48.i.i: ; preds = %bb31.i.i
+ br i1 false, label %sat.exit.i.loopexit.loopexit2, label %bb33.i.i
+
+bb33.i.i.loopexit: ; preds = %bb27.i.i, %bb26.i.i
+ br label %bb33.i.i
+
+bb33.i.i: ; preds = %bb33.i.i.loopexit, %bb1.i48.i.i, %bb31.i.i
+ br i1 false, label %bb34.i.i, label %bb35.i.i
+
+bb34.i.i: ; preds = %bb33.i.i
+ br i1 false, label %bb35.i.i, label %bb2.i44.i.i76
+
+bb2.i44.i.i76: ; preds = %bb34.i.i
+ br label %bb35.i.i
+
+bb35.i.i: ; preds = %bb2.i44.i.i76, %bb34.i.i, %bb33.i.i
+ br i1 false, label %bb1.i37.i.i, label %bb.i35.i.i
+
+bb.i35.i.i: ; preds = %bb35.i.i
+ br label %bb36.i.i
+
+bb1.i37.i.i: ; preds = %bb35.i.i
+ br i1 false, label %bb37.i.i, label %bb36.i.i
+
+bb36.i.i: ; preds = %bb1.i37.i.i, %bb.i35.i.i
+ br label %bb25.i23.i.i
+
+bb.i18.i.i: ; preds = %bb25.i23.i.i
+ br i1 false, label %bb24.i22.i.i, label %bb22.i19.i.i
+
+bb22.i19.i.i: ; preds = %bb.i18.i.i
+ br label %bb24.i22.i.i
+
+bb24.i22.i.i: ; preds = %bb22.i19.i.i, %bb.i18.i.i
+ br label %bb25.i23.i.i
+
+bb25.i23.i.i: ; preds = %bb24.i22.i.i, %bb36.i.i
+ br i1 false, label %bb.i18.i.i, label %bb26.i24.i.i
+
+bb26.i24.i.i: ; preds = %bb25.i23.i.i
+ br i1 false, label %bb27.i25.i.i, label %bb32.i.i.i
+
+bb27.i25.i.i: ; preds = %bb26.i24.i.i
+ br label %bb32.i.i.i
+
+bb32.i.i.i: ; preds = %bb27.i25.i.i, %bb26.i24.i.i
+ br label %bb64.i.i.i
+
+bb33.i.i.i: ; preds = %bb64.i.i.i
+ br i1 false, label %bb60.i.i.i, label %bb34.i.i.i
+
+bb34.i.i.i: ; preds = %bb33.i.i.i
+ br i1 false, label %bb38.i.i.i, label %bb60.i.i.i
+
+bb38.i.i.i: ; preds = %bb34.i.i.i
+ br i1 false, label %bb39.i.i.i, label %bb48.i.i.i
+
+bb39.i.i.i: ; preds = %bb38.i.i.i
+ br i1 false, label %bb48.i.i.i, label %bb40.i.i.i
+
+bb40.i.i.i: ; preds = %bb39.i.i.i
+ br i1 false, label %bb60.i.i.i, label %bb45.i.i.i
+
+bb45.i.i.i: ; preds = %bb40.i.i.i
+ br label %bb60.i.i.i
+
+bb48.i.i.i: ; preds = %bb39.i.i.i, %bb38.i.i.i
+ br i1 false, label %bb53.i.i.i, label %bb60.i.i.i
+
+bb53.i.i.i: ; preds = %bb48.i.i.i
+ br i1 false, label %bb60.i.i.i, label %bb58.i.i.i
+
+bb58.i.i.i: ; preds = %bb53.i.i.i
+ br i1 false, label %bb59.i.i.i, label %bb60.i.i.i
+
+bb59.i.i.i: ; preds = %bb58.i.i.i
+ br label %bb60.i.i.i
+
+bb60.i.i.i: ; preds = %bb59.i.i.i, %bb58.i.i.i, %bb53.i.i.i, %bb48.i.i.i, %bb45.i.i.i, %bb40.i.i.i, %bb34.i.i.i, %bb33.i.i.i
+ %lcollect.i.i.i.1 = phi i32 [ %lcollect.i.i.i.2, %bb34.i.i.i ], [ %lcollect.i.i.i.2, %bb48.i.i.i ], [ %lcollect.i.i.i.2, %bb58.i.i.i ], [ %lcollect.i.i.i.2, %bb59.i.i.i ], [ %lcollect.i.i.i.2, %bb53.i.i.i ], [ %lcollect.i.i.i.2, %bb33.i.i.i ], [ %lcollect.i.i.i.2, %bb40.i.i.i ], [ 0, %bb45.i.i.i ] ; <i32> [#uses=1]
+ br label %bb64.i.i.i
+
+bb64.i.i.i: ; preds = %bb60.i.i.i, %bb32.i.i.i
+ %lcollect.i.i.i.2 = phi i32 [ 0, %bb32.i.i.i ], [ %lcollect.i.i.i.1, %bb60.i.i.i ] ; <i32> [#uses=8]
+ br i1 false, label %bb65.i.i.i, label %bb33.i.i.i
+
+bb65.i.i.i: ; preds = %bb64.i.i.i
+ br i1 false, label %bb103.i.i.i.preheader, label %bb66.i.i.i.preheader
+
+bb66.i.i.i.preheader: ; preds = %bb65.i.i.i
+ br label %bb66.i.i.i
+
+bb66.i.i.i: ; preds = %bb66.i.i.i.backedge, %bb66.i.i.i.preheader
+ br i1 false, label %bb67.i.i.i, label %bb68.i.i.i
+
+bb67.i.i.i: ; preds = %bb66.i.i.i
+ br label %bb68.i.i.i
+
+bb68.i.i.i: ; preds = %bb67.i.i.i, %bb66.i.i.i
+ br i1 false, label %bb69.i.i.i, label %bb70.i.i.i
+
+bb69.i.i.i: ; preds = %bb68.i.i.i
+ br label %bb70.i.i.i
+
+bb70.i.i.i: ; preds = %bb69.i.i.i, %bb68.i.i.i
+ br i1 false, label %bb71.i.i.i, label %bb72.i.i.i
+
+bb71.i.i.i: ; preds = %bb70.i.i.i
+ br label %bb72.i.i.i
+
+bb72.i.i.i: ; preds = %bb71.i.i.i, %bb70.i.i.i
+ br label %bb73.i.i.i.outer
+
+bb73.i.i.i.outer: ; preds = %bb78.i.i.i, %bb72.i.i.i
+ br label %bb73.i.i.i
+
+bb73.i.i.i: ; preds = %bb73.i.i.i, %bb73.i.i.i.outer
+ br i1 false, label %bb73.i.i.i, label %bb76.i.i.i.preheader
+
+bb76.i.i.i.preheader: ; preds = %bb73.i.i.i
+ br label %bb76.i.i.i
+
+bb76.i.i.i: ; preds = %bb76.i.i.i, %bb76.i.i.i.preheader
+ br i1 false, label %bb77.i.i.i, label %bb76.i.i.i
+
+bb77.i.i.i: ; preds = %bb76.i.i.i
+ br i1 false, label %bb78.i.i.i, label %bb79.i.i.i
+
+bb78.i.i.i: ; preds = %bb77.i.i.i
+ br label %bb73.i.i.i.outer
+
+bb79.i.i.i: ; preds = %bb77.i.i.i
+ br i1 false, label %bb83.i.i.i, label %bb94.i.i.i
+
+bb83.i.i.i: ; preds = %bb79.i.i.i
+ br i1 false, label %bb84.i.i.i, label %bb88.i.i.i
+
+bb84.i.i.i: ; preds = %bb83.i.i.i
+ br i1 false, label %bb87.i.i.i, label %bb85.i.i.i
+
+bb85.i.i.i: ; preds = %bb84.i.i.i
+ br label %bb87.i.i.i
+
+bb87.i.i.i: ; preds = %bb85.i.i.i, %bb84.i.i.i
+ br label %bb88.i.i.i
+
+bb88.i.i.i: ; preds = %bb87.i.i.i, %bb83.i.i.i
+ br i1 false, label %bb89.i.i.i, label %bb93.i.i.i
+
+bb89.i.i.i: ; preds = %bb88.i.i.i
+ br i1 false, label %bb92.i.i.i, label %bb90.i.i.i
+
+bb90.i.i.i: ; preds = %bb89.i.i.i
+ br label %bb92.i.i.i
+
+bb92.i.i.i: ; preds = %bb90.i.i.i, %bb89.i.i.i
+ br label %bb93.i.i.i
+
+bb93.i.i.i: ; preds = %bb92.i.i.i, %bb88.i.i.i
+ br label %bb66.i.i.i.backedge
+
+bb66.i.i.i.backedge: ; preds = %bb97.i.i.i, %bb94.i.i.i, %bb93.i.i.i
+ br label %bb66.i.i.i
+
+bb94.i.i.i: ; preds = %bb79.i.i.i
+ br i1 false, label %bb66.i.i.i.backedge, label %bb96.i.i.i
+
+bb96.i.i.i: ; preds = %bb94.i.i.i
+ br i1 false, label %bb97.i.i.i, label %bb103.i.i.i.preheader.loopexit
+
+bb103.i.i.i.preheader.loopexit: ; preds = %bb96.i.i.i
+ br label %bb103.i.i.i.preheader
+
+bb103.i.i.i.preheader: ; preds = %bb103.i.i.i.preheader.loopexit, %bb65.i.i.i
+ br label %bb103.i.i.i
+
+bb97.i.i.i: ; preds = %bb96.i.i.i
+ br label %bb66.i.i.i.backedge
+
+bb100.i.i.i: ; preds = %bb103.i.i.i
+ br i1 false, label %bb101.i.i.i, label %bb102.i.i.i
+
+bb101.i.i.i: ; preds = %bb100.i.i.i
+ br label %bb102.i.i.i
+
+bb102.i.i.i: ; preds = %bb101.i.i.i, %bb100.i.i.i
+ br label %bb103.i.i.i
+
+bb103.i.i.i: ; preds = %bb102.i.i.i, %bb103.i.i.i.preheader
+ br i1 false, label %bb100.i.i.i, label %bb109.i.i.i.preheader
+
+bb109.i.i.i.preheader: ; preds = %bb103.i.i.i
+ br label %bb109.i.i.i
+
+bb105.i.i.i: ; preds = %bb109.i.i.i
+ br label %bb107.i.i.i
+
+bb106.i.i.i: ; preds = %bb107.i.i.i
+ br label %bb107.i.i.i
+
+bb107.i.i.i: ; preds = %bb106.i.i.i, %bb105.i.i.i
+ br i1 false, label %bb106.i.i.i, label %bb108.i.i.i
+
+bb108.i.i.i: ; preds = %bb107.i.i.i
+ br label %bb109.i.i.i
+
+bb109.i.i.i: ; preds = %bb108.i.i.i, %bb109.i.i.i.preheader
+ br i1 false, label %bb110.i.i.i, label %bb105.i.i.i
+
+bb110.i.i.i: ; preds = %bb109.i.i.i
+ %0 = sub i32 0, %lcollect.i.i.i.2 ; <i32> [#uses=1]
+ %1 = add i32 %0, 1 ; <i32> [#uses=1]
+ br label %bb113.i.i.i
+
+bb111.i.i.i: ; preds = %bb113.i.i.i
+ br i1 false, label %bb114.i.i.i, label %bb113.i.i.i
+
+bb113.i.i.i: ; preds = %bb111.i.i.i, %bb110.i.i.i
+ br i1 false, label %bb111.i.i.i, label %bb114.i.i.i
+
+bb114.i.i.i: ; preds = %bb113.i.i.i, %bb111.i.i.i
+ %2 = lshr i32 %1, 1 ; <i32> [#uses=2]
+ br i1 false, label %bb116.i.i.i, label %bb124.i.i.i
+
+bb116.i.i.i: ; preds = %bb114.i.i.i
+ br i1 false, label %bb117.i.i.i.preheader, label %bb122.i.i.i.preheader
+
+bb122.i.i.i.preheader: ; preds = %bb116.i.i.i
+ br label %bb122.i.i.i
+
+bb117.i.i.i.preheader: ; preds = %bb116.i.i.i
+ br label %bb117.i.i.i
+
+bb117.i.i.i: ; preds = %bb118.i.i.i, %bb117.i.i.i.preheader
+ %target.i.i.i.1 = phi i32 [ %3, %bb118.i.i.i ], [ %2, %bb117.i.i.i.preheader ] ; <i32> [#uses=1]
+ %3 = add i32 %target.i.i.i.1, 1 ; <i32> [#uses=2]
+ br i1 false, label %bb118.i.i.i, label %bb124.i.i.i.loopexit
+
+bb118.i.i.i: ; preds = %bb117.i.i.i
+ br i1 false, label %bb117.i.i.i, label %bb124.i.i.i.loopexit
+
+bb122.i.i.i: ; preds = %bb123.i.i.i, %bb122.i.i.i.preheader
+ %target.i.i.i.2 = phi i32 [ %4, %bb123.i.i.i ], [ %2, %bb122.i.i.i.preheader ] ; <i32> [#uses=2]
+ br i1 false, label %bb124.i.i.i.loopexit1, label %bb123.i.i.i
+
+bb123.i.i.i: ; preds = %bb122.i.i.i
+ %4 = add i32 %target.i.i.i.2, -1 ; <i32> [#uses=1]
+ br i1 false, label %bb122.i.i.i, label %bb124.i.i.i.loopexit1
+
+bb124.i.i.i.loopexit: ; preds = %bb118.i.i.i, %bb117.i.i.i
+ br label %bb124.i.i.i
+
+bb124.i.i.i.loopexit1: ; preds = %bb123.i.i.i, %bb122.i.i.i
+ br label %bb124.i.i.i
+
+bb124.i.i.i: ; preds = %bb124.i.i.i.loopexit1, %bb124.i.i.i.loopexit, %bb114.i.i.i
+ %target.i.i.i.0 = phi i32 [ 0, %bb114.i.i.i ], [ %3, %bb124.i.i.i.loopexit ], [ %target.i.i.i.2, %bb124.i.i.i.loopexit1 ] ; <i32> [#uses=0]
+ br label %bb132.i.i.i.outer
+
+bb125.i.i.i: ; preds = %bb132.i.i.i
+ br i1 false, label %bb132.i.i.i, label %bb130.i.i.i
+
+bb130.i.i.i: ; preds = %bb125.i.i.i
+ br label %bb132.i.i.i.outer
+
+bb132.i.i.i.outer: ; preds = %bb130.i.i.i, %bb124.i.i.i
+ br label %bb132.i.i.i
+
+bb132.i.i.i: ; preds = %bb132.i.i.i.outer, %bb125.i.i.i
+ br i1 false, label %bb125.i.i.i, label %bb133.i.i.i
+
+bb133.i.i.i: ; preds = %bb132.i.i.i
+ br i1 false, label %bb136.i.i.i, label %bb134.i.i.i
+
+bb134.i.i.i: ; preds = %bb133.i.i.i
+ br i1 false, label %bb136.i.i.i, label %bb135.i.i.i
+
+bb135.i.i.i: ; preds = %bb134.i.i.i
+ br label %bb136.i.i.i
+
+bb136.i.i.i: ; preds = %bb135.i.i.i, %bb134.i.i.i, %bb133.i.i.i
+ br i1 false, label %bb137.i.i.i, label %bb37.i.i
+
+bb137.i.i.i: ; preds = %bb136.i.i.i
+ br label %bb37.i.i
+
+bb37.i.i: ; preds = %bb137.i.i.i, %bb136.i.i.i, %bb1.i37.i.i
+ br i1 false, label %bb40.i.i, label %bb38.i.i
+
+bb38.i.i: ; preds = %bb37.i.i
+ br i1 false, label %bb39.i.i, label %bb40.i.i
+
+bb39.i.i: ; preds = %bb38.i.i
+ br i1 false, label %bb17.i.i.i, label %bb3.i12.i.i
+
+bb3.i12.i.i: ; preds = %bb39.i.i
+ br label %bb5.i14.i.i
+
+bb5.i14.i.i: ; preds = %bb8.i.i.i79, %bb3.i12.i.i
+ br i1 false, label %bb6.i15.i.i, label %bb9.i.i.i80
+
+bb6.i15.i.i: ; preds = %bb5.i14.i.i
+ br i1 false, label %bb7.i.i.i78, label %bb9.i.i.i80
+
+bb7.i.i.i78: ; preds = %bb6.i15.i.i
+ br i1 false, label %bb9.i.i.i80, label %bb8.i.i.i79
+
+bb8.i.i.i79: ; preds = %bb7.i.i.i78
+ br i1 false, label %bb9.i.i.i80, label %bb5.i14.i.i
+
+bb9.i.i.i80: ; preds = %bb8.i.i.i79, %bb7.i.i.i78, %bb6.i15.i.i, %bb5.i14.i.i
+ br i1 false, label %bb16.i.i.i, label %bb10.i.i.i81
+
+bb10.i.i.i81: ; preds = %bb9.i.i.i80
+ br i1 false, label %bb11.i.i.i, label %bb15.i.i.i
+
+bb11.i.i.i: ; preds = %bb10.i.i.i81
+ br i1 false, label %bb16.i.i.i, label %bb15.i.i.i
+
+bb15.i.i.i: ; preds = %bb11.i.i.i, %bb10.i.i.i81
+ br label %bb16.i.i.i
+
+bb16.i.i.i: ; preds = %bb15.i.i.i, %bb11.i.i.i, %bb9.i.i.i80
+ br label %bb17.i.i.i
+
+bb17.i.i.i: ; preds = %bb16.i.i.i, %bb39.i.i
+ br i1 false, label %bb18.i.i.i, label %bb25.i.i.i
+
+bb18.i.i.i: ; preds = %bb17.i.i.i
+ br i1 false, label %bb24.i.i.i, label %bb23.i.i.i
+
+bb23.i.i.i: ; preds = %bb18.i.i.i
+ br label %bb24.i.i.i
+
+bb24.i.i.i: ; preds = %bb23.i.i.i, %bb18.i.i.i
+ br label %bb29.i.i.i
+
+bb25.i.i.i: ; preds = %bb17.i.i.i
+ br i1 false, label %bb29.i.i.i, label %bb27.i.i.i
+
+bb27.i.i.i: ; preds = %bb25.i.i.i
+ br i1 false, label %bb29.i.i.i, label %bb28.i.i.i
+
+bb28.i.i.i: ; preds = %bb27.i.i.i
+ br i1 false, label %bb29.i.i.i, label %bb.i4.i.i.i
+
+bb.i4.i.i.i: ; preds = %bb28.i.i.i
+ br i1 false, label %bb4.i.i16.i.i, label %bb29.i.i.i
+
+bb4.i.i16.i.i: ; preds = %bb.i4.i.i.i
+ br label %bb29.i.i.i
+
+bb29.i.i.i: ; preds = %bb4.i.i16.i.i, %bb.i4.i.i.i, %bb28.i.i.i, %bb27.i.i.i, %bb25.i.i.i, %bb24.i.i.i
+ br label %bb40.i.i
+
+bb40.i.i: ; preds = %bb29.i.i.i, %bb38.i.i, %bb37.i.i
+ br i1 false, label %bb9.i.i.i.i.preheader, label %bb2.i.i.i87
+
+bb9.i.i.i.i.preheader: ; preds = %bb40.i.i
+ br label %bb9.i.i.i.i
+
+bb.i.i.i.i84: ; preds = %bb9.i.i.i.i
+ switch i8 0, label %bb8.i.i.i.i [
+ i8 -1, label %bb1.i.i.i.i85
+ i8 1, label %bb9.i.i.i.i
+ ]
+
+bb1.i.i.i.i85: ; preds = %bb.i.i.i.i84
+ br i1 false, label %bb5.i.i.i.i, label %bb2.i.i.i87
+
+bb5.i.i.i.i: ; preds = %bb1.i.i.i.i85
+ br label %bb2.i.i.i87
+
+bb8.i.i.i.i: ; preds = %bb.i.i.i.i84
+ br i1 false, label %bb2.i.i.i87, label %bb6.i.i.i95
+
+bb9.i.i.i.i: ; preds = %bb.i.i.i.i84, %bb9.i.i.i.i.preheader
+ br i1 false, label %bb.i.i.i.i84, label %bb10.i.i.i.i
+
+bb10.i.i.i.i: ; preds = %bb9.i.i.i.i
+ br label %bb2.i.i.i87
+
+bb2.i.i.i87: ; preds = %bb10.i.i.i.i, %bb8.i.i.i.i, %bb5.i.i.i.i, %bb1.i.i.i.i85, %bb40.i.i
+ br i1 false, label %bb3.i.i.i88, label %decide.exit.i.i
+
+bb3.i.i.i88: ; preds = %bb2.i.i.i87
+ br i1 false, label %bb4.i.i.i90, label %bb1.i23.i.i.i
+
+bb1.i23.i.i.i: ; preds = %bb3.i.i.i88
+ br i1 false, label %decide.exit.i.i, label %bb4.i.i.i90
+
+bb4.i.i.i90: ; preds = %bb1.i23.i.i.i, %bb3.i.i.i88
+ br i1 false, label %bb1.i9.i.i.i, label %bb5.i.i.i94
+
+bb1.i9.i.i.i: ; preds = %bb4.i.i.i90
+ br i1 false, label %bb.i.i27.i.i.i.i, label %bb1.i.i28.i.i.i.i
+
+bb.i.i27.i.i.i.i: ; preds = %bb1.i9.i.i.i
+ br label %int2lit.exit32.i.i.i.i
+
+bb1.i.i28.i.i.i.i: ; preds = %bb1.i9.i.i.i
+ br label %int2lit.exit32.i.i.i.i
+
+int2lit.exit32.i.i.i.i: ; preds = %bb1.i.i28.i.i.i.i, %bb.i.i27.i.i.i.i
+ br i1 false, label %bb8.i19.i.i.i, label %bb2.i.i.i.i91
+
+bb2.i.i.i.i91: ; preds = %int2lit.exit32.i.i.i.i
+ br label %bb4.i.i.i.i
+
+bb3.i.i.i.i92: ; preds = %gcd.exit.i.i.i.i
+ br label %bb4.i.i.i.i
+
+bb4.i.i.i.i: ; preds = %bb3.i.i.i.i92, %bb2.i.i.i.i91
+ br label %bb3.i.i13.i.i.i
+
+bb2.i.i12.i.i.i: ; preds = %bb3.i.i13.i.i.i
+ br label %bb3.i.i13.i.i.i
+
+bb3.i.i13.i.i.i: ; preds = %bb2.i.i12.i.i.i, %bb4.i.i.i.i
+ br i1 false, label %gcd.exit.i.i.i.i, label %bb2.i.i12.i.i.i
+
+gcd.exit.i.i.i.i: ; preds = %bb3.i.i13.i.i.i
+ br i1 false, label %bb5.i14.i.i.i.preheader, label %bb3.i.i.i.i92
+
+bb5.i14.i.i.i.preheader: ; preds = %gcd.exit.i.i.i.i
+ br label %bb5.i14.i.i.i
+
+bb5.i14.i.i.i: ; preds = %int2lit.exit.i.i.i.i, %bb5.i14.i.i.i.preheader
+ br i1 false, label %bb.i.i.i17.i.i.i, label %bb1.i.i.i18.i.i.i
+
+bb.i.i.i17.i.i.i: ; preds = %bb5.i14.i.i.i
+ br label %int2lit.exit.i.i.i.i
+
+bb1.i.i.i18.i.i.i: ; preds = %bb5.i14.i.i.i
+ br label %int2lit.exit.i.i.i.i
+
+int2lit.exit.i.i.i.i: ; preds = %bb1.i.i.i18.i.i.i, %bb.i.i.i17.i.i.i
+ br i1 false, label %bb8.i19.i.i.i.loopexit, label %bb5.i14.i.i.i
+
+bb8.i19.i.i.i.loopexit: ; preds = %int2lit.exit.i.i.i.i
+ br label %bb8.i19.i.i.i
+
+bb8.i19.i.i.i: ; preds = %bb8.i19.i.i.i.loopexit, %int2lit.exit32.i.i.i.i
+ br i1 false, label %bb5.i.i.i94, label %bb6.i.i.i95
+
+bb5.i.i.i94: ; preds = %bb8.i19.i.i.i, %bb4.i.i.i90
+ br label %bb.i2.i.i.i
+
+bb.i2.i.i.i: ; preds = %hpop.exit.i.i.i.i, %bb5.i.i.i94
+ br i1 false, label %hpop.exit.i.i.i.i, label %bb1.i.i.i.i.i
+
+bb1.i.i.i.i.i: ; preds = %bb.i2.i.i.i
+ br label %bb2.i.i.i.i.i
+
+bb2.i.i.i.i.i: ; preds = %bb11.i.i.i.i.i, %bb1.i.i.i.i.i
+ br i1 false, label %bb3.i.i.i.i.i, label %bb12.i.i.i.i.i
+
+bb3.i.i.i.i.i: ; preds = %bb2.i.i.i.i.i
+ br i1 false, label %bb4.i.i.i.i.i, label %bb1.i.i.i.i.i.i
+
+bb1.i.i.i.i.i.i: ; preds = %bb3.i.i.i.i.i
+ br i1 false, label %bb8.i.i.i.i.i, label %bb3.i.i.i.i.i.i
+
+bb3.i.i.i.i.i.i: ; preds = %bb1.i.i.i.i.i.i
+ br i1 false, label %bb4.i.i.i.i.i, label %bb8.i.i.i.i.i
+
+bb4.i.i.i.i.i: ; preds = %bb3.i.i.i.i.i.i, %bb3.i.i.i.i.i
+ br i1 false, label %bb5.i.i.i.i.i, label %bb11.i.i.i.i.i
+
+bb5.i.i.i.i.i: ; preds = %bb4.i.i.i.i.i
+ br i1 false, label %bb6.i.i.i.i.i, label %bb1.i21.i.i.i.i.i
+
+bb1.i21.i.i.i.i.i: ; preds = %bb5.i.i.i.i.i
+ br i1 false, label %bb11.i.i.i.i.i, label %bb3.i24.i.i.i.i.i
+
+bb3.i24.i.i.i.i.i: ; preds = %bb1.i21.i.i.i.i.i
+ br i1 false, label %bb6.i.i.i.i.i, label %bb11.i.i.i.i.i
+
+bb6.i.i.i.i.i: ; preds = %bb3.i24.i.i.i.i.i, %bb5.i.i.i.i.i
+ br label %bb11.i.i.i.i.i
+
+bb8.i.i.i.i.i: ; preds = %bb3.i.i.i.i.i.i, %bb1.i.i.i.i.i.i
+ br i1 false, label %bb9.i.i.i.i.i, label %bb12.i.i.i.i.i
+
+bb9.i.i.i.i.i: ; preds = %bb8.i.i.i.i.i
+ br i1 false, label %bb11.i.i.i.i.i, label %bb1.i8.i.i.i.i.i
+
+bb1.i8.i.i.i.i.i: ; preds = %bb9.i.i.i.i.i
+ br i1 false, label %bb12.i.i.i.i.i, label %bb3.i11.i.i.i.i.i
+
+bb3.i11.i.i.i.i.i: ; preds = %bb1.i8.i.i.i.i.i
+ br i1 false, label %bb11.i.i.i.i.i, label %bb12.i.i.i.i.i
+
+bb11.i.i.i.i.i: ; preds = %bb3.i11.i.i.i.i.i, %bb9.i.i.i.i.i, %bb6.i.i.i.i.i, %bb3.i24.i.i.i.i.i, %bb1.i21.i.i.i.i.i, %bb4.i.i.i.i.i
+ br label %bb2.i.i.i.i.i
+
+bb12.i.i.i.i.i: ; preds = %bb3.i11.i.i.i.i.i, %bb1.i8.i.i.i.i.i, %bb8.i.i.i.i.i, %bb2.i.i.i.i.i
+ br label %hpop.exit.i.i.i.i
+
+hpop.exit.i.i.i.i: ; preds = %bb12.i.i.i.i.i, %bb.i2.i.i.i
+ br i1 false, label %sdecide.exit.i.i.i, label %bb.i2.i.i.i
+
+sdecide.exit.i.i.i: ; preds = %hpop.exit.i.i.i.i
+ br label %bb6.i.i.i95
+
+bb6.i.i.i95: ; preds = %sdecide.exit.i.i.i, %bb8.i19.i.i.i, %bb8.i.i.i.i
+ br label %decide.exit.i.i
+
+decide.exit.i.i: ; preds = %bb6.i.i.i95, %bb1.i23.i.i.i, %bb2.i.i.i87
+ br i1 false, label %bb42.i.i, label %sat.exit.i.loopexit.loopexit2
+
+bb42.i.i: ; preds = %decide.exit.i.i
+ br label %bb13.i.i71.outer
+
+sat.exit.i.loopexit.loopexit: ; preds = %bb24.i.i, %bb1.i68.i.i, %incincs.exit.i.i
+ br label %sat.exit.i.loopexit
+
+sat.exit.i.loopexit.loopexit2: ; preds = %decide.exit.i.i, %bb1.i48.i.i, %bb29.i.i
+ br label %sat.exit.i.loopexit
+
+sat.exit.i.loopexit: ; preds = %sat.exit.i.loopexit.loopexit2, %sat.exit.i.loopexit.loopexit
+ br label %sat.exit.i
+
+sat.exit.i: ; preds = %sat.exit.i.loopexit, %bb1.i61.i.i, %bb8.i.i67, %bb1.i.i.i63, %bb3.i.i59
+ br i1 false, label %bb7.i, label %bb2.i96
+
+bb2.i96: ; preds = %sat.exit.i
+ switch i32 0, label %bb5.i99 [
+ i32 10, label %bb4.i98
+ i32 20, label %bb6.i100
+ ]
+
+bb4.i98: ; preds = %bb2.i96
+ br label %bb6.i100
+
+bb5.i99: ; preds = %bb2.i96
+ br label %bb6.i100
+
+bb6.i100: ; preds = %bb5.i99, %bb4.i98, %bb2.i96
+ br label %bb7.i
+
+bb7.i: ; preds = %bb6.i100, %sat.exit.i
+ br i1 false, label %bb.i1.i, label %picosat_sat.exit
+
+bb.i1.i: ; preds = %bb7.i
+ br label %picosat_sat.exit
+
+picosat_sat.exit: ; preds = %bb.i1.i, %bb7.i
+ switch i32 0, label %bb166 [
+ i32 20, label %bb150
+ i32 10, label %bb163
+ ]
+
+bb150: ; preds = %picosat_sat.exit
+ br i1 false, label %bb152, label %bb151
+
+bb151: ; preds = %bb150
+ br label %bb152
+
+bb152: ; preds = %bb151, %bb150
+ br i1 false, label %bb154, label %bb153
+
+bb153: ; preds = %bb152
+ br label %bb154
+
+bb154: ; preds = %bb153, %bb152
+ br i1 false, label %bb157, label %bb156
+
+bb156: ; preds = %bb154
+ br label %bb157
+
+bb157: ; preds = %bb156, %bb154
+ br i1 false, label %bb159, label %bb158
+
+bb158: ; preds = %bb157
+ br label %bb159
+
+bb159: ; preds = %bb158, %bb157
+ br i1 false, label %bb167, label %bb160
+
+bb160: ; preds = %bb159
+ br label %bb167
+
+bb163: ; preds = %picosat_sat.exit
+ br i1 false, label %bb167, label %bb164
+
+bb164: ; preds = %bb163
+ br label %bb4.i
+
+bb.i11: ; preds = %bb4.i
+ br i1 false, label %bb.i.i12, label %bb1.i.i14
+
+bb.i.i12: ; preds = %bb.i11
+ unreachable
+
+bb1.i.i14: ; preds = %bb.i11
+ br i1 false, label %bb3.i.i16, label %bb2.i.i15
+
+bb2.i.i15: ; preds = %bb1.i.i14
+ unreachable
+
+bb3.i.i16: ; preds = %bb1.i.i14
+ br i1 false, label %bb3.i, label %bb7.i.i
+
+bb7.i.i: ; preds = %bb3.i.i16
+ br i1 false, label %bb.i.i.i.i17, label %bb1.i.i.i.i18
+
+bb.i.i.i.i17: ; preds = %bb7.i.i
+ br label %int2lit.exit.i.i
+
+bb1.i.i.i.i18: ; preds = %bb7.i.i
+ br label %int2lit.exit.i.i
+
+int2lit.exit.i.i: ; preds = %bb1.i.i.i.i18, %bb.i.i.i.i17
+ br i1 false, label %bb3.i, label %bb9.i.i
+
+bb9.i.i: ; preds = %int2lit.exit.i.i
+ br label %bb3.i
+
+bb3.i: ; preds = %bb9.i.i, %int2lit.exit.i.i, %bb3.i.i16
+ br label %bb4.i
+
+bb4.i: ; preds = %bb3.i, %bb164
+ br i1 false, label %bb5.i, label %bb.i11
+
+bb5.i: ; preds = %bb4.i
+ br i1 false, label %bb6.i, label %bb167
+
+bb6.i: ; preds = %bb5.i
+ br label %bb167
+
+bb166: ; preds = %picosat_sat.exit
+ br label %bb167
+
+bb167: ; preds = %bb166, %bb6.i, %bb5.i, %bb163, %bb160, %bb159, %picosat_print.exit
+ br i1 false, label %bb168, label %bb170
+
+bb168: ; preds = %bb167
+ br i1 false, label %bb170, label %bb169
+
+bb169: ; preds = %bb168
+ br i1 false, label %bb.i7, label %picosat_time_stamp.exit9
+
+bb.i7: ; preds = %bb169
+ br label %picosat_time_stamp.exit9
+
+picosat_time_stamp.exit9: ; preds = %bb.i7, %bb169
+ br label %bb170
+
+bb170: ; preds = %picosat_time_stamp.exit9, %bb168, %bb167, %bb129
+ br i1 false, label %bb.i.i3, label %picosat_leave.exit
+
+bb.i.i3: ; preds = %bb170
+ br label %picosat_leave.exit
+
+picosat_leave.exit: ; preds = %bb.i.i3, %bb170
+ br i1 false, label %bb1.i.i, label %bb.i.i
+
+bb.i.i: ; preds = %picosat_leave.exit
+ unreachable
+
+bb1.i.i: ; preds = %picosat_leave.exit
+ br label %bb9.i.i.i
+
+bb3.i.i.i: ; preds = %bb9.i.i.i
+ br i1 false, label %bb5.i.i.i, label %bb4.i.i.i
+
+bb4.i.i.i: ; preds = %bb3.i.i.i
+ br label %bb5.i.i.i
+
+bb5.i.i.i: ; preds = %bb4.i.i.i, %bb3.i.i.i
+ br label %bb9.i.i.i
+
+bb9.i.i.i: ; preds = %bb5.i.i.i, %bb1.i.i
+ br i1 false, label %bb10.i.i.i, label %bb3.i.i.i
+
+bb10.i.i.i: ; preds = %bb9.i.i.i
+ br i1 false, label %delete.exit.i.i.i, label %bb1.i.i.i.i
+
+bb1.i.i.i.i: ; preds = %bb10.i.i.i
+ br label %delete.exit.i.i.i
+
+delete.exit.i.i.i: ; preds = %bb1.i.i.i.i, %bb10.i.i.i
+ br i1 false, label %delete_clauses.exit.i.i, label %bb1.i7.i.i.i
+
+bb1.i7.i.i.i: ; preds = %delete.exit.i.i.i
+ br label %delete_clauses.exit.i.i
+
+delete_clauses.exit.i.i: ; preds = %bb1.i7.i.i.i, %delete.exit.i.i.i
+ br label %bb3.i.i
+
+bb2.i.i: ; preds = %bb3.i.i
+ br i1 false, label %lrelease.exit.i.i, label %bb1.i.i23.i.i
+
+bb1.i.i23.i.i: ; preds = %bb2.i.i
+ br label %lrelease.exit.i.i
+
+lrelease.exit.i.i: ; preds = %bb1.i.i23.i.i, %bb2.i.i
+ br label %bb3.i.i
+
+bb3.i.i: ; preds = %lrelease.exit.i.i, %delete_clauses.exit.i.i
+ br i1 false, label %bb4.i.i, label %bb2.i.i
+
+bb4.i.i: ; preds = %bb3.i.i
+ br i1 false, label %delete.exit214.i.i, label %bb1.i208.i.i
+
+bb1.i208.i.i: ; preds = %bb4.i.i
+ br label %delete.exit214.i.i
+
+delete.exit214.i.i: ; preds = %bb1.i208.i.i, %bb4.i.i
+ br i1 false, label %delete.exit203.i.i, label %bb1.i197.i.i
+
+bb1.i197.i.i: ; preds = %delete.exit214.i.i
+ br label %delete.exit203.i.i
+
+delete.exit203.i.i: ; preds = %bb1.i197.i.i, %delete.exit214.i.i
+ br i1 false, label %delete.exit192.i.i, label %bb1.i186.i.i
+
+bb1.i186.i.i: ; preds = %delete.exit203.i.i
+ br label %delete.exit192.i.i
+
+delete.exit192.i.i: ; preds = %bb1.i186.i.i, %delete.exit203.i.i
+ br i1 false, label %delete.exit181.i.i, label %bb1.i175.i.i
+
+bb1.i175.i.i: ; preds = %delete.exit192.i.i
+ br label %delete.exit181.i.i
+
+delete.exit181.i.i: ; preds = %bb1.i175.i.i, %delete.exit192.i.i
+ br i1 false, label %delete.exit170.i.i, label %bb1.i164.i.i
+
+bb1.i164.i.i: ; preds = %delete.exit181.i.i
+ br label %delete.exit170.i.i
+
+delete.exit170.i.i: ; preds = %bb1.i164.i.i, %delete.exit181.i.i
+ br i1 false, label %delete.exit159.i.i, label %bb1.i153.i.i
+
+bb1.i153.i.i: ; preds = %delete.exit170.i.i
+ br label %delete.exit159.i.i
+
+delete.exit159.i.i: ; preds = %bb1.i153.i.i, %delete.exit170.i.i
+ br i1 false, label %delete.exit148.i.i, label %bb1.i142.i.i
+
+bb1.i142.i.i: ; preds = %delete.exit159.i.i
+ br label %delete.exit148.i.i
+
+delete.exit148.i.i: ; preds = %bb1.i142.i.i, %delete.exit159.i.i
+ br i1 false, label %delete.exit137.i.i, label %bb1.i131.i.i
+
+bb1.i131.i.i: ; preds = %delete.exit148.i.i
+ br label %delete.exit137.i.i
+
+delete.exit137.i.i: ; preds = %bb1.i131.i.i, %delete.exit148.i.i
+ br i1 false, label %delete.exit126.i.i, label %bb1.i120.i.i
+
+bb1.i120.i.i: ; preds = %delete.exit137.i.i
+ br label %delete.exit126.i.i
+
+delete.exit126.i.i: ; preds = %bb1.i120.i.i, %delete.exit137.i.i
+ br i1 false, label %delete.exit115.i.i, label %bb1.i109.i.i
+
+bb1.i109.i.i: ; preds = %delete.exit126.i.i
+ br label %delete.exit115.i.i
+
+delete.exit115.i.i: ; preds = %bb1.i109.i.i, %delete.exit126.i.i
+ br i1 false, label %delete.exit104.i.i, label %bb1.i98.i.i
+
+bb1.i98.i.i: ; preds = %delete.exit115.i.i
+ br label %delete.exit104.i.i
+
+delete.exit104.i.i: ; preds = %bb1.i98.i.i, %delete.exit115.i.i
+ br i1 false, label %delete.exit93.i.i, label %bb1.i87.i.i
+
+bb1.i87.i.i: ; preds = %delete.exit104.i.i
+ br label %delete.exit93.i.i
+
+delete.exit93.i.i: ; preds = %bb1.i87.i.i, %delete.exit104.i.i
+ br i1 false, label %delete.exit82.i.i, label %bb1.i76.i.i
+
+bb1.i76.i.i: ; preds = %delete.exit93.i.i
+ br label %delete.exit82.i.i
+
+delete.exit82.i.i: ; preds = %bb1.i76.i.i, %delete.exit93.i.i
+ br i1 false, label %delete.exit71.i.i, label %bb1.i65.i.i
+
+bb1.i65.i.i: ; preds = %delete.exit82.i.i
+ br label %delete.exit71.i.i
+
+delete.exit71.i.i: ; preds = %bb1.i65.i.i, %delete.exit82.i.i
+ br i1 false, label %delete.exit60.i.i, label %bb1.i54.i.i
+
+bb1.i54.i.i: ; preds = %delete.exit71.i.i
+ br label %delete.exit60.i.i
+
+delete.exit60.i.i: ; preds = %bb1.i54.i.i, %delete.exit71.i.i
+ br i1 false, label %delete.exit38.i.i, label %bb1.i32.i.i
+
+bb1.i32.i.i: ; preds = %delete.exit60.i.i
+ br label %delete.exit38.i.i
+
+delete.exit38.i.i: ; preds = %bb1.i32.i.i, %delete.exit60.i.i
+ br i1 false, label %delete.exit18.i.i, label %bb1.i12.i.i
+
+bb1.i12.i.i: ; preds = %delete.exit38.i.i
+ br label %delete.exit18.i.i
+
+delete.exit18.i.i: ; preds = %bb1.i12.i.i, %delete.exit38.i.i
+ br i1 false, label %picosat_reset.exit, label %bb1.i2.i.i
+
+bb1.i2.i.i: ; preds = %delete.exit18.i.i
+ br label %picosat_reset.exit
+
+picosat_reset.exit: ; preds = %bb1.i2.i.i, %delete.exit18.i.i
+ br label %bb171
+
+bb171: ; preds = %picosat_reset.exit, %bb110
+ br i1 false, label %bb173, label %bb172
+
+bb172: ; preds = %bb171
+ br label %bb173
+
+bb173: ; preds = %bb172, %bb171
+ br i1 false, label %bb175, label %bb174
+
+bb174: ; preds = %bb173
+ br label %bb175
+
+bb175: ; preds = %bb174, %bb173
+ br i1 false, label %bb177, label %bb176
+
+bb176: ; preds = %bb175
+ br label %bb177
+
+bb177: ; preds = %bb176, %bb175
+ br i1 false, label %bb179, label %bb178
+
+bb178: ; preds = %bb177
+ ret i32 0
+
+bb179: ; preds = %bb177
+ ret i32 0
+}
+
+define i32 @main(i32 %argc, i8** %argv) nounwind {
+entry:
+ br label %bb2
+
+bb: ; preds = %bb2
+ br i1 false, label %bb3, label %bb2
+
+bb2: ; preds = %bb, %entry
+ br i1 false, label %bb5.loopexit, label %bb
+
+bb3: ; preds = %bb
+ br i1 false, label %bb5, label %bb4
+
+bb4: ; preds = %bb3
+ br label %bb5
+
+bb5.loopexit: ; preds = %bb2
+ br label %bb5
+
+bb5: ; preds = %bb5.loopexit, %bb4, %bb3
+ %0 = call fastcc i32 @picosat_main(i32 %argc, i8** %argv) nounwind ; <i32> [#uses=2]
+ br i1 false, label %bb7, label %bb6
+
+bb6: ; preds = %bb5
+ ret i32 %0
+
+bb7: ; preds = %bb5
+ ret i32 %0
+}
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/pr32917.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/pr32917.ll
new file mode 100644
index 000000000000..fcf1ac0478be
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/pr32917.ll
@@ -0,0 +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=3 < %s | FileCheck %s
+; PR 32917
+
+ at b = common local_unnamed_addr global i32 0, align 4
+ at 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 [[TMP3]])
+; CHECK-NEXT: ret i32 undef
+;
+ %1 = load i32, i32* @b, align 4
+ %2 = sext i32 %1 to i64
+ %3 = inttoptr i64 %2 to i32*
+ call fastcc void @fn1(i32* %3)
+ ret i32 undef
+}
+
+define internal fastcc void @fn1(i32* nocapture readonly) unnamed_addr {
+; CHECK-LABEL: define {{[^@]+}}@fn1
+; CHECK-SAME: (i32* nocapture nofree nonnull readonly align 4 [[TMP0:%.*]]) unnamed_addr
+; CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds i32, i32* [[TMP0]], i64 -1
+; CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* [[TMP2]], align 4
+; CHECK-NEXT: store i32 [[TMP3]], i32* @a, align 4
+; CHECK-NEXT: ret void
+;
+ %2 = getelementptr inbounds i32, i32* %0, i64 -1
+ %3 = load i32, i32* %2, align 4
+ store i32 %3, i32* @a, align 4
+ ret void
+}
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/pr33641_remove_arg_dbgvalue.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/pr33641_remove_arg_dbgvalue.ll
new file mode 100644
index 000000000000..de67b8970c23
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/pr33641_remove_arg_dbgvalue.ll
@@ -0,0 +1,45 @@
+; 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
+
+; Fix for PR33641. ArgumentPromotion removed the argument to bar but left the call to
+; dbg.value which still used the removed argument.
+
+; The %p argument should be removed, and the use of it in dbg.value should be
+; changed to undef.
+
+%p_t = type i16*
+%fun_t = type void (%p_t)*
+
+define void @foo() {
+; CHECK-LABEL: define {{[^@]+}}@foo()
+; CHECK-NEXT: [[TMP:%.*]] = alloca void (i16*)*
+; CHECK-NEXT: store void (i16*)* @bar, void (i16*)** [[TMP]], align 8
+; CHECK-NEXT: ret void
+;
+ %tmp = alloca %fun_t
+ store %fun_t @bar, %fun_t* %tmp
+ ret void
+}
+
+define internal void @bar(%p_t %p) {
+; CHECK-LABEL: define {{[^@]+}}@bar
+; CHECK-SAME: (i16* nocapture nofree readnone [[P:%.*]])
+; CHECK-NEXT: call void @llvm.dbg.value(metadata i16* [[P]], metadata !3, metadata !DIExpression()) #3, !dbg !5
+; CHECK-NEXT: ret void
+;
+ call void @llvm.dbg.value(metadata %p_t %p, metadata !4, metadata !5), !dbg !6
+ ret void
+}
+
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1)
+!1 = !DIFile(filename: "test.c", directory: "")
+!2 = !{i32 2, !"Debug Info Version", i32 3}
+!3 = distinct !DISubprogram(name: "bar", unit: !0)
+!4 = !DILocalVariable(name: "p", scope: !3)
+!5 = !DIExpression()
+!6 = !DILocation(line: 1, column: 1, scope: !3)
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/profile.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/profile.ll
new file mode 100644
index 000000000000..c40b4c475b9d
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/profile.ll
@@ -0,0 +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
+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: call void @promote_i32_ptr(i32* noalias nocapture nonnull align 4 dereferenceable(4) [[X]]), !prof !0
+; CHECK-NEXT: ret void
+;
+ %x = alloca i32
+ store i32 42, i32* %x
+ call void @promote_i32_ptr(i32* %x), !prof !0
+ ret void
+}
+
+define internal void @promote_i32_ptr(i32* %xp) {
+; CHECK-LABEL: define {{[^@]+}}@promote_i32_ptr
+; CHECK-SAME: (i32* noalias nocapture nonnull readonly align 4 dereferenceable(4) [[XP:%.*]])
+; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[XP]], align 4
+; CHECK-NEXT: call void @use_i32(i32 [[X]])
+; CHECK-NEXT: ret void
+;
+ %x = load i32, i32* %xp
+ call void @use_i32(i32 %x)
+ ret void
+}
+
+declare void @use_i32(i32)
+
+!0 = !{!"branch_weights", i32 30}
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/reserve-tbaa.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/reserve-tbaa.ll
new file mode 100644
index 000000000000..093dcb4932fc
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/reserve-tbaa.ll
@@ -0,0 +1,65 @@
+; 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
+
+; PR17906
+; When we promote two arguments in a single function with
diff erent types,
+; before the fix, we used the same tag for the newly-created two loads.
+; This testing case makes sure that we correctly transfer the tbaa tags from the
+; original loads to the newly-created loads when promoting pointer arguments.
+
+ at a = global i32* null, align 8
+ at e = global i32** @a, align 8
+ at g = global i32 0, align 4
+ at c = global i64 0, align 8
+ at 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:%.*]], i64* nocapture nofree nonnull readonly align 8 dereferenceable(8) [[P2:%.*]])
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* @c, align 8, !tbaa !0
+; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[TMP0]] to i32
+; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @g, align 4, !tbaa !4
+; CHECK-NEXT: [[CONV1:%.*]] = trunc i32 [[TMP1]] to i8
+; CHECK-NEXT: store i8 [[CONV1]], i8* @d, align 1, !tbaa !6
+; CHECK-NEXT: ret void
+;
+entry:
+ %0 = load i64, i64* %p2, align 8, !tbaa !1
+ %conv = trunc i64 %0 to i32
+ %1 = load i32, i32* %p1, align 4, !tbaa !5
+ %conv1 = trunc i32 %1 to i8
+ store i8 %conv1, i8* @d, align 1, !tbaa !7
+ ret void
+}
+
+define i32 @main() {
+; CHECK-LABEL: define {{[^@]+}}@main()
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[TMP0:%.*]] = load i32**, i32*** @e, align 8, !tbaa !7
+; CHECK-NEXT: store i32* @g, i32** [[TMP0]], align 8, !tbaa !7
+; CHECK-NEXT: [[TMP1:%.*]] = load i32*, i32** @a, align 8, !tbaa !7
+; CHECK-NEXT: store i32 1, i32* [[TMP1]], align 4, !tbaa !4
+; CHECK-NEXT: call fastcc void @fn(i32* nofree nonnull align 4 dereferenceable(4) @g, i64* nofree nonnull align 8 dereferenceable(8) undef)
+; CHECK-NEXT: ret i32 0
+;
+entry:
+ %0 = load i32**, i32*** @e, align 8, !tbaa !8
+ store i32* @g, i32** %0, align 8, !tbaa !8
+ %1 = load i32*, i32** @a, align 8, !tbaa !8
+ store i32 1, i32* %1, align 4, !tbaa !5
+ call fastcc void @fn(i32* @g, i64* @c)
+
+ ret i32 0
+}
+
+!1 = !{!2, !2, i64 0}
+!2 = !{!"long", !3, i64 0}
+!3 = !{!"omnipotent char", !4, i64 0}
+!4 = !{!"Simple C/C++ TBAA"}
+!5 = !{!6, !6, i64 0}
+!6 = !{!"int", !3, i64 0}
+!7 = !{!3, !3, i64 0}
+!8 = !{!9, !9, i64 0}
+!9 = !{!"any pointer", !3, i64 0}
+
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/sret.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/sret.ll
new file mode 100644
index 000000000000..d98fcd42de16
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/sret.ll
@@ -0,0 +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=2 < %s | FileCheck %s
+
+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
+;
+ %ap = getelementptr {i32, i32}, {i32, i32}* %this, i32 0, i32 0
+ %bp = getelementptr {i32, i32}, {i32, i32}* %this, i32 0, i32 1
+ %a = load i32, i32* %ap
+ %b = load i32, i32* %bp
+ %ab = add i32 %a, %b
+ store i32 %ab, i32* %r
+ ret void
+}
+
+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 align 8 dereferenceable(8) [[PAIR]], i32* noalias nocapture nofree nonnull sret align 4 dereferenceable(4) [[R]])
+; CHECK-NEXT: ret void
+;
+ %r = alloca i32
+ %pair = alloca {i32, i32}
+
+ call void @add({i32, i32}* %pair, i32* sret %r)
+ ret void
+}
diff --git a/llvm/test/Transforms/Attributor/ArgumentPromotion/tail.ll b/llvm/test/Transforms/Attributor/ArgumentPromotion/tail.ll
new file mode 100644
index 000000000000..2a34bde6636b
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/tail.ll
@@ -0,0 +1,29 @@
+; 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
+; PR14710
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+
+%pair = type { i32, i32 }
+
+declare i8* @foo(%pair*)
+
+define internal void @bar(%pair* byval %Data) {
+; CHECK-LABEL: define {{[^@]+}}@bar
+; CHECK-SAME: (%pair* byval [[DATA:%.*]])
+; CHECK-NEXT: [[TMP1:%.*]] = tail call i8* @foo(%pair* [[DATA]])
+; CHECK-NEXT: ret void
+;
+ tail call i8* @foo(%pair* %Data)
+ ret void
+}
+
+define void @zed(%pair* byval %Data) {
+; CHECK-LABEL: define {{[^@]+}}@zed
+; CHECK-SAME: (%pair* nocapture readonly byval [[DATA:%.*]])
+; CHECK-NEXT: call void @bar(%pair* nocapture readonly byval [[DATA]])
+; CHECK-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
new file mode 100644
index 000000000000..97e634a97fc6
--- /dev/null
+++ b/llvm/test/Transforms/Attributor/ArgumentPromotion/variadic.ll
@@ -0,0 +1,38 @@
+; 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
+
+; Unused arguments from variadic functions cannot be eliminated as that changes
+; their classiciation according to the SysV amd64 ABI. Clang and other frontends
+; bake in the classification when they use things like byval, as in this test.
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%struct.tt0 = type { i64, i64 }
+%struct.__va_list_tag = type { i32, i32, i8*, i8* }
+
+ at t45 = internal global %struct.tt0 { i64 1335139741, i64 438042995 }, align 8
+
+; Function Attrs: nounwind uwtable
+define i32 @main(i32 %argc, i8** nocapture readnone %argv) #0 {
+; CHECK-LABEL: define {{[^@]+}}@main
+; CHECK-SAME: (i32 [[ARGC:%.*]], i8** nocapture nofree readnone [[ARGV:%.*]])
+; CHECK-NEXT: entry:
+; CHECK-NEXT: tail call void (i8*, i8*, i8*, i8*, i8*, ...) @callee_t0f(i8* undef, i8* undef, i8* undef, i8* undef, i8* undef, %struct.tt0* byval align 8 @t45)
+; CHECK-NEXT: ret i32 0
+;
+entry:
+ tail call void (i8*, i8*, i8*, i8*, i8*, ...) @callee_t0f(i8* undef, i8* undef, i8* undef, i8* undef, i8* undef, %struct.tt0* byval align 8 @t45)
+ ret i32 0
+}
+
+; 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* 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:%.*]], ...)
+; CHECK-NEXT: entry:
+; CHECK-NEXT: ret void
+;
+entry:
+ ret void
+}
More information about the llvm-commits
mailing list