1# RUN: llc -mtriple=aarch64-apple-darwin -run-pass=aarch64-ldst-opt -verify-machineinstrs -o - %s | FileCheck %s 2 3--- | 4 target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" 5 target triple = "arm64e-apple-ios13.0" 6 7 %struct.widget = type { i64, i64, i32, i32, i64, i64, i64, i64, i64, i32, i32, i32, i16, i32, ptr, %struct.zot, %struct.zot, %struct.zot, %struct.zot, %struct.zot, i64, i64, i64, i32, i64, i32, i32, i32, ptr, %struct.baz, %struct.baz, i64, i64, ptr, %struct.zot, i32, i32, i32, i32, i32, i32, i32, [32 x i8], i64, i64, %struct.wombat, i32, i64, i64, i64, i64 } 8 %struct.baz = type { [4 x i32] } 9 %struct.snork = type { i32, i32, [1 x %struct.spam] } 10 %struct.spam = type { %struct.baz, i32, i32 } 11 %struct.zot = type { i64, i64 } 12 %struct.wombat = type { [2 x i32] } 13 %struct.wombat.0 = type { [200 x i32] } 14 15 @__stack_chk_guard = external global ptr 16 17 ; Function Attrs: noredzone ssp 18 define hidden void @with_noredzone_80bytes() #0 { 19 bb: 20 %StackGuardSlot = alloca ptr, align 8 21 %0 = call ptr @llvm.stackguard() 22 call void @llvm.stackprotector(ptr %0, ptr %StackGuardSlot) 23 %tmp = alloca %struct.widget, align 16 24 %tmp1 = alloca ptr, align 8 25 %tmp2 = alloca ptr, align 8 26 %tmp3 = alloca ptr, align 8 27 %tmp4 = alloca ptr, align 8 28 store ptr null, ptr %tmp3, align 8 29 store ptr null, ptr %tmp4, align 8 30 ret void 31 } 32 33 define hidden void @with_redzone_480bytes() #2 { 34 bb: 35 %StackGuardSlot = alloca ptr, align 8 36 %0 = call ptr @llvm.stackguard() 37 call void @llvm.stackprotector(ptr %0, ptr %StackGuardSlot) 38 %tmp = alloca %struct.widget, align 16 39 %tmp1 = alloca ptr, align 8 40 %tmp2 = alloca ptr, align 8 41 %tmp3 = alloca ptr, align 8 42 %tmp4 = alloca ptr, align 8 43 store ptr null, ptr %tmp3, align 8 44 store ptr null, ptr %tmp4, align 8 45 ret void 46 } 47 48 define hidden void @with_noredzone_no_mem_between() #0 { 49 bb: 50 %StackGuardSlot = alloca ptr, align 8 51 %0 = call ptr @llvm.stackguard() 52 call void @llvm.stackprotector(ptr %0, ptr %StackGuardSlot) 53 %tmp = alloca %struct.widget, align 16 54 %tmp1 = alloca ptr, align 8 55 %tmp2 = alloca ptr, align 8 56 %tmp3 = alloca ptr, align 8 57 %tmp4 = alloca ptr, align 8 58 store ptr null, ptr %tmp3, align 8 59 store ptr null, ptr %tmp4, align 8 60 ret void 61 } 62 63 ; Function Attrs: nofree nosync nounwind willreturn 64 declare ptr @llvm.stackguard() #1 65 66 ; Function Attrs: nofree nosync nounwind willreturn 67 declare void @llvm.stackprotector(ptr, ptr) #1 68 69 attributes #0 = { noredzone ssp "frame-pointer"="non-leaf" } 70 attributes #1 = { nofree nosync nounwind willreturn } 71 attributes #2 = { ssp "frame-pointer"="non-leaf" } 72... 73# Check that we don't try to combine the SUB with the STP using pre-index addressing 74# if the function does not have redzone enabled. 75# CHECK-LABEL: name: with_noredzone_80bytes 76# CHECK-NOT: STPXpre $xzr, $xzr 77--- 78name: with_noredzone_80bytes 79alignment: 4 80exposesReturnsTwice: false 81legalized: false 82regBankSelected: false 83selected: false 84failedISel: false 85tracksRegLiveness: true 86hasWinCFI: false 87registers: [] 88liveins: [] 89frameInfo: 90 isFrameAddressTaken: false 91 isReturnAddressTaken: false 92 hasStackMap: false 93 hasPatchPoint: false 94 stackSize: 512 95 offsetAdjustment: 0 96 maxAlignment: 16 97 adjustsStack: true 98 hasCalls: true 99 stackProtector: '%stack.0.StackGuardSlot' 100 maxCallFrameSize: 0 101 cvBytesOfCalleeSavedRegisters: 0 102 hasOpaqueSPAdjustment: false 103 hasVAStart: false 104 hasMustTailInVarArgFunc: false 105 localFrameSize: 480 106 savePoint: '' 107 restorePoint: '' 108fixedStack: [] 109stack: 110 - { id: 0, name: StackGuardSlot, type: default, offset: -40, size: 8, 111 alignment: 8, stack-id: default, callee-saved-register: '', callee-saved-restored: true, 112 local-offset: -8, debug-info-variable: '', debug-info-expression: '', 113 debug-info-location: '' } 114 - { id: 1, name: tmp, type: default, offset: -480, size: 440, alignment: 16, 115 stack-id: default, callee-saved-register: '', callee-saved-restored: true, 116 local-offset: -448, debug-info-variable: '', debug-info-expression: '', 117 debug-info-location: '' } 118 - { id: 2, name: tmp1, type: default, offset: -488, size: 8, alignment: 8, 119 stack-id: default, callee-saved-register: '', callee-saved-restored: true, 120 local-offset: -456, debug-info-variable: '', debug-info-expression: '', 121 debug-info-location: '' } 122 - { id: 3, name: tmp2, type: default, offset: -496, size: 8, alignment: 8, 123 stack-id: default, callee-saved-register: '', callee-saved-restored: true, 124 local-offset: -464, debug-info-variable: '', debug-info-expression: '', 125 debug-info-location: '' } 126 - { id: 4, name: tmp3, type: default, offset: -504, size: 8, alignment: 8, 127 stack-id: default, callee-saved-register: '', callee-saved-restored: true, 128 local-offset: -472, debug-info-variable: '', debug-info-expression: '', 129 debug-info-location: '' } 130 - { id: 5, name: tmp4, type: default, offset: -512, size: 8, alignment: 8, 131 stack-id: default, callee-saved-register: '', callee-saved-restored: true, 132 local-offset: -480, debug-info-variable: '', debug-info-expression: '', 133 debug-info-location: '' } 134 - { id: 6, name: '', type: spill-slot, offset: -8, size: 8, alignment: 8, 135 stack-id: default, callee-saved-register: '$lr', callee-saved-restored: true, 136 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } 137 - { id: 7, name: '', type: spill-slot, offset: -16, size: 8, alignment: 8, 138 stack-id: default, callee-saved-register: '$fp', callee-saved-restored: true, 139 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } 140 - { id: 8, name: '', type: spill-slot, offset: -24, size: 8, alignment: 8, 141 stack-id: default, callee-saved-register: '$x27', callee-saved-restored: true, 142 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } 143 - { id: 9, name: '', type: spill-slot, offset: -32, size: 8, alignment: 8, 144 stack-id: default, callee-saved-register: '$x28', callee-saved-restored: true, 145 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } 146callSites: [] 147debugValueSubstitutions: [] 148constants: [] 149machineFunctionInfo: 150 hasRedZone: false 151body: | 152 bb.0.bb: 153 successors: %bb.1(0x7ffff800), %bb.2(0x00000800) 154 liveins: $x27, $x28, $lr 155 early-clobber $sp = frame-setup STPXpre killed $x28, killed $x27, $sp, -4 :: (store (s64) into %stack.9), (store (s64) into %stack.8) 156 frame-setup STPXi killed $fp, killed $lr, $sp, 2 :: (store (s64) into %stack.7), (store (s64) into %stack.6) 157 $fp = frame-setup ADDXri $sp, 16, 0 158 $sp = frame-setup SUBXri $sp, 80, 0 159 frame-setup CFI_INSTRUCTION def_cfa $w29, 16 160 frame-setup CFI_INSTRUCTION offset $w30, -8 161 frame-setup CFI_INSTRUCTION offset $w29, -16 162 frame-setup CFI_INSTRUCTION offset $w27, -24 163 frame-setup CFI_INSTRUCTION offset $w28, -32 164 $x8 = ADRP target-flags(aarch64-page, aarch64-got) @__stack_chk_guard 165 $x8 = LDRXui killed $x8, target-flags(aarch64-pageoff, aarch64-got, aarch64-nc) @__stack_chk_guard 166 $x8 = LDRXui killed $x8, 0 :: (dereferenceable invariant load (s64) from @__stack_chk_guard) 167 STURXi killed renamable $x8, $fp, -24 :: (volatile store (s64) into %stack.0.StackGuardSlot) 168 STRXui $xzr, $sp, 1 :: (store (s64) into %ir.tmp3) 169 STRXui $xzr, $sp, 0 :: (store (s64) into %ir.tmp4) 170 renamable $x8 = LDURXi $fp, -24 :: (volatile load (s64) from %stack.0.StackGuardSlot) 171 $x9 = ADRP target-flags(aarch64-page, aarch64-got) @__stack_chk_guard 172 $x9 = LDRXui killed $x9, target-flags(aarch64-pageoff, aarch64-got, aarch64-nc) @__stack_chk_guard 173 $x9 = LDRXui killed $x9, 0 :: (dereferenceable invariant load (s64) from @__stack_chk_guard) 174 $xzr = SUBSXrs killed renamable $x9, killed renamable $x8, 0, implicit-def $nzcv, implicit-def $nzcv 175 Bcc 1, %bb.2, implicit $nzcv 176 177 bb.1.bb: 178 $sp = frame-destroy ADDXri $sp, 480, 0 179 $fp, $lr = frame-destroy LDPXi $sp, 2 :: (load (s64) from %stack.7), (load (s64) from %stack.6) 180 early-clobber $sp, $x28, $x27 = frame-destroy LDPXpost $sp, 4 :: (load (s64) from %stack.9), (load (s64) from %stack.8) 181 RET undef $lr 182 183 bb.2.bb: 184 BL &__stack_chk_fail, csr_darwin_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp 185 186... 187# Check we don't try to fold a 480 byte offset, even if we have a 128 byte redzone. 188# CHECK-LABEL: name: with_redzone_480bytes 189# CHECK-NOT: STPXpre $xzr, $xzr 190--- 191name: with_redzone_480bytes 192alignment: 4 193exposesReturnsTwice: false 194legalized: false 195regBankSelected: false 196selected: false 197failedISel: false 198tracksRegLiveness: true 199hasWinCFI: false 200registers: [] 201liveins: [] 202frameInfo: 203 isFrameAddressTaken: false 204 isReturnAddressTaken: false 205 hasStackMap: false 206 hasPatchPoint: false 207 stackSize: 512 208 offsetAdjustment: 0 209 maxAlignment: 16 210 adjustsStack: true 211 hasCalls: true 212 stackProtector: '%stack.0.StackGuardSlot' 213 maxCallFrameSize: 0 214 cvBytesOfCalleeSavedRegisters: 0 215 hasOpaqueSPAdjustment: false 216 hasVAStart: false 217 hasMustTailInVarArgFunc: false 218 localFrameSize: 480 219 savePoint: '' 220 restorePoint: '' 221fixedStack: [] 222stack: 223 - { id: 0, name: StackGuardSlot, type: default, offset: -40, size: 8, 224 alignment: 8, stack-id: default, callee-saved-register: '', callee-saved-restored: true, 225 local-offset: -8, debug-info-variable: '', debug-info-expression: '', 226 debug-info-location: '' } 227 - { id: 1, name: tmp, type: default, offset: -480, size: 440, alignment: 16, 228 stack-id: default, callee-saved-register: '', callee-saved-restored: true, 229 local-offset: -448, debug-info-variable: '', debug-info-expression: '', 230 debug-info-location: '' } 231 - { id: 2, name: tmp1, type: default, offset: -488, size: 8, alignment: 8, 232 stack-id: default, callee-saved-register: '', callee-saved-restored: true, 233 local-offset: -456, debug-info-variable: '', debug-info-expression: '', 234 debug-info-location: '' } 235 - { id: 3, name: tmp2, type: default, offset: -496, size: 8, alignment: 8, 236 stack-id: default, callee-saved-register: '', callee-saved-restored: true, 237 local-offset: -464, debug-info-variable: '', debug-info-expression: '', 238 debug-info-location: '' } 239 - { id: 4, name: tmp3, type: default, offset: -504, size: 8, alignment: 8, 240 stack-id: default, callee-saved-register: '', callee-saved-restored: true, 241 local-offset: -472, debug-info-variable: '', debug-info-expression: '', 242 debug-info-location: '' } 243 - { id: 5, name: tmp4, type: default, offset: -512, size: 8, alignment: 8, 244 stack-id: default, callee-saved-register: '', callee-saved-restored: true, 245 local-offset: -480, debug-info-variable: '', debug-info-expression: '', 246 debug-info-location: '' } 247 - { id: 6, name: '', type: spill-slot, offset: -8, size: 8, alignment: 8, 248 stack-id: default, callee-saved-register: '$lr', callee-saved-restored: true, 249 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } 250 - { id: 7, name: '', type: spill-slot, offset: -16, size: 8, alignment: 8, 251 stack-id: default, callee-saved-register: '$fp', callee-saved-restored: true, 252 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } 253 - { id: 8, name: '', type: spill-slot, offset: -24, size: 8, alignment: 8, 254 stack-id: default, callee-saved-register: '$x27', callee-saved-restored: true, 255 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } 256 - { id: 9, name: '', type: spill-slot, offset: -32, size: 8, alignment: 8, 257 stack-id: default, callee-saved-register: '$x28', callee-saved-restored: true, 258 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } 259callSites: [] 260debugValueSubstitutions: [] 261constants: [] 262body: | 263 bb.0.bb: 264 successors: %bb.1(0x7ffff800), %bb.2(0x00000800) 265 liveins: $x27, $x28, $lr 266 early-clobber $sp = frame-setup STPXpre killed $x28, killed $x27, $sp, -4 :: (store (s64) into %stack.9), (store (s64) into %stack.8) 267 frame-setup STPXi killed $fp, killed $lr, $sp, 2 :: (store (s64) into %stack.7), (store (s64) into %stack.6) 268 $fp = frame-setup ADDXri $sp, 16, 0 269 $sp = frame-setup SUBXri $sp, 480, 0 270 frame-setup CFI_INSTRUCTION def_cfa $w29, 16 271 frame-setup CFI_INSTRUCTION offset $w30, -8 272 frame-setup CFI_INSTRUCTION offset $w29, -16 273 frame-setup CFI_INSTRUCTION offset $w27, -24 274 frame-setup CFI_INSTRUCTION offset $w28, -32 275 $x8 = ADRP target-flags(aarch64-page, aarch64-got) @__stack_chk_guard 276 $x8 = LDRXui killed $x8, target-flags(aarch64-pageoff, aarch64-got, aarch64-nc) @__stack_chk_guard 277 $x8 = LDRXui killed $x8, 0 :: (dereferenceable invariant load (s64) from @__stack_chk_guard) 278 STURXi killed renamable $x8, $fp, -24 :: (volatile store (s64) into %stack.0.StackGuardSlot) 279 STRXui $xzr, $sp, 1 :: (store (s64) into %ir.tmp3) 280 STRXui $xzr, $sp, 0 :: (store (s64) into %ir.tmp4) 281 renamable $x8 = LDURXi $fp, -24 :: (volatile load (s64) from %stack.0.StackGuardSlot) 282 $x9 = ADRP target-flags(aarch64-page, aarch64-got) @__stack_chk_guard 283 $x9 = LDRXui killed $x9, target-flags(aarch64-pageoff, aarch64-got, aarch64-nc) @__stack_chk_guard 284 $x9 = LDRXui killed $x9, 0 :: (dereferenceable invariant load (s64) from @__stack_chk_guard) 285 $xzr = SUBSXrs killed renamable $x9, killed renamable $x8, 0, implicit-def $nzcv, implicit-def $nzcv 286 Bcc 1, %bb.2, implicit $nzcv 287 288 bb.1.bb: 289 $sp = frame-destroy ADDXri $sp, 480, 0 290 $fp, $lr = frame-destroy LDPXi $sp, 2 :: (load (s64) from %stack.7), (load (s64) from %stack.6) 291 early-clobber $sp, $x28, $x27 = frame-destroy LDPXpost $sp, 4 :: (load (s64) from %stack.9), (load (s64) from %stack.8) 292 RET undef $lr 293 294 bb.2.bb: 295 BL &__stack_chk_fail, csr_darwin_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp 296 297... 298# Check we still do the opt if there are no mem ops between. 299# CHECK-LABEL: name: with_noredzone_no_mem_between 300# CHECK: STPXpre $xzr, $xzr 301--- 302name: with_noredzone_no_mem_between 303alignment: 4 304exposesReturnsTwice: false 305legalized: false 306regBankSelected: false 307selected: false 308failedISel: false 309tracksRegLiveness: true 310hasWinCFI: false 311registers: [] 312liveins: [] 313frameInfo: 314 isFrameAddressTaken: false 315 isReturnAddressTaken: false 316 hasStackMap: false 317 hasPatchPoint: false 318 stackSize: 512 319 offsetAdjustment: 0 320 maxAlignment: 16 321 adjustsStack: true 322 hasCalls: true 323 stackProtector: '%stack.0.StackGuardSlot' 324 maxCallFrameSize: 0 325 cvBytesOfCalleeSavedRegisters: 0 326 hasOpaqueSPAdjustment: false 327 hasVAStart: false 328 hasMustTailInVarArgFunc: false 329 localFrameSize: 480 330 savePoint: '' 331 restorePoint: '' 332fixedStack: [] 333stack: 334 - { id: 0, name: StackGuardSlot, type: default, offset: -40, size: 8, 335 alignment: 8, stack-id: default, callee-saved-register: '', callee-saved-restored: true, 336 local-offset: -8, debug-info-variable: '', debug-info-expression: '', 337 debug-info-location: '' } 338 - { id: 1, name: tmp, type: default, offset: -480, size: 440, alignment: 16, 339 stack-id: default, callee-saved-register: '', callee-saved-restored: true, 340 local-offset: -448, debug-info-variable: '', debug-info-expression: '', 341 debug-info-location: '' } 342 - { id: 2, name: tmp1, type: default, offset: -488, size: 8, alignment: 8, 343 stack-id: default, callee-saved-register: '', callee-saved-restored: true, 344 local-offset: -456, debug-info-variable: '', debug-info-expression: '', 345 debug-info-location: '' } 346 - { id: 3, name: tmp2, type: default, offset: -496, size: 8, alignment: 8, 347 stack-id: default, callee-saved-register: '', callee-saved-restored: true, 348 local-offset: -464, debug-info-variable: '', debug-info-expression: '', 349 debug-info-location: '' } 350 - { id: 4, name: tmp3, type: default, offset: -504, size: 8, alignment: 8, 351 stack-id: default, callee-saved-register: '', callee-saved-restored: true, 352 local-offset: -472, debug-info-variable: '', debug-info-expression: '', 353 debug-info-location: '' } 354 - { id: 5, name: tmp4, type: default, offset: -512, size: 8, alignment: 8, 355 stack-id: default, callee-saved-register: '', callee-saved-restored: true, 356 local-offset: -480, debug-info-variable: '', debug-info-expression: '', 357 debug-info-location: '' } 358 - { id: 6, name: '', type: spill-slot, offset: -8, size: 8, alignment: 8, 359 stack-id: default, callee-saved-register: '$lr', callee-saved-restored: true, 360 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } 361 - { id: 7, name: '', type: spill-slot, offset: -16, size: 8, alignment: 8, 362 stack-id: default, callee-saved-register: '$fp', callee-saved-restored: true, 363 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } 364 - { id: 8, name: '', type: spill-slot, offset: -24, size: 8, alignment: 8, 365 stack-id: default, callee-saved-register: '$x27', callee-saved-restored: true, 366 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } 367 - { id: 9, name: '', type: spill-slot, offset: -32, size: 8, alignment: 8, 368 stack-id: default, callee-saved-register: '$x28', callee-saved-restored: true, 369 debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } 370callSites: [] 371debugValueSubstitutions: [] 372constants: [] 373machineFunctionInfo: 374 hasRedZone: false 375body: | 376 bb.0.bb: 377 successors: %bb.1(0x7ffff800), %bb.2(0x00000800) 378 liveins: $x27, $x28, $lr 379 early-clobber $sp = frame-setup STPXpre killed $x28, killed $x27, $sp, -4 :: (store (s64) into %stack.9), (store (s64) into %stack.8) 380 frame-setup STPXi killed $fp, killed $lr, $sp, 2 :: (store (s64) into %stack.7), (store (s64) into %stack.6) 381 $fp = frame-setup ADDXri $sp, 16, 0 382 $sp = frame-setup SUBXri $sp, 480, 0 383 frame-setup CFI_INSTRUCTION def_cfa $w29, 16 384 frame-setup CFI_INSTRUCTION offset $w30, -8 385 frame-setup CFI_INSTRUCTION offset $w29, -16 386 frame-setup CFI_INSTRUCTION offset $w27, -24 387 frame-setup CFI_INSTRUCTION offset $w28, -32 388 $x8 = ADRP target-flags(aarch64-page, aarch64-got) @__stack_chk_guard 389 STRXui $xzr, $sp, 1 :: (store (s64) into %ir.tmp3) 390 STRXui $xzr, $sp, 0 :: (store (s64) into %ir.tmp4) 391 renamable $x8 = LDURXi $fp, -24 :: (volatile load (s64) from %stack.0.StackGuardSlot) 392 $x9 = ADRP target-flags(aarch64-page, aarch64-got) @__stack_chk_guard 393 $x9 = LDRXui killed $x9, target-flags(aarch64-pageoff, aarch64-got, aarch64-nc) @__stack_chk_guard 394 $x9 = LDRXui killed $x9, 0 :: (dereferenceable invariant load (s64) from @__stack_chk_guard) 395 $xzr = SUBSXrs killed renamable $x9, killed renamable $x8, 0, implicit-def $nzcv, implicit-def $nzcv 396 Bcc 1, %bb.2, implicit $nzcv 397 398 bb.1.bb: 399 $sp = frame-destroy ADDXri $sp, 480, 0 400 $fp, $lr = frame-destroy LDPXi $sp, 2 :: (load (s64) from %stack.7), (load (s64) from %stack.6) 401 early-clobber $sp, $x28, $x27 = frame-destroy LDPXpost $sp, 4 :: (load (s64) from %stack.9), (load (s64) from %stack.8) 402 RET undef $lr 403 404 bb.2.bb: 405 BL &__stack_chk_fail, csr_darwin_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp 406 407... 408