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
8 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
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 }
14 declare void @func(ptr, ptr)
15 declare void @func_cold(ptr) #0
16 declare void @func_strbool(ptr) #1
17 declare void @func_many(ptr) #2
18 declare void @func_argattr(ptr align 8, ptr nonnull) #3
19 declare void @func_argattr2(ptr noundef align 8, ptr noundef nonnull) #3
21 declare void @may_throw()
23 define 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:%.*]]) {
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
50 ; ALL-LABEL: define {{[^@]+}}@test
51 ; ALL-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]], ptr [[P3:%.*]]) {
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]])
78 ; WITH-AC-LABEL: define {{[^@]+}}@test
79 ; WITH-AC-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], ptr [[P2:%.*]], ptr [[P3:%.*]]) {
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
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
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
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)
171 define i32 @test2(ptr %arg, ptr %arg1, ptr %arg2) {
172 ; BASIC-LABEL: define {{[^@]+}}@test2
173 ; BASIC-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) {
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]]
204 ; ALL-LABEL: define {{[^@]+}}@test2
205 ; ALL-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) {
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]]
236 ; WITH-AC-LABEL: define {{[^@]+}}@test2
237 ; WITH-AC-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) {
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]]
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]]
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]]
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
360 define 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]+]] {
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]]
394 ; ALL-LABEL: define {{[^@]+}}@test3
395 ; ALL-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) #[[ATTR4:[0-9]+]] {
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]]
427 ; WITH-AC-LABEL: define {{[^@]+}}@test3
428 ; WITH-AC-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], ptr [[ARG2:%.*]]) #[[ATTR4:[0-9]+]] {
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]]
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]]
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]]
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
555 define dso_local i32 @_Z6squarePi(ptr %P, ptr %P1, i1 %cond) {
556 ; BASIC-LABEL: define {{[^@]+}}@_Z6squarePi
557 ; BASIC-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], i1 [[COND:%.*]]) {
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:%.*]]
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]]
570 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 8) ]
571 ; BASIC-NEXT: store i32 0, ptr [[P]], align 8
572 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ]
573 ; BASIC-NEXT: store i32 0, ptr [[P1]], align 8
574 ; BASIC-NEXT: br label [[C]]
576 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 32) ]
577 ; BASIC-NEXT: store i32 0, ptr [[P]], align 32
578 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 4) ]
579 ; BASIC-NEXT: store i32 0, ptr [[P1]], align 4
580 ; BASIC-NEXT: ret i32 0
582 ; ALL-LABEL: define {{[^@]+}}@_Z6squarePi
583 ; ALL-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], i1 [[COND:%.*]]) {
585 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 4) ]
586 ; ALL-NEXT: store i32 0, ptr [[P]], align 4
587 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ]
588 ; ALL-NEXT: store i32 0, ptr [[P1]], align 8
589 ; ALL-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]]
591 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ]
592 ; ALL-NEXT: store i32 0, ptr [[P]], align 8
593 ; ALL-NEXT: store i32 0, ptr [[P1]], align 4
594 ; ALL-NEXT: br i1 [[COND]], label [[C:%.*]], label [[B]]
596 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 8) ]
597 ; ALL-NEXT: store i32 0, ptr [[P]], align 8
598 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ]
599 ; ALL-NEXT: store i32 0, ptr [[P1]], align 8
600 ; ALL-NEXT: br label [[C]]
602 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 32) ]
603 ; ALL-NEXT: store i32 0, ptr [[P]], align 32
604 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 4) ]
605 ; ALL-NEXT: store i32 0, ptr [[P1]], align 4
606 ; ALL-NEXT: ret i32 0
608 ; WITH-AC-LABEL: define {{[^@]+}}@_Z6squarePi
609 ; WITH-AC-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], i1 [[COND:%.*]]) {
611 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 4) ]
612 ; WITH-AC-NEXT: store i32 0, ptr [[P]], align 4
613 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ]
614 ; WITH-AC-NEXT: store i32 0, ptr [[P1]], align 8
615 ; WITH-AC-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]]
617 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ]
618 ; WITH-AC-NEXT: store i32 0, ptr [[P]], align 8
619 ; WITH-AC-NEXT: store i32 0, ptr [[P1]], align 4
620 ; WITH-AC-NEXT: br i1 [[COND]], label [[C:%.*]], label [[B]]
622 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 8) ]
623 ; WITH-AC-NEXT: store i32 0, ptr [[P]], align 8
624 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ]
625 ; WITH-AC-NEXT: store i32 0, ptr [[P1]], align 8
626 ; WITH-AC-NEXT: br label [[C]]
628 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 32) ]
629 ; WITH-AC-NEXT: store i32 0, ptr [[P]], align 32
630 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 4) ]
631 ; WITH-AC-NEXT: store i32 0, ptr [[P1]], align 4
632 ; WITH-AC-NEXT: ret i32 0
634 ; CROSS-BLOCK-LABEL: define {{[^@]+}}@_Z6squarePi
635 ; CROSS-BLOCK-SAME: (ptr [[P:%.*]], ptr [[P1:%.*]], i1 [[COND:%.*]]) {
636 ; CROSS-BLOCK-NEXT: bb:
637 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P]], i64 4), "nonnull"(ptr [[P]]), "align"(ptr [[P]], i64 4) ]
638 ; CROSS-BLOCK-NEXT: store i32 0, ptr [[P]], align 4
639 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[P1]], i64 4), "nonnull"(ptr [[P1]]), "align"(ptr [[P1]], i64 8) ]
640 ; CROSS-BLOCK-NEXT: store i32 0, ptr [[P1]], align 8
641 ; CROSS-BLOCK-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]]
643 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ]
644 ; CROSS-BLOCK-NEXT: store i32 0, ptr [[P]], align 8
645 ; CROSS-BLOCK-NEXT: store i32 0, ptr [[P1]], align 4
646 ; CROSS-BLOCK-NEXT: br i1 [[COND]], label [[C:%.*]], label [[B]]
648 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ]
649 ; CROSS-BLOCK-NEXT: store i32 0, ptr [[P]], align 8
650 ; CROSS-BLOCK-NEXT: store i32 0, ptr [[P1]], align 8
651 ; CROSS-BLOCK-NEXT: br label [[C]]
653 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 32) ]
654 ; CROSS-BLOCK-NEXT: store i32 0, ptr [[P]], align 32
655 ; CROSS-BLOCK-NEXT: store i32 0, ptr [[P1]], align 4
656 ; CROSS-BLOCK-NEXT: ret i32 0
658 ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@_Z6squarePi
659 ; FULL-SIMPLIFY-SAME: (ptr nonnull align 4 dereferenceable(4) [[P:%.*]], ptr nonnull align 8 dereferenceable(4) [[P1:%.*]], i1 [[COND:%.*]]) {
660 ; FULL-SIMPLIFY-NEXT: bb:
661 ; FULL-SIMPLIFY-NEXT: store i32 0, ptr [[P]], align 4
662 ; FULL-SIMPLIFY-NEXT: store i32 0, ptr [[P1]], align 8
663 ; FULL-SIMPLIFY-NEXT: br i1 [[COND]], label [[A:%.*]], label [[B:%.*]]
665 ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P]], i64 8) ]
666 ; FULL-SIMPLIFY-NEXT: store i32 0, ptr [[P]], align 8
667 ; FULL-SIMPLIFY-NEXT: store i32 0, ptr [[P1]], align 4
668 ; FULL-SIMPLIFY-NEXT: br i1 [[COND]], label [[C:%.*]], label [[B]]
670 ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "ignore"(ptr undef, i64 4), "ignore"(ptr undef), "align"(ptr [[P]], i64 8) ]
671 ; FULL-SIMPLIFY-NEXT: store i32 0, ptr [[P]], align 8
672 ; FULL-SIMPLIFY-NEXT: store i32 0, ptr [[P1]], align 8
673 ; FULL-SIMPLIFY-NEXT: br label [[C]]
675 ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "ignore"(ptr undef, i64 4), "ignore"(ptr undef), "align"(ptr [[P]], i64 32) ]
676 ; FULL-SIMPLIFY-NEXT: store i32 0, ptr [[P]], align 32
677 ; FULL-SIMPLIFY-NEXT: store i32 0, ptr [[P1]], align 4
678 ; FULL-SIMPLIFY-NEXT: ret i32 0
681 store i32 0, ptr %P, align 4
682 store i32 0, ptr %P1, align 8
683 br i1 %cond, label %A, label %B
686 store i32 0, ptr %P, align 8
687 store i32 0, ptr %P1, align 4
688 br i1 %cond, label %C, label %B
691 store i32 0, ptr %P, align 8
692 store i32 0, ptr %P1, align 8
696 store i32 0, ptr %P, align 32
697 store i32 0, ptr %P1, align 4
701 define dso_local i32 @test4A(ptr %arg, ptr %arg1, i32 %arg2, i32 %arg3) {
702 ; BASIC-LABEL: define {{[^@]+}}@test4A
703 ; BASIC-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) {
705 ; BASIC-NEXT: [[I:%.*]] = icmp ne ptr [[ARG1]], null
706 ; BASIC-NEXT: br i1 [[I]], label [[BB4:%.*]], label [[BB10:%.*]]
708 ; BASIC-NEXT: [[I5:%.*]] = add nsw i32 [[ARG3]], [[ARG2]]
709 ; BASIC-NEXT: call void @may_throw()
710 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ]
711 ; BASIC-NEXT: [[I6:%.*]] = load i32, ptr [[ARG]], align 4
712 ; BASIC-NEXT: [[I7:%.*]] = add nsw i32 [[I5]], [[I6]]
713 ; BASIC-NEXT: store i32 0, ptr [[ARG]], align 4
714 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG1]], i64 4), "nonnull"(ptr [[ARG1]]), "align"(ptr [[ARG1]], i64 4) ]
715 ; BASIC-NEXT: [[I8:%.*]] = load i32, ptr [[ARG1]], align 4
716 ; BASIC-NEXT: [[I9:%.*]] = add nsw i32 [[I7]], [[I8]]
717 ; BASIC-NEXT: call void @may_throw()
718 ; BASIC-NEXT: store i32 [[I9]], ptr [[ARG1]], align 4
719 ; BASIC-NEXT: br label [[BB10]]
721 ; BASIC-NEXT: ret i32 0
723 ; ALL-LABEL: define {{[^@]+}}@test4A
724 ; ALL-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) {
726 ; ALL-NEXT: [[I:%.*]] = icmp ne ptr [[ARG1]], null
727 ; ALL-NEXT: br i1 [[I]], label [[BB4:%.*]], label [[BB10:%.*]]
729 ; ALL-NEXT: [[I5:%.*]] = add nsw i32 [[ARG3]], [[ARG2]]
730 ; ALL-NEXT: call void @may_throw()
731 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ]
732 ; ALL-NEXT: [[I6:%.*]] = load i32, ptr [[ARG]], align 4
733 ; ALL-NEXT: [[I7:%.*]] = add nsw i32 [[I5]], [[I6]]
734 ; ALL-NEXT: store i32 0, ptr [[ARG]], align 4
735 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG1]], i64 4), "nonnull"(ptr [[ARG1]]), "align"(ptr [[ARG1]], i64 4) ]
736 ; ALL-NEXT: [[I8:%.*]] = load i32, ptr [[ARG1]], align 4
737 ; ALL-NEXT: [[I9:%.*]] = add nsw i32 [[I7]], [[I8]]
738 ; ALL-NEXT: call void @may_throw()
739 ; ALL-NEXT: store i32 [[I9]], ptr [[ARG1]], align 4
740 ; ALL-NEXT: br label [[BB10]]
742 ; ALL-NEXT: ret i32 0
744 ; WITH-AC-LABEL: define {{[^@]+}}@test4A
745 ; WITH-AC-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) {
747 ; WITH-AC-NEXT: [[I:%.*]] = icmp ne ptr [[ARG1]], null
748 ; WITH-AC-NEXT: br i1 [[I]], label [[BB4:%.*]], label [[BB10:%.*]]
750 ; WITH-AC-NEXT: [[I5:%.*]] = add nsw i32 [[ARG3]], [[ARG2]]
751 ; WITH-AC-NEXT: call void @may_throw()
752 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ]
753 ; WITH-AC-NEXT: [[I6:%.*]] = load i32, ptr [[ARG]], align 4
754 ; WITH-AC-NEXT: [[I7:%.*]] = add nsw i32 [[I5]], [[I6]]
755 ; WITH-AC-NEXT: store i32 0, ptr [[ARG]], align 4
756 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG1]], i64 4), "nonnull"(ptr [[ARG1]]), "align"(ptr [[ARG1]], i64 4) ]
757 ; WITH-AC-NEXT: [[I8:%.*]] = load i32, ptr [[ARG1]], align 4
758 ; WITH-AC-NEXT: [[I9:%.*]] = add nsw i32 [[I7]], [[I8]]
759 ; WITH-AC-NEXT: call void @may_throw()
760 ; WITH-AC-NEXT: store i32 [[I9]], ptr [[ARG1]], align 4
761 ; WITH-AC-NEXT: br label [[BB10]]
763 ; WITH-AC-NEXT: ret i32 0
765 ; CROSS-BLOCK-LABEL: define {{[^@]+}}@test4A
766 ; CROSS-BLOCK-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) {
767 ; CROSS-BLOCK-NEXT: bb:
768 ; CROSS-BLOCK-NEXT: [[I:%.*]] = icmp ne ptr [[ARG1]], null
769 ; CROSS-BLOCK-NEXT: br i1 [[I]], label [[BB4:%.*]], label [[BB10:%.*]]
771 ; CROSS-BLOCK-NEXT: [[I5:%.*]] = add nsw i32 [[ARG3]], [[ARG2]]
772 ; CROSS-BLOCK-NEXT: call void @may_throw()
773 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 4), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ]
774 ; CROSS-BLOCK-NEXT: [[I6:%.*]] = load i32, ptr [[ARG]], align 4
775 ; CROSS-BLOCK-NEXT: [[I7:%.*]] = add nsw i32 [[I5]], [[I6]]
776 ; CROSS-BLOCK-NEXT: store i32 0, ptr [[ARG]], align 4
777 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG1]], i64 4), "nonnull"(ptr [[ARG1]]), "align"(ptr [[ARG1]], i64 4) ]
778 ; CROSS-BLOCK-NEXT: [[I8:%.*]] = load i32, ptr [[ARG1]], align 4
779 ; CROSS-BLOCK-NEXT: [[I9:%.*]] = add nsw i32 [[I7]], [[I8]]
780 ; CROSS-BLOCK-NEXT: call void @may_throw()
781 ; CROSS-BLOCK-NEXT: store i32 [[I9]], ptr [[ARG1]], align 4
782 ; CROSS-BLOCK-NEXT: br label [[BB10]]
784 ; CROSS-BLOCK-NEXT: ret i32 0
786 ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test4A
787 ; FULL-SIMPLIFY-SAME: (ptr [[ARG:%.*]], ptr [[ARG1:%.*]], i32 [[ARG2:%.*]], i32 [[ARG3:%.*]]) {
788 ; FULL-SIMPLIFY-NEXT: bb:
789 ; FULL-SIMPLIFY-NEXT: [[I:%.*]] = icmp ne ptr [[ARG1]], null
790 ; FULL-SIMPLIFY-NEXT: br i1 [[I]], label [[BB4:%.*]], label [[BB10:%.*]]
791 ; FULL-SIMPLIFY: bb4:
792 ; FULL-SIMPLIFY-NEXT: [[I5:%.*]] = add nsw i32 [[ARG3]], [[ARG2]]
793 ; FULL-SIMPLIFY-NEXT: call void @may_throw()
794 ; 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) ]
795 ; FULL-SIMPLIFY-NEXT: [[I6:%.*]] = load i32, ptr [[ARG]], align 4
796 ; FULL-SIMPLIFY-NEXT: [[I7:%.*]] = add nsw i32 [[I5]], [[I6]]
797 ; FULL-SIMPLIFY-NEXT: store i32 0, ptr [[ARG]], align 4
798 ; FULL-SIMPLIFY-NEXT: [[I8:%.*]] = load i32, ptr [[ARG1]], align 4
799 ; FULL-SIMPLIFY-NEXT: [[I9:%.*]] = add nsw i32 [[I7]], [[I8]]
800 ; FULL-SIMPLIFY-NEXT: call void @may_throw()
801 ; FULL-SIMPLIFY-NEXT: store i32 [[I9]], ptr [[ARG1]], align 4
802 ; FULL-SIMPLIFY-NEXT: br label [[BB10]]
803 ; FULL-SIMPLIFY: bb10:
804 ; FULL-SIMPLIFY-NEXT: ret i32 0
807 %i = icmp ne ptr %arg1, null
808 br i1 %i, label %bb4, label %bb10
811 %i5 = add nsw i32 %arg3, %arg2
812 call void @may_throw()
813 %i6 = load i32, ptr %arg, align 4
814 %i7 = add nsw i32 %i5, %i6
815 store i32 0, ptr %arg, align 4
816 %i8 = load i32, ptr %arg1, align 4
817 %i9 = add nsw i32 %i7, %i8
818 call void @may_throw()
819 store i32 %i9, ptr %arg1, align 4
822 bb10: ; preds = %bb4, %bb
826 declare void @may_throwv2(ptr)
828 define dso_local i32 @terminator(ptr %P) personality ptr @__gxx_personality_v0 {
829 ; BASIC-LABEL: define {{[^@]+}}@terminator
830 ; BASIC-SAME: (ptr [[P:%.*]]) personality ptr @__gxx_personality_v0 {
832 ; BASIC-NEXT: invoke void @may_throwv2(ptr nonnull [[P]])
833 ; BASIC-NEXT: to label [[EXIT:%.*]] unwind label [[CATCH:%.*]]
835 ; BASIC-NEXT: [[V:%.*]] = landingpad { ptr, i32 }
836 ; BASIC-NEXT: catch ptr null
837 ; BASIC-NEXT: br label [[EXIT]]
839 ; BASIC-NEXT: [[DOT0:%.*]] = phi i32 [ 1, [[BB:%.*]] ], [ 0, [[CATCH]] ]
840 ; BASIC-NEXT: ret i32 [[DOT0]]
842 ; ALL-LABEL: define {{[^@]+}}@terminator
843 ; ALL-SAME: (ptr [[P:%.*]]) personality ptr @__gxx_personality_v0 {
845 ; ALL-NEXT: invoke void @may_throwv2(ptr nonnull [[P]])
846 ; ALL-NEXT: to label [[EXIT:%.*]] unwind label [[CATCH:%.*]]
848 ; ALL-NEXT: [[V:%.*]] = landingpad { ptr, i32 }
849 ; ALL-NEXT: catch ptr null
850 ; ALL-NEXT: br label [[EXIT]]
852 ; ALL-NEXT: [[DOT0:%.*]] = phi i32 [ 1, [[BB:%.*]] ], [ 0, [[CATCH]] ]
853 ; ALL-NEXT: ret i32 [[DOT0]]
855 ; WITH-AC-LABEL: define {{[^@]+}}@terminator
856 ; WITH-AC-SAME: (ptr [[P:%.*]]) personality ptr @__gxx_personality_v0 {
858 ; WITH-AC-NEXT: invoke void @may_throwv2(ptr nonnull [[P]])
859 ; WITH-AC-NEXT: to label [[EXIT:%.*]] unwind label [[CATCH:%.*]]
861 ; WITH-AC-NEXT: [[V:%.*]] = landingpad { ptr, i32 }
862 ; WITH-AC-NEXT: catch ptr null
863 ; WITH-AC-NEXT: br label [[EXIT]]
865 ; WITH-AC-NEXT: [[DOT0:%.*]] = phi i32 [ 1, [[BB:%.*]] ], [ 0, [[CATCH]] ]
866 ; WITH-AC-NEXT: ret i32 [[DOT0]]
868 ; CROSS-BLOCK-LABEL: define {{[^@]+}}@terminator
869 ; CROSS-BLOCK-SAME: (ptr [[P:%.*]]) personality ptr @__gxx_personality_v0 {
870 ; CROSS-BLOCK-NEXT: bb:
871 ; CROSS-BLOCK-NEXT: invoke void @may_throwv2(ptr nonnull [[P]])
872 ; CROSS-BLOCK-NEXT: to label [[EXIT:%.*]] unwind label [[CATCH:%.*]]
873 ; CROSS-BLOCK: Catch:
874 ; CROSS-BLOCK-NEXT: [[V:%.*]] = landingpad { ptr, i32 }
875 ; CROSS-BLOCK-NEXT: catch ptr null
876 ; CROSS-BLOCK-NEXT: br label [[EXIT]]
878 ; CROSS-BLOCK-NEXT: [[DOT0:%.*]] = phi i32 [ 1, [[BB:%.*]] ], [ 0, [[CATCH]] ]
879 ; CROSS-BLOCK-NEXT: ret i32 [[DOT0]]
881 ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@terminator
882 ; FULL-SIMPLIFY-SAME: (ptr [[P:%.*]]) personality ptr @__gxx_personality_v0 {
883 ; FULL-SIMPLIFY-NEXT: bb:
884 ; FULL-SIMPLIFY-NEXT: invoke void @may_throwv2(ptr nonnull [[P]])
885 ; FULL-SIMPLIFY-NEXT: to label [[EXIT:%.*]] unwind label [[CATCH:%.*]]
886 ; FULL-SIMPLIFY: Catch:
887 ; FULL-SIMPLIFY-NEXT: [[V:%.*]] = landingpad { ptr, i32 }
888 ; FULL-SIMPLIFY-NEXT: catch ptr null
889 ; FULL-SIMPLIFY-NEXT: br label [[EXIT]]
890 ; FULL-SIMPLIFY: Exit:
891 ; FULL-SIMPLIFY-NEXT: [[DOT0:%.*]] = phi i32 [ 1, [[BB:%.*]] ], [ 0, [[CATCH]] ]
892 ; FULL-SIMPLIFY-NEXT: ret i32 [[DOT0]]
895 invoke void @may_throwv2(ptr nonnull %P)
896 to label %Exit unwind label %Catch
899 %v = landingpad { ptr, i32 }
903 Exit: ; preds = %Catch, %bb
904 %.0 = phi i32 [ 1, %bb ], [ 0, %Catch ]
908 declare dso_local i32 @__gxx_personality_v0(...)
910 define dso_local i32 @test5(ptr %arg, i32 %arg1) {
911 ; BASIC-LABEL: define {{[^@]+}}@test5
912 ; BASIC-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]]) {
914 ; BASIC-NEXT: [[I3:%.*]] = sext i32 [[ARG1]] to i64
915 ; BASIC-NEXT: [[I4:%.*]] = getelementptr inbounds i16, ptr [[ARG]], i64 [[I3]]
916 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I4]], i64 2), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 8) ]
917 ; BASIC-NEXT: [[I5:%.*]] = load i16, ptr [[I4]], align 2
918 ; BASIC-NEXT: [[A:%.*]] = load i16, ptr [[I4]], align 4
919 ; BASIC-NEXT: [[I6:%.*]] = sext i16 [[I5]] to i64
920 ; BASIC-NEXT: [[I7:%.*]] = getelementptr inbounds i64, ptr [[ARG]], i64 [[I6]]
921 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I7]], i64 8) ]
922 ; BASIC-NEXT: [[I8:%.*]] = load i64, ptr [[I7]], align 16
923 ; BASIC-NEXT: [[B:%.*]] = load i64, ptr [[I7]], align 32
924 ; BASIC-NEXT: [[I9:%.*]] = trunc i64 [[I8]] to i32
925 ; BASIC-NEXT: ret i32 [[I9]]
927 ; ALL-LABEL: define {{[^@]+}}@test5
928 ; ALL-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]]) {
930 ; ALL-NEXT: [[I3:%.*]] = sext i32 [[ARG1]] to i64
931 ; ALL-NEXT: [[I4:%.*]] = getelementptr inbounds i16, ptr [[ARG]], i64 [[I3]]
932 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I4]], i64 2), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 8) ]
933 ; ALL-NEXT: [[I5:%.*]] = load i16, ptr [[I4]], align 2
934 ; ALL-NEXT: [[A:%.*]] = load i16, ptr [[I4]], align 4
935 ; ALL-NEXT: [[I6:%.*]] = sext i16 [[I5]] to i64
936 ; ALL-NEXT: [[I7:%.*]] = getelementptr inbounds i64, ptr [[ARG]], i64 [[I6]]
937 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I7]], i64 8) ]
938 ; ALL-NEXT: [[I8:%.*]] = load i64, ptr [[I7]], align 16
939 ; ALL-NEXT: [[B:%.*]] = load i64, ptr [[I7]], align 32
940 ; ALL-NEXT: [[I9:%.*]] = trunc i64 [[I8]] to i32
941 ; ALL-NEXT: ret i32 [[I9]]
943 ; WITH-AC-LABEL: define {{[^@]+}}@test5
944 ; WITH-AC-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]]) {
946 ; WITH-AC-NEXT: [[I3:%.*]] = sext i32 [[ARG1]] to i64
947 ; WITH-AC-NEXT: [[I4:%.*]] = getelementptr inbounds i16, ptr [[ARG]], i64 [[I3]]
948 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I4]], i64 2), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 8) ]
949 ; WITH-AC-NEXT: [[I5:%.*]] = load i16, ptr [[I4]], align 2
950 ; WITH-AC-NEXT: [[A:%.*]] = load i16, ptr [[I4]], align 4
951 ; WITH-AC-NEXT: [[I6:%.*]] = sext i16 [[I5]] to i64
952 ; WITH-AC-NEXT: [[I7:%.*]] = getelementptr inbounds i64, ptr [[ARG]], i64 [[I6]]
953 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I7]], i64 8) ]
954 ; WITH-AC-NEXT: [[I8:%.*]] = load i64, ptr [[I7]], align 16
955 ; WITH-AC-NEXT: [[B:%.*]] = load i64, ptr [[I7]], align 32
956 ; WITH-AC-NEXT: [[I9:%.*]] = trunc i64 [[I8]] to i32
957 ; WITH-AC-NEXT: ret i32 [[I9]]
959 ; CROSS-BLOCK-LABEL: define {{[^@]+}}@test5
960 ; CROSS-BLOCK-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]]) {
961 ; CROSS-BLOCK-NEXT: bb:
962 ; CROSS-BLOCK-NEXT: [[I3:%.*]] = sext i32 [[ARG1]] to i64
963 ; CROSS-BLOCK-NEXT: [[I4:%.*]] = getelementptr inbounds i16, ptr [[ARG]], i64 [[I3]]
964 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I4]], i64 2), "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 8) ]
965 ; CROSS-BLOCK-NEXT: [[I5:%.*]] = load i16, ptr [[I4]], align 2
966 ; CROSS-BLOCK-NEXT: [[A:%.*]] = load i16, ptr [[I4]], align 4
967 ; CROSS-BLOCK-NEXT: [[I6:%.*]] = sext i16 [[I5]] to i64
968 ; CROSS-BLOCK-NEXT: [[I7:%.*]] = getelementptr inbounds i64, ptr [[ARG]], i64 [[I6]]
969 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I7]], i64 8) ]
970 ; CROSS-BLOCK-NEXT: [[I8:%.*]] = load i64, ptr [[I7]], align 16
971 ; CROSS-BLOCK-NEXT: [[B:%.*]] = load i64, ptr [[I7]], align 32
972 ; CROSS-BLOCK-NEXT: [[I9:%.*]] = trunc i64 [[I8]] to i32
973 ; CROSS-BLOCK-NEXT: ret i32 [[I9]]
975 ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test5
976 ; FULL-SIMPLIFY-SAME: (ptr nonnull align 8 [[ARG:%.*]], i32 [[ARG1:%.*]]) {
977 ; FULL-SIMPLIFY-NEXT: bb:
978 ; FULL-SIMPLIFY-NEXT: [[I3:%.*]] = sext i32 [[ARG1]] to i64
979 ; FULL-SIMPLIFY-NEXT: [[I4:%.*]] = getelementptr inbounds i16, ptr [[ARG]], i64 [[I3]]
980 ; FULL-SIMPLIFY-NEXT: [[I5:%.*]] = load i16, ptr [[I4]], align 2
981 ; FULL-SIMPLIFY-NEXT: [[A:%.*]] = load i16, ptr [[I4]], align 4
982 ; FULL-SIMPLIFY-NEXT: [[I6:%.*]] = sext i16 [[I5]] to i64
983 ; FULL-SIMPLIFY-NEXT: [[I7:%.*]] = getelementptr inbounds i64, ptr [[ARG]], i64 [[I6]]
984 ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I4]], i64 2), "dereferenceable"(ptr [[I7]], i64 8) ]
985 ; FULL-SIMPLIFY-NEXT: [[I8:%.*]] = load i64, ptr [[I7]], align 16
986 ; FULL-SIMPLIFY-NEXT: [[B:%.*]] = load i64, ptr [[I7]], align 32
987 ; FULL-SIMPLIFY-NEXT: [[I9:%.*]] = trunc i64 [[I8]] to i32
988 ; FULL-SIMPLIFY-NEXT: ret i32 [[I9]]
991 %i3 = sext i32 %arg1 to i64
992 %i4 = getelementptr inbounds i16, ptr %arg, i64 %i3
993 %i5 = load i16, ptr %i4, align 2
994 %A = load i16, ptr %i4, align 4
995 %i6 = sext i16 %i5 to i64
996 %i7 = getelementptr inbounds i64, ptr %arg, i64 %i6
997 %i8 = load i64, ptr %i7, align 16
998 %B = load i64, ptr %i7, align 32
999 %i9 = trunc i64 %i8 to i32
1003 define i32 @test6(ptr %arg, i32 %arg1, ptr %arg2) {
1004 ; BASIC-LABEL: define {{[^@]+}}@test6
1005 ; BASIC-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]], ptr [[ARG2:%.*]]) {
1007 ; BASIC-NEXT: br label [[BB3:%.*]]
1009 ; BASIC-NEXT: [[DOT0:%.*]] = phi i32 [ 0, [[BB:%.*]] ], [ [[I14:%.*]], [[BB4:%.*]] ]
1010 ; BASIC-NEXT: [[I:%.*]] = icmp slt i32 [[DOT0]], [[ARG1]]
1011 ; BASIC-NEXT: br i1 [[I]], label [[BB4]], label [[BB15:%.*]]
1013 ; BASIC-NEXT: [[I5:%.*]] = add nsw i32 [[ARG1]], [[DOT0]]
1014 ; BASIC-NEXT: [[I6:%.*]] = sext i32 [[I5]] to i64
1015 ; BASIC-NEXT: [[I7:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I6]]
1016 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ]
1017 ; BASIC-NEXT: [[I8:%.*]] = load i32, ptr [[I7]], align 4
1018 ; BASIC-NEXT: [[I9:%.*]] = mul nsw i32 [[DOT0]], [[I8]]
1019 ; BASIC-NEXT: [[I10:%.*]] = sext i32 [[DOT0]] to i64
1020 ; BASIC-NEXT: [[I11:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I10]]
1021 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I11]], i64 4) ]
1022 ; BASIC-NEXT: [[I12:%.*]] = load i32, ptr [[I11]], align 4
1023 ; BASIC-NEXT: [[I13:%.*]] = add nsw i32 [[I12]], [[I9]]
1024 ; BASIC-NEXT: store i32 [[I13]], ptr [[I11]], align 4
1025 ; BASIC-NEXT: [[I14]] = add nsw i32 [[DOT0]], 1
1026 ; BASIC-NEXT: br label [[BB3]]
1028 ; BASIC-NEXT: [[I16:%.*]] = sext i32 [[ARG1]] to i64
1029 ; BASIC-NEXT: [[I17:%.*]] = getelementptr inbounds i32, ptr [[ARG2]], i64 [[I16]]
1030 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG2]]), "align"(ptr [[ARG2]], i64 4) ]
1031 ; BASIC-NEXT: [[I18:%.*]] = load i32, ptr [[I17]], align 4
1032 ; BASIC-NEXT: ret i32 [[I18]]
1034 ; ALL-LABEL: define {{[^@]+}}@test6
1035 ; ALL-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]], ptr [[ARG2:%.*]]) {
1037 ; ALL-NEXT: br label [[BB3:%.*]]
1039 ; ALL-NEXT: [[DOT0:%.*]] = phi i32 [ 0, [[BB:%.*]] ], [ [[I14:%.*]], [[BB4:%.*]] ]
1040 ; ALL-NEXT: [[I:%.*]] = icmp slt i32 [[DOT0]], [[ARG1]]
1041 ; ALL-NEXT: br i1 [[I]], label [[BB4]], label [[BB15:%.*]]
1043 ; ALL-NEXT: [[I5:%.*]] = add nsw i32 [[ARG1]], [[DOT0]]
1044 ; ALL-NEXT: [[I6:%.*]] = sext i32 [[I5]] to i64
1045 ; ALL-NEXT: [[I7:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I6]]
1046 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ]
1047 ; ALL-NEXT: [[I8:%.*]] = load i32, ptr [[I7]], align 4
1048 ; ALL-NEXT: [[I9:%.*]] = mul nsw i32 [[DOT0]], [[I8]]
1049 ; ALL-NEXT: [[I10:%.*]] = sext i32 [[DOT0]] to i64
1050 ; ALL-NEXT: [[I11:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I10]]
1051 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I11]], i64 4) ]
1052 ; ALL-NEXT: [[I12:%.*]] = load i32, ptr [[I11]], align 4
1053 ; ALL-NEXT: [[I13:%.*]] = add nsw i32 [[I12]], [[I9]]
1054 ; ALL-NEXT: store i32 [[I13]], ptr [[I11]], align 4
1055 ; ALL-NEXT: [[I14]] = add nsw i32 [[DOT0]], 1
1056 ; ALL-NEXT: br label [[BB3]]
1058 ; ALL-NEXT: [[I16:%.*]] = sext i32 [[ARG1]] to i64
1059 ; ALL-NEXT: [[I17:%.*]] = getelementptr inbounds i32, ptr [[ARG2]], i64 [[I16]]
1060 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG2]]), "align"(ptr [[ARG2]], i64 4) ]
1061 ; ALL-NEXT: [[I18:%.*]] = load i32, ptr [[I17]], align 4
1062 ; ALL-NEXT: ret i32 [[I18]]
1064 ; WITH-AC-LABEL: define {{[^@]+}}@test6
1065 ; WITH-AC-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]], ptr [[ARG2:%.*]]) {
1067 ; WITH-AC-NEXT: br label [[BB3:%.*]]
1069 ; WITH-AC-NEXT: [[DOT0:%.*]] = phi i32 [ 0, [[BB:%.*]] ], [ [[I14:%.*]], [[BB4:%.*]] ]
1070 ; WITH-AC-NEXT: [[I:%.*]] = icmp slt i32 [[DOT0]], [[ARG1]]
1071 ; WITH-AC-NEXT: br i1 [[I]], label [[BB4]], label [[BB15:%.*]]
1073 ; WITH-AC-NEXT: [[I5:%.*]] = add nsw i32 [[ARG1]], [[DOT0]]
1074 ; WITH-AC-NEXT: [[I6:%.*]] = sext i32 [[I5]] to i64
1075 ; WITH-AC-NEXT: [[I7:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I6]]
1076 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ]
1077 ; WITH-AC-NEXT: [[I8:%.*]] = load i32, ptr [[I7]], align 4
1078 ; WITH-AC-NEXT: [[I9:%.*]] = mul nsw i32 [[DOT0]], [[I8]]
1079 ; WITH-AC-NEXT: [[I10:%.*]] = sext i32 [[DOT0]] to i64
1080 ; WITH-AC-NEXT: [[I11:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I10]]
1081 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I11]], i64 4) ]
1082 ; WITH-AC-NEXT: [[I12:%.*]] = load i32, ptr [[I11]], align 4
1083 ; WITH-AC-NEXT: [[I13:%.*]] = add nsw i32 [[I12]], [[I9]]
1084 ; WITH-AC-NEXT: store i32 [[I13]], ptr [[I11]], align 4
1085 ; WITH-AC-NEXT: [[I14]] = add nsw i32 [[DOT0]], 1
1086 ; WITH-AC-NEXT: br label [[BB3]]
1088 ; WITH-AC-NEXT: [[I16:%.*]] = sext i32 [[ARG1]] to i64
1089 ; WITH-AC-NEXT: [[I17:%.*]] = getelementptr inbounds i32, ptr [[ARG2]], i64 [[I16]]
1090 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG2]]), "align"(ptr [[ARG2]], i64 4) ]
1091 ; WITH-AC-NEXT: [[I18:%.*]] = load i32, ptr [[I17]], align 4
1092 ; WITH-AC-NEXT: ret i32 [[I18]]
1094 ; CROSS-BLOCK-LABEL: define {{[^@]+}}@test6
1095 ; CROSS-BLOCK-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]], ptr [[ARG2:%.*]]) {
1096 ; CROSS-BLOCK-NEXT: bb:
1097 ; CROSS-BLOCK-NEXT: br label [[BB3:%.*]]
1099 ; CROSS-BLOCK-NEXT: [[DOT0:%.*]] = phi i32 [ 0, [[BB:%.*]] ], [ [[I14:%.*]], [[BB4:%.*]] ]
1100 ; CROSS-BLOCK-NEXT: [[I:%.*]] = icmp slt i32 [[DOT0]], [[ARG1]]
1101 ; CROSS-BLOCK-NEXT: br i1 [[I]], label [[BB4]], label [[BB15:%.*]]
1103 ; CROSS-BLOCK-NEXT: [[I5:%.*]] = add nsw i32 [[ARG1]], [[DOT0]]
1104 ; CROSS-BLOCK-NEXT: [[I6:%.*]] = sext i32 [[I5]] to i64
1105 ; CROSS-BLOCK-NEXT: [[I7:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I6]]
1106 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4) ]
1107 ; CROSS-BLOCK-NEXT: [[I8:%.*]] = load i32, ptr [[I7]], align 4
1108 ; CROSS-BLOCK-NEXT: [[I9:%.*]] = mul nsw i32 [[DOT0]], [[I8]]
1109 ; CROSS-BLOCK-NEXT: [[I10:%.*]] = sext i32 [[DOT0]] to i64
1110 ; CROSS-BLOCK-NEXT: [[I11:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I10]]
1111 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I11]], i64 4) ]
1112 ; CROSS-BLOCK-NEXT: [[I12:%.*]] = load i32, ptr [[I11]], align 4
1113 ; CROSS-BLOCK-NEXT: [[I13:%.*]] = add nsw i32 [[I12]], [[I9]]
1114 ; CROSS-BLOCK-NEXT: store i32 [[I13]], ptr [[I11]], align 4
1115 ; CROSS-BLOCK-NEXT: [[I14]] = add nsw i32 [[DOT0]], 1
1116 ; CROSS-BLOCK-NEXT: br label [[BB3]]
1117 ; CROSS-BLOCK: bb15:
1118 ; CROSS-BLOCK-NEXT: [[I16:%.*]] = sext i32 [[ARG1]] to i64
1119 ; CROSS-BLOCK-NEXT: [[I17:%.*]] = getelementptr inbounds i32, ptr [[ARG2]], i64 [[I16]]
1120 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG2]]), "align"(ptr [[ARG2]], i64 4) ]
1121 ; CROSS-BLOCK-NEXT: [[I18:%.*]] = load i32, ptr [[I17]], align 4
1122 ; CROSS-BLOCK-NEXT: ret i32 [[I18]]
1124 ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test6
1125 ; FULL-SIMPLIFY-SAME: (ptr [[ARG:%.*]], i32 [[ARG1:%.*]], ptr [[ARG2:%.*]]) {
1126 ; FULL-SIMPLIFY-NEXT: bb:
1127 ; FULL-SIMPLIFY-NEXT: br label [[BB3:%.*]]
1128 ; FULL-SIMPLIFY: bb3:
1129 ; FULL-SIMPLIFY-NEXT: [[DOT0:%.*]] = phi i32 [ 0, [[BB:%.*]] ], [ [[I14:%.*]], [[BB4:%.*]] ]
1130 ; FULL-SIMPLIFY-NEXT: [[I:%.*]] = icmp slt i32 [[DOT0]], [[ARG1]]
1131 ; FULL-SIMPLIFY-NEXT: br i1 [[I]], label [[BB4]], label [[BB15:%.*]]
1132 ; FULL-SIMPLIFY: bb4:
1133 ; FULL-SIMPLIFY-NEXT: [[I5:%.*]] = add nsw i32 [[ARG1]], [[DOT0]]
1134 ; FULL-SIMPLIFY-NEXT: [[I6:%.*]] = sext i32 [[I5]] to i64
1135 ; FULL-SIMPLIFY-NEXT: [[I7:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I6]]
1136 ; FULL-SIMPLIFY-NEXT: [[I8:%.*]] = load i32, ptr [[I7]], align 4
1137 ; FULL-SIMPLIFY-NEXT: [[I9:%.*]] = mul nsw i32 [[DOT0]], [[I8]]
1138 ; FULL-SIMPLIFY-NEXT: [[I10:%.*]] = sext i32 [[DOT0]] to i64
1139 ; FULL-SIMPLIFY-NEXT: [[I11:%.*]] = getelementptr inbounds i32, ptr [[ARG]], i64 [[I10]]
1140 ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG]]), "align"(ptr [[ARG]], i64 4), "dereferenceable"(ptr [[I11]], i64 4) ]
1141 ; FULL-SIMPLIFY-NEXT: [[I12:%.*]] = load i32, ptr [[I11]], align 4
1142 ; FULL-SIMPLIFY-NEXT: [[I13:%.*]] = add nsw i32 [[I12]], [[I9]]
1143 ; FULL-SIMPLIFY-NEXT: store i32 [[I13]], ptr [[I11]], align 4
1144 ; FULL-SIMPLIFY-NEXT: [[I14]] = add nsw i32 [[DOT0]], 1
1145 ; FULL-SIMPLIFY-NEXT: br label [[BB3]]
1146 ; FULL-SIMPLIFY: bb15:
1147 ; FULL-SIMPLIFY-NEXT: [[I16:%.*]] = sext i32 [[ARG1]] to i64
1148 ; FULL-SIMPLIFY-NEXT: [[I17:%.*]] = getelementptr inbounds i32, ptr [[ARG2]], i64 [[I16]]
1149 ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(ptr [[ARG2]]), "align"(ptr [[ARG2]], i64 4) ]
1150 ; FULL-SIMPLIFY-NEXT: [[I18:%.*]] = load i32, ptr [[I17]], align 4
1151 ; FULL-SIMPLIFY-NEXT: ret i32 [[I18]]
1156 bb3: ; preds = %bb4, %bb
1157 %.0 = phi i32 [ 0, %bb ], [ %i14, %bb4 ]
1158 %i = icmp slt i32 %.0, %arg1
1159 br i1 %i, label %bb4, label %bb15
1162 %i5 = add nsw i32 %arg1, %.0
1163 %i6 = sext i32 %i5 to i64
1164 %i7 = getelementptr inbounds i32, ptr %arg, i64 %i6
1165 %i8 = load i32, ptr %i7, align 4
1166 %i9 = mul nsw i32 %.0, %i8
1167 %i10 = sext i32 %.0 to i64
1168 %i11 = getelementptr inbounds i32, ptr %arg, i64 %i10
1169 %i12 = load i32, ptr %i11, align 4
1170 %i13 = add nsw i32 %i12, %i9
1171 store i32 %i13, ptr %i11, align 4
1172 %i14 = add nsw i32 %.0, 1
1175 bb15: ; preds = %bb3
1176 %i16 = sext i32 %arg1 to i64
1177 %i17 = getelementptr inbounds i32, ptr %arg2, i64 %i16
1178 %i18 = load i32, ptr %i17, align 4
1182 define i32 @test7(ptr nonnull %arg, i32 %arg1) {
1183 ; BASIC-LABEL: define {{[^@]+}}@test7
1184 ; BASIC-SAME: (ptr nonnull [[ARG:%.*]], i32 [[ARG1:%.*]]) {
1186 ; BASIC-NEXT: [[I:%.*]] = sext i32 [[ARG1]] to i64
1187 ; BASIC-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[ARG]], i64 0, i32 3
1188 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 280), "align"(ptr [[ARG]], i64 16) ]
1189 ; BASIC-NEXT: [[I3:%.*]] = load i64, ptr [[I2]], align 8
1190 ; BASIC-NEXT: [[I4:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 2, i64 [[I]], i64 [[I3]], i32 0
1191 ; BASIC-NEXT: [[I5:%.*]] = load i64, ptr [[I4]], align 32
1192 ; BASIC-NEXT: [[I6:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 1
1193 ; BASIC-NEXT: [[I7:%.*]] = load ptr, ptr [[I6]], align 8
1194 ; BASIC-NEXT: [[I8:%.*]] = getelementptr inbounds i64, ptr [[I7]], i64 [[I3]]
1195 ; BASIC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I8]], i64 8), "nonnull"(ptr [[I7]]), "align"(ptr [[I7]], i64 8) ]
1196 ; BASIC-NEXT: store i64 [[I5]], ptr [[I8]], align 8
1197 ; BASIC-NEXT: store i64 [[I5]], ptr [[I8]], align 8
1198 ; BASIC-NEXT: [[I10:%.*]] = load ptr, ptr [[ARG]], align 8
1199 ; BASIC-NEXT: [[I11:%.*]] = load i32, ptr [[I10]], align 4
1200 ; BASIC-NEXT: ret i32 [[I11]]
1202 ; ALL-LABEL: define {{[^@]+}}@test7
1203 ; ALL-SAME: (ptr nonnull [[ARG:%.*]], i32 [[ARG1:%.*]]) {
1205 ; ALL-NEXT: [[I:%.*]] = sext i32 [[ARG1]] to i64
1206 ; ALL-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[ARG]], i64 0, i32 3
1207 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 280), "align"(ptr [[ARG]], i64 16) ]
1208 ; ALL-NEXT: [[I3:%.*]] = load i64, ptr [[I2]], align 8
1209 ; ALL-NEXT: [[I4:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 2, i64 [[I]], i64 [[I3]], i32 0
1210 ; ALL-NEXT: [[I5:%.*]] = load i64, ptr [[I4]], align 32
1211 ; ALL-NEXT: [[I6:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 1
1212 ; ALL-NEXT: [[I7:%.*]] = load ptr, ptr [[I6]], align 8
1213 ; ALL-NEXT: [[I8:%.*]] = getelementptr inbounds i64, ptr [[I7]], i64 [[I3]]
1214 ; ALL-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I8]], i64 8), "nonnull"(ptr [[I7]]), "align"(ptr [[I7]], i64 8) ]
1215 ; ALL-NEXT: store i64 [[I5]], ptr [[I8]], align 8
1216 ; ALL-NEXT: store i64 [[I5]], ptr [[I8]], align 8
1217 ; ALL-NEXT: [[I10:%.*]] = load ptr, ptr [[ARG]], align 8
1218 ; ALL-NEXT: [[I11:%.*]] = load i32, ptr [[I10]], align 4
1219 ; ALL-NEXT: ret i32 [[I11]]
1221 ; WITH-AC-LABEL: define {{[^@]+}}@test7
1222 ; WITH-AC-SAME: (ptr nonnull [[ARG:%.*]], i32 [[ARG1:%.*]]) {
1224 ; WITH-AC-NEXT: [[I:%.*]] = sext i32 [[ARG1]] to i64
1225 ; WITH-AC-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[ARG]], i64 0, i32 3
1226 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 280), "align"(ptr [[ARG]], i64 16) ]
1227 ; WITH-AC-NEXT: [[I3:%.*]] = load i64, ptr [[I2]], align 8
1228 ; WITH-AC-NEXT: [[I4:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 2, i64 [[I]], i64 [[I3]], i32 0
1229 ; WITH-AC-NEXT: [[I5:%.*]] = load i64, ptr [[I4]], align 32
1230 ; WITH-AC-NEXT: [[I6:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 1
1231 ; WITH-AC-NEXT: [[I7:%.*]] = load ptr, ptr [[I6]], align 8
1232 ; WITH-AC-NEXT: [[I8:%.*]] = getelementptr inbounds i64, ptr [[I7]], i64 [[I3]]
1233 ; WITH-AC-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I8]], i64 8), "nonnull"(ptr [[I7]]), "align"(ptr [[I7]], i64 8) ]
1234 ; WITH-AC-NEXT: store i64 [[I5]], ptr [[I8]], align 8
1235 ; WITH-AC-NEXT: store i64 [[I5]], ptr [[I8]], align 8
1236 ; WITH-AC-NEXT: [[I10:%.*]] = load ptr, ptr [[ARG]], align 8
1237 ; WITH-AC-NEXT: [[I11:%.*]] = load i32, ptr [[I10]], align 4
1238 ; WITH-AC-NEXT: ret i32 [[I11]]
1240 ; CROSS-BLOCK-LABEL: define {{[^@]+}}@test7
1241 ; CROSS-BLOCK-SAME: (ptr nonnull [[ARG:%.*]], i32 [[ARG1:%.*]]) {
1242 ; CROSS-BLOCK-NEXT: bb:
1243 ; CROSS-BLOCK-NEXT: [[I:%.*]] = sext i32 [[ARG1]] to i64
1244 ; CROSS-BLOCK-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[ARG]], i64 0, i32 3
1245 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[ARG]], i64 280), "align"(ptr [[ARG]], i64 16) ]
1246 ; CROSS-BLOCK-NEXT: [[I3:%.*]] = load i64, ptr [[I2]], align 8
1247 ; CROSS-BLOCK-NEXT: [[I4:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 2, i64 [[I]], i64 [[I3]], i32 0
1248 ; CROSS-BLOCK-NEXT: [[I5:%.*]] = load i64, ptr [[I4]], align 32
1249 ; CROSS-BLOCK-NEXT: [[I6:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 1
1250 ; CROSS-BLOCK-NEXT: [[I7:%.*]] = load ptr, ptr [[I6]], align 8
1251 ; CROSS-BLOCK-NEXT: [[I8:%.*]] = getelementptr inbounds i64, ptr [[I7]], i64 [[I3]]
1252 ; CROSS-BLOCK-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I8]], i64 8), "nonnull"(ptr [[I7]]), "align"(ptr [[I7]], i64 8) ]
1253 ; CROSS-BLOCK-NEXT: store i64 [[I5]], ptr [[I8]], align 8
1254 ; CROSS-BLOCK-NEXT: store i64 [[I5]], ptr [[I8]], align 8
1255 ; CROSS-BLOCK-NEXT: [[I10:%.*]] = load ptr, ptr [[ARG]], align 8
1256 ; CROSS-BLOCK-NEXT: [[I11:%.*]] = load i32, ptr [[I10]], align 4
1257 ; CROSS-BLOCK-NEXT: ret i32 [[I11]]
1259 ; FULL-SIMPLIFY-LABEL: define {{[^@]+}}@test7
1260 ; FULL-SIMPLIFY-SAME: (ptr nonnull align 16 dereferenceable(280) [[ARG:%.*]], i32 [[ARG1:%.*]]) {
1261 ; FULL-SIMPLIFY-NEXT: bb:
1262 ; FULL-SIMPLIFY-NEXT: [[I:%.*]] = sext i32 [[ARG1]] to i64
1263 ; FULL-SIMPLIFY-NEXT: [[I2:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[ARG]], i64 0, i32 3
1264 ; FULL-SIMPLIFY-NEXT: [[I3:%.*]] = load i64, ptr [[I2]], align 8
1265 ; FULL-SIMPLIFY-NEXT: [[I4:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 2, i64 [[I]], i64 [[I3]], i32 0
1266 ; FULL-SIMPLIFY-NEXT: [[I5:%.*]] = load i64, ptr [[I4]], align 32
1267 ; FULL-SIMPLIFY-NEXT: [[I6:%.*]] = getelementptr inbounds [[STRUCT_A]], ptr [[ARG]], i64 0, i32 1
1268 ; FULL-SIMPLIFY-NEXT: [[I7:%.*]] = load ptr, ptr [[I6]], align 8
1269 ; FULL-SIMPLIFY-NEXT: [[I8:%.*]] = getelementptr inbounds i64, ptr [[I7]], i64 [[I3]]
1270 ; FULL-SIMPLIFY-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(ptr [[I8]], i64 8), "nonnull"(ptr [[I7]]), "align"(ptr [[I7]], i64 8) ]
1271 ; FULL-SIMPLIFY-NEXT: store i64 [[I5]], ptr [[I8]], align 8
1272 ; FULL-SIMPLIFY-NEXT: store i64 [[I5]], ptr [[I8]], align 8
1273 ; FULL-SIMPLIFY-NEXT: [[I10:%.*]] = load ptr, ptr [[ARG]], align 8
1274 ; FULL-SIMPLIFY-NEXT: [[I11:%.*]] = load i32, ptr [[I10]], align 4
1275 ; FULL-SIMPLIFY-NEXT: ret i32 [[I11]]
1278 %i = sext i32 %arg1 to i64
1279 %i2 = getelementptr inbounds %struct.A, ptr %arg, i64 0, i32 3
1280 %i3 = load i64, ptr %i2, align 8
1281 %i4 = getelementptr inbounds %struct.A, ptr %arg, i64 0, i32 2, i64 %i, i64 %i3, i32 0
1282 %i5 = load i64, ptr %i4, align 32
1283 %i6 = getelementptr inbounds %struct.A, ptr %arg, i64 0, i32 1
1284 %i7 = load ptr, ptr %i6, align 8
1285 %i8 = getelementptr inbounds i64, ptr %i7, i64 %i3
1286 store i64 %i5, ptr %i8, align 8
1287 store i64 %i5, ptr %i8, align 8
1288 %i10 = load ptr, ptr %arg, align 8
1289 %i11 = load i32, ptr %i10, align 4
1293 attributes #0 = { cold nounwind willreturn }
1294 attributes #1 = { "no-jump-tables" }
1295 attributes #2 = { norecurse nounwind willreturn "less-precise-fpmad" "no-jump-tables" }
1296 attributes #3 = { nounwind }
1297 attributes #4 = { null_pointer_is_valid }
1298 attributes #5 = { cold }