xref: /llvm-project/llvm/test/Transforms/SROA/select-load.ll (revision 6dba99e14f7e508a5028036b753fa7f84e846307)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes='sroa<preserve-cfg>' -S | FileCheck %s --check-prefixes=CHECK,CHECK-PRESERVE-CFG
3; RUN: opt < %s -passes='sroa<modify-cfg>' -S | FileCheck %s --check-prefixes=CHECK,CHECK-MODIFY-CFG
4
5%st.half = type { half }
6
7; Allow speculateSelectInstLoads to fold load and select
8; even if there is an intervening bitcast.
9define <2 x i16> @test_load_bitcast_select(i1 %cond1, i1 %cond2) {
10; CHECK-LABEL: @test_load_bitcast_select(
11; CHECK-NEXT:  entry:
12; CHECK-NEXT:    [[TMP0:%.*]] = bitcast half 0xHFFFF to i16
13; CHECK-NEXT:    [[TMP1:%.*]] = bitcast half 0xH0000 to i16
14; CHECK-NEXT:    [[LD1_SROA_SPECULATED:%.*]] = select i1 [[COND1:%.*]], i16 [[TMP0]], i16 [[TMP1]]
15; CHECK-NEXT:    [[V1:%.*]] = insertelement <2 x i16> poison, i16 [[LD1_SROA_SPECULATED]], i32 0
16; CHECK-NEXT:    [[TMP2:%.*]] = bitcast half 0xHFFFF to i16
17; CHECK-NEXT:    [[TMP3:%.*]] = bitcast half 0xH0000 to i16
18; CHECK-NEXT:    [[LD2_SROA_SPECULATED:%.*]] = select i1 [[COND2:%.*]], i16 [[TMP2]], i16 [[TMP3]]
19; CHECK-NEXT:    [[V2:%.*]] = insertelement <2 x i16> [[V1]], i16 [[LD2_SROA_SPECULATED]], i32 1
20; CHECK-NEXT:    ret <2 x i16> [[V2]]
21;
22entry:
23  %true = alloca half, align 2
24  %false = alloca half, align 2
25  store half 0xHFFFF, ptr %true, align 2
26  store half 0xH0000, ptr %false, align 2
27  %sel1 = select i1 %cond1, ptr %true, ptr %false
28  %ld1 = load i16, ptr %sel1, align 2
29  %v1 = insertelement <2 x i16> poison, i16 %ld1, i32 0
30  %sel2 = select i1 %cond2, ptr %true, ptr %false
31  %ld2 = load i16, ptr %sel2, align 2
32  %v2 = insertelement <2 x i16> %v1, i16 %ld2, i32 1
33  ret <2 x i16> %v2
34}
35
36%st.args = type { i32, ptr }
37
38; A bitcasted load and a direct load of select.
39define void @test_multiple_loads_select(i1 %cmp) {
40; CHECK-LABEL: @test_multiple_loads_select(
41; CHECK-NEXT:  entry:
42; CHECK-NEXT:    [[ADDR_I8_SROA_SPECULATED:%.*]] = select i1 [[CMP:%.*]], ptr undef, ptr undef
43; CHECK-NEXT:    call void @foo_i8(ptr [[ADDR_I8_SROA_SPECULATED]])
44; CHECK-NEXT:    [[ADDR_I32_SROA_SPECULATED:%.*]] = select i1 [[CMP]], ptr undef, ptr undef
45; CHECK-NEXT:    call void @foo_i32(ptr [[ADDR_I32_SROA_SPECULATED]])
46; CHECK-NEXT:    ret void
47;
48entry:
49  %args = alloca [2 x %st.args], align 16
50  %arr1 = getelementptr inbounds [2 x %st.args], ptr %args, i64 0, i64 1
51  %sel = select i1 %cmp, ptr %arr1, ptr %args
52  %addr = getelementptr inbounds %st.args, ptr %sel, i64 0, i32 1
53  %addr.i8 = load ptr, ptr %addr, align 8
54  call void @foo_i8(ptr %addr.i8)
55  %addr.i32 = load ptr, ptr %addr, align 8
56  call void @foo_i32 (ptr %addr.i32)
57  ret void
58}
59
60; Sanitizer will break optimization.
61define void @test_multiple_loads_select_asan(i1 %cmp) sanitize_address {
62; CHECK-PRESERVE-CFG-LABEL: @test_multiple_loads_select_asan(
63; CHECK-PRESERVE-CFG-NEXT:  entry:
64; CHECK-PRESERVE-CFG-NEXT:    [[ARGS_SROA_0:%.*]] = alloca ptr, align 8
65; CHECK-PRESERVE-CFG-NEXT:    [[ARGS_SROA_1:%.*]] = alloca ptr, align 8
66; CHECK-PRESERVE-CFG-NEXT:    [[SEL_SROA_SEL:%.*]] = select i1 [[CMP:%.*]], ptr [[ARGS_SROA_1]], ptr [[ARGS_SROA_0]]
67; CHECK-PRESERVE-CFG-NEXT:    [[ADDR_I8:%.*]] = load ptr, ptr [[SEL_SROA_SEL]], align 8
68; CHECK-PRESERVE-CFG-NEXT:    call void @foo_i8(ptr [[ADDR_I8]])
69; CHECK-PRESERVE-CFG-NEXT:    [[ADDR_I32:%.*]] = load ptr, ptr [[SEL_SROA_SEL]], align 8
70; CHECK-PRESERVE-CFG-NEXT:    call void @foo_i32(ptr [[ADDR_I32]])
71; CHECK-PRESERVE-CFG-NEXT:    ret void
72;
73; CHECK-MODIFY-CFG-LABEL: @test_multiple_loads_select_asan(
74; CHECK-MODIFY-CFG-NEXT:  entry:
75; CHECK-MODIFY-CFG-NEXT:    br i1 [[CMP:%.*]], label [[ENTRY_THEN:%.*]], label [[ENTRY_ELSE:%.*]]
76; CHECK-MODIFY-CFG:       entry.then:
77; CHECK-MODIFY-CFG-NEXT:    br label [[ENTRY_CONT:%.*]]
78; CHECK-MODIFY-CFG:       entry.else:
79; CHECK-MODIFY-CFG-NEXT:    br label [[ENTRY_CONT]]
80; CHECK-MODIFY-CFG:       entry.cont:
81; CHECK-MODIFY-CFG-NEXT:    [[ADDR_I8:%.*]] = phi ptr [ undef, [[ENTRY_THEN]] ], [ undef, [[ENTRY_ELSE]] ]
82; CHECK-MODIFY-CFG-NEXT:    call void @foo_i8(ptr [[ADDR_I8]])
83; CHECK-MODIFY-CFG-NEXT:    br i1 [[CMP]], label [[ENTRY_CONT_THEN:%.*]], label [[ENTRY_CONT_ELSE:%.*]]
84; CHECK-MODIFY-CFG:       entry.cont.then:
85; CHECK-MODIFY-CFG-NEXT:    br label [[ENTRY_CONT_CONT:%.*]]
86; CHECK-MODIFY-CFG:       entry.cont.else:
87; CHECK-MODIFY-CFG-NEXT:    br label [[ENTRY_CONT_CONT]]
88; CHECK-MODIFY-CFG:       entry.cont.cont:
89; CHECK-MODIFY-CFG-NEXT:    [[ADDR_I32:%.*]] = phi ptr [ undef, [[ENTRY_CONT_THEN]] ], [ undef, [[ENTRY_CONT_ELSE]] ]
90; CHECK-MODIFY-CFG-NEXT:    call void @foo_i32(ptr [[ADDR_I32]])
91; CHECK-MODIFY-CFG-NEXT:    ret void
92;
93entry:
94  %args = alloca [2 x %st.args], align 16
95  %arr1 = getelementptr inbounds [2 x %st.args], ptr %args, i64 0, i64 1
96  %sel = select i1 %cmp, ptr %arr1, ptr %args
97  %addr = getelementptr inbounds %st.args, ptr %sel, i64 0, i32 1
98  %addr.i8 = load ptr, ptr %addr, align 8
99  call void @foo_i8(ptr %addr.i8)
100  %addr.i32 = load ptr, ptr %addr, align 8
101  call void @foo_i32 (ptr %addr.i32)
102  ret void
103}
104
105declare void @foo_i8(ptr)
106declare void @foo_i32(ptr)
107
108; Lifetime intrinsics should not prevent dereferenceability inferrence.
109define i32 @interfering_lifetime(ptr %data, i64 %indvars.iv) {
110; CHECK-LABEL: @interfering_lifetime(
111; CHECK-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV:%.*]]
112; CHECK-NEXT:    [[I1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
113; CHECK-NEXT:    [[CMP_I_I:%.*]] = icmp slt i32 [[I1]], 0
114; CHECK-NEXT:    [[I3_SROA_SPECULATE_LOAD_FALSE:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
115; CHECK-NEXT:    [[I3_SROA_SPECULATED:%.*]] = select i1 [[CMP_I_I]], i32 0, i32 [[I3_SROA_SPECULATE_LOAD_FALSE]]
116; CHECK-NEXT:    ret i32 [[I3_SROA_SPECULATED]]
117;
118  %min = alloca i32, align 4
119  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
120  %i1 = load i32, ptr %arrayidx, align 4
121  call void @llvm.lifetime.start.p0(i64 4, ptr %min)
122  store i32 0, ptr %min, align 4
123  %cmp.i.i = icmp slt i32 %i1, 0
124  %__b.__a.i.i = select i1 %cmp.i.i, ptr %min, ptr %arrayidx
125  %i3 = load i32, ptr %__b.__a.i.i, align 4
126  ret i32 %i3
127}
128
129; We should recursively evaluate select's.
130define i32 @clamp_load_to_constant_range(ptr %data, i64 %indvars.iv) {
131; CHECK-PRESERVE-CFG-LABEL: @clamp_load_to_constant_range(
132; CHECK-PRESERVE-CFG-NEXT:    [[MIN:%.*]] = alloca i32, align 4
133; CHECK-PRESERVE-CFG-NEXT:    [[MAX:%.*]] = alloca i32, align 4
134; CHECK-PRESERVE-CFG-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV:%.*]]
135; CHECK-PRESERVE-CFG-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr [[MIN]])
136; CHECK-PRESERVE-CFG-NEXT:    store i32 0, ptr [[MIN]], align 4
137; CHECK-PRESERVE-CFG-NEXT:    call void @llvm.lifetime.start.p0(i64 4, ptr [[MAX]])
138; CHECK-PRESERVE-CFG-NEXT:    store i32 4095, ptr [[MAX]], align 4
139; CHECK-PRESERVE-CFG-NEXT:    [[I1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
140; CHECK-PRESERVE-CFG-NEXT:    [[CMP_I_I:%.*]] = icmp slt i32 [[I1]], 0
141; CHECK-PRESERVE-CFG-NEXT:    [[I2:%.*]] = tail call i32 @llvm.smax.i32(i32 [[I1]], i32 0)
142; CHECK-PRESERVE-CFG-NEXT:    [[__B___A_I_I:%.*]] = select i1 [[CMP_I_I]], ptr [[MIN]], ptr [[ARRAYIDX]]
143; CHECK-PRESERVE-CFG-NEXT:    [[CMP_I1_I:%.*]] = icmp ugt i32 [[I2]], 4095
144; CHECK-PRESERVE-CFG-NEXT:    [[__B___A_I2_I:%.*]] = select i1 [[CMP_I1_I]], ptr [[MAX]], ptr [[__B___A_I_I]]
145; CHECK-PRESERVE-CFG-NEXT:    [[I3:%.*]] = load i32, ptr [[__B___A_I2_I]], align 4
146; CHECK-PRESERVE-CFG-NEXT:    ret i32 [[I3]]
147;
148; CHECK-MODIFY-CFG-LABEL: @clamp_load_to_constant_range(
149; CHECK-MODIFY-CFG-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV:%.*]]
150; CHECK-MODIFY-CFG-NEXT:    [[I1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
151; CHECK-MODIFY-CFG-NEXT:    [[CMP_I_I:%.*]] = icmp slt i32 [[I1]], 0
152; CHECK-MODIFY-CFG-NEXT:    [[I2:%.*]] = tail call i32 @llvm.smax.i32(i32 [[I1]], i32 0)
153; CHECK-MODIFY-CFG-NEXT:    [[CMP_I1_I:%.*]] = icmp ugt i32 [[I2]], 4095
154; CHECK-MODIFY-CFG-NEXT:    br i1 [[CMP_I1_I]], label [[DOTCONT:%.*]], label [[DOTELSE:%.*]]
155; CHECK-MODIFY-CFG:       .else:
156; CHECK-MODIFY-CFG-NEXT:    br i1 [[CMP_I_I]], label [[DOTELSE_CONT:%.*]], label [[DOTELSE_ELSE:%.*]]
157; CHECK-MODIFY-CFG:       .else.else:
158; CHECK-MODIFY-CFG-NEXT:    [[I3_ELSE_VAL_ELSE_VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
159; CHECK-MODIFY-CFG-NEXT:    br label [[DOTELSE_CONT]]
160; CHECK-MODIFY-CFG:       .else.cont:
161; CHECK-MODIFY-CFG-NEXT:    [[I3_ELSE_VAL:%.*]] = phi i32 [ 0, [[DOTELSE]] ], [ [[I3_ELSE_VAL_ELSE_VAL]], [[DOTELSE_ELSE]] ]
162; CHECK-MODIFY-CFG-NEXT:    br label [[DOTCONT]]
163; CHECK-MODIFY-CFG:       .cont:
164; CHECK-MODIFY-CFG-NEXT:    [[I3:%.*]] = phi i32 [ 4095, [[TMP0:%.*]] ], [ [[I3_ELSE_VAL]], [[DOTELSE_CONT]] ]
165; CHECK-MODIFY-CFG-NEXT:    ret i32 [[I3]]
166;
167  %min = alloca i32, align 4
168  %max = alloca i32, align 4
169  %arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
170  call void @llvm.lifetime.start.p0(i64 4, ptr %min)
171  store i32 0, ptr %min, align 4
172  call void @llvm.lifetime.start.p0(i64 4, ptr %max)
173  store i32 4095, ptr %max, align 4
174  %i1 = load i32, ptr %arrayidx, align 4
175  %cmp.i.i = icmp slt i32 %i1, 0
176  %i2 = tail call i32 @llvm.smax.i32(i32 %i1, i32 0)
177  %__b.__a.i.i = select i1 %cmp.i.i, ptr %min, ptr %arrayidx
178  %cmp.i1.i = icmp ugt i32 %i2, 4095
179  %__b.__a.i2.i = select i1 %cmp.i1.i, ptr %max, ptr %__b.__a.i.i
180  %i3 = load i32, ptr %__b.__a.i2.i, align 4
181  ret i32 %i3
182}
183
184define i32 @non_speculatable_load_of_select(i1 %cond, ptr %else.addr) {
185; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_load_of_select(
186; CHECK-PRESERVE-CFG-NEXT:  entry:
187; CHECK-PRESERVE-CFG-NEXT:    [[MIN:%.*]] = alloca i32, align 4
188; CHECK-PRESERVE-CFG-NEXT:    store i32 0, ptr [[MIN]], align 4
189; CHECK-PRESERVE-CFG-NEXT:    [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[MIN]], ptr [[ELSE_ADDR:%.*]], !prof [[PROF0:![0-9]+]]
190; CHECK-PRESERVE-CFG-NEXT:    [[R:%.*]] = load i32, ptr [[ADDR]], align 4
191; CHECK-PRESERVE-CFG-NEXT:    ret i32 [[R]]
192;
193; CHECK-MODIFY-CFG-LABEL: @non_speculatable_load_of_select(
194; CHECK-MODIFY-CFG-NEXT:  entry:
195; CHECK-MODIFY-CFG-NEXT:    br i1 [[COND:%.*]], label [[ENTRY_CONT:%.*]], label [[ENTRY_ELSE:%.*]], !prof [[PROF0:![0-9]+]]
196; CHECK-MODIFY-CFG:       entry.else:
197; CHECK-MODIFY-CFG-NEXT:    [[R_ELSE_VAL:%.*]] = load i32, ptr [[ELSE_ADDR:%.*]], align 4
198; CHECK-MODIFY-CFG-NEXT:    br label [[ENTRY_CONT]]
199; CHECK-MODIFY-CFG:       entry.cont:
200; CHECK-MODIFY-CFG-NEXT:    [[R:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[R_ELSE_VAL]], [[ENTRY_ELSE]] ]
201; CHECK-MODIFY-CFG-NEXT:    ret i32 [[R]]
202;
203entry:
204  %min = alloca i32, align 4
205  store i32 0, ptr %min, align 4
206  %addr = select i1 %cond, ptr %min, ptr %else.addr, !prof !0
207  %r = load i32, ptr %addr, align 4
208  ret i32 %r
209}
210define i32 @non_speculatable_load_of_select_inverted(i1 %cond, ptr %then.addr) {
211; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_load_of_select_inverted(
212; CHECK-PRESERVE-CFG-NEXT:  entry:
213; CHECK-PRESERVE-CFG-NEXT:    [[MAX:%.*]] = alloca i32, align 4
214; CHECK-PRESERVE-CFG-NEXT:    store i32 4095, ptr [[MAX]], align 4
215; CHECK-PRESERVE-CFG-NEXT:    [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[THEN_ADDR:%.*]], ptr [[MAX]], !prof [[PROF0]]
216; CHECK-PRESERVE-CFG-NEXT:    [[R:%.*]] = load i32, ptr [[ADDR]], align 4
217; CHECK-PRESERVE-CFG-NEXT:    ret i32 [[R]]
218;
219; CHECK-MODIFY-CFG-LABEL: @non_speculatable_load_of_select_inverted(
220; CHECK-MODIFY-CFG-NEXT:  entry:
221; CHECK-MODIFY-CFG-NEXT:    br i1 [[COND:%.*]], label [[ENTRY_THEN:%.*]], label [[ENTRY_CONT:%.*]], !prof [[PROF1:![0-9]+]]
222; CHECK-MODIFY-CFG:       entry.then:
223; CHECK-MODIFY-CFG-NEXT:    [[R_THEN_VAL:%.*]] = load i32, ptr [[THEN_ADDR:%.*]], align 4
224; CHECK-MODIFY-CFG-NEXT:    br label [[ENTRY_CONT]]
225; CHECK-MODIFY-CFG:       entry.cont:
226; CHECK-MODIFY-CFG-NEXT:    [[R:%.*]] = phi i32 [ [[R_THEN_VAL]], [[ENTRY_THEN]] ], [ 4095, [[ENTRY:%.*]] ]
227; CHECK-MODIFY-CFG-NEXT:    ret i32 [[R]]
228;
229entry:
230  %max = alloca i32, align 4
231  store i32 4095, ptr %max, align 4
232  %addr = select i1 %cond, ptr %then.addr, ptr %max, !prof !0
233  %r = load i32, ptr %addr, align 4
234  ret i32 %r
235}
236
237define i32 @non_speculatable_volatile_load_of_select(i1 %cond, ptr %else.addr) {
238; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_volatile_load_of_select(
239; CHECK-PRESERVE-CFG-NEXT:  entry:
240; CHECK-PRESERVE-CFG-NEXT:    [[MIN:%.*]] = alloca i32, align 4
241; CHECK-PRESERVE-CFG-NEXT:    store i32 0, ptr [[MIN]], align 4
242; CHECK-PRESERVE-CFG-NEXT:    [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[MIN]], ptr [[ELSE_ADDR:%.*]], !prof [[PROF0]]
243; CHECK-PRESERVE-CFG-NEXT:    [[R:%.*]] = load volatile i32, ptr [[ADDR]], align 4
244; CHECK-PRESERVE-CFG-NEXT:    ret i32 [[R]]
245;
246; CHECK-MODIFY-CFG-LABEL: @non_speculatable_volatile_load_of_select(
247; CHECK-MODIFY-CFG-NEXT:  entry:
248; CHECK-MODIFY-CFG-NEXT:    [[MIN:%.*]] = alloca i32, align 4
249; CHECK-MODIFY-CFG-NEXT:    store i32 0, ptr [[MIN]], align 4
250; CHECK-MODIFY-CFG-NEXT:    [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[MIN]], ptr [[ELSE_ADDR:%.*]], !prof [[PROF1]]
251; CHECK-MODIFY-CFG-NEXT:    [[R:%.*]] = load volatile i32, ptr [[ADDR]], align 4
252; CHECK-MODIFY-CFG-NEXT:    ret i32 [[R]]
253;
254entry:
255  %min = alloca i32, align 4
256  store i32 0, ptr %min, align 4
257  %addr = select i1 %cond, ptr %min, ptr %else.addr, !prof !0
258  %r = load volatile i32, ptr %addr, align 4
259  ret i32 %r
260}
261define i32 @non_speculatable_volatile_load_of_select_inverted(i1 %cond, ptr %then.addr) {
262; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_volatile_load_of_select_inverted(
263; CHECK-PRESERVE-CFG-NEXT:  entry:
264; CHECK-PRESERVE-CFG-NEXT:    [[MAX:%.*]] = alloca i32, align 4
265; CHECK-PRESERVE-CFG-NEXT:    store i32 4095, ptr [[MAX]], align 4
266; CHECK-PRESERVE-CFG-NEXT:    [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[THEN_ADDR:%.*]], ptr [[MAX]], !prof [[PROF0]]
267; CHECK-PRESERVE-CFG-NEXT:    [[R:%.*]] = load volatile i32, ptr [[ADDR]], align 4
268; CHECK-PRESERVE-CFG-NEXT:    ret i32 [[R]]
269;
270; CHECK-MODIFY-CFG-LABEL: @non_speculatable_volatile_load_of_select_inverted(
271; CHECK-MODIFY-CFG-NEXT:  entry:
272; CHECK-MODIFY-CFG-NEXT:    [[MAX:%.*]] = alloca i32, align 4
273; CHECK-MODIFY-CFG-NEXT:    store i32 4095, ptr [[MAX]], align 4
274; CHECK-MODIFY-CFG-NEXT:    [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[THEN_ADDR:%.*]], ptr [[MAX]], !prof [[PROF1]]
275; CHECK-MODIFY-CFG-NEXT:    [[R:%.*]] = load volatile i32, ptr [[ADDR]], align 4
276; CHECK-MODIFY-CFG-NEXT:    ret i32 [[R]]
277;
278entry:
279  %max = alloca i32, align 4
280  store i32 4095, ptr %max, align 4
281  %addr = select i1 %cond, ptr %then.addr, ptr %max, !prof !0
282  %r = load volatile i32, ptr %addr, align 4
283  ret i32 %r
284}
285
286define i32 @non_speculatable_atomic_unord_load_of_select(i1 %cond, ptr %else.addr) {
287; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_atomic_unord_load_of_select(
288; CHECK-PRESERVE-CFG-NEXT:  entry:
289; CHECK-PRESERVE-CFG-NEXT:    [[MIN:%.*]] = alloca i32, align 4
290; CHECK-PRESERVE-CFG-NEXT:    store i32 0, ptr [[MIN]], align 4
291; CHECK-PRESERVE-CFG-NEXT:    [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[MIN]], ptr [[ELSE_ADDR:%.*]], !prof [[PROF0]]
292; CHECK-PRESERVE-CFG-NEXT:    [[R:%.*]] = load atomic i32, ptr [[ADDR]] unordered, align 4
293; CHECK-PRESERVE-CFG-NEXT:    ret i32 [[R]]
294;
295; CHECK-MODIFY-CFG-LABEL: @non_speculatable_atomic_unord_load_of_select(
296; CHECK-MODIFY-CFG-NEXT:  entry:
297; CHECK-MODIFY-CFG-NEXT:    br i1 [[COND:%.*]], label [[ENTRY_THEN:%.*]], label [[ENTRY_ELSE:%.*]], !prof [[PROF1]]
298; CHECK-MODIFY-CFG:       entry.then:
299; CHECK-MODIFY-CFG-NEXT:    br label [[ENTRY_CONT:%.*]]
300; CHECK-MODIFY-CFG:       entry.else:
301; CHECK-MODIFY-CFG-NEXT:    [[R_ELSE_VAL:%.*]] = load atomic i32, ptr [[ELSE_ADDR:%.*]] unordered, align 4
302; CHECK-MODIFY-CFG-NEXT:    br label [[ENTRY_CONT]]
303; CHECK-MODIFY-CFG:       entry.cont:
304; CHECK-MODIFY-CFG-NEXT:    [[R:%.*]] = phi i32 [ 0, [[ENTRY_THEN]] ], [ [[R_ELSE_VAL]], [[ENTRY_ELSE]] ]
305; CHECK-MODIFY-CFG-NEXT:    ret i32 [[R]]
306;
307entry:
308  %min = alloca i32, align 4
309  store i32 0, ptr %min, align 4
310  %addr = select i1 %cond, ptr %min, ptr %else.addr, !prof !0
311  %r = load atomic i32, ptr %addr unordered, align 4
312  ret i32 %r
313}
314define i32 @non_speculatable_atomic_unord_load_of_select_inverted(i1 %cond, ptr %then.addr) {
315; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_atomic_unord_load_of_select_inverted(
316; CHECK-PRESERVE-CFG-NEXT:  entry:
317; CHECK-PRESERVE-CFG-NEXT:    [[MAX:%.*]] = alloca i32, align 4
318; CHECK-PRESERVE-CFG-NEXT:    store i32 4095, ptr [[MAX]], align 4
319; CHECK-PRESERVE-CFG-NEXT:    [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[THEN_ADDR:%.*]], ptr [[MAX]], !prof [[PROF0]]
320; CHECK-PRESERVE-CFG-NEXT:    [[R:%.*]] = load atomic i32, ptr [[ADDR]] unordered, align 4
321; CHECK-PRESERVE-CFG-NEXT:    ret i32 [[R]]
322;
323; CHECK-MODIFY-CFG-LABEL: @non_speculatable_atomic_unord_load_of_select_inverted(
324; CHECK-MODIFY-CFG-NEXT:  entry:
325; CHECK-MODIFY-CFG-NEXT:    br i1 [[COND:%.*]], label [[ENTRY_THEN:%.*]], label [[ENTRY_ELSE:%.*]], !prof [[PROF1]]
326; CHECK-MODIFY-CFG:       entry.then:
327; CHECK-MODIFY-CFG-NEXT:    [[R_THEN_VAL:%.*]] = load atomic i32, ptr [[THEN_ADDR:%.*]] unordered, align 4
328; CHECK-MODIFY-CFG-NEXT:    br label [[ENTRY_CONT:%.*]]
329; CHECK-MODIFY-CFG:       entry.else:
330; CHECK-MODIFY-CFG-NEXT:    br label [[ENTRY_CONT]]
331; CHECK-MODIFY-CFG:       entry.cont:
332; CHECK-MODIFY-CFG-NEXT:    [[R:%.*]] = phi i32 [ [[R_THEN_VAL]], [[ENTRY_THEN]] ], [ 4095, [[ENTRY_ELSE]] ]
333; CHECK-MODIFY-CFG-NEXT:    ret i32 [[R]]
334;
335entry:
336  %max = alloca i32, align 4
337  store i32 4095, ptr %max, align 4
338  %addr = select i1 %cond, ptr %then.addr, ptr %max, !prof !0
339  %r = load atomic i32, ptr %addr unordered, align 4
340  ret i32 %r
341}
342
343define i32 @non_speculatable_load_of_select_outer(i1 %cond_inner, i1 %cond_outer, ptr %data_then, ptr %data_else) {
344; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_load_of_select_outer(
345; CHECK-PRESERVE-CFG-NEXT:  entry:
346; CHECK-PRESERVE-CFG-NEXT:    [[MIN:%.*]] = alloca i32, align 4
347; CHECK-PRESERVE-CFG-NEXT:    store i32 0, ptr [[MIN]], align 4
348; CHECK-PRESERVE-CFG-NEXT:    [[ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[DATA_THEN:%.*]], ptr [[DATA_ELSE:%.*]], !prof [[PROF0]]
349; CHECK-PRESERVE-CFG-NEXT:    [[ADDR:%.*]] = select i1 [[COND_OUTER:%.*]], ptr [[MIN]], ptr [[ADDR_DATA]], !prof [[PROF0]]
350; CHECK-PRESERVE-CFG-NEXT:    [[R:%.*]] = load i32, ptr [[ADDR]], align 4
351; CHECK-PRESERVE-CFG-NEXT:    ret i32 [[R]]
352;
353; CHECK-MODIFY-CFG-LABEL: @non_speculatable_load_of_select_outer(
354; CHECK-MODIFY-CFG-NEXT:  entry:
355; CHECK-MODIFY-CFG-NEXT:    [[ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[DATA_THEN:%.*]], ptr [[DATA_ELSE:%.*]], !prof [[PROF1]]
356; CHECK-MODIFY-CFG-NEXT:    br i1 [[COND_OUTER:%.*]], label [[ENTRY_CONT:%.*]], label [[ENTRY_ELSE:%.*]], !prof [[PROF0]]
357; CHECK-MODIFY-CFG:       entry.else:
358; CHECK-MODIFY-CFG-NEXT:    [[R_ELSE_VAL:%.*]] = load i32, ptr [[ADDR_DATA]], align 4
359; CHECK-MODIFY-CFG-NEXT:    br label [[ENTRY_CONT]]
360; CHECK-MODIFY-CFG:       entry.cont:
361; CHECK-MODIFY-CFG-NEXT:    [[R:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[R_ELSE_VAL]], [[ENTRY_ELSE]] ]
362; CHECK-MODIFY-CFG-NEXT:    ret i32 [[R]]
363;
364entry:
365  %min = alloca i32, align 4
366  store i32 0, ptr %min, align 4
367  %addr.data = select i1 %cond_inner, ptr %data_then, ptr %data_else, !prof !0
368  %addr = select i1 %cond_outer, ptr %min, ptr %addr.data, !prof !0
369  %r = load i32, ptr %addr, align 4
370  ret i32 %r
371}
372define i32 @non_speculatable_load_of_select_outer_inverted(i1 %cond_inner, i1 %cond_outer, ptr %data_then, ptr %data_else) {
373; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_load_of_select_outer_inverted(
374; CHECK-PRESERVE-CFG-NEXT:  entry:
375; CHECK-PRESERVE-CFG-NEXT:    [[MIN:%.*]] = alloca i32, align 4
376; CHECK-PRESERVE-CFG-NEXT:    store i32 0, ptr [[MIN]], align 4
377; CHECK-PRESERVE-CFG-NEXT:    [[ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[DATA_THEN:%.*]], ptr [[DATA_ELSE:%.*]], !prof [[PROF0]]
378; CHECK-PRESERVE-CFG-NEXT:    [[ADDR:%.*]] = select i1 [[COND_OUTER:%.*]], ptr [[ADDR_DATA]], ptr [[MIN]], !prof [[PROF0]]
379; CHECK-PRESERVE-CFG-NEXT:    [[R:%.*]] = load i32, ptr [[ADDR]], align 4
380; CHECK-PRESERVE-CFG-NEXT:    ret i32 [[R]]
381;
382; CHECK-MODIFY-CFG-LABEL: @non_speculatable_load_of_select_outer_inverted(
383; CHECK-MODIFY-CFG-NEXT:  entry:
384; CHECK-MODIFY-CFG-NEXT:    [[ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[DATA_THEN:%.*]], ptr [[DATA_ELSE:%.*]], !prof [[PROF1]]
385; CHECK-MODIFY-CFG-NEXT:    br i1 [[COND_OUTER:%.*]], label [[ENTRY_THEN:%.*]], label [[ENTRY_CONT:%.*]], !prof [[PROF1]]
386; CHECK-MODIFY-CFG:       entry.then:
387; CHECK-MODIFY-CFG-NEXT:    [[R_THEN_VAL:%.*]] = load i32, ptr [[ADDR_DATA]], align 4
388; CHECK-MODIFY-CFG-NEXT:    br label [[ENTRY_CONT]]
389; CHECK-MODIFY-CFG:       entry.cont:
390; CHECK-MODIFY-CFG-NEXT:    [[R:%.*]] = phi i32 [ [[R_THEN_VAL]], [[ENTRY_THEN]] ], [ 0, [[ENTRY:%.*]] ]
391; CHECK-MODIFY-CFG-NEXT:    ret i32 [[R]]
392;
393entry:
394  %min = alloca i32, align 4
395  store i32 0, ptr %min, align 4
396  %addr.data = select i1 %cond_inner, ptr %data_then, ptr %data_else, !prof !0
397  %addr = select i1 %cond_outer, ptr %addr.data, ptr %min, !prof !0
398  %r = load i32, ptr %addr, align 4
399  ret i32 %r
400}
401
402define i32 @non_speculatable_load_of_select_inner(i1 %cond_inner, i1 %cond_outer, ptr %data_else, ptr %min_else) {
403; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_load_of_select_inner(
404; CHECK-PRESERVE-CFG-NEXT:  entry:
405; CHECK-PRESERVE-CFG-NEXT:    [[MIN:%.*]] = alloca i32, align 4
406; CHECK-PRESERVE-CFG-NEXT:    store i32 0, ptr [[MIN]], align 4
407; CHECK-PRESERVE-CFG-NEXT:    [[MIN_ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[MIN]], ptr [[MIN_ELSE:%.*]], !prof [[PROF0]]
408; CHECK-PRESERVE-CFG-NEXT:    [[ADDR:%.*]] = select i1 [[COND_OUTER:%.*]], ptr [[MIN_ADDR_DATA]], ptr [[DATA_ELSE:%.*]], !prof [[PROF0]]
409; CHECK-PRESERVE-CFG-NEXT:    [[R:%.*]] = load i32, ptr [[ADDR]], align 4
410; CHECK-PRESERVE-CFG-NEXT:    ret i32 [[R]]
411;
412; CHECK-MODIFY-CFG-LABEL: @non_speculatable_load_of_select_inner(
413; CHECK-MODIFY-CFG-NEXT:  entry:
414; CHECK-MODIFY-CFG-NEXT:    [[MIN:%.*]] = alloca i32, align 4
415; CHECK-MODIFY-CFG-NEXT:    store i32 0, ptr [[MIN]], align 4
416; CHECK-MODIFY-CFG-NEXT:    [[MIN_ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[MIN]], ptr [[MIN_ELSE:%.*]], !prof [[PROF1]]
417; CHECK-MODIFY-CFG-NEXT:    [[ADDR:%.*]] = select i1 [[COND_OUTER:%.*]], ptr [[MIN_ADDR_DATA]], ptr [[DATA_ELSE:%.*]], !prof [[PROF1]]
418; CHECK-MODIFY-CFG-NEXT:    [[R:%.*]] = load i32, ptr [[ADDR]], align 4
419; CHECK-MODIFY-CFG-NEXT:    ret i32 [[R]]
420;
421entry:
422  %min = alloca i32, align 4
423  store i32 0, ptr %min, align 4
424  %min.addr.data = select i1 %cond_inner, ptr %min, ptr %min_else, !prof !0
425  %addr = select i1 %cond_outer, ptr %min.addr.data, ptr %data_else, !prof !0
426  %r = load i32, ptr %addr, align 4
427  ret i32 %r
428}
429define i32 @non_speculatable_load_of_select_inner_inverted(i1 %cond_inner, i1 %cond_outer, ptr %data_else, ptr %min_then) {
430; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_load_of_select_inner_inverted(
431; CHECK-PRESERVE-CFG-NEXT:  entry:
432; CHECK-PRESERVE-CFG-NEXT:    [[MIN:%.*]] = alloca i32, align 4
433; CHECK-PRESERVE-CFG-NEXT:    store i32 0, ptr [[MIN]], align 4
434; CHECK-PRESERVE-CFG-NEXT:    [[MIN_ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[MIN_THEN:%.*]], ptr [[MIN]], !prof [[PROF0]]
435; CHECK-PRESERVE-CFG-NEXT:    [[ADDR:%.*]] = select i1 [[COND_OUTER:%.*]], ptr [[MIN_ADDR_DATA]], ptr [[DATA_ELSE:%.*]], !prof [[PROF0]]
436; CHECK-PRESERVE-CFG-NEXT:    [[R:%.*]] = load i32, ptr [[ADDR]], align 4
437; CHECK-PRESERVE-CFG-NEXT:    ret i32 [[R]]
438;
439; CHECK-MODIFY-CFG-LABEL: @non_speculatable_load_of_select_inner_inverted(
440; CHECK-MODIFY-CFG-NEXT:  entry:
441; CHECK-MODIFY-CFG-NEXT:    [[MIN:%.*]] = alloca i32, align 4
442; CHECK-MODIFY-CFG-NEXT:    store i32 0, ptr [[MIN]], align 4
443; CHECK-MODIFY-CFG-NEXT:    [[MIN_ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[MIN_THEN:%.*]], ptr [[MIN]], !prof [[PROF1]]
444; CHECK-MODIFY-CFG-NEXT:    [[ADDR:%.*]] = select i1 [[COND_OUTER:%.*]], ptr [[MIN_ADDR_DATA]], ptr [[DATA_ELSE:%.*]], !prof [[PROF1]]
445; CHECK-MODIFY-CFG-NEXT:    [[R:%.*]] = load i32, ptr [[ADDR]], align 4
446; CHECK-MODIFY-CFG-NEXT:    ret i32 [[R]]
447;
448entry:
449  %min = alloca i32, align 4
450  store i32 0, ptr %min, align 4
451  %min.addr.data = select i1 %cond_inner, ptr %min_then, ptr %min, !prof !0
452  %addr = select i1 %cond_outer, ptr %min.addr.data, ptr %data_else, !prof !0
453  %r = load i32, ptr %addr, align 4
454  ret i32 %r
455}
456
457; When promoting speculative instruction, metadata that may trigger immediate UB should be dropped.
458define void @load_of_select_with_noundef_nonnull(ptr %buffer, i1 %b) {
459; CHECK-PRESERVE-CFG-LABEL: @load_of_select_with_noundef_nonnull(
460; CHECK-PRESERVE-CFG-NEXT:    [[UB_PTR:%.*]] = alloca ptr, align 8
461; CHECK-PRESERVE-CFG-NEXT:    [[SELECT_PTR:%.*]] = select i1 [[B:%.*]], ptr [[BUFFER:%.*]], ptr [[UB_PTR]]
462; CHECK-PRESERVE-CFG-NEXT:    [[LOAD_PTR:%.*]] = load ptr, ptr [[SELECT_PTR]], align 8, !nonnull [[META1:![0-9]+]], !noundef [[META1]]
463; CHECK-PRESERVE-CFG-NEXT:    ret void
464;
465; CHECK-MODIFY-CFG-LABEL: @load_of_select_with_noundef_nonnull(
466; CHECK-MODIFY-CFG-NEXT:    br i1 [[B:%.*]], label [[DOTTHEN:%.*]], label [[DOTCONT:%.*]]
467; CHECK-MODIFY-CFG:       .then:
468; CHECK-MODIFY-CFG-NEXT:    [[LOAD_PTR_THEN_VAL:%.*]] = load ptr, ptr [[BUFFER:%.*]], align 8, !nonnull [[META2:![0-9]+]], !noundef [[META2]]
469; CHECK-MODIFY-CFG-NEXT:    br label [[DOTCONT]]
470; CHECK-MODIFY-CFG:       .cont:
471; CHECK-MODIFY-CFG-NEXT:    [[LOAD_PTR:%.*]] = phi ptr [ [[LOAD_PTR_THEN_VAL]], [[DOTTHEN]] ], [ undef, [[TMP0:%.*]] ]
472; CHECK-MODIFY-CFG-NEXT:    ret void
473;
474  %ub_ptr = alloca ptr
475  %select_ptr = select i1 %b, ptr %buffer, ptr %ub_ptr
476  %load_ptr = load ptr, ptr %select_ptr, !nonnull !1, !noundef !1
477  ret void
478}
479
480!0  = !{!"branch_weights", i32 1,  i32 99}
481!1 = !{}
482
483; Ensure that the branch metadata is reversed to match the reversals above.
484
485declare void @llvm.lifetime.start.p0(i64, ptr )
486declare void @llvm.lifetime.end.p0(i64, ptr)
487declare i32 @llvm.smax.i32(i32, i32)
488