# RUN: llc -mtriple=s390x-linux-gnu -start-before=prologepilog %s -o - -mcpu=z14 \ # RUN: -verify-machineinstrs 2>&1 | FileCheck %s # REQUIRES: asserts # # Test that redundant frame addressing anchor points are removed by # MachineLateInstrsCleanup. --- | define void @fun1() { ret void } define void @fun2() { ret void } define void @fun3() { ret void } define void @fun4() { ret void } define void @fun5() { ret void } define void @fun6() { ret void } define void @fun7() { ret void } define void @fun8() { ret void } declare i32 @foo() @ptr = external dso_local local_unnamed_addr global ptr --- # Test elimination of redundant LAYs in successor blocks. # CHECK-LABEL: fun1: # CHECK: lay %r1, 4096(%r15) # CHECK: # %bb.1: # CHECK-NOT: lay # CHECK: .LBB0_2: # CHECK-NOT: lay --- name: fun1 tracksRegLiveness: true stack: - { id: 0, size: 5000 } - { id: 1, size: 2500 } - { id: 2, size: 2500 } machineFunctionInfo: {} body: | bb.0 (%ir-block.0): liveins: $f16d successors: %bb.2(0x00000001), %bb.1(0x7fffffff) VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.1, 0, $noreg CHIMux undef $r0l, 3, implicit-def $cc BRC 14, 8, %bb.2, implicit killed $cc J %bb.1 bb.1: liveins: $f16d VST64 renamable $f16d, %stack.2, 0, $noreg J %bb.2 bb.2: liveins: $f16d VST64 renamable $f16d, %stack.1, 0, $noreg Return ... # In this function the LAY in bb.1 will have a different offset, so the first # LAY in bb.2 must remain. # CHECK-LABEL: fun2: # CHECK: lay %r1, 4096(%r15) # CHECK: # %bb.1: # CHECK: lay %r1, 8192(%r15) # CHECK: .LBB1_2: # CHECK: lay %r1, 4096(%r15) # CHECK-NOT: lay --- name: fun2 tracksRegLiveness: true stack: - { id: 0, size: 5000 } - { id: 1, size: 5000 } - { id: 2, size: 2500 } machineFunctionInfo: {} body: | bb.0 (%ir-block.0): liveins: $f16d successors: %bb.2(0x00000001), %bb.1(0x7fffffff) VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.1, 0, $noreg CHIMux undef $r0l, 3, implicit-def $cc BRC 14, 8, %bb.2, implicit killed $cc J %bb.1 bb.1: liveins: $f16d VST64 renamable $f16d, %stack.2, 0, $noreg J %bb.2 bb.2: liveins: $f16d VST64 renamable $f16d, %stack.1, 0, $noreg VST64 renamable $f16d, %stack.1, 0, $noreg Return ... # Test case with a loop (with room for improvement: since %r1 is not clobbered # inside the loop only the first LAY is needed). # CHECK-LABEL: fun3: # CHECK: lay %r1, 4096(%r15) # CHECK: .LBB2_1: # CHECK: lay %r1, 4096(%r15) # CHECK: .LBB2_2: # CHECK-NOT: lay %r1, 4096(%r15) --- name: fun3 tracksRegLiveness: true stack: - { id: 0, size: 5000 } - { id: 1, size: 2500 } - { id: 2, size: 2500 } machineFunctionInfo: {} body: | bb.0 (%ir-block.0): liveins: $f16d successors: %bb.2(0x00000001), %bb.1(0x7fffffff) VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.1, 0, $noreg CHIMux undef $r0l, 3, implicit-def $cc BRC 14, 8, %bb.2, implicit killed $cc J %bb.1 bb.1: liveins: $f16d successors: %bb.2(0x00000001), %bb.1(0x7fffffff) VST64 renamable $f16d, %stack.2, 0, $noreg CHIMux undef $r0l, 3, implicit-def $cc BRC 14, 8, %bb.1, implicit killed $cc J %bb.2 bb.2: liveins: $f16d VST64 renamable $f16d, %stack.1, 0, $noreg Return ... # Test case with a call which clobbers r1: the second LAY after the call is needed. # CHECK-LABEL: fun4: # CHECK: lay %r1, 4096(%r15) # CHECK: brasl # CHECK: lay %r1, 4096(%r15) --- name: fun4 tracksRegLiveness: true stack: - { id: 0, size: 5000 } - { id: 1, size: 2500 } machineFunctionInfo: {} body: | bb.0 (%ir-block.0): liveins: $f16d VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.1, 0, $noreg ADJCALLSTACKDOWN 0, 0 CallBRASL @foo, csr_systemz_elf, implicit-def dead $r14d, implicit-def dead $cc, implicit $fpc, implicit-def $r2l ADJCALLSTACKUP 0, 0 $f17d = IMPLICIT_DEF VST64 renamable $f17d, %stack.1, 0, $noreg Return ... # Test case where index reg is loaded instead of using an LAY. Only one LGHI is needed. # CHECK-LABEL: fun5: # CHECK: lghi %r1, 4096 # CHECK-NOT: lghi --- name: fun5 tracksRegLiveness: true stack: - { id: 0, size: 5000 } - { id: 1, size: 2500 } machineFunctionInfo: {} body: | bb.0 (%ir-block.0): liveins: $f16d VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg VST64 renamable $f16d, %stack.0, 0, $noreg $f0q = nofpexcept LXEB %stack.1, 0, $noreg, implicit $fpc $f1q = nofpexcept LXEB %stack.1, 0, $noreg, implicit $fpc Return ... # Test where the constant is a Global. Only one LARL is needed. # CHECK-LABEL: fun6: # CHECK: larl %r1, ptr # CHECK-NOT: larl --- name: fun6 alignment: 16 tracksRegLiveness: true tracksDebugUserValues: true frameInfo: maxAlignment: 1 maxCallFrameSize: 0 fixedStack: - { id: 0, offset: -160, size: 8, alignment: 8 } machineFunctionInfo: {} body: | bb.0: successors: %bb.2(0x30000000), %bb.1(0x50000000) renamable $r1d = LARL @ptr CGHSI killed renamable $r1d, 0, 0, implicit-def $cc :: (volatile dereferenceable load (s64) from @ptr) BRC 14, 8, %bb.2, implicit killed $cc J %bb.1 bb.1: renamable $r1d = LARL @ptr MVGHI killed renamable $r1d, 0, 0 bb.2: Return ... # Load of an invariant location (GOT). Only one LGRL is needed. # CHECK-LABEL: fun7: # CHECK: lgrl %r1, ptr # CHECK-NOT: lgrl --- name: fun7 alignment: 16 tracksRegLiveness: true tracksDebugUserValues: true frameInfo: maxAlignment: 1 maxCallFrameSize: 0 fixedStack: - { id: 0, offset: -160, size: 8, alignment: 8 } machineFunctionInfo: {} body: | bb.0: successors: %bb.2(0x30000000), %bb.1(0x50000000) renamable $r1d = LGRL @ptr :: (load (s64) from got) CGHSI killed renamable $r1d, 0, 0, implicit-def $cc :: (volatile dereferenceable load (s64) from @ptr) BRC 14, 8, %bb.2, implicit killed $cc J %bb.1 bb.1: renamable $r1d = LGRL @ptr :: (load (s64) from got) MVGHI killed renamable $r1d, 0, 0 bb.2: Return ... # Load from constant pool. Only one LARL is needed. # CHECK-LABEL: fun8: # CHECK: larl %r1, .LCPI7_0 # CHECK-NOT: larl --- name: fun8 alignment: 16 tracksRegLiveness: true tracksDebugUserValues: true liveins: - { reg: '$f0s' } frameInfo: maxAlignment: 1 maxCallFrameSize: 0 fixedStack: - { id: 0, offset: -160, size: 8, alignment: 8 } constants: - id: 0 value: float 0x43E0000000000000 alignment: 4 machineFunctionInfo: {} body: | bb.0 (%ir-block.0): successors: %bb.1, %bb.2 liveins: $f0s renamable $r1d = LARL %const.0 renamable $f1s = LE killed renamable $r1d, 0, $noreg :: (load (s32) from constant-pool) nofpexcept CEBR renamable $f0s, renamable $f1s, implicit-def $cc, implicit $fpc BRC 15, 11, %bb.2, implicit killed $cc bb.1: liveins: $f0s J %bb.3 bb.2 (%ir-block.0): liveins: $f0s, $f1s renamable $r1d = LARL %const.0 renamable $f1s = LE killed renamable $r1d, 0, $noreg :: (load (s32) from constant-pool) bb.3 (%ir-block.0): liveins: $r2d Return ...