Skip to content

Commit acdbd34

Browse files
committed
[RISCV] Loosen some restrictions on lowering constant BUILD_VECTORs using vid.v.
The immediate size check on StepNumerator did not take into account that vmul.vi does not exist. It also did not account for power of 2 constants that can be done with vshl.vi. This patch fixes this by moving the conversion from mul to shift further up. Then we can consider the immediates separately for MUL vs SHL. For MUL I've allowed simm12 which requires a single addi before a vmul.vx. For SHL I've allowed any uimm5 which works with vshl.vi. We could relax these further in the future. This is a starting point that allows us to emit the same number of instructions we were already using for smaller numerators. Reviewed By: frasercrmck Differential Revision: https://reviews.llvm.org/D115081
1 parent 744aa09 commit acdbd34

File tree

2 files changed

+46
-13
lines changed

2 files changed

+46
-13
lines changed

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1960,29 +1960,37 @@ static SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG,
19601960
int64_t StepNumerator = SimpleVID->StepNumerator;
19611961
unsigned StepDenominator = SimpleVID->StepDenominator;
19621962
int64_t Addend = SimpleVID->Addend;
1963+
1964+
assert(StepNumerator != 0 && "Invalid step");
1965+
bool Negate = false;
1966+
int64_t SplatStepVal = StepNumerator;
1967+
unsigned StepOpcode = ISD::MUL;
1968+
if (StepNumerator != 1) {
1969+
if (isPowerOf2_64(std::abs(StepNumerator))) {
1970+
Negate = StepNumerator < 0;
1971+
StepOpcode = ISD::SHL;
1972+
SplatStepVal = Log2_64(std::abs(StepNumerator));
1973+
}
1974+
}
1975+
19631976
// Only emit VIDs with suitably-small steps/addends. We use imm5 is a
19641977
// threshold since it's the immediate value many RVV instructions accept.
1965-
if (isInt<5>(StepNumerator) && isPowerOf2_32(StepDenominator) &&
1966-
isInt<5>(Addend)) {
1978+
// There is no vmul.vi instruction so ensure multiply constant can fit in
1979+
// a single addi instruction.
1980+
if (((StepOpcode == ISD::MUL && isInt<12>(SplatStepVal)) ||
1981+
(StepOpcode == ISD::SHL && isUInt<5>(SplatStepVal))) &&
1982+
isPowerOf2_32(StepDenominator) && isInt<5>(Addend)) {
19671983
SDValue VID = DAG.getNode(RISCVISD::VID_VL, DL, ContainerVT, Mask, VL);
19681984
// Convert right out of the scalable type so we can use standard ISD
19691985
// nodes for the rest of the computation. If we used scalable types with
19701986
// these, we'd lose the fixed-length vector info and generate worse
19711987
// vsetvli code.
19721988
VID = convertFromScalableVector(VT, VID, DAG, Subtarget);
1973-
assert(StepNumerator != 0 && "Invalid step");
1974-
bool Negate = false;
1975-
if (StepNumerator != 1) {
1976-
int64_t SplatStepVal = StepNumerator;
1977-
unsigned Opcode = ISD::MUL;
1978-
if (isPowerOf2_64(std::abs(StepNumerator))) {
1979-
Negate = StepNumerator < 0;
1980-
Opcode = ISD::SHL;
1981-
SplatStepVal = Log2_64(std::abs(StepNumerator));
1982-
}
1989+
if ((StepOpcode == ISD::MUL && SplatStepVal != 1) ||
1990+
(StepOpcode == ISD::SHL && SplatStepVal != 0)) {
19831991
SDValue SplatStep = DAG.getSplatVector(
19841992
VT, DL, DAG.getConstant(SplatStepVal, DL, XLenVT));
1985-
VID = DAG.getNode(Opcode, DL, VT, VID, SplatStep);
1993+
VID = DAG.getNode(StepOpcode, DL, VT, VID, SplatStep);
19861994
}
19871995
if (StepDenominator != 1) {
19881996
SDValue SplatStep = DAG.getSplatVector(

llvm/test/CodeGen/RISCV/rvv/fixed-vectors-int-buildvec.ll

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,3 +638,28 @@ define void @buildvec_vid_stepn1o4_addn5_v8i8(<8 x i8>* %z0) {
638638
store <8 x i8> <i8 -5, i8 -5, i8 -5, i8 -5, i8 -6, i8 -6, i8 -6, i8 -6>, <8 x i8>* %z0
639639
ret void
640640
}
641+
642+
define void @buildvec_vid_mpy_imm_v8i16(<8 x i16>* %x) {
643+
; CHECK-LABEL: buildvec_vid_mpy_imm_v8i16:
644+
; CHECK: # %bb.0:
645+
; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, mu
646+
; CHECK-NEXT: vid.v v8
647+
; CHECK-NEXT: li a1, 17
648+
; CHECK-NEXT: vmul.vx v8, v8, a1
649+
; CHECK-NEXT: vse16.v v8, (a0)
650+
; CHECK-NEXT: ret
651+
store <8 x i16> <i16 0, i16 17, i16 34, i16 51, i16 68, i16 85, i16 102, i16 119>, <8 x i16>* %x
652+
ret void
653+
}
654+
655+
define void @buildvec_vid_shl_imm_v8i16(<8 x i16>* %x) {
656+
; CHECK-LABEL: buildvec_vid_shl_imm_v8i16:
657+
; CHECK: # %bb.0:
658+
; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, mu
659+
; CHECK-NEXT: vid.v v8
660+
; CHECK-NEXT: vsll.vi v8, v8, 9
661+
; CHECK-NEXT: vse16.v v8, (a0)
662+
; CHECK-NEXT: ret
663+
store <8 x i16> <i16 0, i16 512, i16 1024, i16 1536, i16 2048, i16 2560, i16 3072, i16 3584>, <8 x i16>* %x
664+
ret void
665+
}

0 commit comments

Comments
 (0)