xref: /llvm-project/llvm/test/Transforms/GVNHoist/hoist.ll (revision 8c6aea6c5662e48526cf575f7163a5830abd1d43)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=gvn-hoist -S < %s | FileCheck %s
3target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
4target triple = "x86_64-unknown-linux-gnu"
5
6@GlobalVar = internal global float 1.000000e+00
7
8; Check that all scalar expressions are hoisted.
9define float @scalarsHoisting(float %d, float %min, float %max, float %a) {
10; CHECK-LABEL: @scalarsHoisting(
11; CHECK-NEXT:  entry:
12; CHECK-NEXT:    [[DIV:%.*]] = fdiv float 1.000000e+00, [[D:%.*]]
13; CHECK-NEXT:    [[CMP:%.*]] = fcmp oge float [[DIV]], 0.000000e+00
14; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[MIN:%.*]], [[A:%.*]]
15; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[SUB]], [[DIV]]
16; CHECK-NEXT:    [[SUB1:%.*]] = fsub float [[MAX:%.*]], [[A]]
17; CHECK-NEXT:    [[MUL2:%.*]] = fmul float [[SUB1]], [[DIV]]
18; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
19; CHECK:       if.then:
20; CHECK-NEXT:    br label [[IF_END:%.*]]
21; CHECK:       if.else:
22; CHECK-NEXT:    br label [[IF_END]]
23; CHECK:       if.end:
24; CHECK-NEXT:    [[TMAX_0:%.*]] = phi float [ [[MUL2]], [[IF_THEN]] ], [ [[MUL]], [[IF_ELSE]] ]
25; CHECK-NEXT:    [[TMIN_0:%.*]] = phi float [ [[MUL]], [[IF_THEN]] ], [ [[MUL2]], [[IF_ELSE]] ]
26; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[TMAX_0]], [[TMIN_0]]
27; CHECK-NEXT:    ret float [[ADD]]
28;
29entry:
30  %div = fdiv float 1.000000e+00, %d
31  %cmp = fcmp oge float %div, 0.000000e+00
32  br i1 %cmp, label %if.then, label %if.else
33
34if.then:                                          ; preds = %entry
35  %sub = fsub float %min, %a
36  %mul = fmul float %sub, %div
37  %sub1 = fsub float %max, %a
38  %mul2 = fmul float %sub1, %div
39  br label %if.end
40
41if.else:                                          ; preds = %entry
42  %sub3 = fsub float %max, %a
43  %mul4 = fmul float %sub3, %div
44  %sub5 = fsub float %min, %a
45  %mul6 = fmul float %sub5, %div
46  br label %if.end
47
48if.end:                                           ; preds = %if.else, %if.then
49  %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
50  %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ]
51  %add = fadd float %tmax.0, %tmin.0
52  ret float %add
53}
54
55; Check that all loads and scalars depending on the loads are hoisted.
56; Check that getelementptr computation gets hoisted before the load.
57define float @readsAndScalarsHoisting(float %d, ptr %min, ptr %max, ptr %a) {
58; CHECK-LABEL: @readsAndScalarsHoisting(
59; CHECK-NEXT:  entry:
60; CHECK-NEXT:    [[DIV:%.*]] = fdiv float 1.000000e+00, [[D:%.*]]
61; CHECK-NEXT:    [[CMP:%.*]] = fcmp oge float [[DIV]], 0.000000e+00
62; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr float, ptr [[MIN:%.*]], i32 1
63; CHECK-NEXT:    [[TMP1:%.*]] = load float, ptr [[TMP0]], align 4
64; CHECK-NEXT:    [[TMP2:%.*]] = load float, ptr [[A:%.*]], align 4
65; CHECK-NEXT:    [[TMP3:%.*]] = load float, ptr [[MAX:%.*]], align 4
66; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[TMP1]], [[TMP2]]
67; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[SUB]], [[DIV]]
68; CHECK-NEXT:    [[SUB1:%.*]] = fsub float [[TMP3]], [[TMP2]]
69; CHECK-NEXT:    [[MUL2:%.*]] = fmul float [[SUB1]], [[DIV]]
70; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
71; CHECK:       if.then:
72; CHECK-NEXT:    [[A:%.*]] = getelementptr float, ptr [[MIN]], i32 1
73; CHECK-NEXT:    br label [[IF_END:%.*]]
74; CHECK:       if.else:
75; CHECK-NEXT:    [[B:%.*]] = getelementptr float, ptr [[MIN]], i32 1
76; CHECK-NEXT:    br label [[IF_END]]
77; CHECK:       if.end:
78; CHECK-NEXT:    [[TMAX_0:%.*]] = phi float [ [[MUL2]], [[IF_THEN]] ], [ [[MUL]], [[IF_ELSE]] ]
79; CHECK-NEXT:    [[TMIN_0:%.*]] = phi float [ [[MUL]], [[IF_THEN]] ], [ [[MUL2]], [[IF_ELSE]] ]
80; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[TMAX_0]], [[TMIN_0]]
81; CHECK-NEXT:    ret float [[ADD]]
82;
83entry:
84  %div = fdiv float 1.000000e+00, %d
85  %cmp = fcmp oge float %div, 0.000000e+00
86  br i1 %cmp, label %if.then, label %if.else
87
88if.then:                                          ; preds = %entry
89  %A = getelementptr float, ptr %min, i32 1
90  %0 = load float, ptr %A, align 4
91  %1 = load float, ptr %a, align 4
92  %sub = fsub float %0, %1
93  %mul = fmul float %sub, %div
94  %2 = load float, ptr %max, align 4
95  %sub1 = fsub float %2, %1
96  %mul2 = fmul float %sub1, %div
97  br label %if.end
98
99if.else:                                          ; preds = %entry
100  %3 = load float, ptr %max, align 4
101  %4 = load float, ptr %a, align 4
102  %sub3 = fsub float %3, %4
103  %mul4 = fmul float %sub3, %div
104  %B = getelementptr float, ptr %min, i32 1
105  %5 = load float, ptr %B, align 4
106  %sub5 = fsub float %5, %4
107  %mul6 = fmul float %sub5, %div
108  br label %if.end
109
110if.end:                                           ; preds = %if.else, %if.then
111  %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
112  %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ]
113  %add = fadd float %tmax.0, %tmin.0
114  ret float %add
115}
116
117; Check that we do not hoist loads after a store: the first two loads will be
118; hoisted, and then the third load will not be hoisted.
119define float @readsAndWrites(float %d, ptr %min, ptr %max, ptr %a) {
120; CHECK-LABEL: @readsAndWrites(
121; CHECK-NEXT:  entry:
122; CHECK-NEXT:    [[DIV:%.*]] = fdiv float 1.000000e+00, [[D:%.*]]
123; CHECK-NEXT:    [[CMP:%.*]] = fcmp oge float [[DIV]], 0.000000e+00
124; CHECK-NEXT:    [[TMP0:%.*]] = load float, ptr [[MIN:%.*]], align 4
125; CHECK-NEXT:    [[TMP1:%.*]] = load float, ptr [[A:%.*]], align 4
126; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[TMP0]], [[TMP1]]
127; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[SUB]], [[DIV]]
128; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
129; CHECK:       if.then:
130; CHECK-NEXT:    store float [[TMP0]], ptr @GlobalVar, align 4
131; CHECK-NEXT:    [[TMP2:%.*]] = load float, ptr [[MAX:%.*]], align 4
132; CHECK-NEXT:    [[SUB1:%.*]] = fsub float [[TMP2]], [[TMP1]]
133; CHECK-NEXT:    [[MUL2:%.*]] = fmul float [[SUB1]], [[DIV]]
134; CHECK-NEXT:    br label [[IF_END:%.*]]
135; CHECK:       if.else:
136; CHECK-NEXT:    [[TMP3:%.*]] = load float, ptr [[MAX]], align 4
137; CHECK-NEXT:    [[SUB3:%.*]] = fsub float [[TMP3]], [[TMP1]]
138; CHECK-NEXT:    [[MUL4:%.*]] = fmul float [[SUB3]], [[DIV]]
139; CHECK-NEXT:    br label [[IF_END]]
140; CHECK:       if.end:
141; CHECK-NEXT:    [[TMAX_0:%.*]] = phi float [ [[MUL2]], [[IF_THEN]] ], [ [[MUL]], [[IF_ELSE]] ]
142; CHECK-NEXT:    [[TMIN_0:%.*]] = phi float [ [[MUL]], [[IF_THEN]] ], [ [[MUL4]], [[IF_ELSE]] ]
143; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[TMAX_0]], [[TMIN_0]]
144; CHECK-NEXT:    ret float [[ADD]]
145;
146entry:
147  %div = fdiv float 1.000000e+00, %d
148  %cmp = fcmp oge float %div, 0.000000e+00
149  br i1 %cmp, label %if.then, label %if.else
150
151if.then:                                          ; preds = %entry
152  %0 = load float, ptr %min, align 4
153  %1 = load float, ptr %a, align 4
154  store float %0, ptr @GlobalVar
155  %sub = fsub float %0, %1
156  %mul = fmul float %sub, %div
157  %2 = load float, ptr %max, align 4
158  %sub1 = fsub float %2, %1
159  %mul2 = fmul float %sub1, %div
160  br label %if.end
161
162if.else:                                          ; preds = %entry
163  %3 = load float, ptr %max, align 4
164  %4 = load float, ptr %a, align 4
165  %sub3 = fsub float %3, %4
166  %mul4 = fmul float %sub3, %div
167  %5 = load float, ptr %min, align 4
168  %sub5 = fsub float %5, %4
169  %mul6 = fmul float %sub5, %div
170  br label %if.end
171
172if.end:                                           ; preds = %if.else, %if.then
173  %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
174  %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ]
175  %add = fadd float %tmax.0, %tmin.0
176  ret float %add
177}
178
179; Check that we do hoist loads when the store is above the insertion point.
180define float @readsAndWriteAboveInsertPt(float %d, ptr %min, ptr %max, ptr %a) {
181; CHECK-LABEL: @readsAndWriteAboveInsertPt(
182; CHECK-NEXT:  entry:
183; CHECK-NEXT:    [[DIV:%.*]] = fdiv float 1.000000e+00, [[D:%.*]]
184; CHECK-NEXT:    store float 0.000000e+00, ptr @GlobalVar, align 4
185; CHECK-NEXT:    [[CMP:%.*]] = fcmp oge float [[DIV]], 0.000000e+00
186; CHECK-NEXT:    [[TMP0:%.*]] = load float, ptr [[MIN:%.*]], align 4
187; CHECK-NEXT:    [[TMP1:%.*]] = load float, ptr [[A:%.*]], align 4
188; CHECK-NEXT:    [[TMP2:%.*]] = load float, ptr [[MAX:%.*]], align 4
189; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[TMP0]], [[TMP1]]
190; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[SUB]], [[DIV]]
191; CHECK-NEXT:    [[SUB1:%.*]] = fsub float [[TMP2]], [[TMP1]]
192; CHECK-NEXT:    [[MUL2:%.*]] = fmul float [[SUB1]], [[DIV]]
193; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
194; CHECK:       if.then:
195; CHECK-NEXT:    br label [[IF_END:%.*]]
196; CHECK:       if.else:
197; CHECK-NEXT:    br label [[IF_END]]
198; CHECK:       if.end:
199; CHECK-NEXT:    [[TMAX_0:%.*]] = phi float [ [[MUL2]], [[IF_THEN]] ], [ [[MUL]], [[IF_ELSE]] ]
200; CHECK-NEXT:    [[TMIN_0:%.*]] = phi float [ [[MUL]], [[IF_THEN]] ], [ [[MUL2]], [[IF_ELSE]] ]
201; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[TMAX_0]], [[TMIN_0]]
202; CHECK-NEXT:    ret float [[ADD]]
203;
204entry:
205  %div = fdiv float 1.000000e+00, %d
206  store float 0.000000e+00, ptr @GlobalVar
207  %cmp = fcmp oge float %div, 0.000000e+00
208  br i1 %cmp, label %if.then, label %if.else
209
210if.then:                                          ; preds = %entry
211  %0 = load float, ptr %min, align 4
212  %1 = load float, ptr %a, align 4
213  %sub = fsub float %0, %1
214  %mul = fmul float %sub, %div
215  %2 = load float, ptr %max, align 4
216  %sub1 = fsub float %2, %1
217  %mul2 = fmul float %sub1, %div
218  br label %if.end
219
220if.else:                                          ; preds = %entry
221  %3 = load float, ptr %max, align 4
222  %4 = load float, ptr %a, align 4
223  %sub3 = fsub float %3, %4
224  %mul4 = fmul float %sub3, %div
225  %5 = load float, ptr %min, align 4
226  %sub5 = fsub float %5, %4
227  %mul6 = fmul float %sub5, %div
228  br label %if.end
229
230if.end:                                           ; preds = %if.else, %if.then
231  %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
232  %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ]
233  %add = fadd float %tmax.0, %tmin.0
234  ret float %add
235}
236
237; Check that dependent expressions are hoisted.
238define float @dependentScalarsHoisting(float %a, float %b, i1 %c) {
239; CHECK-LABEL: @dependentScalarsHoisting(
240; CHECK-NEXT:  entry:
241; CHECK-NEXT:    [[D:%.*]] = fsub float [[B:%.*]], [[A:%.*]]
242; CHECK-NEXT:    [[E:%.*]] = fadd float [[D]], [[A]]
243; CHECK-NEXT:    [[F:%.*]] = fdiv float [[E]], [[A]]
244; CHECK-NEXT:    [[G:%.*]] = fmul float [[F]], [[A]]
245; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
246; CHECK:       if.then:
247; CHECK-NEXT:    br label [[IF_END:%.*]]
248; CHECK:       if.else:
249; CHECK-NEXT:    br label [[IF_END]]
250; CHECK:       if.end:
251; CHECK-NEXT:    [[R:%.*]] = phi float [ [[G]], [[IF_THEN]] ], [ [[G]], [[IF_ELSE]] ]
252; CHECK-NEXT:    ret float [[R]]
253;
254entry:
255  br i1 %c, label %if.then, label %if.else
256
257if.then:
258  %d = fsub float %b, %a
259  %e = fadd float %d, %a
260  %f = fdiv float %e, %a
261  %g = fmul float %f, %a
262  br label %if.end
263
264if.else:
265  %h = fsub float %b, %a
266  %i = fadd float %h, %a
267  %j = fdiv float %i, %a
268  %k = fmul float %j, %a
269  br label %if.end
270
271if.end:
272  %r = phi float [ %g, %if.then ], [ %k, %if.else ]
273  ret float %r
274}
275
276; Check that all independent expressions are hoisted.
277define float @independentScalarsHoisting(float %a, float %b, i1 %c) {
278; CHECK-LABEL: @independentScalarsHoisting(
279; CHECK-NEXT:  entry:
280; CHECK-NEXT:    [[D:%.*]] = fadd float [[B:%.*]], [[A:%.*]]
281; CHECK-NEXT:    [[E:%.*]] = fsub float [[B]], [[A]]
282; CHECK-NEXT:    [[F:%.*]] = fdiv float [[B]], [[A]]
283; CHECK-NEXT:    [[G:%.*]] = fmul float [[B]], [[A]]
284; CHECK-NEXT:    br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
285; CHECK:       if.then:
286; CHECK-NEXT:    br label [[IF_END:%.*]]
287; CHECK:       if.else:
288; CHECK-NEXT:    br label [[IF_END]]
289; CHECK:       if.end:
290; CHECK-NEXT:    [[P:%.*]] = phi float [ [[D]], [[IF_THEN]] ], [ [[D]], [[IF_ELSE]] ]
291; CHECK-NEXT:    [[Q:%.*]] = phi float [ [[E]], [[IF_THEN]] ], [ [[E]], [[IF_ELSE]] ]
292; CHECK-NEXT:    [[R:%.*]] = phi float [ [[F]], [[IF_THEN]] ], [ [[F]], [[IF_ELSE]] ]
293; CHECK-NEXT:    [[S:%.*]] = phi float [ [[G]], [[IF_THEN]] ], [ [[G]], [[IF_ELSE]] ]
294; CHECK-NEXT:    [[T:%.*]] = fadd float [[P]], [[Q]]
295; CHECK-NEXT:    [[U:%.*]] = fadd float [[R]], [[S]]
296; CHECK-NEXT:    [[V:%.*]] = fadd float [[T]], [[U]]
297; CHECK-NEXT:    ret float [[V]]
298;
299entry:
300  br i1 %c, label %if.then, label %if.else
301
302if.then:
303  %d = fadd float %b, %a
304  %e = fsub float %b, %a
305  %f = fdiv float %b, %a
306  %g = fmul float %b, %a
307  br label %if.end
308
309if.else:
310  %i = fadd float %b, %a
311  %h = fsub float %b, %a
312  %j = fdiv float %b, %a
313  %k = fmul float %b, %a
314  br label %if.end
315
316if.end:
317  %p = phi float [ %d, %if.then ], [ %i, %if.else ]
318  %q = phi float [ %e, %if.then ], [ %h, %if.else ]
319  %r = phi float [ %f, %if.then ], [ %j, %if.else ]
320  %s = phi float [ %g, %if.then ], [ %k, %if.else ]
321  %t = fadd float %p, %q
322  %u = fadd float %r, %s
323  %v = fadd float %t, %u
324  ret float %v
325}
326
327; Check that we hoist load and scalar expressions in triangles.
328define float @triangleHoisting(float %d, ptr %min, ptr %max, ptr %a) {
329; CHECK-LABEL: @triangleHoisting(
330; CHECK-NEXT:  entry:
331; CHECK-NEXT:    [[DIV:%.*]] = fdiv float 1.000000e+00, [[D:%.*]]
332; CHECK-NEXT:    [[CMP:%.*]] = fcmp oge float [[DIV]], 0.000000e+00
333; CHECK-NEXT:    [[TMP0:%.*]] = load float, ptr [[MIN:%.*]], align 4
334; CHECK-NEXT:    [[TMP1:%.*]] = load float, ptr [[A:%.*]], align 4
335; CHECK-NEXT:    [[TMP2:%.*]] = load float, ptr [[MAX:%.*]], align 4
336; CHECK-NEXT:    [[SUB5:%.*]] = fsub float [[TMP0]], [[TMP1]]
337; CHECK-NEXT:    [[MUL6:%.*]] = fmul float [[SUB5]], [[DIV]]
338; CHECK-NEXT:    [[SUB3:%.*]] = fsub float [[TMP2]], [[TMP1]]
339; CHECK-NEXT:    [[MUL4:%.*]] = fmul float [[SUB3]], [[DIV]]
340; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
341; CHECK:       if.then:
342; CHECK-NEXT:    br label [[IF_END]]
343; CHECK:       if.end:
344; CHECK-NEXT:    [[P1:%.*]] = phi float [ [[MUL4]], [[IF_THEN]] ], [ 0.000000e+00, [[ENTRY:%.*]] ]
345; CHECK-NEXT:    [[P2:%.*]] = phi float [ [[MUL6]], [[IF_THEN]] ], [ 0.000000e+00, [[ENTRY]] ]
346; CHECK-NEXT:    [[X:%.*]] = fadd float [[P1]], [[MUL6]]
347; CHECK-NEXT:    [[Y:%.*]] = fadd float [[P2]], [[MUL4]]
348; CHECK-NEXT:    [[Z:%.*]] = fadd float [[X]], [[Y]]
349; CHECK-NEXT:    ret float [[Z]]
350;
351entry:
352  %div = fdiv float 1.000000e+00, %d
353  %cmp = fcmp oge float %div, 0.000000e+00
354  br i1 %cmp, label %if.then, label %if.end
355
356if.then:                                          ; preds = %entry
357  %0 = load float, ptr %min, align 4
358  %1 = load float, ptr %a, align 4
359  %sub = fsub float %0, %1
360  %mul = fmul float %sub, %div
361  %2 = load float, ptr %max, align 4
362  %sub1 = fsub float %2, %1
363  %mul2 = fmul float %sub1, %div
364  br label %if.end
365
366if.end:                                          ; preds = %entry
367  %p1 = phi float [ %mul2, %if.then ], [ 0.000000e+00, %entry ]
368  %p2 = phi float [ %mul, %if.then ], [ 0.000000e+00, %entry ]
369  %3 = load float, ptr %max, align 4
370  %4 = load float, ptr %a, align 4
371  %sub3 = fsub float %3, %4
372  %mul4 = fmul float %sub3, %div
373  %5 = load float, ptr %min, align 4
374  %sub5 = fsub float %5, %4
375  %mul6 = fmul float %sub5, %div
376
377  %x = fadd float %p1, %mul6
378  %y = fadd float %p2, %mul4
379  %z = fadd float %x, %y
380  ret float %z
381}
382
383; Check that we do not hoist loads past stores within a same basic block.
384define i32 @noHoistInSingleBBWithStore() {
385; CHECK-LABEL: @noHoistInSingleBBWithStore(
386; CHECK-NEXT:  entry:
387; CHECK-NEXT:    [[D:%.*]] = alloca i32, align 4
388; CHECK-NEXT:    [[TMP0:%.*]] = bitcast ptr [[D]] to ptr
389; CHECK-NEXT:    [[BF:%.*]] = load i8, ptr [[TMP0]], align 4
390; CHECK-NEXT:    [[BF_CLEAR:%.*]] = and i8 [[BF]], -3
391; CHECK-NEXT:    store i8 [[BF_CLEAR]], ptr [[TMP0]], align 4
392; CHECK-NEXT:    [[BF1:%.*]] = load i8, ptr [[TMP0]], align 4
393; CHECK-NEXT:    [[BF_CLEAR1:%.*]] = and i8 [[BF1]], 1
394; CHECK-NEXT:    store i8 [[BF_CLEAR1]], ptr [[TMP0]], align 4
395; CHECK-NEXT:    ret i32 0
396;
397entry:
398  %D = alloca i32, align 4
399  %0 = bitcast ptr %D to ptr
400  %bf = load i8, ptr %0, align 4
401  %bf.clear = and i8 %bf, -3
402  store i8 %bf.clear, ptr %0, align 4
403  %bf1 = load i8, ptr %0, align 4
404  %bf.clear1 = and i8 %bf1, 1
405  store i8 %bf.clear1, ptr %0, align 4
406  ret i32 0
407}
408
409; Check that we do not hoist loads past calls within a same basic block.
410declare void @foo()
411define i32 @noHoistInSingleBBWithCall() {
412; CHECK-LABEL: @noHoistInSingleBBWithCall(
413; CHECK-NEXT:  entry:
414; CHECK-NEXT:    [[D:%.*]] = alloca i32, align 4
415; CHECK-NEXT:    [[TMP0:%.*]] = bitcast ptr [[D]] to ptr
416; CHECK-NEXT:    [[BF:%.*]] = load i8, ptr [[TMP0]], align 4
417; CHECK-NEXT:    [[BF_CLEAR:%.*]] = and i8 [[BF]], -3
418; CHECK-NEXT:    call void @foo()
419; CHECK-NEXT:    [[BF1:%.*]] = load i8, ptr [[TMP0]], align 4
420; CHECK-NEXT:    [[BF_CLEAR1:%.*]] = and i8 [[BF1]], 1
421; CHECK-NEXT:    ret i32 0
422;
423entry:
424  %D = alloca i32, align 4
425  %0 = bitcast ptr %D to ptr
426  %bf = load i8, ptr %0, align 4
427  %bf.clear = and i8 %bf, -3
428  call void @foo()
429  %bf1 = load i8, ptr %0, align 4
430  %bf.clear1 = and i8 %bf1, 1
431  ret i32 0
432}
433
434; Check that we do not hoist loads past stores in any branch of a diamond.
435define float @noHoistInDiamondWithOneStore1(float %d, ptr %min, ptr %max, ptr %a) {
436; CHECK-LABEL: @noHoistInDiamondWithOneStore1(
437; CHECK-NEXT:  entry:
438; CHECK-NEXT:    [[DIV:%.*]] = fdiv float 1.000000e+00, [[D:%.*]]
439; CHECK-NEXT:    [[CMP:%.*]] = fcmp oge float [[DIV]], 0.000000e+00
440; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
441; CHECK:       if.then:
442; CHECK-NEXT:    store float 0.000000e+00, ptr @GlobalVar, align 4
443; CHECK-NEXT:    [[TMP0:%.*]] = load float, ptr [[MIN:%.*]], align 4
444; CHECK-NEXT:    [[TMP1:%.*]] = load float, ptr [[A:%.*]], align 4
445; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[TMP0]], [[TMP1]]
446; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[SUB]], [[DIV]]
447; CHECK-NEXT:    [[TMP2:%.*]] = load float, ptr [[MAX:%.*]], align 4
448; CHECK-NEXT:    [[SUB1:%.*]] = fsub float [[TMP2]], [[TMP1]]
449; CHECK-NEXT:    [[MUL2:%.*]] = fmul float [[SUB1]], [[DIV]]
450; CHECK-NEXT:    br label [[IF_END:%.*]]
451; CHECK:       if.else:
452; CHECK-NEXT:    [[TMP3:%.*]] = load float, ptr [[MAX]], align 4
453; CHECK-NEXT:    [[TMP4:%.*]] = load float, ptr [[A]], align 4
454; CHECK-NEXT:    [[SUB3:%.*]] = fsub float [[TMP3]], [[TMP4]]
455; CHECK-NEXT:    [[MUL4:%.*]] = fmul float [[SUB3]], [[DIV]]
456; CHECK-NEXT:    [[TMP5:%.*]] = load float, ptr [[MIN]], align 4
457; CHECK-NEXT:    [[SUB5:%.*]] = fsub float [[TMP5]], [[TMP4]]
458; CHECK-NEXT:    [[MUL6:%.*]] = fmul float [[SUB5]], [[DIV]]
459; CHECK-NEXT:    br label [[IF_END]]
460; CHECK:       if.end:
461; CHECK-NEXT:    [[TMAX_0:%.*]] = phi float [ [[MUL2]], [[IF_THEN]] ], [ [[MUL6]], [[IF_ELSE]] ]
462; CHECK-NEXT:    [[TMIN_0:%.*]] = phi float [ [[MUL]], [[IF_THEN]] ], [ [[MUL4]], [[IF_ELSE]] ]
463; CHECK-NEXT:    [[TMP6:%.*]] = load float, ptr [[MAX]], align 4
464; CHECK-NEXT:    [[TMP7:%.*]] = load float, ptr [[A]], align 4
465; CHECK-NEXT:    [[SUB6:%.*]] = fsub float [[TMP6]], [[TMP7]]
466; CHECK-NEXT:    [[MUL7:%.*]] = fmul float [[SUB6]], [[DIV]]
467; CHECK-NEXT:    [[TMP8:%.*]] = load float, ptr [[MIN]], align 4
468; CHECK-NEXT:    [[SUB8:%.*]] = fsub float [[TMP8]], [[TMP7]]
469; CHECK-NEXT:    [[MUL9:%.*]] = fmul float [[SUB8]], [[DIV]]
470; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[TMAX_0]], [[TMIN_0]]
471; CHECK-NEXT:    ret float [[ADD]]
472;
473entry:
474  %div = fdiv float 1.000000e+00, %d
475  %cmp = fcmp oge float %div, 0.000000e+00
476  br i1 %cmp, label %if.then, label %if.else
477
478if.then:                                          ; preds = %entry
479  store float 0.000000e+00, ptr @GlobalVar
480  %0 = load float, ptr %min, align 4
481  %1 = load float, ptr %a, align 4
482  %sub = fsub float %0, %1
483  %mul = fmul float %sub, %div
484  %2 = load float, ptr %max, align 4
485  %sub1 = fsub float %2, %1
486  %mul2 = fmul float %sub1, %div
487  br label %if.end
488
489if.else:                                          ; preds = %entry
490  ; There are no side effects on the if.else branch.
491  %3 = load float, ptr %max, align 4
492  %4 = load float, ptr %a, align 4
493  %sub3 = fsub float %3, %4
494  %mul4 = fmul float %sub3, %div
495  %5 = load float, ptr %min, align 4
496  %sub5 = fsub float %5, %4
497  %mul6 = fmul float %sub5, %div
498  br label %if.end
499
500if.end:                                           ; preds = %if.else, %if.then
501  %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
502  %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ]
503
504  %6 = load float, ptr %max, align 4
505  %7 = load float, ptr %a, align 4
506  %sub6 = fsub float %6, %7
507  %mul7 = fmul float %sub6, %div
508  %8 = load float, ptr %min, align 4
509  %sub8 = fsub float %8, %7
510  %mul9 = fmul float %sub8, %div
511
512  %add = fadd float %tmax.0, %tmin.0
513  ret float %add
514}
515
516; Check that we do not hoist loads past stores from half diamond.
517define float @noHoistInHalfDiamondPastStore(float %d, ptr %min, ptr %max, ptr %a) {
518; CHECK-LABEL: @noHoistInHalfDiamondPastStore(
519; CHECK-NEXT:  entry:
520; CHECK-NEXT:    [[DIV:%.*]] = fdiv float 1.000000e+00, [[D:%.*]]
521; CHECK-NEXT:    [[CMP:%.*]] = fcmp oge float [[DIV]], 0.000000e+00
522; CHECK-NEXT:    [[TMP0:%.*]] = load float, ptr [[MIN:%.*]], align 4
523; CHECK-NEXT:    [[TMP1:%.*]] = load float, ptr [[A:%.*]], align 4
524; CHECK-NEXT:    store float 0.000000e+00, ptr @GlobalVar, align 4
525; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
526; CHECK:       if.then:
527; CHECK-NEXT:    [[TMP2:%.*]] = load float, ptr [[MAX:%.*]], align 4
528; CHECK-NEXT:    [[TMP3:%.*]] = load float, ptr [[A]], align 4
529; CHECK-NEXT:    [[SUB3:%.*]] = fsub float [[TMP2]], [[TMP3]]
530; CHECK-NEXT:    [[MUL4:%.*]] = fmul float [[SUB3]], [[DIV]]
531; CHECK-NEXT:    [[TMP4:%.*]] = load float, ptr [[MIN]], align 4
532; CHECK-NEXT:    [[SUB5:%.*]] = fsub float [[TMP4]], [[TMP3]]
533; CHECK-NEXT:    [[MUL6:%.*]] = fmul float [[SUB5]], [[DIV]]
534; CHECK-NEXT:    br label [[IF_END]]
535; CHECK:       if.end:
536; CHECK-NEXT:    [[TMAX_0:%.*]] = phi float [ [[MUL4]], [[IF_THEN]] ], [ [[TMP0]], [[ENTRY:%.*]] ]
537; CHECK-NEXT:    [[TMIN_0:%.*]] = phi float [ [[MUL6]], [[IF_THEN]] ], [ [[TMP1]], [[ENTRY]] ]
538; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[TMAX_0]], [[TMIN_0]]
539; CHECK-NEXT:    ret float [[ADD]]
540;
541entry:
542  %div = fdiv float 1.000000e+00, %d
543  %cmp = fcmp oge float %div, 0.000000e+00
544  %0 = load float, ptr %min, align 4
545  %1 = load float, ptr %a, align 4
546
547  ; Loads should not be hoisted above this store.
548  store float 0.000000e+00, ptr @GlobalVar
549
550  br i1 %cmp, label %if.then, label %if.end
551
552if.then:
553  ; There are no side effects on the if.then branch.
554  %2 = load float, ptr %max, align 4
555  %3 = load float, ptr %a, align 4
556  %sub3 = fsub float %2, %3
557  %mul4 = fmul float %sub3, %div
558  %4 = load float, ptr %min, align 4
559  %sub5 = fsub float %4, %3
560  %mul6 = fmul float %sub5, %div
561  br label %if.end
562
563if.end:
564  %tmax.0 = phi float [ %mul4, %if.then ], [ %0, %entry ]
565  %tmin.0 = phi float [ %mul6, %if.then ], [ %1, %entry ]
566
567  %add = fadd float %tmax.0, %tmin.0
568  ret float %add
569}
570
571; Check that we do not hoist loads past a store in any branch of a diamond.
572define float @noHoistInDiamondWithOneStore2(float %d, ptr %min, ptr %max, ptr %a) {
573; CHECK-LABEL: @noHoistInDiamondWithOneStore2(
574; CHECK-NEXT:  entry:
575; CHECK-NEXT:    [[DIV:%.*]] = fdiv float 1.000000e+00, [[D:%.*]]
576; CHECK-NEXT:    [[CMP:%.*]] = fcmp oge float [[DIV]], 0.000000e+00
577; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
578; CHECK:       if.then:
579; CHECK-NEXT:    [[TMP0:%.*]] = load float, ptr [[MIN:%.*]], align 4
580; CHECK-NEXT:    [[TMP1:%.*]] = load float, ptr [[A:%.*]], align 4
581; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[TMP0]], [[TMP1]]
582; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[SUB]], [[DIV]]
583; CHECK-NEXT:    [[TMP2:%.*]] = load float, ptr [[MAX:%.*]], align 4
584; CHECK-NEXT:    [[SUB1:%.*]] = fsub float [[TMP2]], [[TMP1]]
585; CHECK-NEXT:    [[MUL2:%.*]] = fmul float [[SUB1]], [[DIV]]
586; CHECK-NEXT:    br label [[IF_END:%.*]]
587; CHECK:       if.else:
588; CHECK-NEXT:    store float 0.000000e+00, ptr @GlobalVar, align 4
589; CHECK-NEXT:    [[TMP3:%.*]] = load float, ptr [[MAX]], align 4
590; CHECK-NEXT:    [[TMP4:%.*]] = load float, ptr [[A]], align 4
591; CHECK-NEXT:    [[SUB3:%.*]] = fsub float [[TMP3]], [[TMP4]]
592; CHECK-NEXT:    [[MUL4:%.*]] = fmul float [[SUB3]], [[DIV]]
593; CHECK-NEXT:    [[TMP5:%.*]] = load float, ptr [[MIN]], align 4
594; CHECK-NEXT:    [[SUB5:%.*]] = fsub float [[TMP5]], [[TMP4]]
595; CHECK-NEXT:    [[MUL6:%.*]] = fmul float [[SUB5]], [[DIV]]
596; CHECK-NEXT:    br label [[IF_END]]
597; CHECK:       if.end:
598; CHECK-NEXT:    [[TMAX_0:%.*]] = phi float [ [[MUL2]], [[IF_THEN]] ], [ [[MUL6]], [[IF_ELSE]] ]
599; CHECK-NEXT:    [[TMIN_0:%.*]] = phi float [ [[MUL]], [[IF_THEN]] ], [ [[MUL4]], [[IF_ELSE]] ]
600; CHECK-NEXT:    [[TMP6:%.*]] = load float, ptr [[MAX]], align 4
601; CHECK-NEXT:    [[TMP7:%.*]] = load float, ptr [[A]], align 4
602; CHECK-NEXT:    [[SUB6:%.*]] = fsub float [[TMP6]], [[TMP7]]
603; CHECK-NEXT:    [[MUL7:%.*]] = fmul float [[SUB6]], [[DIV]]
604; CHECK-NEXT:    [[TMP8:%.*]] = load float, ptr [[MIN]], align 4
605; CHECK-NEXT:    [[SUB8:%.*]] = fsub float [[TMP8]], [[TMP7]]
606; CHECK-NEXT:    [[MUL9:%.*]] = fmul float [[SUB8]], [[DIV]]
607; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[TMAX_0]], [[TMIN_0]]
608; CHECK-NEXT:    ret float [[ADD]]
609;
610entry:
611  %div = fdiv float 1.000000e+00, %d
612  %cmp = fcmp oge float %div, 0.000000e+00
613  br i1 %cmp, label %if.then, label %if.else
614
615if.then:                                          ; preds = %entry
616  ; There are no side effects on the if.then branch.
617  %0 = load float, ptr %min, align 4
618  %1 = load float, ptr %a, align 4
619  %sub = fsub float %0, %1
620  %mul = fmul float %sub, %div
621  %2 = load float, ptr %max, align 4
622  %sub1 = fsub float %2, %1
623  %mul2 = fmul float %sub1, %div
624  br label %if.end
625
626if.else:                                          ; preds = %entry
627  store float 0.000000e+00, ptr @GlobalVar
628  %3 = load float, ptr %max, align 4
629  %4 = load float, ptr %a, align 4
630  %sub3 = fsub float %3, %4
631  %mul4 = fmul float %sub3, %div
632  %5 = load float, ptr %min, align 4
633  %sub5 = fsub float %5, %4
634  %mul6 = fmul float %sub5, %div
635  br label %if.end
636
637if.end:                                           ; preds = %if.else, %if.then
638  %tmax.0 = phi float [ %mul2, %if.then ], [ %mul6, %if.else ]
639  %tmin.0 = phi float [ %mul, %if.then ], [ %mul4, %if.else ]
640
641  %6 = load float, ptr %max, align 4
642  %7 = load float, ptr %a, align 4
643  %sub6 = fsub float %6, %7
644  %mul7 = fmul float %sub6, %div
645  %8 = load float, ptr %min, align 4
646  %sub8 = fsub float %8, %7
647  %mul9 = fmul float %sub8, %div
648
649  %add = fadd float %tmax.0, %tmin.0
650  ret float %add
651}
652
653; Check that we do not hoist loads outside a loop containing stores.
654define float @noHoistInLoopsWithStores(float %d, ptr %min, ptr %max, ptr %a) {
655; CHECK-LABEL: @noHoistInLoopsWithStores(
656; CHECK-NEXT:  entry:
657; CHECK-NEXT:    [[DIV:%.*]] = fdiv float 1.000000e+00, [[D:%.*]]
658; CHECK-NEXT:    [[CMP:%.*]] = fcmp oge float [[DIV]], 0.000000e+00
659; CHECK-NEXT:    br i1 [[CMP]], label [[DO_BODY:%.*]], label [[IF_ELSE:%.*]]
660; CHECK:       do.body:
661; CHECK-NEXT:    [[TMP0:%.*]] = load float, ptr [[MIN:%.*]], align 4
662; CHECK-NEXT:    [[TMP1:%.*]] = load float, ptr [[A:%.*]], align 4
663; CHECK-NEXT:    store float 0.000000e+00, ptr @GlobalVar, align 4
664; CHECK-NEXT:    [[SUB:%.*]] = fsub float [[TMP0]], [[TMP1]]
665; CHECK-NEXT:    [[MUL:%.*]] = fmul float [[SUB]], [[DIV]]
666; CHECK-NEXT:    [[TMP2:%.*]] = load float, ptr [[MAX:%.*]], align 4
667; CHECK-NEXT:    [[SUB1:%.*]] = fsub float [[TMP2]], [[TMP1]]
668; CHECK-NEXT:    [[MUL2:%.*]] = fmul float [[SUB1]], [[DIV]]
669; CHECK-NEXT:    br label [[WHILE_COND:%.*]]
670; CHECK:       while.cond:
671; CHECK-NEXT:    [[CMP1:%.*]] = fcmp oge float [[MUL2]], 0.000000e+00
672; CHECK-NEXT:    br i1 [[CMP1]], label [[IF_END:%.*]], label [[DO_BODY]]
673; CHECK:       if.else:
674; CHECK-NEXT:    [[TMP3:%.*]] = load float, ptr [[MAX]], align 4
675; CHECK-NEXT:    [[TMP4:%.*]] = load float, ptr [[A]], align 4
676; CHECK-NEXT:    [[SUB3:%.*]] = fsub float [[TMP3]], [[TMP4]]
677; CHECK-NEXT:    [[MUL4:%.*]] = fmul float [[SUB3]], [[DIV]]
678; CHECK-NEXT:    [[TMP5:%.*]] = load float, ptr [[MIN]], align 4
679; CHECK-NEXT:    [[SUB5:%.*]] = fsub float [[TMP5]], [[TMP4]]
680; CHECK-NEXT:    [[MUL6:%.*]] = fmul float [[SUB5]], [[DIV]]
681; CHECK-NEXT:    br label [[IF_END]]
682; CHECK:       if.end:
683; CHECK-NEXT:    [[TMAX_0:%.*]] = phi float [ [[MUL2]], [[WHILE_COND]] ], [ [[MUL6]], [[IF_ELSE]] ]
684; CHECK-NEXT:    [[TMIN_0:%.*]] = phi float [ [[MUL]], [[WHILE_COND]] ], [ [[MUL4]], [[IF_ELSE]] ]
685; CHECK-NEXT:    [[ADD:%.*]] = fadd float [[TMAX_0]], [[TMIN_0]]
686; CHECK-NEXT:    ret float [[ADD]]
687;
688entry:
689  %div = fdiv float 1.000000e+00, %d
690  %cmp = fcmp oge float %div, 0.000000e+00
691  br i1 %cmp, label %do.body, label %if.else
692
693do.body:
694  %0 = load float, ptr %min, align 4
695  %1 = load float, ptr %a, align 4
696
697  ; It is unsafe to hoist the loads outside the loop because of the store.
698  store float 0.000000e+00, ptr @GlobalVar
699
700  %sub = fsub float %0, %1
701  %mul = fmul float %sub, %div
702  %2 = load float, ptr %max, align 4
703  %sub1 = fsub float %2, %1
704  %mul2 = fmul float %sub1, %div
705  br label %while.cond
706
707while.cond:
708  %cmp1 = fcmp oge float %mul2, 0.000000e+00
709  br i1 %cmp1, label %if.end, label %do.body
710
711if.else:
712  %3 = load float, ptr %max, align 4
713  %4 = load float, ptr %a, align 4
714  %sub3 = fsub float %3, %4
715  %mul4 = fmul float %sub3, %div
716  %5 = load float, ptr %min, align 4
717  %sub5 = fsub float %5, %4
718  %mul6 = fmul float %sub5, %div
719  br label %if.end
720
721if.end:
722  %tmax.0 = phi float [ %mul2, %while.cond ], [ %mul6, %if.else ]
723  %tmin.0 = phi float [ %mul, %while.cond ], [ %mul4, %if.else ]
724
725  %add = fadd float %tmax.0, %tmin.0
726  ret float %add
727}
728
729; Check that we hoist stores: all the instructions from the then branch
730; should be hoisted.
731
732%struct.foo = type { ptr }
733
734define void @hoistStores(ptr %s, ptr %coord, i1 zeroext %delta) {
735; CHECK-LABEL: @hoistStores(
736; CHECK-NEXT:  entry:
737; CHECK-NEXT:    [[FROMBOOL:%.*]] = zext i1 [[DELTA:%.*]] to i8
738; CHECK-NEXT:    [[TOBOOL:%.*]] = trunc i8 [[FROMBOOL]] to i1
739; CHECK-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_FOO:%.*]], ptr [[S:%.*]], i32 0, i32 0
740; CHECK-NEXT:    [[TMP1:%.*]] = load ptr, ptr [[TMP0]], align 8
741; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr [[S]], i32 0, i32 0
742; CHECK-NEXT:    [[TMP3:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 1
743; CHECK-NEXT:    store ptr [[TMP3]], ptr [[TMP2]], align 8
744; CHECK-NEXT:    [[TMP4:%.*]] = load i16, ptr [[TMP1]], align 2
745; CHECK-NEXT:    [[TMP5:%.*]] = load i32, ptr [[COORD:%.*]], align 4
746; CHECK-NEXT:    [[CONV:%.*]] = zext i16 [[TMP4]] to i32
747; CHECK-NEXT:    [[ADD:%.*]] = add i32 [[TMP5]], [[CONV]]
748; CHECK-NEXT:    store i32 [[ADD]], ptr [[COORD]], align 4
749; CHECK-NEXT:    br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
750; CHECK:       if.then:
751; CHECK-NEXT:    [[P:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr [[S]], i32 0, i32 0
752; CHECK-NEXT:    [[INCDEC_PTR:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 1
753; CHECK-NEXT:    br label [[IF_END:%.*]]
754; CHECK:       if.else:
755; CHECK-NEXT:    [[P1:%.*]] = getelementptr inbounds [[STRUCT_FOO]], ptr [[S]], i32 0, i32 0
756; CHECK-NEXT:    [[INCDEC_PTR2:%.*]] = getelementptr inbounds i16, ptr [[TMP1]], i32 1
757; CHECK-NEXT:    [[TMP6:%.*]] = load ptr, ptr [[P1]], align 8
758; CHECK-NEXT:    [[INCDEC_PTR6:%.*]] = getelementptr inbounds i16, ptr [[TMP6]], i32 1
759; CHECK-NEXT:    store ptr [[INCDEC_PTR6]], ptr [[P1]], align 8
760; CHECK-NEXT:    [[TMP7:%.*]] = load i16, ptr [[TMP6]], align 2
761; CHECK-NEXT:    [[CONV7:%.*]] = zext i16 [[TMP7]] to i32
762; CHECK-NEXT:    [[SHL:%.*]] = shl i32 [[CONV7]], 8
763; CHECK-NEXT:    [[TMP8:%.*]] = load i32, ptr [[COORD]], align 4
764; CHECK-NEXT:    [[ADD8:%.*]] = add i32 [[TMP8]], [[SHL]]
765; CHECK-NEXT:    store i32 [[ADD8]], ptr [[COORD]], align 4
766; CHECK-NEXT:    br label [[IF_END]]
767; CHECK:       if.end:
768; CHECK-NEXT:    ret void
769;
770entry:
771  %frombool = zext i1 %delta to i8
772  %tobool = trunc i8 %frombool to i1
773  br i1 %tobool, label %if.then, label %if.else
774
775if.then:                                          ; preds = %entry
776  %p = getelementptr inbounds %struct.foo, ptr %s, i32 0, i32 0
777  %0 = load ptr, ptr %p, align 8
778  %incdec.ptr = getelementptr inbounds i16, ptr %0, i32 1
779  store ptr %incdec.ptr, ptr %p, align 8
780  %1 = load i16, ptr %0, align 2
781  %conv = zext i16 %1 to i32
782  %2 = load i32, ptr %coord, align 4
783  %add = add i32 %2, %conv
784  store i32 %add, ptr %coord, align 4
785  br label %if.end
786
787if.else:                                          ; preds = %entry
788  %p1 = getelementptr inbounds %struct.foo, ptr %s, i32 0, i32 0
789  %3 = load ptr, ptr %p1, align 8
790  %incdec.ptr2 = getelementptr inbounds i16, ptr %3, i32 1
791  store ptr %incdec.ptr2, ptr %p1, align 8
792  %4 = load i16, ptr %3, align 2
793  %conv3 = zext i16 %4 to i32
794  %5 = load i32, ptr %coord, align 4
795  %add4 = add i32 %5, %conv3
796  store i32 %add4, ptr %coord, align 4
797  %6 = load ptr, ptr %p1, align 8
798  %incdec.ptr6 = getelementptr inbounds i16, ptr %6, i32 1
799  store ptr %incdec.ptr6, ptr %p1, align 8
800  %7 = load i16, ptr %6, align 2
801  %conv7 = zext i16 %7 to i32
802  %shl = shl i32 %conv7, 8
803  %8 = load i32, ptr %coord, align 4
804  %add8 = add i32 %8, %shl
805  store i32 %add8, ptr %coord, align 4
806  br label %if.end
807
808if.end:                                           ; preds = %if.else, %if.then
809  ret void
810}
811
812define i32 @mergeAlignments(i1 %b, ptr %y) {
813; CHECK-LABEL: @mergeAlignments(
814; CHECK-NEXT:  entry:
815; CHECK-NEXT:    [[L1:%.*]] = load i32, ptr [[Y:%.*]], align 1
816; CHECK-NEXT:    br i1 [[B:%.*]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
817; CHECK:       if.then:
818; CHECK-NEXT:    br label [[RETURN:%.*]]
819; CHECK:       if.end:
820; CHECK-NEXT:    br label [[RETURN]]
821; CHECK:       return:
822; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[L1]], [[IF_THEN]] ], [ [[L1]], [[IF_END]] ]
823; CHECK-NEXT:    ret i32 [[RETVAL_0]]
824;
825entry:
826  br i1 %b, label %if.then, label %if.end
827
828if.then:                                          ; preds = %entry
829  %l1 = load i32, ptr %y, align 4
830  br label %return
831
832if.end:                                           ; preds = %entry
833  %l2 = load i32, ptr %y, align 1
834  br label %return
835
836return:                                           ; preds = %if.end, %if.then
837  %retval.0 = phi i32 [ %l1, %if.then ], [ %l2, %if.end ]
838  ret i32 %retval.0
839}
840
841declare i8 @pr30991_f() nounwind readonly
842declare void @pr30991_f1(i8)
843define i8 @pr30991(ptr %sp, ptr %word, i1 %b1, i1 %b2) {
844; CHECK-LABEL: @pr30991(
845; CHECK-NEXT:  entry:
846; CHECK-NEXT:    [[R0:%.*]] = load i8, ptr [[WORD:%.*]], align 1
847; CHECK-NEXT:    br i1 [[B1:%.*]], label [[A:%.*]], label [[B:%.*]]
848; CHECK:       a:
849; CHECK-NEXT:    [[INCDEC_PTR:%.*]] = getelementptr i8, ptr [[SP:%.*]], i32 1
850; CHECK-NEXT:    [[RR0:%.*]] = call i8 @pr30991_f() #[[ATTR0:[0-9]+]]
851; CHECK-NEXT:    call void @pr30991_f1(i8 [[R0]])
852; CHECK-NEXT:    ret i8 [[RR0]]
853; CHECK:       b:
854; CHECK-NEXT:    br i1 [[B2:%.*]], label [[C:%.*]], label [[X:%.*]]
855; CHECK:       c:
856; CHECK-NEXT:    [[INCDEC_PTR115:%.*]] = getelementptr i8, ptr [[SP]], i32 1
857; CHECK-NEXT:    [[RR1:%.*]] = call i8 @pr30991_f() #[[ATTR0]]
858; CHECK-NEXT:    call void @pr30991_f1(i8 [[R0]])
859; CHECK-NEXT:    ret i8 [[RR1]]
860; CHECK:       x:
861; CHECK-NEXT:    ret i8 [[R0]]
862;
863entry:
864  br i1 %b1, label %a, label %b
865
866a:
867  %r0 = load i8, ptr %word, align 1
868  %incdec.ptr = getelementptr i8, ptr %sp, i32 1
869  %rr0 = call i8 @pr30991_f() nounwind readonly
870  call void @pr30991_f1(i8 %r0)
871  ret i8 %rr0
872
873b:
874  br i1 %b2, label %c, label %x
875
876c:
877  %r1 = load i8, ptr %word, align 1
878  %incdec.ptr115 = getelementptr i8, ptr %sp, i32 1
879  %rr1 = call i8 @pr30991_f() nounwind readonly
880  call void @pr30991_f1(i8 %r1)
881  ret i8 %rr1
882
883x:
884  %r2 = load i8, ptr %word, align 1
885  ret i8 %r2
886}
887