MIR Serialization: Serialize unnamed local IR values in memory operands.
[oota-llvm.git] / test / CodeGen / MIR / X86 / memory-operands.mir
1 # RUN: llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %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   define i32 @global_value() {
97   entry:
98     %a = load i32, i32* @G
99     %b = add i32 %a, 1
100     ret i32 %b
101   }
102
103   define i32 @jumptable_psv(i32 %in) {
104   entry:
105     switch i32 %in, label %def [
106       i32 0, label %lbl1
107       i32 1, label %lbl2
108       i32 2, label %lbl3
109       i32 3, label %lbl4
110     ]
111   def:
112     ret i32 0
113   lbl1:
114     ret i32 1
115   lbl2:
116     ret i32 2
117   lbl3:
118     ret i32 4
119   lbl4:
120     ret i32 8
121   }
122
123   %struct.XXH_state64_t = type { i32, i32, i64, i64, i64 }
124
125   @a = common global i32 0, align 4
126
127   define i32 @tbaa_metadata() {
128   entry:
129     %0 = load i32, i32* @a, align 4, !tbaa !2
130     %1 = inttoptr i32 %0 to %struct.XXH_state64_t*
131     %total_len2 = bitcast %struct.XXH_state64_t* %1 to i32*
132     %2 = load i32, i32* %total_len2, align 4, !tbaa !6
133     ret i32 %2
134   }
135
136   !2 = !{!3, !3, i64 0}
137   !3 = !{!"int", !4, i64 0}
138   !4 = !{!"omnipotent char", !5, i64 0}
139   !5 = !{!"Simple C/C++ TBAA"}
140   !6 = !{!7, !3, i64 0}
141   !7 = !{!"XXH_state64_t", !3, i64 0, !3, i64 4, !8, i64 8, !8, i64 16, !8, i64 24}
142   !8 = !{!"long long", !4, i64 0}
143
144   define void @aa_scope(float* nocapture %a, float* nocapture readonly %c) #1 {
145   entry:
146     %0 = load float, float* %c, align 4, !alias.scope !9
147     %arrayidx.i = getelementptr inbounds float, float* %a, i64 5
148     store float %0, float* %arrayidx.i, align 4, !noalias !9
149     %1 = load float, float* %c, align 4
150     %arrayidx = getelementptr inbounds float, float* %a, i64 7
151     store float %1, float* %arrayidx, align 4
152     ret void
153   }
154
155   attributes #1 = { nounwind uwtable }
156
157   !9 = distinct !{!9, !10, !"some scope"}
158   !10 = distinct !{!10, !"some domain"}
159
160   define zeroext i1 @range_metadata(i8* %x) {
161   entry:
162     %0 = load i8, i8* %x, align 1, !range !11
163     %tobool = trunc i8 %0 to i1
164     ret i1 %tobool
165   }
166
167   !11 = !{i8 0, i8 2}
168
169 ...
170 ---
171 name:            test
172 tracksRegLiveness: true
173 liveins:
174   - { reg: '%rdi' }
175 body: |
176   bb.0.entry:
177     liveins: %rdi
178   ; CHECK:      %eax = MOV32rm %rdi, 1, _, 0, _ :: (load 4 from %ir.a)
179   ; CHECK-NEXT: MOV32mi killed %rdi, 1, _, 0, _, 42 :: (store 4 into %ir.a)
180     %eax = MOV32rm %rdi, 1, _, 0, _ :: (load 4 from %ir.a)
181     MOV32mi killed %rdi, 1, _, 0, _, 42 :: (store 4 into %ir.a)
182     RETQ %eax
183 ...
184 ---
185 name:            test2
186 tracksRegLiveness: true
187 liveins:
188   - { reg: '%rdi' }
189 body: |
190   bb.0.entry2:
191     liveins: %rdi
192   ; CHECK: INC32m killed %rdi, 1, _, 0, _, implicit-def dead %eflags :: (store 4 into %ir."a value"), (load 4 from %ir."a value")
193     INC32m killed %rdi, 1, _, 0, _, implicit-def dead %eflags :: (store 4 into %ir."a value"), (load 4 from %ir."a value")
194     RETQ
195 ...
196 ---
197 name:            test3
198 tracksRegLiveness: true
199 liveins:
200   - { reg: '%rdi' }
201 frameInfo:
202   maxAlignment:    4
203 stack:
204   - { id: 0, offset: -12, size: 4, alignment: 4 }
205 body: |
206   bb.0.entry3:
207     liveins: %rdi
208   ; Verify that the unnamed local values can be serialized.
209   ; CHECK-LABEL: name: test3
210   ; CHECK: %eax = MOV32rm killed %rdi, 1, _, 0, _ :: (load 4 from %ir.0)
211   ; CHECK: MOV32mr %rsp, 1, _, -4, _, killed %eax :: (store 4 into %ir.1)
212     %eax = MOV32rm killed %rdi, 1, _, 0, _ :: (load 4 from %ir.0)
213     %eax = INC32r killed %eax, implicit-def dead %eflags
214     MOV32mr %rsp, 1, _, -4, _, killed %eax :: (store 4 into %ir.1)
215     RETQ
216 ...
217 ---
218 name:            volatile_inc
219 tracksRegLiveness: true
220 liveins:
221   - { reg: '%rdi' }
222 body: |
223   bb.0.entry:
224     liveins: %rdi
225     ; CHECK: name: volatile_inc
226     ; CHECK: %eax = MOV32rm %rdi, 1, _, 0, _ :: (volatile load 4 from %ir.x)
227     ; CHECK: MOV32mr killed %rdi, 1, _, 0, _, %eax :: (volatile store 4 into %ir.x)
228     %eax = MOV32rm %rdi, 1, _, 0, _ :: (volatile load 4 from %ir.x)
229     %eax = INC32r killed %eax, implicit-def dead %eflags
230     MOV32mr killed %rdi, 1, _, 0, _, %eax :: (volatile store 4 into %ir.x)
231     RETQ %eax
232 ...
233 ---
234 name:            non_temporal_store
235 tracksRegLiveness: true
236 liveins:
237   - { reg: '%rdi' }
238   - { reg: '%esi' }
239 body: |
240   bb.0.entry:
241     liveins: %esi, %rdi
242   ; CHECK: name: non_temporal_store
243   ; CHECK: MOVNTImr killed %rdi, 1, _, 0, _, killed %esi :: (non-temporal store 4 into %ir.a)
244     MOVNTImr killed %rdi, 1, _, 0, _, killed %esi :: (non-temporal store 4 into %ir.a)
245     RETQ
246 ...
247 ---
248 name:            invariant_load
249 tracksRegLiveness: true
250 liveins:
251   - { reg: '%rdi' }
252 body: |
253   bb.0.entry:
254     liveins: %rdi
255   ; CHECK: name: invariant_load
256   ; CHECK: %eax = MOV32rm killed %rdi, 1, _, 0, _ :: (invariant load 4 from %ir.x)
257     %eax = MOV32rm killed %rdi, 1, _, 0, _ :: (invariant load 4 from %ir.x)
258     RETQ %eax
259 ...
260 ---
261 name:            memory_offset
262 tracksRegLiveness: true
263 liveins:
264   - { reg: '%rdi' }
265 body: |
266   bb.0.entry:
267     liveins: %rdi
268   ; CHECK: name: memory_offset
269   ; CHECK:      %xmm0 = MOVAPSrm %rdi, 1, _, 0, _ :: (load 16 from %ir.vec)
270   ; CHECK-NEXT: %xmm1 = MOVAPSrm %rdi, 1, _, 16, _ :: (load 16 from %ir.vec + 16)
271   ; CHECK:      MOVAPSmr %rdi, 1, _, 0, _, killed %xmm0 :: (store 16 into %ir.vec)
272   ; CHECK-NEXT: MOVAPSmr killed %rdi, 1, _, 16, _, killed %xmm1 :: (store 16 into %ir.vec + 16)
273     %xmm0 = MOVAPSrm %rdi, 1, _, 0, _ :: (load 16 from %ir.vec)
274     %xmm1 = MOVAPSrm %rdi, 1, _, 16, _ :: (load 16 from %ir.vec + 16)
275     %xmm2 = FsFLD0SS
276     %xmm1 = MOVSSrr killed %xmm1, killed %xmm2
277     MOVAPSmr %rdi, 1, _, 0, _, killed %xmm0 :: (store 16 into %ir.vec)
278     MOVAPSmr killed %rdi, 1, _, 16, _, killed %xmm1 :: (store 16 into %ir.vec + 16)
279     RETQ
280 ...
281 ---
282 name:            memory_alignment
283 tracksRegLiveness: true
284 liveins:
285   - { reg: '%rdi' }
286 body: |
287   bb.0.entry:
288     liveins: %rdi
289   ; CHECK: name: memory_alignment
290   ; CHECK:      %xmm0 = MOVAPSrm %rdi, 1, _, 0, _ :: (load 16 from %ir.vec, align 32)
291   ; CHECK-NEXT: %xmm1 = MOVAPSrm %rdi, 1, _, 16, _ :: (load 16 from %ir.vec + 16, align 32)
292   ; CHECK:      MOVAPSmr %rdi, 1, _, 0, _, killed %xmm0 :: (store 16 into %ir.vec, align 32)
293   ; CHECK-NEXT: MOVAPSmr killed %rdi, 1, _, 16, _, killed %xmm1 :: (store 16 into %ir.vec + 16, align 32)
294     %xmm0 = MOVAPSrm %rdi, 1, _, 0, _ :: (load 16 from %ir.vec, align 32)
295     %xmm1 = MOVAPSrm %rdi, 1, _, 16, _ :: (load 16 from %ir.vec + 16, align 32)
296     %xmm2 = FsFLD0SS
297     %xmm1 = MOVSSrr killed %xmm1, killed %xmm2
298     MOVAPSmr %rdi, 1, _, 0, _, killed %xmm0 :: (store 16 into %ir.vec, align 32)
299     MOVAPSmr killed %rdi, 1, _, 16, _, killed %xmm1 :: (store 16 into %ir.vec + 16, align 32)
300     RETQ
301 ...
302 ---
303 name:            constant_pool_psv
304 tracksRegLiveness: true
305 liveins:
306   - { reg: '%xmm0' }
307 constants:
308   - id:          0
309     value:       'double 3.250000e+00'
310 body: |
311   bb.0.entry:
312     liveins: %xmm0
313   ; CHECK: name: constant_pool_psv
314   ; CHECK:      %xmm0 = ADDSDrm killed %xmm0, %rip, 1, _, %const.0, _ :: (load 8 from constant-pool)
315   ; CHECK-NEXT: %xmm0 = ADDSDrm killed %xmm0, %rip, 1, _, %const.0, _ :: (load 8 from constant-pool + 8)
316     %xmm0 = ADDSDrm killed %xmm0, %rip, 1, _, %const.0, _ :: (load 8 from constant-pool)
317     %xmm0 = ADDSDrm killed %xmm0, %rip, 1, _, %const.0, _ :: (load 8 from constant-pool + 8)
318     RETQ %xmm0
319 ...
320 ---
321 name:            stack_psv
322 tracksRegLiveness: true
323 frameInfo:
324   stackSize:       24
325   maxAlignment:    16
326   adjustsStack:    true
327   hasCalls:        true
328   maxCallFrameSize: 16
329 fixedStack:
330   - { id: 0, offset: 0, size: 10, alignment: 16, isImmutable: true, isAliased: false }
331 body: |
332   bb.0.entry:
333     %rsp = frame-setup SUB64ri8 %rsp, 24, implicit-def dead %eflags
334     CFI_INSTRUCTION .cfi_def_cfa_offset 32
335     LD_F80m %rsp, 1, _, 32, _, implicit-def dead %fpsw
336   ; CHECK: name: stack_psv
337   ; CHECK: ST_FP80m %rsp, 1, _, 0, _, implicit-def dead %fpsw :: (store 10 into stack, align 16)
338     ST_FP80m %rsp, 1, _, 0, _, implicit-def dead %fpsw :: (store 10 into stack, align 16)
339     CALL64pcrel32 $cosl, csr_64, implicit %rsp, implicit-def %rsp, implicit-def %fp0
340     %rsp = ADD64ri8 %rsp, 24, implicit-def dead %eflags
341     RETQ
342 ...
343 ---
344 name:            got_psv
345 tracksRegLiveness: true
346 body: |
347   bb.0.entry:
348   ; CHECK: name: got_psv
349   ; CHECK: %rax = MOV64rm %rip, 1, _, @G, _ :: (load 8 from got)
350     %rax = MOV64rm %rip, 1, _, @G, _ :: (load 8 from got)
351     %eax = MOV32rm killed %rax, 1, _, 0, _
352     %eax = INC32r killed %eax, implicit-def dead %eflags
353     RETQ %eax
354 ...
355 ---
356 name:            global_value
357 tracksRegLiveness: true
358 body: |
359   bb.0.entry:
360     %rax = MOV64rm %rip, 1, _, @G, _
361   ; CHECK: name: global_value
362   ; CHECK: %eax = MOV32rm killed %rax, 1, _, 0, _ :: (load 4 from %ir.G)
363     %eax = MOV32rm killed %rax, 1, _, 0, _ :: (load 4 from %ir.G)
364     %eax = INC32r killed %eax, implicit-def dead %eflags
365     RETQ %eax
366 ...
367 ---
368 name:            jumptable_psv
369 tracksRegLiveness: true
370 liveins:
371   - { reg: '%edi' }
372 jumpTable:
373   kind:          label-difference32
374   entries:
375     - id:        0
376       blocks:    [ '%bb.3.lbl1', '%bb.4.lbl2', '%bb.5.lbl3', '%bb.6.lbl4' ]
377 body: |
378   bb.0.entry:
379     successors: %bb.2.def, %bb.1.entry
380     liveins: %edi
381
382     %eax = MOV32rr %edi, implicit-def %rax
383     CMP32ri8 killed %edi, 3, implicit-def %eflags
384     JA_1 %bb.2.def, implicit killed %eflags
385
386   bb.1.entry:
387     successors: %bb.3.lbl1, %bb.4.lbl2, %bb.5.lbl3, %bb.6.lbl4
388     liveins: %rax
389
390     %rcx = LEA64r %rip, 1, _, %jump-table.0, _
391   ; CHECK: name: jumptable_psv
392   ; CHECK: %rax = MOVSX64rm32 %rcx, 4, killed %rax, 0, _ :: (load 4 from jump-table, align 8)
393     %rax = MOVSX64rm32 %rcx, 4, killed %rax, 0, _ :: (load 4 from jump-table, align 8)
394     %rax = ADD64rr killed %rax, killed %rcx, implicit-def dead %eflags
395     JMP64r killed %rax
396
397   bb.2.def:
398     %eax = MOV32r0 implicit-def dead %eflags
399     RETQ %eax
400
401   bb.3.lbl1:
402     %eax = MOV32ri 1
403     RETQ %eax
404
405   bb.4.lbl2:
406     %eax = MOV32ri 2
407     RETQ %eax
408
409   bb.5.lbl3:
410     %eax = MOV32ri 4
411     RETQ %eax
412
413   bb.6.lbl4:
414     %eax = MOV32ri 8
415     RETQ %eax
416 ...
417 ---
418 name:            tbaa_metadata
419 tracksRegLiveness: true
420 body: |
421   bb.0.entry:
422     %rax = MOV64rm %rip, 1, _, @a, _ :: (load 8 from got)
423   ; CHECK-LABEL: name: tbaa_metadata
424   ; CHECK:      %eax = MOV32rm killed %rax, 1, _, 0, _, implicit-def %rax :: (load 4 from %ir.a, !tbaa !2)
425   ; CHECK-NEXT: %eax = MOV32rm killed %rax, 1, _, 0, _ :: (load 4 from %ir.total_len2, !tbaa !6)
426     %eax = MOV32rm killed %rax, 1, _, 0, _, implicit-def %rax :: (load 4 from %ir.a, !tbaa !2)
427     %eax = MOV32rm killed %rax, 1, _, 0, _ :: (load 4 from %ir.total_len2, !tbaa !6)
428     RETQ %eax
429 ...
430 ---
431 name:            aa_scope
432 tracksRegLiveness: true
433 liveins:
434   - { reg: '%rdi' }
435   - { reg: '%rsi' }
436 body: |
437   bb.0.entry:
438     liveins: %rdi, %rsi
439   ; CHECK-LABEL: name: aa_scope
440   ; CHECK: %xmm0 = MOVSSrm %rsi, 1, _, 0, _ :: (load 4 from %ir.c, !alias.scope !9)
441     %xmm0 = MOVSSrm %rsi, 1, _, 0, _ :: (load 4 from %ir.c, !alias.scope !9)
442   ; CHECK-NEXT: MOVSSmr %rdi, 1, _, 20, _, killed %xmm0 :: (store 4 into %ir.arrayidx.i, !noalias !9)
443     MOVSSmr %rdi, 1, _, 20, _, killed %xmm0 :: (store 4 into %ir.arrayidx.i, !noalias !9)
444     %xmm0 = MOVSSrm killed %rsi, 1, _, 0, _ :: (load 4 from %ir.c)
445     MOVSSmr killed %rdi, 1, _, 28, _, killed %xmm0 :: (store 4 into %ir.arrayidx)
446     RETQ
447 ...
448 ---
449 name:            range_metadata
450 tracksRegLiveness: true
451 liveins:
452   - { reg: '%rdi' }
453 body: |
454   bb.0.entry:
455     liveins: %rdi
456   ; CHECK-LABEL: name: range_metadata
457   ; CHECK: %al = MOV8rm killed %rdi, 1, _, 0, _ :: (load 1 from %ir.x, !range !11)
458     %al = MOV8rm killed %rdi, 1, _, 0, _ :: (load 1 from %ir.x, !range !11)
459     RETQ %al
460 ...