Skip to content

Commit b6a507c

Browse files
committed
[AArch64] Combine shift and truncate into deinterleave.
This is an alternative approach to #213252, from which I've taken some of the tests. Co-authored by Jacob Crawley
1 parent 801a015 commit b6a507c

2 files changed

Lines changed: 45 additions & 40 deletions

File tree

llvm/lib/Target/AArch64/AArch64ISelLowering.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26632,6 +26632,27 @@ static SDValue performUzpCombine(SDNode *N, SelectionDAG &DAG,
2663226632
}
2663326633
}
2663426634

26635+
// uzp1(nvcast(x >> k), nvcast(y >> k)) -> uzp2(nvcast(x), nvcast(y))
26636+
// where 'k' is 'sizeof(eltty(x))/2'.
26637+
if (SDValue PreCastOp0 = isNVCastToHalfWidthElements(Op0)) {
26638+
if (SDValue PreCastOp1 = isNVCastToHalfWidthElements(Op1)) {
26639+
if (PreCastOp0.getOpcode() == ISD::SRL &&
26640+
PreCastOp1.getOpcode() == ISD::SRL &&
26641+
PreCastOp0.getOperand(1) == PreCastOp1.getOperand(1)) {
26642+
ConstantSDNode *ShiftAmount =
26643+
isConstOrConstSplat(PreCastOp0.getOperand(1), /*AllowUndef=*/false,
26644+
/*AllowTruncate=*/true);
26645+
if (ShiftAmount &&
26646+
ShiftAmount->getAsZExtVal() == ResVT.getScalarSizeInBits())
26647+
return DAG.getNode(AArch64ISD::UZP2, DL, ResVT,
26648+
DAG.getNode(AArch64ISD::NVCAST, DL, ResVT,
26649+
PreCastOp0.getOperand(0)),
26650+
DAG.getNode(AArch64ISD::NVCAST, DL, ResVT,
26651+
PreCastOp1.getOperand(0)));
26652+
}
26653+
}
26654+
}
26655+
2663526656
// These optimizations only work on little endian.
2663626657
if (!DAG.getDataLayout().isLittleEndian())
2663726658
return SDValue();

llvm/test/CodeGen/AArch64/sve-shift-trunc-combine.ll

Lines changed: 24 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,19 @@
99
define void @lshr_trunc_i16_load_scalable(ptr %src, ptr %dst) #0 {
1010
; CHECK-LABEL: lshr_trunc_i16_load_scalable:
1111
; CHECK: // %bb.0:
12-
; CHECK-NEXT: ldr z0, [x0]
13-
; CHECK-NEXT: ldr z1, [x0, #1, mul vl]
14-
; CHECK-NEXT: lsr z1.h, z1.h, #8
15-
; CHECK-NEXT: lsr z0.h, z0.h, #8
16-
; CHECK-NEXT: uzp1 z0.b, z0.b, z1.b
12+
; CHECK-NEXT: ldr z0, [x0, #1, mul vl]
13+
; CHECK-NEXT: ldr z1, [x0]
14+
; CHECK-NEXT: uzp2 z0.b, z1.b, z0.b
1715
; CHECK-NEXT: str z0, [x1]
1816
; CHECK-NEXT: ret
1917
;
2018
; BE-LABEL: lshr_trunc_i16_load_scalable:
2119
; BE: // %bb.0:
2220
; BE-NEXT: ptrue p0.h
23-
; BE-NEXT: ld1h { z0.h }, p0/z, [x0]
24-
; BE-NEXT: ld1h { z1.h }, p0/z, [x0, #1, mul vl]
21+
; BE-NEXT: ld1h { z0.h }, p0/z, [x0, #1, mul vl]
22+
; BE-NEXT: ld1h { z1.h }, p0/z, [x0]
2523
; BE-NEXT: ptrue p0.b
26-
; BE-NEXT: lsr z1.h, z1.h, #8
27-
; BE-NEXT: lsr z0.h, z0.h, #8
28-
; BE-NEXT: uzp1 z0.b, z0.b, z1.b
24+
; BE-NEXT: uzp2 z0.b, z1.b, z0.b
2925
; BE-NEXT: st1b { z0.b }, p0, [x1]
3026
; BE-NEXT: ret
3127
%x = load <vscale x 16 x i16>, ptr %src, align 2
@@ -61,23 +57,19 @@ define void @lshr_trunc_i16_load_fixed_length(ptr %src, ptr %dst) #0 {
6157
define void @ashr_trunc_i16_load(ptr %src, ptr %dst)#0 {
6258
; CHECK-LABEL: ashr_trunc_i16_load:
6359
; CHECK: // %bb.0:
64-
; CHECK-NEXT: ldr z0, [x0]
65-
; CHECK-NEXT: ldr z1, [x0, #1, mul vl]
66-
; CHECK-NEXT: lsr z1.h, z1.h, #8
67-
; CHECK-NEXT: lsr z0.h, z0.h, #8
68-
; CHECK-NEXT: uzp1 z0.b, z0.b, z1.b
60+
; CHECK-NEXT: ldr z0, [x0, #1, mul vl]
61+
; CHECK-NEXT: ldr z1, [x0]
62+
; CHECK-NEXT: uzp2 z0.b, z1.b, z0.b
6963
; CHECK-NEXT: str z0, [x1]
7064
; CHECK-NEXT: ret
7165
;
7266
; BE-LABEL: ashr_trunc_i16_load:
7367
; BE: // %bb.0:
7468
; BE-NEXT: ptrue p0.h
75-
; BE-NEXT: ld1h { z0.h }, p0/z, [x0]
76-
; BE-NEXT: ld1h { z1.h }, p0/z, [x0, #1, mul vl]
69+
; BE-NEXT: ld1h { z0.h }, p0/z, [x0, #1, mul vl]
70+
; BE-NEXT: ld1h { z1.h }, p0/z, [x0]
7771
; BE-NEXT: ptrue p0.b
78-
; BE-NEXT: lsr z1.h, z1.h, #8
79-
; BE-NEXT: lsr z0.h, z0.h, #8
80-
; BE-NEXT: uzp1 z0.b, z0.b, z1.b
72+
; BE-NEXT: uzp2 z0.b, z1.b, z0.b
8173
; BE-NEXT: st1b { z0.b }, p0, [x1]
8274
; BE-NEXT: ret
8375
%x = load <vscale x 16 x i16>, ptr %src, align 2
@@ -90,23 +82,19 @@ define void @ashr_trunc_i16_load(ptr %src, ptr %dst)#0 {
9082
define void @lshr_trunc_i32_load(ptr %src, ptr %dst) #0 {
9183
; CHECK-LABEL: lshr_trunc_i32_load:
9284
; CHECK: // %bb.0:
93-
; CHECK-NEXT: ldr z0, [x0]
94-
; CHECK-NEXT: ldr z1, [x0, #1, mul vl]
95-
; CHECK-NEXT: lsr z1.s, z1.s, #16
96-
; CHECK-NEXT: lsr z0.s, z0.s, #16
97-
; CHECK-NEXT: uzp1 z0.h, z0.h, z1.h
85+
; CHECK-NEXT: ldr z0, [x0, #1, mul vl]
86+
; CHECK-NEXT: ldr z1, [x0]
87+
; CHECK-NEXT: uzp2 z0.h, z1.h, z0.h
9888
; CHECK-NEXT: str z0, [x1]
9989
; CHECK-NEXT: ret
10090
;
10191
; BE-LABEL: lshr_trunc_i32_load:
10292
; BE: // %bb.0:
10393
; BE-NEXT: ptrue p0.s
104-
; BE-NEXT: ld1w { z0.s }, p0/z, [x0]
105-
; BE-NEXT: ld1w { z1.s }, p0/z, [x0, #1, mul vl]
94+
; BE-NEXT: ld1w { z0.s }, p0/z, [x0, #1, mul vl]
95+
; BE-NEXT: ld1w { z1.s }, p0/z, [x0]
10696
; BE-NEXT: ptrue p0.h
107-
; BE-NEXT: lsr z1.s, z1.s, #16
108-
; BE-NEXT: lsr z0.s, z0.s, #16
109-
; BE-NEXT: uzp1 z0.h, z0.h, z1.h
97+
; BE-NEXT: uzp2 z0.h, z1.h, z0.h
11098
; BE-NEXT: st1h { z0.h }, p0, [x1]
11199
; BE-NEXT: ret
112100
%x = load <vscale x 8 x i32>, ptr %src, align 2
@@ -119,23 +107,19 @@ define void @lshr_trunc_i32_load(ptr %src, ptr %dst) #0 {
119107
define void @lshr_trunc_i64_load(ptr %src, ptr %dst) #0 {
120108
; CHECK-LABEL: lshr_trunc_i64_load:
121109
; CHECK: // %bb.0:
122-
; CHECK-NEXT: ldr z0, [x0]
123-
; CHECK-NEXT: ldr z1, [x0, #1, mul vl]
124-
; CHECK-NEXT: lsr z1.d, z1.d, #32
125-
; CHECK-NEXT: lsr z0.d, z0.d, #32
126-
; CHECK-NEXT: uzp1 z0.s, z0.s, z1.s
110+
; CHECK-NEXT: ldr z0, [x0, #1, mul vl]
111+
; CHECK-NEXT: ldr z1, [x0]
112+
; CHECK-NEXT: uzp2 z0.s, z1.s, z0.s
127113
; CHECK-NEXT: str z0, [x1]
128114
; CHECK-NEXT: ret
129115
;
130116
; BE-LABEL: lshr_trunc_i64_load:
131117
; BE: // %bb.0:
132118
; BE-NEXT: ptrue p0.d
133-
; BE-NEXT: ld1d { z0.d }, p0/z, [x0]
134-
; BE-NEXT: ld1d { z1.d }, p0/z, [x0, #1, mul vl]
119+
; BE-NEXT: ld1d { z0.d }, p0/z, [x0, #1, mul vl]
120+
; BE-NEXT: ld1d { z1.d }, p0/z, [x0]
135121
; BE-NEXT: ptrue p0.s
136-
; BE-NEXT: lsr z1.d, z1.d, #32
137-
; BE-NEXT: lsr z0.d, z0.d, #32
138-
; BE-NEXT: uzp1 z0.s, z0.s, z1.s
122+
; BE-NEXT: uzp2 z0.s, z1.s, z0.s
139123
; BE-NEXT: st1w { z0.s }, p0, [x1]
140124
; BE-NEXT: ret
141125
%x = load <vscale x 4 x i64>, ptr %src, align 2

0 commit comments

Comments
 (0)