diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -11204,8 +11204,54 @@ N0.getOperand(0)); } +// vadd (build_vector x), (build_vector c) +// -> build_vector (add x, c) +static SDValue transformSplatVectorToScalar(SDNode *N, SelectionDAG &DAG, + const RISCVSubtarget &Subtarget) { + SDValue N0 = N->getOperand(0); + SDValue N1 = N->getOperand(1); + APInt ShAmt; + if (N->getOpcode() == ISD::ADD && N0.getOpcode() == ISD::BUILD_VECTOR && + ISD::isConstantSplatVector(N1.getNode(), ShAmt) && N0.hasOneUse() && + N1.hasOneUse()) { + EVT VT0 = N0.getValueType(); + EVT VT1 = N1.getValueType(); + unsigned NumElts0 = VT0.getVectorNumElements(); + unsigned NumElts1 = VT1.getVectorNumElements(); + SDValue Base; + SDLoc DL(N); + bool AllSame = true; + for (unsigned i = 0; i != NumElts0; ++i) { + if (!N0.getOperand(i).isUndef()) { + Base = N0.getOperand(i); + break; + } + } + for (unsigned i = 0; i != NumElts0; ++i) { + if (N0.getOperand(i) != Base) { + AllSame = false; + break; + } + } + MVT XLenVT = Subtarget.getXLenVT(); + if (AllSame && NumElts0 == NumElts1 && Base.getValueType() == XLenVT) { + SDValue NAdd = DAG.getNode(ISD::ADD, DL, XLenVT, Base, N1.getOperand(0)); + SmallVector NOps; + for (unsigned i = 0; i != NumElts0; ++i) { + NOps.push_back(NAdd); + } + return DAG.getNode(ISD::BUILD_VECTOR, DL, VT0, NOps); + } + } + return SDValue(); +} + static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, const RISCVSubtarget &Subtarget) { + EVT VT = N->getValueType(0); + if (VT.isFixedLengthVector()) + return transformSplatVectorToScalar(N, DAG, Subtarget); + if (SDValue V = combineAddOfBooleanXor(N, DAG)) return V; if (SDValue V = transformAddImmMulImm(N, DAG, Subtarget)) diff --git a/llvm/test/CodeGen/RISCV/rvv/pr65068.ll b/llvm/test/CodeGen/RISCV/rvv/pr65068.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/pr65068.ll @@ -0,0 +1,16 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3 +; RUN: llc -mtriple=riscv64 -mattr=+v -riscv-v-vector-bits-min=128 -verify-machineinstrs < %s | FileCheck %s --check-prefixes=CHECK-RV64 + +define <4 x i64> @f_v4i64(<4 x i64> %x, i64 %y) { +; CHECK-RV64-LABEL: f_v4i64: +; CHECK-RV64: # %bb.0: +; CHECK-RV64-NEXT: addi a0, a0, 3 +; CHECK-RV64-NEXT: vsetivli zero, 4, e64, m2, ta, ma +; CHECK-RV64-NEXT: vmul.vx v8, v8, a0 +; CHECK-RV64-NEXT: ret + %1 = insertelement <4 x i64> poison, i64 %y, i32 0 + %2 = shufflevector <4 x i64> %1, <4 x i64> poison, <4 x i32> zeroinitializer + %3 = add <4 x i64> %2, + %4 = mul <4 x i64> %x, %3 + ret <4 x i64> %4 +}