1 # RUN: llc -march=x86-64 -run-pass none -o - %s | FileCheck %s
2 # This test ensures that the MIR parser parses the machine memory operands
7 define i32 @test(ptr %a) {
14 define void @test2(ptr %"a value") {
16 %b = load i32, ptr %"a value"
18 store i32 %c, ptr %"a value"
22 define void @test3(ptr) {
31 define i32 @volatile_inc(ptr %x) {
33 %0 = load volatile i32, ptr %x
35 store volatile i32 %1, ptr %x
39 define void @non_temporal_store(ptr %a, i32 %b) {
41 store i32 %b, ptr %a, align 16, !nontemporal !0
47 define i32 @invariant_load(ptr %x) {
49 %v = load i32, ptr %x, !invariant.load !1
55 define void @memory_offset(ptr %vec) {
57 %v = load <8 x float>, ptr %vec
58 %v2 = insertelement <8 x float> %v, float 0.0, i32 4
59 store <8 x float> %v2, ptr %vec
63 define void @memory_alignment(ptr %vec) {
65 %v = load <16 x float>, ptr %vec
66 %v2 = insertelement <16 x float> %v, float 0.0, i32 4
67 store <16 x float> %v2, ptr %vec
71 define double @constant_pool_psv(double %a) {
73 %b = fadd double %a, 3.250000e+00
77 declare x86_fp80 @cosl(x86_fp80) #0
79 define x86_fp80 @stack_psv(x86_fp80 %x) {
81 %y = call x86_fp80 @cosl(x86_fp80 %x) #0
85 attributes #0 = { readonly }
87 @G = external global i32
89 define i32 @got_psv() {
96 @0 = external global i32
98 define i32 @global_value() {
100 %a = load i32, ptr @G
102 %c = load i32, ptr @0
107 define i32 @jumptable_psv(i32 %in) {
109 switch i32 %in, label %def [
127 %struct.XXH_state64_t = type { i32, i32, i64, i64, i64 }
129 @a = common global i32 0, align 4
131 define i32 @tbaa_metadata() {
133 %0 = load i32, ptr @a, align 4, !tbaa !2
134 %1 = inttoptr i32 %0 to ptr
135 %2 = load i32, ptr %1, align 4, !tbaa !6
139 !2 = !{!3, !3, i64 0}
140 !3 = !{!"int", !4, i64 0}
141 !4 = !{!"omnipotent char", !5, i64 0}
142 !5 = !{!"Simple C/C++ TBAA"}
143 !6 = !{!7, !3, i64 0}
144 !7 = !{!"XXH_state64_t", !3, i64 0, !3, i64 4, !8, i64 8, !8, i64 16, !8, i64 24}
145 !8 = !{!"long long", !4, i64 0}
147 define void @aa_scope(ptr nocapture %a, ptr nocapture readonly %c) #1 {
149 %0 = load float, ptr %c, align 4, !alias.scope !9
150 %arrayidx.i = getelementptr inbounds float, ptr %a, i64 5
151 store float %0, ptr %arrayidx.i, align 4, !noalias !9
152 %1 = load float, ptr %c, align 4
153 %arrayidx = getelementptr inbounds float, ptr %a, i64 7
154 store float %1, ptr %arrayidx, align 4
158 attributes #1 = { nounwind uwtable }
161 !10 = distinct !{!10, !11, !"some scope"}
162 !11 = distinct !{!11, !"some domain"}
164 define zeroext i1 @range_metadata(ptr %x) {
166 %0 = load i8, ptr %x, align 1, !range !12
167 %tobool = trunc i8 %0 to i1
173 %st = type { i32, i32 }
175 @values = common global [50 x %st] zeroinitializer, align 16
177 define void @gep_value(i64 %d) {
179 %conv = trunc i64 %d to i32
180 store i32 %conv, ptr @values, align 16
184 define ptr @undef_value() {
186 %0 = load ptr, ptr undef, align 8
190 define void @dummy0() { ret void }
191 define void @dummy1() { ret void }
192 define void @dummy2() { ret void }
193 define void @dummy3() { ret void }
197 tracksRegLiveness: true
203 ; CHECK: $eax = MOV32rm $rdi, 1, $noreg, 0, $noreg :: (load (s32) from %ir.a)
204 ; CHECK-NEXT: MOV32mi killed $rdi, 1, $noreg, 0, $noreg, 42 :: (store (s32) into %ir.a)
205 $eax = MOV32rm $rdi, 1, _, 0, _ :: (load (s32) from %ir.a)
206 MOV32mi killed $rdi, 1, _, 0, _, 42 :: (store (s32) into %ir.a)
211 tracksRegLiveness: true
217 ; CHECK: INC32m killed $rdi, 1, $noreg, 0, $noreg, implicit-def dead $eflags :: (store (s32) into %ir."a value"), (load (s32) from %ir."a value")
218 INC32m killed $rdi, 1, _, 0, _, implicit-def dead $eflags :: (store (s32) into %ir."a value"), (load (s32) from %ir."a value")
223 tracksRegLiveness: true
229 - { id: 0, offset: -12, size: 4, alignment: 4 }
233 ; Verify that the unnamed local values can be serialized.
234 ; CHECK-LABEL: name: test3
235 ; CHECK: $eax = MOV32rm killed $rdi, 1, $noreg, 0, $noreg :: (load (s32) from %ir.0)
236 ; CHECK: MOV32mr $rsp, 1, $noreg, -4, $noreg, killed $eax :: (store (s32) into %ir.1)
237 $eax = MOV32rm killed $rdi, 1, _, 0, _ :: (load (s32) from %ir.0)
238 $eax = INC32r killed $eax, implicit-def dead $eflags
239 MOV32mr $rsp, 1, _, -4, _, killed $eax :: (store (s32) into %ir.1)
244 tracksRegLiveness: true
250 ; CHECK: name: volatile_inc
251 ; CHECK: $eax = MOV32rm $rdi, 1, $noreg, 0, $noreg :: (volatile load (s32) from %ir.x)
252 ; CHECK: MOV32mr killed $rdi, 1, $noreg, 0, $noreg, $eax :: (volatile store (s32) into %ir.x)
253 $eax = MOV32rm $rdi, 1, _, 0, _ :: (volatile load (s32) from %ir.x)
254 $eax = INC32r killed $eax, implicit-def dead $eflags
255 MOV32mr killed $rdi, 1, _, 0, _, $eax :: (volatile store (s32) into %ir.x)
259 name: non_temporal_store
260 tracksRegLiveness: true
267 ; CHECK: name: non_temporal_store
268 ; CHECK: MOVNTImr killed $rdi, 1, $noreg, 0, $noreg, killed $esi :: (non-temporal store (s32) into %ir.a)
269 MOVNTImr killed $rdi, 1, _, 0, _, killed $esi :: (non-temporal store (s32) into %ir.a)
274 tracksRegLiveness: true
280 ; CHECK: name: invariant_load
281 ; CHECK: $eax = MOV32rm killed $rdi, 1, $noreg, 0, $noreg :: (invariant load (s32) from %ir.x)
282 $eax = MOV32rm killed $rdi, 1, _, 0, _ :: (invariant load (s32) from %ir.x)
287 tracksRegLiveness: true
293 ; CHECK: name: memory_offset
294 ; CHECK: $xmm0 = MOVAPSrm $rdi, 1, $noreg, 0, $noreg :: (load (s128) from %ir.vec)
295 ; CHECK-NEXT: $xmm1 = MOVAPSrm $rdi, 1, $noreg, 16, $noreg :: (load (s128) from %ir.vec + 16)
296 ; CHECK: MOVAPSmr $rdi, 1, $noreg, 0, $noreg, killed $xmm0 :: (store (s128) into %ir.vec)
297 ; CHECK-NEXT: MOVAPSmr killed $rdi, 1, $noreg, 16, $noreg, killed $xmm1 :: (store (s128) into %ir.vec + 16)
298 $xmm0 = MOVAPSrm $rdi, 1, _, 0, _ :: (load (s128) from %ir.vec)
299 $xmm1 = MOVAPSrm $rdi, 1, _, 16, _ :: (load (s128) from %ir.vec + 16)
301 $xmm1 = MOVSSrr killed $xmm1, killed $xmm2
302 MOVAPSmr $rdi, 1, _, 0, _, killed $xmm0 :: (store (s128) into %ir.vec)
303 MOVAPSmr killed $rdi, 1, _, 16, _, killed $xmm1 :: (store (s128) into %ir.vec + 16)
307 name: memory_alignment
308 tracksRegLiveness: true
314 ; CHECK: name: memory_alignment
315 ; CHECK: $xmm0 = MOVAPSrm $rdi, 1, $noreg, 0, $noreg :: (load (s128) from %ir.vec, align 64)
316 ; CHECK-NEXT: $xmm1 = MOVAPSrm $rdi, 1, $noreg, 16, $noreg :: (load (s128) from %ir.vec + 16, basealign 64)
317 ; CHECK-NEXT: $xmm2 = MOVAPSrm $rdi, 1, $noreg, 32, $noreg :: (load (s128) from %ir.vec + 32, align 32, basealign 64)
318 ; CHECK-NEXT: $xmm3 = MOVAPSrm $rdi, 1, $noreg, 48, $noreg :: (load (s128) from %ir.vec + 48, basealign 64)
319 ; CHECK: MOVAPSmr $rdi, 1, $noreg, 0, $noreg, killed $xmm0 :: (store (s128) into %ir.vec, align 64)
320 ; CHECK-NEXT: MOVAPSmr $rdi, 1, $noreg, 16, $noreg, killed $xmm1 :: (store (s128) into %ir.vec + 16, basealign 64)
321 ; CHECK-NEXT: MOVAPSmr $rdi, 1, $noreg, 32, $noreg, killed $xmm2 :: (store (s128) into %ir.vec + 32, align 32, basealign 64)
322 ; CHECK-NEXT: MOVAPSmr killed $rdi, 1, $noreg, 48, $noreg, killed $xmm3 :: (store (s128) into %ir.vec + 48, basealign 64)
323 $xmm0 = MOVAPSrm $rdi, 1, _, 0, _ :: (load (s128) from %ir.vec, align 64)
324 $xmm1 = MOVAPSrm $rdi, 1, _, 16, _ :: (load (s128) from %ir.vec + 16, basealign 64)
325 $xmm2 = MOVAPSrm $rdi, 1, _, 32, _ :: (load (s128) from %ir.vec + 32, align 32, basealign 64)
326 $xmm3 = MOVAPSrm $rdi, 1, _, 48, _ :: (load (s128) from %ir.vec + 48, basealign 64)
328 $xmm1 = MOVSSrr killed $xmm1, killed $xmm4
329 MOVAPSmr $rdi, 1, _, 0, _, killed $xmm0 :: (store (s128) into %ir.vec, align 64)
330 MOVAPSmr $rdi, 1, _, 16, _, killed $xmm1 :: (store (s128) into %ir.vec + 16, basealign 64)
331 MOVAPSmr $rdi, 1, _, 32, _, killed $xmm2 :: (store (s128) into %ir.vec + 32, align 32, basealign 64)
332 MOVAPSmr killed $rdi, 1, _, 48, _, killed $xmm3 :: (store (s128) into %ir.vec + 48, basealign 64)
336 name: constant_pool_psv
337 tracksRegLiveness: true
342 value: 'double 3.250000e+00'
346 ; CHECK: name: constant_pool_psv
347 ; CHECK: $xmm0 = ADDSDrm killed $xmm0, $rip, 1, $noreg, %const.0, $noreg, implicit $mxcsr :: (load (s64) from constant-pool)
348 ; CHECK-NEXT: $xmm0 = ADDSDrm killed $xmm0, $rip, 1, $noreg, %const.0, $noreg, implicit $mxcsr :: (load (s64) from constant-pool + 8)
349 $xmm0 = ADDSDrm killed $xmm0, $rip, 1, _, %const.0, _, implicit $mxcsr :: (load (s64) from constant-pool)
350 $xmm0 = ADDSDrm killed $xmm0, $rip, 1, _, %const.0, _, implicit $mxcsr :: (load (s64) from constant-pool + 8)
355 tracksRegLiveness: true
363 - { id: 0, offset: 0, size: 10, alignment: 16, isImmutable: true, isAliased: false }
366 $rsp = frame-setup SUB64ri8 $rsp, 24, implicit-def dead $eflags
367 CFI_INSTRUCTION def_cfa_offset 32
368 LD_F80m $rsp, 1, $noreg, 32, $noreg, implicit-def dead $fpsw, implicit $fpcw
369 ; CHECK: name: stack_psv
370 ; CHECK: ST_FP80m $rsp, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (store (s80) into stack, align 16)
371 ST_FP80m $rsp, 1, _, 0, _, implicit-def dead $fpsw, implicit $fpcw :: (store (s80) into stack, align 16)
372 CALL64pcrel32 &cosl, csr_64, implicit $rsp, implicit-def $rsp, implicit-def $fp0
373 $rsp = ADD64ri8 $rsp, 24, implicit-def dead $eflags
378 tracksRegLiveness: true
381 ; CHECK: name: got_psv
382 ; CHECK: $rax = MOV64rm $rip, 1, $noreg, @G, $noreg :: (load (s64) from got)
383 $rax = MOV64rm $rip, 1, _, @G, _ :: (load (s64) from got)
384 $eax = MOV32rm killed $rax, 1, _, 0, _
385 $eax = INC32r killed $eax, implicit-def dead $eflags
390 tracksRegLiveness: true
393 $rax = MOV64rm $rip, 1, _, @G, _
394 ; CHECK-LABEL: name: global_value
395 ; CHECK: $eax = MOV32rm killed $rax, 1, $noreg, 0, $noreg, implicit-def $rax :: (load (s32) from @G)
396 ; CHECK: $ecx = MOV32rm killed $rcx, 1, $noreg, 0, $noreg, implicit-def $rcx :: (load (s32) from @0)
397 $eax = MOV32rm killed $rax, 1, _, 0, _, implicit-def $rax :: (load (s32) from @G)
398 $rcx = MOV64rm $rip, 1, _, @0, _
399 $ecx = MOV32rm killed $rcx, 1, _, 0, _, implicit-def $rcx :: (load (s32) from @0)
400 $eax = LEA64_32r killed $rax, 1, killed $rcx, 1, _
405 tracksRegLiveness: true
409 kind: label-difference32
412 blocks: [ '%bb.3.lbl1', '%bb.4.lbl2', '%bb.5.lbl3', '%bb.6.lbl4' ]
415 successors: %bb.2.def, %bb.1.entry
418 $eax = MOV32rr $edi, implicit-def $rax
419 CMP32ri8 killed $edi, 3, implicit-def $eflags
420 JCC_1 %bb.2.def, 7, implicit killed $eflags
423 successors: %bb.3.lbl1, %bb.4.lbl2, %bb.5.lbl3, %bb.6.lbl4
426 $rcx = LEA64r $rip, 1, _, %jump-table.0, _
427 ; CHECK: name: jumptable_psv
428 ; CHECK: $rax = MOVSX64rm32 $rcx, 4, killed $rax, 0, $noreg :: (load (s32) from jump-table, align 8)
429 $rax = MOVSX64rm32 $rcx, 4, killed $rax, 0, _ :: (load (s32) from jump-table, align 8)
430 $rax = ADD64rr killed $rax, killed $rcx, implicit-def dead $eflags
434 $eax = MOV32r0 implicit-def dead $eflags
455 tracksRegLiveness: true
458 $rax = MOV64rm $rip, 1, _, @a, _ :: (load (s64) from got)
459 ; CHECK-LABEL: name: tbaa_metadata
460 ; CHECK: $eax = MOV32rm killed $rax, 1, $noreg, 0, $noreg, implicit-def $rax :: (load (s32) from @a, !tbaa !2)
461 ; CHECK-NEXT: $eax = MOV32rm killed $rax, 1, $noreg, 0, $noreg :: (load (s32) from %ir.1, !tbaa !6)
462 $eax = MOV32rm killed $rax, 1, _, 0, _, implicit-def $rax :: (load (s32) from @a, !tbaa !2)
463 $eax = MOV32rm killed $rax, 1, _, 0, _ :: (load (s32) from %ir.1, !tbaa !6)
468 tracksRegLiveness: true
475 ; CHECK-LABEL: name: aa_scope
476 ; CHECK: $xmm0 = MOVSSrm_alt $rsi, 1, $noreg, 0, $noreg :: (load (s32) from %ir.c, !alias.scope !9)
477 $xmm0 = MOVSSrm_alt $rsi, 1, _, 0, _ :: (load (s32) from %ir.c, !alias.scope !9)
478 ; CHECK-NEXT: MOVSSmr $rdi, 1, $noreg, 20, $noreg, killed $xmm0 :: (store (s32) into %ir.arrayidx.i, !noalias !9)
479 MOVSSmr $rdi, 1, _, 20, _, killed $xmm0 :: (store (s32) into %ir.arrayidx.i, !noalias !9)
480 $xmm0 = MOVSSrm_alt killed $rsi, 1, _, 0, _ :: (load (s32) from %ir.c)
481 MOVSSmr killed $rdi, 1, _, 28, _, killed $xmm0 :: (store (s32) into %ir.arrayidx)
486 tracksRegLiveness: true
492 ; CHECK-LABEL: name: range_metadata
493 ; CHECK: $al = MOV8rm killed $rdi, 1, $noreg, 0, $noreg :: (load (s8) from %ir.x, !range !11)
494 $al = MOV8rm killed $rdi, 1, _, 0, _ :: (load (s8) from %ir.x, !range !11)
499 tracksRegLiveness: true
506 $rax = MOV64rm $rip, 1, _, @values, _ :: (load (s64) from got)
507 ; CHECK-LABEL: gep_value
508 ; CHECK: MOV32mr killed $rax, 1, $noreg, 0, $noreg, $edi, implicit killed $rdi :: (store (s32) into @values, align 16)
509 MOV32mr killed $rax, 1, _, 0, _, $edi, implicit killed $rdi :: (store (s32) into @values, align 16)
514 tracksRegLiveness: true
517 ; CHECK-LABEL: name: undef_value
518 ; CHECK: $rax = MOV64rm undef $rax, 1, $noreg, 0, $noreg :: (load (s64) from `ptr undef`)
519 $rax = MOV64rm undef $rax, 1, _, 0, _ :: (load (s64) from `ptr undef`)
523 # Test memory operand without associated value.
524 # CHECK-LABEL: name: dummy0
525 # CHECK: $rax = MOV64rm undef $rax, 1, $noreg, 0, $noreg :: (load (s64))
527 tracksRegLiveness: true
530 $rax = MOV64rm undef $rax, 1, _, 0, _ :: (load (s64))
534 # Test parsing of stack references in machine memory operands.
535 # CHECK-LABEL: name: dummy1
536 # CHECK: $rax = MOV64rm $rsp, 1, $noreg, 0, $noreg :: (load (s64) from %stack.0)
538 tracksRegLiveness: true
540 - { id: 0, size: 4, alignment: 4 }
543 $rax = MOV64rm $rsp, 1, _, 0, _ :: (load (s64) from %stack.0)
547 # Test parsing of unknown size in machine memory operands without alignment.
548 # CHECK-LABEL: name: dummy2
549 # CHECK: $rax = MOV64rm $rsp, 1, $noreg, 0, $noreg :: (load unknown-size from %stack.0, align 1)
551 tracksRegLiveness: true
553 - { id: 0, size: 4, alignment: 4 }
556 $rax = MOV64rm $rsp, 1, _, 0, _ :: (load unknown-size from %stack.0)
560 # Test parsing of unknown size in machine memory operands with alignment.
561 # CHECK-LABEL: name: dummy3
562 # CHECK: $rax = MOV64rm $rsp, 1, $noreg, 0, $noreg :: (load unknown-size from %stack.0, align 4)
564 tracksRegLiveness: true
566 - { id: 0, size: 4, alignment: 4 }
569 $rax = MOV64rm $rsp, 1, _, 0, _ :: (load unknown-size from %stack.0, align 4)