By reordering the objects on the stack frame after looking at the users, a better utilization of displacement operands will result. This means less needed Load Address instructions for the accessing of these objects. This is important for very large functions where otherwise small changes could cause a lot more/less accesses go out of range. Note: this is not yet enabled for SystemZXPLINKFrameLowering, but should be. Review: Ulrich Weigand Differential Revision: https://reviews.llvm.org/D115690
204 lines
6.2 KiB
YAML
204 lines
6.2 KiB
YAML
# RUN: llc -mtriple=s390x-linux-gnu -start-before=prologepilog %s -o - -mcpu=z14 \
|
|
# RUN: -debug-only=prologepilog -print-after=prologepilog -verify-machineinstrs 2>&1 \
|
|
# RUN: | FileCheck %s
|
|
# REQUIRES: asserts
|
|
#
|
|
# Test that stack objects are ordered in a good way with respect to the
|
|
# displacement operands of users.
|
|
|
|
--- |
|
|
define void @f1() { ret void }
|
|
define void @f2() { ret void }
|
|
define void @f3() { ret void }
|
|
define void @f4() { ret void }
|
|
define void @f5() { ret void }
|
|
define void @f6() { ret void }
|
|
|
|
...
|
|
|
|
### Test that %stack.0 is placed close to its D12 user.
|
|
# CHECK: alloc FI(1) at SP[-4255]
|
|
# CHECK-NEXT: alloc FI(0) at SP[-4271]
|
|
# CHECK-NEXT: alloc FI(2) at SP[-4280]
|
|
# CHECK-NEXT: alloc FI(3) at SP[-4288]
|
|
# CHECK-NEXT: # *** IR Dump After Prologue/Epilogue Insertion & Frame Finalization
|
|
# CHECK-NEXT: # Machine code for function f1: IsSSA, NoPHIs, TracksLiveness, NoVRegs
|
|
# CHECK-NOT: LAY
|
|
# CHECK: VL32
|
|
---
|
|
name: f1
|
|
tracksRegLiveness: true
|
|
stack:
|
|
- { id: 0, size: 16 }
|
|
- { id: 1, size: 4095 }
|
|
machineFunctionInfo: {}
|
|
body: |
|
|
bb.0:
|
|
renamable $f0s = VL32 %stack.0, 0, $noreg
|
|
Return
|
|
|
|
...
|
|
|
|
### Test that %stack.1 is placed close to its D12 user.
|
|
# CHECK: alloc FI(0) at SP[-176]
|
|
# CHECK-NEXT: alloc FI(1) at SP[-4271]
|
|
# CHECK-NEXT: alloc FI(2) at SP[-4280]
|
|
# CHECK-NEXT: alloc FI(3) at SP[-4288]
|
|
# CHECK-NEXT: # *** IR Dump After Prologue/Epilogue Insertion & Frame Finalization
|
|
# CHECK-NEXT: # Machine code for function f2: IsSSA, NoPHIs, TracksLiveness, NoVRegs
|
|
# CHECK-NOT: LAY
|
|
# CHECK: VL32
|
|
---
|
|
name: f2
|
|
tracksRegLiveness: true
|
|
stack:
|
|
- { id: 0, size: 16 }
|
|
- { id: 1, size: 4095 }
|
|
machineFunctionInfo: {}
|
|
body: |
|
|
bb.0:
|
|
renamable $f0s = VL32 %stack.1, 3916, $noreg
|
|
Return
|
|
|
|
...
|
|
|
|
### Swap the order of the objects so that both accesses are in range.
|
|
# CHECK: alloc FI(1) at SP[-8350]
|
|
# CHECK-NEXT: alloc FI(0) at SP[-12445]
|
|
# CHECK-NEXT: alloc FI(2) at SP[-12456]
|
|
# CHECK-NEXT: alloc FI(3) at SP[-12464]
|
|
# CHECK-NEXT: # *** IR Dump After Prologue/Epilogue Insertion & Frame Finalization
|
|
# CHECK-NEXT: # Machine code for function f3: IsSSA, NoPHIs, TracksLiveness, NoVRegs
|
|
# CHECK-NOT: LAY
|
|
# CHECK: VL32
|
|
# CHECK-NOT: LAY
|
|
# CHECK: LEY
|
|
---
|
|
name: f3
|
|
tracksRegLiveness: true
|
|
stack:
|
|
- { id: 0, size: 4095 }
|
|
- { id: 1, size: 8190 }
|
|
machineFunctionInfo: {}
|
|
body: |
|
|
bb.0:
|
|
renamable $f0s = VL32 %stack.0, 0, $noreg
|
|
renamable $f0s = LE %stack.1, 0, $noreg
|
|
Return
|
|
|
|
...
|
|
|
|
### Reorder the objects so that all accesses are in range.
|
|
# CHECK: alloc FI(0) at SP[-8350]
|
|
# CHECK-NEXT: alloc FI(2) at SP[-16540]
|
|
# CHECK-NEXT: alloc FI(3) at SP[-24730]
|
|
# CHECK-NEXT: alloc FI(1) at SP[-26777]
|
|
# CHECK-NEXT: alloc FI(4) at SP[-28824]
|
|
# CHECK-NEXT: alloc FI(5) at SP[-28832]
|
|
# CHECK-NEXT: alloc FI(6) at SP[-28840]
|
|
# CHECK-NEXT: # *** IR Dump After Prologue/Epilogue Insertion & Frame Finalization
|
|
# CHECK-NEXT: # Machine code for function f4: IsSSA, NoPHIs, TracksLiveness, NoVRegs
|
|
# CHECK-NOT: LAY
|
|
# CHECK: LEY
|
|
# CHECK-NEXT: VL32
|
|
# CHECK-NEXT: LEY
|
|
# CHECK-NEXT: LEY
|
|
# CHECK-NEXT: VL32
|
|
---
|
|
name: f4
|
|
tracksRegLiveness: true
|
|
stack:
|
|
- { id: 0, size: 8190 }
|
|
- { id: 1, size: 2047 }
|
|
- { id: 2, size: 8190 }
|
|
- { id: 3, size: 8190 }
|
|
- { id: 4, size: 2047 }
|
|
machineFunctionInfo: {}
|
|
body: |
|
|
bb.0:
|
|
renamable $f2s = LE %stack.0, 0, $noreg
|
|
renamable $f0s = VL32 %stack.1, 0, $noreg
|
|
renamable $f3s = LEY %stack.2, 0, $noreg
|
|
renamable $f4s = LE %stack.3, 0, $noreg
|
|
renamable $f1s = VL32 %stack.4, 0, $noreg
|
|
Return
|
|
|
|
...
|
|
|
|
### Reorder the objects so that the VL32 object is in range and the LYs are
|
|
### shortened to Ls (STOC cannot be shortened).
|
|
# CHECK: alloc FI(0) at SP[-8350]
|
|
# CHECK-NEXT: alloc FI(1) at SP[-16540]
|
|
# CHECK-NEXT: alloc FI(2) at SP[-24730]
|
|
# CHECK-NEXT: alloc FI(3) at SP[-26777]
|
|
# CHECK-NEXT: alloc FI(4) at SP[-26792]
|
|
# CHECK-NEXT: alloc FI(5) at SP[-26800]
|
|
# CHECK-NEXT: # *** IR Dump After Prologue/Epilogue Insertion & Frame Finalization
|
|
# CHECK-NEXT: # Machine code for function f5: IsSSA, NoPHIs, TracksLiveness, NoVRegs
|
|
# CHECK-NOT: LAY
|
|
# CHECK: $r1l = L $r15
|
|
# CHECK-NEXT: $r1l = L $r15
|
|
# CHECK-NEXT: IMPLICIT_DEF
|
|
# CHECK-NEXT: STOC
|
|
# CHECK-NEXT: STOC
|
|
# CHECK-NEXT: VL32
|
|
---
|
|
name: f5
|
|
tracksRegLiveness: true
|
|
stack:
|
|
- { id: 0, size: 8190 }
|
|
- { id: 1, size: 8190 }
|
|
- { id: 2, size: 8190 }
|
|
- { id: 3, size: 2047 }
|
|
machineFunctionInfo: {}
|
|
body: |
|
|
bb.0:
|
|
$r1l = LY %stack.2, 0, $noreg
|
|
$r1l = LY %stack.2, 0, $noreg
|
|
$cc = IMPLICIT_DEF
|
|
STOC $r1l, %stack.0, 0, 14, 8, implicit $cc
|
|
STOC $r1l, %stack.1, 0, 14, 8, implicit $cc
|
|
renamable $f3s = VL32 %stack.3, 0, $noreg
|
|
Return
|
|
|
|
...
|
|
|
|
### Test handling of a variable sized object.
|
|
# CHECK: alloc FI(1) at SP[-476]
|
|
# CHECK-NEXT: alloc FI(0) at SP[-776]
|
|
# CHECK-NEXT: alloc FI(2) at SP[-776]
|
|
# CHECK-NEXT: # *** IR Dump After Prologue/Epilogue Insertion & Frame Finalization
|
|
# CHECK-NEXT: # Machine code for function f6: IsSSA, NoPHIs, TracksLiveness, NoVRegs
|
|
|
|
# CHECK: $r15d = AGHI $r15d(tied-def 0), -776, implicit-def dead $cc
|
|
# CHECK: $r11d = LGR $r15d
|
|
# CHECK: renamable $r2d = ADJDYNALLOC renamable $r1d, 0, $noreg
|
|
# CHECK: VST64 renamable $f0d, $r11d, 160, $noreg
|
|
# CHECK: VST32 renamable $f1s, $r11d, 460, $noreg
|
|
# CHECK: VST32 killed renamable $f0s, killed renamable $r2d, 0, $noreg
|
|
---
|
|
name: f6
|
|
tracksRegLiveness: true
|
|
stack:
|
|
- { id: 0, size: 300 }
|
|
- { id: 1, size: 316 }
|
|
- { id: 2, type: variable-sized }
|
|
machineFunctionInfo: {}
|
|
body: |
|
|
bb.0 (%ir-block.0):
|
|
liveins: $f0d, $f0s, $f1s, $r2l
|
|
|
|
renamable $r2l = KILL $r2l, implicit-def $r2d
|
|
renamable $r1d = RISBGN undef renamable $r1d, killed renamable $r2d, 30, 189, 2
|
|
renamable $r0d = nuw LA killed renamable $r1d, 7, $noreg
|
|
renamable $r0d = RISBGN undef renamable $r0d, killed renamable $r0d, 29, 188, 0
|
|
renamable $r1d = SGRK $r15d, killed renamable $r0d, implicit-def dead $cc
|
|
renamable $r2d = ADJDYNALLOC renamable $r1d, 0, $noreg
|
|
$r15d = COPY killed renamable $r1d
|
|
VST64 renamable $f0d, %stack.0, 0, $noreg
|
|
VST32 renamable $f1s, %stack.1, 0, $noreg
|
|
VST32 killed renamable $f0s, killed renamable $r2d, 0, $noreg
|
|
Return
|
|
|
|
...
|