@@ -95,7 +95,8 @@ class RISCVInstructionSelector : public InstructionSelector {
9595 void addVectorLoadStoreOperands (MachineInstr &I,
9696 SmallVectorImpl<SrcOp> &SrcOps,
9797 unsigned &CurOp, bool IsMasked,
98- bool IsStrided) const ;
98+ bool IsStridedOrIndexed,
99+ LLT *IndexVT = nullptr ) const ;
99100 bool selectIntrinsicWithSideEffects (MachineInstr &I,
100101 MachineIRBuilder &MIB) const ;
101102
@@ -722,15 +723,17 @@ static unsigned selectRegImmLoadStoreOp(unsigned GenericOpc, unsigned OpSize) {
722723
723724void RISCVInstructionSelector::addVectorLoadStoreOperands (
724725 MachineInstr &I, SmallVectorImpl<SrcOp> &SrcOps, unsigned &CurOp,
725- bool IsMasked, bool IsStrided ) const {
726+ bool IsMasked, bool IsStridedOrIndexed, LLT *IndexVT ) const {
726727 // Base Pointer
727728 auto PtrReg = I.getOperand (CurOp++).getReg ();
728729 SrcOps.push_back (PtrReg);
729730
730- // Stride
731- if (IsStrided ) {
731+ // Stride or Index
732+ if (IsStridedOrIndexed ) {
732733 auto StrideReg = I.getOperand (CurOp++).getReg ();
733734 SrcOps.push_back (StrideReg);
735+ if (IndexVT)
736+ *IndexVT = MRI->getType (StrideReg);
734737 }
735738
736739 // Mask
@@ -805,6 +808,70 @@ bool RISCVInstructionSelector::selectIntrinsicWithSideEffects(
805808 I.eraseFromParent ();
806809 return constrainSelectedInstRegOperands (*PseudoMI, TII, TRI, RBI);
807810 }
811+ case Intrinsic::riscv_vloxei:
812+ case Intrinsic::riscv_vloxei_mask:
813+ case Intrinsic::riscv_vluxei:
814+ case Intrinsic::riscv_vluxei_mask: {
815+ bool IsMasked = IntrinID == Intrinsic::riscv_vloxei_mask ||
816+ IntrinID == Intrinsic::riscv_vluxei_mask;
817+ bool IsOrdered = IntrinID == Intrinsic::riscv_vloxei ||
818+ IntrinID == Intrinsic::riscv_vloxei_mask;
819+ LLT VT = MRI->getType (I.getOperand (0 ).getReg ());
820+ unsigned Log2SEW = Log2_32 (VT.getScalarSizeInBits ());
821+
822+ // Result vector
823+ const Register DstReg = I.getOperand (0 ).getReg ();
824+
825+ // Sources
826+ bool HasPassthruOperand = IntrinID != Intrinsic::riscv_vlm;
827+ unsigned CurOp = 2 ;
828+ SmallVector<SrcOp, 4 > SrcOps; // Source registers.
829+
830+ // Passthru
831+ if (HasPassthruOperand) {
832+ auto PassthruReg = I.getOperand (CurOp++).getReg ();
833+ SrcOps.push_back (PassthruReg);
834+ } else {
835+ // Use NoRegister if there is no specified passthru.
836+ SrcOps.push_back (Register ());
837+ }
838+ LLT IndexVT;
839+ addVectorLoadStoreOperands (I, SrcOps, CurOp, IsMasked, true , &IndexVT);
840+
841+ RISCVVType::VLMUL LMUL = RISCVTargetLowering::getLMUL (getMVTForLLT (VT));
842+ RISCVVType::VLMUL IndexLMUL =
843+ RISCVTargetLowering::getLMUL (getMVTForLLT (IndexVT));
844+ unsigned IndexLog2EEW = Log2_32 (IndexVT.getScalarSizeInBits ());
845+ if (IndexLog2EEW == 6 && !Subtarget->is64Bit ()) {
846+ reportFatalUsageError (" The V extension does not support EEW=64 for index "
847+ " values when XLEN=32" );
848+ }
849+ const RISCV::VLX_VSXPseudo *P = RISCV::getVLXPseudo (
850+ IsMasked, IsOrdered, IndexLog2EEW, static_cast <unsigned >(LMUL),
851+ static_cast <unsigned >(IndexLMUL));
852+
853+ auto PseudoMI = MIB.buildInstr (P->Pseudo , {DstReg}, SrcOps);
854+
855+ // Select VL
856+ auto VLOpFn = renderVLOp (I.getOperand (CurOp++));
857+ for (auto &RenderFn : *VLOpFn)
858+ RenderFn (PseudoMI);
859+
860+ // SEW
861+ PseudoMI.addImm (Log2SEW);
862+
863+ // Policy
864+ uint64_t Policy = RISCVVType::MASK_AGNOSTIC;
865+ if (IsMasked)
866+ Policy = I.getOperand (CurOp++).getImm ();
867+ PseudoMI.addImm (Policy);
868+
869+ // Memref
870+ PseudoMI.cloneMemRefs (I);
871+
872+ I.eraseFromParent ();
873+ return constrainSelectedInstRegOperands (*PseudoMI, TII, TRI, RBI);
874+ }
808875 case Intrinsic::riscv_vsm:
809876 case Intrinsic::riscv_vse:
810877 case Intrinsic::riscv_vse_mask:
@@ -847,6 +914,56 @@ bool RISCVInstructionSelector::selectIntrinsicWithSideEffects(
847914 I.eraseFromParent ();
848915 return constrainSelectedInstRegOperands (*PseudoMI, TII, TRI, RBI);
849916 }
917+ case Intrinsic::riscv_vsoxei:
918+ case Intrinsic::riscv_vsoxei_mask:
919+ case Intrinsic::riscv_vsuxei:
920+ case Intrinsic::riscv_vsuxei_mask: {
921+ bool IsMasked = IntrinID == Intrinsic::riscv_vsoxei_mask ||
922+ IntrinID == Intrinsic::riscv_vsuxei_mask;
923+ bool IsOrdered = IntrinID == Intrinsic::riscv_vsoxei ||
924+ IntrinID == Intrinsic::riscv_vsoxei_mask;
925+ LLT VT = MRI->getType (I.getOperand (1 ).getReg ());
926+ unsigned Log2SEW = Log2_32 (VT.getScalarSizeInBits ());
927+
928+ // Sources
929+ unsigned CurOp = 1 ;
930+ SmallVector<SrcOp, 4 > SrcOps; // Source registers.
931+
932+ // Store value
933+ auto PassthruReg = I.getOperand (CurOp++).getReg ();
934+ SrcOps.push_back (PassthruReg);
935+
936+ LLT IndexVT;
937+ addVectorLoadStoreOperands (I, SrcOps, CurOp, IsMasked, true , &IndexVT);
938+
939+ RISCVVType::VLMUL LMUL = RISCVTargetLowering::getLMUL (getMVTForLLT (VT));
940+ RISCVVType::VLMUL IndexLMUL =
941+ RISCVTargetLowering::getLMUL (getMVTForLLT (IndexVT));
942+ unsigned IndexLog2EEW = Log2_32 (IndexVT.getScalarSizeInBits ());
943+ if (IndexLog2EEW == 6 && !Subtarget->is64Bit ()) {
944+ reportFatalUsageError (" The V extension does not support EEW=64 for index "
945+ " values when XLEN=32" );
946+ }
947+ const RISCV::VLX_VSXPseudo *P = RISCV::getVSXPseudo (
948+ IsMasked, IsOrdered, IndexLog2EEW, static_cast <unsigned >(LMUL),
949+ static_cast <unsigned >(IndexLMUL));
950+
951+ auto PseudoMI = MIB.buildInstr (P->Pseudo , {}, SrcOps);
952+
953+ // Select VL
954+ auto VLOpFn = renderVLOp (I.getOperand (CurOp++));
955+ for (auto &RenderFn : *VLOpFn)
956+ RenderFn (PseudoMI);
957+
958+ // SEW
959+ PseudoMI.addImm (Log2SEW);
960+
961+ // Memref
962+ PseudoMI.cloneMemRefs (I);
963+
964+ I.eraseFromParent ();
965+ return constrainSelectedInstRegOperands (*PseudoMI, TII, TRI, RBI);
966+ }
850967 }
851968}
852969
0 commit comments