xref: /llvm-project/llvm/test/Transforms/Util/assume-builder.ll (revision dd599e92a6e5a1abc55ac694799102410c0d18c0)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
2; RUN: opt -passes='assume-builder,verify' --enable-knowledge-retention -S %s | FileCheck %s --check-prefixes=BASIC
3; RUN: opt -passes='assume-builder,verify' --enable-knowledge-retention --assume-preserve-all -S %s | FileCheck %s --check-prefixes=ALL
4; RUN: opt -passes='require<assumptions>,assume-builder,verify' --enable-knowledge-retention -S %s | FileCheck %s --check-prefixes=WITH-AC
5; RUN: opt -passes='require<domtree>,require<assumptions>,assume-builder,verify' --enable-knowledge-retention -S %s | FileCheck %s --check-prefixes=CROSS-BLOCK
6; RUN: opt -passes='assume-builder,require<domtree>,require<assumptions>,assume-simplify,verify' --enable-knowledge-retention -S %s | FileCheck %s --check-prefixes=FULL-SIMPLIFY
7
8target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
9
10%struct.S = type { i32, i8, ptr }
11%struct.A = type { ptr, ptr, [4 x [4 x %struct.D]], i64 }
12%struct.D = type { i64, i64 }
13
14declare void @func(ptr, ptr)
15declare void @func_cold(ptr) #0
16declare void @func_strbool(ptr) #1
17declare void @func_many(ptr) #2
18declare void @func_argattr(ptr align 8, ptr nonnull) #3
19declare void @func_argattr2(ptr noundef align 8, ptr noundef nonnull) #3
20
21declare void @may_throw()
22
23define void @test(ptr %P, ptr %P1, ptr %P2, ptr %P3) {
24; BASIC-LABEL: define {{[^@]+}}@test
25; BASIC-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]], ptr [[P3:%.*]]) {
26; BASIC-NEXT:  bb:
27; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P]]), "dereferenceable"(ptr [[P]], i64 16) ]
28; BASIC-NEXT:    call void @func(ptr nonnull dereferenceable(16) [[P]], ptr null)
29; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 12) ]
30; BASIC-NEXT:    call void @func(ptr dereferenceable(12) [[P1]], ptr nonnull [[P]])
31; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "cold"() ]
32; BASIC-NEXT:    call void @func_cold(ptr dereferenceable(12) [[P1]]) #[[ATTR6:[0-9]+]]
33; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "cold"() ]
34; BASIC-NEXT:    call void @func_cold(ptr dereferenceable(12) [[P1]])
35; BASIC-NEXT:    call void @func(ptr [[P1]], ptr [[P]])
36; BASIC-NEXT:    call void @func_strbool(ptr [[P1]])
37; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 32) ]
38; BASIC-NEXT:    call void @func(ptr dereferenceable(32) [[P]], ptr dereferenceable(8) [[P]])
39; BASIC-NEXT:    call void @func_many(ptr align 8 [[P1]])
40; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ]
41; BASIC-NEXT:    call void @func_many(ptr noundef align 8 [[P1]])
42; BASIC-NEXT:    call void @func_argattr(ptr [[P2]], ptr [[P3]])
43; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(ptr [[P2]]), "align"(ptr [[P2]], i64 8), "noundef"(ptr [[P3]]), "nonnull"(ptr [[P3]]) ]
44; BASIC-NEXT:    call void @func_argattr2(ptr [[P2]], ptr [[P3]])
45; BASIC-NEXT:    call void @func(ptr nonnull [[P1]], ptr nonnull [[P]])
46; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P1]]), "noundef"(ptr [[P]]) ]
47; BASIC-NEXT:    call void @func(ptr noundef nonnull [[P1]], ptr noundef nonnull [[P]])
48; BASIC-NEXT:    ret void
49;
50; ALL-LABEL: define {{[^@]+}}@test
51; ALL-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]], ptr [[P3:%.*]]) {
52; ALL-NEXT:  bb:
53; ALL-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P]]), "dereferenceable"(ptr [[P]], i64 16) ]
54; ALL-NEXT:    call void @func(ptr nonnull dereferenceable(16) [[P]], ptr null)
55; ALL-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 12) ]
56; ALL-NEXT:    call void @func(ptr dereferenceable(12) [[P1]], ptr nonnull [[P]])
57; ALL-NEXT:    call void @llvm.assume(i1 true) [ "cold"(), "nounwind"(), "willreturn"() ]
58; ALL-NEXT:    call void @func_cold(ptr dereferenceable(12) [[P1]]) #[[ATTR6:[0-9]+]]
59; ALL-NEXT:    call void @llvm.assume(i1 true) [ "cold"(), "nounwind"(), "willreturn"() ]
60; ALL-NEXT:    call void @func_cold(ptr dereferenceable(12) [[P1]])
61; ALL-NEXT:    call void @func(ptr [[P1]], ptr [[P]])
62; ALL-NEXT:    call void @func_strbool(ptr [[P1]])
63; ALL-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 32) ]
64; ALL-NEXT:    call void @func(ptr dereferenceable(32) [[P]], ptr dereferenceable(8) [[P]])
65; ALL-NEXT:    call void @llvm.assume(i1 true) [ "norecurse"(), "nounwind"(), "willreturn"() ]
66; ALL-NEXT:    call void @func_many(ptr align 8 [[P1]])
67; ALL-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(ptr [[P1]]), "align"(ptr [[P1]], i64 8), "norecurse"(), "nounwind"(), "willreturn"() ]
68; ALL-NEXT:    call void @func_many(ptr noundef align 8 [[P1]])
69; ALL-NEXT:    call void @llvm.assume(i1 true) [ "nounwind"() ]
70; ALL-NEXT:    call void @func_argattr(ptr [[P2]], ptr [[P3]])
71; ALL-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(ptr [[P2]]), "align"(ptr [[P2]], i64 8), "noundef"(ptr [[P3]]), "nonnull"(ptr [[P3]]), "nounwind"() ]
72; ALL-NEXT:    call void @func_argattr2(ptr [[P2]], ptr [[P3]])
73; ALL-NEXT:    call void @func(ptr nonnull [[P1]], ptr nonnull [[P]])
74; ALL-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P1]]), "noundef"(ptr [[P]]) ]
75; ALL-NEXT:    call void @func(ptr noundef nonnull [[P1]], ptr noundef nonnull [[P]])
76; ALL-NEXT:    ret void
77;
78; WITH-AC-LABEL: define {{[^@]+}}@test
79; WITH-AC-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]], ptr [[P3:%.*]]) {
80; WITH-AC-NEXT:  bb:
81; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P]]), "dereferenceable"(ptr [[P]], i64 16) ]
82; WITH-AC-NEXT:    call void @func(ptr nonnull dereferenceable(16) [[P]], ptr null)
83; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 12) ]
84; WITH-AC-NEXT:    call void @func(ptr dereferenceable(12) [[P1]], ptr nonnull [[P]])
85; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "cold"() ]
86; WITH-AC-NEXT:    call void @func_cold(ptr dereferenceable(12) [[P1]]) #[[ATTR6:[0-9]+]]
87; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "cold"() ]
88; WITH-AC-NEXT:    call void @func_cold(ptr dereferenceable(12) [[P1]])
89; WITH-AC-NEXT:    call void @func(ptr [[P1]], ptr [[P]])
90; WITH-AC-NEXT:    call void @func_strbool(ptr [[P1]])
91; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 32) ]
92; WITH-AC-NEXT:    call void @func(ptr dereferenceable(32) [[P]], ptr dereferenceable(8) [[P]])
93; WITH-AC-NEXT:    call void @func_many(ptr align 8 [[P1]])
94; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ]
95; WITH-AC-NEXT:    call void @func_many(ptr noundef align 8 [[P1]])
96; WITH-AC-NEXT:    call void @func_argattr(ptr [[P2]], ptr [[P3]])
97; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(ptr [[P2]]), "align"(ptr [[P2]], i64 8), "noundef"(ptr [[P3]]), "nonnull"(ptr [[P3]]) ]
98; WITH-AC-NEXT:    call void @func_argattr2(ptr [[P2]], ptr [[P3]])
99; WITH-AC-NEXT:    call void @func(ptr nonnull [[P1]], ptr nonnull [[P]])
100; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P1]]), "noundef"(ptr [[P]]) ]
101; WITH-AC-NEXT:    call void @func(ptr noundef nonnull [[P1]], ptr noundef nonnull [[P]])
102; WITH-AC-NEXT:    ret void
103;
104; CROSS-BLOCK-LABEL: define {{[^@]+}}@test
105; CROSS-BLOCK-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]], ptr [[P3:%.*]]) {
106; CROSS-BLOCK-NEXT:  bb:
107; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P]]), "dereferenceable"(ptr [[P]], i64 16) ]
108; CROSS-BLOCK-NEXT:    call void @func(ptr nonnull dereferenceable(16) [[P]], ptr null)
109; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 12) ]
110; CROSS-BLOCK-NEXT:    call void @func(ptr dereferenceable(12) [[P1]], ptr nonnull [[P]])
111; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "cold"() ]
112; CROSS-BLOCK-NEXT:    call void @func_cold(ptr dereferenceable(12) [[P1]]) #[[ATTR6:[0-9]+]]
113; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "cold"() ]
114; CROSS-BLOCK-NEXT:    call void @func_cold(ptr dereferenceable(12) [[P1]])
115; CROSS-BLOCK-NEXT:    call void @func(ptr [[P1]], ptr [[P]])
116; CROSS-BLOCK-NEXT:    call void @func_strbool(ptr [[P1]])
117; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 32) ]
118; CROSS-BLOCK-NEXT:    call void @func(ptr dereferenceable(32) [[P]], ptr dereferenceable(8) [[P]])
119; CROSS-BLOCK-NEXT:    call void @func_many(ptr align 8 [[P1]])
120; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ]
121; CROSS-BLOCK-NEXT:    call void @func_many(ptr noundef align 8 [[P1]])
122; CROSS-BLOCK-NEXT:    call void @func_argattr(ptr [[P2]], ptr [[P3]])
123; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(ptr [[P2]]), "align"(ptr [[P2]], i64 8), "noundef"(ptr [[P3]]), "nonnull"(ptr [[P3]]) ]
124; CROSS-BLOCK-NEXT:    call void @func_argattr2(ptr [[P2]], ptr [[P3]])
125; CROSS-BLOCK-NEXT:    call void @func(ptr nonnull [[P1]], ptr nonnull [[P]])
126; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P1]]), "noundef"(ptr [[P]]) ]
127; CROSS-BLOCK-NEXT:    call void @func(ptr noundef nonnull [[P1]], ptr noundef nonnull [[P]])
128; CROSS-BLOCK-NEXT:    ret void
129;
130; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test
131; FULL-SIMPLIFY-SAME: (ptr nonnull dereferenceable(16) [[P:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]], ptr [[P3:%.*]]) {
132; FULL-SIMPLIFY-NEXT:  bb:
133; FULL-SIMPLIFY-NEXT:    call void @func(ptr nonnull dereferenceable(16) [[P]], ptr null)
134; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 12) ]
135; FULL-SIMPLIFY-NEXT:    call void @func(ptr dereferenceable(12) [[P1]], ptr nonnull [[P]])
136; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "cold"() ]
137; FULL-SIMPLIFY-NEXT:    call void @func_cold(ptr dereferenceable(12) [[P1]]) #[[ATTR6:[0-9]+]]
138; FULL-SIMPLIFY-NEXT:    call void @func_cold(ptr dereferenceable(12) [[P1]])
139; FULL-SIMPLIFY-NEXT:    call void @func(ptr [[P1]], ptr [[P]])
140; FULL-SIMPLIFY-NEXT:    call void @func_strbool(ptr [[P1]])
141; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 32) ]
142; FULL-SIMPLIFY-NEXT:    call void @func(ptr dereferenceable(32) [[P]], ptr dereferenceable(8) [[P]])
143; FULL-SIMPLIFY-NEXT:    call void @func_many(ptr align 8 [[P1]])
144; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ]
145; FULL-SIMPLIFY-NEXT:    call void @func_many(ptr noundef align 8 [[P1]])
146; FULL-SIMPLIFY-NEXT:    call void @func_argattr(ptr [[P2]], ptr [[P3]])
147; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "noundef"(ptr [[P2]]), "align"(ptr [[P2]], i64 8), "noundef"(ptr [[P3]]), "nonnull"(ptr [[P3]]) ]
148; FULL-SIMPLIFY-NEXT:    call void @func_argattr2(ptr [[P2]], ptr [[P3]])
149; FULL-SIMPLIFY-NEXT:    call void @func(ptr nonnull [[P1]], ptr nonnull [[P]])
150; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[P1]]), "noundef"(ptr [[P]]) ]
151; FULL-SIMPLIFY-NEXT:    call void @func(ptr noundef nonnull [[P1]], ptr noundef nonnull [[P]])
152; FULL-SIMPLIFY-NEXT:    ret void
153;
154bb:
155  call void @func(ptr nonnull dereferenceable(16) %P, ptr null)
156  call void @func(ptr dereferenceable(12) %P1, ptr nonnull %P)
157  call void @func_cold(ptr dereferenceable(12) %P1) #5
158  call void @func_cold(ptr dereferenceable(12) %P1)
159  call void @func(ptr %P1, ptr %P)
160  call void @func_strbool(ptr %P1)
161  call void @func(ptr dereferenceable(32) %P, ptr dereferenceable(8) %P)
162  call void @func_many(ptr align 8 %P1)
163  call void @func_many(ptr noundef align 8 %P1)
164  call void @func_argattr(ptr %P2, ptr %P3)
165  call void @func_argattr2(ptr %P2, ptr %P3)
166  call void @func(ptr nonnull %P1, ptr nonnull %P)
167  call void @func(ptr noundef nonnull %P1, ptr noundef nonnull %P)
168  ret void
169}
170
171define i32 @test2(ptr %arg, ptr %arg1, ptr %arg2) {
172; BASIC-LABEL: define {{[^@]+}}@test2
173; BASIC-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) {
174; BASIC-NEXT:  bb:
175; BASIC-NEXT:    [[I:%.*]] = alloca ptr, align 8
176; BASIC-NEXT:    [[I3:%.*]] = alloca ptr, align 8
177; BASIC-NEXT:    [[I4:%.*]] = alloca ptr, align 8
178; BASIC-NEXT:    [[I5:%.*]] = alloca [[STRUCT_S:%.*]], align 8
179; BASIC-NEXT:    store ptr [[ARG]], ptr [[I]], align 8
180; BASIC-NEXT:    store ptr [[ARG1]], ptr [[I3]], align 8
181; BASIC-NEXT:    store ptr [[ARG2]], ptr [[I4]], align 8
182; BASIC-NEXT:    [[I6:%.*]] = load ptr, ptr [[I3]], align 8
183; BASIC-NEXT:    [[I7:%.*]] = load i32, ptr [[I6]], align 4
184; BASIC-NEXT:    [[I8:%.*]] = trunc i32 [[I7]] to i8
185; BASIC-NEXT:    [[I9:%.*]] = load ptr, ptr [[I4]], align 8
186; BASIC-NEXT:    store i8 [[I8]], ptr [[I9]], align 1
187; BASIC-NEXT:    [[I11:%.*]] = load ptr, ptr [[I]], align 8
188; BASIC-NEXT:    [[I14:%.*]] = load ptr, ptr [[I]], align 8
189; BASIC-NEXT:    [[I16:%.*]] = load i32, ptr [[I14]], align 8
190; BASIC-NEXT:    [[I17:%.*]] = load ptr, ptr [[I]], align 8
191; BASIC-NEXT:    [[I18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I17]], i32 0, i32 1
192; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I17]], i64 5), "nonnull"(ptr [[I17]]), "align"(ptr [[I17]], i64 4) ]
193; BASIC-NEXT:    [[I19:%.*]] = load i8, ptr [[I18]], align 4
194; BASIC-NEXT:    [[I20:%.*]] = sext i8 [[I19]] to i32
195; BASIC-NEXT:    [[I21:%.*]] = add nsw i32 [[I16]], [[I20]]
196; BASIC-NEXT:    [[I22:%.*]] = load ptr, ptr [[I]], align 8
197; BASIC-NEXT:    [[I23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I22]], i32 0, i32 2
198; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I22]], i64 16), "nonnull"(ptr [[I22]]), "align"(ptr [[I22]], i64 8) ]
199; BASIC-NEXT:    [[I24:%.*]] = load ptr, ptr [[I23]], align 8
200; BASIC-NEXT:    [[I25:%.*]] = load i32, ptr [[I24]], align 4
201; BASIC-NEXT:    [[I26:%.*]] = add nsw i32 [[I21]], [[I25]]
202; BASIC-NEXT:    ret i32 [[I26]]
203;
204; ALL-LABEL: define {{[^@]+}}@test2
205; ALL-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) {
206; ALL-NEXT:  bb:
207; ALL-NEXT:    [[I:%.*]] = alloca ptr, align 8
208; ALL-NEXT:    [[I3:%.*]] = alloca ptr, align 8
209; ALL-NEXT:    [[I4:%.*]] = alloca ptr, align 8
210; ALL-NEXT:    [[I5:%.*]] = alloca [[STRUCT_S:%.*]], align 8
211; ALL-NEXT:    store ptr [[ARG]], ptr [[I]], align 8
212; ALL-NEXT:    store ptr [[ARG1]], ptr [[I3]], align 8
213; ALL-NEXT:    store ptr [[ARG2]], ptr [[I4]], align 8
214; ALL-NEXT:    [[I6:%.*]] = load ptr, ptr [[I3]], align 8
215; ALL-NEXT:    [[I7:%.*]] = load i32, ptr [[I6]], align 4
216; ALL-NEXT:    [[I8:%.*]] = trunc i32 [[I7]] to i8
217; ALL-NEXT:    [[I9:%.*]] = load ptr, ptr [[I4]], align 8
218; ALL-NEXT:    store i8 [[I8]], ptr [[I9]], align 1
219; ALL-NEXT:    [[I11:%.*]] = load ptr, ptr [[I]], align 8
220; ALL-NEXT:    [[I14:%.*]] = load ptr, ptr [[I]], align 8
221; ALL-NEXT:    [[I16:%.*]] = load i32, ptr [[I14]], align 8
222; ALL-NEXT:    [[I17:%.*]] = load ptr, ptr [[I]], align 8
223; ALL-NEXT:    [[I18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I17]], i32 0, i32 1
224; ALL-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I17]], i64 5), "nonnull"(ptr [[I17]]), "align"(ptr [[I17]], i64 4) ]
225; ALL-NEXT:    [[I19:%.*]] = load i8, ptr [[I18]], align 4
226; ALL-NEXT:    [[I20:%.*]] = sext i8 [[I19]] to i32
227; ALL-NEXT:    [[I21:%.*]] = add nsw i32 [[I16]], [[I20]]
228; ALL-NEXT:    [[I22:%.*]] = load ptr, ptr [[I]], align 8
229; ALL-NEXT:    [[I23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I22]], i32 0, i32 2
230; ALL-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I22]], i64 16), "nonnull"(ptr [[I22]]), "align"(ptr [[I22]], i64 8) ]
231; ALL-NEXT:    [[I24:%.*]] = load ptr, ptr [[I23]], align 8
232; ALL-NEXT:    [[I25:%.*]] = load i32, ptr [[I24]], align 4
233; ALL-NEXT:    [[I26:%.*]] = add nsw i32 [[I21]], [[I25]]
234; ALL-NEXT:    ret i32 [[I26]]
235;
236; WITH-AC-LABEL: define {{[^@]+}}@test2
237; WITH-AC-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) {
238; WITH-AC-NEXT:  bb:
239; WITH-AC-NEXT:    [[I:%.*]] = alloca ptr, align 8
240; WITH-AC-NEXT:    [[I3:%.*]] = alloca ptr, align 8
241; WITH-AC-NEXT:    [[I4:%.*]] = alloca ptr, align 8
242; WITH-AC-NEXT:    [[I5:%.*]] = alloca [[STRUCT_S:%.*]], align 8
243; WITH-AC-NEXT:    store ptr [[ARG]], ptr [[I]], align 8
244; WITH-AC-NEXT:    store ptr [[ARG1]], ptr [[I3]], align 8
245; WITH-AC-NEXT:    store ptr [[ARG2]], ptr [[I4]], align 8
246; WITH-AC-NEXT:    [[I6:%.*]] = load ptr, ptr [[I3]], align 8
247; WITH-AC-NEXT:    [[I7:%.*]] = load i32, ptr [[I6]], align 4
248; WITH-AC-NEXT:    [[I8:%.*]] = trunc i32 [[I7]] to i8
249; WITH-AC-NEXT:    [[I9:%.*]] = load ptr, ptr [[I4]], align 8
250; WITH-AC-NEXT:    store i8 [[I8]], ptr [[I9]], align 1
251; WITH-AC-NEXT:    [[I11:%.*]] = load ptr, ptr [[I]], align 8
252; WITH-AC-NEXT:    [[I14:%.*]] = load ptr, ptr [[I]], align 8
253; WITH-AC-NEXT:    [[I16:%.*]] = load i32, ptr [[I14]], align 8
254; WITH-AC-NEXT:    [[I17:%.*]] = load ptr, ptr [[I]], align 8
255; WITH-AC-NEXT:    [[I18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I17]], i32 0, i32 1
256; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I17]], i64 5), "nonnull"(ptr [[I17]]), "align"(ptr [[I17]], i64 4) ]
257; WITH-AC-NEXT:    [[I19:%.*]] = load i8, ptr [[I18]], align 4
258; WITH-AC-NEXT:    [[I20:%.*]] = sext i8 [[I19]] to i32
259; WITH-AC-NEXT:    [[I21:%.*]] = add nsw i32 [[I16]], [[I20]]
260; WITH-AC-NEXT:    [[I22:%.*]] = load ptr, ptr [[I]], align 8
261; WITH-AC-NEXT:    [[I23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I22]], i32 0, i32 2
262; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I22]], i64 16), "nonnull"(ptr [[I22]]), "align"(ptr [[I22]], i64 8) ]
263; WITH-AC-NEXT:    [[I24:%.*]] = load ptr, ptr [[I23]], align 8
264; WITH-AC-NEXT:    [[I25:%.*]] = load i32, ptr [[I24]], align 4
265; WITH-AC-NEXT:    [[I26:%.*]] = add nsw i32 [[I21]], [[I25]]
266; WITH-AC-NEXT:    ret i32 [[I26]]
267;
268; CROSS-BLOCK-LABEL: define {{[^@]+}}@test2
269; CROSS-BLOCK-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) {
270; CROSS-BLOCK-NEXT:  bb:
271; CROSS-BLOCK-NEXT:    [[I:%.*]] = alloca ptr, align 8
272; CROSS-BLOCK-NEXT:    [[I3:%.*]] = alloca ptr, align 8
273; CROSS-BLOCK-NEXT:    [[I4:%.*]] = alloca ptr, align 8
274; CROSS-BLOCK-NEXT:    [[I5:%.*]] = alloca [[STRUCT_S:%.*]], align 8
275; CROSS-BLOCK-NEXT:    store ptr [[ARG]], ptr [[I]], align 8
276; CROSS-BLOCK-NEXT:    store ptr [[ARG1]], ptr [[I3]], align 8
277; CROSS-BLOCK-NEXT:    store ptr [[ARG2]], ptr [[I4]], align 8
278; CROSS-BLOCK-NEXT:    [[I6:%.*]] = load ptr, ptr [[I3]], align 8
279; CROSS-BLOCK-NEXT:    [[I7:%.*]] = load i32, ptr [[I6]], align 4
280; CROSS-BLOCK-NEXT:    [[I8:%.*]] = trunc i32 [[I7]] to i8
281; CROSS-BLOCK-NEXT:    [[I9:%.*]] = load ptr, ptr [[I4]], align 8
282; CROSS-BLOCK-NEXT:    store i8 [[I8]], ptr [[I9]], align 1
283; CROSS-BLOCK-NEXT:    [[I11:%.*]] = load ptr, ptr [[I]], align 8
284; CROSS-BLOCK-NEXT:    [[I14:%.*]] = load ptr, ptr [[I]], align 8
285; CROSS-BLOCK-NEXT:    [[I16:%.*]] = load i32, ptr [[I14]], align 8
286; CROSS-BLOCK-NEXT:    [[I17:%.*]] = load ptr, ptr [[I]], align 8
287; CROSS-BLOCK-NEXT:    [[I18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I17]], i32 0, i32 1
288; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I17]], i64 5), "nonnull"(ptr [[I17]]), "align"(ptr [[I17]], i64 4) ]
289; CROSS-BLOCK-NEXT:    [[I19:%.*]] = load i8, ptr [[I18]], align 4
290; CROSS-BLOCK-NEXT:    [[I20:%.*]] = sext i8 [[I19]] to i32
291; CROSS-BLOCK-NEXT:    [[I21:%.*]] = add nsw i32 [[I16]], [[I20]]
292; CROSS-BLOCK-NEXT:    [[I22:%.*]] = load ptr, ptr [[I]], align 8
293; CROSS-BLOCK-NEXT:    [[I23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I22]], i32 0, i32 2
294; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I22]], i64 16), "nonnull"(ptr [[I22]]), "align"(ptr [[I22]], i64 8) ]
295; CROSS-BLOCK-NEXT:    [[I24:%.*]] = load ptr, ptr [[I23]], align 8
296; CROSS-BLOCK-NEXT:    [[I25:%.*]] = load i32, ptr [[I24]], align 4
297; CROSS-BLOCK-NEXT:    [[I26:%.*]] = add nsw i32 [[I21]], [[I25]]
298; CROSS-BLOCK-NEXT:    ret i32 [[I26]]
299;
300; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test2
301; FULL-SIMPLIFY-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) {
302; FULL-SIMPLIFY-NEXT:  bb:
303; FULL-SIMPLIFY-NEXT:    [[I:%.*]] = alloca ptr, align 8
304; FULL-SIMPLIFY-NEXT:    [[I3:%.*]] = alloca ptr, align 8
305; FULL-SIMPLIFY-NEXT:    [[I4:%.*]] = alloca ptr, align 8
306; FULL-SIMPLIFY-NEXT:    [[I5:%.*]] = alloca [[STRUCT_S:%.*]], align 8
307; FULL-SIMPLIFY-NEXT:    store ptr [[ARG]], ptr [[I]], align 8
308; FULL-SIMPLIFY-NEXT:    store ptr [[ARG1]], ptr [[I3]], align 8
309; FULL-SIMPLIFY-NEXT:    store ptr [[ARG2]], ptr [[I4]], align 8
310; FULL-SIMPLIFY-NEXT:    [[I6:%.*]] = load ptr, ptr [[I3]], align 8
311; FULL-SIMPLIFY-NEXT:    [[I7:%.*]] = load i32, ptr [[I6]], align 4
312; FULL-SIMPLIFY-NEXT:    [[I8:%.*]] = trunc i32 [[I7]] to i8
313; FULL-SIMPLIFY-NEXT:    [[I9:%.*]] = load ptr, ptr [[I4]], align 8
314; FULL-SIMPLIFY-NEXT:    store i8 [[I8]], ptr [[I9]], align 1
315; FULL-SIMPLIFY-NEXT:    [[I11:%.*]] = load ptr, ptr [[I]], align 8
316; FULL-SIMPLIFY-NEXT:    [[I14:%.*]] = load ptr, ptr [[I]], align 8
317; FULL-SIMPLIFY-NEXT:    [[I16:%.*]] = load i32, ptr [[I14]], align 8
318; FULL-SIMPLIFY-NEXT:    [[I17:%.*]] = load ptr, ptr [[I]], align 8
319; FULL-SIMPLIFY-NEXT:    [[I18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I17]], i32 0, i32 1
320; FULL-SIMPLIFY-NEXT:    [[I19:%.*]] = load i8, ptr [[I18]], align 4
321; FULL-SIMPLIFY-NEXT:    [[I20:%.*]] = sext i8 [[I19]] to i32
322; FULL-SIMPLIFY-NEXT:    [[I21:%.*]] = add nsw i32 [[I16]], [[I20]]
323; FULL-SIMPLIFY-NEXT:    [[I22:%.*]] = load ptr, ptr [[I]], align 8
324; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I17]], i64 5), "nonnull"(ptr [[I17]]), "align"(ptr [[I17]], i64 4), "dereferenceable"(ptr [[I22]], i64 16), "nonnull"(ptr [[I22]]), "align"(ptr [[I22]], i64 8) ]
325; FULL-SIMPLIFY-NEXT:    [[I23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I22]], i32 0, i32 2
326; FULL-SIMPLIFY-NEXT:    [[I24:%.*]] = load ptr, ptr [[I23]], align 8
327; FULL-SIMPLIFY-NEXT:    [[I25:%.*]] = load i32, ptr [[I24]], align 4
328; FULL-SIMPLIFY-NEXT:    [[I26:%.*]] = add nsw i32 [[I21]], [[I25]]
329; FULL-SIMPLIFY-NEXT:    ret i32 [[I26]]
330;
331bb:
332  %i = alloca ptr, align 8
333  %i3 = alloca ptr, align 8
334  %i4 = alloca ptr, align 8
335  %i5 = alloca %struct.S, align 8
336  store ptr %arg, ptr %i, align 8
337  store ptr %arg1, ptr %i3, align 8
338  store ptr %arg2, ptr %i4, align 8
339  %i6 = load ptr, ptr %i3, align 8
340  %i7 = load i32, ptr %i6, align 4
341  %i8 = trunc i32 %i7 to i8
342  %i9 = load ptr, ptr %i4, align 8
343  store i8 %i8, ptr %i9, align 1
344  %i11 = load ptr, ptr %i, align 8
345  %i14 = load ptr, ptr %i, align 8
346  %i16 = load i32, ptr %i14, align 8
347  %i17 = load ptr, ptr %i, align 8
348  %i18 = getelementptr inbounds %struct.S, ptr %i17, i32 0, i32 1
349  %i19 = load i8, ptr %i18, align 4
350  %i20 = sext i8 %i19 to i32
351  %i21 = add nsw i32 %i16, %i20
352  %i22 = load ptr, ptr %i, align 8
353  %i23 = getelementptr inbounds %struct.S, ptr %i22, i32 0, i32 2
354  %i24 = load ptr, ptr %i23, align 8
355  %i25 = load i32, ptr %i24, align 4
356  %i26 = add nsw i32 %i21, %i25
357  ret i32 %i26
358}
359
360define i32 @test3(ptr %arg, ptr %arg1, ptr %arg2) #4 {
361; BASIC-LABEL: define {{[^@]+}}@test3
362; BASIC-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) #[[ATTR4:[0-9]+]] {
363; BASIC-NEXT:  bb:
364; BASIC-NEXT:    [[I:%.*]] = alloca ptr, align 8
365; BASIC-NEXT:    [[I3:%.*]] = alloca ptr, align 8
366; BASIC-NEXT:    [[I4:%.*]] = alloca ptr, align 8
367; BASIC-NEXT:    [[I5:%.*]] = alloca [[STRUCT_S:%.*]], align 8
368; BASIC-NEXT:    store ptr [[ARG]], ptr [[I]], align 8
369; BASIC-NEXT:    store ptr [[ARG1]], ptr [[I3]], align 8
370; BASIC-NEXT:    store ptr [[ARG2]], ptr [[I4]], align 8
371; BASIC-NEXT:    [[I6:%.*]] = load ptr, ptr [[I3]], align 8
372; BASIC-NEXT:    [[I7:%.*]] = load i32, ptr [[I6]], align 4
373; BASIC-NEXT:    [[I8:%.*]] = trunc i32 [[I7]] to i8
374; BASIC-NEXT:    [[I9:%.*]] = load ptr, ptr [[I4]], align 8
375; BASIC-NEXT:    store i8 [[I8]], ptr [[I9]], align 1
376; BASIC-NEXT:    [[I11:%.*]] = load ptr, ptr [[I]], align 32
377; BASIC-NEXT:    call void @may_throw()
378; BASIC-NEXT:    [[I14:%.*]] = load ptr, ptr [[I]], align 8
379; BASIC-NEXT:    [[I16:%.*]] = load i32, ptr [[I14]], align 8
380; BASIC-NEXT:    [[I17:%.*]] = load ptr, ptr [[I]], align 8
381; BASIC-NEXT:    [[I18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I17]], i32 0, i32 1
382; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I17]], i64 5), "align"(ptr [[I17]], i64 4) ]
383; BASIC-NEXT:    [[I19:%.*]] = load i8, ptr [[I18]], align 8
384; BASIC-NEXT:    [[I20:%.*]] = sext i8 [[I19]] to i32
385; BASIC-NEXT:    [[I21:%.*]] = add nsw i32 [[I16]], [[I20]]
386; BASIC-NEXT:    [[I22:%.*]] = load ptr, ptr [[I]], align 8
387; BASIC-NEXT:    [[I23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I22]], i32 0, i32 2
388; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I22]], i64 16), "align"(ptr [[I22]], i64 8) ]
389; BASIC-NEXT:    [[I24:%.*]] = load ptr, ptr [[I23]], align 8
390; BASIC-NEXT:    [[I25:%.*]] = load i32, ptr [[I24]], align 4
391; BASIC-NEXT:    [[I26:%.*]] = add nsw i32 [[I21]], [[I25]]
392; BASIC-NEXT:    ret i32 [[I26]]
393;
394; ALL-LABEL: define {{[^@]+}}@test3
395; ALL-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) #[[ATTR4:[0-9]+]] {
396; ALL-NEXT:  bb:
397; ALL-NEXT:    [[I:%.*]] = alloca ptr, align 8
398; ALL-NEXT:    [[I3:%.*]] = alloca ptr, align 8
399; ALL-NEXT:    [[I4:%.*]] = alloca ptr, align 8
400; ALL-NEXT:    [[I5:%.*]] = alloca [[STRUCT_S:%.*]], align 8
401; ALL-NEXT:    store ptr [[ARG]], ptr [[I]], align 8
402; ALL-NEXT:    store ptr [[ARG1]], ptr [[I3]], align 8
403; ALL-NEXT:    store ptr [[ARG2]], ptr [[I4]], align 8
404; ALL-NEXT:    [[I6:%.*]] = load ptr, ptr [[I3]], align 8
405; ALL-NEXT:    [[I7:%.*]] = load i32, ptr [[I6]], align 4
406; ALL-NEXT:    [[I8:%.*]] = trunc i32 [[I7]] to i8
407; ALL-NEXT:    [[I9:%.*]] = load ptr, ptr [[I4]], align 8
408; ALL-NEXT:    store i8 [[I8]], ptr [[I9]], align 1
409; ALL-NEXT:    [[I11:%.*]] = load ptr, ptr [[I]], align 32
410; ALL-NEXT:    call void @may_throw()
411; ALL-NEXT:    [[I14:%.*]] = load ptr, ptr [[I]], align 8
412; ALL-NEXT:    [[I16:%.*]] = load i32, ptr [[I14]], align 8
413; ALL-NEXT:    [[I17:%.*]] = load ptr, ptr [[I]], align 8
414; ALL-NEXT:    [[I18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I17]], i32 0, i32 1
415; ALL-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I17]], i64 5), "align"(ptr [[I17]], i64 4) ]
416; ALL-NEXT:    [[I19:%.*]] = load i8, ptr [[I18]], align 8
417; ALL-NEXT:    [[I20:%.*]] = sext i8 [[I19]] to i32
418; ALL-NEXT:    [[I21:%.*]] = add nsw i32 [[I16]], [[I20]]
419; ALL-NEXT:    [[I22:%.*]] = load ptr, ptr [[I]], align 8
420; ALL-NEXT:    [[I23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I22]], i32 0, i32 2
421; ALL-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I22]], i64 16), "align"(ptr [[I22]], i64 8) ]
422; ALL-NEXT:    [[I24:%.*]] = load ptr, ptr [[I23]], align 8
423; ALL-NEXT:    [[I25:%.*]] = load i32, ptr [[I24]], align 4
424; ALL-NEXT:    [[I26:%.*]] = add nsw i32 [[I21]], [[I25]]
425; ALL-NEXT:    ret i32 [[I26]]
426;
427; WITH-AC-LABEL: define {{[^@]+}}@test3
428; WITH-AC-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) #[[ATTR4:[0-9]+]] {
429; WITH-AC-NEXT:  bb:
430; WITH-AC-NEXT:    [[I:%.*]] = alloca ptr, align 8
431; WITH-AC-NEXT:    [[I3:%.*]] = alloca ptr, align 8
432; WITH-AC-NEXT:    [[I4:%.*]] = alloca ptr, align 8
433; WITH-AC-NEXT:    [[I5:%.*]] = alloca [[STRUCT_S:%.*]], align 8
434; WITH-AC-NEXT:    store ptr [[ARG]], ptr [[I]], align 8
435; WITH-AC-NEXT:    store ptr [[ARG1]], ptr [[I3]], align 8
436; WITH-AC-NEXT:    store ptr [[ARG2]], ptr [[I4]], align 8
437; WITH-AC-NEXT:    [[I6:%.*]] = load ptr, ptr [[I3]], align 8
438; WITH-AC-NEXT:    [[I7:%.*]] = load i32, ptr [[I6]], align 4
439; WITH-AC-NEXT:    [[I8:%.*]] = trunc i32 [[I7]] to i8
440; WITH-AC-NEXT:    [[I9:%.*]] = load ptr, ptr [[I4]], align 8
441; WITH-AC-NEXT:    store i8 [[I8]], ptr [[I9]], align 1
442; WITH-AC-NEXT:    [[I11:%.*]] = load ptr, ptr [[I]], align 32
443; WITH-AC-NEXT:    call void @may_throw()
444; WITH-AC-NEXT:    [[I14:%.*]] = load ptr, ptr [[I]], align 8
445; WITH-AC-NEXT:    [[I16:%.*]] = load i32, ptr [[I14]], align 8
446; WITH-AC-NEXT:    [[I17:%.*]] = load ptr, ptr [[I]], align 8
447; WITH-AC-NEXT:    [[I18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I17]], i32 0, i32 1
448; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I17]], i64 5), "align"(ptr [[I17]], i64 4) ]
449; WITH-AC-NEXT:    [[I19:%.*]] = load i8, ptr [[I18]], align 8
450; WITH-AC-NEXT:    [[I20:%.*]] = sext i8 [[I19]] to i32
451; WITH-AC-NEXT:    [[I21:%.*]] = add nsw i32 [[I16]], [[I20]]
452; WITH-AC-NEXT:    [[I22:%.*]] = load ptr, ptr [[I]], align 8
453; WITH-AC-NEXT:    [[I23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I22]], i32 0, i32 2
454; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I22]], i64 16), "align"(ptr [[I22]], i64 8) ]
455; WITH-AC-NEXT:    [[I24:%.*]] = load ptr, ptr [[I23]], align 8
456; WITH-AC-NEXT:    [[I25:%.*]] = load i32, ptr [[I24]], align 4
457; WITH-AC-NEXT:    [[I26:%.*]] = add nsw i32 [[I21]], [[I25]]
458; WITH-AC-NEXT:    ret i32 [[I26]]
459;
460; CROSS-BLOCK-LABEL: define {{[^@]+}}@test3
461; CROSS-BLOCK-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) #[[ATTR4:[0-9]+]] {
462; CROSS-BLOCK-NEXT:  bb:
463; CROSS-BLOCK-NEXT:    [[I:%.*]] = alloca ptr, align 8
464; CROSS-BLOCK-NEXT:    [[I3:%.*]] = alloca ptr, align 8
465; CROSS-BLOCK-NEXT:    [[I4:%.*]] = alloca ptr, align 8
466; CROSS-BLOCK-NEXT:    [[I5:%.*]] = alloca [[STRUCT_S:%.*]], align 8
467; CROSS-BLOCK-NEXT:    store ptr [[ARG]], ptr [[I]], align 8
468; CROSS-BLOCK-NEXT:    store ptr [[ARG1]], ptr [[I3]], align 8
469; CROSS-BLOCK-NEXT:    store ptr [[ARG2]], ptr [[I4]], align 8
470; CROSS-BLOCK-NEXT:    [[I6:%.*]] = load ptr, ptr [[I3]], align 8
471; CROSS-BLOCK-NEXT:    [[I7:%.*]] = load i32, ptr [[I6]], align 4
472; CROSS-BLOCK-NEXT:    [[I8:%.*]] = trunc i32 [[I7]] to i8
473; CROSS-BLOCK-NEXT:    [[I9:%.*]] = load ptr, ptr [[I4]], align 8
474; CROSS-BLOCK-NEXT:    store i8 [[I8]], ptr [[I9]], align 1
475; CROSS-BLOCK-NEXT:    [[I11:%.*]] = load ptr, ptr [[I]], align 32
476; CROSS-BLOCK-NEXT:    call void @may_throw()
477; CROSS-BLOCK-NEXT:    [[I14:%.*]] = load ptr, ptr [[I]], align 8
478; CROSS-BLOCK-NEXT:    [[I16:%.*]] = load i32, ptr [[I14]], align 8
479; CROSS-BLOCK-NEXT:    [[I17:%.*]] = load ptr, ptr [[I]], align 8
480; CROSS-BLOCK-NEXT:    [[I18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I17]], i32 0, i32 1
481; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I17]], i64 5), "align"(ptr [[I17]], i64 4) ]
482; CROSS-BLOCK-NEXT:    [[I19:%.*]] = load i8, ptr [[I18]], align 8
483; CROSS-BLOCK-NEXT:    [[I20:%.*]] = sext i8 [[I19]] to i32
484; CROSS-BLOCK-NEXT:    [[I21:%.*]] = add nsw i32 [[I16]], [[I20]]
485; CROSS-BLOCK-NEXT:    [[I22:%.*]] = load ptr, ptr [[I]], align 8
486; CROSS-BLOCK-NEXT:    [[I23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I22]], i32 0, i32 2
487; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I22]], i64 16), "align"(ptr [[I22]], i64 8) ]
488; CROSS-BLOCK-NEXT:    [[I24:%.*]] = load ptr, ptr [[I23]], align 8
489; CROSS-BLOCK-NEXT:    [[I25:%.*]] = load i32, ptr [[I24]], align 4
490; CROSS-BLOCK-NEXT:    [[I26:%.*]] = add nsw i32 [[I21]], [[I25]]
491; CROSS-BLOCK-NEXT:    ret i32 [[I26]]
492;
493; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test3
494; FULL-SIMPLIFY-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) #[[ATTR4:[0-9]+]] {
495; FULL-SIMPLIFY-NEXT:  bb:
496; FULL-SIMPLIFY-NEXT:    [[I:%.*]] = alloca ptr, align 8
497; FULL-SIMPLIFY-NEXT:    [[I3:%.*]] = alloca ptr, align 8
498; FULL-SIMPLIFY-NEXT:    [[I4:%.*]] = alloca ptr, align 8
499; FULL-SIMPLIFY-NEXT:    [[I5:%.*]] = alloca [[STRUCT_S:%.*]], align 8
500; FULL-SIMPLIFY-NEXT:    store ptr [[ARG]], ptr [[I]], align 8
501; FULL-SIMPLIFY-NEXT:    store ptr [[ARG1]], ptr [[I3]], align 8
502; FULL-SIMPLIFY-NEXT:    store ptr [[ARG2]], ptr [[I4]], align 8
503; FULL-SIMPLIFY-NEXT:    [[I6:%.*]] = load ptr, ptr [[I3]], align 8
504; FULL-SIMPLIFY-NEXT:    [[I7:%.*]] = load i32, ptr [[I6]], align 4
505; FULL-SIMPLIFY-NEXT:    [[I8:%.*]] = trunc i32 [[I7]] to i8
506; FULL-SIMPLIFY-NEXT:    [[I9:%.*]] = load ptr, ptr [[I4]], align 8
507; FULL-SIMPLIFY-NEXT:    store i8 [[I8]], ptr [[I9]], align 1
508; FULL-SIMPLIFY-NEXT:    [[I11:%.*]] = load ptr, ptr [[I]], align 32
509; FULL-SIMPLIFY-NEXT:    call void @may_throw()
510; FULL-SIMPLIFY-NEXT:    [[I14:%.*]] = load ptr, ptr [[I]], align 8
511; FULL-SIMPLIFY-NEXT:    [[I16:%.*]] = load i32, ptr [[I14]], align 8
512; FULL-SIMPLIFY-NEXT:    [[I17:%.*]] = load ptr, ptr [[I]], align 8
513; FULL-SIMPLIFY-NEXT:    [[I18:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I17]], i32 0, i32 1
514; FULL-SIMPLIFY-NEXT:    [[I19:%.*]] = load i8, ptr [[I18]], align 8
515; FULL-SIMPLIFY-NEXT:    [[I20:%.*]] = sext i8 [[I19]] to i32
516; FULL-SIMPLIFY-NEXT:    [[I21:%.*]] = add nsw i32 [[I16]], [[I20]]
517; FULL-SIMPLIFY-NEXT:    [[I22:%.*]] = load ptr, ptr [[I]], align 8
518; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I17]], i64 5), "align"(ptr [[I17]], i64 4), "dereferenceable"(ptr [[I22]], i64 16), "align"(ptr [[I22]], i64 8) ]
519; FULL-SIMPLIFY-NEXT:    [[I23:%.*]] = getelementptr inbounds [[STRUCT_S]], ptr [[I22]], i32 0, i32 2
520; FULL-SIMPLIFY-NEXT:    [[I24:%.*]] = load ptr, ptr [[I23]], align 8
521; FULL-SIMPLIFY-NEXT:    [[I25:%.*]] = load i32, ptr [[I24]], align 4
522; FULL-SIMPLIFY-NEXT:    [[I26:%.*]] = add nsw i32 [[I21]], [[I25]]
523; FULL-SIMPLIFY-NEXT:    ret i32 [[I26]]
524;
525bb:
526  %i = alloca ptr, align 8
527  %i3 = alloca ptr, align 8
528  %i4 = alloca ptr, align 8
529  %i5 = alloca %struct.S, align 8
530  store ptr %arg, ptr %i, align 8
531  store ptr %arg1, ptr %i3, align 8
532  store ptr %arg2, ptr %i4, align 8
533  %i6 = load ptr, ptr %i3, align 8
534  %i7 = load i32, ptr %i6, align 4
535  %i8 = trunc i32 %i7 to i8
536  %i9 = load ptr, ptr %i4, align 8
537  store i8 %i8, ptr %i9, align 1
538  %i11 = load ptr, ptr %i, align 32
539  call void @may_throw()
540  %i14 = load ptr, ptr %i, align 8
541  %i16 = load i32, ptr %i14, align 8
542  %i17 = load ptr, ptr %i, align 8
543  %i18 = getelementptr inbounds %struct.S, ptr %i17, i32 0, i32 1
544  %i19 = load i8, ptr %i18, align 8
545  %i20 = sext i8 %i19 to i32
546  %i21 = add nsw i32 %i16, %i20
547  %i22 = load ptr, ptr %i, align 8
548  %i23 = getelementptr inbounds %struct.S, ptr %i22, i32 0, i32 2
549  %i24 = load ptr, ptr %i23, align 8
550  %i25 = load i32, ptr %i24, align 4
551  %i26 = add nsw i32 %i21, %i25
552  ret i32 %i26
553}
554
555define dso_local i32 @_Z6squarePi(ptr %P, ptr %P1, i1 %cond) {
556; BASIC-LABEL: define {{[^@]+}}@_Z6squarePi
557; BASIC-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], i1 [[COND:%.*]]) {
558; BASIC-NEXT:  bb:
559; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 4) ]
560; BASIC-NEXT:    store i32 0, ptr [[P]], align 4
561; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ]
562; BASIC-NEXT:    store i32 0, ptr [[P1]], align 8
563; BASIC-NEXT:    br i1 [[COND]], label [[A:%.*]], label [[B:%.*]]
564; BASIC:       A:
565; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ]
566; BASIC-NEXT:    store i32 0, ptr [[P]], align 8
567; BASIC-NEXT:    store i32 0, ptr [[P1]], align 4
568; BASIC-NEXT:    br i1 [[COND]], label [[C:%.*]], label [[B]]
569; BASIC:       B:
570; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ]
571; BASIC-NEXT:    store i32 0, ptr [[P]], align 8
572; BASIC-NEXT:    store i32 0, ptr [[P1]], align 8
573; BASIC-NEXT:    br label [[C]]
574; BASIC:       C:
575; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 32) ]
576; BASIC-NEXT:    store i32 0, ptr [[P]], align 32
577; BASIC-NEXT:    store i32 0, ptr [[P1]], align 4
578; BASIC-NEXT:    ret i32 0
579;
580; ALL-LABEL: define {{[^@]+}}@_Z6squarePi
581; ALL-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], i1 [[COND:%.*]]) {
582; ALL-NEXT:  bb:
583; ALL-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 4) ]
584; ALL-NEXT:    store i32 0, ptr [[P]], align 4
585; ALL-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ]
586; ALL-NEXT:    store i32 0, ptr [[P1]], align 8
587; ALL-NEXT:    br i1 [[COND]], label [[A:%.*]], label [[B:%.*]]
588; ALL:       A:
589; ALL-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ]
590; ALL-NEXT:    store i32 0, ptr [[P]], align 8
591; ALL-NEXT:    store i32 0, ptr [[P1]], align 4
592; ALL-NEXT:    br i1 [[COND]], label [[C:%.*]], label [[B]]
593; ALL:       B:
594; ALL-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ]
595; ALL-NEXT:    store i32 0, ptr [[P]], align 8
596; ALL-NEXT:    store i32 0, ptr [[P1]], align 8
597; ALL-NEXT:    br label [[C]]
598; ALL:       C:
599; ALL-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 32) ]
600; ALL-NEXT:    store i32 0, ptr [[P]], align 32
601; ALL-NEXT:    store i32 0, ptr [[P1]], align 4
602; ALL-NEXT:    ret i32 0
603;
604; WITH-AC-LABEL: define {{[^@]+}}@_Z6squarePi
605; WITH-AC-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], i1 [[COND:%.*]]) {
606; WITH-AC-NEXT:  bb:
607; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 4) ]
608; WITH-AC-NEXT:    store i32 0, ptr [[P]], align 4
609; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ]
610; WITH-AC-NEXT:    store i32 0, ptr [[P1]], align 8
611; WITH-AC-NEXT:    br i1 [[COND]], label [[A:%.*]], label [[B:%.*]]
612; WITH-AC:       A:
613; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ]
614; WITH-AC-NEXT:    store i32 0, ptr [[P]], align 8
615; WITH-AC-NEXT:    store i32 0, ptr [[P1]], align 4
616; WITH-AC-NEXT:    br i1 [[COND]], label [[C:%.*]], label [[B]]
617; WITH-AC:       B:
618; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ]
619; WITH-AC-NEXT:    store i32 0, ptr [[P]], align 8
620; WITH-AC-NEXT:    store i32 0, ptr [[P1]], align 8
621; WITH-AC-NEXT:    br label [[C]]
622; WITH-AC:       C:
623; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 32) ]
624; WITH-AC-NEXT:    store i32 0, ptr [[P]], align 32
625; WITH-AC-NEXT:    store i32 0, ptr [[P1]], align 4
626; WITH-AC-NEXT:    ret i32 0
627;
628; CROSS-BLOCK-LABEL: define {{[^@]+}}@_Z6squarePi
629; CROSS-BLOCK-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], i1 [[COND:%.*]]) {
630; CROSS-BLOCK-NEXT:  bb:
631; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 4) ]
632; CROSS-BLOCK-NEXT:    store i32 0, ptr [[P]], align 4
633; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ]
634; CROSS-BLOCK-NEXT:    store i32 0, ptr [[P1]], align 8
635; CROSS-BLOCK-NEXT:    br i1 [[COND]], label [[A:%.*]], label [[B:%.*]]
636; CROSS-BLOCK:       A:
637; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ]
638; CROSS-BLOCK-NEXT:    store i32 0, ptr [[P]], align 8
639; CROSS-BLOCK-NEXT:    store i32 0, ptr [[P1]], align 4
640; CROSS-BLOCK-NEXT:    br i1 [[COND]], label [[C:%.*]], label [[B]]
641; CROSS-BLOCK:       B:
642; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ]
643; CROSS-BLOCK-NEXT:    store i32 0, ptr [[P]], align 8
644; CROSS-BLOCK-NEXT:    store i32 0, ptr [[P1]], align 8
645; CROSS-BLOCK-NEXT:    br label [[C]]
646; CROSS-BLOCK:       C:
647; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 32) ]
648; CROSS-BLOCK-NEXT:    store i32 0, ptr [[P]], align 32
649; CROSS-BLOCK-NEXT:    store i32 0, ptr [[P1]], align 4
650; CROSS-BLOCK-NEXT:    ret i32 0
651;
652; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@_Z6squarePi
653; FULL-SIMPLIFY-SAME: (ptr nonnull align 4 dereferenceable(4) [[P:%.*]], ptr nonnull align 8 dereferenceable(4) [[P1:%.*]], i1 [[COND:%.*]]) {
654; FULL-SIMPLIFY-NEXT:  bb:
655; FULL-SIMPLIFY-NEXT:    store i32 0, ptr [[P]], align 4
656; FULL-SIMPLIFY-NEXT:    store i32 0, ptr [[P1]], align 8
657; FULL-SIMPLIFY-NEXT:    br i1 [[COND]], label [[A:%.*]], label [[B:%.*]]
658; FULL-SIMPLIFY:       A:
659; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ]
660; FULL-SIMPLIFY-NEXT:    store i32 0, ptr [[P]], align 8
661; FULL-SIMPLIFY-NEXT:    store i32 0, ptr [[P1]], align 4
662; FULL-SIMPLIFY-NEXT:    br i1 [[COND]], label [[C:%.*]], label [[B]]
663; FULL-SIMPLIFY:       B:
664; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ]
665; FULL-SIMPLIFY-NEXT:    store i32 0, ptr [[P]], align 8
666; FULL-SIMPLIFY-NEXT:    store i32 0, ptr [[P1]], align 8
667; FULL-SIMPLIFY-NEXT:    br label [[C]]
668; FULL-SIMPLIFY:       C:
669; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 32) ]
670; FULL-SIMPLIFY-NEXT:    store i32 0, ptr [[P]], align 32
671; FULL-SIMPLIFY-NEXT:    store i32 0, ptr [[P1]], align 4
672; FULL-SIMPLIFY-NEXT:    ret i32 0
673;
674bb:
675  store i32 0, ptr %P, align 4
676  store i32 0, ptr %P1, align 8
677  br i1 %cond, label %A, label %B
678
679A:                                                ; preds = %bb
680  store i32 0, ptr %P, align 8
681  store i32 0, ptr %P1, align 4
682  br i1 %cond, label %C, label %B
683
684B:                                                ; preds = %A, %bb
685  store i32 0, ptr %P, align 8
686  store i32 0, ptr %P1, align 8
687  br label %C
688
689C:                                                ; preds = %B, %A
690  store i32 0, ptr %P, align 32
691  store i32 0, ptr %P1, align 4
692  ret i32 0
693}
694
695define dso_local i32 @test4A(ptr %arg, ptr %arg1, i32 %arg2, i32 %arg3) {
696; BASIC-LABEL: define {{[^@]+}}@test4A
697; BASIC-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) {
698; BASIC-NEXT:  bb:
699; BASIC-NEXT:    [[I:%.*]] = icmp ne ptr [[ARG1]], null
700; BASIC-NEXT:    br i1 [[I]], label [[BB4:%.*]], label [[BB10:%.*]]
701; BASIC:       bb4:
702; BASIC-NEXT:    [[I5:%.*]] = add nsw i32 [[ARG3]], [[ARG2]]
703; BASIC-NEXT:    call void @may_throw()
704; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ]
705; BASIC-NEXT:    [[I6:%.*]] = load i32, ptr [[ARG]], align 4
706; BASIC-NEXT:    [[I7:%.*]] = add nsw i32 [[I5]], [[I6]]
707; BASIC-NEXT:    store i32 0, ptr [[ARG]], align 4
708; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG1]], i64 4), "nonnull"(ptr [[ARG1]]), "align"(ptr [[ARG1]], i64 4) ]
709; BASIC-NEXT:    [[I8:%.*]] = load i32, ptr [[ARG1]], align 4
710; BASIC-NEXT:    [[I9:%.*]] = add nsw i32 [[I7]], [[I8]]
711; BASIC-NEXT:    call void @may_throw()
712; BASIC-NEXT:    store i32 [[I9]], ptr [[ARG1]], align 4
713; BASIC-NEXT:    br label [[BB10]]
714; BASIC:       bb10:
715; BASIC-NEXT:    ret i32 0
716;
717; ALL-LABEL: define {{[^@]+}}@test4A
718; ALL-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) {
719; ALL-NEXT:  bb:
720; ALL-NEXT:    [[I:%.*]] = icmp ne ptr [[ARG1]], null
721; ALL-NEXT:    br i1 [[I]], label [[BB4:%.*]], label [[BB10:%.*]]
722; ALL:       bb4:
723; ALL-NEXT:    [[I5:%.*]] = add nsw i32 [[ARG3]], [[ARG2]]
724; ALL-NEXT:    call void @may_throw()
725; ALL-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ]
726; ALL-NEXT:    [[I6:%.*]] = load i32, ptr [[ARG]], align 4
727; ALL-NEXT:    [[I7:%.*]] = add nsw i32 [[I5]], [[I6]]
728; ALL-NEXT:    store i32 0, ptr [[ARG]], align 4
729; ALL-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG1]], i64 4), "nonnull"(ptr [[ARG1]]), "align"(ptr [[ARG1]], i64 4) ]
730; ALL-NEXT:    [[I8:%.*]] = load i32, ptr [[ARG1]], align 4
731; ALL-NEXT:    [[I9:%.*]] = add nsw i32 [[I7]], [[I8]]
732; ALL-NEXT:    call void @may_throw()
733; ALL-NEXT:    store i32 [[I9]], ptr [[ARG1]], align 4
734; ALL-NEXT:    br label [[BB10]]
735; ALL:       bb10:
736; ALL-NEXT:    ret i32 0
737;
738; WITH-AC-LABEL: define {{[^@]+}}@test4A
739; WITH-AC-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) {
740; WITH-AC-NEXT:  bb:
741; WITH-AC-NEXT:    [[I:%.*]] = icmp ne ptr [[ARG1]], null
742; WITH-AC-NEXT:    br i1 [[I]], label [[BB4:%.*]], label [[BB10:%.*]]
743; WITH-AC:       bb4:
744; WITH-AC-NEXT:    [[I5:%.*]] = add nsw i32 [[ARG3]], [[ARG2]]
745; WITH-AC-NEXT:    call void @may_throw()
746; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ]
747; WITH-AC-NEXT:    [[I6:%.*]] = load i32, ptr [[ARG]], align 4
748; WITH-AC-NEXT:    [[I7:%.*]] = add nsw i32 [[I5]], [[I6]]
749; WITH-AC-NEXT:    store i32 0, ptr [[ARG]], align 4
750; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG1]], i64 4), "nonnull"(ptr [[ARG1]]), "align"(ptr [[ARG1]], i64 4) ]
751; WITH-AC-NEXT:    [[I8:%.*]] = load i32, ptr [[ARG1]], align 4
752; WITH-AC-NEXT:    [[I9:%.*]] = add nsw i32 [[I7]], [[I8]]
753; WITH-AC-NEXT:    call void @may_throw()
754; WITH-AC-NEXT:    store i32 [[I9]], ptr [[ARG1]], align 4
755; WITH-AC-NEXT:    br label [[BB10]]
756; WITH-AC:       bb10:
757; WITH-AC-NEXT:    ret i32 0
758;
759; CROSS-BLOCK-LABEL: define {{[^@]+}}@test4A
760; CROSS-BLOCK-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) {
761; CROSS-BLOCK-NEXT:  bb:
762; CROSS-BLOCK-NEXT:    [[I:%.*]] = icmp ne ptr [[ARG1]], null
763; CROSS-BLOCK-NEXT:    br i1 [[I]], label [[BB4:%.*]], label [[BB10:%.*]]
764; CROSS-BLOCK:       bb4:
765; CROSS-BLOCK-NEXT:    [[I5:%.*]] = add nsw i32 [[ARG3]], [[ARG2]]
766; CROSS-BLOCK-NEXT:    call void @may_throw()
767; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ]
768; CROSS-BLOCK-NEXT:    [[I6:%.*]] = load i32, ptr [[ARG]], align 4
769; CROSS-BLOCK-NEXT:    [[I7:%.*]] = add nsw i32 [[I5]], [[I6]]
770; CROSS-BLOCK-NEXT:    store i32 0, ptr [[ARG]], align 4
771; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG1]], i64 4), "nonnull"(ptr [[ARG1]]), "align"(ptr [[ARG1]], i64 4) ]
772; CROSS-BLOCK-NEXT:    [[I8:%.*]] = load i32, ptr [[ARG1]], align 4
773; CROSS-BLOCK-NEXT:    [[I9:%.*]] = add nsw i32 [[I7]], [[I8]]
774; CROSS-BLOCK-NEXT:    call void @may_throw()
775; CROSS-BLOCK-NEXT:    store i32 [[I9]], ptr [[ARG1]], align 4
776; CROSS-BLOCK-NEXT:    br label [[BB10]]
777; CROSS-BLOCK:       bb10:
778; CROSS-BLOCK-NEXT:    ret i32 0
779;
780; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test4A
781; FULL-SIMPLIFY-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) {
782; FULL-SIMPLIFY-NEXT:  bb:
783; FULL-SIMPLIFY-NEXT:    [[I:%.*]] = icmp ne ptr [[ARG1]], null
784; FULL-SIMPLIFY-NEXT:    br i1 [[I]], label [[BB4:%.*]], label [[BB10:%.*]]
785; FULL-SIMPLIFY:       bb4:
786; FULL-SIMPLIFY-NEXT:    [[I5:%.*]] = add nsw i32 [[ARG3]], [[ARG2]]
787; FULL-SIMPLIFY-NEXT:    call void @may_throw()
788; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4), "dereferenceable"(ptr [[ARG1]], i64 4), "nonnull"(ptr [[ARG1]]), "align"(ptr [[ARG1]], i64 4) ]
789; FULL-SIMPLIFY-NEXT:    [[I6:%.*]] = load i32, ptr [[ARG]], align 4
790; FULL-SIMPLIFY-NEXT:    [[I7:%.*]] = add nsw i32 [[I5]], [[I6]]
791; FULL-SIMPLIFY-NEXT:    store i32 0, ptr [[ARG]], align 4
792; FULL-SIMPLIFY-NEXT:    [[I8:%.*]] = load i32, ptr [[ARG1]], align 4
793; FULL-SIMPLIFY-NEXT:    [[I9:%.*]] = add nsw i32 [[I7]], [[I8]]
794; FULL-SIMPLIFY-NEXT:    call void @may_throw()
795; FULL-SIMPLIFY-NEXT:    store i32 [[I9]], ptr [[ARG1]], align 4
796; FULL-SIMPLIFY-NEXT:    br label [[BB10]]
797; FULL-SIMPLIFY:       bb10:
798; FULL-SIMPLIFY-NEXT:    ret i32 0
799;
800bb:
801  %i = icmp ne ptr %arg1, null
802  br i1 %i, label %bb4, label %bb10
803
804bb4:                                              ; preds = %bb
805  %i5 = add nsw i32 %arg3, %arg2
806  call void @may_throw()
807  %i6 = load i32, ptr %arg, align 4
808  %i7 = add nsw i32 %i5, %i6
809  store i32 0, ptr %arg, align 4
810  %i8 = load i32, ptr %arg1, align 4
811  %i9 = add nsw i32 %i7, %i8
812  call void @may_throw()
813  store i32 %i9, ptr %arg1, align 4
814  br label %bb10
815
816bb10:                                             ; preds = %bb4, %bb
817  ret i32 0
818}
819
820declare void @may_throwv2(ptr)
821
822define dso_local i32 @terminator(ptr %P) personality ptr @__gxx_personality_v0 {
823; BASIC-LABEL: define {{[^@]+}}@terminator
824; BASIC-SAME: (ptr [[P:%.*]]) personality ptr @__gxx_personality_v0 {
825; BASIC-NEXT:  bb:
826; BASIC-NEXT:    invoke void @may_throwv2(ptr nonnull [[P]])
827; BASIC-NEXT:            to label [[EXIT:%.*]] unwind label [[CATCH:%.*]]
828; BASIC:       Catch:
829; BASIC-NEXT:    [[V:%.*]] = landingpad { ptr, i32 }
830; BASIC-NEXT:            catch ptr null
831; BASIC-NEXT:    br label [[EXIT]]
832; BASIC:       Exit:
833; BASIC-NEXT:    [[DOT0:%.*]] = phi i32 [ 1, [[BB:%.*]] ], [ 0, [[CATCH]] ]
834; BASIC-NEXT:    ret i32 [[DOT0]]
835;
836; ALL-LABEL: define {{[^@]+}}@terminator
837; ALL-SAME: (ptr [[P:%.*]]) personality ptr @__gxx_personality_v0 {
838; ALL-NEXT:  bb:
839; ALL-NEXT:    invoke void @may_throwv2(ptr nonnull [[P]])
840; ALL-NEXT:            to label [[EXIT:%.*]] unwind label [[CATCH:%.*]]
841; ALL:       Catch:
842; ALL-NEXT:    [[V:%.*]] = landingpad { ptr, i32 }
843; ALL-NEXT:            catch ptr null
844; ALL-NEXT:    br label [[EXIT]]
845; ALL:       Exit:
846; ALL-NEXT:    [[DOT0:%.*]] = phi i32 [ 1, [[BB:%.*]] ], [ 0, [[CATCH]] ]
847; ALL-NEXT:    ret i32 [[DOT0]]
848;
849; WITH-AC-LABEL: define {{[^@]+}}@terminator
850; WITH-AC-SAME: (ptr [[P:%.*]]) personality ptr @__gxx_personality_v0 {
851; WITH-AC-NEXT:  bb:
852; WITH-AC-NEXT:    invoke void @may_throwv2(ptr nonnull [[P]])
853; WITH-AC-NEXT:            to label [[EXIT:%.*]] unwind label [[CATCH:%.*]]
854; WITH-AC:       Catch:
855; WITH-AC-NEXT:    [[V:%.*]] = landingpad { ptr, i32 }
856; WITH-AC-NEXT:            catch ptr null
857; WITH-AC-NEXT:    br label [[EXIT]]
858; WITH-AC:       Exit:
859; WITH-AC-NEXT:    [[DOT0:%.*]] = phi i32 [ 1, [[BB:%.*]] ], [ 0, [[CATCH]] ]
860; WITH-AC-NEXT:    ret i32 [[DOT0]]
861;
862; CROSS-BLOCK-LABEL: define {{[^@]+}}@terminator
863; CROSS-BLOCK-SAME: (ptr [[P:%.*]]) personality ptr @__gxx_personality_v0 {
864; CROSS-BLOCK-NEXT:  bb:
865; CROSS-BLOCK-NEXT:    invoke void @may_throwv2(ptr nonnull [[P]])
866; CROSS-BLOCK-NEXT:            to label [[EXIT:%.*]] unwind label [[CATCH:%.*]]
867; CROSS-BLOCK:       Catch:
868; CROSS-BLOCK-NEXT:    [[V:%.*]] = landingpad { ptr, i32 }
869; CROSS-BLOCK-NEXT:            catch ptr null
870; CROSS-BLOCK-NEXT:    br label [[EXIT]]
871; CROSS-BLOCK:       Exit:
872; CROSS-BLOCK-NEXT:    [[DOT0:%.*]] = phi i32 [ 1, [[BB:%.*]] ], [ 0, [[CATCH]] ]
873; CROSS-BLOCK-NEXT:    ret i32 [[DOT0]]
874;
875; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@terminator
876; FULL-SIMPLIFY-SAME: (ptr [[P:%.*]]) personality ptr @__gxx_personality_v0 {
877; FULL-SIMPLIFY-NEXT:  bb:
878; FULL-SIMPLIFY-NEXT:    invoke void @may_throwv2(ptr nonnull [[P]])
879; FULL-SIMPLIFY-NEXT:            to label [[EXIT:%.*]] unwind label [[CATCH:%.*]]
880; FULL-SIMPLIFY:       Catch:
881; FULL-SIMPLIFY-NEXT:    [[V:%.*]] = landingpad { ptr, i32 }
882; FULL-SIMPLIFY-NEXT:            catch ptr null
883; FULL-SIMPLIFY-NEXT:    br label [[EXIT]]
884; FULL-SIMPLIFY:       Exit:
885; FULL-SIMPLIFY-NEXT:    [[DOT0:%.*]] = phi i32 [ 1, [[BB:%.*]] ], [ 0, [[CATCH]] ]
886; FULL-SIMPLIFY-NEXT:    ret i32 [[DOT0]]
887;
888bb:
889  invoke void @may_throwv2(ptr nonnull %P)
890  to label %Exit unwind label %Catch
891
892Catch:                                            ; preds = %bb
893  %v = landingpad { ptr, i32 }
894  catch ptr null
895  br label %Exit
896
897Exit:                                             ; preds = %Catch, %bb
898  %.0 = phi i32 [ 1, %bb ], [ 0, %Catch ]
899  ret i32 %.0
900}
901
902declare dso_local i32 @__gxx_personality_v0(...)
903
904define dso_local i32 @test5(ptr %arg, i32 %arg1) {
905; BASIC-LABEL: define {{[^@]+}}@test5
906; BASIC-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]]) {
907; BASIC-NEXT:  bb:
908; BASIC-NEXT:    [[I3:%.*]] = sext i32 [[ARG1]] to i64
909; BASIC-NEXT:    [[I4:%.*]] = getelementptr inbounds i16, ptr [[ARG]], i64 [[I3]]
910; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I4]], i64 2), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 8) ]
911; BASIC-NEXT:    [[I5:%.*]] = load i16, ptr [[I4]], align 2
912; BASIC-NEXT:    [[A:%.*]] = load i16, ptr [[I4]], align 4
913; BASIC-NEXT:    [[I6:%.*]] = sext i16 [[I5]] to i64
914; BASIC-NEXT:    [[I7:%.*]] = getelementptr inbounds i64, ptr [[ARG]], i64 [[I6]]
915; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I7]], i64 8) ]
916; BASIC-NEXT:    [[I8:%.*]] = load i64, ptr [[I7]], align 16
917; BASIC-NEXT:    [[B:%.*]] = load i64, ptr [[I7]], align 32
918; BASIC-NEXT:    [[I9:%.*]] = trunc i64 [[I8]] to i32
919; BASIC-NEXT:    ret i32 [[I9]]
920;
921; ALL-LABEL: define {{[^@]+}}@test5
922; ALL-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]]) {
923; ALL-NEXT:  bb:
924; ALL-NEXT:    [[I3:%.*]] = sext i32 [[ARG1]] to i64
925; ALL-NEXT:    [[I4:%.*]] = getelementptr inbounds i16, ptr [[ARG]], i64 [[I3]]
926; ALL-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I4]], i64 2), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 8) ]
927; ALL-NEXT:    [[I5:%.*]] = load i16, ptr [[I4]], align 2
928; ALL-NEXT:    [[A:%.*]] = load i16, ptr [[I4]], align 4
929; ALL-NEXT:    [[I6:%.*]] = sext i16 [[I5]] to i64
930; ALL-NEXT:    [[I7:%.*]] = getelementptr inbounds i64, ptr [[ARG]], i64 [[I6]]
931; ALL-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I7]], i64 8) ]
932; ALL-NEXT:    [[I8:%.*]] = load i64, ptr [[I7]], align 16
933; ALL-NEXT:    [[B:%.*]] = load i64, ptr [[I7]], align 32
934; ALL-NEXT:    [[I9:%.*]] = trunc i64 [[I8]] to i32
935; ALL-NEXT:    ret i32 [[I9]]
936;
937; WITH-AC-LABEL: define {{[^@]+}}@test5
938; WITH-AC-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]]) {
939; WITH-AC-NEXT:  bb:
940; WITH-AC-NEXT:    [[I3:%.*]] = sext i32 [[ARG1]] to i64
941; WITH-AC-NEXT:    [[I4:%.*]] = getelementptr inbounds i16, ptr [[ARG]], i64 [[I3]]
942; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I4]], i64 2), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 8) ]
943; WITH-AC-NEXT:    [[I5:%.*]] = load i16, ptr [[I4]], align 2
944; WITH-AC-NEXT:    [[A:%.*]] = load i16, ptr [[I4]], align 4
945; WITH-AC-NEXT:    [[I6:%.*]] = sext i16 [[I5]] to i64
946; WITH-AC-NEXT:    [[I7:%.*]] = getelementptr inbounds i64, ptr [[ARG]], i64 [[I6]]
947; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I7]], i64 8) ]
948; WITH-AC-NEXT:    [[I8:%.*]] = load i64, ptr [[I7]], align 16
949; WITH-AC-NEXT:    [[B:%.*]] = load i64, ptr [[I7]], align 32
950; WITH-AC-NEXT:    [[I9:%.*]] = trunc i64 [[I8]] to i32
951; WITH-AC-NEXT:    ret i32 [[I9]]
952;
953; CROSS-BLOCK-LABEL: define {{[^@]+}}@test5
954; CROSS-BLOCK-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]]) {
955; CROSS-BLOCK-NEXT:  bb:
956; CROSS-BLOCK-NEXT:    [[I3:%.*]] = sext i32 [[ARG1]] to i64
957; CROSS-BLOCK-NEXT:    [[I4:%.*]] = getelementptr inbounds i16, ptr [[ARG]], i64 [[I3]]
958; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I4]], i64 2), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 8) ]
959; CROSS-BLOCK-NEXT:    [[I5:%.*]] = load i16, ptr [[I4]], align 2
960; CROSS-BLOCK-NEXT:    [[A:%.*]] = load i16, ptr [[I4]], align 4
961; CROSS-BLOCK-NEXT:    [[I6:%.*]] = sext i16 [[I5]] to i64
962; CROSS-BLOCK-NEXT:    [[I7:%.*]] = getelementptr inbounds i64, ptr [[ARG]], i64 [[I6]]
963; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I7]], i64 8) ]
964; CROSS-BLOCK-NEXT:    [[I8:%.*]] = load i64, ptr [[I7]], align 16
965; CROSS-BLOCK-NEXT:    [[B:%.*]] = load i64, ptr [[I7]], align 32
966; CROSS-BLOCK-NEXT:    [[I9:%.*]] = trunc i64 [[I8]] to i32
967; CROSS-BLOCK-NEXT:    ret i32 [[I9]]
968;
969; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test5
970; FULL-SIMPLIFY-SAME: (ptr nonnull align 8 [[ARG:%.*]], i32 [[ARG1:%.*]]) {
971; FULL-SIMPLIFY-NEXT:  bb:
972; FULL-SIMPLIFY-NEXT:    [[I3:%.*]] = sext i32 [[ARG1]] to i64
973; FULL-SIMPLIFY-NEXT:    [[I4:%.*]] = getelementptr inbounds i16, ptr [[ARG]], i64 [[I3]]
974; FULL-SIMPLIFY-NEXT:    [[I5:%.*]] = load i16, ptr [[I4]], align 2
975; FULL-SIMPLIFY-NEXT:    [[A:%.*]] = load i16, ptr [[I4]], align 4
976; FULL-SIMPLIFY-NEXT:    [[I6:%.*]] = sext i16 [[I5]] to i64
977; FULL-SIMPLIFY-NEXT:    [[I7:%.*]] = getelementptr inbounds i64, ptr [[ARG]], i64 [[I6]]
978; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I4]], i64 2), "dereferenceable"(ptr [[I7]], i64 8) ]
979; FULL-SIMPLIFY-NEXT:    [[I8:%.*]] = load i64, ptr [[I7]], align 16
980; FULL-SIMPLIFY-NEXT:    [[B:%.*]] = load i64, ptr [[I7]], align 32
981; FULL-SIMPLIFY-NEXT:    [[I9:%.*]] = trunc i64 [[I8]] to i32
982; FULL-SIMPLIFY-NEXT:    ret i32 [[I9]]
983;
984bb:
985  %i3 = sext i32 %arg1 to i64
986  %i4 = getelementptr inbounds i16, ptr %arg, i64 %i3
987  %i5 = load i16, ptr %i4, align 2
988  %A = load i16, ptr %i4, align 4
989  %i6 = sext i16 %i5 to i64
990  %i7 = getelementptr inbounds i64, ptr %arg, i64 %i6
991  %i8 = load i64, ptr %i7, align 16
992  %B = load i64, ptr %i7, align 32
993  %i9 = trunc i64 %i8 to i32
994  ret i32 %i9
995}
996
997define i32 @test6(ptr %arg, i32 %arg1, ptr %arg2) {
998; BASIC-LABEL: define {{[^@]+}}@test6
999; BASIC-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]], ptr [[ARG2:%.*]]) {
1000; BASIC-NEXT:  bb:
1001; BASIC-NEXT:    br label [[BB3:%.*]]
1002; BASIC:       bb3:
1003; BASIC-NEXT:    [[DOT0:%.*]] = phi i32 [ 0, [[BB:%.*]] ], [ [[I14:%.*]], [[BB4:%.*]] ]
1004; BASIC-NEXT:    [[I:%.*]] = icmp slt i32 [[DOT0]], [[ARG1]]
1005; BASIC-NEXT:    br i1 [[I]], label [[BB4]], label [[BB15:%.*]]
1006; BASIC:       bb4:
1007; BASIC-NEXT:    [[I5:%.*]] = add nsw i32 [[ARG1]], [[DOT0]]
1008; BASIC-NEXT:    [[I6:%.*]] = sext i32 [[I5]] to i64
1009; BASIC-NEXT:    [[I7:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I6]]
1010; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ]
1011; BASIC-NEXT:    [[I8:%.*]] = load i32, ptr [[I7]], align 4
1012; BASIC-NEXT:    [[I9:%.*]] = mul nsw i32 [[DOT0]], [[I8]]
1013; BASIC-NEXT:    [[I10:%.*]] = sext i32 [[DOT0]] to i64
1014; BASIC-NEXT:    [[I11:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I10]]
1015; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I11]], i64 4) ]
1016; BASIC-NEXT:    [[I12:%.*]] = load i32, ptr [[I11]], align 4
1017; BASIC-NEXT:    [[I13:%.*]] = add nsw i32 [[I12]], [[I9]]
1018; BASIC-NEXT:    store i32 [[I13]], ptr [[I11]], align 4
1019; BASIC-NEXT:    [[I14]] = add nsw i32 [[DOT0]], 1
1020; BASIC-NEXT:    br label [[BB3]]
1021; BASIC:       bb15:
1022; BASIC-NEXT:    [[I16:%.*]] = sext i32 [[ARG1]] to i64
1023; BASIC-NEXT:    [[I17:%.*]] = getelementptr inbounds i32, ptr [[ARG2]], i64 [[I16]]
1024; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG2]]), "align"(ptr [[ARG2]], i64 4) ]
1025; BASIC-NEXT:    [[I18:%.*]] = load i32, ptr [[I17]], align 4
1026; BASIC-NEXT:    ret i32 [[I18]]
1027;
1028; ALL-LABEL: define {{[^@]+}}@test6
1029; ALL-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]], ptr [[ARG2:%.*]]) {
1030; ALL-NEXT:  bb:
1031; ALL-NEXT:    br label [[BB3:%.*]]
1032; ALL:       bb3:
1033; ALL-NEXT:    [[DOT0:%.*]] = phi i32 [ 0, [[BB:%.*]] ], [ [[I14:%.*]], [[BB4:%.*]] ]
1034; ALL-NEXT:    [[I:%.*]] = icmp slt i32 [[DOT0]], [[ARG1]]
1035; ALL-NEXT:    br i1 [[I]], label [[BB4]], label [[BB15:%.*]]
1036; ALL:       bb4:
1037; ALL-NEXT:    [[I5:%.*]] = add nsw i32 [[ARG1]], [[DOT0]]
1038; ALL-NEXT:    [[I6:%.*]] = sext i32 [[I5]] to i64
1039; ALL-NEXT:    [[I7:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I6]]
1040; ALL-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ]
1041; ALL-NEXT:    [[I8:%.*]] = load i32, ptr [[I7]], align 4
1042; ALL-NEXT:    [[I9:%.*]] = mul nsw i32 [[DOT0]], [[I8]]
1043; ALL-NEXT:    [[I10:%.*]] = sext i32 [[DOT0]] to i64
1044; ALL-NEXT:    [[I11:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I10]]
1045; ALL-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I11]], i64 4) ]
1046; ALL-NEXT:    [[I12:%.*]] = load i32, ptr [[I11]], align 4
1047; ALL-NEXT:    [[I13:%.*]] = add nsw i32 [[I12]], [[I9]]
1048; ALL-NEXT:    store i32 [[I13]], ptr [[I11]], align 4
1049; ALL-NEXT:    [[I14]] = add nsw i32 [[DOT0]], 1
1050; ALL-NEXT:    br label [[BB3]]
1051; ALL:       bb15:
1052; ALL-NEXT:    [[I16:%.*]] = sext i32 [[ARG1]] to i64
1053; ALL-NEXT:    [[I17:%.*]] = getelementptr inbounds i32, ptr [[ARG2]], i64 [[I16]]
1054; ALL-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG2]]), "align"(ptr [[ARG2]], i64 4) ]
1055; ALL-NEXT:    [[I18:%.*]] = load i32, ptr [[I17]], align 4
1056; ALL-NEXT:    ret i32 [[I18]]
1057;
1058; WITH-AC-LABEL: define {{[^@]+}}@test6
1059; WITH-AC-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]], ptr [[ARG2:%.*]]) {
1060; WITH-AC-NEXT:  bb:
1061; WITH-AC-NEXT:    br label [[BB3:%.*]]
1062; WITH-AC:       bb3:
1063; WITH-AC-NEXT:    [[DOT0:%.*]] = phi i32 [ 0, [[BB:%.*]] ], [ [[I14:%.*]], [[BB4:%.*]] ]
1064; WITH-AC-NEXT:    [[I:%.*]] = icmp slt i32 [[DOT0]], [[ARG1]]
1065; WITH-AC-NEXT:    br i1 [[I]], label [[BB4]], label [[BB15:%.*]]
1066; WITH-AC:       bb4:
1067; WITH-AC-NEXT:    [[I5:%.*]] = add nsw i32 [[ARG1]], [[DOT0]]
1068; WITH-AC-NEXT:    [[I6:%.*]] = sext i32 [[I5]] to i64
1069; WITH-AC-NEXT:    [[I7:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I6]]
1070; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ]
1071; WITH-AC-NEXT:    [[I8:%.*]] = load i32, ptr [[I7]], align 4
1072; WITH-AC-NEXT:    [[I9:%.*]] = mul nsw i32 [[DOT0]], [[I8]]
1073; WITH-AC-NEXT:    [[I10:%.*]] = sext i32 [[DOT0]] to i64
1074; WITH-AC-NEXT:    [[I11:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I10]]
1075; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I11]], i64 4) ]
1076; WITH-AC-NEXT:    [[I12:%.*]] = load i32, ptr [[I11]], align 4
1077; WITH-AC-NEXT:    [[I13:%.*]] = add nsw i32 [[I12]], [[I9]]
1078; WITH-AC-NEXT:    store i32 [[I13]], ptr [[I11]], align 4
1079; WITH-AC-NEXT:    [[I14]] = add nsw i32 [[DOT0]], 1
1080; WITH-AC-NEXT:    br label [[BB3]]
1081; WITH-AC:       bb15:
1082; WITH-AC-NEXT:    [[I16:%.*]] = sext i32 [[ARG1]] to i64
1083; WITH-AC-NEXT:    [[I17:%.*]] = getelementptr inbounds i32, ptr [[ARG2]], i64 [[I16]]
1084; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG2]]), "align"(ptr [[ARG2]], i64 4) ]
1085; WITH-AC-NEXT:    [[I18:%.*]] = load i32, ptr [[I17]], align 4
1086; WITH-AC-NEXT:    ret i32 [[I18]]
1087;
1088; CROSS-BLOCK-LABEL: define {{[^@]+}}@test6
1089; CROSS-BLOCK-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]], ptr [[ARG2:%.*]]) {
1090; CROSS-BLOCK-NEXT:  bb:
1091; CROSS-BLOCK-NEXT:    br label [[BB3:%.*]]
1092; CROSS-BLOCK:       bb3:
1093; CROSS-BLOCK-NEXT:    [[DOT0:%.*]] = phi i32 [ 0, [[BB:%.*]] ], [ [[I14:%.*]], [[BB4:%.*]] ]
1094; CROSS-BLOCK-NEXT:    [[I:%.*]] = icmp slt i32 [[DOT0]], [[ARG1]]
1095; CROSS-BLOCK-NEXT:    br i1 [[I]], label [[BB4]], label [[BB15:%.*]]
1096; CROSS-BLOCK:       bb4:
1097; CROSS-BLOCK-NEXT:    [[I5:%.*]] = add nsw i32 [[ARG1]], [[DOT0]]
1098; CROSS-BLOCK-NEXT:    [[I6:%.*]] = sext i32 [[I5]] to i64
1099; CROSS-BLOCK-NEXT:    [[I7:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I6]]
1100; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ]
1101; CROSS-BLOCK-NEXT:    [[I8:%.*]] = load i32, ptr [[I7]], align 4
1102; CROSS-BLOCK-NEXT:    [[I9:%.*]] = mul nsw i32 [[DOT0]], [[I8]]
1103; CROSS-BLOCK-NEXT:    [[I10:%.*]] = sext i32 [[DOT0]] to i64
1104; CROSS-BLOCK-NEXT:    [[I11:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I10]]
1105; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I11]], i64 4) ]
1106; CROSS-BLOCK-NEXT:    [[I12:%.*]] = load i32, ptr [[I11]], align 4
1107; CROSS-BLOCK-NEXT:    [[I13:%.*]] = add nsw i32 [[I12]], [[I9]]
1108; CROSS-BLOCK-NEXT:    store i32 [[I13]], ptr [[I11]], align 4
1109; CROSS-BLOCK-NEXT:    [[I14]] = add nsw i32 [[DOT0]], 1
1110; CROSS-BLOCK-NEXT:    br label [[BB3]]
1111; CROSS-BLOCK:       bb15:
1112; CROSS-BLOCK-NEXT:    [[I16:%.*]] = sext i32 [[ARG1]] to i64
1113; CROSS-BLOCK-NEXT:    [[I17:%.*]] = getelementptr inbounds i32, ptr [[ARG2]], i64 [[I16]]
1114; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG2]]), "align"(ptr [[ARG2]], i64 4) ]
1115; CROSS-BLOCK-NEXT:    [[I18:%.*]] = load i32, ptr [[I17]], align 4
1116; CROSS-BLOCK-NEXT:    ret i32 [[I18]]
1117;
1118; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test6
1119; FULL-SIMPLIFY-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]], ptr [[ARG2:%.*]]) {
1120; FULL-SIMPLIFY-NEXT:  bb:
1121; FULL-SIMPLIFY-NEXT:    br label [[BB3:%.*]]
1122; FULL-SIMPLIFY:       bb3:
1123; FULL-SIMPLIFY-NEXT:    [[DOT0:%.*]] = phi i32 [ 0, [[BB:%.*]] ], [ [[I14:%.*]], [[BB4:%.*]] ]
1124; FULL-SIMPLIFY-NEXT:    [[I:%.*]] = icmp slt i32 [[DOT0]], [[ARG1]]
1125; FULL-SIMPLIFY-NEXT:    br i1 [[I]], label [[BB4]], label [[BB15:%.*]]
1126; FULL-SIMPLIFY:       bb4:
1127; FULL-SIMPLIFY-NEXT:    [[I5:%.*]] = add nsw i32 [[ARG1]], [[DOT0]]
1128; FULL-SIMPLIFY-NEXT:    [[I6:%.*]] = sext i32 [[I5]] to i64
1129; FULL-SIMPLIFY-NEXT:    [[I7:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I6]]
1130; FULL-SIMPLIFY-NEXT:    [[I8:%.*]] = load i32, ptr [[I7]], align 4
1131; FULL-SIMPLIFY-NEXT:    [[I9:%.*]] = mul nsw i32 [[DOT0]], [[I8]]
1132; FULL-SIMPLIFY-NEXT:    [[I10:%.*]] = sext i32 [[DOT0]] to i64
1133; FULL-SIMPLIFY-NEXT:    [[I11:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I10]]
1134; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4), "dereferenceable"(ptr [[I11]], i64 4) ]
1135; FULL-SIMPLIFY-NEXT:    [[I12:%.*]] = load i32, ptr [[I11]], align 4
1136; FULL-SIMPLIFY-NEXT:    [[I13:%.*]] = add nsw i32 [[I12]], [[I9]]
1137; FULL-SIMPLIFY-NEXT:    store i32 [[I13]], ptr [[I11]], align 4
1138; FULL-SIMPLIFY-NEXT:    [[I14]] = add nsw i32 [[DOT0]], 1
1139; FULL-SIMPLIFY-NEXT:    br label [[BB3]]
1140; FULL-SIMPLIFY:       bb15:
1141; FULL-SIMPLIFY-NEXT:    [[I16:%.*]] = sext i32 [[ARG1]] to i64
1142; FULL-SIMPLIFY-NEXT:    [[I17:%.*]] = getelementptr inbounds i32, ptr [[ARG2]], i64 [[I16]]
1143; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG2]]), "align"(ptr [[ARG2]], i64 4) ]
1144; FULL-SIMPLIFY-NEXT:    [[I18:%.*]] = load i32, ptr [[I17]], align 4
1145; FULL-SIMPLIFY-NEXT:    ret i32 [[I18]]
1146;
1147bb:
1148  br label %bb3
1149
1150bb3:                                              ; preds = %bb4, %bb
1151  %.0 = phi i32 [ 0, %bb ], [ %i14, %bb4 ]
1152  %i = icmp slt i32 %.0, %arg1
1153  br i1 %i, label %bb4, label %bb15
1154
1155bb4:                                              ; preds = %bb3
1156  %i5 = add nsw i32 %arg1, %.0
1157  %i6 = sext i32 %i5 to i64
1158  %i7 = getelementptr inbounds i32, ptr %arg, i64 %i6
1159  %i8 = load i32, ptr %i7, align 4
1160  %i9 = mul nsw i32 %.0, %i8
1161  %i10 = sext i32 %.0 to i64
1162  %i11 = getelementptr inbounds i32, ptr %arg, i64 %i10
1163  %i12 = load i32, ptr %i11, align 4
1164  %i13 = add nsw i32 %i12, %i9
1165  store i32 %i13, ptr %i11, align 4
1166  %i14 = add nsw i32 %.0, 1
1167  br label %bb3
1168
1169bb15:                                             ; preds = %bb3
1170  %i16 = sext i32 %arg1 to i64
1171  %i17 = getelementptr inbounds i32, ptr %arg2, i64 %i16
1172  %i18 = load i32, ptr %i17, align 4
1173  ret i32 %i18
1174}
1175
1176define i32 @test7(ptr nonnull %arg, i32 %arg1) {
1177; BASIC-LABEL: define {{[^@]+}}@test7
1178; BASIC-SAME: (ptr nonnull [[ARG:%.*]], i32 [[ARG1:%.*]]) {
1179; BASIC-NEXT:  bb:
1180; BASIC-NEXT:    [[I:%.*]] = sext i32 [[ARG1]] to i64
1181; BASIC-NEXT:    [[I2:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[ARG]], i64 0, i32 3
1182; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 280), "align"(ptr [[ARG]], i64 16) ]
1183; BASIC-NEXT:    [[I3:%.*]] = load i64, ptr [[I2]], align 8
1184; BASIC-NEXT:    [[I4:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 2, i64 [[I]], i64 [[I3]], i32 0
1185; BASIC-NEXT:    [[I5:%.*]] = load i64, ptr [[I4]], align 32
1186; BASIC-NEXT:    [[I6:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 1
1187; BASIC-NEXT:    [[I7:%.*]] = load ptr, ptr [[I6]], align 8
1188; BASIC-NEXT:    [[I8:%.*]] = getelementptr inbounds i64, ptr [[I7]], i64 [[I3]]
1189; BASIC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I8]], i64 8), "nonnull"(ptr [[I7]]), "align"(ptr [[I7]], i64 8) ]
1190; BASIC-NEXT:    store i64 [[I5]], ptr [[I8]], align 8
1191; BASIC-NEXT:    store i64 [[I5]], ptr [[I8]], align 8
1192; BASIC-NEXT:    [[I10:%.*]] = load ptr, ptr [[ARG]], align 8
1193; BASIC-NEXT:    [[I11:%.*]] = load i32, ptr [[I10]], align 4
1194; BASIC-NEXT:    ret i32 [[I11]]
1195;
1196; ALL-LABEL: define {{[^@]+}}@test7
1197; ALL-SAME: (ptr nonnull [[ARG:%.*]], i32 [[ARG1:%.*]]) {
1198; ALL-NEXT:  bb:
1199; ALL-NEXT:    [[I:%.*]] = sext i32 [[ARG1]] to i64
1200; ALL-NEXT:    [[I2:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[ARG]], i64 0, i32 3
1201; ALL-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 280), "align"(ptr [[ARG]], i64 16) ]
1202; ALL-NEXT:    [[I3:%.*]] = load i64, ptr [[I2]], align 8
1203; ALL-NEXT:    [[I4:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 2, i64 [[I]], i64 [[I3]], i32 0
1204; ALL-NEXT:    [[I5:%.*]] = load i64, ptr [[I4]], align 32
1205; ALL-NEXT:    [[I6:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 1
1206; ALL-NEXT:    [[I7:%.*]] = load ptr, ptr [[I6]], align 8
1207; ALL-NEXT:    [[I8:%.*]] = getelementptr inbounds i64, ptr [[I7]], i64 [[I3]]
1208; ALL-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I8]], i64 8), "nonnull"(ptr [[I7]]), "align"(ptr [[I7]], i64 8) ]
1209; ALL-NEXT:    store i64 [[I5]], ptr [[I8]], align 8
1210; ALL-NEXT:    store i64 [[I5]], ptr [[I8]], align 8
1211; ALL-NEXT:    [[I10:%.*]] = load ptr, ptr [[ARG]], align 8
1212; ALL-NEXT:    [[I11:%.*]] = load i32, ptr [[I10]], align 4
1213; ALL-NEXT:    ret i32 [[I11]]
1214;
1215; WITH-AC-LABEL: define {{[^@]+}}@test7
1216; WITH-AC-SAME: (ptr nonnull [[ARG:%.*]], i32 [[ARG1:%.*]]) {
1217; WITH-AC-NEXT:  bb:
1218; WITH-AC-NEXT:    [[I:%.*]] = sext i32 [[ARG1]] to i64
1219; WITH-AC-NEXT:    [[I2:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[ARG]], i64 0, i32 3
1220; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 280), "align"(ptr [[ARG]], i64 16) ]
1221; WITH-AC-NEXT:    [[I3:%.*]] = load i64, ptr [[I2]], align 8
1222; WITH-AC-NEXT:    [[I4:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 2, i64 [[I]], i64 [[I3]], i32 0
1223; WITH-AC-NEXT:    [[I5:%.*]] = load i64, ptr [[I4]], align 32
1224; WITH-AC-NEXT:    [[I6:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 1
1225; WITH-AC-NEXT:    [[I7:%.*]] = load ptr, ptr [[I6]], align 8
1226; WITH-AC-NEXT:    [[I8:%.*]] = getelementptr inbounds i64, ptr [[I7]], i64 [[I3]]
1227; WITH-AC-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I8]], i64 8), "nonnull"(ptr [[I7]]), "align"(ptr [[I7]], i64 8) ]
1228; WITH-AC-NEXT:    store i64 [[I5]], ptr [[I8]], align 8
1229; WITH-AC-NEXT:    store i64 [[I5]], ptr [[I8]], align 8
1230; WITH-AC-NEXT:    [[I10:%.*]] = load ptr, ptr [[ARG]], align 8
1231; WITH-AC-NEXT:    [[I11:%.*]] = load i32, ptr [[I10]], align 4
1232; WITH-AC-NEXT:    ret i32 [[I11]]
1233;
1234; CROSS-BLOCK-LABEL: define {{[^@]+}}@test7
1235; CROSS-BLOCK-SAME: (ptr nonnull [[ARG:%.*]], i32 [[ARG1:%.*]]) {
1236; CROSS-BLOCK-NEXT:  bb:
1237; CROSS-BLOCK-NEXT:    [[I:%.*]] = sext i32 [[ARG1]] to i64
1238; CROSS-BLOCK-NEXT:    [[I2:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[ARG]], i64 0, i32 3
1239; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 280), "align"(ptr [[ARG]], i64 16) ]
1240; CROSS-BLOCK-NEXT:    [[I3:%.*]] = load i64, ptr [[I2]], align 8
1241; CROSS-BLOCK-NEXT:    [[I4:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 2, i64 [[I]], i64 [[I3]], i32 0
1242; CROSS-BLOCK-NEXT:    [[I5:%.*]] = load i64, ptr [[I4]], align 32
1243; CROSS-BLOCK-NEXT:    [[I6:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 1
1244; CROSS-BLOCK-NEXT:    [[I7:%.*]] = load ptr, ptr [[I6]], align 8
1245; CROSS-BLOCK-NEXT:    [[I8:%.*]] = getelementptr inbounds i64, ptr [[I7]], i64 [[I3]]
1246; CROSS-BLOCK-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I8]], i64 8), "nonnull"(ptr [[I7]]), "align"(ptr [[I7]], i64 8) ]
1247; CROSS-BLOCK-NEXT:    store i64 [[I5]], ptr [[I8]], align 8
1248; CROSS-BLOCK-NEXT:    store i64 [[I5]], ptr [[I8]], align 8
1249; CROSS-BLOCK-NEXT:    [[I10:%.*]] = load ptr, ptr [[ARG]], align 8
1250; CROSS-BLOCK-NEXT:    [[I11:%.*]] = load i32, ptr [[I10]], align 4
1251; CROSS-BLOCK-NEXT:    ret i32 [[I11]]
1252;
1253; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test7
1254; FULL-SIMPLIFY-SAME: (ptr nonnull align 16 dereferenceable(280) [[ARG:%.*]], i32 [[ARG1:%.*]]) {
1255; FULL-SIMPLIFY-NEXT:  bb:
1256; FULL-SIMPLIFY-NEXT:    [[I:%.*]] = sext i32 [[ARG1]] to i64
1257; FULL-SIMPLIFY-NEXT:    [[I2:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[ARG]], i64 0, i32 3
1258; FULL-SIMPLIFY-NEXT:    [[I3:%.*]] = load i64, ptr [[I2]], align 8
1259; FULL-SIMPLIFY-NEXT:    [[I4:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 2, i64 [[I]], i64 [[I3]], i32 0
1260; FULL-SIMPLIFY-NEXT:    [[I5:%.*]] = load i64, ptr [[I4]], align 32
1261; FULL-SIMPLIFY-NEXT:    [[I6:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 1
1262; FULL-SIMPLIFY-NEXT:    [[I7:%.*]] = load ptr, ptr [[I6]], align 8
1263; FULL-SIMPLIFY-NEXT:    [[I8:%.*]] = getelementptr inbounds i64, ptr [[I7]], i64 [[I3]]
1264; FULL-SIMPLIFY-NEXT:    call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I8]], i64 8), "nonnull"(ptr [[I7]]), "align"(ptr [[I7]], i64 8) ]
1265; FULL-SIMPLIFY-NEXT:    store i64 [[I5]], ptr [[I8]], align 8
1266; FULL-SIMPLIFY-NEXT:    store i64 [[I5]], ptr [[I8]], align 8
1267; FULL-SIMPLIFY-NEXT:    [[I10:%.*]] = load ptr, ptr [[ARG]], align 8
1268; FULL-SIMPLIFY-NEXT:    [[I11:%.*]] = load i32, ptr [[I10]], align 4
1269; FULL-SIMPLIFY-NEXT:    ret i32 [[I11]]
1270;
1271bb:
1272  %i = sext i32 %arg1 to i64
1273  %i2 = getelementptr inbounds %struct.A, ptr %arg, i64 0, i32 3
1274  %i3 = load i64, ptr %i2, align 8
1275  %i4 = getelementptr inbounds %struct.A, ptr %arg, i64 0, i32 2, i64 %i, i64 %i3, i32 0
1276  %i5 = load i64, ptr %i4, align 32
1277  %i6 = getelementptr inbounds %struct.A, ptr %arg, i64 0, i32 1
1278  %i7 = load ptr, ptr %i6, align 8
1279  %i8 = getelementptr inbounds i64, ptr %i7, i64 %i3
1280  store i64 %i5, ptr %i8, align 8
1281  store i64 %i5, ptr %i8, align 8
1282  %i10 = load ptr, ptr %arg, align 8
1283  %i11 = load i32, ptr %i10, align 4
1284  ret i32 %i11
1285}
1286
1287attributes #0 = { cold nounwind willreturn }
1288attributes #1 = { "no-jump-tables" }
1289attributes #2 = { norecurse nounwind willreturn "less-precise-fpmad" "no-jump-tables" }
1290attributes #3 = { nounwind }
1291attributes #4 = { null_pointer_is_valid }
1292attributes #5 = { cold }
1293