diff --git a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp index 1e5d0a4297465..4f2e633c1c524 100644 --- a/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp +++ b/llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp @@ -99,6 +99,7 @@ class RISCVInstructionSelector : public InstructionSelector { LLT *IndexVT = nullptr) const; bool selectIntrinsicWithSideEffects(MachineInstr &I, MachineIRBuilder &MIB) const; + bool selectExtractSubvector(MachineInstr &MI, MachineIRBuilder &MIB) const; ComplexRendererFns selectShiftMask(MachineOperand &Root, unsigned ShiftWidth) const; @@ -967,6 +968,45 @@ bool RISCVInstructionSelector::selectIntrinsicWithSideEffects( } } +bool RISCVInstructionSelector::selectExtractSubvector( + MachineInstr &MI, MachineIRBuilder &MIB) const { + assert(MI.getOpcode() == TargetOpcode::G_EXTRACT_SUBVECTOR); + + Register DstReg = MI.getOperand(0).getReg(); + Register SrcReg = MI.getOperand(1).getReg(); + + LLT DstTy = MRI->getType(DstReg); + LLT SrcTy = MRI->getType(SrcReg); + + unsigned Idx = static_cast(MI.getOperand(2).getImm()); + + MVT DstMVT = getMVTForLLT(DstTy); + MVT SrcMVT = getMVTForLLT(SrcTy); + + unsigned SubRegIdx; + std::tie(SubRegIdx, Idx) = + RISCVTargetLowering::decomposeSubvectorInsertExtractToSubRegs( + SrcMVT, DstMVT, Idx, &TRI); + + if (Idx != 0) + return false; + + unsigned DstRegClassID = RISCVTargetLowering::getRegClassIDForVecVT(DstMVT); + const TargetRegisterClass *DstRC = TRI.getRegClass(DstRegClassID); + if (!RBI.constrainGenericRegister(DstReg, *DstRC, *MRI)) + return false; + + unsigned SrcRegClassID = RISCVTargetLowering::getRegClassIDForVecVT(SrcMVT); + const TargetRegisterClass *SrcRC = TRI.getRegClass(SrcRegClassID); + if (!RBI.constrainGenericRegister(SrcReg, *SrcRC, *MRI)) + return false; + + MIB.buildInstr(TargetOpcode::COPY, {DstReg}, {}).addReg(SrcReg, 0, SubRegIdx); + + MI.eraseFromParent(); + return true; +} + bool RISCVInstructionSelector::select(MachineInstr &MI) { MachineIRBuilder MIB(MI); @@ -1239,6 +1279,8 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) { } case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: return selectIntrinsicWithSideEffects(MI, MIB); + case TargetOpcode::G_EXTRACT_SUBVECTOR: + return selectExtractSubvector(MI, MIB); default: return false; } diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index ab2652eac3823..a6eb225e24609 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -25580,6 +25580,8 @@ bool RISCVTargetLowering::fallBackToDAGISel(const Instruction &Inst) const { return false; } + if (II->getIntrinsicID() == Intrinsic::vector_extract) + return false; } if (Inst.getType()->isScalableTy()) diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/rvv/extract-subvector.ll b/llvm/test/CodeGen/RISCV/GlobalISel/rvv/extract-subvector.ll new file mode 100644 index 0000000000000..e5de4f39c19b7 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/GlobalISel/rvv/extract-subvector.ll @@ -0,0 +1,383 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple riscv32 -global-isel -mattr=+m,+d,+zvfh,+v,+zvfbfmin -verify-machineinstrs < %s | FileCheck %s +; RUN: llc -mtriple riscv64 -global-isel -mattr=+m,+d,+zvfh,+v,+zvfbfmin -verify-machineinstrs < %s | FileCheck %s +; +define @extract_nxv8i32_nxv4i32_0( %vec) { +; CHECK-LABEL: extract_nxv8i32_nxv4i32_0: +; CHECK: # %bb.0: +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv4i32.nxv8i32( %vec, i64 0) + ret %c +} + +define @extract_nxv8i32_nxv4i32_4( %vec) { +; CHECK-LABEL: extract_nxv8i32_nxv4i32_4: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma +; CHECK-NEXT: vmv2r.v v8, v10 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv4i32.nxv8i32( %vec, i64 4) + ret %c +} + +define @extract_nxv8i32_nxv2i32_0( %vec) { +; CHECK-LABEL: extract_nxv8i32_nxv2i32_0: +; CHECK: # %bb.0: +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2i32.nxv8i32( %vec, i64 0) + ret %c +} + +define @extract_nxv8i32_nxv2i32_2( %vec) { +; CHECK-LABEL: extract_nxv8i32_nxv2i32_2: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma +; CHECK-NEXT: vmv1r.v v8, v9 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2i32.nxv8i32( %vec, i64 2) + ret %c +} + +define @extract_nxv8i32_nxv2i32_4( %vec) { +; CHECK-LABEL: extract_nxv8i32_nxv2i32_4: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma +; CHECK-NEXT: vmv1r.v v8, v10 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2i32.nxv8i32( %vec, i64 4) + ret %c +} + +define @extract_nxv8i32_nxv2i32_6( %vec) { +; CHECK-LABEL: extract_nxv8i32_nxv2i32_6: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma +; CHECK-NEXT: vmv1r.v v8, v11 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2i32.nxv8i32( %vec, i64 6) + ret %c +} + +define @extract_nxv16i32_nxv8i32_0( %vec) { +; CHECK-LABEL: extract_nxv16i32_nxv8i32_0: +; CHECK: # %bb.0: +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv8i32.nxv16i32( %vec, i64 0) + ret %c +} + +define @extract_nxv16i32_nxv8i32_8( %vec) { +; CHECK-LABEL: extract_nxv16i32_nxv8i32_8: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma +; CHECK-NEXT: vmv4r.v v8, v12 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv8i32.nxv16i32( %vec, i64 8) + ret %c +} + +define @extract_nxv16i32_nxv4i32_0( %vec) { +; CHECK-LABEL: extract_nxv16i32_nxv4i32_0: +; CHECK: # %bb.0: +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv4i32.nxv16i32( %vec, i64 0) + ret %c +} + +define @extract_nxv16i32_nxv4i32_4( %vec) { +; CHECK-LABEL: extract_nxv16i32_nxv4i32_4: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma +; CHECK-NEXT: vmv2r.v v8, v10 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv4i32.nxv16i32( %vec, i64 4) + ret %c +} + +define @extract_nxv16i32_nxv4i32_8( %vec) { +; CHECK-LABEL: extract_nxv16i32_nxv4i32_8: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma +; CHECK-NEXT: vmv2r.v v8, v12 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv4i32.nxv16i32( %vec, i64 8) + ret %c +} + +define @extract_nxv16i32_nxv4i32_12( %vec) { +; CHECK-LABEL: extract_nxv16i32_nxv4i32_12: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma +; CHECK-NEXT: vmv2r.v v8, v14 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv4i32.nxv16i32( %vec, i64 12) + ret %c +} + +define @extract_nxv16i32_nxv2i32_0( %vec) { +; CHECK-LABEL: extract_nxv16i32_nxv2i32_0: +; CHECK: # %bb.0: +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2i32.nxv16i32( %vec, i64 0) + ret %c +} + +define @extract_nxv16i32_nxv2i32_2( %vec) { +; CHECK-LABEL: extract_nxv16i32_nxv2i32_2: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma +; CHECK-NEXT: vmv1r.v v8, v9 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2i32.nxv16i32( %vec, i64 2) + ret %c +} + +define @extract_nxv16i32_nxv2i32_4( %vec) { +; CHECK-LABEL: extract_nxv16i32_nxv2i32_4: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma +; CHECK-NEXT: vmv1r.v v8, v10 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2i32.nxv16i32( %vec, i64 4) + ret %c +} + +define @extract_nxv16i32_nxv2i32_6( %vec) { +; CHECK-LABEL: extract_nxv16i32_nxv2i32_6: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma +; CHECK-NEXT: vmv1r.v v8, v11 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2i32.nxv16i32( %vec, i64 6) + ret %c +} + +define @extract_nxv16i32_nxv2i32_8( %vec) { +; CHECK-LABEL: extract_nxv16i32_nxv2i32_8: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma +; CHECK-NEXT: vmv1r.v v8, v12 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2i32.nxv16i32( %vec, i64 8) + ret %c +} + +define @extract_nxv16i32_nxv2i32_10( %vec) { +; CHECK-LABEL: extract_nxv16i32_nxv2i32_10: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma +; CHECK-NEXT: vmv1r.v v8, v13 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2i32.nxv16i32( %vec, i64 10) + ret %c +} + +define @extract_nxv16i32_nxv2i32_12( %vec) { +; CHECK-LABEL: extract_nxv16i32_nxv2i32_12: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma +; CHECK-NEXT: vmv1r.v v8, v14 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2i32.nxv16i32( %vec, i64 12) + ret %c +} + +define @extract_nxv16i32_nxv2i32_14( %vec) { +; CHECK-LABEL: extract_nxv16i32_nxv2i32_14: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma +; CHECK-NEXT: vmv1r.v v8, v15 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2i32.nxv16i32( %vec, i64 14) + ret %c +} + +define @extract_nxv16i32_nxv1i32_0( %vec) { +; CHECK-LABEL: extract_nxv16i32_nxv1i32_0: +; CHECK: # %bb.0: +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv1i32.nxv16i32( %vec, i64 0) + ret %c +} + +define @extract_nxv16i32_nxv1i32_1( %vec) { +; CHECK-LABEL: extract_nxv16i32_nxv1i32_1: +; CHECK: # %bb.0: +; CHECK-NEXT: csrr a0, vlenb +; CHECK-NEXT: srli a0, a0, 3 +; CHECK-NEXT: vsetvli a1, zero, e32, m1, ta, ma +; CHECK-NEXT: vslidedown.vx v8, v8, a0 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv1i32.nxv16i32( %vec, i64 1) + ret %c +} + +define @extract_nxv16i32_nxv1i32_3( %vec) { +; CHECK-LABEL: extract_nxv16i32_nxv1i32_3: +; CHECK: # %bb.0: +; CHECK-NEXT: csrr a0, vlenb +; CHECK-NEXT: srli a0, a0, 3 +; CHECK-NEXT: vsetvli a1, zero, e32, m1, ta, ma +; CHECK-NEXT: vslidedown.vx v8, v9, a0 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv1i32.nxv16i32( %vec, i64 3) + ret %c +} + +define @extract_nxv16i32_nxv1i32_15( %vec) { +; CHECK-LABEL: extract_nxv16i32_nxv1i32_15: +; CHECK: # %bb.0: +; CHECK-NEXT: csrr a0, vlenb +; CHECK-NEXT: srli a0, a0, 3 +; CHECK-NEXT: vsetvli a1, zero, e32, m1, ta, ma +; CHECK-NEXT: vslidedown.vx v8, v15, a0 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv1i32.nxv16i32( %vec, i64 15) + ret %c +} + +define @extract_nxv16i32_nxv1i32_2( %vec) { +; CHECK-LABEL: extract_nxv16i32_nxv1i32_2: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma +; CHECK-NEXT: vmv1r.v v8, v9 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv1i32.nxv16i32( %vec, i64 2) + ret %c +} + +define @extract_nxv2i32_nxv1i32_0( %vec) { +; CHECK-LABEL: extract_nxv2i32_nxv1i32_0: +; CHECK: # %bb.0: +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv1i32.nxv2i32( %vec, i64 0) + ret %c +} + +define @extract_nxv32i8_nxv2i8_0( %vec) { +; CHECK-LABEL: extract_nxv32i8_nxv2i8_0: +; CHECK: # %bb.0: +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2i8.nxv32i8( %vec, i64 0) + ret %c +} + +define @extract_nxv32i8_nxv2i8_2( %vec) { +; CHECK-LABEL: extract_nxv32i8_nxv2i8_2: +; CHECK: # %bb.0: +; CHECK-NEXT: csrr a0, vlenb +; CHECK-NEXT: srli a0, a0, 2 +; CHECK-NEXT: vsetvli a1, zero, e8, m1, ta, ma +; CHECK-NEXT: vslidedown.vx v8, v8, a0 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2i8.nxv32i8( %vec, i64 2) + ret %c +} + +define @extract_nxv32i8_nxv2i8_4( %vec) { +; CHECK-LABEL: extract_nxv32i8_nxv2i8_4: +; CHECK: # %bb.0: +; CHECK-NEXT: csrr a0, vlenb +; CHECK-NEXT: srli a0, a0, 1 +; CHECK-NEXT: vsetvli a1, zero, e8, m1, ta, ma +; CHECK-NEXT: vslidedown.vx v8, v8, a0 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2i8.nxv32i8( %vec, i64 4) + ret %c +} + +define @extract_nxv32i8_nxv2i8_6( %vec) { +; CHECK-LABEL: extract_nxv32i8_nxv2i8_6: +; CHECK: # %bb.0: +; CHECK-NEXT: csrr a0, vlenb +; CHECK-NEXT: srli a0, a0, 3 +; CHECK-NEXT: li a1, 6 +; CHECK-NEXT: mul a0, a0, a1 +; CHECK-NEXT: vsetvli a1, zero, e8, m1, ta, ma +; CHECK-NEXT: vslidedown.vx v8, v8, a0 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2i8.nxv32i8( %vec, i64 6) + ret %c +} + +define @extract_nxv32i8_nxv2i8_8( %vec) { +; CHECK-LABEL: extract_nxv32i8_nxv2i8_8: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma +; CHECK-NEXT: vmv1r.v v8, v9 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2i8.nxv32i8( %vec, i64 8) + ret %c +} + +define @extract_nxv32i8_nxv2i8_22( %vec) { +; CHECK-LABEL: extract_nxv32i8_nxv2i8_22: +; CHECK: # %bb.0: +; CHECK-NEXT: csrr a0, vlenb +; CHECK-NEXT: srli a0, a0, 3 +; CHECK-NEXT: li a1, 6 +; CHECK-NEXT: mul a0, a0, a1 +; CHECK-NEXT: vsetvli a1, zero, e8, m1, ta, ma +; CHECK-NEXT: vslidedown.vx v8, v10, a0 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2i8.nxv32i8( %vec, i64 22) + ret %c +} + +define @extract_nxv8i8_nxv1i8_7( %vec) { +; CHECK-LABEL: extract_nxv8i8_nxv1i8_7: +; CHECK: # %bb.0: +; CHECK-NEXT: csrr a0, vlenb +; CHECK-NEXT: srli a0, a0, 3 +; CHECK-NEXT: li a1, 7 +; CHECK-NEXT: mul a0, a0, a1 +; CHECK-NEXT: vsetvli a1, zero, e8, m1, ta, ma +; CHECK-NEXT: vslidedown.vx v8, v8, a0 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv1i8.nxv8i8( %vec, i64 7) + ret %c +} + +define @extract_nxv4i8_nxv1i8_3( %vec) { +; CHECK-LABEL: extract_nxv4i8_nxv1i8_3: +; CHECK: # %bb.0: +; CHECK-NEXT: csrr a0, vlenb +; CHECK-NEXT: li a1, 3 +; CHECK-NEXT: srli a0, a0, 3 +; CHECK-NEXT: mul a0, a0, a1 +; CHECK-NEXT: vsetvli a1, zero, e8, mf2, ta, ma +; CHECK-NEXT: vslidedown.vx v8, v8, a0 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv1i8.nxv4i8( %vec, i64 3) + ret %c +} + +define @extract_nxv2f16_nxv16f16_0( %vec) { +; CHECK-LABEL: extract_nxv2f16_nxv16f16_0: +; CHECK: # %bb.0: +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2f16.nxv16f16( %vec, i64 0) + ret %c +} + +define @extract_nxv2f16_nxv16f16_2( %vec) { +; CHECK-LABEL: extract_nxv2f16_nxv16f16_2: +; CHECK: # %bb.0: +; CHECK-NEXT: csrr a0, vlenb +; CHECK-NEXT: srli a0, a0, 2 +; CHECK-NEXT: vsetvli a1, zero, e16, m1, ta, ma +; CHECK-NEXT: vslidedown.vx v8, v8, a0 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2f16.nxv16f16( %vec, i64 2) + ret %c +} + +define @extract_nxv2f16_nxv16f16_4( %vec) { +; CHECK-LABEL: extract_nxv2f16_nxv16f16_4: +; CHECK: # %bb.0: +; CHECK-NEXT: vsetivli zero, 1, e8, m1, ta, ma +; CHECK-NEXT: vmv1r.v v8, v9 +; CHECK-NEXT: ret + %c = call @llvm.vector.extract.nxv2f16.nxv16f16( %vec, i64 4) + ret %c +}