xref: /llvm-project/llvm/test/CodeGen/ARM/execute-only-save-cpsr.mir (revision 40614e1c1483c698a228c3d038621e834d94086c)
1# RUN: llc -run-pass=prologepilog %s -o - | FileCheck %s
2# Tests to check that CPSR is saved and restored if live when we emit tMOVi32imm
3# to resolve a frame offset.
4
5--- |
6  target triple = "thumbv6m-arm-none-eabi"
7
8  define void @test_def_in_block(i32 %x) #0 {
9  entry:
10    %var = alloca i32, align 4
11    %dummy = alloca [2048 x i8], align 1
12    %cmp = icmp eq i32 %x, 0
13    store i32 %x, ptr %var, align 4
14    br i1 %cmp, label %if.then, label %if.end
15
16  if.then:
17    br label %if.end
18
19  if.end:
20    ret void
21  }
22
23  define void @test_live_in(i32 %x) #0 {
24  entry:
25    %var = alloca i32, align 4
26    %dummy = alloca [2048 x i8], align 1
27    %cmp = icmp eq i32 %x, 0
28    br i1 %cmp, label %if.then, label %if.end
29
30  if.then:
31    store i32 %x, ptr %var, align 4
32    %cmp1 = icmp slt i32 %x, 0
33    br i1 %cmp1, label %if.then2, label %if.end
34
35  if.then2:
36    br label %if.end
37
38  if.end:
39    ret void
40  }
41
42  define void @test_live_out(i32 %x) #0 {
43  entry:
44    %var = alloca i32, align 4
45    %dummy = alloca [2048 x i8], align 1
46    %cmp = icmp eq i32 %x, 0
47    store i32 %x, ptr %var, align 4
48    br label %if.then
49
50  if.then:
51    br i1 %cmp, label %if.then2, label %if.end
52
53  if.then2:
54    br label %if.end
55
56  if.end:
57    ret void
58  }
59
60  define void @test_live_out_def_after_mov(i32 %x) #0 {
61  entry:
62    %var = alloca i32, align 4
63    %dummy = alloca [2048 x i8], align 1
64    store i32 %x, ptr %var, align 4
65    %cmp = icmp eq i32 %x, 0
66    br label %if.then
67
68  if.then:
69    br i1 %cmp, label %if.then2, label %if.end
70
71  if.then2:
72    br label %if.end
73
74  if.end:
75    ret void
76  }
77
78  attributes #0 = { "target-features"="+execute-only" }
79...
80---
81name:            test_def_in_block
82alignment:       2
83exposesReturnsTwice: false
84legalized:       false
85regBankSelected: false
86selected:        false
87failedISel:      false
88tracksRegLiveness: true
89hasWinCFI:       false
90callsEHReturn:   false
91callsUnwindInit: false
92hasEHCatchret:   false
93hasEHScopes:     false
94hasEHFunclets:   false
95isOutlined:      false
96debugInstrRef:   false
97failsVerification: false
98tracksDebugUserValues: false
99registers:       []
100liveins:
101  - { reg: '$r0', virtual-reg: '' }
102frameInfo:
103  isFrameAddressTaken: false
104  isReturnAddressTaken: false
105  hasStackMap:     false
106  hasPatchPoint:   false
107  stackSize:       0
108  offsetAdjustment: 0
109  maxAlignment:    4
110  adjustsStack:    false
111  hasCalls:        false
112  stackProtector:  ''
113  functionContext: ''
114  maxCallFrameSize: 0
115  cvBytesOfCalleeSavedRegisters: 0
116  hasOpaqueSPAdjustment: false
117  hasVAStart:      false
118  hasMustTailInVarArgFunc: false
119  hasTailCall:     false
120  localFrameSize:  2052
121  savePoint:       ''
122  restorePoint:    ''
123fixedStack:      []
124stack:
125  - { id: 0, name: var, type: default, offset: 0, size: 4, alignment: 4,
126      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
127      local-offset: -4, debug-info-variable: '', debug-info-expression: '',
128      debug-info-location: '' }
129  - { id: 1, name: dummy, type: default, offset: 0, size: 2048, alignment: 1,
130      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
131      local-offset: -2052, debug-info-variable: '', debug-info-expression: '',
132      debug-info-location: '' }
133entry_values:    []
134callSites:       []
135debugValueSubstitutions: []
136constants:       []
137machineFunctionInfo: {}
138body:             |
139  bb.0.entry:
140    successors: %bb.1(0x40000000), %bb.2(0x40000000)
141    liveins: $r0
142
143    ; CHECK-LABEL: name: test_def_in_block
144    ; CHECK-LABEL: bb.0.entry:
145    ; CHECK: tCMPi8 renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr
146    ; CHECK-NEXT: $r2 = t2MRS_M 2048, 14 /* CC::al */, $noreg, implicit $cpsr
147    ; CHECK-NEXT: $r1 = tMOVi32imm 2048, implicit-def $cpsr
148    ; CHECK-NEXT: t2MSR_M 2048, killed $r2, 14 /* CC::al */, $noreg, implicit-def $cpsr
149    ; CHECK-NEXT: $r1 = tADDhirr $r1, killed $sp, 14 /* CC::al */, $noreg
150    ; CHECK-NEXT: tSTRi renamable $r0, killed $r1, 0, 14 /* CC::al */, $noreg :: (store (s32) into %ir.var)
151
152    tCMPi8 renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr
153    tSTRspi renamable $r0, %stack.0.var, 0, 14 /* CC::al */, $noreg :: (store (s32) into %ir.var)
154    tBcc %bb.1, 1 /* CC::ne */, killed $cpsr
155    tB %bb.2, 14 /* CC::al */, $noreg
156
157  bb.1.if.then:
158    successors: %bb.2(0x80000000)
159
160    tB %bb.2, 14 /* CC::al */, $noreg
161
162  bb.2.if.end:
163    tBX_RET 14 /* CC::al */, $noreg
164
165...
166---
167name:            test_live_in
168alignment:       2
169exposesReturnsTwice: false
170legalized:       false
171regBankSelected: false
172selected:        false
173failedISel:      false
174tracksRegLiveness: true
175hasWinCFI:       false
176callsEHReturn:   false
177callsUnwindInit: false
178hasEHCatchret:   false
179hasEHScopes:     false
180hasEHFunclets:   false
181isOutlined:      false
182debugInstrRef:   false
183failsVerification: false
184tracksDebugUserValues: false
185registers:       []
186liveins:
187  - { reg: '$r0', virtual-reg: '' }
188frameInfo:
189  isFrameAddressTaken: false
190  isReturnAddressTaken: false
191  hasStackMap:     false
192  hasPatchPoint:   false
193  stackSize:       0
194  offsetAdjustment: 0
195  maxAlignment:    4
196  adjustsStack:    false
197  hasCalls:        false
198  stackProtector:  ''
199  functionContext: ''
200  maxCallFrameSize: 0
201  cvBytesOfCalleeSavedRegisters: 0
202  hasOpaqueSPAdjustment: false
203  hasVAStart:      false
204  hasMustTailInVarArgFunc: false
205  hasTailCall:     false
206  localFrameSize:  2052
207  savePoint:       ''
208  restorePoint:    ''
209fixedStack:      []
210stack:
211  - { id: 0, name: var, type: default, offset: 0, size: 4, alignment: 4,
212      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
213      local-offset: -4, debug-info-variable: '', debug-info-expression: '',
214      debug-info-location: '' }
215  - { id: 1, name: dummy, type: default, offset: 0, size: 2048, alignment: 1,
216      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
217      local-offset: -2052, debug-info-variable: '', debug-info-expression: '',
218      debug-info-location: '' }
219entry_values:    []
220callSites:       []
221debugValueSubstitutions: []
222constants:       []
223machineFunctionInfo: {}
224body:             |
225  bb.0.entry:
226    successors: %bb.1(0x40000000), %bb.3(0x40000000)
227    liveins: $r0
228
229    tCMPi8 renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr
230    tBcc %bb.3, 1 /* CC::ne */, $cpsr
231    tB %bb.1, 14 /* CC::al */, $noreg
232
233  bb.1.if.then:
234    successors: %bb.2(0x40000000), %bb.3(0x40000000)
235    liveins: $r0, $cpsr
236
237    ; CHECK-LABEL: name: test_live_in
238    ; CHECK-LABEL: bb.1.if.then:
239    ; CHECK: $r2 = t2MRS_M 2048, 14 /* CC::al */, $noreg, implicit $cpsr
240    ; CHECK-NEXT: $r1 = tMOVi32imm 2048, implicit-def $cpsr
241    ; CHECK-NEXT: t2MSR_M 2048, killed $r2, 14 /* CC::al */, $noreg, implicit-def $cpsr
242    ; CHECK-NEXT: $r1 = tADDhirr $r1, killed $sp, 14 /* CC::al */, $noreg
243    ; CHECK-NEXT: tSTRi renamable $r0, killed $r1, 0, 14 /* CC::al */, $noreg :: (store (s32) into %ir.var)
244
245    tSTRspi renamable $r0, %stack.0.var, 0, 14 /* CC::al */, $noreg :: (store (s32) into %ir.var)
246    tBcc %bb.3, 5 /* CC::pl */, killed $cpsr
247    tB %bb.2, 14 /* CC::al */, $noreg
248
249  bb.2.if.then2:
250    successors: %bb.3(0x80000000)
251
252    tB %bb.3, 14 /* CC::al */, $noreg
253
254  bb.3.if.end:
255    tBX_RET 14 /* CC::al */, $noreg
256
257...
258---
259name:            test_live_out
260alignment:       2
261exposesReturnsTwice: false
262legalized:       false
263regBankSelected: false
264selected:        false
265failedISel:      false
266tracksRegLiveness: true
267hasWinCFI:       false
268callsEHReturn:   false
269callsUnwindInit: false
270hasEHCatchret:   false
271hasEHScopes:     false
272hasEHFunclets:   false
273isOutlined:      false
274debugInstrRef:   false
275failsVerification: false
276tracksDebugUserValues: false
277registers:       []
278liveins:
279  - { reg: '$r0', virtual-reg: '' }
280frameInfo:
281  isFrameAddressTaken: false
282  isReturnAddressTaken: false
283  hasStackMap:     false
284  hasPatchPoint:   false
285  stackSize:       0
286  offsetAdjustment: 0
287  maxAlignment:    4
288  adjustsStack:    false
289  hasCalls:        false
290  stackProtector:  ''
291  functionContext: ''
292  maxCallFrameSize: 0
293  cvBytesOfCalleeSavedRegisters: 0
294  hasOpaqueSPAdjustment: false
295  hasVAStart:      false
296  hasMustTailInVarArgFunc: false
297  hasTailCall:     false
298  localFrameSize:  2052
299  savePoint:       ''
300  restorePoint:    ''
301fixedStack:      []
302stack:
303  - { id: 0, name: var, type: default, offset: 0, size: 4, alignment: 4,
304      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
305      local-offset: -4, debug-info-variable: '', debug-info-expression: '',
306      debug-info-location: '' }
307  - { id: 1, name: dummy, type: default, offset: 0, size: 2048, alignment: 1,
308      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
309      local-offset: -2052, debug-info-variable: '', debug-info-expression: '',
310      debug-info-location: '' }
311entry_values:    []
312callSites:       []
313debugValueSubstitutions: []
314constants:       []
315machineFunctionInfo: {}
316body:             |
317  bb.0.entry:
318    successors: %bb.1(0x40000000)
319    liveins: $r0
320
321    ; CHECK-LABEL: name: test_live_out
322    ; CHECK-LABEL: bb.0.entry:
323    ; CHECK: tCMPi8 renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr
324    ; CHECK-NEXT: $r2 = t2MRS_M 2048, 14 /* CC::al */, $noreg, implicit $cpsr
325    ; CHECK-NEXT: $r1 = tMOVi32imm 2048, implicit-def $cpsr
326    ; CHECK-NEXT: t2MSR_M 2048, killed $r2, 14 /* CC::al */, $noreg, implicit-def $cpsr
327    ; CHECK-NEXT: $r1 = tADDhirr $r1, killed $sp, 14 /* CC::al */, $noreg
328    ; CHECK-NEXT: tSTRi renamable $r0, killed $r1, 0, 14 /* CC::al */, $noreg :: (store (s32) into %ir.var)
329
330    tCMPi8 renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr
331    tSTRspi renamable $r0, %stack.0.var, 0, 14 /* CC::al */, $noreg :: (store (s32) into %ir.var)
332    tB %bb.1, 14 /* CC::al */, $noreg
333
334  bb.1.if.then:
335    successors: %bb.2(0x40000000), %bb.3(0x40000000)
336    liveins: $cpsr
337
338    tBcc %bb.3, 5 /* CC::pl */, killed $cpsr
339    tB %bb.2, 14 /* CC::al */, $noreg
340
341  bb.2.if.then2:
342    successors: %bb.3(0x80000000)
343
344    tB %bb.3, 14 /* CC::al */, $noreg
345
346  bb.3.if.end:
347    tBX_RET 14 /* CC::al */, $noreg
348
349...
350---
351name:            test_live_out_def_after_mov
352alignment:       2
353exposesReturnsTwice: false
354legalized:       false
355regBankSelected: false
356selected:        false
357failedISel:      false
358tracksRegLiveness: true
359hasWinCFI:       false
360callsEHReturn:   false
361callsUnwindInit: false
362hasEHCatchret:   false
363hasEHScopes:     false
364hasEHFunclets:   false
365isOutlined:      false
366debugInstrRef:   false
367failsVerification: false
368tracksDebugUserValues: false
369registers:       []
370liveins:
371  - { reg: '$r0', virtual-reg: '' }
372frameInfo:
373  isFrameAddressTaken: false
374  isReturnAddressTaken: false
375  hasStackMap:     false
376  hasPatchPoint:   false
377  stackSize:       0
378  offsetAdjustment: 0
379  maxAlignment:    4
380  adjustsStack:    false
381  hasCalls:        false
382  stackProtector:  ''
383  functionContext: ''
384  maxCallFrameSize: 0
385  cvBytesOfCalleeSavedRegisters: 0
386  hasOpaqueSPAdjustment: false
387  hasVAStart:      false
388  hasMustTailInVarArgFunc: false
389  hasTailCall:     false
390  localFrameSize:  2052
391  savePoint:       ''
392  restorePoint:    ''
393fixedStack:      []
394stack:
395  - { id: 0, name: var, type: default, offset: 0, size: 4, alignment: 4,
396      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
397      local-offset: -4, debug-info-variable: '', debug-info-expression: '',
398      debug-info-location: '' }
399  - { id: 1, name: dummy, type: default, offset: 0, size: 2048, alignment: 1,
400      stack-id: default, callee-saved-register: '', callee-saved-restored: true,
401      local-offset: -2052, debug-info-variable: '', debug-info-expression: '',
402      debug-info-location: '' }
403entry_values:    []
404callSites:       []
405debugValueSubstitutions: []
406constants:       []
407machineFunctionInfo: {}
408body:             |
409  bb.0.entry:
410    successors: %bb.1(0x40000000)
411    liveins: $r0
412
413    ; Here the live-out cpsr is defined after the tMOVi32imm, so cpsr doesn't
414    ; need to be saved.
415    ; CHECK-LABEL: name: test_live_out
416    ; CHECK-LABEL: bb.0.entry:
417    ; CHECK: $r1 = tMOVi32imm 2048, implicit-def $cpsr
418    ; CHECK-NEXT: $r1 = tADDhirr $r1, killed $sp, 14 /* CC::al */, $noreg
419    ; CHECK-NEXT: tSTRi renamable $r0, killed $r1, 0, 14 /* CC::al */, $noreg :: (store (s32) into %ir.var)
420    ; CHECK-NEXT: tCMPi8 renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr
421
422    tSTRspi renamable $r0, %stack.0.var, 0, 14 /* CC::al */, $noreg :: (store (s32) into %ir.var)
423    tCMPi8 renamable $r0, 0, 14 /* CC::al */, $noreg, implicit-def $cpsr
424    tB %bb.1, 14 /* CC::al */, $noreg
425
426  bb.1.if.then:
427    successors: %bb.2(0x40000000), %bb.3(0x40000000)
428    liveins: $cpsr
429
430    tBcc %bb.3, 5 /* CC::pl */, killed $cpsr
431    tB %bb.2, 14 /* CC::al */, $noreg
432
433  bb.2.if.then2:
434    successors: %bb.3(0x80000000)
435
436    tB %bb.3, 14 /* CC::al */, $noreg
437
438  bb.3.if.end:
439    tBX_RET 14 /* CC::al */, $noreg
440
441...
442