Skip to content

Commit a9af66a

Browse files
committed
[RISCV] Lower (vector_interleave X, undef) to (vzext_vl X). (#87283)
If the odd vector is undef or poison, the widening add and multiply trick doesn't work unless we freeze the odd vector. Unfortunately, freezing doesn't work when the operand is provably undef/poison. MIR doesn't have a representation for freeze so it just becomes a COPY from IMPLICIT_DEF which freely propagates undef to each operand independently. To work around this, check for undef explicitly and lower to a VZEXT_VL of the even vector. This produces better code than we'd get from a freeze anyway. I've left a FIXME for adding a freeze. I'll do that as a separate patch as it affects other tests and doesn't help with the new test.
1 parent 8c1dc5d commit a9af66a

File tree

2 files changed

+16
-14
lines changed

2 files changed

+16
-14
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4624,7 +4624,13 @@ static SDValue getWideningInterleave(SDValue EvenV, SDValue OddV,
46244624
SDValue Passthru = DAG.getUNDEF(WideContainerVT);
46254625

46264626
SDValue Interleaved;
4627-
if (Subtarget.hasStdExtZvbb()) {
4627+
if (OddV.isUndef()) {
4628+
// If OddV is undef, this is a zero extend.
4629+
// FIXME: Not only does this optimize the code, it fixes some correctness
4630+
// issues because MIR does not have freeze.
4631+
Interleaved =
4632+
DAG.getNode(RISCVISD::VZEXT_VL, DL, WideContainerVT, EvenV, Mask, VL);
4633+
} else if (Subtarget.hasStdExtZvbb()) {
46284634
// Interleaved = (OddV << VecVT.getScalarSizeInBits()) + EvenV.
46294635
SDValue OffsetVec =
46304636
DAG.getSplatVector(VecContainerVT, DL,
@@ -4635,6 +4641,9 @@ static SDValue getWideningInterleave(SDValue EvenV, SDValue OddV,
46354641
Interleaved = DAG.getNode(RISCVISD::VWADDU_W_VL, DL, WideContainerVT,
46364642
Interleaved, EvenV, Passthru, Mask, VL);
46374643
} else {
4644+
// FIXME: We should freeze the odd vector here. We already handled the case
4645+
// of provably undef/poison above.
4646+
46384647
// Widen EvenV and OddV with 0s and add one copy of OddV to EvenV with
46394648
// vwaddu.vv
46404649
Interleaved = DAG.getNode(RISCVISD::VWADDU_VL, DL, WideContainerVT, EvenV,

llvm/test/CodeGen/RISCV/rvv/vector-interleave.ll

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -656,26 +656,19 @@ define <vscale x 16 x double> @vector_interleave_nxv16f64_nxv8f64(<vscale x 8 x
656656
ret <vscale x 16 x double> %res
657657
}
658658

659-
; FIXME: The last operand to the vwaddu.vv and vwmaccu.vx are both undef. They
660-
; need to be the same register with the same contents. Otherwise, the even
661-
; elements will not contain just the values from %a.
662659
define <vscale x 8 x i32> @vector_interleave_nxv8i32_nxv4i32_poison(<vscale x 4 x i32> %a) {
663660
; CHECK-LABEL: vector_interleave_nxv8i32_nxv4i32_poison:
664661
; CHECK: # %bb.0:
665-
; CHECK-NEXT: vsetvli a0, zero, e32, m2, ta, ma
666-
; CHECK-NEXT: vwaddu.vv v12, v8, v10
667-
; CHECK-NEXT: li a0, -1
668-
; CHECK-NEXT: vwmaccu.vx v12, a0, v8
669-
; CHECK-NEXT: vmv4r.v v8, v12
662+
; CHECK-NEXT: vsetvli a0, zero, e64, m4, ta, ma
663+
; CHECK-NEXT: vzext.vf2 v12, v8
664+
; CHECK-NEXT: vmv.v.v v8, v12
670665
; CHECK-NEXT: ret
671666
;
672667
; ZVBB-LABEL: vector_interleave_nxv8i32_nxv4i32_poison:
673668
; ZVBB: # %bb.0:
674-
; ZVBB-NEXT: li a0, 32
675-
; ZVBB-NEXT: vsetvli a1, zero, e32, m2, ta, ma
676-
; ZVBB-NEXT: vwsll.vx v12, v10, a0
677-
; ZVBB-NEXT: vwaddu.wv v12, v12, v8
678-
; ZVBB-NEXT: vmv4r.v v8, v12
669+
; ZVBB-NEXT: vsetvli a0, zero, e64, m4, ta, ma
670+
; ZVBB-NEXT: vzext.vf2 v12, v8
671+
; ZVBB-NEXT: vmv.v.v v8, v12
679672
; ZVBB-NEXT: ret
680673
%res = call <vscale x 8 x i32> @llvm.experimental.vector.interleave2.nxv8i32(<vscale x 4 x i32> %a, <vscale x 4 x i32> poison)
681674
ret <vscale x 8 x i32> %res

0 commit comments

Comments
 (0)