[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