llvm-project

Форк
0
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.
9
define <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
;
22
entry:
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.
39
define 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
;
48
entry:
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
declare void @foo_i8(ptr)
61
declare void @foo_i32(ptr)
62

63
; Lifetime intrinsics should not prevent dereferenceability inferrence.
64
define 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
76
  call void @llvm.lifetime.start.p0(i64 4, ptr %min)
77
  store 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
81
  ret i32 %i3
82
}
83

84
; We should recursively evaluate select's.
85
define 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
125
  call void @llvm.lifetime.start.p0(i64 4, ptr %min)
126
  store i32 0, ptr %min, align 4
127
  call void @llvm.lifetime.start.p0(i64 4, ptr %max)
128
  store 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
136
  ret i32 %i3
137
}
138

139
define 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
;
158
entry:
159
  %min = alloca i32, align 4
160
  store 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
163
  ret i32 %r
164
}
165
define 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
;
184
entry:
185
  %max = alloca i32, align 4
186
  store 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
189
  ret i32 %r
190
}
191

192
define 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
;
209
entry:
210
  %min = alloca i32, align 4
211
  store 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
214
  ret i32 %r
215
}
216
define 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
;
233
entry:
234
  %max = alloca i32, align 4
235
  store 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
238
  ret i32 %r
239
}
240

241
define 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
;
262
entry:
263
  %min = alloca i32, align 4
264
  store 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
267
  ret i32 %r
268
}
269
define 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
;
290
entry:
291
  %max = alloca i32, align 4
292
  store 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
295
  ret i32 %r
296
}
297

298
define 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
;
319
entry:
320
  %min = alloca i32, align 4
321
  store 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
325
  ret i32 %r
326
}
327
define 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
;
348
entry:
349
  %min = alloca i32, align 4
350
  store 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
354
  ret i32 %r
355
}
356

357
define 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
;
376
entry:
377
  %min = alloca i32, align 4
378
  store 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
382
  ret i32 %r
383
}
384
define 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
;
403
entry:
404
  %min = alloca i32, align 4
405
  store 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
409
  ret i32 %r
410
}
411

412
; When promoting speculative instruction, metadata that may trigger immediate UB should be dropped.
413
define 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
432
  ret 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

440
declare void @llvm.lifetime.start.p0(i64, ptr )
441
declare void @llvm.lifetime.end.p0(i64, ptr)
442
declare i32 @llvm.smax.i32(i32, i32)
443

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.