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