diff --git a/llvm/lib/Target/Mips/MipsInstructionSelector.cpp b/llvm/lib/Target/Mips/MipsInstructionSelector.cpp --- a/llvm/lib/Target/Mips/MipsInstructionSelector.cpp +++ b/llvm/lib/Target/Mips/MipsInstructionSelector.cpp @@ -45,6 +45,8 @@ const TargetRegisterClass * getRegClassForTypeOnBank(unsigned OpSize, const RegisterBank &RB, const RegisterBankInfo &RBI) const; + unsigned selectLoadStoreOpCode(MachineInstr &I, + MachineRegisterInfo &MRI) const; const MipsTargetMachine &TM; const MipsSubtarget &STI; @@ -159,9 +161,15 @@ } /// Returning Opc indicates that we failed to select MIPS instruction opcode. -static unsigned selectLoadStoreOpCode(unsigned Opc, unsigned MemSizeInBytes, - unsigned RegBank, bool isFP64) { - bool isStore = Opc == TargetOpcode::G_STORE; +unsigned +MipsInstructionSelector::selectLoadStoreOpCode(MachineInstr &I, + MachineRegisterInfo &MRI) const { + STI.getRegisterInfo(); + const Register DestReg = I.getOperand(0).getReg(); + const unsigned RegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID(); + const unsigned MemSizeInBytes = (*I.memoperands_begin())->getSize(); + unsigned Opc = I.getOpcode(); + const bool isStore = Opc == TargetOpcode::G_STORE; if (RegBank == Mips::GPRBRegBankID) { if (isStore) switch (MemSizeInBytes) { @@ -193,10 +201,24 @@ case 4: return isStore ? Mips::SWC1 : Mips::LWC1; case 8: - if (isFP64) + if (STI.isFP64bit()) return isStore ? Mips::SDC164 : Mips::LDC164; else return isStore ? Mips::SDC1 : Mips::LDC1; + case 16: { + assert(STI.hasMSA() && "Vector instructions require target with MSA."); + const unsigned VectorElementSizeInBytes = + MRI.getType(DestReg).getElementType().getSizeInBytes(); + if (VectorElementSizeInBytes == 1) + return isStore ? Mips::ST_B : Mips::LD_B; + if (VectorElementSizeInBytes == 2) + return isStore ? Mips::ST_H : Mips::LD_H; + if (VectorElementSizeInBytes == 4) + return isStore ? Mips::ST_W : Mips::LD_W; + if (VectorElementSizeInBytes == 8) + return isStore ? Mips::ST_D : Mips::LD_D; + return Opc; + } default: return Opc; } @@ -361,19 +383,7 @@ case G_LOAD: case G_ZEXTLOAD: case G_SEXTLOAD: { - const Register DestReg = I.getOperand(0).getReg(); - const unsigned DestRegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID(); - const unsigned OpSize = MRI.getType(DestReg).getSizeInBits(); - const unsigned OpMemSizeInBytes = (*I.memoperands_begin())->getSize(); - - if (DestRegBank == Mips::GPRBRegBankID && OpSize != 32) - return false; - - if (DestRegBank == Mips::FPRBRegBankID && OpSize != 32 && OpSize != 64) - return false; - - const unsigned NewOpc = selectLoadStoreOpCode( - I.getOpcode(), OpMemSizeInBytes, DestRegBank, STI.isFP64bit()); + const unsigned NewOpc = selectLoadStoreOpCode(I, MRI); if (NewOpc == I.getOpcode()) return false; diff --git a/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp b/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp --- a/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp +++ b/llvm/lib/Target/Mips/MipsLegalizerInfo.cpp @@ -16,12 +16,41 @@ using namespace llvm; +struct TypesAndMemOps { + LLT ValTy; + LLT PtrTy; + unsigned MemSize; + bool MustBeNaturallyAligned; +}; + +static bool +CheckTy0Ty1MemSizeAlign(const LegalityQuery &Query, + std::initializer_list SupportedValues) { + for (auto &Val : SupportedValues) { + if (Val.ValTy != Query.Types[0]) + continue; + if (Val.PtrTy != Query.Types[1]) + continue; + if (Val.MemSize != Query.MMODescrs[0].SizeInBits) + continue; + if (Val.MustBeNaturallyAligned && + Query.MMODescrs[0].SizeInBits % Query.MMODescrs[0].AlignInBits != 0) + continue; + return true; + } + return false; +} + MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) { using namespace TargetOpcode; const LLT s1 = LLT::scalar(1); const LLT s32 = LLT::scalar(32); const LLT s64 = LLT::scalar(64); + const LLT v16s8 = LLT::vector(16, 8); + const LLT v8s16 = LLT::vector(8, 16); + const LLT v4s32 = LLT::vector(4, 32); + const LLT v2s64 = LLT::vector(2, 64); const LLT p0 = LLT::pointer(0, 32); getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL}) @@ -36,11 +65,21 @@ .maxScalar(0, s32); getActionDefinitionsBuilder({G_LOAD, G_STORE}) - .legalForTypesWithMemDesc({{s32, p0, 8, 8}, - {s32, p0, 16, 8}, - {s32, p0, 32, 8}, - {s64, p0, 64, 8}, - {p0, p0, 32, 8}}) + .legalIf([=, &ST](const LegalityQuery &Query) { + if (CheckTy0Ty1MemSizeAlign(Query, {{s32, p0, 8, ST.hasMips32r6()}, + {s32, p0, 16, ST.hasMips32r6()}, + {s32, p0, 32, ST.hasMips32r6()}, + {p0, p0, 32, ST.hasMips32r6()}, + {s64, p0, 64, ST.hasMips32r6()}})) + return true; + if (ST.hasMSA() && + CheckTy0Ty1MemSizeAlign(Query, {{v16s8, p0, 128, false}, + {v8s16, p0, 128, false}, + {v4s32, p0, 128, false}, + {v2s64, p0, 128, false}})) + return true; + return false; + }) .minScalar(0, s32); getActionDefinitionsBuilder(G_IMPLICIT_DEF) diff --git a/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp b/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp --- a/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp +++ b/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp @@ -12,6 +12,7 @@ #include "MipsRegisterBankInfo.h" #include "MipsInstrInfo.h" +#include "MipsTargetMachine.h" #include "llvm/CodeGen/GlobalISel/GISelChangeObserver.h" #include "llvm/CodeGen/GlobalISel/LegalizationArtifactCombiner.h" #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" @@ -27,20 +28,23 @@ PMI_GPR, PMI_SPR, PMI_DPR, + PMI_MSA, PMI_Min = PMI_GPR, }; RegisterBankInfo::PartialMapping PartMappings[]{ {0, 32, GPRBRegBank}, {0, 32, FPRBRegBank}, - {0, 64, FPRBRegBank} + {0, 64, FPRBRegBank}, + {0, 128, FPRBRegBank} }; enum ValueMappingIdx { InvalidIdx = 0, GPRIdx = 1, SPRIdx = 4, - DPRIdx = 7 + DPRIdx = 7, + MSAIdx = 10 }; RegisterBankInfo::ValueMapping ValueMappings[] = { @@ -57,7 +61,11 @@ // up to 3 operands in FPRs - double precission {&PartMappings[PMI_DPR - PMI_Min], 1}, {&PartMappings[PMI_DPR - PMI_Min], 1}, - {&PartMappings[PMI_DPR - PMI_Min], 1} + {&PartMappings[PMI_DPR - PMI_Min], 1}, + // up to 3 operands in FPRs - MSA + {&PartMappings[PMI_MSA - PMI_Min], 1}, + {&PartMappings[PMI_MSA - PMI_Min], 1}, + {&PartMappings[PMI_MSA - PMI_Min], 1} }; } // end namespace Mips @@ -86,6 +94,10 @@ case Mips::FGR32RegClassID: case Mips::FGR64RegClassID: case Mips::AFGR64RegClassID: + case Mips::MSA128BRegClassID: + case Mips::MSA128HRegClassID: + case Mips::MSA128WRegClassID: + case Mips::MSA128DRegClassID: return getRegBank(Mips::FPRBRegBankID); default: llvm_unreachable("Register class not supported"); @@ -355,6 +367,13 @@ } } +static const MipsRegisterBankInfo::ValueMapping * +getMSAMapping(const MachineFunction &MF) { + assert(static_cast(MF.getSubtarget()).hasMSA() && + "MSA mapping not available on target without MSA."); + return &Mips::ValueMappings[Mips::MSAIdx]; +} + static const MipsRegisterBankInfo::ValueMapping *getFprbMapping(unsigned Size) { return Size == 32 ? &Mips::ValueMappings[Mips::SPRIdx] : &Mips::ValueMappings[Mips::DPRIdx]; @@ -406,6 +425,9 @@ if (RegTy.isScalar() && (RegTy.getSizeInBits() != 32 && RegTy.getSizeInBits() != 64)) return getInvalidInstructionMapping(); + + if (RegTy.isVector() && RegTy.getSizeInBits() != 128) + return getInvalidInstructionMapping(); } } @@ -440,6 +462,12 @@ break; case G_STORE: case G_LOAD: + if (Op0Size == 128) { + OperandsMapping = getOperandsMapping( + {getMSAMapping(MF), &Mips::ValueMappings[Mips::GPRIdx]}); + break; + } + if (!Op0Ty.isPointer()) InstTy = TI.determineInstType(&MI); diff --git a/llvm/lib/Target/Mips/MipsRegisterBanks.td b/llvm/lib/Target/Mips/MipsRegisterBanks.td --- a/llvm/lib/Target/Mips/MipsRegisterBanks.td +++ b/llvm/lib/Target/Mips/MipsRegisterBanks.td @@ -11,4 +11,4 @@ def GPRBRegBank : RegisterBank<"GPRB", [GPR32]>; -def FPRBRegBank : RegisterBank<"FPRB", [FGR64, AFGR64]>; +def FPRBRegBank : RegisterBank<"FPRB", [FGR64, AFGR64, MSA128D]>; diff --git a/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/load_store_vec.mir b/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/load_store_vec.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/Mips/GlobalISel/instruction-select/load_store_vec.mir @@ -0,0 +1,156 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -mcpu=mips32r5 -mattr=msa,+fp64 -mattr=nan2008 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=P5600 +--- | + + define void @load_store_v16i8(<16 x i8>* %a, <16 x i8>* %b) { entry: ret void } + define void @load_store_v8i16(<8 x i16>* %a, <8 x i16>* %b) { entry: ret void } + define void @load_store_v4i32(<4 x i32>* %a, <4 x i32>* %b) { entry: ret void } + define void @load_store_v2i64(<2 x i64>* %a, <2 x i64>* %b) { entry: ret void } + define void @load_store_v4f32(<4 x float>* %a, <4 x float>* %b) { entry: ret void } + define void @load_store_v2f64(<2 x double>* %a, <2 x double>* %b) { entry: ret void } + +... +--- +name: load_store_v16i8 +alignment: 4 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; P5600-LABEL: name: load_store_v16i8 + ; P5600: liveins: $a0, $a1 + ; P5600: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; P5600: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1 + ; P5600: [[LD_B:%[0-9]+]]:msa128b = LD_B [[COPY1]], 0 :: (load 16 from %ir.b) + ; P5600: ST_B [[LD_B]], [[COPY]], 0 :: (store 16 into %ir.a) + ; P5600: RetRA + %0:gprb(p0) = COPY $a0 + %1:gprb(p0) = COPY $a1 + %2:fprb(<16 x s8>) = G_LOAD %1(p0) :: (load 16 from %ir.b) + G_STORE %2(<16 x s8>), %0(p0) :: (store 16 into %ir.a) + RetRA + +... +--- +name: load_store_v8i16 +alignment: 4 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; P5600-LABEL: name: load_store_v8i16 + ; P5600: liveins: $a0, $a1 + ; P5600: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; P5600: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1 + ; P5600: [[LD_H:%[0-9]+]]:msa128h = LD_H [[COPY1]], 0 :: (load 16 from %ir.b) + ; P5600: ST_H [[LD_H]], [[COPY]], 0 :: (store 16 into %ir.a) + ; P5600: RetRA + %0:gprb(p0) = COPY $a0 + %1:gprb(p0) = COPY $a1 + %2:fprb(<8 x s16>) = G_LOAD %1(p0) :: (load 16 from %ir.b) + G_STORE %2(<8 x s16>), %0(p0) :: (store 16 into %ir.a) + RetRA + +... +--- +name: load_store_v4i32 +alignment: 4 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; P5600-LABEL: name: load_store_v4i32 + ; P5600: liveins: $a0, $a1 + ; P5600: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; P5600: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1 + ; P5600: [[LD_W:%[0-9]+]]:msa128w = LD_W [[COPY1]], 0 :: (load 16 from %ir.b) + ; P5600: ST_W [[LD_W]], [[COPY]], 0 :: (store 16 into %ir.a) + ; P5600: RetRA + %0:gprb(p0) = COPY $a0 + %1:gprb(p0) = COPY $a1 + %2:fprb(<4 x s32>) = G_LOAD %1(p0) :: (load 16 from %ir.b) + G_STORE %2(<4 x s32>), %0(p0) :: (store 16 into %ir.a) + RetRA + +... +--- +name: load_store_v2i64 +alignment: 4 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; P5600-LABEL: name: load_store_v2i64 + ; P5600: liveins: $a0, $a1 + ; P5600: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; P5600: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1 + ; P5600: [[LD_D:%[0-9]+]]:msa128d = LD_D [[COPY1]], 0 :: (load 16 from %ir.b) + ; P5600: ST_D [[LD_D]], [[COPY]], 0 :: (store 16 into %ir.a) + ; P5600: RetRA + %0:gprb(p0) = COPY $a0 + %1:gprb(p0) = COPY $a1 + %2:fprb(<2 x s64>) = G_LOAD %1(p0) :: (load 16 from %ir.b) + G_STORE %2(<2 x s64>), %0(p0) :: (store 16 into %ir.a) + RetRA + +... +--- +name: load_store_v4f32 +alignment: 4 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; P5600-LABEL: name: load_store_v4f32 + ; P5600: liveins: $a0, $a1 + ; P5600: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; P5600: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1 + ; P5600: [[LD_W:%[0-9]+]]:msa128w = LD_W [[COPY1]], 0 :: (load 16 from %ir.b) + ; P5600: ST_W [[LD_W]], [[COPY]], 0 :: (store 16 into %ir.a) + ; P5600: RetRA + %0:gprb(p0) = COPY $a0 + %1:gprb(p0) = COPY $a1 + %2:fprb(<4 x s32>) = G_LOAD %1(p0) :: (load 16 from %ir.b) + G_STORE %2(<4 x s32>), %0(p0) :: (store 16 into %ir.a) + RetRA + +... +--- +name: load_store_v2f64 +alignment: 4 +legalized: true +regBankSelected: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; P5600-LABEL: name: load_store_v2f64 + ; P5600: liveins: $a0, $a1 + ; P5600: [[COPY:%[0-9]+]]:gpr32 = COPY $a0 + ; P5600: [[COPY1:%[0-9]+]]:gpr32 = COPY $a1 + ; P5600: [[LD_D:%[0-9]+]]:msa128d = LD_D [[COPY1]], 0 :: (load 16 from %ir.b) + ; P5600: ST_D [[LD_D]], [[COPY]], 0 :: (store 16 into %ir.a) + ; P5600: RetRA + %0:gprb(p0) = COPY $a0 + %1:gprb(p0) = COPY $a1 + %2:fprb(<2 x s64>) = G_LOAD %1(p0) :: (load 16 from %ir.b) + G_STORE %2(<2 x s64>), %0(p0) :: (store 16 into %ir.a) + RetRA + +... diff --git a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/load_store_vec.mir b/llvm/test/CodeGen/Mips/GlobalISel/legalizer/load_store_vec.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/Mips/GlobalISel/legalizer/load_store_vec.mir @@ -0,0 +1,144 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -mcpu=mips32r5 -mattr=msa,+fp64 -mattr=nan2008 -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=P5600 +--- | + + define void @load_store_v16i8(<16 x i8>* %a, <16 x i8>* %b) { entry: ret void } + define void @load_store_v8i16(<8 x i16>* %a, <8 x i16>* %b) { entry: ret void } + define void @load_store_v4i32(<4 x i32>* %a, <4 x i32>* %b) { entry: ret void } + define void @load_store_v2i64(<2 x i64>* %a, <2 x i64>* %b) { entry: ret void } + define void @load_store_v4f32(<4 x float>* %a, <4 x float>* %b) { entry: ret void } + define void @load_store_v2f64(<2 x double>* %a, <2 x double>* %b) { entry: ret void } + +... +--- +name: load_store_v16i8 +alignment: 4 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; P5600-LABEL: name: load_store_v16i8 + ; P5600: liveins: $a0, $a1 + ; P5600: [[COPY:%[0-9]+]]:_(p0) = COPY $a0 + ; P5600: [[COPY1:%[0-9]+]]:_(p0) = COPY $a1 + ; P5600: [[LOAD:%[0-9]+]]:_(<16 x s8>) = G_LOAD [[COPY1]](p0) :: (load 16 from %ir.b) + ; P5600: G_STORE [[LOAD]](<16 x s8>), [[COPY]](p0) :: (store 16 into %ir.a) + ; P5600: RetRA + %0:_(p0) = COPY $a0 + %1:_(p0) = COPY $a1 + %2:_(<16 x s8>) = G_LOAD %1(p0) :: (load 16 from %ir.b) + G_STORE %2(<16 x s8>), %0(p0) :: (store 16 into %ir.a) + RetRA + +... +--- +name: load_store_v8i16 +alignment: 4 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; P5600-LABEL: name: load_store_v8i16 + ; P5600: liveins: $a0, $a1 + ; P5600: [[COPY:%[0-9]+]]:_(p0) = COPY $a0 + ; P5600: [[COPY1:%[0-9]+]]:_(p0) = COPY $a1 + ; P5600: [[LOAD:%[0-9]+]]:_(<8 x s16>) = G_LOAD [[COPY1]](p0) :: (load 16 from %ir.b) + ; P5600: G_STORE [[LOAD]](<8 x s16>), [[COPY]](p0) :: (store 16 into %ir.a) + ; P5600: RetRA + %0:_(p0) = COPY $a0 + %1:_(p0) = COPY $a1 + %2:_(<8 x s16>) = G_LOAD %1(p0) :: (load 16 from %ir.b) + G_STORE %2(<8 x s16>), %0(p0) :: (store 16 into %ir.a) + RetRA + +... +--- +name: load_store_v4i32 +alignment: 4 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; P5600-LABEL: name: load_store_v4i32 + ; P5600: liveins: $a0, $a1 + ; P5600: [[COPY:%[0-9]+]]:_(p0) = COPY $a0 + ; P5600: [[COPY1:%[0-9]+]]:_(p0) = COPY $a1 + ; P5600: [[LOAD:%[0-9]+]]:_(<4 x s32>) = G_LOAD [[COPY1]](p0) :: (load 16 from %ir.b) + ; P5600: G_STORE [[LOAD]](<4 x s32>), [[COPY]](p0) :: (store 16 into %ir.a) + ; P5600: RetRA + %0:_(p0) = COPY $a0 + %1:_(p0) = COPY $a1 + %2:_(<4 x s32>) = G_LOAD %1(p0) :: (load 16 from %ir.b) + G_STORE %2(<4 x s32>), %0(p0) :: (store 16 into %ir.a) + RetRA + +... +--- +name: load_store_v2i64 +alignment: 4 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; P5600-LABEL: name: load_store_v2i64 + ; P5600: liveins: $a0, $a1 + ; P5600: [[COPY:%[0-9]+]]:_(p0) = COPY $a0 + ; P5600: [[COPY1:%[0-9]+]]:_(p0) = COPY $a1 + ; P5600: [[LOAD:%[0-9]+]]:_(<2 x s64>) = G_LOAD [[COPY1]](p0) :: (load 16 from %ir.b) + ; P5600: G_STORE [[LOAD]](<2 x s64>), [[COPY]](p0) :: (store 16 into %ir.a) + ; P5600: RetRA + %0:_(p0) = COPY $a0 + %1:_(p0) = COPY $a1 + %2:_(<2 x s64>) = G_LOAD %1(p0) :: (load 16 from %ir.b) + G_STORE %2(<2 x s64>), %0(p0) :: (store 16 into %ir.a) + RetRA + +... +--- +name: load_store_v4f32 +alignment: 4 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; P5600-LABEL: name: load_store_v4f32 + ; P5600: liveins: $a0, $a1 + ; P5600: [[COPY:%[0-9]+]]:_(p0) = COPY $a0 + ; P5600: [[COPY1:%[0-9]+]]:_(p0) = COPY $a1 + ; P5600: [[LOAD:%[0-9]+]]:_(<4 x s32>) = G_LOAD [[COPY1]](p0) :: (load 16 from %ir.b) + ; P5600: G_STORE [[LOAD]](<4 x s32>), [[COPY]](p0) :: (store 16 into %ir.a) + ; P5600: RetRA + %0:_(p0) = COPY $a0 + %1:_(p0) = COPY $a1 + %2:_(<4 x s32>) = G_LOAD %1(p0) :: (load 16 from %ir.b) + G_STORE %2(<4 x s32>), %0(p0) :: (store 16 into %ir.a) + RetRA + +... +--- +name: load_store_v2f64 +alignment: 4 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; P5600-LABEL: name: load_store_v2f64 + ; P5600: liveins: $a0, $a1 + ; P5600: [[COPY:%[0-9]+]]:_(p0) = COPY $a0 + ; P5600: [[COPY1:%[0-9]+]]:_(p0) = COPY $a1 + ; P5600: [[LOAD:%[0-9]+]]:_(<2 x s64>) = G_LOAD [[COPY1]](p0) :: (load 16 from %ir.b) + ; P5600: G_STORE [[LOAD]](<2 x s64>), [[COPY]](p0) :: (store 16 into %ir.a) + ; P5600: RetRA + %0:_(p0) = COPY $a0 + %1:_(p0) = COPY $a1 + %2:_(<2 x s64>) = G_LOAD %1(p0) :: (load 16 from %ir.b) + G_STORE %2(<2 x s64>), %0(p0) :: (store 16 into %ir.a) + RetRA + +... diff --git a/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/load_store_vec.ll b/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/load_store_vec.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/load_store_vec.ll @@ -0,0 +1,80 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -O0 -mtriple=mipsel-linux-gnu -global-isel -mcpu=mips32r5 -mattr=msa,+fp64 -mattr=nan2008 -verify-machineinstrs %s -o -| FileCheck %s -check-prefixes=P5600 + +define void @load_store_v16i8(<16 x i8>* %a, <16 x i8>* %b) { +; P5600-LABEL: load_store_v16i8: +; P5600: # %bb.0: # %entry +; P5600-NEXT: ld.b $w0, 0($5) +; P5600-NEXT: st.b $w0, 0($4) +; P5600-NEXT: jr $ra +; P5600-NEXT: nop +entry: + %0 = load <16 x i8>, <16 x i8>* %b, align 16 + store <16 x i8> %0, <16 x i8>* %a, align 16 + ret void +} + +define void @load_store_v8i16(<8 x i16>* %a, <8 x i16>* %b) { +; P5600-LABEL: load_store_v8i16: +; P5600: # %bb.0: # %entry +; P5600-NEXT: ld.h $w0, 0($5) +; P5600-NEXT: st.h $w0, 0($4) +; P5600-NEXT: jr $ra +; P5600-NEXT: nop +entry: + %0 = load <8 x i16>, <8 x i16>* %b, align 16 + store <8 x i16> %0, <8 x i16>* %a, align 16 + ret void +} + +define void @load_store_v4i32(<4 x i32>* %a, <4 x i32>* %b) { +; P5600-LABEL: load_store_v4i32: +; P5600: # %bb.0: # %entry +; P5600-NEXT: ld.w $w0, 0($5) +; P5600-NEXT: st.w $w0, 0($4) +; P5600-NEXT: jr $ra +; P5600-NEXT: nop +entry: + %0 = load <4 x i32>, <4 x i32>* %b, align 16 + store <4 x i32> %0, <4 x i32>* %a, align 16 + ret void +} + +define void @load_store_v2i64(<2 x i64>* %a, <2 x i64>* %b) { +; P5600-LABEL: load_store_v2i64: +; P5600: # %bb.0: # %entry +; P5600-NEXT: ld.d $w0, 0($5) +; P5600-NEXT: st.d $w0, 0($4) +; P5600-NEXT: jr $ra +; P5600-NEXT: nop +entry: + %0 = load <2 x i64>, <2 x i64>* %b, align 16 + store <2 x i64> %0, <2 x i64>* %a, align 16 + ret void +} + +define void @load_store_v4f32(<4 x float>* %a, <4 x float>* %b) { +; P5600-LABEL: load_store_v4f32: +; P5600: # %bb.0: # %entry +; P5600-NEXT: ld.w $w0, 0($5) +; P5600-NEXT: st.w $w0, 0($4) +; P5600-NEXT: jr $ra +; P5600-NEXT: nop +entry: + %0 = load <4 x float>, <4 x float>* %b, align 16 + store <4 x float> %0, <4 x float>* %a, align 16 + ret void +} + +define void @load_store_v2f64(<2 x double>* %a, <2 x double>* %b) { +; P5600-LABEL: load_store_v2f64: +; P5600: # %bb.0: # %entry +; P5600-NEXT: ld.d $w0, 0($5) +; P5600-NEXT: st.d $w0, 0($4) +; P5600-NEXT: jr $ra +; P5600-NEXT: nop +entry: + %0 = load <2 x double>, <2 x double>* %b, align 16 + store <2 x double> %0, <2 x double>* %a, align 16 + ret void +} diff --git a/llvm/test/CodeGen/Mips/GlobalISel/regbankselect/load_store_vec.mir b/llvm/test/CodeGen/Mips/GlobalISel/regbankselect/load_store_vec.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/Mips/GlobalISel/regbankselect/load_store_vec.mir @@ -0,0 +1,150 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 -mtriple=mipsel-linux-gnu -mcpu=mips32r5 -mattr=msa,+fp64 -mattr=nan2008 -run-pass=regbankselect -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=P5600 +--- | + + define void @load_store_v16i8(<16 x i8>* %a, <16 x i8>* %b) { entry: ret void } + define void @load_store_v8i16(<8 x i16>* %a, <8 x i16>* %b) { entry: ret void } + define void @load_store_v4i32(<4 x i32>* %a, <4 x i32>* %b) { entry: ret void } + define void @load_store_v2i64(<2 x i64>* %a, <2 x i64>* %b) { entry: ret void } + define void @load_store_v4f32(<4 x float>* %a, <4 x float>* %b) { entry: ret void } + define void @load_store_v2f64(<2 x double>* %a, <2 x double>* %b) { entry: ret void } + +... +--- +name: load_store_v16i8 +alignment: 4 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; P5600-LABEL: name: load_store_v16i8 + ; P5600: liveins: $a0, $a1 + ; P5600: [[COPY:%[0-9]+]]:gprb(p0) = COPY $a0 + ; P5600: [[COPY1:%[0-9]+]]:gprb(p0) = COPY $a1 + ; P5600: [[LOAD:%[0-9]+]]:fprb(<16 x s8>) = G_LOAD [[COPY1]](p0) :: (load 16 from %ir.b) + ; P5600: G_STORE [[LOAD]](<16 x s8>), [[COPY]](p0) :: (store 16 into %ir.a) + ; P5600: RetRA + %0:_(p0) = COPY $a0 + %1:_(p0) = COPY $a1 + %2:_(<16 x s8>) = G_LOAD %1(p0) :: (load 16 from %ir.b) + G_STORE %2(<16 x s8>), %0(p0) :: (store 16 into %ir.a) + RetRA + +... +--- +name: load_store_v8i16 +alignment: 4 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; P5600-LABEL: name: load_store_v8i16 + ; P5600: liveins: $a0, $a1 + ; P5600: [[COPY:%[0-9]+]]:gprb(p0) = COPY $a0 + ; P5600: [[COPY1:%[0-9]+]]:gprb(p0) = COPY $a1 + ; P5600: [[LOAD:%[0-9]+]]:fprb(<8 x s16>) = G_LOAD [[COPY1]](p0) :: (load 16 from %ir.b) + ; P5600: G_STORE [[LOAD]](<8 x s16>), [[COPY]](p0) :: (store 16 into %ir.a) + ; P5600: RetRA + %0:_(p0) = COPY $a0 + %1:_(p0) = COPY $a1 + %2:_(<8 x s16>) = G_LOAD %1(p0) :: (load 16 from %ir.b) + G_STORE %2(<8 x s16>), %0(p0) :: (store 16 into %ir.a) + RetRA + +... +--- +name: load_store_v4i32 +alignment: 4 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; P5600-LABEL: name: load_store_v4i32 + ; P5600: liveins: $a0, $a1 + ; P5600: [[COPY:%[0-9]+]]:gprb(p0) = COPY $a0 + ; P5600: [[COPY1:%[0-9]+]]:gprb(p0) = COPY $a1 + ; P5600: [[LOAD:%[0-9]+]]:fprb(<4 x s32>) = G_LOAD [[COPY1]](p0) :: (load 16 from %ir.b) + ; P5600: G_STORE [[LOAD]](<4 x s32>), [[COPY]](p0) :: (store 16 into %ir.a) + ; P5600: RetRA + %0:_(p0) = COPY $a0 + %1:_(p0) = COPY $a1 + %2:_(<4 x s32>) = G_LOAD %1(p0) :: (load 16 from %ir.b) + G_STORE %2(<4 x s32>), %0(p0) :: (store 16 into %ir.a) + RetRA + +... +--- +name: load_store_v2i64 +alignment: 4 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; P5600-LABEL: name: load_store_v2i64 + ; P5600: liveins: $a0, $a1 + ; P5600: [[COPY:%[0-9]+]]:gprb(p0) = COPY $a0 + ; P5600: [[COPY1:%[0-9]+]]:gprb(p0) = COPY $a1 + ; P5600: [[LOAD:%[0-9]+]]:fprb(<2 x s64>) = G_LOAD [[COPY1]](p0) :: (load 16 from %ir.b) + ; P5600: G_STORE [[LOAD]](<2 x s64>), [[COPY]](p0) :: (store 16 into %ir.a) + ; P5600: RetRA + %0:_(p0) = COPY $a0 + %1:_(p0) = COPY $a1 + %2:_(<2 x s64>) = G_LOAD %1(p0) :: (load 16 from %ir.b) + G_STORE %2(<2 x s64>), %0(p0) :: (store 16 into %ir.a) + RetRA + +... +--- +name: load_store_v4f32 +alignment: 4 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; P5600-LABEL: name: load_store_v4f32 + ; P5600: liveins: $a0, $a1 + ; P5600: [[COPY:%[0-9]+]]:gprb(p0) = COPY $a0 + ; P5600: [[COPY1:%[0-9]+]]:gprb(p0) = COPY $a1 + ; P5600: [[LOAD:%[0-9]+]]:fprb(<4 x s32>) = G_LOAD [[COPY1]](p0) :: (load 16 from %ir.b) + ; P5600: G_STORE [[LOAD]](<4 x s32>), [[COPY]](p0) :: (store 16 into %ir.a) + ; P5600: RetRA + %0:_(p0) = COPY $a0 + %1:_(p0) = COPY $a1 + %2:_(<4 x s32>) = G_LOAD %1(p0) :: (load 16 from %ir.b) + G_STORE %2(<4 x s32>), %0(p0) :: (store 16 into %ir.a) + RetRA + +... +--- +name: load_store_v2f64 +alignment: 4 +legalized: true +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $a0, $a1 + + ; P5600-LABEL: name: load_store_v2f64 + ; P5600: liveins: $a0, $a1 + ; P5600: [[COPY:%[0-9]+]]:gprb(p0) = COPY $a0 + ; P5600: [[COPY1:%[0-9]+]]:gprb(p0) = COPY $a1 + ; P5600: [[LOAD:%[0-9]+]]:fprb(<2 x s64>) = G_LOAD [[COPY1]](p0) :: (load 16 from %ir.b) + ; P5600: G_STORE [[LOAD]](<2 x s64>), [[COPY]](p0) :: (store 16 into %ir.a) + ; P5600: RetRA + %0:_(p0) = COPY $a0 + %1:_(p0) = COPY $a1 + %2:_(<2 x s64>) = G_LOAD %1(p0) :: (load 16 from %ir.b) + G_STORE %2(<2 x s64>), %0(p0) :: (store 16 into %ir.a) + RetRA + +...