llvm-project
442 строки · 22.9 Кб
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
25store half 0xHFFFF, ptr %true, align 2
26store 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
33ret <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
54call void @foo_i8(ptr %addr.i8)
55%addr.i32 = load ptr, ptr %addr, align 8
56call void @foo_i32 (ptr %addr.i32)
57ret void
58}
59
60declare void @foo_i8(ptr)
61declare void @foo_i32(ptr)
62
63; Lifetime intrinsics should not prevent dereferenceability inferrence.
64define i32 @interfering_lifetime(ptr %data, i64 %indvars.iv) {
65; CHECK-LABEL: @interfering_lifetime(
66; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV:%.*]]
67; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
68; CHECK-NEXT: [[CMP_I_I:%.*]] = icmp slt i32 [[I1]], 0
69; CHECK-NEXT: [[I3_SROA_SPECULATE_LOAD_FALSE:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
70; CHECK-NEXT: [[I3_SROA_SPECULATED:%.*]] = select i1 [[CMP_I_I]], i32 0, i32 [[I3_SROA_SPECULATE_LOAD_FALSE]]
71; CHECK-NEXT: ret i32 [[I3_SROA_SPECULATED]]
72;
73%min = alloca i32, align 4
74%arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
75%i1 = load i32, ptr %arrayidx, align 4
76call void @llvm.lifetime.start.p0(i64 4, ptr %min)
77store i32 0, ptr %min, align 4
78%cmp.i.i = icmp slt i32 %i1, 0
79%__b.__a.i.i = select i1 %cmp.i.i, ptr %min, ptr %arrayidx
80%i3 = load i32, ptr %__b.__a.i.i, align 4
81ret i32 %i3
82}
83
84; We should recursively evaluate select's.
85define i32 @clamp_load_to_constant_range(ptr %data, i64 %indvars.iv) {
86; CHECK-PRESERVE-CFG-LABEL: @clamp_load_to_constant_range(
87; CHECK-PRESERVE-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4
88; CHECK-PRESERVE-CFG-NEXT: [[MAX:%.*]] = alloca i32, align 4
89; CHECK-PRESERVE-CFG-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV:%.*]]
90; CHECK-PRESERVE-CFG-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[MIN]])
91; CHECK-PRESERVE-CFG-NEXT: store i32 0, ptr [[MIN]], align 4
92; CHECK-PRESERVE-CFG-NEXT: call void @llvm.lifetime.start.p0(i64 4, ptr [[MAX]])
93; CHECK-PRESERVE-CFG-NEXT: store i32 4095, ptr [[MAX]], align 4
94; CHECK-PRESERVE-CFG-NEXT: [[I1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
95; CHECK-PRESERVE-CFG-NEXT: [[CMP_I_I:%.*]] = icmp slt i32 [[I1]], 0
96; CHECK-PRESERVE-CFG-NEXT: [[I2:%.*]] = tail call i32 @llvm.smax.i32(i32 [[I1]], i32 0)
97; CHECK-PRESERVE-CFG-NEXT: [[__B___A_I_I:%.*]] = select i1 [[CMP_I_I]], ptr [[MIN]], ptr [[ARRAYIDX]]
98; CHECK-PRESERVE-CFG-NEXT: [[CMP_I1_I:%.*]] = icmp ugt i32 [[I2]], 4095
99; CHECK-PRESERVE-CFG-NEXT: [[__B___A_I2_I:%.*]] = select i1 [[CMP_I1_I]], ptr [[MAX]], ptr [[__B___A_I_I]]
100; CHECK-PRESERVE-CFG-NEXT: [[I3:%.*]] = load i32, ptr [[__B___A_I2_I]], align 4
101; CHECK-PRESERVE-CFG-NEXT: ret i32 [[I3]]
102;
103; CHECK-MODIFY-CFG-LABEL: @clamp_load_to_constant_range(
104; CHECK-MODIFY-CFG-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[DATA:%.*]], i64 [[INDVARS_IV:%.*]]
105; CHECK-MODIFY-CFG-NEXT: [[I1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
106; CHECK-MODIFY-CFG-NEXT: [[CMP_I_I:%.*]] = icmp slt i32 [[I1]], 0
107; CHECK-MODIFY-CFG-NEXT: [[I2:%.*]] = tail call i32 @llvm.smax.i32(i32 [[I1]], i32 0)
108; CHECK-MODIFY-CFG-NEXT: [[CMP_I1_I:%.*]] = icmp ugt i32 [[I2]], 4095
109; CHECK-MODIFY-CFG-NEXT: br i1 [[CMP_I1_I]], label [[DOTCONT:%.*]], label [[DOTELSE:%.*]]
110; CHECK-MODIFY-CFG: .else:
111; CHECK-MODIFY-CFG-NEXT: br i1 [[CMP_I_I]], label [[DOTELSE_CONT:%.*]], label [[DOTELSE_ELSE:%.*]]
112; CHECK-MODIFY-CFG: .else.else:
113; CHECK-MODIFY-CFG-NEXT: [[I3_ELSE_VAL_ELSE_VAL:%.*]] = load i32, ptr [[ARRAYIDX]], align 4
114; CHECK-MODIFY-CFG-NEXT: br label [[DOTELSE_CONT]]
115; CHECK-MODIFY-CFG: .else.cont:
116; CHECK-MODIFY-CFG-NEXT: [[I3_ELSE_VAL:%.*]] = phi i32 [ 0, [[DOTELSE]] ], [ [[I3_ELSE_VAL_ELSE_VAL]], [[DOTELSE_ELSE]] ]
117; CHECK-MODIFY-CFG-NEXT: br label [[DOTCONT]]
118; CHECK-MODIFY-CFG: .cont:
119; CHECK-MODIFY-CFG-NEXT: [[I3:%.*]] = phi i32 [ 4095, [[TMP0:%.*]] ], [ [[I3_ELSE_VAL]], [[DOTELSE_CONT]] ]
120; CHECK-MODIFY-CFG-NEXT: ret i32 [[I3]]
121;
122%min = alloca i32, align 4
123%max = alloca i32, align 4
124%arrayidx = getelementptr inbounds i32, ptr %data, i64 %indvars.iv
125call void @llvm.lifetime.start.p0(i64 4, ptr %min)
126store i32 0, ptr %min, align 4
127call void @llvm.lifetime.start.p0(i64 4, ptr %max)
128store i32 4095, ptr %max, align 4
129%i1 = load i32, ptr %arrayidx, align 4
130%cmp.i.i = icmp slt i32 %i1, 0
131%i2 = tail call i32 @llvm.smax.i32(i32 %i1, i32 0)
132%__b.__a.i.i = select i1 %cmp.i.i, ptr %min, ptr %arrayidx
133%cmp.i1.i = icmp ugt i32 %i2, 4095
134%__b.__a.i2.i = select i1 %cmp.i1.i, ptr %max, ptr %__b.__a.i.i
135%i3 = load i32, ptr %__b.__a.i2.i, align 4
136ret i32 %i3
137}
138
139define i32 @non_speculatable_load_of_select(i1 %cond, ptr %else.addr) {
140; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_load_of_select(
141; CHECK-PRESERVE-CFG-NEXT: entry:
142; CHECK-PRESERVE-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4
143; CHECK-PRESERVE-CFG-NEXT: store i32 0, ptr [[MIN]], align 4
144; CHECK-PRESERVE-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[MIN]], ptr [[ELSE_ADDR:%.*]], !prof [[PROF0:![0-9]+]]
145; CHECK-PRESERVE-CFG-NEXT: [[R:%.*]] = load i32, ptr [[ADDR]], align 4
146; CHECK-PRESERVE-CFG-NEXT: ret i32 [[R]]
147;
148; CHECK-MODIFY-CFG-LABEL: @non_speculatable_load_of_select(
149; CHECK-MODIFY-CFG-NEXT: entry:
150; CHECK-MODIFY-CFG-NEXT: br i1 [[COND:%.*]], label [[ENTRY_CONT:%.*]], label [[ENTRY_ELSE:%.*]], !prof [[PROF0:![0-9]+]]
151; CHECK-MODIFY-CFG: entry.else:
152; CHECK-MODIFY-CFG-NEXT: [[R_ELSE_VAL:%.*]] = load i32, ptr [[ELSE_ADDR:%.*]], align 4
153; CHECK-MODIFY-CFG-NEXT: br label [[ENTRY_CONT]]
154; CHECK-MODIFY-CFG: entry.cont:
155; CHECK-MODIFY-CFG-NEXT: [[R:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[R_ELSE_VAL]], [[ENTRY_ELSE]] ]
156; CHECK-MODIFY-CFG-NEXT: ret i32 [[R]]
157;
158entry:
159%min = alloca i32, align 4
160store i32 0, ptr %min, align 4
161%addr = select i1 %cond, ptr %min, ptr %else.addr, !prof !0
162%r = load i32, ptr %addr, align 4
163ret i32 %r
164}
165define i32 @non_speculatable_load_of_select_inverted(i1 %cond, ptr %then.addr) {
166; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_load_of_select_inverted(
167; CHECK-PRESERVE-CFG-NEXT: entry:
168; CHECK-PRESERVE-CFG-NEXT: [[MAX:%.*]] = alloca i32, align 4
169; CHECK-PRESERVE-CFG-NEXT: store i32 4095, ptr [[MAX]], align 4
170; CHECK-PRESERVE-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[THEN_ADDR:%.*]], ptr [[MAX]], !prof [[PROF0]]
171; CHECK-PRESERVE-CFG-NEXT: [[R:%.*]] = load i32, ptr [[ADDR]], align 4
172; CHECK-PRESERVE-CFG-NEXT: ret i32 [[R]]
173;
174; CHECK-MODIFY-CFG-LABEL: @non_speculatable_load_of_select_inverted(
175; CHECK-MODIFY-CFG-NEXT: entry:
176; CHECK-MODIFY-CFG-NEXT: br i1 [[COND:%.*]], label [[ENTRY_THEN:%.*]], label [[ENTRY_CONT:%.*]], !prof [[PROF1:![0-9]+]]
177; CHECK-MODIFY-CFG: entry.then:
178; CHECK-MODIFY-CFG-NEXT: [[R_THEN_VAL:%.*]] = load i32, ptr [[THEN_ADDR:%.*]], align 4
179; CHECK-MODIFY-CFG-NEXT: br label [[ENTRY_CONT]]
180; CHECK-MODIFY-CFG: entry.cont:
181; CHECK-MODIFY-CFG-NEXT: [[R:%.*]] = phi i32 [ [[R_THEN_VAL]], [[ENTRY_THEN]] ], [ 4095, [[ENTRY:%.*]] ]
182; CHECK-MODIFY-CFG-NEXT: ret i32 [[R]]
183;
184entry:
185%max = alloca i32, align 4
186store i32 4095, ptr %max, align 4
187%addr = select i1 %cond, ptr %then.addr, ptr %max, !prof !0
188%r = load i32, ptr %addr, align 4
189ret i32 %r
190}
191
192define i32 @non_speculatable_volatile_load_of_select(i1 %cond, ptr %else.addr) {
193; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_volatile_load_of_select(
194; CHECK-PRESERVE-CFG-NEXT: entry:
195; CHECK-PRESERVE-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4
196; CHECK-PRESERVE-CFG-NEXT: store i32 0, ptr [[MIN]], align 4
197; CHECK-PRESERVE-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[MIN]], ptr [[ELSE_ADDR:%.*]], !prof [[PROF0]]
198; CHECK-PRESERVE-CFG-NEXT: [[R:%.*]] = load volatile i32, ptr [[ADDR]], align 4
199; CHECK-PRESERVE-CFG-NEXT: ret i32 [[R]]
200;
201; CHECK-MODIFY-CFG-LABEL: @non_speculatable_volatile_load_of_select(
202; CHECK-MODIFY-CFG-NEXT: entry:
203; CHECK-MODIFY-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4
204; CHECK-MODIFY-CFG-NEXT: store i32 0, ptr [[MIN]], align 4
205; CHECK-MODIFY-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[MIN]], ptr [[ELSE_ADDR:%.*]], !prof [[PROF1]]
206; CHECK-MODIFY-CFG-NEXT: [[R:%.*]] = load volatile i32, ptr [[ADDR]], align 4
207; CHECK-MODIFY-CFG-NEXT: ret i32 [[R]]
208;
209entry:
210%min = alloca i32, align 4
211store i32 0, ptr %min, align 4
212%addr = select i1 %cond, ptr %min, ptr %else.addr, !prof !0
213%r = load volatile i32, ptr %addr, align 4
214ret i32 %r
215}
216define i32 @non_speculatable_volatile_load_of_select_inverted(i1 %cond, ptr %then.addr) {
217; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_volatile_load_of_select_inverted(
218; CHECK-PRESERVE-CFG-NEXT: entry:
219; CHECK-PRESERVE-CFG-NEXT: [[MAX:%.*]] = alloca i32, align 4
220; CHECK-PRESERVE-CFG-NEXT: store i32 4095, ptr [[MAX]], align 4
221; CHECK-PRESERVE-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[THEN_ADDR:%.*]], ptr [[MAX]], !prof [[PROF0]]
222; CHECK-PRESERVE-CFG-NEXT: [[R:%.*]] = load volatile i32, ptr [[ADDR]], align 4
223; CHECK-PRESERVE-CFG-NEXT: ret i32 [[R]]
224;
225; CHECK-MODIFY-CFG-LABEL: @non_speculatable_volatile_load_of_select_inverted(
226; CHECK-MODIFY-CFG-NEXT: entry:
227; CHECK-MODIFY-CFG-NEXT: [[MAX:%.*]] = alloca i32, align 4
228; CHECK-MODIFY-CFG-NEXT: store i32 4095, ptr [[MAX]], align 4
229; CHECK-MODIFY-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[THEN_ADDR:%.*]], ptr [[MAX]], !prof [[PROF1]]
230; CHECK-MODIFY-CFG-NEXT: [[R:%.*]] = load volatile i32, ptr [[ADDR]], align 4
231; CHECK-MODIFY-CFG-NEXT: ret i32 [[R]]
232;
233entry:
234%max = alloca i32, align 4
235store i32 4095, ptr %max, align 4
236%addr = select i1 %cond, ptr %then.addr, ptr %max, !prof !0
237%r = load volatile i32, ptr %addr, align 4
238ret i32 %r
239}
240
241define i32 @non_speculatable_atomic_unord_load_of_select(i1 %cond, ptr %else.addr) {
242; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_atomic_unord_load_of_select(
243; CHECK-PRESERVE-CFG-NEXT: entry:
244; CHECK-PRESERVE-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4
245; CHECK-PRESERVE-CFG-NEXT: store i32 0, ptr [[MIN]], align 4
246; CHECK-PRESERVE-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[MIN]], ptr [[ELSE_ADDR:%.*]], !prof [[PROF0]]
247; CHECK-PRESERVE-CFG-NEXT: [[R:%.*]] = load atomic i32, ptr [[ADDR]] unordered, align 4
248; CHECK-PRESERVE-CFG-NEXT: ret i32 [[R]]
249;
250; CHECK-MODIFY-CFG-LABEL: @non_speculatable_atomic_unord_load_of_select(
251; CHECK-MODIFY-CFG-NEXT: entry:
252; CHECK-MODIFY-CFG-NEXT: br i1 [[COND:%.*]], label [[ENTRY_THEN:%.*]], label [[ENTRY_ELSE:%.*]], !prof [[PROF1]]
253; CHECK-MODIFY-CFG: entry.then:
254; CHECK-MODIFY-CFG-NEXT: br label [[ENTRY_CONT:%.*]]
255; CHECK-MODIFY-CFG: entry.else:
256; CHECK-MODIFY-CFG-NEXT: [[R_ELSE_VAL:%.*]] = load atomic i32, ptr [[ELSE_ADDR:%.*]] unordered, align 4
257; CHECK-MODIFY-CFG-NEXT: br label [[ENTRY_CONT]]
258; CHECK-MODIFY-CFG: entry.cont:
259; CHECK-MODIFY-CFG-NEXT: [[R:%.*]] = phi i32 [ 0, [[ENTRY_THEN]] ], [ [[R_ELSE_VAL]], [[ENTRY_ELSE]] ]
260; CHECK-MODIFY-CFG-NEXT: ret i32 [[R]]
261;
262entry:
263%min = alloca i32, align 4
264store i32 0, ptr %min, align 4
265%addr = select i1 %cond, ptr %min, ptr %else.addr, !prof !0
266%r = load atomic i32, ptr %addr unordered, align 4
267ret i32 %r
268}
269define i32 @non_speculatable_atomic_unord_load_of_select_inverted(i1 %cond, ptr %then.addr) {
270; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_atomic_unord_load_of_select_inverted(
271; CHECK-PRESERVE-CFG-NEXT: entry:
272; CHECK-PRESERVE-CFG-NEXT: [[MAX:%.*]] = alloca i32, align 4
273; CHECK-PRESERVE-CFG-NEXT: store i32 4095, ptr [[MAX]], align 4
274; CHECK-PRESERVE-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND:%.*]], ptr [[THEN_ADDR:%.*]], ptr [[MAX]], !prof [[PROF0]]
275; CHECK-PRESERVE-CFG-NEXT: [[R:%.*]] = load atomic i32, ptr [[ADDR]] unordered, align 4
276; CHECK-PRESERVE-CFG-NEXT: ret i32 [[R]]
277;
278; CHECK-MODIFY-CFG-LABEL: @non_speculatable_atomic_unord_load_of_select_inverted(
279; CHECK-MODIFY-CFG-NEXT: entry:
280; CHECK-MODIFY-CFG-NEXT: br i1 [[COND:%.*]], label [[ENTRY_THEN:%.*]], label [[ENTRY_ELSE:%.*]], !prof [[PROF1]]
281; CHECK-MODIFY-CFG: entry.then:
282; CHECK-MODIFY-CFG-NEXT: [[R_THEN_VAL:%.*]] = load atomic i32, ptr [[THEN_ADDR:%.*]] unordered, align 4
283; CHECK-MODIFY-CFG-NEXT: br label [[ENTRY_CONT:%.*]]
284; CHECK-MODIFY-CFG: entry.else:
285; CHECK-MODIFY-CFG-NEXT: br label [[ENTRY_CONT]]
286; CHECK-MODIFY-CFG: entry.cont:
287; CHECK-MODIFY-CFG-NEXT: [[R:%.*]] = phi i32 [ [[R_THEN_VAL]], [[ENTRY_THEN]] ], [ 4095, [[ENTRY_ELSE]] ]
288; CHECK-MODIFY-CFG-NEXT: ret i32 [[R]]
289;
290entry:
291%max = alloca i32, align 4
292store i32 4095, ptr %max, align 4
293%addr = select i1 %cond, ptr %then.addr, ptr %max, !prof !0
294%r = load atomic i32, ptr %addr unordered, align 4
295ret i32 %r
296}
297
298define i32 @non_speculatable_load_of_select_outer(i1 %cond_inner, i1 %cond_outer, ptr %data_then, ptr %data_else) {
299; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_load_of_select_outer(
300; CHECK-PRESERVE-CFG-NEXT: entry:
301; CHECK-PRESERVE-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4
302; CHECK-PRESERVE-CFG-NEXT: store i32 0, ptr [[MIN]], align 4
303; CHECK-PRESERVE-CFG-NEXT: [[ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[DATA_THEN:%.*]], ptr [[DATA_ELSE:%.*]], !prof [[PROF0]]
304; CHECK-PRESERVE-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND_OUTER:%.*]], ptr [[MIN]], ptr [[ADDR_DATA]], !prof [[PROF0]]
305; CHECK-PRESERVE-CFG-NEXT: [[R:%.*]] = load i32, ptr [[ADDR]], align 4
306; CHECK-PRESERVE-CFG-NEXT: ret i32 [[R]]
307;
308; CHECK-MODIFY-CFG-LABEL: @non_speculatable_load_of_select_outer(
309; CHECK-MODIFY-CFG-NEXT: entry:
310; CHECK-MODIFY-CFG-NEXT: [[ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[DATA_THEN:%.*]], ptr [[DATA_ELSE:%.*]], !prof [[PROF1]]
311; CHECK-MODIFY-CFG-NEXT: br i1 [[COND_OUTER:%.*]], label [[ENTRY_CONT:%.*]], label [[ENTRY_ELSE:%.*]], !prof [[PROF0]]
312; CHECK-MODIFY-CFG: entry.else:
313; CHECK-MODIFY-CFG-NEXT: [[R_ELSE_VAL:%.*]] = load i32, ptr [[ADDR_DATA]], align 4
314; CHECK-MODIFY-CFG-NEXT: br label [[ENTRY_CONT]]
315; CHECK-MODIFY-CFG: entry.cont:
316; CHECK-MODIFY-CFG-NEXT: [[R:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[R_ELSE_VAL]], [[ENTRY_ELSE]] ]
317; CHECK-MODIFY-CFG-NEXT: ret i32 [[R]]
318;
319entry:
320%min = alloca i32, align 4
321store i32 0, ptr %min, align 4
322%addr.data = select i1 %cond_inner, ptr %data_then, ptr %data_else, !prof !0
323%addr = select i1 %cond_outer, ptr %min, ptr %addr.data, !prof !0
324%r = load i32, ptr %addr, align 4
325ret i32 %r
326}
327define i32 @non_speculatable_load_of_select_outer_inverted(i1 %cond_inner, i1 %cond_outer, ptr %data_then, ptr %data_else) {
328; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_load_of_select_outer_inverted(
329; CHECK-PRESERVE-CFG-NEXT: entry:
330; CHECK-PRESERVE-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4
331; CHECK-PRESERVE-CFG-NEXT: store i32 0, ptr [[MIN]], align 4
332; CHECK-PRESERVE-CFG-NEXT: [[ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[DATA_THEN:%.*]], ptr [[DATA_ELSE:%.*]], !prof [[PROF0]]
333; CHECK-PRESERVE-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND_OUTER:%.*]], ptr [[ADDR_DATA]], ptr [[MIN]], !prof [[PROF0]]
334; CHECK-PRESERVE-CFG-NEXT: [[R:%.*]] = load i32, ptr [[ADDR]], align 4
335; CHECK-PRESERVE-CFG-NEXT: ret i32 [[R]]
336;
337; CHECK-MODIFY-CFG-LABEL: @non_speculatable_load_of_select_outer_inverted(
338; CHECK-MODIFY-CFG-NEXT: entry:
339; CHECK-MODIFY-CFG-NEXT: [[ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[DATA_THEN:%.*]], ptr [[DATA_ELSE:%.*]], !prof [[PROF1]]
340; CHECK-MODIFY-CFG-NEXT: br i1 [[COND_OUTER:%.*]], label [[ENTRY_THEN:%.*]], label [[ENTRY_CONT:%.*]], !prof [[PROF1]]
341; CHECK-MODIFY-CFG: entry.then:
342; CHECK-MODIFY-CFG-NEXT: [[R_THEN_VAL:%.*]] = load i32, ptr [[ADDR_DATA]], align 4
343; CHECK-MODIFY-CFG-NEXT: br label [[ENTRY_CONT]]
344; CHECK-MODIFY-CFG: entry.cont:
345; CHECK-MODIFY-CFG-NEXT: [[R:%.*]] = phi i32 [ [[R_THEN_VAL]], [[ENTRY_THEN]] ], [ 0, [[ENTRY:%.*]] ]
346; CHECK-MODIFY-CFG-NEXT: ret i32 [[R]]
347;
348entry:
349%min = alloca i32, align 4
350store i32 0, ptr %min, align 4
351%addr.data = select i1 %cond_inner, ptr %data_then, ptr %data_else, !prof !0
352%addr = select i1 %cond_outer, ptr %addr.data, ptr %min, !prof !0
353%r = load i32, ptr %addr, align 4
354ret i32 %r
355}
356
357define i32 @non_speculatable_load_of_select_inner(i1 %cond_inner, i1 %cond_outer, ptr %data_else, ptr %min_else) {
358; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_load_of_select_inner(
359; CHECK-PRESERVE-CFG-NEXT: entry:
360; CHECK-PRESERVE-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4
361; CHECK-PRESERVE-CFG-NEXT: store i32 0, ptr [[MIN]], align 4
362; CHECK-PRESERVE-CFG-NEXT: [[MIN_ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[MIN]], ptr [[MIN_ELSE:%.*]], !prof [[PROF0]]
363; CHECK-PRESERVE-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND_OUTER:%.*]], ptr [[MIN_ADDR_DATA]], ptr [[DATA_ELSE:%.*]], !prof [[PROF0]]
364; CHECK-PRESERVE-CFG-NEXT: [[R:%.*]] = load i32, ptr [[ADDR]], align 4
365; CHECK-PRESERVE-CFG-NEXT: ret i32 [[R]]
366;
367; CHECK-MODIFY-CFG-LABEL: @non_speculatable_load_of_select_inner(
368; CHECK-MODIFY-CFG-NEXT: entry:
369; CHECK-MODIFY-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4
370; CHECK-MODIFY-CFG-NEXT: store i32 0, ptr [[MIN]], align 4
371; CHECK-MODIFY-CFG-NEXT: [[MIN_ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[MIN]], ptr [[MIN_ELSE:%.*]], !prof [[PROF1]]
372; CHECK-MODIFY-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND_OUTER:%.*]], ptr [[MIN_ADDR_DATA]], ptr [[DATA_ELSE:%.*]], !prof [[PROF1]]
373; CHECK-MODIFY-CFG-NEXT: [[R:%.*]] = load i32, ptr [[ADDR]], align 4
374; CHECK-MODIFY-CFG-NEXT: ret i32 [[R]]
375;
376entry:
377%min = alloca i32, align 4
378store i32 0, ptr %min, align 4
379%min.addr.data = select i1 %cond_inner, ptr %min, ptr %min_else, !prof !0
380%addr = select i1 %cond_outer, ptr %min.addr.data, ptr %data_else, !prof !0
381%r = load i32, ptr %addr, align 4
382ret i32 %r
383}
384define i32 @non_speculatable_load_of_select_inner_inverted(i1 %cond_inner, i1 %cond_outer, ptr %data_else, ptr %min_then) {
385; CHECK-PRESERVE-CFG-LABEL: @non_speculatable_load_of_select_inner_inverted(
386; CHECK-PRESERVE-CFG-NEXT: entry:
387; CHECK-PRESERVE-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4
388; CHECK-PRESERVE-CFG-NEXT: store i32 0, ptr [[MIN]], align 4
389; CHECK-PRESERVE-CFG-NEXT: [[MIN_ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[MIN_THEN:%.*]], ptr [[MIN]], !prof [[PROF0]]
390; CHECK-PRESERVE-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND_OUTER:%.*]], ptr [[MIN_ADDR_DATA]], ptr [[DATA_ELSE:%.*]], !prof [[PROF0]]
391; CHECK-PRESERVE-CFG-NEXT: [[R:%.*]] = load i32, ptr [[ADDR]], align 4
392; CHECK-PRESERVE-CFG-NEXT: ret i32 [[R]]
393;
394; CHECK-MODIFY-CFG-LABEL: @non_speculatable_load_of_select_inner_inverted(
395; CHECK-MODIFY-CFG-NEXT: entry:
396; CHECK-MODIFY-CFG-NEXT: [[MIN:%.*]] = alloca i32, align 4
397; CHECK-MODIFY-CFG-NEXT: store i32 0, ptr [[MIN]], align 4
398; CHECK-MODIFY-CFG-NEXT: [[MIN_ADDR_DATA:%.*]] = select i1 [[COND_INNER:%.*]], ptr [[MIN_THEN:%.*]], ptr [[MIN]], !prof [[PROF1]]
399; CHECK-MODIFY-CFG-NEXT: [[ADDR:%.*]] = select i1 [[COND_OUTER:%.*]], ptr [[MIN_ADDR_DATA]], ptr [[DATA_ELSE:%.*]], !prof [[PROF1]]
400; CHECK-MODIFY-CFG-NEXT: [[R:%.*]] = load i32, ptr [[ADDR]], align 4
401; CHECK-MODIFY-CFG-NEXT: ret i32 [[R]]
402;
403entry:
404%min = alloca i32, align 4
405store i32 0, ptr %min, align 4
406%min.addr.data = select i1 %cond_inner, ptr %min_then, ptr %min, !prof !0
407%addr = select i1 %cond_outer, ptr %min.addr.data, ptr %data_else, !prof !0
408%r = load i32, ptr %addr, align 4
409ret i32 %r
410}
411
412; When promoting speculative instruction, metadata that may trigger immediate UB should be dropped.
413define void @load_of_select_with_noundef_nonnull(ptr %buffer, i1 %b) {
414; CHECK-PRESERVE-CFG-LABEL: @load_of_select_with_noundef_nonnull(
415; CHECK-PRESERVE-CFG-NEXT: [[UB_PTR:%.*]] = alloca ptr, align 8
416; CHECK-PRESERVE-CFG-NEXT: [[SELECT_PTR:%.*]] = select i1 [[B:%.*]], ptr [[BUFFER:%.*]], ptr [[UB_PTR]]
417; CHECK-PRESERVE-CFG-NEXT: [[LOAD_PTR:%.*]] = load ptr, ptr [[SELECT_PTR]], align 8, !nonnull !1, !noundef !1
418; CHECK-PRESERVE-CFG-NEXT: ret void
419;
420; CHECK-MODIFY-CFG-LABEL: @load_of_select_with_noundef_nonnull(
421; CHECK-MODIFY-CFG-NEXT: br i1 [[B:%.*]], label [[DOTTHEN:%.*]], label [[DOTCONT:%.*]]
422; CHECK-MODIFY-CFG: .then:
423; CHECK-MODIFY-CFG-NEXT: [[LOAD_PTR_THEN_VAL:%.*]] = load ptr, ptr [[BUFFER:%.*]], align 8, !nonnull !2, !noundef !2
424; CHECK-MODIFY-CFG-NEXT: br label [[DOTCONT]]
425; CHECK-MODIFY-CFG: .cont:
426; CHECK-MODIFY-CFG-NEXT: [[LOAD_PTR:%.*]] = phi ptr [ [[LOAD_PTR_THEN_VAL]], [[DOTTHEN]] ], [ undef, [[TMP0:%.*]] ]
427; CHECK-MODIFY-CFG-NEXT: ret void
428;
429%ub_ptr = alloca ptr
430%select_ptr = select i1 %b, ptr %buffer, ptr %ub_ptr
431%load_ptr = load ptr, ptr %select_ptr, !nonnull !1, !noundef !1
432ret void
433}
434
435!0 = !{!"branch_weights", i32 1, i32 99}
436!1 = !{}
437
438; Ensure that the branch metadata is reversed to match the reversals above.
439
440declare void @llvm.lifetime.start.p0(i64, ptr )
441declare void @llvm.lifetime.end.p0(i64, ptr)
442declare i32 @llvm.smax.i32(i32, i32)
443