int64_t StepNumerator = SimpleVID->StepNumerator;
unsigned StepDenominator = SimpleVID->StepDenominator;
int64_t Addend = SimpleVID->Addend;
+
+ assert(StepNumerator != 0 && "Invalid step");
+ bool Negate = false;
+ int64_t SplatStepVal = StepNumerator;
+ unsigned StepOpcode = ISD::MUL;
+ if (StepNumerator != 1) {
+ if (isPowerOf2_64(std::abs(StepNumerator))) {
+ Negate = StepNumerator < 0;
+ StepOpcode = ISD::SHL;
+ SplatStepVal = Log2_64(std::abs(StepNumerator));
+ }
+ }
+
// Only emit VIDs with suitably-small steps/addends. We use imm5 is a
// threshold since it's the immediate value many RVV instructions accept.
- if (isInt<5>(StepNumerator) && isPowerOf2_32(StepDenominator) &&
- isInt<5>(Addend)) {
+ // There is no vmul.vi instruction so ensure multiply constant can fit in
+ // a single addi instruction.
+ if (((StepOpcode == ISD::MUL && isInt<12>(SplatStepVal)) ||
+ (StepOpcode == ISD::SHL && isUInt<5>(SplatStepVal))) &&
+ isPowerOf2_32(StepDenominator) && isInt<5>(Addend)) {
SDValue VID = DAG.getNode(RISCVISD::VID_VL, DL, ContainerVT, Mask, VL);
// Convert right out of the scalable type so we can use standard ISD
// nodes for the rest of the computation. If we used scalable types with
// these, we'd lose the fixed-length vector info and generate worse
// vsetvli code.
VID = convertFromScalableVector(VT, VID, DAG, Subtarget);
- assert(StepNumerator != 0 && "Invalid step");
- bool Negate = false;
- if (StepNumerator != 1) {
- int64_t SplatStepVal = StepNumerator;
- unsigned Opcode = ISD::MUL;
- if (isPowerOf2_64(std::abs(StepNumerator))) {
- Negate = StepNumerator < 0;
- Opcode = ISD::SHL;
- SplatStepVal = Log2_64(std::abs(StepNumerator));
- }
+ if ((StepOpcode == ISD::MUL && SplatStepVal != 1) ||
+ (StepOpcode == ISD::SHL && SplatStepVal != 0)) {
SDValue SplatStep = DAG.getSplatVector(
VT, DL, DAG.getConstant(SplatStepVal, DL, XLenVT));
- VID = DAG.getNode(Opcode, DL, VT, VID, SplatStep);
+ VID = DAG.getNode(StepOpcode, DL, VT, VID, SplatStep);
}
if (StepDenominator != 1) {
SDValue SplatStep = DAG.getSplatVector(
store <8 x i8> <i8 -5, i8 -5, i8 -5, i8 -5, i8 -6, i8 -6, i8 -6, i8 -6>, <8 x i8>* %z0
ret void
}
+
+define void @buildvec_vid_mpy_imm_v8i16(<8 x i16>* %x) {
+; CHECK-LABEL: buildvec_vid_mpy_imm_v8i16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, mu
+; CHECK-NEXT: vid.v v8
+; CHECK-NEXT: li a1, 17
+; CHECK-NEXT: vmul.vx v8, v8, a1
+; CHECK-NEXT: vse16.v v8, (a0)
+; CHECK-NEXT: ret
+ store <8 x i16> <i16 0, i16 17, i16 34, i16 51, i16 68, i16 85, i16 102, i16 119>, <8 x i16>* %x
+ ret void
+}
+
+define void @buildvec_vid_shl_imm_v8i16(<8 x i16>* %x) {
+; CHECK-LABEL: buildvec_vid_shl_imm_v8i16:
+; CHECK: # %bb.0:
+; CHECK-NEXT: vsetivli zero, 8, e16, m1, ta, mu
+; CHECK-NEXT: vid.v v8
+; CHECK-NEXT: vsll.vi v8, v8, 9
+; CHECK-NEXT: vse16.v v8, (a0)
+; CHECK-NEXT: ret
+ store <8 x i16> <i16 0, i16 512, i16 1024, i16 1536, i16 2048, i16 2560, i16 3072, i16 3584>, <8 x i16>* %x
+ ret void
+}