diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.h @@ -50,6 +50,8 @@ bool SelectSLLIUW(SDValue N, SDValue &RS1, SDValue &Shamt); bool SelectSLOIW(SDValue N, SDValue &RS1, SDValue &Shamt); bool SelectSROIW(SDValue N, SDValue &RS1, SDValue &Shamt); + bool SelectVSplat(SDValue N, SDValue &SplatVal); + bool SelectVSplat_simm5(SDValue N, SDValue &SplatVal); // Include the pieces autogenerated from the target description. #include "RISCVGenDAGISel.inc" diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -367,6 +367,35 @@ return true; } +bool RISCVDAGToDAGISel::SelectVSplat(SDValue N, SDValue &SplatVal) { + if (N.getOpcode() != ISD::SPLAT_VECTOR && + N.getOpcode() != RISCVISD::SPLAT_VECTOR_I64) + return false; + SplatVal = N.getOperand(0); + return true; +} + +bool RISCVDAGToDAGISel::SelectVSplat_simm5(SDValue N, SDValue &SplatVal) { + if ((N.getOpcode() != ISD::SPLAT_VECTOR && + N.getOpcode() != RISCVISD::SPLAT_VECTOR_I64) || + !isa(N.getOperand(0))) + return false; + + int64_t SplatImm = cast(N.getOperand(0))->getSExtValue(); + + // TODO: First truncate the constant to the vector element type since the + // bits will be implicitly truncated anyway. This would catch cases where the + // immediate was zero-extended instead of sign-extended: we would still want + // to match (i8 -1) -> (XLenVT 255) as a simm5, for example + if (!isInt<5>(SplatImm)) + return false; + + SplatVal = + CurDAG->getTargetConstant(SplatImm, SDLoc(N), Subtarget->getXLenVT()); + + return true; +} + // Merge an ADDI into the offset of a load/store instruction where possible. // (load (addi base, off1), off2) -> (load base, off1+off2) // (store val, (addi base, off1), off2) -> (store val, base, off1+off2) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -78,6 +78,9 @@ GORCI, GORCIW, // Splats an i64 scalar to a vector type (with element type i64) where the + // scalar is a sign-extended i32. + SPLAT_VECTOR_I64, + // Splats an i64 scalar to a vector type (with element type i64) where the // scalar is split into two i32 operands: low and high halves SPLAT_VECTOR_I64_PAIR, }; 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 @@ -1029,18 +1029,26 @@ // Lower a vXi64 = SPLAT_VECTOR i64 on RV32 to SPLAT_VECTOR_I64_PAIR with two // separated i32 lo/hi operands +// FIXME: We could also catch sign-extended i32 values and lower them to +// SPLAT_VECTOR_I64 SDValue RISCVTargetLowering::lowerSPLATVECTOR(SDValue Op, SelectionDAG &DAG) const { SDLoc DL(Op); EVT VecVT = Op.getValueType(); assert(!Subtarget.is64Bit() && VecVT.getVectorElementType() == MVT::i64 && "Unexpected SPLAT_VECTOR lowering"); + SDValue SplatVal = Op.getOperand(0); + if (auto *CVal = dyn_cast(SplatVal)) { + if (isInt<32>(CVal->getSExtValue())) + return DAG.getNode(RISCVISD::SPLAT_VECTOR_I64, DL, VecVT, + DAG.getConstant(CVal->getSExtValue(), DL, MVT::i32)); + } SDValue One = DAG.getConstant(1, DL, MVT::i32); SDValue Zero = DAG.getConstant(0, DL, MVT::i32); return DAG.getNode( RISCVISD::SPLAT_VECTOR_I64_PAIR, DL, VecVT, - DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, Op.getOperand(0), Zero), - DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, Op.getOperand(0), One)); + DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, SplatVal, Zero), + DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, SplatVal, One)); } SDValue RISCVTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, @@ -3357,6 +3365,7 @@ NODE_NAME_CASE(GREVIW) NODE_NAME_CASE(GORCI) NODE_NAME_CASE(GORCIW) + NODE_NAME_CASE(SPLAT_VECTOR_I64) NODE_NAME_CASE(SPLAT_VECTOR_I64_PAIR) } // clang-format on diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td @@ -621,12 +621,21 @@ // Helpers to define the SDNode patterns. //===----------------------------------------------------------------------===// +def SDTSplatI64 : SDTypeProfile<1, 1, [ + SDTCVecEltisVT<0, i64>, SDTCisVT<1, i32> +]>; + def SDTSplatPairI64 : SDTypeProfile<1, 2, [ SDTCVecEltisVT<0, i64>, SDTCisVT<1, i32>, SDTCisSameAs<1, 2> ]>; +def rv32_splat_i64 : SDNode<"RISCVISD::SPLAT_VECTOR_I64", SDTSplatI64>; def rv32_splat_i64_pair : SDNode<"RISCVISD::SPLAT_VECTOR_I64_PAIR", SDTSplatPairI64>; +let Complexity = 1 in +def SplatPat : ComplexPattern; +def SplatPat_simm5 : ComplexPattern; + multiclass VPatUSLoadStoreSDNode : Pat<(result_type (vop (vop_type vop_reg_class:$rs1), - (vop_type (splat_vector xop_kind:$rs2)))), + (vop_type (SplatPatKind xop_kind:$rs2)))), (!cast(instruction_name#_#suffix#_# vlmul.MX) vop_reg_class:$rs1, xop_kind:$rs2, @@ -696,10 +706,13 @@ vti.LMul, vti.RegClass, vti.RegClass>; def : VPatBinarySDNode_XI; + vti.LMul, vti.RegClass, vti.RegClass, + SplatPat, GPR>; def : VPatBinarySDNode_XI; + vti.LMul, vti.RegClass, vti.RegClass, + !cast(SplatPat#_#ImmType), + ImmType>; } } @@ -1106,8 +1119,10 @@ def PseudoVMV8R_V : VPseudo; foreach vlmul = MxList.m in - let VLMul = vlmul.value in + let VLMul = vlmul.value in { def PseudoVMV_V_X_ # vlmul.MX : VPseudoUnaryNoMask; + def PseudoVMV_V_I_ # vlmul.MX : VPseudoUnaryNoMask; + } } //===----------------------------------------------------------------------===// @@ -1365,6 +1380,16 @@ // Misc Helpers //===----------------------------------------------------------------------===// +let Predicates = [HasStdExtV] in { +foreach vti = AllIntegerVectors in { + def : Pat<(vti.Vector (splat_vector GPR:$rs1)), + (!cast("PseudoVMV_V_X_" # vti.LMul.MX) + GPR:$rs1, VLMax, vti.SEW)>; + def : Pat<(vti.Vector (splat_vector simm5:$rs1)), + (!cast("PseudoVMV_V_I_" # vti.LMul.MX) + simm5:$rs1, VLMax, vti.SEW)>; +} +} // Predicates = [HasStdExtV] let Predicates = [HasStdExtV, IsRV32] in { foreach vti = AllIntegerVectors in { @@ -1401,6 +1426,13 @@ (VMVInst GPR:$op1, VLMax, vti.SEW), ShAmt32, VLMax, vti.SEW), ShAmt32, VLMax, vti.SEW)>; + + def : Pat<(vti.Vector (rv32_splat_i64 GPR:$rs1)), + (!cast("PseudoVMV_V_X_" # vti.LMul.MX) + GPR:$rs1, VLMax, vti.SEW)>; + def : Pat<(vti.Vector (rv32_splat_i64 simm5:$rs1)), + (!cast("PseudoVMV_V_I_" # vti.LMul.MX) + simm5:$rs1, VLMax, vti.SEW)>; } } } // Predicates = [HasStdExtV, IsRV32] diff --git a/llvm/test/CodeGen/RISCV/rvv/vadd-sdnode-rv32.ll b/llvm/test/CodeGen/RISCV/rvv/vadd-sdnode-rv32.ll --- a/llvm/test/CodeGen/RISCV/rvv/vadd-sdnode-rv32.ll +++ b/llvm/test/CodeGen/RISCV/rvv/vadd-sdnode-rv32.ll @@ -671,14 +671,8 @@ define @vadd_vx_nxv1i64_0( %va) { ; CHECK-LABEL: vadd_vx_nxv1i64_0: ; CHECK: # %bb.0: -; CHECK-NEXT: addi a0, zero, -1 -; CHECK-NEXT: vsetvli a1, zero, e64,m1,ta,mu -; CHECK-NEXT: vmv.v.x v25, a0 -; CHECK-NEXT: addi a0, zero, 32 -; CHECK-NEXT: vsll.vx v25, v25, a0 -; CHECK-NEXT: vsrl.vx v26, v25, a0 -; CHECK-NEXT: vor.vv v25, v26, v25 -; CHECK-NEXT: vadd.vv v16, v16, v25 +; CHECK-NEXT: vsetvli a0, zero, e64,m1,ta,mu +; CHECK-NEXT: vadd.vi v16, v16, -1 ; CHECK-NEXT: ret %head = insertelement undef, i64 -1, i32 0 %splat = shufflevector %head, undef, zeroinitializer @@ -689,13 +683,8 @@ define @vadd_vx_nxv1i64_1( %va) { ; CHECK-LABEL: vadd_vx_nxv1i64_1: ; CHECK: # %bb.0: -; CHECK-NEXT: addi a0, zero, 2 -; CHECK-NEXT: vsetvli a1, zero, e64,m1,ta,mu -; CHECK-NEXT: vmv.v.x v25, a0 -; CHECK-NEXT: addi a0, zero, 32 -; CHECK-NEXT: vsll.vx v25, v25, a0 -; CHECK-NEXT: vsrl.vx v25, v25, a0 -; CHECK-NEXT: vadd.vv v16, v16, v25 +; CHECK-NEXT: vsetvli a0, zero, e64,m1,ta,mu +; CHECK-NEXT: vadd.vi v16, v16, 2 ; CHECK-NEXT: ret %head = insertelement undef, i64 2, i32 0 %splat = shufflevector %head, undef, zeroinitializer @@ -725,14 +714,8 @@ define @vadd_vx_nxv2i64_0( %va) { ; CHECK-LABEL: vadd_vx_nxv2i64_0: ; CHECK: # %bb.0: -; CHECK-NEXT: addi a0, zero, -1 -; CHECK-NEXT: vsetvli a1, zero, e64,m2,ta,mu -; CHECK-NEXT: vmv.v.x v26, a0 -; CHECK-NEXT: addi a0, zero, 32 -; CHECK-NEXT: vsll.vx v26, v26, a0 -; CHECK-NEXT: vsrl.vx v28, v26, a0 -; CHECK-NEXT: vor.vv v26, v28, v26 -; CHECK-NEXT: vadd.vv v16, v16, v26 +; CHECK-NEXT: vsetvli a0, zero, e64,m2,ta,mu +; CHECK-NEXT: vadd.vi v16, v16, -1 ; CHECK-NEXT: ret %head = insertelement undef, i64 -1, i32 0 %splat = shufflevector %head, undef, zeroinitializer @@ -743,13 +726,8 @@ define @vadd_vx_nxv2i64_1( %va) { ; CHECK-LABEL: vadd_vx_nxv2i64_1: ; CHECK: # %bb.0: -; CHECK-NEXT: addi a0, zero, 2 -; CHECK-NEXT: vsetvli a1, zero, e64,m2,ta,mu -; CHECK-NEXT: vmv.v.x v26, a0 -; CHECK-NEXT: addi a0, zero, 32 -; CHECK-NEXT: vsll.vx v26, v26, a0 -; CHECK-NEXT: vsrl.vx v26, v26, a0 -; CHECK-NEXT: vadd.vv v16, v16, v26 +; CHECK-NEXT: vsetvli a0, zero, e64,m2,ta,mu +; CHECK-NEXT: vadd.vi v16, v16, 2 ; CHECK-NEXT: ret %head = insertelement undef, i64 2, i32 0 %splat = shufflevector %head, undef, zeroinitializer @@ -779,14 +757,8 @@ define @vadd_vx_nxv4i64_0( %va) { ; CHECK-LABEL: vadd_vx_nxv4i64_0: ; CHECK: # %bb.0: -; CHECK-NEXT: addi a0, zero, -1 -; CHECK-NEXT: vsetvli a1, zero, e64,m4,ta,mu -; CHECK-NEXT: vmv.v.x v28, a0 -; CHECK-NEXT: addi a0, zero, 32 -; CHECK-NEXT: vsll.vx v28, v28, a0 -; CHECK-NEXT: vsrl.vx v8, v28, a0 -; CHECK-NEXT: vor.vv v28, v8, v28 -; CHECK-NEXT: vadd.vv v16, v16, v28 +; CHECK-NEXT: vsetvli a0, zero, e64,m4,ta,mu +; CHECK-NEXT: vadd.vi v16, v16, -1 ; CHECK-NEXT: ret %head = insertelement undef, i64 -1, i32 0 %splat = shufflevector %head, undef, zeroinitializer @@ -797,13 +769,8 @@ define @vadd_vx_nxv4i64_1( %va) { ; CHECK-LABEL: vadd_vx_nxv4i64_1: ; CHECK: # %bb.0: -; CHECK-NEXT: addi a0, zero, 2 -; CHECK-NEXT: vsetvli a1, zero, e64,m4,ta,mu -; CHECK-NEXT: vmv.v.x v28, a0 -; CHECK-NEXT: addi a0, zero, 32 -; CHECK-NEXT: vsll.vx v28, v28, a0 -; CHECK-NEXT: vsrl.vx v28, v28, a0 -; CHECK-NEXT: vadd.vv v16, v16, v28 +; CHECK-NEXT: vsetvli a0, zero, e64,m4,ta,mu +; CHECK-NEXT: vadd.vi v16, v16, 2 ; CHECK-NEXT: ret %head = insertelement undef, i64 2, i32 0 %splat = shufflevector %head, undef, zeroinitializer @@ -833,14 +800,8 @@ define @vadd_vx_nxv8i64_0( %va) { ; CHECK-LABEL: vadd_vx_nxv8i64_0: ; CHECK: # %bb.0: -; CHECK-NEXT: addi a0, zero, -1 -; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu -; CHECK-NEXT: vmv.v.x v8, a0 -; CHECK-NEXT: addi a0, zero, 32 -; CHECK-NEXT: vsll.vx v8, v8, a0 -; CHECK-NEXT: vsrl.vx v24, v8, a0 -; CHECK-NEXT: vor.vv v8, v24, v8 -; CHECK-NEXT: vadd.vv v16, v16, v8 +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vadd.vi v16, v16, -1 ; CHECK-NEXT: ret %head = insertelement undef, i64 -1, i32 0 %splat = shufflevector %head, undef, zeroinitializer @@ -851,13 +812,8 @@ define @vadd_vx_nxv8i64_1( %va) { ; CHECK-LABEL: vadd_vx_nxv8i64_1: ; CHECK: # %bb.0: -; CHECK-NEXT: addi a0, zero, 2 -; CHECK-NEXT: vsetvli a1, zero, e64,m8,ta,mu -; CHECK-NEXT: vmv.v.x v8, a0 -; CHECK-NEXT: addi a0, zero, 32 -; CHECK-NEXT: vsll.vx v8, v8, a0 -; CHECK-NEXT: vsrl.vx v8, v8, a0 -; CHECK-NEXT: vadd.vv v16, v16, v8 +; CHECK-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; CHECK-NEXT: vadd.vi v16, v16, 2 ; CHECK-NEXT: ret %head = insertelement undef, i64 2, i32 0 %splat = shufflevector %head, undef, zeroinitializer diff --git a/llvm/test/CodeGen/RISCV/rvv/vsplats-i64.ll b/llvm/test/CodeGen/RISCV/rvv/vsplats-i64.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/vsplats-i64.ll @@ -0,0 +1,267 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+experimental-v -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefix=RV32V +; RUN: llc -mtriple=riscv64 -mattr=+experimental-v -verify-machineinstrs < %s \ +; RUN: | FileCheck %s --check-prefix=RV64V + +define @vsplat_nxv8i64_1() { +; RV32V-LABEL: vsplat_nxv8i64_1: +; RV32V: # %bb.0: +; RV32V-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; RV32V-NEXT: vmv.v.i v16, -1 +; RV32V-NEXT: ret +; +; RV64V-LABEL: vsplat_nxv8i64_1: +; RV64V: # %bb.0: +; RV64V-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; RV64V-NEXT: vmv.v.i v16, -1 +; RV64V-NEXT: ret + %head = insertelement undef, i64 -1, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + ret %splat +} + +define @vsplat_nxv8i64_2() { +; RV32V-LABEL: vsplat_nxv8i64_2: +; RV32V: # %bb.0: +; RV32V-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; RV32V-NEXT: vmv.v.i v16, 4 +; RV32V-NEXT: ret +; +; RV64V-LABEL: vsplat_nxv8i64_2: +; RV64V: # %bb.0: +; RV64V-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; RV64V-NEXT: vmv.v.i v16, 4 +; RV64V-NEXT: ret + %head = insertelement undef, i64 4, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + ret %splat +} + +define @vsplat_nxv8i64_3() { +; RV32V-LABEL: vsplat_nxv8i64_3: +; RV32V: # %bb.0: +; RV32V-NEXT: addi a0, zero, 255 +; RV32V-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; RV32V-NEXT: vmv.v.x v16, a0 +; RV32V-NEXT: ret +; +; RV64V-LABEL: vsplat_nxv8i64_3: +; RV64V: # %bb.0: +; RV64V-NEXT: addi a0, zero, 255 +; RV64V-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; RV64V-NEXT: vmv.v.x v16, a0 +; RV64V-NEXT: ret + %head = insertelement undef, i64 255, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + ret %splat +} + +define @vsplat_nxv8i64_4() { +; RV32V-LABEL: vsplat_nxv8i64_4: +; RV32V: # %bb.0: +; RV32V-NEXT: lui a0, 1028096 +; RV32V-NEXT: addi a0, a0, -1281 +; RV32V-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; RV32V-NEXT: vmv.v.x v8, a0 +; RV32V-NEXT: addi a0, zero, 32 +; RV32V-NEXT: vsll.vx v8, v8, a0 +; RV32V-NEXT: vsrl.vx v16, v8, a0 +; RV32V-NEXT: ret +; +; RV64V-LABEL: vsplat_nxv8i64_4: +; RV64V: # %bb.0: +; RV64V-NEXT: addi a0, zero, 251 +; RV64V-NEXT: slli a0, a0, 24 +; RV64V-NEXT: addi a0, a0, -1281 +; RV64V-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; RV64V-NEXT: vmv.v.x v16, a0 +; RV64V-NEXT: ret + %head = insertelement undef, i64 4211079935, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + ret %splat +} + +define @vsplat_nxv8i64_5(i64 %a) { +; RV32V-LABEL: vsplat_nxv8i64_5: +; RV32V: # %bb.0: +; RV32V-NEXT: vsetvli a2, zero, e64,m8,ta,mu +; RV32V-NEXT: vmv.v.x v8, a1 +; RV32V-NEXT: addi a1, zero, 32 +; RV32V-NEXT: vsll.vx v8, v8, a1 +; RV32V-NEXT: vmv.v.x v16, a0 +; RV32V-NEXT: vsll.vx v16, v16, a1 +; RV32V-NEXT: vsrl.vx v16, v16, a1 +; RV32V-NEXT: vor.vv v16, v16, v8 +; RV32V-NEXT: ret +; +; RV64V-LABEL: vsplat_nxv8i64_5: +; RV64V: # %bb.0: +; RV64V-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; RV64V-NEXT: vmv.v.x v16, a0 +; RV64V-NEXT: ret + %head = insertelement undef, i64 %a, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + ret %splat +} + +define @vadd_vx_nxv8i64_6( %v) { +; RV32V-LABEL: vadd_vx_nxv8i64_6: +; RV32V: # %bb.0: +; RV32V-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; RV32V-NEXT: vadd.vi v16, v16, 2 +; RV32V-NEXT: ret +; +; RV64V-LABEL: vadd_vx_nxv8i64_6: +; RV64V: # %bb.0: +; RV64V-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; RV64V-NEXT: vadd.vi v16, v16, 2 +; RV64V-NEXT: ret + %head = insertelement undef, i64 2, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vret = add %v, %splat + ret %vret +} + +define @vadd_vx_nxv8i64_7( %v) { +; RV32V-LABEL: vadd_vx_nxv8i64_7: +; RV32V: # %bb.0: +; RV32V-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; RV32V-NEXT: vadd.vi v16, v16, -1 +; RV32V-NEXT: ret +; +; RV64V-LABEL: vadd_vx_nxv8i64_7: +; RV64V: # %bb.0: +; RV64V-NEXT: vsetvli a0, zero, e64,m8,ta,mu +; RV64V-NEXT: vadd.vi v16, v16, -1 +; RV64V-NEXT: ret + %head = insertelement undef, i64 -1, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vret = add %v, %splat + ret %vret +} + +define @vadd_vx_nxv8i64_8( %v) { +; RV32V-LABEL: vadd_vx_nxv8i64_8: +; RV32V: # %bb.0: +; RV32V-NEXT: addi a0, zero, 255 +; RV32V-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; RV32V-NEXT: vadd.vx v16, v16, a0 +; RV32V-NEXT: ret +; +; RV64V-LABEL: vadd_vx_nxv8i64_8: +; RV64V: # %bb.0: +; RV64V-NEXT: addi a0, zero, 255 +; RV64V-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; RV64V-NEXT: vadd.vx v16, v16, a0 +; RV64V-NEXT: ret + %head = insertelement undef, i64 255, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vret = add %v, %splat + ret %vret +} + +define @vadd_vx_nxv8i64_9( %v) { +; RV32V-LABEL: vadd_vx_nxv8i64_9: +; RV32V: # %bb.0: +; RV32V-NEXT: lui a0, 503808 +; RV32V-NEXT: addi a0, a0, -1281 +; RV32V-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; RV32V-NEXT: vadd.vx v16, v16, a0 +; RV32V-NEXT: ret +; +; RV64V-LABEL: vadd_vx_nxv8i64_9: +; RV64V: # %bb.0: +; RV64V-NEXT: lui a0, 503808 +; RV64V-NEXT: addiw a0, a0, -1281 +; RV64V-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; RV64V-NEXT: vadd.vx v16, v16, a0 +; RV64V-NEXT: ret + %head = insertelement undef, i64 2063596287, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vret = add %v, %splat + ret %vret +} + +define @vadd_vx_nxv8i64_10( %v) { +; RV32V-LABEL: vadd_vx_nxv8i64_10: +; RV32V: # %bb.0: +; RV32V-NEXT: lui a0, 1028096 +; RV32V-NEXT: addi a0, a0, -1281 +; RV32V-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; RV32V-NEXT: vmv.v.x v8, a0 +; RV32V-NEXT: addi a0, zero, 32 +; RV32V-NEXT: vsll.vx v8, v8, a0 +; RV32V-NEXT: vsrl.vx v8, v8, a0 +; RV32V-NEXT: vadd.vv v16, v16, v8 +; RV32V-NEXT: ret +; +; RV64V-LABEL: vadd_vx_nxv8i64_10: +; RV64V: # %bb.0: +; RV64V-NEXT: addi a0, zero, 251 +; RV64V-NEXT: slli a0, a0, 24 +; RV64V-NEXT: addi a0, a0, -1281 +; RV64V-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; RV64V-NEXT: vadd.vx v16, v16, a0 +; RV64V-NEXT: ret + %head = insertelement undef, i64 4211079935, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vret = add %v, %splat + ret %vret +} + +define @vadd_vx_nxv8i64_11( %v) { +; RV32V-LABEL: vadd_vx_nxv8i64_11: +; RV32V: # %bb.0: +; RV32V-NEXT: addi a0, zero, 1 +; RV32V-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; RV32V-NEXT: vmv.v.x v8, a0 +; RV32V-NEXT: addi a0, zero, 32 +; RV32V-NEXT: vsll.vx v8, v8, a0 +; RV32V-NEXT: lui a1, 1028096 +; RV32V-NEXT: addi a1, a1, -1281 +; RV32V-NEXT: vmv.v.x v24, a1 +; RV32V-NEXT: vsll.vx v24, v24, a0 +; RV32V-NEXT: vsrl.vx v24, v24, a0 +; RV32V-NEXT: vor.vv v8, v24, v8 +; RV32V-NEXT: vadd.vv v16, v16, v8 +; RV32V-NEXT: ret +; +; RV64V-LABEL: vadd_vx_nxv8i64_11: +; RV64V: # %bb.0: +; RV64V-NEXT: addi a0, zero, 507 +; RV64V-NEXT: slli a0, a0, 24 +; RV64V-NEXT: addi a0, a0, -1281 +; RV64V-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; RV64V-NEXT: vadd.vx v16, v16, a0 +; RV64V-NEXT: ret + %head = insertelement undef, i64 8506047231, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vret = add %v, %splat + ret %vret +} + +define @vadd_vx_nxv8i64_12( %v, i64 %a) { +; RV32V-LABEL: vadd_vx_nxv8i64_12: +; RV32V: # %bb.0: +; RV32V-NEXT: vsetvli a2, zero, e64,m8,ta,mu +; RV32V-NEXT: vmv.v.x v8, a1 +; RV32V-NEXT: addi a1, zero, 32 +; RV32V-NEXT: vsll.vx v8, v8, a1 +; RV32V-NEXT: vmv.v.x v24, a0 +; RV32V-NEXT: vsll.vx v24, v24, a1 +; RV32V-NEXT: vsrl.vx v24, v24, a1 +; RV32V-NEXT: vor.vv v8, v24, v8 +; RV32V-NEXT: vadd.vv v16, v16, v8 +; RV32V-NEXT: ret +; +; RV64V-LABEL: vadd_vx_nxv8i64_12: +; RV64V: # %bb.0: +; RV64V-NEXT: vsetvli a1, zero, e64,m8,ta,mu +; RV64V-NEXT: vadd.vx v16, v16, a0 +; RV64V-NEXT: ret + %head = insertelement undef, i64 %a, i32 0 + %splat = shufflevector %head, undef, zeroinitializer + %vret = add %v, %splat + ret %vret +}