xref: /llvm-project/llvm/test/Transforms/LICM/expr-reassociate-int.ll (revision 1261c02be4829984f025f258f3717277d04a8332)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2; RUN: opt -passes='loop-mssa(licm)' -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CONSTRAINED
3; RUN: opt -passes='loop-mssa(licm)' -licm-max-num-int-reassociations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,CONSTRAINED
4
5;
6; A simple loop:
7;
8;  int j;
9;
10;  for (j = 0; j <= i; j++)
11;    cells[j] = d1 * cells[j + 1] * delta;
12;
13; ...should be transformed by the LICM pass into this:
14;
15;  int j;
16;  const uint64_t d1d = d1 * delta;
17;
18;  for (j = 0; j <= i; j++)
19;    cells[j] = d1d * cells[j + 1];
20;
21
22define void @innermost_loop_1d_shouldhoist(i32 %i, i64 %d1, i64 %delta, ptr %cells) {
23; CHECK-LABEL: define void @innermost_loop_1d_shouldhoist
24; CHECK-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) {
25; CHECK-NEXT:  entry:
26; CHECK-NEXT:    [[MUL_1:%.*]] = mul nuw nsw i64 [[DELTA]], [[D1]]
27; CHECK-NEXT:    br label [[FOR_COND:%.*]]
28; CHECK:       for.cond:
29; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ]
30; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]]
31; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]]
32; CHECK:       for.body:
33; CHECK-NEXT:    [[ADD_J_1]] = add nuw nsw i32 [[J]], 1
34; CHECK-NEXT:    [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64
35; CHECK-NEXT:    [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]]
36; CHECK-NEXT:    [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8
37; CHECK-NEXT:    [[MUL_2:%.*]] = mul i64 [[MUL_1]], [[CELL_1]]
38; CHECK-NEXT:    [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64
39; CHECK-NEXT:    [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]]
40; CHECK-NEXT:    store i64 [[MUL_2]], ptr [[ARRAYIDX_J]], align 8
41; CHECK-NEXT:    br label [[FOR_COND]]
42; CHECK:       for.end:
43; CHECK-NEXT:    ret void
44;
45entry:
46  br label %for.cond
47
48for.cond:
49  %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ]
50  %cmp.not = icmp sgt i32 %j, %i
51  br i1 %cmp.not, label %for.end, label %for.body
52
53for.body:
54  %add.j.1 = add nuw nsw i32 %j, 1
55  %idxprom.j.1 = zext i32 %add.j.1 to i64
56  %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1
57  %cell.1 = load i64, ptr %arrayidx.j.1, align 8
58  %mul.1 = mul nsw nuw i64 %delta, %d1
59  %mul.2 = mul i64 %mul.1, %cell.1
60  %idxprom.j = zext i32 %j to i64
61  %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j
62  store i64 %mul.2, ptr %arrayidx.j, align 8
63  br label %for.cond
64
65for.end:
66  ret void
67}
68
69;
70; The following loop will be modified by the 'Reassociate expressions' pass,
71;
72;  int j;
73;  const uint64_t d1d = d1 * delta;
74;  const uint64_t d2d = d2 * delta;
75;
76;  for (j = 0; j <= i; j++)
77;    cells[j] = d1d * cells[j + 1] + d2d * cells[j];
78;
79; ...into this:
80;
81;  int j;
82;
83;  for (j = 0; j <= i; j++)
84;    cells[j] = (d1 * cells[j + 1] + d2 * cells[j]) * delta;
85;
86; We expect the LICM pass to undo this transformation.
87;
88
89define void @innermost_loop_2d(i32 %i, i64 %d1, i64 %d2, i64 %delta, ptr %cells) {
90; NOT_CONSTRAINED-LABEL: define void @innermost_loop_2d
91; NOT_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) {
92; NOT_CONSTRAINED-NEXT:  entry:
93; NOT_CONSTRAINED-NEXT:    [[FACTOR_OP_MUL:%.*]] = mul i64 [[D1]], [[DELTA]]
94; NOT_CONSTRAINED-NEXT:    [[FACTOR_OP_MUL1:%.*]] = mul i64 [[D2]], [[DELTA]]
95; NOT_CONSTRAINED-NEXT:    br label [[FOR_COND:%.*]]
96; NOT_CONSTRAINED:       for.cond:
97; NOT_CONSTRAINED-NEXT:    [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ]
98; NOT_CONSTRAINED-NEXT:    [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]]
99; NOT_CONSTRAINED-NEXT:    br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]]
100; NOT_CONSTRAINED:       for.body:
101; NOT_CONSTRAINED-NEXT:    [[ADD_J_1]] = add nuw nsw i32 [[J]], 1
102; NOT_CONSTRAINED-NEXT:    [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64
103; NOT_CONSTRAINED-NEXT:    [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]]
104; NOT_CONSTRAINED-NEXT:    [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8
105; NOT_CONSTRAINED-NEXT:    [[MUL_1:%.*]] = mul i64 [[CELL_1]], [[FACTOR_OP_MUL]]
106; NOT_CONSTRAINED-NEXT:    [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64
107; NOT_CONSTRAINED-NEXT:    [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]]
108; NOT_CONSTRAINED-NEXT:    [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8
109; NOT_CONSTRAINED-NEXT:    [[MUL_2:%.*]] = mul i64 [[CELL_2]], [[FACTOR_OP_MUL1]]
110; NOT_CONSTRAINED-NEXT:    [[REASS_ADD:%.*]] = add i64 [[MUL_2]], [[MUL_1]]
111; NOT_CONSTRAINED-NEXT:    store i64 [[REASS_ADD]], ptr [[ARRAYIDX_J]], align 8
112; NOT_CONSTRAINED-NEXT:    br label [[FOR_COND]]
113; NOT_CONSTRAINED:       for.end:
114; NOT_CONSTRAINED-NEXT:    ret void
115;
116; CONSTRAINED-LABEL: define void @innermost_loop_2d
117; CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) {
118; CONSTRAINED-NEXT:  entry:
119; CONSTRAINED-NEXT:    br label [[FOR_COND:%.*]]
120; CONSTRAINED:       for.cond:
121; CONSTRAINED-NEXT:    [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ]
122; CONSTRAINED-NEXT:    [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]]
123; CONSTRAINED-NEXT:    br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]]
124; CONSTRAINED:       for.body:
125; CONSTRAINED-NEXT:    [[ADD_J_1]] = add nuw nsw i32 [[J]], 1
126; CONSTRAINED-NEXT:    [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64
127; CONSTRAINED-NEXT:    [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]]
128; CONSTRAINED-NEXT:    [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8
129; CONSTRAINED-NEXT:    [[MUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]]
130; CONSTRAINED-NEXT:    [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64
131; CONSTRAINED-NEXT:    [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]]
132; CONSTRAINED-NEXT:    [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8
133; CONSTRAINED-NEXT:    [[MUL_2:%.*]] = mul nuw nsw i64 [[CELL_2]], [[D2]]
134; CONSTRAINED-NEXT:    [[REASS_ADD:%.*]] = add nuw nsw i64 [[MUL_2]], [[MUL_1]]
135; CONSTRAINED-NEXT:    [[REASS_MUL:%.*]] = mul i64 [[REASS_ADD]], [[DELTA]]
136; CONSTRAINED-NEXT:    store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8
137; CONSTRAINED-NEXT:    br label [[FOR_COND]]
138; CONSTRAINED:       for.end:
139; CONSTRAINED-NEXT:    ret void
140;
141entry:
142  br label %for.cond
143
144for.cond:
145  %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ]
146  %cmp.not = icmp sgt i32 %j, %i
147  br i1 %cmp.not, label %for.end, label %for.body
148
149for.body:
150  %add.j.1 = add nuw nsw i32 %j, 1
151  %idxprom.j.1 = zext i32 %add.j.1 to i64
152  %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1
153  %cell.1 = load i64, ptr %arrayidx.j.1, align 8
154  %mul.1 = mul i64 %cell.1, %d1
155  %idxprom.j = zext i32 %j to i64
156  %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j
157  %cell.2 = load i64, ptr %arrayidx.j, align 8
158  %mul.2 = mul nsw nuw i64 %cell.2, %d2
159  %reass.add = add nsw nuw i64 %mul.2, %mul.1
160  %reass.mul = mul i64 %reass.add, %delta
161  store i64 %reass.mul, ptr %arrayidx.j, align 8
162  br label %for.cond
163
164for.end:
165  ret void
166}
167
168;
169; The following loop will be modified by the 'Reassociate expressions' pass,
170;
171;  int j;
172;  const uint64_t d1d = d1 * delta;
173;  const uint64_t d2d = d2 * delta;
174;  const uint64_t d3d = d3 * delta;
175;
176;  for (j = 0; j <= i; j++)
177;    cells[j] = d1d * cells[j + 1] + d2d * cells[j] + d3d * cells[j + 2];
178;
179; ...into this:
180;
181;  int j;
182;
183;  for (j = 0; j <= i; j++)
184;    cells[j] = (d1 * cells[j + 1] + d2 * cells[j] + d3 * cells[j + 2]) * delta;
185;
186; We expect the LICM pass to undo this transformation.
187;
188
189
190define void @innermost_loop_3d(i32 %i, i64 %d1, i64 %d2, i64 %d3, i64 %delta, ptr %cells) {
191; NOT_CONSTRAINED-LABEL: define void @innermost_loop_3d
192; NOT_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[D3:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) {
193; NOT_CONSTRAINED-NEXT:  entry:
194; NOT_CONSTRAINED-NEXT:    [[FACTOR_OP_MUL:%.*]] = mul i64 [[D3]], [[DELTA]]
195; NOT_CONSTRAINED-NEXT:    [[FACTOR_OP_MUL1:%.*]] = mul i64 [[D1]], [[DELTA]]
196; NOT_CONSTRAINED-NEXT:    [[FACTOR_OP_MUL2:%.*]] = mul i64 [[D2]], [[DELTA]]
197; NOT_CONSTRAINED-NEXT:    br label [[FOR_COND:%.*]]
198; NOT_CONSTRAINED:       for.cond:
199; NOT_CONSTRAINED-NEXT:    [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ]
200; NOT_CONSTRAINED-NEXT:    [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]]
201; NOT_CONSTRAINED-NEXT:    br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]]
202; NOT_CONSTRAINED:       for.body:
203; NOT_CONSTRAINED-NEXT:    [[ADD_J_1]] = add nuw nsw i32 [[J]], 1
204; NOT_CONSTRAINED-NEXT:    [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64
205; NOT_CONSTRAINED-NEXT:    [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]]
206; NOT_CONSTRAINED-NEXT:    [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8
207; NOT_CONSTRAINED-NEXT:    [[MUL_1:%.*]] = mul i64 [[CELL_1]], [[FACTOR_OP_MUL1]]
208; NOT_CONSTRAINED-NEXT:    [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64
209; NOT_CONSTRAINED-NEXT:    [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]]
210; NOT_CONSTRAINED-NEXT:    [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8
211; NOT_CONSTRAINED-NEXT:    [[MUL_2:%.*]] = mul i64 [[CELL_2]], [[FACTOR_OP_MUL2]]
212; NOT_CONSTRAINED-NEXT:    [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2
213; NOT_CONSTRAINED-NEXT:    [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64
214; NOT_CONSTRAINED-NEXT:    [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]]
215; NOT_CONSTRAINED-NEXT:    [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8
216; NOT_CONSTRAINED-NEXT:    [[MUL_3:%.*]] = mul i64 [[CELL_3]], [[FACTOR_OP_MUL]]
217; NOT_CONSTRAINED-NEXT:    [[REASS_ADD:%.*]] = add i64 [[MUL_2]], [[MUL_1]]
218; NOT_CONSTRAINED-NEXT:    [[REASS_ADD1:%.*]] = add i64 [[REASS_ADD]], [[MUL_3]]
219; NOT_CONSTRAINED-NEXT:    store i64 [[REASS_ADD1]], ptr [[ARRAYIDX_J_2]], align 8
220; NOT_CONSTRAINED-NEXT:    br label [[FOR_COND]]
221; NOT_CONSTRAINED:       for.end:
222; NOT_CONSTRAINED-NEXT:    ret void
223;
224; CONSTRAINED-LABEL: define void @innermost_loop_3d
225; CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[D3:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) {
226; CONSTRAINED-NEXT:  entry:
227; CONSTRAINED-NEXT:    br label [[FOR_COND:%.*]]
228; CONSTRAINED:       for.cond:
229; CONSTRAINED-NEXT:    [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ]
230; CONSTRAINED-NEXT:    [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]]
231; CONSTRAINED-NEXT:    br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]]
232; CONSTRAINED:       for.body:
233; CONSTRAINED-NEXT:    [[ADD_J_1]] = add nuw nsw i32 [[J]], 1
234; CONSTRAINED-NEXT:    [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64
235; CONSTRAINED-NEXT:    [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]]
236; CONSTRAINED-NEXT:    [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8
237; CONSTRAINED-NEXT:    [[MUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]]
238; CONSTRAINED-NEXT:    [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64
239; CONSTRAINED-NEXT:    [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]]
240; CONSTRAINED-NEXT:    [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8
241; CONSTRAINED-NEXT:    [[MUL_2:%.*]] = mul i64 [[CELL_2]], [[D2]]
242; CONSTRAINED-NEXT:    [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2
243; CONSTRAINED-NEXT:    [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64
244; CONSTRAINED-NEXT:    [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]]
245; CONSTRAINED-NEXT:    [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8
246; CONSTRAINED-NEXT:    [[MUL_3:%.*]] = mul nuw nsw i64 [[CELL_3]], [[D3]]
247; CONSTRAINED-NEXT:    [[REASS_ADD:%.*]] = add nuw nsw i64 [[MUL_2]], [[MUL_1]]
248; CONSTRAINED-NEXT:    [[REASS_ADD1:%.*]] = add nuw nsw i64 [[REASS_ADD]], [[MUL_3]]
249; CONSTRAINED-NEXT:    [[REASS_MUL:%.*]] = mul nuw nsw i64 [[REASS_ADD1]], [[DELTA]]
250; CONSTRAINED-NEXT:    store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J_2]], align 8
251; CONSTRAINED-NEXT:    br label [[FOR_COND]]
252; CONSTRAINED:       for.end:
253; CONSTRAINED-NEXT:    ret void
254;
255entry:
256  br label %for.cond
257
258for.cond:
259  %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ]
260  %cmp.not = icmp sgt i32 %j, %i
261  br i1 %cmp.not, label %for.end, label %for.body
262
263for.body:
264  %add.j.1 = add nuw nsw i32 %j, 1
265  %idxprom.j.1 = zext i32 %add.j.1 to i64
266  %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1
267  %cell.1 = load i64, ptr %arrayidx.j.1, align 8
268  %mul.1 = mul i64 %cell.1, %d1
269  %idxprom.j = zext i32 %j to i64
270  %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j
271  %cell.2 = load i64, ptr %arrayidx.j, align 8
272  %mul.2 = mul i64 %cell.2, %d2
273  %add.j.2 = add nuw nsw i32 %j, 2
274  %idxprom.j.2 = zext i32 %add.j.2 to i64
275  %arrayidx.j.2 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.2
276  %cell.3 = load i64, ptr %arrayidx.j.2, align 8
277  %mul.3 = mul nsw nuw i64 %cell.3, %d3
278  %reass.add = add nsw nuw i64 %mul.2, %mul.1
279  %reass.add1 = add nsw nuw i64 %reass.add, %mul.3
280  %reass.mul = mul nsw nuw i64 %reass.add1, %delta
281  store i64 %reass.mul, ptr %arrayidx.j.2, align 8
282  br label %for.cond
283
284for.end:
285  ret void
286}
287
288;
289; The following loop will not be modified by the LICM pass:
290;
291;  int j;
292;
293;  for (j = 0; j <= i; j++)
294;    cells[j] = (d1 * cells[j + 1] + d2 * cells[j] +
295;                cells[j] * cells[j + 1]) * delta;
296;
297; This case differs as one of the multiplications involves no invariants.
298;
299
300define void @innermost_loop_3d_reassociated_different(i32 %i, i64 %d1, i64 %d2, i64 %delta, ptr %cells) {
301; CHECK-LABEL: define void @innermost_loop_3d_reassociated_different
302; CHECK-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) {
303; CHECK-NEXT:  entry:
304; CHECK-NEXT:    br label [[FOR_COND:%.*]]
305; CHECK:       for.cond:
306; CHECK-NEXT:    [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ]
307; CHECK-NEXT:    [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]]
308; CHECK-NEXT:    br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]]
309; CHECK:       for.body:
310; CHECK-NEXT:    [[ADD_J_1]] = add nuw nsw i32 [[J]], 1
311; CHECK-NEXT:    [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64
312; CHECK-NEXT:    [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]]
313; CHECK-NEXT:    [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8
314; CHECK-NEXT:    [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_1]] to i64
315; CHECK-NEXT:    [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]]
316; CHECK-NEXT:    [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8
317; CHECK-NEXT:    [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8
318; CHECK-NEXT:    [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64
319; CHECK-NEXT:    [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]]
320; CHECK-NEXT:    [[CELL_4:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8
321; CHECK-NEXT:    [[MUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]]
322; CHECK-NEXT:    [[MUL_2:%.*]] = mul i64 [[CELL_4]], [[D2]]
323; CHECK-NEXT:    [[EXTRA_MUL:%.*]] = mul i64 [[CELL_3]], [[CELL_2]]
324; CHECK-NEXT:    [[REASS_ADD:%.*]] = add i64 [[EXTRA_MUL]], [[MUL_1]]
325; CHECK-NEXT:    [[EXTRA_ADD:%.*]] = add i64 [[REASS_ADD]], [[MUL_2]]
326; CHECK-NEXT:    [[REASS_MUL:%.*]] = mul i64 [[EXTRA_ADD]], [[DELTA]]
327; CHECK-NEXT:    store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8
328; CHECK-NEXT:    br label [[FOR_COND]]
329; CHECK:       for.end:
330; CHECK-NEXT:    ret void
331;
332entry:
333  br label %for.cond
334
335for.cond:
336  %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ]
337  %cmp.not = icmp sgt i32 %j, %i
338  br i1 %cmp.not, label %for.end, label %for.body
339
340for.body:
341  %add.j.1 = add nuw nsw i32 %j, 1
342  %idxprom.j.1 = zext i32 %add.j.1 to i64
343  %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1
344  %cell.1 = load i64, ptr %arrayidx.j.1, align 8
345  %idxprom.j.2 = zext i32 %add.j.1 to i64
346  %arrayidx.j.2 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.2
347  %cell.2 = load i64, ptr %arrayidx.j.2, align 8
348  %idxprom.j.3 = zext i32 %add.j.1 to i64
349  %cell.3 = load i64, ptr %arrayidx.j.2, align 8
350  %idxprom.j = zext i32 %j to i64
351  %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j
352  %cell.4 = load i64, ptr %arrayidx.j, align 8
353  %mul.1 = mul i64 %cell.1, %d1
354  %mul.2 = mul i64 %cell.4, %d2
355  %extra.mul = mul i64 %cell.3, %cell.2
356  %reass.add = add i64 %extra.mul, %mul.1
357  %extra.add = add i64 %reass.add, %mul.2
358  %reass.mul = mul i64 %extra.add, %delta
359  store i64 %reass.mul, ptr %arrayidx.j, align 8
360  br label %for.cond
361
362for.end:
363  ret void
364}
365
366; Make sure we drop poison flags on the mul in the loop.
367define i32 @pr85457(i32 %x, i32 %y) {
368; CHECK-LABEL: define i32 @pr85457
369; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) {
370; CHECK-NEXT:  entry:
371; CHECK-NEXT:    [[FACTOR_OP_MUL:%.*]] = mul i32 [[X]], [[Y]]
372; CHECK-NEXT:    br label [[LOOP:%.*]]
373; CHECK:       loop:
374; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
375; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
376; CHECK-NEXT:    [[MUL0:%.*]] = mul i32 [[FACTOR_OP_MUL]], [[IV]]
377; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[MUL0]], 1
378; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]]
379; CHECK:       exit:
380; CHECK-NEXT:    ret i32 0
381;
382entry:
383  br label %loop
384
385loop:
386  %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop ]
387  %iv.next = add nuw nsw i32 %iv, 1
388  %mul0 = mul nuw nsw i32 %x, %iv
389  %mul1 = mul nuw i32 %mul0, %y
390  %cmp = icmp slt i32 %mul1, 1
391  br i1 %cmp, label %exit, label %loop
392
393exit:
394  ret i32 0
395}
396