Revert r354244 "[DAGCombiner] Eliminate dead stores to stack."
[llvm-complete.git] / test / CodeGen / X86 / speculative-load-hardening.ll
blob32ad43634fc740b985d3517bf098c1215dd6b8f9
1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s --check-prefix=X64
3 ; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu -x86-slh-lfence | FileCheck %s --check-prefix=X64-LFENCE
5 ; FIXME: Add support for 32-bit and other EH ABIs.
7 declare void @leak(i32 %v1, i32 %v2)
9 declare void @sink(i32)
11 define i32 @test_trivial_entry_load(i32* %ptr) speculative_load_hardening {
12 ; X64-LABEL: test_trivial_entry_load:
13 ; X64:       # %bb.0: # %entry
14 ; X64-NEXT:    movq %rsp, %rcx
15 ; X64-NEXT:    movq $-1, %rax
16 ; X64-NEXT:    sarq $63, %rcx
17 ; X64-NEXT:    movl (%rdi), %eax
18 ; X64-NEXT:    orl %ecx, %eax
19 ; X64-NEXT:    shlq $47, %rcx
20 ; X64-NEXT:    orq %rcx, %rsp
21 ; X64-NEXT:    retq
23 ; X64-LFENCE-LABEL: test_trivial_entry_load:
24 ; X64-LFENCE:       # %bb.0: # %entry
25 ; X64-LFENCE-NEXT:    movl (%rdi), %eax
26 ; X64-LFENCE-NEXT:    retq
27 entry:
28   %v = load i32, i32* %ptr
29   ret i32 %v
32 define void @test_basic_conditions(i32 %a, i32 %b, i32 %c, i32* %ptr1, i32* %ptr2, i32** %ptr3) speculative_load_hardening {
33 ; X64-LABEL: test_basic_conditions:
34 ; X64:       # %bb.0: # %entry
35 ; X64-NEXT:    pushq %r15
36 ; X64-NEXT:    .cfi_def_cfa_offset 16
37 ; X64-NEXT:    pushq %r14
38 ; X64-NEXT:    .cfi_def_cfa_offset 24
39 ; X64-NEXT:    pushq %rbx
40 ; X64-NEXT:    .cfi_def_cfa_offset 32
41 ; X64-NEXT:    .cfi_offset %rbx, -32
42 ; X64-NEXT:    .cfi_offset %r14, -24
43 ; X64-NEXT:    .cfi_offset %r15, -16
44 ; X64-NEXT:    movq %rsp, %rax
45 ; X64-NEXT:    movq $-1, %rbx
46 ; X64-NEXT:    sarq $63, %rax
47 ; X64-NEXT:    testl %edi, %edi
48 ; X64-NEXT:    jne .LBB1_1
49 ; X64-NEXT:  # %bb.2: # %then1
50 ; X64-NEXT:    cmovneq %rbx, %rax
51 ; X64-NEXT:    testl %esi, %esi
52 ; X64-NEXT:    je .LBB1_4
53 ; X64-NEXT:  .LBB1_1:
54 ; X64-NEXT:    cmoveq %rbx, %rax
55 ; X64-NEXT:  .LBB1_8: # %exit
56 ; X64-NEXT:    shlq $47, %rax
57 ; X64-NEXT:    orq %rax, %rsp
58 ; X64-NEXT:    popq %rbx
59 ; X64-NEXT:    .cfi_def_cfa_offset 24
60 ; X64-NEXT:    popq %r14
61 ; X64-NEXT:    .cfi_def_cfa_offset 16
62 ; X64-NEXT:    popq %r15
63 ; X64-NEXT:    .cfi_def_cfa_offset 8
64 ; X64-NEXT:    retq
65 ; X64-NEXT:  .LBB1_4: # %then2
66 ; X64-NEXT:    .cfi_def_cfa_offset 32
67 ; X64-NEXT:    movq %r8, %r14
68 ; X64-NEXT:    cmovneq %rbx, %rax
69 ; X64-NEXT:    testl %edx, %edx
70 ; X64-NEXT:    je .LBB1_6
71 ; X64-NEXT:  # %bb.5: # %else3
72 ; X64-NEXT:    cmoveq %rbx, %rax
73 ; X64-NEXT:    movslq (%r9), %rcx
74 ; X64-NEXT:    orq %rax, %rcx
75 ; X64-NEXT:    leaq (%r14,%rcx,4), %r15
76 ; X64-NEXT:    movl %ecx, (%r14,%rcx,4)
77 ; X64-NEXT:    jmp .LBB1_7
78 ; X64-NEXT:  .LBB1_6: # %then3
79 ; X64-NEXT:    cmovneq %rbx, %rax
80 ; X64-NEXT:    movl (%rcx), %ecx
81 ; X64-NEXT:    addl (%r14), %ecx
82 ; X64-NEXT:    movslq %ecx, %rdi
83 ; X64-NEXT:    orq %rax, %rdi
84 ; X64-NEXT:    movl (%r14,%rdi,4), %esi
85 ; X64-NEXT:    orl %eax, %esi
86 ; X64-NEXT:    movq (%r9), %r15
87 ; X64-NEXT:    orq %rax, %r15
88 ; X64-NEXT:    addl (%r15), %esi
89 ; X64-NEXT:    shlq $47, %rax
90 ; X64-NEXT:    # kill: def $edi killed $edi killed $rdi
91 ; X64-NEXT:    orq %rax, %rsp
92 ; X64-NEXT:    callq leak
93 ; X64-NEXT:  .Lslh_ret_addr0:
94 ; X64-NEXT:    movq %rsp, %rax
95 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
96 ; X64-NEXT:    sarq $63, %rax
97 ; X64-NEXT:    cmpq $.Lslh_ret_addr0, %rcx
98 ; X64-NEXT:    cmovneq %rbx, %rax
99 ; X64-NEXT:  .LBB1_7: # %merge
100 ; X64-NEXT:    movslq (%r15), %rcx
101 ; X64-NEXT:    orq %rax, %rcx
102 ; X64-NEXT:    movl $0, (%r14,%rcx,4)
103 ; X64-NEXT:    jmp .LBB1_8
105 ; X64-LFENCE-LABEL: test_basic_conditions:
106 ; X64-LFENCE:       # %bb.0: # %entry
107 ; X64-LFENCE-NEXT:    pushq %r14
108 ; X64-LFENCE-NEXT:    .cfi_def_cfa_offset 16
109 ; X64-LFENCE-NEXT:    pushq %rbx
110 ; X64-LFENCE-NEXT:    .cfi_def_cfa_offset 24
111 ; X64-LFENCE-NEXT:    pushq %rax
112 ; X64-LFENCE-NEXT:    .cfi_def_cfa_offset 32
113 ; X64-LFENCE-NEXT:    .cfi_offset %rbx, -24
114 ; X64-LFENCE-NEXT:    .cfi_offset %r14, -16
115 ; X64-LFENCE-NEXT:    testl %edi, %edi
116 ; X64-LFENCE-NEXT:    jne .LBB1_6
117 ; X64-LFENCE-NEXT:  # %bb.1: # %then1
118 ; X64-LFENCE-NEXT:    lfence
119 ; X64-LFENCE-NEXT:    testl %esi, %esi
120 ; X64-LFENCE-NEXT:    jne .LBB1_6
121 ; X64-LFENCE-NEXT:  # %bb.2: # %then2
122 ; X64-LFENCE-NEXT:    movq %r8, %rbx
123 ; X64-LFENCE-NEXT:    lfence
124 ; X64-LFENCE-NEXT:    testl %edx, %edx
125 ; X64-LFENCE-NEXT:    je .LBB1_3
126 ; X64-LFENCE-NEXT:  # %bb.4: # %else3
127 ; X64-LFENCE-NEXT:    lfence
128 ; X64-LFENCE-NEXT:    movslq (%r9), %rax
129 ; X64-LFENCE-NEXT:    leaq (%rbx,%rax,4), %r14
130 ; X64-LFENCE-NEXT:    movl %eax, (%rbx,%rax,4)
131 ; X64-LFENCE-NEXT:    jmp .LBB1_5
132 ; X64-LFENCE-NEXT:  .LBB1_3: # %then3
133 ; X64-LFENCE-NEXT:    lfence
134 ; X64-LFENCE-NEXT:    movl (%rcx), %eax
135 ; X64-LFENCE-NEXT:    addl (%rbx), %eax
136 ; X64-LFENCE-NEXT:    movslq %eax, %rdi
137 ; X64-LFENCE-NEXT:    movl (%rbx,%rdi,4), %esi
138 ; X64-LFENCE-NEXT:    movq (%r9), %r14
139 ; X64-LFENCE-NEXT:    addl (%r14), %esi
140 ; X64-LFENCE-NEXT:    # kill: def $edi killed $edi killed $rdi
141 ; X64-LFENCE-NEXT:    callq leak
142 ; X64-LFENCE-NEXT:  .LBB1_5: # %merge
143 ; X64-LFENCE-NEXT:    movslq (%r14), %rax
144 ; X64-LFENCE-NEXT:    movl $0, (%rbx,%rax,4)
145 ; X64-LFENCE-NEXT:  .LBB1_6: # %exit
146 ; X64-LFENCE-NEXT:    lfence
147 ; X64-LFENCE-NEXT:    addq $8, %rsp
148 ; X64-LFENCE-NEXT:    .cfi_def_cfa_offset 24
149 ; X64-LFENCE-NEXT:    popq %rbx
150 ; X64-LFENCE-NEXT:    .cfi_def_cfa_offset 16
151 ; X64-LFENCE-NEXT:    popq %r14
152 ; X64-LFENCE-NEXT:    .cfi_def_cfa_offset 8
153 ; X64-LFENCE-NEXT:    retq
154 entry:
155   %a.cmp = icmp eq i32 %a, 0
156   br i1 %a.cmp, label %then1, label %exit
158 then1:
159   %b.cmp = icmp eq i32 %b, 0
160   br i1 %b.cmp, label %then2, label %exit
162 then2:
163   %c.cmp = icmp eq i32 %c, 0
164   br i1 %c.cmp, label %then3, label %else3
166 then3:
167   %secret1 = load i32, i32* %ptr1
168   %secret2 = load i32, i32* %ptr2
169   %secret.sum1 = add i32 %secret1, %secret2
170   %ptr2.idx = getelementptr i32, i32* %ptr2, i32 %secret.sum1
171   %secret3 = load i32, i32* %ptr2.idx
172   %secret4 = load i32*, i32** %ptr3
173   %secret5 = load i32, i32* %secret4
174   %secret.sum2 = add i32 %secret3, %secret5
175   call void @leak(i32 %secret.sum1, i32 %secret.sum2)
176   br label %merge
178 else3:
179   %secret6 = load i32*, i32** %ptr3
180   %cast = ptrtoint i32* %secret6 to i32
181   %ptr2.idx2 = getelementptr i32, i32* %ptr2, i32 %cast
182   store i32 %cast, i32* %ptr2.idx2
183   br label %merge
185 merge:
186   %phi = phi i32* [ %secret4, %then3 ], [ %ptr2.idx2, %else3 ]
187   %secret7 = load i32, i32* %phi
188   %ptr2.idx3 = getelementptr i32, i32* %ptr2, i32 %secret7
189   store i32 0, i32* %ptr2.idx3
190   br label %exit
192 exit:
193   ret void
196 define void @test_basic_loop(i32 %a, i32 %b, i32* %ptr1, i32* %ptr2) nounwind speculative_load_hardening {
197 ; X64-LABEL: test_basic_loop:
198 ; X64:       # %bb.0: # %entry
199 ; X64-NEXT:    pushq %rbp
200 ; X64-NEXT:    pushq %r15
201 ; X64-NEXT:    pushq %r14
202 ; X64-NEXT:    pushq %r12
203 ; X64-NEXT:    pushq %rbx
204 ; X64-NEXT:    movq %rsp, %rax
205 ; X64-NEXT:    movq $-1, %r15
206 ; X64-NEXT:    sarq $63, %rax
207 ; X64-NEXT:    testl %edi, %edi
208 ; X64-NEXT:    je .LBB2_2
209 ; X64-NEXT:  # %bb.1:
210 ; X64-NEXT:    cmoveq %r15, %rax
211 ; X64-NEXT:    jmp .LBB2_5
212 ; X64-NEXT:  .LBB2_2: # %l.header.preheader
213 ; X64-NEXT:    movq %rcx, %r14
214 ; X64-NEXT:    movq %rdx, %r12
215 ; X64-NEXT:    movl %esi, %ebp
216 ; X64-NEXT:    cmovneq %r15, %rax
217 ; X64-NEXT:    xorl %ebx, %ebx
218 ; X64-NEXT:    jmp .LBB2_3
219 ; X64-NEXT:    .p2align 4, 0x90
220 ; X64-NEXT:  .LBB2_6: # in Loop: Header=BB2_3 Depth=1
221 ; X64-NEXT:    cmovgeq %r15, %rax
222 ; X64-NEXT:  .LBB2_3: # %l.header
223 ; X64-NEXT:    # =>This Inner Loop Header: Depth=1
224 ; X64-NEXT:    movslq (%r12), %rcx
225 ; X64-NEXT:    orq %rax, %rcx
226 ; X64-NEXT:    movq %rax, %rdx
227 ; X64-NEXT:    orq %r14, %rdx
228 ; X64-NEXT:    movl (%rdx,%rcx,4), %edi
229 ; X64-NEXT:    shlq $47, %rax
230 ; X64-NEXT:    orq %rax, %rsp
231 ; X64-NEXT:    callq sink
232 ; X64-NEXT:  .Lslh_ret_addr1:
233 ; X64-NEXT:    movq %rsp, %rax
234 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
235 ; X64-NEXT:    sarq $63, %rax
236 ; X64-NEXT:    cmpq $.Lslh_ret_addr1, %rcx
237 ; X64-NEXT:    cmovneq %r15, %rax
238 ; X64-NEXT:    incl %ebx
239 ; X64-NEXT:    cmpl %ebp, %ebx
240 ; X64-NEXT:    jl .LBB2_6
241 ; X64-NEXT:  # %bb.4:
242 ; X64-NEXT:    cmovlq %r15, %rax
243 ; X64-NEXT:  .LBB2_5: # %exit
244 ; X64-NEXT:    shlq $47, %rax
245 ; X64-NEXT:    orq %rax, %rsp
246 ; X64-NEXT:    popq %rbx
247 ; X64-NEXT:    popq %r12
248 ; X64-NEXT:    popq %r14
249 ; X64-NEXT:    popq %r15
250 ; X64-NEXT:    popq %rbp
251 ; X64-NEXT:    retq
253 ; X64-LFENCE-LABEL: test_basic_loop:
254 ; X64-LFENCE:       # %bb.0: # %entry
255 ; X64-LFENCE-NEXT:    pushq %rbp
256 ; X64-LFENCE-NEXT:    pushq %r15
257 ; X64-LFENCE-NEXT:    pushq %r14
258 ; X64-LFENCE-NEXT:    pushq %rbx
259 ; X64-LFENCE-NEXT:    pushq %rax
260 ; X64-LFENCE-NEXT:    testl %edi, %edi
261 ; X64-LFENCE-NEXT:    jne .LBB2_3
262 ; X64-LFENCE-NEXT:  # %bb.1: # %l.header.preheader
263 ; X64-LFENCE-NEXT:    movq %rcx, %r14
264 ; X64-LFENCE-NEXT:    movq %rdx, %r15
265 ; X64-LFENCE-NEXT:    movl %esi, %ebp
266 ; X64-LFENCE-NEXT:    lfence
267 ; X64-LFENCE-NEXT:    xorl %ebx, %ebx
268 ; X64-LFENCE-NEXT:    .p2align 4, 0x90
269 ; X64-LFENCE-NEXT:  .LBB2_2: # %l.header
270 ; X64-LFENCE-NEXT:    # =>This Inner Loop Header: Depth=1
271 ; X64-LFENCE-NEXT:    lfence
272 ; X64-LFENCE-NEXT:    movslq (%r15), %rax
273 ; X64-LFENCE-NEXT:    movl (%r14,%rax,4), %edi
274 ; X64-LFENCE-NEXT:    callq sink
275 ; X64-LFENCE-NEXT:    incl %ebx
276 ; X64-LFENCE-NEXT:    cmpl %ebp, %ebx
277 ; X64-LFENCE-NEXT:    jl .LBB2_2
278 ; X64-LFENCE-NEXT:  .LBB2_3: # %exit
279 ; X64-LFENCE-NEXT:    lfence
280 ; X64-LFENCE-NEXT:    addq $8, %rsp
281 ; X64-LFENCE-NEXT:    popq %rbx
282 ; X64-LFENCE-NEXT:    popq %r14
283 ; X64-LFENCE-NEXT:    popq %r15
284 ; X64-LFENCE-NEXT:    popq %rbp
285 ; X64-LFENCE-NEXT:    retq
286 entry:
287   %a.cmp = icmp eq i32 %a, 0
288   br i1 %a.cmp, label %l.header, label %exit
290 l.header:
291   %i = phi i32 [ 0, %entry ], [ %i.next, %l.header ]
292   %secret = load i32, i32* %ptr1
293   %ptr2.idx = getelementptr i32, i32* %ptr2, i32 %secret
294   %leak = load i32, i32* %ptr2.idx
295   call void @sink(i32 %leak)
296   %i.next = add i32 %i, 1
297   %i.cmp = icmp slt i32 %i.next, %b
298   br i1 %i.cmp, label %l.header, label %exit
300 exit:
301   ret void
304 define void @test_basic_nested_loop(i32 %a, i32 %b, i32 %c, i32* %ptr1, i32* %ptr2) nounwind speculative_load_hardening {
305 ; X64-LABEL: test_basic_nested_loop:
306 ; X64:       # %bb.0: # %entry
307 ; X64-NEXT:    pushq %rbp
308 ; X64-NEXT:    pushq %r15
309 ; X64-NEXT:    pushq %r14
310 ; X64-NEXT:    pushq %r13
311 ; X64-NEXT:    pushq %r12
312 ; X64-NEXT:    pushq %rbx
313 ; X64-NEXT:    pushq %rax
314 ; X64-NEXT:    movq %rsp, %rax
315 ; X64-NEXT:    movq $-1, %rbp
316 ; X64-NEXT:    sarq $63, %rax
317 ; X64-NEXT:    testl %edi, %edi
318 ; X64-NEXT:    je .LBB3_2
319 ; X64-NEXT:  # %bb.1:
320 ; X64-NEXT:    cmoveq %rbp, %rax
321 ; X64-NEXT:    jmp .LBB3_10
322 ; X64-NEXT:  .LBB3_2: # %l1.header.preheader
323 ; X64-NEXT:    movq %r8, %r14
324 ; X64-NEXT:    movq %rcx, %rbx
325 ; X64-NEXT:    movl %edx, %r12d
326 ; X64-NEXT:    movl %esi, %r15d
327 ; X64-NEXT:    cmovneq %rbp, %rax
328 ; X64-NEXT:    xorl %r13d, %r13d
329 ; X64-NEXT:    movl %esi, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
330 ; X64-NEXT:    testl %r15d, %r15d
331 ; X64-NEXT:    jg .LBB3_5
332 ; X64-NEXT:    jmp .LBB3_4
333 ; X64-NEXT:    .p2align 4, 0x90
334 ; X64-NEXT:  .LBB3_12:
335 ; X64-NEXT:    cmovgeq %rbp, %rax
336 ; X64-NEXT:    testl %r15d, %r15d
337 ; X64-NEXT:    jle .LBB3_4
338 ; X64-NEXT:  .LBB3_5: # %l2.header.preheader
339 ; X64-NEXT:    cmovleq %rbp, %rax
340 ; X64-NEXT:    xorl %r15d, %r15d
341 ; X64-NEXT:    jmp .LBB3_6
342 ; X64-NEXT:    .p2align 4, 0x90
343 ; X64-NEXT:  .LBB3_11: # in Loop: Header=BB3_6 Depth=1
344 ; X64-NEXT:    cmovgeq %rbp, %rax
345 ; X64-NEXT:  .LBB3_6: # %l2.header
346 ; X64-NEXT:    # =>This Inner Loop Header: Depth=1
347 ; X64-NEXT:    movslq (%rbx), %rcx
348 ; X64-NEXT:    orq %rax, %rcx
349 ; X64-NEXT:    movq %rax, %rdx
350 ; X64-NEXT:    orq %r14, %rdx
351 ; X64-NEXT:    movl (%rdx,%rcx,4), %edi
352 ; X64-NEXT:    shlq $47, %rax
353 ; X64-NEXT:    orq %rax, %rsp
354 ; X64-NEXT:    callq sink
355 ; X64-NEXT:  .Lslh_ret_addr2:
356 ; X64-NEXT:    movq %rsp, %rax
357 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
358 ; X64-NEXT:    sarq $63, %rax
359 ; X64-NEXT:    cmpq $.Lslh_ret_addr2, %rcx
360 ; X64-NEXT:    cmovneq %rbp, %rax
361 ; X64-NEXT:    incl %r15d
362 ; X64-NEXT:    cmpl %r12d, %r15d
363 ; X64-NEXT:    jl .LBB3_11
364 ; X64-NEXT:  # %bb.7:
365 ; X64-NEXT:    cmovlq %rbp, %rax
366 ; X64-NEXT:    movl {{[-0-9]+}}(%r{{[sb]}}p), %r15d # 4-byte Reload
367 ; X64-NEXT:    jmp .LBB3_8
368 ; X64-NEXT:    .p2align 4, 0x90
369 ; X64-NEXT:  .LBB3_4:
370 ; X64-NEXT:    cmovgq %rbp, %rax
371 ; X64-NEXT:  .LBB3_8: # %l1.latch
372 ; X64-NEXT:    movslq (%rbx), %rcx
373 ; X64-NEXT:    orq %rax, %rcx
374 ; X64-NEXT:    movq %rax, %rdx
375 ; X64-NEXT:    orq %r14, %rdx
376 ; X64-NEXT:    movl (%rdx,%rcx,4), %edi
377 ; X64-NEXT:    shlq $47, %rax
378 ; X64-NEXT:    orq %rax, %rsp
379 ; X64-NEXT:    callq sink
380 ; X64-NEXT:  .Lslh_ret_addr3:
381 ; X64-NEXT:    movq %rsp, %rax
382 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
383 ; X64-NEXT:    sarq $63, %rax
384 ; X64-NEXT:    cmpq $.Lslh_ret_addr3, %rcx
385 ; X64-NEXT:    cmovneq %rbp, %rax
386 ; X64-NEXT:    incl %r13d
387 ; X64-NEXT:    cmpl %r15d, %r13d
388 ; X64-NEXT:    jl .LBB3_12
389 ; X64-NEXT:  # %bb.9:
390 ; X64-NEXT:    cmovlq %rbp, %rax
391 ; X64-NEXT:  .LBB3_10: # %exit
392 ; X64-NEXT:    shlq $47, %rax
393 ; X64-NEXT:    orq %rax, %rsp
394 ; X64-NEXT:    addq $8, %rsp
395 ; X64-NEXT:    popq %rbx
396 ; X64-NEXT:    popq %r12
397 ; X64-NEXT:    popq %r13
398 ; X64-NEXT:    popq %r14
399 ; X64-NEXT:    popq %r15
400 ; X64-NEXT:    popq %rbp
401 ; X64-NEXT:    retq
403 ; X64-LFENCE-LABEL: test_basic_nested_loop:
404 ; X64-LFENCE:       # %bb.0: # %entry
405 ; X64-LFENCE-NEXT:    pushq %rbp
406 ; X64-LFENCE-NEXT:    pushq %r15
407 ; X64-LFENCE-NEXT:    pushq %r14
408 ; X64-LFENCE-NEXT:    pushq %r13
409 ; X64-LFENCE-NEXT:    pushq %r12
410 ; X64-LFENCE-NEXT:    pushq %rbx
411 ; X64-LFENCE-NEXT:    pushq %rax
412 ; X64-LFENCE-NEXT:    testl %edi, %edi
413 ; X64-LFENCE-NEXT:    jne .LBB3_6
414 ; X64-LFENCE-NEXT:  # %bb.1: # %l1.header.preheader
415 ; X64-LFENCE-NEXT:    movq %r8, %r14
416 ; X64-LFENCE-NEXT:    movq %rcx, %rbx
417 ; X64-LFENCE-NEXT:    movl %edx, %r13d
418 ; X64-LFENCE-NEXT:    movl %esi, %r15d
419 ; X64-LFENCE-NEXT:    lfence
420 ; X64-LFENCE-NEXT:    xorl %r12d, %r12d
421 ; X64-LFENCE-NEXT:    .p2align 4, 0x90
422 ; X64-LFENCE-NEXT:  .LBB3_2: # %l1.header
423 ; X64-LFENCE-NEXT:    # =>This Loop Header: Depth=1
424 ; X64-LFENCE-NEXT:    # Child Loop BB3_4 Depth 2
425 ; X64-LFENCE-NEXT:    lfence
426 ; X64-LFENCE-NEXT:    testl %r15d, %r15d
427 ; X64-LFENCE-NEXT:    jle .LBB3_5
428 ; X64-LFENCE-NEXT:  # %bb.3: # %l2.header.preheader
429 ; X64-LFENCE-NEXT:    # in Loop: Header=BB3_2 Depth=1
430 ; X64-LFENCE-NEXT:    lfence
431 ; X64-LFENCE-NEXT:    xorl %ebp, %ebp
432 ; X64-LFENCE-NEXT:    .p2align 4, 0x90
433 ; X64-LFENCE-NEXT:  .LBB3_4: # %l2.header
434 ; X64-LFENCE-NEXT:    # Parent Loop BB3_2 Depth=1
435 ; X64-LFENCE-NEXT:    # => This Inner Loop Header: Depth=2
436 ; X64-LFENCE-NEXT:    lfence
437 ; X64-LFENCE-NEXT:    movslq (%rbx), %rax
438 ; X64-LFENCE-NEXT:    movl (%r14,%rax,4), %edi
439 ; X64-LFENCE-NEXT:    callq sink
440 ; X64-LFENCE-NEXT:    incl %ebp
441 ; X64-LFENCE-NEXT:    cmpl %r13d, %ebp
442 ; X64-LFENCE-NEXT:    jl .LBB3_4
443 ; X64-LFENCE-NEXT:  .LBB3_5: # %l1.latch
444 ; X64-LFENCE-NEXT:    # in Loop: Header=BB3_2 Depth=1
445 ; X64-LFENCE-NEXT:    lfence
446 ; X64-LFENCE-NEXT:    movslq (%rbx), %rax
447 ; X64-LFENCE-NEXT:    movl (%r14,%rax,4), %edi
448 ; X64-LFENCE-NEXT:    callq sink
449 ; X64-LFENCE-NEXT:    incl %r12d
450 ; X64-LFENCE-NEXT:    cmpl %r15d, %r12d
451 ; X64-LFENCE-NEXT:    jl .LBB3_2
452 ; X64-LFENCE-NEXT:  .LBB3_6: # %exit
453 ; X64-LFENCE-NEXT:    lfence
454 ; X64-LFENCE-NEXT:    addq $8, %rsp
455 ; X64-LFENCE-NEXT:    popq %rbx
456 ; X64-LFENCE-NEXT:    popq %r12
457 ; X64-LFENCE-NEXT:    popq %r13
458 ; X64-LFENCE-NEXT:    popq %r14
459 ; X64-LFENCE-NEXT:    popq %r15
460 ; X64-LFENCE-NEXT:    popq %rbp
461 ; X64-LFENCE-NEXT:    retq
462 entry:
463   %a.cmp = icmp eq i32 %a, 0
464   br i1 %a.cmp, label %l1.header, label %exit
466 l1.header:
467   %i = phi i32 [ 0, %entry ], [ %i.next, %l1.latch ]
468   %b.cmp = icmp sgt i32 %b, 0
469   br i1 %b.cmp, label %l2.header, label %l1.latch
471 l2.header:
472   %j = phi i32 [ 0, %l1.header ], [ %j.next, %l2.header ]
473   %secret = load i32, i32* %ptr1
474   %ptr2.idx = getelementptr i32, i32* %ptr2, i32 %secret
475   %leak = load i32, i32* %ptr2.idx
476   call void @sink(i32 %leak)
477   %j.next = add i32 %j, 1
478   %j.cmp = icmp slt i32 %j.next, %c
479   br i1 %j.cmp, label %l2.header, label %l1.latch
481 l1.latch:
482   %secret2 = load i32, i32* %ptr1
483   %ptr2.idx2 = getelementptr i32, i32* %ptr2, i32 %secret2
484   %leak2 = load i32, i32* %ptr2.idx2
485   call void @sink(i32 %leak2)
486   %i.next = add i32 %i, 1
487   %i.cmp = icmp slt i32 %i.next, %b
488   br i1 %i.cmp, label %l1.header, label %exit
490 exit:
491   ret void
494 declare i32 @__gxx_personality_v0(...)
496 declare i8* @__cxa_allocate_exception(i64) local_unnamed_addr
498 declare void @__cxa_throw(i8*, i8*, i8*) local_unnamed_addr
500 define void @test_basic_eh(i32 %a, i32* %ptr1, i32* %ptr2) speculative_load_hardening personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
501 ; X64-LABEL: test_basic_eh:
502 ; X64:       # %bb.0: # %entry
503 ; X64-NEXT:    pushq %rbp
504 ; X64-NEXT:    .cfi_def_cfa_offset 16
505 ; X64-NEXT:    pushq %r15
506 ; X64-NEXT:    .cfi_def_cfa_offset 24
507 ; X64-NEXT:    pushq %r14
508 ; X64-NEXT:    .cfi_def_cfa_offset 32
509 ; X64-NEXT:    pushq %rbx
510 ; X64-NEXT:    .cfi_def_cfa_offset 40
511 ; X64-NEXT:    pushq %rax
512 ; X64-NEXT:    .cfi_def_cfa_offset 48
513 ; X64-NEXT:    .cfi_offset %rbx, -40
514 ; X64-NEXT:    .cfi_offset %r14, -32
515 ; X64-NEXT:    .cfi_offset %r15, -24
516 ; X64-NEXT:    .cfi_offset %rbp, -16
517 ; X64-NEXT:    movq %rsp, %rax
518 ; X64-NEXT:    movq $-1, %r15
519 ; X64-NEXT:    sarq $63, %rax
520 ; X64-NEXT:    cmpl $41, %edi
521 ; X64-NEXT:    jg .LBB4_1
522 ; X64-NEXT:  # %bb.2: # %thrower
523 ; X64-NEXT:    movq %rdx, %r14
524 ; X64-NEXT:    movq %rsi, %rbx
525 ; X64-NEXT:    cmovgq %r15, %rax
526 ; X64-NEXT:    movslq %edi, %rcx
527 ; X64-NEXT:    movl (%rsi,%rcx,4), %ebp
528 ; X64-NEXT:    orl %eax, %ebp
529 ; X64-NEXT:    movl $4, %edi
530 ; X64-NEXT:    shlq $47, %rax
531 ; X64-NEXT:    orq %rax, %rsp
532 ; X64-NEXT:    callq __cxa_allocate_exception
533 ; X64-NEXT:  .Lslh_ret_addr4:
534 ; X64-NEXT:    movq %rsp, %rcx
535 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rdx
536 ; X64-NEXT:    sarq $63, %rcx
537 ; X64-NEXT:    cmpq $.Lslh_ret_addr4, %rdx
538 ; X64-NEXT:    cmovneq %r15, %rcx
539 ; X64-NEXT:    movl %ebp, (%rax)
540 ; X64-NEXT:  .Ltmp0:
541 ; X64-NEXT:    shlq $47, %rcx
542 ; X64-NEXT:    movq %rax, %rdi
543 ; X64-NEXT:    xorl %esi, %esi
544 ; X64-NEXT:    xorl %edx, %edx
545 ; X64-NEXT:    orq %rcx, %rsp
546 ; X64-NEXT:    callq __cxa_throw
547 ; X64-NEXT:  .Lslh_ret_addr5:
548 ; X64-NEXT:    movq %rsp, %rax
549 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
550 ; X64-NEXT:    sarq $63, %rax
551 ; X64-NEXT:    cmpq $.Lslh_ret_addr5, %rcx
552 ; X64-NEXT:    cmovneq %r15, %rax
553 ; X64-NEXT:  .Ltmp1:
554 ; X64-NEXT:    jmp .LBB4_3
555 ; X64-NEXT:  .LBB4_1:
556 ; X64-NEXT:    cmovleq %r15, %rax
557 ; X64-NEXT:  .LBB4_3: # %exit
558 ; X64-NEXT:    shlq $47, %rax
559 ; X64-NEXT:    orq %rax, %rsp
560 ; X64-NEXT:    addq $8, %rsp
561 ; X64-NEXT:    .cfi_def_cfa_offset 40
562 ; X64-NEXT:    popq %rbx
563 ; X64-NEXT:    .cfi_def_cfa_offset 32
564 ; X64-NEXT:    popq %r14
565 ; X64-NEXT:    .cfi_def_cfa_offset 24
566 ; X64-NEXT:    popq %r15
567 ; X64-NEXT:    .cfi_def_cfa_offset 16
568 ; X64-NEXT:    popq %rbp
569 ; X64-NEXT:    .cfi_def_cfa_offset 8
570 ; X64-NEXT:    retq
571 ; X64-NEXT:  .LBB4_4: # %lpad
572 ; X64-NEXT:    .cfi_def_cfa_offset 48
573 ; X64-NEXT:  .Ltmp2:
574 ; X64-NEXT:    movq %rsp, %rcx
575 ; X64-NEXT:    sarq $63, %rcx
576 ; X64-NEXT:    movl (%rax), %eax
577 ; X64-NEXT:    addl (%rbx), %eax
578 ; X64-NEXT:    cltq
579 ; X64-NEXT:    orq %rcx, %rax
580 ; X64-NEXT:    movl (%r14,%rax,4), %edi
581 ; X64-NEXT:    orl %ecx, %edi
582 ; X64-NEXT:    shlq $47, %rcx
583 ; X64-NEXT:    orq %rcx, %rsp
584 ; X64-NEXT:    callq sink
585 ; X64-NEXT:  .Lslh_ret_addr6:
586 ; X64-NEXT:    movq %rsp, %rax
587 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
588 ; X64-NEXT:    sarq $63, %rax
589 ; X64-NEXT:    cmpq $.Lslh_ret_addr6, %rcx
590 ; X64-NEXT:    cmovneq %r15, %rax
592 ; X64-LFENCE-LABEL: test_basic_eh:
593 ; X64-LFENCE:       # %bb.0: # %entry
594 ; X64-LFENCE-NEXT:    pushq %rbp
595 ; X64-LFENCE-NEXT:    .cfi_def_cfa_offset 16
596 ; X64-LFENCE-NEXT:    pushq %r14
597 ; X64-LFENCE-NEXT:    .cfi_def_cfa_offset 24
598 ; X64-LFENCE-NEXT:    pushq %rbx
599 ; X64-LFENCE-NEXT:    .cfi_def_cfa_offset 32
600 ; X64-LFENCE-NEXT:    .cfi_offset %rbx, -32
601 ; X64-LFENCE-NEXT:    .cfi_offset %r14, -24
602 ; X64-LFENCE-NEXT:    .cfi_offset %rbp, -16
603 ; X64-LFENCE-NEXT:    cmpl $41, %edi
604 ; X64-LFENCE-NEXT:    jg .LBB4_2
605 ; X64-LFENCE-NEXT:  # %bb.1: # %thrower
606 ; X64-LFENCE-NEXT:    movq %rdx, %r14
607 ; X64-LFENCE-NEXT:    movq %rsi, %rbx
608 ; X64-LFENCE-NEXT:    lfence
609 ; X64-LFENCE-NEXT:    movslq %edi, %rax
610 ; X64-LFENCE-NEXT:    movl (%rsi,%rax,4), %ebp
611 ; X64-LFENCE-NEXT:    movl $4, %edi
612 ; X64-LFENCE-NEXT:    callq __cxa_allocate_exception
613 ; X64-LFENCE-NEXT:    movl %ebp, (%rax)
614 ; X64-LFENCE-NEXT:  .Ltmp0:
615 ; X64-LFENCE-NEXT:    movq %rax, %rdi
616 ; X64-LFENCE-NEXT:    xorl %esi, %esi
617 ; X64-LFENCE-NEXT:    xorl %edx, %edx
618 ; X64-LFENCE-NEXT:    callq __cxa_throw
619 ; X64-LFENCE-NEXT:  .Ltmp1:
620 ; X64-LFENCE-NEXT:  .LBB4_2: # %exit
621 ; X64-LFENCE-NEXT:    lfence
622 ; X64-LFENCE-NEXT:    popq %rbx
623 ; X64-LFENCE-NEXT:    .cfi_def_cfa_offset 24
624 ; X64-LFENCE-NEXT:    popq %r14
625 ; X64-LFENCE-NEXT:    .cfi_def_cfa_offset 16
626 ; X64-LFENCE-NEXT:    popq %rbp
627 ; X64-LFENCE-NEXT:    .cfi_def_cfa_offset 8
628 ; X64-LFENCE-NEXT:    retq
629 ; X64-LFENCE-NEXT:  .LBB4_3: # %lpad
630 ; X64-LFENCE-NEXT:    .cfi_def_cfa_offset 32
631 ; X64-LFENCE-NEXT:  .Ltmp2:
632 ; X64-LFENCE-NEXT:    movl (%rax), %eax
633 ; X64-LFENCE-NEXT:    addl (%rbx), %eax
634 ; X64-LFENCE-NEXT:    cltq
635 ; X64-LFENCE-NEXT:    movl (%r14,%rax,4), %edi
636 ; X64-LFENCE-NEXT:    callq sink
637 entry:
638   %a.cmp = icmp slt i32 %a, 42
639   br i1 %a.cmp, label %thrower, label %exit
641 thrower:
642   %badidx = getelementptr i32, i32* %ptr1, i32 %a
643   %secret1 = load i32, i32* %badidx
644   %e.ptr = call i8* @__cxa_allocate_exception(i64 4)
645   %e.ptr.cast = bitcast i8* %e.ptr to i32*
646   store i32 %secret1, i32* %e.ptr.cast
647   invoke void @__cxa_throw(i8* %e.ptr, i8* null, i8* null)
648           to label %exit unwind label %lpad
650 exit:
651   ret void
653 lpad:
654   %e = landingpad { i8*, i32 }
655           catch i8* null
656   %e.catch.ptr = extractvalue { i8*, i32 } %e, 0
657   %e.catch.ptr.cast = bitcast i8* %e.catch.ptr to i32*
658   %secret1.catch = load i32, i32* %e.catch.ptr.cast
659   %secret2 = load i32, i32* %ptr1
660   %secret.sum = add i32 %secret1.catch, %secret2
661   %ptr2.idx = getelementptr i32, i32* %ptr2, i32 %secret.sum
662   %leak = load i32, i32* %ptr2.idx
663   call void @sink(i32 %leak)
664   unreachable
667 declare void @sink_float(float)
668 declare void @sink_double(double)
670 ; Test direct and converting loads of floating point values.
671 define void @test_fp_loads(float* %fptr, double* %dptr, i32* %i32ptr, i64* %i64ptr) nounwind speculative_load_hardening {
672 ; X64-LABEL: test_fp_loads:
673 ; X64:       # %bb.0: # %entry
674 ; X64-NEXT:    pushq %r15
675 ; X64-NEXT:    pushq %r14
676 ; X64-NEXT:    pushq %r13
677 ; X64-NEXT:    pushq %r12
678 ; X64-NEXT:    pushq %rbx
679 ; X64-NEXT:    movq %rsp, %rax
680 ; X64-NEXT:    movq %rcx, %r15
681 ; X64-NEXT:    movq %rdx, %r14
682 ; X64-NEXT:    movq %rsi, %rbx
683 ; X64-NEXT:    movq %rdi, %r12
684 ; X64-NEXT:    movq $-1, %r13
685 ; X64-NEXT:    sarq $63, %rax
686 ; X64-NEXT:    orq %rax, %r12
687 ; X64-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
688 ; X64-NEXT:    shlq $47, %rax
689 ; X64-NEXT:    orq %rax, %rsp
690 ; X64-NEXT:    callq sink_float
691 ; X64-NEXT:  .Lslh_ret_addr7:
692 ; X64-NEXT:    movq %rsp, %rax
693 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
694 ; X64-NEXT:    sarq $63, %rax
695 ; X64-NEXT:    cmpq $.Lslh_ret_addr7, %rcx
696 ; X64-NEXT:    cmovneq %r13, %rax
697 ; X64-NEXT:    orq %rax, %rbx
698 ; X64-NEXT:    movsd {{.*#+}} xmm0 = mem[0],zero
699 ; X64-NEXT:    shlq $47, %rax
700 ; X64-NEXT:    orq %rax, %rsp
701 ; X64-NEXT:    callq sink_double
702 ; X64-NEXT:  .Lslh_ret_addr8:
703 ; X64-NEXT:    movq %rsp, %rax
704 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
705 ; X64-NEXT:    sarq $63, %rax
706 ; X64-NEXT:    cmpq $.Lslh_ret_addr8, %rcx
707 ; X64-NEXT:    cmovneq %r13, %rax
708 ; X64-NEXT:    movsd {{.*#+}} xmm0 = mem[0],zero
709 ; X64-NEXT:    cvtsd2ss %xmm0, %xmm0
710 ; X64-NEXT:    shlq $47, %rax
711 ; X64-NEXT:    orq %rax, %rsp
712 ; X64-NEXT:    callq sink_float
713 ; X64-NEXT:  .Lslh_ret_addr9:
714 ; X64-NEXT:    movq %rsp, %rax
715 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
716 ; X64-NEXT:    sarq $63, %rax
717 ; X64-NEXT:    cmpq $.Lslh_ret_addr9, %rcx
718 ; X64-NEXT:    cmovneq %r13, %rax
719 ; X64-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
720 ; X64-NEXT:    cvtss2sd %xmm0, %xmm0
721 ; X64-NEXT:    shlq $47, %rax
722 ; X64-NEXT:    orq %rax, %rsp
723 ; X64-NEXT:    callq sink_double
724 ; X64-NEXT:  .Lslh_ret_addr10:
725 ; X64-NEXT:    movq %rsp, %rax
726 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
727 ; X64-NEXT:    sarq $63, %rax
728 ; X64-NEXT:    cmpq $.Lslh_ret_addr10, %rcx
729 ; X64-NEXT:    cmovneq %r13, %rax
730 ; X64-NEXT:    orq %rax, %r14
731 ; X64-NEXT:    xorps %xmm0, %xmm0
732 ; X64-NEXT:    cvtsi2ssl (%r14), %xmm0
733 ; X64-NEXT:    shlq $47, %rax
734 ; X64-NEXT:    orq %rax, %rsp
735 ; X64-NEXT:    callq sink_float
736 ; X64-NEXT:  .Lslh_ret_addr11:
737 ; X64-NEXT:    movq %rsp, %rax
738 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
739 ; X64-NEXT:    sarq $63, %rax
740 ; X64-NEXT:    cmpq $.Lslh_ret_addr11, %rcx
741 ; X64-NEXT:    cmovneq %r13, %rax
742 ; X64-NEXT:    orq %rax, %r15
743 ; X64-NEXT:    xorps %xmm0, %xmm0
744 ; X64-NEXT:    cvtsi2sdq (%r15), %xmm0
745 ; X64-NEXT:    shlq $47, %rax
746 ; X64-NEXT:    orq %rax, %rsp
747 ; X64-NEXT:    callq sink_double
748 ; X64-NEXT:  .Lslh_ret_addr12:
749 ; X64-NEXT:    movq %rsp, %rax
750 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
751 ; X64-NEXT:    sarq $63, %rax
752 ; X64-NEXT:    cmpq $.Lslh_ret_addr12, %rcx
753 ; X64-NEXT:    cmovneq %r13, %rax
754 ; X64-NEXT:    xorps %xmm0, %xmm0
755 ; X64-NEXT:    cvtsi2ssq (%r15), %xmm0
756 ; X64-NEXT:    shlq $47, %rax
757 ; X64-NEXT:    orq %rax, %rsp
758 ; X64-NEXT:    callq sink_float
759 ; X64-NEXT:  .Lslh_ret_addr13:
760 ; X64-NEXT:    movq %rsp, %rax
761 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
762 ; X64-NEXT:    sarq $63, %rax
763 ; X64-NEXT:    cmpq $.Lslh_ret_addr13, %rcx
764 ; X64-NEXT:    cmovneq %r13, %rax
765 ; X64-NEXT:    xorps %xmm0, %xmm0
766 ; X64-NEXT:    cvtsi2sdl (%r14), %xmm0
767 ; X64-NEXT:    shlq $47, %rax
768 ; X64-NEXT:    orq %rax, %rsp
769 ; X64-NEXT:    callq sink_double
770 ; X64-NEXT:  .Lslh_ret_addr14:
771 ; X64-NEXT:    movq %rsp, %rax
772 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
773 ; X64-NEXT:    sarq $63, %rax
774 ; X64-NEXT:    cmpq $.Lslh_ret_addr14, %rcx
775 ; X64-NEXT:    cmovneq %r13, %rax
776 ; X64-NEXT:    shlq $47, %rax
777 ; X64-NEXT:    orq %rax, %rsp
778 ; X64-NEXT:    popq %rbx
779 ; X64-NEXT:    popq %r12
780 ; X64-NEXT:    popq %r13
781 ; X64-NEXT:    popq %r14
782 ; X64-NEXT:    popq %r15
783 ; X64-NEXT:    retq
785 ; X64-LFENCE-LABEL: test_fp_loads:
786 ; X64-LFENCE:       # %bb.0: # %entry
787 ; X64-LFENCE-NEXT:    pushq %r15
788 ; X64-LFENCE-NEXT:    pushq %r14
789 ; X64-LFENCE-NEXT:    pushq %r12
790 ; X64-LFENCE-NEXT:    pushq %rbx
791 ; X64-LFENCE-NEXT:    pushq %rax
792 ; X64-LFENCE-NEXT:    movq %rcx, %r15
793 ; X64-LFENCE-NEXT:    movq %rdx, %r14
794 ; X64-LFENCE-NEXT:    movq %rsi, %rbx
795 ; X64-LFENCE-NEXT:    movq %rdi, %r12
796 ; X64-LFENCE-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
797 ; X64-LFENCE-NEXT:    callq sink_float
798 ; X64-LFENCE-NEXT:    movsd {{.*#+}} xmm0 = mem[0],zero
799 ; X64-LFENCE-NEXT:    callq sink_double
800 ; X64-LFENCE-NEXT:    movsd {{.*#+}} xmm0 = mem[0],zero
801 ; X64-LFENCE-NEXT:    cvtsd2ss %xmm0, %xmm0
802 ; X64-LFENCE-NEXT:    callq sink_float
803 ; X64-LFENCE-NEXT:    movss {{.*#+}} xmm0 = mem[0],zero,zero,zero
804 ; X64-LFENCE-NEXT:    cvtss2sd %xmm0, %xmm0
805 ; X64-LFENCE-NEXT:    callq sink_double
806 ; X64-LFENCE-NEXT:    xorps %xmm0, %xmm0
807 ; X64-LFENCE-NEXT:    cvtsi2ssl (%r14), %xmm0
808 ; X64-LFENCE-NEXT:    callq sink_float
809 ; X64-LFENCE-NEXT:    xorps %xmm0, %xmm0
810 ; X64-LFENCE-NEXT:    cvtsi2sdq (%r15), %xmm0
811 ; X64-LFENCE-NEXT:    callq sink_double
812 ; X64-LFENCE-NEXT:    xorps %xmm0, %xmm0
813 ; X64-LFENCE-NEXT:    cvtsi2ssq (%r15), %xmm0
814 ; X64-LFENCE-NEXT:    callq sink_float
815 ; X64-LFENCE-NEXT:    xorps %xmm0, %xmm0
816 ; X64-LFENCE-NEXT:    cvtsi2sdl (%r14), %xmm0
817 ; X64-LFENCE-NEXT:    callq sink_double
818 ; X64-LFENCE-NEXT:    addq $8, %rsp
819 ; X64-LFENCE-NEXT:    popq %rbx
820 ; X64-LFENCE-NEXT:    popq %r12
821 ; X64-LFENCE-NEXT:    popq %r14
822 ; X64-LFENCE-NEXT:    popq %r15
823 ; X64-LFENCE-NEXT:    retq
824 entry:
825   %f1 = load float, float* %fptr
826   call void @sink_float(float %f1)
827   %d1 = load double, double* %dptr
828   call void @sink_double(double %d1)
829   %f2.d = load double, double* %dptr
830   %f2 = fptrunc double %f2.d to float
831   call void @sink_float(float %f2)
832   %d2.f = load float, float* %fptr
833   %d2 = fpext float %d2.f to double
834   call void @sink_double(double %d2)
835   %f3.i = load i32, i32* %i32ptr
836   %f3 = sitofp i32 %f3.i to float
837   call void @sink_float(float %f3)
838   %d3.i = load i64, i64* %i64ptr
839   %d3 = sitofp i64 %d3.i to double
840   call void @sink_double(double %d3)
841   %f4.i = load i64, i64* %i64ptr
842   %f4 = sitofp i64 %f4.i to float
843   call void @sink_float(float %f4)
844   %d4.i = load i32, i32* %i32ptr
845   %d4 = sitofp i32 %d4.i to double
846   call void @sink_double(double %d4)
847   ret void
850 declare void @sink_v4f32(<4 x float>)
851 declare void @sink_v2f64(<2 x double>)
852 declare void @sink_v16i8(<16 x i8>)
853 declare void @sink_v8i16(<8 x i16>)
854 declare void @sink_v4i32(<4 x i32>)
855 declare void @sink_v2i64(<2 x i64>)
857 ; Test loads of vectors.
858 define void @test_vec_loads(<4 x float>* %v4f32ptr, <2 x double>* %v2f64ptr, <16 x i8>* %v16i8ptr, <8 x i16>* %v8i16ptr, <4 x i32>* %v4i32ptr, <2 x i64>* %v2i64ptr) nounwind speculative_load_hardening {
859 ; X64-LABEL: test_vec_loads:
860 ; X64:       # %bb.0: # %entry
861 ; X64-NEXT:    pushq %rbp
862 ; X64-NEXT:    pushq %r15
863 ; X64-NEXT:    pushq %r14
864 ; X64-NEXT:    pushq %r13
865 ; X64-NEXT:    pushq %r12
866 ; X64-NEXT:    pushq %rbx
867 ; X64-NEXT:    pushq %rax
868 ; X64-NEXT:    movq %rsp, %rax
869 ; X64-NEXT:    movq %r9, %r14
870 ; X64-NEXT:    movq %r8, %r15
871 ; X64-NEXT:    movq %rcx, %r12
872 ; X64-NEXT:    movq %rdx, %r13
873 ; X64-NEXT:    movq %rsi, %rbx
874 ; X64-NEXT:    movq $-1, %rbp
875 ; X64-NEXT:    sarq $63, %rax
876 ; X64-NEXT:    orq %rax, %rdi
877 ; X64-NEXT:    movaps (%rdi), %xmm0
878 ; X64-NEXT:    shlq $47, %rax
879 ; X64-NEXT:    orq %rax, %rsp
880 ; X64-NEXT:    callq sink_v4f32
881 ; X64-NEXT:  .Lslh_ret_addr15:
882 ; X64-NEXT:    movq %rsp, %rax
883 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
884 ; X64-NEXT:    sarq $63, %rax
885 ; X64-NEXT:    cmpq $.Lslh_ret_addr15, %rcx
886 ; X64-NEXT:    cmovneq %rbp, %rax
887 ; X64-NEXT:    orq %rax, %rbx
888 ; X64-NEXT:    movaps (%rbx), %xmm0
889 ; X64-NEXT:    shlq $47, %rax
890 ; X64-NEXT:    orq %rax, %rsp
891 ; X64-NEXT:    callq sink_v2f64
892 ; X64-NEXT:  .Lslh_ret_addr16:
893 ; X64-NEXT:    movq %rsp, %rax
894 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
895 ; X64-NEXT:    sarq $63, %rax
896 ; X64-NEXT:    cmpq $.Lslh_ret_addr16, %rcx
897 ; X64-NEXT:    cmovneq %rbp, %rax
898 ; X64-NEXT:    orq %rax, %r13
899 ; X64-NEXT:    movaps (%r13), %xmm0
900 ; X64-NEXT:    shlq $47, %rax
901 ; X64-NEXT:    orq %rax, %rsp
902 ; X64-NEXT:    callq sink_v16i8
903 ; X64-NEXT:  .Lslh_ret_addr17:
904 ; X64-NEXT:    movq %rsp, %rax
905 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
906 ; X64-NEXT:    sarq $63, %rax
907 ; X64-NEXT:    cmpq $.Lslh_ret_addr17, %rcx
908 ; X64-NEXT:    cmovneq %rbp, %rax
909 ; X64-NEXT:    orq %rax, %r12
910 ; X64-NEXT:    movaps (%r12), %xmm0
911 ; X64-NEXT:    shlq $47, %rax
912 ; X64-NEXT:    orq %rax, %rsp
913 ; X64-NEXT:    callq sink_v8i16
914 ; X64-NEXT:  .Lslh_ret_addr18:
915 ; X64-NEXT:    movq %rsp, %rax
916 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
917 ; X64-NEXT:    sarq $63, %rax
918 ; X64-NEXT:    cmpq $.Lslh_ret_addr18, %rcx
919 ; X64-NEXT:    cmovneq %rbp, %rax
920 ; X64-NEXT:    orq %rax, %r15
921 ; X64-NEXT:    movaps (%r15), %xmm0
922 ; X64-NEXT:    shlq $47, %rax
923 ; X64-NEXT:    orq %rax, %rsp
924 ; X64-NEXT:    callq sink_v4i32
925 ; X64-NEXT:  .Lslh_ret_addr19:
926 ; X64-NEXT:    movq %rsp, %rax
927 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
928 ; X64-NEXT:    sarq $63, %rax
929 ; X64-NEXT:    cmpq $.Lslh_ret_addr19, %rcx
930 ; X64-NEXT:    cmovneq %rbp, %rax
931 ; X64-NEXT:    orq %rax, %r14
932 ; X64-NEXT:    movaps (%r14), %xmm0
933 ; X64-NEXT:    shlq $47, %rax
934 ; X64-NEXT:    orq %rax, %rsp
935 ; X64-NEXT:    callq sink_v2i64
936 ; X64-NEXT:  .Lslh_ret_addr20:
937 ; X64-NEXT:    movq %rsp, %rax
938 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
939 ; X64-NEXT:    sarq $63, %rax
940 ; X64-NEXT:    cmpq $.Lslh_ret_addr20, %rcx
941 ; X64-NEXT:    cmovneq %rbp, %rax
942 ; X64-NEXT:    shlq $47, %rax
943 ; X64-NEXT:    orq %rax, %rsp
944 ; X64-NEXT:    addq $8, %rsp
945 ; X64-NEXT:    popq %rbx
946 ; X64-NEXT:    popq %r12
947 ; X64-NEXT:    popq %r13
948 ; X64-NEXT:    popq %r14
949 ; X64-NEXT:    popq %r15
950 ; X64-NEXT:    popq %rbp
951 ; X64-NEXT:    retq
953 ; X64-LFENCE-LABEL: test_vec_loads:
954 ; X64-LFENCE:       # %bb.0: # %entry
955 ; X64-LFENCE-NEXT:    pushq %r15
956 ; X64-LFENCE-NEXT:    pushq %r14
957 ; X64-LFENCE-NEXT:    pushq %r13
958 ; X64-LFENCE-NEXT:    pushq %r12
959 ; X64-LFENCE-NEXT:    pushq %rbx
960 ; X64-LFENCE-NEXT:    movq %r9, %r14
961 ; X64-LFENCE-NEXT:    movq %r8, %r15
962 ; X64-LFENCE-NEXT:    movq %rcx, %r12
963 ; X64-LFENCE-NEXT:    movq %rdx, %r13
964 ; X64-LFENCE-NEXT:    movq %rsi, %rbx
965 ; X64-LFENCE-NEXT:    movaps (%rdi), %xmm0
966 ; X64-LFENCE-NEXT:    callq sink_v4f32
967 ; X64-LFENCE-NEXT:    movaps (%rbx), %xmm0
968 ; X64-LFENCE-NEXT:    callq sink_v2f64
969 ; X64-LFENCE-NEXT:    movaps (%r13), %xmm0
970 ; X64-LFENCE-NEXT:    callq sink_v16i8
971 ; X64-LFENCE-NEXT:    movaps (%r12), %xmm0
972 ; X64-LFENCE-NEXT:    callq sink_v8i16
973 ; X64-LFENCE-NEXT:    movaps (%r15), %xmm0
974 ; X64-LFENCE-NEXT:    callq sink_v4i32
975 ; X64-LFENCE-NEXT:    movaps (%r14), %xmm0
976 ; X64-LFENCE-NEXT:    callq sink_v2i64
977 ; X64-LFENCE-NEXT:    popq %rbx
978 ; X64-LFENCE-NEXT:    popq %r12
979 ; X64-LFENCE-NEXT:    popq %r13
980 ; X64-LFENCE-NEXT:    popq %r14
981 ; X64-LFENCE-NEXT:    popq %r15
982 ; X64-LFENCE-NEXT:    retq
983 entry:
984   %x1 = load <4 x float>, <4 x float>* %v4f32ptr
985   call void @sink_v4f32(<4 x float> %x1)
986   %x2 = load <2 x double>, <2 x double>* %v2f64ptr
987   call void @sink_v2f64(<2 x double> %x2)
988   %x3 = load <16 x i8>, <16 x i8>* %v16i8ptr
989   call void @sink_v16i8(<16 x i8> %x3)
990   %x4 = load <8 x i16>, <8 x i16>* %v8i16ptr
991   call void @sink_v8i16(<8 x i16> %x4)
992   %x5 = load <4 x i32>, <4 x i32>* %v4i32ptr
993   call void @sink_v4i32(<4 x i32> %x5)
994   %x6 = load <2 x i64>, <2 x i64>* %v2i64ptr
995   call void @sink_v2i64(<2 x i64> %x6)
996   ret void
999 define void @test_deferred_hardening(i32* %ptr1, i32* %ptr2, i32 %x) nounwind speculative_load_hardening {
1000 ; X64-LABEL: test_deferred_hardening:
1001 ; X64:       # %bb.0: # %entry
1002 ; X64-NEXT:    pushq %r15
1003 ; X64-NEXT:    pushq %r14
1004 ; X64-NEXT:    pushq %rbx
1005 ; X64-NEXT:    movq %rsp, %rax
1006 ; X64-NEXT:    movq %rsi, %r14
1007 ; X64-NEXT:    movq %rdi, %rbx
1008 ; X64-NEXT:    movq $-1, %r15
1009 ; X64-NEXT:    sarq $63, %rax
1010 ; X64-NEXT:    movl (%rdi), %edi
1011 ; X64-NEXT:    incl %edi
1012 ; X64-NEXT:    imull %edx, %edi
1013 ; X64-NEXT:    orl %eax, %edi
1014 ; X64-NEXT:    shlq $47, %rax
1015 ; X64-NEXT:    orq %rax, %rsp
1016 ; X64-NEXT:    callq sink
1017 ; X64-NEXT:  .Lslh_ret_addr21:
1018 ; X64-NEXT:    movq %rsp, %rax
1019 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
1020 ; X64-NEXT:    sarq $63, %rax
1021 ; X64-NEXT:    cmpq $.Lslh_ret_addr21, %rcx
1022 ; X64-NEXT:    cmovneq %r15, %rax
1023 ; X64-NEXT:    movl (%rbx), %ecx
1024 ; X64-NEXT:    movl (%r14), %edx
1025 ; X64-NEXT:    leal 1(%rcx,%rdx), %edi
1026 ; X64-NEXT:    orl %eax, %edi
1027 ; X64-NEXT:    shlq $47, %rax
1028 ; X64-NEXT:    orq %rax, %rsp
1029 ; X64-NEXT:    callq sink
1030 ; X64-NEXT:  .Lslh_ret_addr22:
1031 ; X64-NEXT:    movq %rsp, %rax
1032 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
1033 ; X64-NEXT:    sarq $63, %rax
1034 ; X64-NEXT:    cmpq $.Lslh_ret_addr22, %rcx
1035 ; X64-NEXT:    cmovneq %r15, %rax
1036 ; X64-NEXT:    movl (%rbx), %edi
1037 ; X64-NEXT:    shll $7, %edi
1038 ; X64-NEXT:    orl %eax, %edi
1039 ; X64-NEXT:    shlq $47, %rax
1040 ; X64-NEXT:    orq %rax, %rsp
1041 ; X64-NEXT:    callq sink
1042 ; X64-NEXT:  .Lslh_ret_addr23:
1043 ; X64-NEXT:    movq %rsp, %rax
1044 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
1045 ; X64-NEXT:    sarq $63, %rax
1046 ; X64-NEXT:    cmpq $.Lslh_ret_addr23, %rcx
1047 ; X64-NEXT:    cmovneq %r15, %rax
1048 ; X64-NEXT:    movzwl (%rbx), %ecx
1049 ; X64-NEXT:    sarw $7, %cx
1050 ; X64-NEXT:    movzwl %cx, %edi
1051 ; X64-NEXT:    notl %edi
1052 ; X64-NEXT:    orl %eax, %edi
1053 ; X64-NEXT:    shlq $47, %rax
1054 ; X64-NEXT:    orq %rax, %rsp
1055 ; X64-NEXT:    callq sink
1056 ; X64-NEXT:  .Lslh_ret_addr24:
1057 ; X64-NEXT:    movq %rsp, %rax
1058 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
1059 ; X64-NEXT:    sarq $63, %rax
1060 ; X64-NEXT:    cmpq $.Lslh_ret_addr24, %rcx
1061 ; X64-NEXT:    cmovneq %r15, %rax
1062 ; X64-NEXT:    movzwl (%rbx), %ecx
1063 ; X64-NEXT:    rolw $9, %cx
1064 ; X64-NEXT:    movswl %cx, %edi
1065 ; X64-NEXT:    negl %edi
1066 ; X64-NEXT:    orl %eax, %edi
1067 ; X64-NEXT:    shlq $47, %rax
1068 ; X64-NEXT:    orq %rax, %rsp
1069 ; X64-NEXT:    callq sink
1070 ; X64-NEXT:  .Lslh_ret_addr25:
1071 ; X64-NEXT:    movq %rsp, %rax
1072 ; X64-NEXT:    movq -{{[0-9]+}}(%rsp), %rcx
1073 ; X64-NEXT:    sarq $63, %rax
1074 ; X64-NEXT:    cmpq $.Lslh_ret_addr25, %rcx
1075 ; X64-NEXT:    cmovneq %r15, %rax
1076 ; X64-NEXT:    shlq $47, %rax
1077 ; X64-NEXT:    orq %rax, %rsp
1078 ; X64-NEXT:    popq %rbx
1079 ; X64-NEXT:    popq %r14
1080 ; X64-NEXT:    popq %r15
1081 ; X64-NEXT:    retq
1083 ; X64-LFENCE-LABEL: test_deferred_hardening:
1084 ; X64-LFENCE:       # %bb.0: # %entry
1085 ; X64-LFENCE-NEXT:    pushq %r14
1086 ; X64-LFENCE-NEXT:    pushq %rbx
1087 ; X64-LFENCE-NEXT:    pushq %rax
1088 ; X64-LFENCE-NEXT:    movq %rsi, %r14
1089 ; X64-LFENCE-NEXT:    movq %rdi, %rbx
1090 ; X64-LFENCE-NEXT:    movl (%rdi), %edi
1091 ; X64-LFENCE-NEXT:    incl %edi
1092 ; X64-LFENCE-NEXT:    imull %edx, %edi
1093 ; X64-LFENCE-NEXT:    callq sink
1094 ; X64-LFENCE-NEXT:    movl (%rbx), %eax
1095 ; X64-LFENCE-NEXT:    movl (%r14), %ecx
1096 ; X64-LFENCE-NEXT:    leal 1(%rax,%rcx), %edi
1097 ; X64-LFENCE-NEXT:    callq sink
1098 ; X64-LFENCE-NEXT:    movl (%rbx), %edi
1099 ; X64-LFENCE-NEXT:    shll $7, %edi
1100 ; X64-LFENCE-NEXT:    callq sink
1101 ; X64-LFENCE-NEXT:    movzwl (%rbx), %eax
1102 ; X64-LFENCE-NEXT:    sarw $7, %ax
1103 ; X64-LFENCE-NEXT:    movzwl %ax, %edi
1104 ; X64-LFENCE-NEXT:    notl %edi
1105 ; X64-LFENCE-NEXT:    callq sink
1106 ; X64-LFENCE-NEXT:    movzwl (%rbx), %eax
1107 ; X64-LFENCE-NEXT:    rolw $9, %ax
1108 ; X64-LFENCE-NEXT:    movswl %ax, %edi
1109 ; X64-LFENCE-NEXT:    negl %edi
1110 ; X64-LFENCE-NEXT:    callq sink
1111 ; X64-LFENCE-NEXT:    addq $8, %rsp
1112 ; X64-LFENCE-NEXT:    popq %rbx
1113 ; X64-LFENCE-NEXT:    popq %r14
1114 ; X64-LFENCE-NEXT:    retq
1115 entry:
1116   %a1 = load i32, i32* %ptr1
1117   %a2 = add i32 %a1, 1
1118   %a3 = mul i32 %a2, %x
1119   call void @sink(i32 %a3)
1120   %b1 = load i32, i32* %ptr1
1121   %b2 = add i32 %b1, 1
1122   %b3 = load i32, i32* %ptr2
1123   %b4 = add i32 %b2, %b3
1124   call void @sink(i32 %b4)
1125   %c1 = load i32, i32* %ptr1
1126   %c2 = shl i32 %c1, 7
1127   call void @sink(i32 %c2)
1128   %d1 = load i32, i32* %ptr1
1129   ; Check trunc and integer ops narrower than i32.
1130   %d2 = trunc i32 %d1 to i16
1131   %d3 = ashr i16 %d2, 7
1132   %d4 = zext i16 %d3 to i32
1133   %d5 = xor i32 %d4, -1
1134   call void @sink(i32 %d5)
1135   %e1 = load i32, i32* %ptr1
1136   %e2 = trunc i32 %e1 to i16
1137   %e3 = lshr i16 %e2, 7
1138   %e4 = shl i16 %e2, 9
1139   %e5 = or i16 %e3, %e4
1140   %e6 = sext i16 %e5 to i32
1141   %e7 = sub i32 0, %e6
1142   call void @sink(i32 %e7)
1143   ret void