Files
clang-p2996/llvm/test/CodeGen/AArch64/spill-fold.mir
john-brawn-arm a574ef6176 [AArch64] Fix incorrect big-endian spill in foldMemoryOperandImpl (#65601)
When an sreg sub-register of a q register was spilled,
AArch64InstrInfo::foldMemoryOperandImpl would emit a spill of a d
register, which gives the wrong result when the target is big-endian as
the following q register fill will put the value in the top half.

Fix this by greatly simplifying the existing code for widening the spill
to only handle wzr to xzr widening, as the default result we get if the
function returns nullptr is already that a widened spill will be
emitted.
2023-10-12 16:10:28 +01:00

136 lines
11 KiB
YAML

# RUN: llc -mtriple=aarch64-none-linux-gnu -run-pass greedy -verify-machineinstrs -o - %s | FileCheck %s
# RUN: llc -mtriple=aarch64_be-none-linux-gnu -run-pass greedy -verify-machineinstrs -o - %s | FileCheck %s
--- |
define i64 @test_subreg_spill_fold() { ret i64 0 }
define i64 @test_subreg_spill_fold2() { ret i64 0 }
define i64 @test_subreg_spill_fold3() { ret i64 0 }
define <4 x float> @test_subreg_spill_fold4() { ret <4 x float> undef }
define i64 @test_subreg_fill_fold() { ret i64 0 }
define double @test_subreg_fill_fold2() { ret double 0.0 }
define <4 x float> @test_subreg_fill_fold3() { ret <4 x float> undef }
define i64 @test_nzcv_spill_fold() { ret i64 0 }
...
---
# CHECK-LABEL: name: test_subreg_spill_fold
# Ensure that the spilled subreg COPY is eliminated and folded into the spill store.
name: test_subreg_spill_fold
registers:
- { id: 0, class: gpr64 }
body: |
bb.0:
; CHECK: STRXui $xzr, %stack.0, 0 :: (store (s64) into %stack.0)
undef %0.sub_32 = COPY $wzr
INLINEASM &nop, 1, 12, implicit-def dead $x0, 12, implicit-def dead $x1, 12, implicit-def dead $x2, 12, implicit-def dead $x3, 12, implicit-def dead $x4, 12, implicit-def dead $x5, 12, implicit-def dead $x6, 12, implicit-def dead $x7, 12, implicit-def dead $x8, 12, implicit-def dead $x9, 12, implicit-def dead $x10, 12, implicit-def dead $x11, 12, implicit-def dead $x12, 12, implicit-def dead $x13, 12, implicit-def dead $x14, 12, implicit-def dead $x15, 12, implicit-def dead $x16, 12, implicit-def dead $x17, 12, implicit-def dead $x18, 12, implicit-def dead $x19, 12, implicit-def dead $x20, 12, implicit-def dead $x21, 12, implicit-def dead $x22, 12, implicit-def dead $x23, 12, implicit-def dead $x24, 12, implicit-def dead $x25, 12, implicit-def dead $x26, 12, implicit-def dead $x27, 12, implicit-def dead $x28, 12, implicit-def dead $fp, 12, implicit-def dead $lr, 12, implicit-def $sp
$x0 = COPY %0
RET_ReallyLR implicit $x0
...
---
# CHECK-LABEL: name: test_subreg_spill_fold2
# Similar to test_subreg_spill_fold, but with a %0 register class not containing %WZR.
name: test_subreg_spill_fold2
registers:
- { id: 0, class: gpr64sp }
body: |
bb.0:
; CHECK: STRXui $xzr, %stack.0, 0 :: (store (s64) into %stack.0)
undef %0.sub_32 = COPY $wzr
INLINEASM &nop, 1, 12, implicit-def dead $x0, 12, implicit-def dead $x1, 12, implicit-def dead $x2, 12, implicit-def dead $x3, 12, implicit-def dead $x4, 12, implicit-def dead $x5, 12, implicit-def dead $x6, 12, implicit-def dead $x7, 12, implicit-def dead $x8, 12, implicit-def dead $x9, 12, implicit-def dead $x10, 12, implicit-def dead $x11, 12, implicit-def dead $x12, 12, implicit-def dead $x13, 12, implicit-def dead $x14, 12, implicit-def dead $x15, 12, implicit-def dead $x16, 12, implicit-def dead $x17, 12, implicit-def dead $x18, 12, implicit-def dead $x19, 12, implicit-def dead $x20, 12, implicit-def dead $x21, 12, implicit-def dead $x22, 12, implicit-def dead $x23, 12, implicit-def dead $x24, 12, implicit-def dead $x25, 12, implicit-def dead $x26, 12, implicit-def dead $x27, 12, implicit-def dead $x28, 12, implicit-def dead $fp, 12, implicit-def dead $lr, 12, implicit-def $sp
$x0 = ADDXri %0, 1, 0
RET_ReallyLR implicit $x0
...
---
# CHECK-LABEL: name: test_subreg_spill_fold3
# Similar to test_subreg_spill_fold, but with a cross register class copy.
name: test_subreg_spill_fold3
registers:
- { id: 0, class: fpr64 }
body: |
bb.0:
; CHECK: STRXui $xzr, %stack.0, 0 :: (store (s64) into %stack.0)
undef %0.ssub = COPY $wzr
INLINEASM &nop, 1, 12, implicit-def dead $d0, 12, implicit-def dead $d1, 12, implicit-def dead $d2, 12, implicit-def dead $d3, 12, implicit-def dead $d4, 12, implicit-def dead $d5, 12, implicit-def dead $d6, 12, implicit-def dead $d7, 12, implicit-def dead $d8, 12, implicit-def dead $d9, 12, implicit-def dead $d10, 12, implicit-def dead $d11, 12, implicit-def dead $d12, 12, implicit-def dead $d13, 12, implicit-def dead $d14, 12, implicit-def dead $d15, 12, implicit-def dead $d16, 12, implicit-def dead $d17, 12, implicit-def dead $d18, 12, implicit-def dead $d19, 12, implicit-def dead $d20, 12, implicit-def dead $d21, 12, implicit-def dead $d22, 12, implicit-def dead $d23, 12, implicit-def dead $d24, 12, implicit-def dead $d25, 12, implicit-def dead $d26, 12, implicit-def dead $d27, 12, implicit-def dead $d28, 12, implicit-def dead $d29, 12, implicit-def dead $d30, 12, implicit-def $d31
$x0 = COPY %0
RET_ReallyLR implicit $x0
...
---
# CHECK-LABEL: name: test_subreg_spill_fold4
# A spilled write to a 128-bit register needs a 128-bit store
name: test_subreg_spill_fold4
registers:
- { id: 0, class: fpr128 }
body: |
bb.0:
; CHECK: undef %1.ssub:fpr128 = COPY $wzr
; CHECK-NEXT: STRQui %1, %stack.0, 0 :: (store (s128) into %stack.0)
undef %0.ssub:fpr128 = COPY $wzr
INLINEASM &nop, 1, 12, implicit-def dead $d0, 12, implicit-def dead $d1, 12, implicit-def dead $d2, 12, implicit-def dead $d3, 12, implicit-def dead $d4, 12, implicit-def dead $d5, 12, implicit-def dead $d6, 12, implicit-def dead $d7, 12, implicit-def dead $d8, 12, implicit-def dead $d9, 12, implicit-def dead $d10, 12, implicit-def dead $d11, 12, implicit-def dead $d12, 12, implicit-def dead $d13, 12, implicit-def dead $d14, 12, implicit-def dead $d15, 12, implicit-def dead $d16, 12, implicit-def dead $d17, 12, implicit-def dead $d18, 12, implicit-def dead $d19, 12, implicit-def dead $d20, 12, implicit-def dead $d21, 12, implicit-def dead $d22, 12, implicit-def dead $d23, 12, implicit-def dead $d24, 12, implicit-def dead $d25, 12, implicit-def dead $d26, 12, implicit-def dead $d27, 12, implicit-def dead $d28, 12, implicit-def dead $d29, 12, implicit-def dead $d30, 12, implicit-def $d31
$q0 = COPY %0
RET_ReallyLR implicit $q0
...
---
# CHECK-LABEL: name: test_subreg_fill_fold
# Ensure that the filled COPY is eliminated and folded into the fill load.
name: test_subreg_fill_fold
registers:
- { id: 0, class: gpr32 }
- { id: 1, class: gpr64 }
body: |
bb.0:
%0 = COPY $wzr
INLINEASM &nop, 1, 12, implicit-def dead $x0, 12, implicit-def dead $x1, 12, implicit-def dead $x2, 12, implicit-def dead $x3, 12, implicit-def dead $x4, 12, implicit-def dead $x5, 12, implicit-def dead $x6, 12, implicit-def dead $x7, 12, implicit-def dead $x8, 12, implicit-def dead $x9, 12, implicit-def dead $x10, 12, implicit-def dead $x11, 12, implicit-def dead $x12, 12, implicit-def dead $x13, 12, implicit-def dead $x14, 12, implicit-def dead $x15, 12, implicit-def dead $x16, 12, implicit-def dead $x17, 12, implicit-def dead $x18, 12, implicit-def dead $x19, 12, implicit-def dead $x20, 12, implicit-def dead $x21, 12, implicit-def dead $x22, 12, implicit-def dead $x23, 12, implicit-def dead $x24, 12, implicit-def dead $x25, 12, implicit-def dead $x26, 12, implicit-def dead $x27, 12, implicit-def dead $x28, 12, implicit-def dead $fp, 12, implicit-def dead $lr, 12, implicit-def $sp
; CHECK: undef %1.sub_32:gpr64 = LDRWui %stack.0, 0 :: (load (s32) from %stack.0)
undef %1.sub_32 = COPY %0
$x0 = COPY %1
RET_ReallyLR implicit $x0
...
---
# CHECK-LABEL: name: test_subreg_fill_fold2
# Similar to test_subreg_fill_fold, but with a cross-class copy.
name: test_subreg_fill_fold2
registers:
- { id: 0, class: gpr32 }
- { id: 1, class: fpr64 }
body: |
bb.0:
%0 = COPY $wzr
INLINEASM &nop, 1, 12, implicit-def dead $x0, 12, implicit-def dead $x1, 12, implicit-def dead $x2, 12, implicit-def dead $x3, 12, implicit-def dead $x4, 12, implicit-def dead $x5, 12, implicit-def dead $x6, 12, implicit-def dead $x7, 12, implicit-def dead $x8, 12, implicit-def dead $x9, 12, implicit-def dead $x10, 12, implicit-def dead $x11, 12, implicit-def dead $x12, 12, implicit-def dead $x13, 12, implicit-def dead $x14, 12, implicit-def dead $x15, 12, implicit-def dead $x16, 12, implicit-def dead $x17, 12, implicit-def dead $x18, 12, implicit-def dead $x19, 12, implicit-def dead $x20, 12, implicit-def dead $x21, 12, implicit-def dead $x22, 12, implicit-def dead $x23, 12, implicit-def dead $x24, 12, implicit-def dead $x25, 12, implicit-def dead $x26, 12, implicit-def dead $x27, 12, implicit-def dead $x28, 12, implicit-def dead $fp, 12, implicit-def dead $lr, 12, implicit-def $sp
; CHECK: undef %1.ssub:fpr64 = LDRSui %stack.0, 0 :: (load (s32) from %stack.0)
undef %1.ssub = COPY %0
$d0 = COPY %1
RET_ReallyLR implicit $d0
...
---
# CHECK-LABEL: name: test_subreg_fill_fold3
# A filled copy from a sub-register should load the whole register
name: test_subreg_fill_fold3
tracksRegLiveness: true
registers:
- { id: 0, class: fpr128 }
liveins:
- { reg: '$q0' }
body: |
bb.0:
liveins: $q0
%0 = COPY $q0
INLINEASM &nop, 1, 12, implicit-def dead $d0, 12, implicit-def dead $d1, 12, implicit-def dead $d2, 12, implicit-def dead $d3, 12, implicit-def dead $d4, 12, implicit-def dead $d5, 12, implicit-def dead $d6, 12, implicit-def dead $d7, 12, implicit-def dead $d8, 12, implicit-def dead $d9, 12, implicit-def dead $d10, 12, implicit-def dead $d11, 12, implicit-def dead $d12, 12, implicit-def dead $d13, 12, implicit-def dead $d14, 12, implicit-def dead $d15, 12, implicit-def dead $d16, 12, implicit-def dead $d17, 12, implicit-def dead $d18, 12, implicit-def dead $d19, 12, implicit-def dead $d20, 12, implicit-def dead $d21, 12, implicit-def dead $d22, 12, implicit-def dead $d23, 12, implicit-def dead $d24, 12, implicit-def dead $d25, 12, implicit-def dead $d26, 12, implicit-def dead $d27, 12, implicit-def dead $d28, 12, implicit-def dead $d29, 12, implicit-def dead $d30, 12, implicit-def $d31
; CHECK: %1:fpr128 = LDRQui %stack.0, 0 :: (load (s128) from %stack.0)
; CHECK-NEXT: $s0 = COPY %1.ssub
$s0 = COPY %0.ssub
RET_ReallyLR implicit $s0
...
---
# CHECK-LABEL: name: test_nzcv_spill_fold
# Ensure that nzcv COPY cannot be folded.
name: test_nzcv_spill_fold
registers:
- { id: 0, class: gpr64 }
body: |
bb.0:
; CHECK: %1:gpr64 = COPY $nzcv
; CHECK: STRXui %1, %stack.0, 0 :: (store (s64) into %stack.0)
%0 = COPY $nzcv
INLINEASM &nop, 1, 12, implicit-def dead $x0, 12, implicit-def dead $x1, 12, implicit-def dead $x2, 12, implicit-def dead $x3, 12, implicit-def dead $x4, 12, implicit-def dead $x5, 12, implicit-def dead $x6, 12, implicit-def dead $x7, 12, implicit-def dead $x8, 12, implicit-def dead $x9, 12, implicit-def dead $x10, 12, implicit-def dead $x11, 12, implicit-def dead $x12, 12, implicit-def dead $x13, 12, implicit-def dead $x14, 12, implicit-def dead $x15, 12, implicit-def dead $x16, 12, implicit-def dead $x17, 12, implicit-def dead $x18, 12, implicit-def dead $x19, 12, implicit-def dead $x20, 12, implicit-def dead $x21, 12, implicit-def dead $x22, 12, implicit-def dead $x23, 12, implicit-def dead $x24, 12, implicit-def dead $x25, 12, implicit-def dead $x26, 12, implicit-def dead $x27, 12, implicit-def dead $x28, 12, implicit-def dead $fp, 12, implicit-def dead $lr, 12, implicit-def $sp
$x0 = COPY %0
RET_ReallyLR implicit $x0
...