1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 2
# RUN: llc -o - %s -mtriple=amdgcn-- -mcpu=fiji -verify-machineinstrs -run-pass=greedy,virtregrewriter | FileCheck %s
--- |
define amdgpu_kernel void @func0() #0 { ret void }
define amdgpu_kernel void @func1() #0 { ret void }
define amdgpu_kernel void @splitHoist() #0 { ret void }
attributes #0 = { "amdgpu-num-sgpr"="12" }
...
---
# Make sure we only get a single spill+reload even if liverange splitting
# created a sequence of multiple copy instructions.
name: func0
body: |
bb.0:
; CHECK-LABEL: name: func0
; CHECK: S_NOP 0, implicit-def renamable $sgpr0
; CHECK-NEXT: S_NOP 0, implicit-def renamable $sgpr3
; CHECK-NEXT: SI_SPILL_S128_SAVE renamable $sgpr0_sgpr1_sgpr2_sgpr3, %stack.0, implicit $exec, implicit $sp_reg :: (store (s128) into %stack.0, align 4, addrspace 5)
; CHECK-NEXT: S_NOP 0, implicit-def dead $sgpr0, implicit-def dead $sgpr1, implicit-def dead $sgpr2, implicit-def dead $sgpr3, implicit-def dead $sgpr4, implicit-def dead $sgpr5, implicit-def dead $sgpr6, implicit-def dead $sgpr7, implicit-def dead $sgpr8, implicit-def dead $sgpr9, implicit-def dead $sgpr10, implicit-def dead $sgpr11
; CHECK-NEXT: renamable $sgpr0_sgpr1_sgpr2_sgpr3 = SI_SPILL_S128_RESTORE %stack.0, implicit $exec, implicit $sp_reg :: (load (s128) from %stack.0, align 4, addrspace 5)
; CHECK-NEXT: S_NOP 0, implicit renamable $sgpr0
; CHECK-NEXT: S_NOP 0, implicit renamable $sgpr3
; CHECK-NEXT: S_NOP 0, implicit renamable $sgpr0
; CHECK-NEXT: S_NOP 0, implicit killed renamable $sgpr3
S_NOP 0, implicit-def undef %0.sub0 : sgpr_128
S_NOP 0, implicit-def %0.sub3 : sgpr_128
; Clobber registers
S_NOP 0, implicit-def dead $sgpr0, implicit-def dead $sgpr1, implicit-def dead $sgpr2, implicit-def dead $sgpr3, implicit-def dead $sgpr4, implicit-def dead $sgpr5, implicit-def dead $sgpr6, implicit-def dead $sgpr7, implicit-def dead $sgpr8, implicit-def dead $sgpr9, implicit-def dead $sgpr10, implicit-def dead $sgpr11
S_NOP 0, implicit %0.sub0
S_NOP 0, implicit %0.sub3
S_NOP 0, implicit %0.sub0
S_NOP 0, implicit %0.sub3
...
---
# LiveRange splitting should split this into 2 intervals with the second getting
# allocated to sgpr0_sgpr1 and the first to something else so we see two copies
# in between for the two subregisters that are alive.
name: func1
tracksRegLiveness: true
body: |
bb.0:
liveins: $sgpr0, $sgpr1, $sgpr2
; CHECK-LABEL: name: func1
; CHECK: liveins: $sgpr0, $sgpr1, $sgpr2
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: renamable $sgpr4 = COPY $sgpr0
; CHECK-NEXT: renamable $sgpr6 = COPY $sgpr2
; CHECK-NEXT: S_NOP 0, implicit-def dead $sgpr0, implicit-def dead $sgpr1
; CHECK-NEXT: S_NOP 0, implicit renamable $sgpr4
; CHECK-NEXT: S_NOP 0, implicit renamable $sgpr6
; CHECK-NEXT: renamable $sgpr0 = COPY killed renamable $sgpr4
; CHECK-NEXT: renamable $sgpr2 = COPY renamable $sgpr6
; CHECK-NEXT: S_NOP 0, implicit-def dead $sgpr4, implicit-def dead $sgpr5, implicit-def dead $sgpr6, implicit-def dead $sgpr7, implicit-def dead $sgpr8, implicit-def dead $sgpr9, implicit-def dead $sgpr10, implicit-def dead $sgpr11, implicit-def dead $sgpr12, implicit-def dead $sgpr13, implicit-def dead $sgpr14, implicit-def dead $sgpr15, implicit-def dead $vcc_lo, implicit-def dead $vcc_hi
; CHECK-NEXT: S_NOP 0, implicit renamable $sgpr0
; CHECK-NEXT: S_NOP 0, implicit killed renamable $sgpr2
undef %0.sub0 : sgpr_128 = COPY $sgpr0
%0.sub2 = COPY $sgpr2
S_NOP 0, implicit-def dead $sgpr0, implicit-def dead $sgpr1
S_NOP 0, implicit %0.sub0
S_NOP 0, implicit %0.sub2
; Clobber everything but sgpr0-sgpr3
S_NOP 0, implicit-def dead $sgpr4, implicit-def dead $sgpr5, implicit-def dead $sgpr6, implicit-def dead $sgpr7, implicit-def dead $sgpr8, implicit-def dead $sgpr9, implicit-def dead $sgpr10, implicit-def dead $sgpr11, implicit-def dead $sgpr12, implicit-def dead $sgpr13, implicit-def dead $sgpr14, implicit-def dead $sgpr15, implicit-def dead $vcc_lo, implicit-def dead $vcc_hi
S_NOP 0, implicit %0.sub0
S_NOP 0, implicit %0.sub2
...
---
# Check that copy hoisting out of loops works. This mainly should not crash the
# compiler when it hoists a subreg copy sequence.
name: splitHoist
tracksRegLiveness: true
body: |
; CHECK-LABEL: name: splitHoist
; CHECK: bb.0:
; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000)
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: S_NOP 0, implicit-def renamable $sgpr0
; CHECK-NEXT: S_NOP 0, implicit-def renamable $sgpr3
; CHECK-NEXT: SI_SPILL_S128_SAVE renamable $sgpr0_sgpr1_sgpr2_sgpr3, %stack.0, implicit $exec, implicit $sp_reg :: (store (s128) into %stack.0, align 4, addrspace 5)
; CHECK-NEXT: S_CBRANCH_VCCNZ %bb.1, implicit undef $vcc
; CHECK-NEXT: S_BRANCH %bb.2
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.1:
; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.3(0x40000000)
; CHECK-NEXT: liveins: $sgpr0_sgpr1_sgpr2_sgpr3:0x00000000000000C3
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: S_NOP 0, implicit renamable $sgpr0
; CHECK-NEXT: S_NOP 0, implicit-def dead $sgpr0, implicit-def dead $sgpr1, implicit-def dead $sgpr2, implicit-def dead $sgpr3, implicit-def dead $sgpr4, implicit-def dead $sgpr5, implicit-def dead $sgpr6, implicit-def dead $sgpr7, implicit-def dead $sgpr8, implicit-def dead $sgpr9, implicit-def dead $sgpr10, implicit-def dead $sgpr11
; CHECK-NEXT: renamable $sgpr0_sgpr1_sgpr2_sgpr3 = SI_SPILL_S128_RESTORE %stack.0, implicit $exec, implicit $sp_reg :: (load (s128) from %stack.0, align 4, addrspace 5)
; CHECK-NEXT: S_CBRANCH_VCCNZ %bb.1, implicit undef $vcc
; CHECK-NEXT: S_BRANCH %bb.3
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.2:
; CHECK-NEXT: successors: %bb.3(0x80000000)
; CHECK-NEXT: liveins: $sgpr0_sgpr1_sgpr2_sgpr3:0x00000000000000C3
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: S_NOP 0, implicit-def dead $sgpr0, implicit-def dead $sgpr1, implicit-def dead $sgpr2, implicit-def dead $sgpr3, implicit-def dead $sgpr4, implicit-def dead $sgpr5, implicit-def dead $sgpr6, implicit-def dead $sgpr7, implicit-def dead $sgpr8, implicit-def dead $sgpr9, implicit-def dead $sgpr10, implicit-def dead $sgpr11
; CHECK-NEXT: renamable $sgpr0_sgpr1_sgpr2_sgpr3 = SI_SPILL_S128_RESTORE %stack.0, implicit $exec, implicit $sp_reg :: (load (s128) from %stack.0, align 4, addrspace 5)
; CHECK-NEXT: S_BRANCH %bb.3
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.3:
; CHECK-NEXT: liveins: $sgpr0_sgpr1_sgpr2_sgpr3:0x00000000000000C3
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: S_NOP 0, implicit renamable $sgpr0
; CHECK-NEXT: S_NOP 0, implicit renamable $sgpr3
; CHECK-NEXT: S_NOP 0, implicit renamable $sgpr0
; CHECK-NEXT: S_NOP 0, implicit killed renamable $sgpr3
bb.0:
successors: %bb.1, %bb.2
S_NOP 0, implicit-def undef %0.sub0 : sgpr_128
S_NOP 0, implicit-def %0.sub3 : sgpr_128
S_CBRANCH_VCCNZ %bb.1, implicit undef $vcc
S_BRANCH %bb.2
bb.1:
successors: %bb.1, %bb.3
S_NOP 0, implicit %0.sub0
; Clobber registers
S_NOP 0, implicit-def dead $sgpr0, implicit-def dead $sgpr1, implicit-def dead $sgpr2, implicit-def dead $sgpr3, implicit-def dead $sgpr4, implicit-def dead $sgpr5, implicit-def dead $sgpr6, implicit-def dead $sgpr7, implicit-def dead $sgpr8, implicit-def dead $sgpr9, implicit-def dead $sgpr10, implicit-def dead $sgpr11
S_CBRANCH_VCCNZ %bb.1, implicit undef $vcc
S_BRANCH %bb.3
bb.2:
successors: %bb.3
; Clobber registers
S_NOP 0, implicit-def dead $sgpr0, implicit-def dead $sgpr1, implicit-def dead $sgpr2, implicit-def dead $sgpr3, implicit-def dead $sgpr4, implicit-def dead $sgpr5, implicit-def dead $sgpr6, implicit-def dead $sgpr7, implicit-def dead $sgpr8, implicit-def dead $sgpr9, implicit-def dead $sgpr10, implicit-def dead $sgpr11
S_BRANCH %bb.3
bb.3:
S_NOP 0, implicit %0.sub0
S_NOP 0, implicit %0.sub3
S_NOP 0, implicit %0.sub0
S_NOP 0, implicit %0.sub3
...
|