• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# RUN: llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o - %s | FileCheck %s
2# This test ensures that the MIR parser parses the machine memory operands
3# correctly.
4
5--- |
6
7  define i32 @test(i32* %a) {
8  entry:
9    %b = load i32, i32* %a
10    store i32 42, i32* %a
11    ret i32 %b
12  }
13
14  define void @test2(i32* %"a value") {
15  entry2:
16    %b = load i32, i32* %"a value"
17    %c = add i32 %b, 1
18    store i32 %c, i32* %"a value"
19    ret void
20  }
21
22  define void @test3(i32*) {
23  entry3:
24    %1 = alloca i32
25    %b = load i32, i32* %0
26    %c = add i32 %b, 1
27    store i32 %c, i32* %1
28    ret void
29  }
30
31  define i32 @volatile_inc(i32* %x) {
32  entry:
33    %0 = load volatile i32, i32* %x
34    %1 = add i32 %0, 1
35    store volatile i32 %1, i32* %x
36    ret i32 %1
37  }
38
39  define void @non_temporal_store(i32* %a, i32 %b) {
40  entry:
41    store i32 %b, i32* %a, align 16, !nontemporal !0
42    ret void
43  }
44
45  !0 = !{i32 1}
46
47  define i32 @invariant_load(i32* %x) {
48  entry:
49    %v = load i32, i32* %x, !invariant.load !1
50    ret i32 %v
51  }
52
53  !1 = !{}
54
55  define void @memory_offset(<8 x float>* %vec) {
56  entry:
57    %v = load <8 x float>, <8 x float>* %vec
58    %v2 = insertelement <8 x float> %v, float 0.0, i32 4
59    store <8 x float> %v2, <8 x float>* %vec
60    ret void
61  }
62
63  define void @memory_alignment(<8 x float>* %vec) {
64  entry:
65    %v = load <8 x float>, <8 x float>* %vec
66    %v2 = insertelement <8 x float> %v, float 0.0, i32 4
67    store <8 x float> %v2, <8 x float>* %vec
68    ret void
69  }
70
71  define double @constant_pool_psv(double %a) {
72  entry:
73    %b = fadd double %a, 3.250000e+00
74    ret double %b
75  }
76
77  declare x86_fp80 @cosl(x86_fp80) #0
78
79  define x86_fp80 @stack_psv(x86_fp80 %x) {
80  entry:
81    %y = call x86_fp80 @cosl(x86_fp80 %x) #0
82    ret x86_fp80 %y
83  }
84
85  attributes #0 = { readonly }
86
87  @G = external global i32
88
89  define i32 @got_psv() {
90  entry:
91    %a = load i32, i32* @G
92    %b = add i32 %a, 1
93    ret i32 %b
94  }
95
96  @0 = external global i32
97
98  define i32 @global_value() {
99  entry:
100    %a = load i32, i32* @G
101    %b = add i32 %a, 1
102    %c = load i32, i32* @0
103    %d = add i32 %b, %c
104    ret i32 %d
105  }
106
107  define i32 @jumptable_psv(i32 %in) {
108  entry:
109    switch i32 %in, label %def [
110      i32 0, label %lbl1
111      i32 1, label %lbl2
112      i32 2, label %lbl3
113      i32 3, label %lbl4
114    ]
115  def:
116    ret i32 0
117  lbl1:
118    ret i32 1
119  lbl2:
120    ret i32 2
121  lbl3:
122    ret i32 4
123  lbl4:
124    ret i32 8
125  }
126
127  %struct.XXH_state64_t = type { i32, i32, i64, i64, i64 }
128
129  @a = common global i32 0, align 4
130
131  define i32 @tbaa_metadata() {
132  entry:
133    %0 = load i32, i32* @a, align 4, !tbaa !2
134    %1 = inttoptr i32 %0 to %struct.XXH_state64_t*
135    %total_len2 = bitcast %struct.XXH_state64_t* %1 to i32*
136    %2 = load i32, i32* %total_len2, align 4, !tbaa !6
137    ret i32 %2
138  }
139
140  !2 = !{!3, !3, i64 0}
141  !3 = !{!"int", !4, i64 0}
142  !4 = !{!"omnipotent char", !5, i64 0}
143  !5 = !{!"Simple C/C++ TBAA"}
144  !6 = !{!7, !3, i64 0}
145  !7 = !{!"XXH_state64_t", !3, i64 0, !3, i64 4, !8, i64 8, !8, i64 16, !8, i64 24}
146  !8 = !{!"long long", !4, i64 0}
147
148  define void @aa_scope(float* nocapture %a, float* nocapture readonly %c) #1 {
149  entry:
150    %0 = load float, float* %c, align 4, !alias.scope !9
151    %arrayidx.i = getelementptr inbounds float, float* %a, i64 5
152    store float %0, float* %arrayidx.i, align 4, !noalias !9
153    %1 = load float, float* %c, align 4
154    %arrayidx = getelementptr inbounds float, float* %a, i64 7
155    store float %1, float* %arrayidx, align 4
156    ret void
157  }
158
159  attributes #1 = { nounwind uwtable }
160
161  !9 = distinct !{!9, !10, !"some scope"}
162  !10 = distinct !{!10, !"some domain"}
163
164  define zeroext i1 @range_metadata(i8* %x) {
165  entry:
166    %0 = load i8, i8* %x, align 1, !range !11
167    %tobool = trunc i8 %0 to i1
168    ret i1 %tobool
169  }
170
171  !11 = !{i8 0, i8 2}
172
173  %st = type { i32, i32 }
174
175  @values = common global [50 x %st] zeroinitializer, align 16
176
177  define void @gep_value(i64 %d) {
178  entry:
179    %conv = trunc i64 %d to i32
180    store i32 %conv, i32* getelementptr inbounds ([50 x %st], [50 x %st]* @values, i64 0, i64 0, i32 0), align 16
181    ret void
182  }
183
184  define i8* @undef_value() {
185  entry:
186    %0 = load i8*, i8** undef, align 8
187    ret i8* %0
188  }
189
190  define void @dummy0() { ret void }
191  define void @dummy1() { ret void }
192...
193---
194name:            test
195tracksRegLiveness: true
196liveins:
197  - { reg: '%rdi' }
198body: |
199  bb.0.entry:
200    liveins: %rdi
201  ; CHECK:      %eax = MOV32rm %rdi, 1, _, 0, _ :: (load 4 from %ir.a)
202  ; CHECK-NEXT: MOV32mi killed %rdi, 1, _, 0, _, 42 :: (store 4 into %ir.a)
203    %eax = MOV32rm %rdi, 1, _, 0, _ :: (load 4 from %ir.a)
204    MOV32mi killed %rdi, 1, _, 0, _, 42 :: (store 4 into %ir.a)
205    RETQ %eax
206...
207---
208name:            test2
209tracksRegLiveness: true
210liveins:
211  - { reg: '%rdi' }
212body: |
213  bb.0.entry2:
214    liveins: %rdi
215  ; CHECK: INC32m killed %rdi, 1, _, 0, _, implicit-def dead %eflags :: (store 4 into %ir."a value"), (load 4 from %ir."a value")
216    INC32m killed %rdi, 1, _, 0, _, implicit-def dead %eflags :: (store 4 into %ir."a value"), (load 4 from %ir."a value")
217    RETQ
218...
219---
220name:            test3
221tracksRegLiveness: true
222liveins:
223  - { reg: '%rdi' }
224frameInfo:
225  maxAlignment:    4
226stack:
227  - { id: 0, offset: -12, size: 4, alignment: 4 }
228body: |
229  bb.0.entry3:
230    liveins: %rdi
231  ; Verify that the unnamed local values can be serialized.
232  ; CHECK-LABEL: name: test3
233  ; CHECK: %eax = MOV32rm killed %rdi, 1, _, 0, _ :: (load 4 from %ir.0)
234  ; CHECK: MOV32mr %rsp, 1, _, -4, _, killed %eax :: (store 4 into %ir.1)
235    %eax = MOV32rm killed %rdi, 1, _, 0, _ :: (load 4 from %ir.0)
236    %eax = INC32r killed %eax, implicit-def dead %eflags
237    MOV32mr %rsp, 1, _, -4, _, killed %eax :: (store 4 into %ir.1)
238    RETQ
239...
240---
241name:            volatile_inc
242tracksRegLiveness: true
243liveins:
244  - { reg: '%rdi' }
245body: |
246  bb.0.entry:
247    liveins: %rdi
248    ; CHECK: name: volatile_inc
249    ; CHECK: %eax = MOV32rm %rdi, 1, _, 0, _ :: (volatile load 4 from %ir.x)
250    ; CHECK: MOV32mr killed %rdi, 1, _, 0, _, %eax :: (volatile store 4 into %ir.x)
251    %eax = MOV32rm %rdi, 1, _, 0, _ :: (volatile load 4 from %ir.x)
252    %eax = INC32r killed %eax, implicit-def dead %eflags
253    MOV32mr killed %rdi, 1, _, 0, _, %eax :: (volatile store 4 into %ir.x)
254    RETQ %eax
255...
256---
257name:            non_temporal_store
258tracksRegLiveness: true
259liveins:
260  - { reg: '%rdi' }
261  - { reg: '%esi' }
262body: |
263  bb.0.entry:
264    liveins: %esi, %rdi
265  ; CHECK: name: non_temporal_store
266  ; CHECK: MOVNTImr killed %rdi, 1, _, 0, _, killed %esi :: (non-temporal store 4 into %ir.a)
267    MOVNTImr killed %rdi, 1, _, 0, _, killed %esi :: (non-temporal store 4 into %ir.a)
268    RETQ
269...
270---
271name:            invariant_load
272tracksRegLiveness: true
273liveins:
274  - { reg: '%rdi' }
275body: |
276  bb.0.entry:
277    liveins: %rdi
278  ; CHECK: name: invariant_load
279  ; CHECK: %eax = MOV32rm killed %rdi, 1, _, 0, _ :: (invariant load 4 from %ir.x)
280    %eax = MOV32rm killed %rdi, 1, _, 0, _ :: (invariant load 4 from %ir.x)
281    RETQ %eax
282...
283---
284name:            memory_offset
285tracksRegLiveness: true
286liveins:
287  - { reg: '%rdi' }
288body: |
289  bb.0.entry:
290    liveins: %rdi
291  ; CHECK: name: memory_offset
292  ; CHECK:      %xmm0 = MOVAPSrm %rdi, 1, _, 0, _ :: (load 16 from %ir.vec)
293  ; CHECK-NEXT: %xmm1 = MOVAPSrm %rdi, 1, _, 16, _ :: (load 16 from %ir.vec + 16)
294  ; CHECK:      MOVAPSmr %rdi, 1, _, 0, _, killed %xmm0 :: (store 16 into %ir.vec)
295  ; CHECK-NEXT: MOVAPSmr killed %rdi, 1, _, 16, _, killed %xmm1 :: (store 16 into %ir.vec + 16)
296    %xmm0 = MOVAPSrm %rdi, 1, _, 0, _ :: (load 16 from %ir.vec)
297    %xmm1 = MOVAPSrm %rdi, 1, _, 16, _ :: (load 16 from %ir.vec + 16)
298    %xmm2 = FsFLD0SS
299    %xmm1 = MOVSSrr killed %xmm1, killed %xmm2
300    MOVAPSmr %rdi, 1, _, 0, _, killed %xmm0 :: (store 16 into %ir.vec)
301    MOVAPSmr killed %rdi, 1, _, 16, _, killed %xmm1 :: (store 16 into %ir.vec + 16)
302    RETQ
303...
304---
305name:            memory_alignment
306tracksRegLiveness: true
307liveins:
308  - { reg: '%rdi' }
309body: |
310  bb.0.entry:
311    liveins: %rdi
312  ; CHECK: name: memory_alignment
313  ; CHECK:      %xmm0 = MOVAPSrm %rdi, 1, _, 0, _ :: (load 16 from %ir.vec, align 32)
314  ; CHECK-NEXT: %xmm1 = MOVAPSrm %rdi, 1, _, 16, _ :: (load 16 from %ir.vec + 16, align 32)
315  ; CHECK:      MOVAPSmr %rdi, 1, _, 0, _, killed %xmm0 :: (store 16 into %ir.vec, align 32)
316  ; CHECK-NEXT: MOVAPSmr killed %rdi, 1, _, 16, _, killed %xmm1 :: (store 16 into %ir.vec + 16, align 32)
317    %xmm0 = MOVAPSrm %rdi, 1, _, 0, _ :: (load 16 from %ir.vec, align 32)
318    %xmm1 = MOVAPSrm %rdi, 1, _, 16, _ :: (load 16 from %ir.vec + 16, align 32)
319    %xmm2 = FsFLD0SS
320    %xmm1 = MOVSSrr killed %xmm1, killed %xmm2
321    MOVAPSmr %rdi, 1, _, 0, _, killed %xmm0 :: (store 16 into %ir.vec, align 32)
322    MOVAPSmr killed %rdi, 1, _, 16, _, killed %xmm1 :: (store 16 into %ir.vec + 16, align 32)
323    RETQ
324...
325---
326name:            constant_pool_psv
327tracksRegLiveness: true
328liveins:
329  - { reg: '%xmm0' }
330constants:
331  - id:          0
332    value:       'double 3.250000e+00'
333body: |
334  bb.0.entry:
335    liveins: %xmm0
336  ; CHECK: name: constant_pool_psv
337  ; CHECK:      %xmm0 = ADDSDrm killed %xmm0, %rip, 1, _, %const.0, _ :: (load 8 from constant-pool)
338  ; CHECK-NEXT: %xmm0 = ADDSDrm killed %xmm0, %rip, 1, _, %const.0, _ :: (load 8 from constant-pool + 8)
339    %xmm0 = ADDSDrm killed %xmm0, %rip, 1, _, %const.0, _ :: (load 8 from constant-pool)
340    %xmm0 = ADDSDrm killed %xmm0, %rip, 1, _, %const.0, _ :: (load 8 from constant-pool + 8)
341    RETQ %xmm0
342...
343---
344name:            stack_psv
345tracksRegLiveness: true
346frameInfo:
347  stackSize:       24
348  maxAlignment:    16
349  adjustsStack:    true
350  hasCalls:        true
351  maxCallFrameSize: 16
352fixedStack:
353  - { id: 0, offset: 0, size: 10, alignment: 16, isImmutable: true, isAliased: false }
354body: |
355  bb.0.entry:
356    %rsp = frame-setup SUB64ri8 %rsp, 24, implicit-def dead %eflags
357    CFI_INSTRUCTION .cfi_def_cfa_offset 32
358    LD_F80m %rsp, 1, _, 32, _, implicit-def dead %fpsw
359  ; CHECK: name: stack_psv
360  ; CHECK: ST_FP80m %rsp, 1, _, 0, _, implicit-def dead %fpsw :: (store 10 into stack, align 16)
361    ST_FP80m %rsp, 1, _, 0, _, implicit-def dead %fpsw :: (store 10 into stack, align 16)
362    CALL64pcrel32 $cosl, csr_64, implicit %rsp, implicit-def %rsp, implicit-def %fp0
363    %rsp = ADD64ri8 %rsp, 24, implicit-def dead %eflags
364    RETQ
365...
366---
367name:            got_psv
368tracksRegLiveness: true
369body: |
370  bb.0.entry:
371  ; CHECK: name: got_psv
372  ; CHECK: %rax = MOV64rm %rip, 1, _, @G, _ :: (load 8 from got)
373    %rax = MOV64rm %rip, 1, _, @G, _ :: (load 8 from got)
374    %eax = MOV32rm killed %rax, 1, _, 0, _
375    %eax = INC32r killed %eax, implicit-def dead %eflags
376    RETQ %eax
377...
378---
379name:            global_value
380tracksRegLiveness: true
381body: |
382  bb.0.entry:
383    %rax = MOV64rm %rip, 1, _, @G, _
384  ; CHECK-LABEL: name: global_value
385  ; CHECK: %eax = MOV32rm killed %rax, 1, _, 0, _, implicit-def %rax :: (load 4 from @G)
386  ; CHECK: %ecx = MOV32rm killed %rcx, 1, _, 0, _, implicit-def %rcx :: (load 4 from @0)
387    %eax = MOV32rm killed %rax, 1, _, 0, _, implicit-def %rax :: (load 4 from @G)
388    %rcx = MOV64rm %rip, 1, _, @0, _
389    %ecx = MOV32rm killed %rcx, 1, _, 0, _, implicit-def %rcx :: (load 4 from @0)
390    %eax = LEA64_32r killed %rax, 1, killed %rcx, 1, _
391    RETQ %eax
392...
393---
394name:            jumptable_psv
395tracksRegLiveness: true
396liveins:
397  - { reg: '%edi' }
398jumpTable:
399  kind:          label-difference32
400  entries:
401    - id:        0
402      blocks:    [ '%bb.3.lbl1', '%bb.4.lbl2', '%bb.5.lbl3', '%bb.6.lbl4' ]
403body: |
404  bb.0.entry:
405    successors: %bb.2.def, %bb.1.entry
406    liveins: %edi
407
408    %eax = MOV32rr %edi, implicit-def %rax
409    CMP32ri8 killed %edi, 3, implicit-def %eflags
410    JA_1 %bb.2.def, implicit killed %eflags
411
412  bb.1.entry:
413    successors: %bb.3.lbl1, %bb.4.lbl2, %bb.5.lbl3, %bb.6.lbl4
414    liveins: %rax
415
416    %rcx = LEA64r %rip, 1, _, %jump-table.0, _
417  ; CHECK: name: jumptable_psv
418  ; CHECK: %rax = MOVSX64rm32 %rcx, 4, killed %rax, 0, _ :: (load 4 from jump-table, align 8)
419    %rax = MOVSX64rm32 %rcx, 4, killed %rax, 0, _ :: (load 4 from jump-table, align 8)
420    %rax = ADD64rr killed %rax, killed %rcx, implicit-def dead %eflags
421    JMP64r killed %rax
422
423  bb.2.def:
424    %eax = MOV32r0 implicit-def dead %eflags
425    RETQ %eax
426
427  bb.3.lbl1:
428    %eax = MOV32ri 1
429    RETQ %eax
430
431  bb.4.lbl2:
432    %eax = MOV32ri 2
433    RETQ %eax
434
435  bb.5.lbl3:
436    %eax = MOV32ri 4
437    RETQ %eax
438
439  bb.6.lbl4:
440    %eax = MOV32ri 8
441    RETQ %eax
442...
443---
444name:            tbaa_metadata
445tracksRegLiveness: true
446body: |
447  bb.0.entry:
448    %rax = MOV64rm %rip, 1, _, @a, _ :: (load 8 from got)
449  ; CHECK-LABEL: name: tbaa_metadata
450  ; CHECK:      %eax = MOV32rm killed %rax, 1, _, 0, _, implicit-def %rax :: (load 4 from @a, !tbaa !2)
451  ; CHECK-NEXT: %eax = MOV32rm killed %rax, 1, _, 0, _ :: (load 4 from %ir.total_len2, !tbaa !6)
452    %eax = MOV32rm killed %rax, 1, _, 0, _, implicit-def %rax :: (load 4 from @a, !tbaa !2)
453    %eax = MOV32rm killed %rax, 1, _, 0, _ :: (load 4 from %ir.total_len2, !tbaa !6)
454    RETQ %eax
455...
456---
457name:            aa_scope
458tracksRegLiveness: true
459liveins:
460  - { reg: '%rdi' }
461  - { reg: '%rsi' }
462body: |
463  bb.0.entry:
464    liveins: %rdi, %rsi
465  ; CHECK-LABEL: name: aa_scope
466  ; CHECK: %xmm0 = MOVSSrm %rsi, 1, _, 0, _ :: (load 4 from %ir.c, !alias.scope !9)
467    %xmm0 = MOVSSrm %rsi, 1, _, 0, _ :: (load 4 from %ir.c, !alias.scope !9)
468  ; CHECK-NEXT: MOVSSmr %rdi, 1, _, 20, _, killed %xmm0 :: (store 4 into %ir.arrayidx.i, !noalias !9)
469    MOVSSmr %rdi, 1, _, 20, _, killed %xmm0 :: (store 4 into %ir.arrayidx.i, !noalias !9)
470    %xmm0 = MOVSSrm killed %rsi, 1, _, 0, _ :: (load 4 from %ir.c)
471    MOVSSmr killed %rdi, 1, _, 28, _, killed %xmm0 :: (store 4 into %ir.arrayidx)
472    RETQ
473...
474---
475name:            range_metadata
476tracksRegLiveness: true
477liveins:
478  - { reg: '%rdi' }
479body: |
480  bb.0.entry:
481    liveins: %rdi
482  ; CHECK-LABEL: name: range_metadata
483  ; CHECK: %al = MOV8rm killed %rdi, 1, _, 0, _ :: (load 1 from %ir.x, !range !11)
484    %al = MOV8rm killed %rdi, 1, _, 0, _ :: (load 1 from %ir.x, !range !11)
485    RETQ %al
486...
487---
488name:            gep_value
489tracksRegLiveness: true
490liveins:
491  - { reg: '%rdi' }
492body: |
493  bb.0.entry:
494    liveins: %rdi
495
496    %rax = MOV64rm %rip, 1, _, @values, _ :: (load 8 from got)
497  ; CHECK-LABEL: gep_value
498  ; CHECK: MOV32mr killed %rax, 1, _, 0, _, %edi, implicit killed %rdi :: (store 4 into `i32* getelementptr inbounds ([50 x %st], [50 x %st]* @values, i64 0, i64 0, i32 0)`, align 16)
499    MOV32mr killed %rax, 1, _, 0, _, %edi, implicit killed %rdi :: (store 4 into `i32* getelementptr inbounds ([50 x %st], [50 x %st]* @values, i64 0, i64 0, i32 0)`, align 16)
500    RETQ
501...
502---
503name:            undef_value
504tracksRegLiveness: true
505body: |
506  bb.0.entry:
507  ; CHECK-LABEL: name: undef_value
508  ; CHECK: %rax = MOV64rm undef %rax, 1, _, 0, _ :: (load 8 from `i8** undef`)
509    %rax = MOV64rm undef %rax, 1, _, 0, _ :: (load 8 from `i8** undef`)
510    RETQ %rax
511...
512---
513# Test memory operand without associated value.
514# CHECK-LABEL: name: dummy0
515# CHECK: %rax = MOV64rm undef %rax, 1, _, 0, _ :: (load 8)
516name: dummy0
517tracksRegLiveness: true
518body: |
519  bb.0:
520    %rax = MOV64rm undef %rax, 1, _, 0, _ :: (load 8)
521    RETQ %rax
522...
523---
524# Test parsing of stack references in machine memory operands.
525# CHECK-LABEL: name: dummy1
526# CHECK: %rax = MOV64rm %rsp, 1, _, 0, _ :: (load 8 from %stack.0)
527name: dummy1
528tracksRegLiveness: true
529stack:
530  - { id: 0, size: 4, alignment: 4 }
531body: |
532  bb.0:
533    %rax = MOV64rm %rsp, 1, _, 0, _ :: (load 8 from %stack.0)
534    RETQ %rax
535
536...
537