@@ -338,7 +338,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
338338 setOperationAction ({ISD::MUL, ISD::SDIV, ISD::SREM, ISD::UDIV, ISD::UREM},
339339 VT, Legal);
340340 setOperationAction ({ISD::AND, ISD::OR, ISD::XOR}, VT, Legal);
341- setOperationAction ({ISD::SHL, ISD::SRA, ISD::SRL }, VT, Legal);
341+ setOperationAction ({ISD::SHL, ISD::SRA}, VT, Legal);
342342 setOperationAction ({ISD::CTPOP, ISD::CTLZ}, VT, Legal);
343343 setOperationAction ({ISD::MULHS, ISD::MULHU}, VT, Legal);
344344 setCondCodeAction (
@@ -354,6 +354,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
354354 setOperationAction (ISD::USUBSAT, VT, Legal);
355355 setOperationAction (ISD::ROTL, VT, Custom);
356356 setOperationAction (ISD::ROTR, VT, Custom);
357+ setOperationAction (ISD::SRL, VT, Custom);
357358 }
358359 for (MVT VT : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
359360 setOperationAction (ISD::BITREVERSE, VT, Custom);
@@ -427,7 +428,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
427428 setOperationAction ({ISD::MUL, ISD::SDIV, ISD::SREM, ISD::UDIV, ISD::UREM},
428429 VT, Legal);
429430 setOperationAction ({ISD::AND, ISD::OR, ISD::XOR}, VT, Legal);
430- setOperationAction ({ISD::SHL, ISD::SRA, ISD::SRL }, VT, Legal);
431+ setOperationAction ({ISD::SHL, ISD::SRA}, VT, Legal);
431432 setOperationAction ({ISD::CTPOP, ISD::CTLZ}, VT, Legal);
432433 setOperationAction ({ISD::MULHS, ISD::MULHU}, VT, Legal);
433434 setCondCodeAction (
@@ -444,6 +445,7 @@ LoongArchTargetLowering::LoongArchTargetLowering(const TargetMachine &TM,
444445 setOperationAction (ISD::VECREDUCE_ADD, VT, Custom);
445446 setOperationAction (ISD::ROTL, VT, Custom);
446447 setOperationAction (ISD::ROTR, VT, Custom);
448+ setOperationAction (ISD::SRL, VT, Custom);
447449 }
448450 for (MVT VT : {MVT::v32i8, MVT::v16i16, MVT::v8i32})
449451 setOperationAction (ISD::BITREVERSE, VT, Custom);
@@ -618,10 +620,51 @@ SDValue LoongArchTargetLowering::LowerOperation(SDValue Op,
618620 return lowerVECREDUCE (Op, DAG);
619621 case ISD::ConstantFP:
620622 return lowerConstantFP (Op, DAG);
623+ case ISD::SRL:
624+ return lowerVectorSRL (Op, DAG);
621625 }
622626 return SDValue ();
623627}
624628
629+ // / getVShiftAmt - Check if this is a valid build_vector for the immediate
630+ // / operand of a vector shift operation, where all the elements of the
631+ // / build_vector must have the same constant integer value.
632+ static bool getVShiftAmt (SDValue Op, unsigned ElementBits, int64_t &Amt) {
633+ // Ignore bit_converts.
634+ while (Op.getOpcode () == ISD::BITCAST)
635+ Op = Op.getOperand (0 );
636+ BuildVectorSDNode *BVN = dyn_cast<BuildVectorSDNode>(Op.getNode ());
637+ APInt SplatBits, SplatUndef;
638+ unsigned SplatBitSize;
639+ bool HasAnyUndefs;
640+ if (!BVN ||
641+ !BVN->isConstantSplat (SplatBits, SplatUndef, SplatBitSize, HasAnyUndefs,
642+ ElementBits) ||
643+ SplatBitSize > ElementBits)
644+ return false ;
645+ Amt = SplatBits.getSExtValue ();
646+ return true ;
647+ }
648+
649+ SDValue LoongArchTargetLowering::lowerVectorSRL (SDValue Op,
650+ SelectionDAG &DAG) const {
651+ EVT VT = Op.getValueType ();
652+ SDLoc DL (Op);
653+ int64_t Amt;
654+
655+ if (!Op.getOperand (1 ).getValueType ().isVector ())
656+ return Op;
657+ unsigned EltSize = VT.getScalarSizeInBits ();
658+ MVT GRLenVT = Subtarget.getGRLenVT ();
659+
660+ assert (Op.getOpcode () == ISD::SRL && " unexpected shift opcode" );
661+ if (getVShiftAmt (Op.getOperand (1 ), EltSize, Amt) && Amt >= 0 && Amt < EltSize)
662+ return DAG.getNode (LoongArchISD::VSRLI, DL, VT, Op.getOperand (0 ),
663+ DAG.getConstant (Amt, DL, GRLenVT));
664+ return DAG.getNode (LoongArchISD::VSRL, DL, VT, Op.getOperand (0 ),
665+ Op.getOperand (1 ));
666+ }
667+
625668// Helper to attempt to return a cheaper, bit-inverted version of \p V.
626669static SDValue isNOT (SDValue V, SelectionDAG &DAG) {
627670 // TODO: don't always ignore oneuse constraints.
0 commit comments