diff options
| author | Krzysztof Parzyszek <kparzysz@codeaurora.org> | 2018-02-14 20:46:06 +0000 |
|---|---|---|
| committer | Krzysztof Parzyszek <kparzysz@codeaurora.org> | 2018-02-14 20:46:06 +0000 |
| commit | ad83ce4cb45771aecd4ed916abe368787da55b72 (patch) | |
| tree | 104cd6bb2cd84d25a020d10c44f3815456f54816 /llvm/lib/Target/Hexagon | |
| parent | 668664889c790227fef496bffcbe6b21eb33007b (diff) | |
| download | bcm5719-llvm-ad83ce4cb45771aecd4ed916abe368787da55b72.tar.gz bcm5719-llvm-ad83ce4cb45771aecd4ed916abe368787da55b72.zip | |
[Hexagon] Split HVX vector pair loads/stores, expand unaligned loads
llvm-svn: 325169
Diffstat (limited to 'llvm/lib/Target/Hexagon')
| -rw-r--r-- | llvm/lib/Target/Hexagon/HexagonISelLowering.cpp | 11 | ||||
| -rw-r--r-- | llvm/lib/Target/Hexagon/HexagonISelLowering.h | 5 | ||||
| -rw-r--r-- | llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp | 139 | ||||
| -rw-r--r-- | llvm/lib/Target/Hexagon/HexagonPatterns.td | 27 | ||||
| -rw-r--r-- | llvm/lib/Target/Hexagon/HexagonPatternsHVX.td | 125 |
5 files changed, 222 insertions, 85 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp index e0078221b5e..fd99a8fd0f0 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp +++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.cpp @@ -1727,6 +1727,7 @@ const char* HexagonTargetLowering::getTargetNodeName(unsigned Opcode) const { case HexagonISD::QTRUE: return "HexagonISD::QTRUE"; case HexagonISD::QFALSE: return "HexagonISD::QFALSE"; case HexagonISD::TYPECAST: return "HexagonISD::TYPECAST"; + case HexagonISD::VALIGNADDR: return "HexagonISD::VALIGNADDR"; case HexagonISD::OP_END: break; } return nullptr; @@ -1821,6 +1822,16 @@ HexagonTargetLowering::getPreferredVectorAction(EVT VT) const { return TargetLoweringBase::TypeSplitVector; } +std::pair<SDValue, int> +HexagonTargetLowering::getBaseAndOffset(SDValue Addr) const { + if (Addr.getOpcode() == ISD::ADD) { + SDValue Op1 = Addr.getOperand(1); + if (auto *CN = dyn_cast<const ConstantSDNode>(Op1.getNode())) + return { Addr.getOperand(0), CN->getSExtValue() }; + } + return { Addr, 0 }; +} + // Lower a vector shuffle (V1, V2, V3). V1 and V2 are the two vectors // to select data from, V3 is the permutation. SDValue diff --git a/llvm/lib/Target/Hexagon/HexagonISelLowering.h b/llvm/lib/Target/Hexagon/HexagonISelLowering.h index a57acec8204..8ba08564547 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelLowering.h +++ b/llvm/lib/Target/Hexagon/HexagonISelLowering.h @@ -79,6 +79,8 @@ namespace HexagonISD { VZERO, TYPECAST, // No-op that's used to convert between different legal // types in a register. + VALIGNADDR, // Align vector address: Op & -HwLen, except when it is + // an address in a vector load, then it's a no-op. OP_END }; @@ -299,6 +301,7 @@ namespace HexagonISD { private: void initializeHVXLowering(); + std::pair<SDValue,int> getBaseAndOffset(SDValue Addr) const; bool getBuildVectorConstInts(ArrayRef<SDValue> Values, MVT VecTy, SelectionDAG &DAG, @@ -415,8 +418,10 @@ namespace HexagonISD { SDValue LowerHvxSetCC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerHvxExtend(SDValue Op, SelectionDAG &DAG) const; SDValue LowerHvxShift(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerHvxUnalignedLoad(SDValue Op, SelectionDAG &DAG) const; SDValue SplitHvxPairOp(SDValue Op, SelectionDAG &DAG) const; + SDValue SplitHvxMemOp(SDValue Op, SelectionDAG &DAG) const; std::pair<const TargetRegisterClass*, uint8_t> findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT) diff --git a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp index 4b732171805..b9e285131b3 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp +++ b/llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp @@ -10,9 +10,14 @@ #include "HexagonISelLowering.h" #include "HexagonRegisterInfo.h" #include "HexagonSubtarget.h" +#include "llvm/Support/CommandLine.h" using namespace llvm; +static cl::opt<bool> ExpandUnalignedLoads("hvx-expand-unaligned-loads", + cl::Hidden, cl::init(true), + cl::desc("Expand unaligned HVX loads into a pair of aligned loads")); + static const MVT LegalV64[] = { MVT::v64i8, MVT::v32i16, MVT::v16i32 }; static const MVT LegalW64[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 }; static const MVT LegalV128[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 }; @@ -83,6 +88,7 @@ HexagonTargetLowering::initializeHVXLowering() { setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, T, Legal); } + setOperationAction(ISD::LOAD, T, Custom); setOperationAction(ISD::MUL, T, Custom); setOperationAction(ISD::MULHS, T, Custom); setOperationAction(ISD::MULHU, T, Custom); @@ -151,6 +157,9 @@ HexagonTargetLowering::initializeHVXLowering() { setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, T, Legal); setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, T, Legal); + setOperationAction(ISD::LOAD, T, Custom); + setOperationAction(ISD::STORE, T, Custom); + setOperationAction(ISD::ADD, T, Legal); setOperationAction(ISD::SUB, T, Legal); setOperationAction(ISD::MUL, T, Custom); @@ -1287,6 +1296,59 @@ HexagonTargetLowering::LowerHvxShift(SDValue Op, SelectionDAG &DAG) const { } SDValue +HexagonTargetLowering::LowerHvxUnalignedLoad(SDValue Op, SelectionDAG &DAG) + const { + LoadSDNode *LN = cast<LoadSDNode>(Op.getNode()); + unsigned HaveAlign = LN->getAlignment(); + MVT VecTy = ty(Op); + Type *Ty = EVT(VecTy).getTypeForEVT(*DAG.getContext()); + const DataLayout &DL = DAG.getDataLayout(); + unsigned NeedAlign = DL.getABITypeAlignment(Ty); + if (HaveAlign >= NeedAlign || !ExpandUnalignedLoads) + return Op; + + unsigned HwLen = Subtarget.getVectorLength(); + + SDValue Base = LN->getBasePtr(); + SDValue Chain = LN->getChain(); + auto BO = getBaseAndOffset(Base); + unsigned BaseOpc = BO.first.getOpcode(); + if (BaseOpc == HexagonISD::VALIGNADDR && BO.second % HwLen == 0) + return Op; + + const SDLoc &dl(Op); + if (BO.second % HwLen != 0) { + BO.first = DAG.getNode(ISD::ADD, dl, MVT::i32, BO.first, + DAG.getConstant(BO.second % HwLen, dl, MVT::i32)); + BO.second -= BO.second % HwLen; + } + SDValue BaseNoOff = (BaseOpc != HexagonISD::VALIGNADDR) + ? DAG.getNode(HexagonISD::VALIGNADDR, dl, MVT::i32, BO.first) + : BO.first; + SDValue Base0 = DAG.getMemBasePlusOffset(BaseNoOff, BO.second, dl); + SDValue Base1 = DAG.getMemBasePlusOffset(BaseNoOff, BO.second+HwLen, dl); + + MachineMemOperand *WideMMO = nullptr; + if (MachineMemOperand *MMO = LN->getMemOperand()) { + MachineFunction &MF = DAG.getMachineFunction(); + WideMMO = MF.getMachineMemOperand(MMO->getPointerInfo(), MMO->getFlags(), + 2*HwLen, HwLen, MMO->getAAInfo(), MMO->getRanges(), + MMO->getSyncScopeID(), MMO->getOrdering(), + MMO->getFailureOrdering()); + } + + SDValue Load0 = DAG.getLoad(VecTy, dl, Chain, Base0, WideMMO); + SDValue Load1 = DAG.getLoad(VecTy, dl, Chain, Base1, WideMMO); + + SDValue Aligned = getInstr(Hexagon::V6_valignb, dl, VecTy, + {Load1, Load0, BaseNoOff.getOperand(0)}, DAG); + SDValue NewChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + Load0.getValue(1), Load1.getValue(1)); + SDValue M = DAG.getMergeValues({Aligned, NewChain}, dl); + return M; +} + +SDValue HexagonTargetLowering::SplitHvxPairOp(SDValue Op, SelectionDAG &DAG) const { assert(!Op.isMachineOpcode()); SmallVector<SDValue,2> OpsL, OpsH; @@ -1320,6 +1382,49 @@ HexagonTargetLowering::SplitHvxPairOp(SDValue Op, SelectionDAG &DAG) const { } SDValue +HexagonTargetLowering::SplitHvxMemOp(SDValue Op, SelectionDAG &DAG) const { + LSBaseSDNode *BN = cast<LSBaseSDNode>(Op.getNode()); + assert(BN->isUnindexed()); + MVT MemTy = BN->getMemoryVT().getSimpleVT(); + if (!isHvxPairTy(MemTy)) + return Op; + + const SDLoc &dl(Op); + unsigned HwLen = Subtarget.getVectorLength(); + MVT SingleTy = typeSplit(MemTy).first; + SDValue Chain = BN->getChain(); + SDValue Base0 = BN->getBasePtr(); + SDValue Base1 = DAG.getMemBasePlusOffset(Base0, HwLen, dl); + + MachineMemOperand *MOp0 = nullptr, *MOp1 = nullptr; + if (MachineMemOperand *MMO = BN->getMemOperand()) { + MachineFunction &MF = DAG.getMachineFunction(); + MOp0 = MF.getMachineMemOperand(MMO, 0, HwLen); + MOp1 = MF.getMachineMemOperand(MMO, HwLen, HwLen); + } + + unsigned MemOpc = BN->getOpcode(); + SDValue NewOp; + + if (MemOpc == ISD::LOAD) { + SDValue Load0 = DAG.getLoad(SingleTy, dl, Chain, Base0, MOp0); + SDValue Load1 = DAG.getLoad(SingleTy, dl, Chain, Base1, MOp1); + NewOp = DAG.getMergeValues( + { DAG.getNode(ISD::CONCAT_VECTORS, dl, MemTy, Load0, Load1), + DAG.getNode(ISD::TokenFactor, dl, MVT::Other, + Load0.getValue(1), Load1.getValue(1)) }, dl); + } else { + assert(MemOpc == ISD::STORE); + VectorPair Vals = opSplit(cast<StoreSDNode>(Op)->getValue(), dl, DAG); + SDValue Store0 = DAG.getStore(Chain, dl, Vals.first, Base0, MOp0); + SDValue Store1 = DAG.getStore(Chain, dl, Vals.second, Base1, MOp1); + NewOp = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Store0, Store1); + } + + return NewOp; +} + +SDValue HexagonTargetLowering::LowerHvxOperation(SDValue Op, SelectionDAG &DAG) const { unsigned Opc = Op.getOpcode(); bool IsPairOp = isHvxPairTy(ty(Op)) || @@ -1331,6 +1436,9 @@ HexagonTargetLowering::LowerHvxOperation(SDValue Op, SelectionDAG &DAG) const { switch (Opc) { default: break; + case ISD::LOAD: + case ISD::STORE: + return SplitHvxMemOp(Op, DAG); case ISD::MUL: case ISD::MULHS: case ISD::MULHU: @@ -1350,25 +1458,26 @@ HexagonTargetLowering::LowerHvxOperation(SDValue Op, SelectionDAG &DAG) const { switch (Opc) { default: break; - case ISD::BUILD_VECTOR: return LowerHvxBuildVector(Op, DAG); - case ISD::CONCAT_VECTORS: return LowerHvxConcatVectors(Op, DAG); - case ISD::INSERT_SUBVECTOR: return LowerHvxInsertSubvector(Op, DAG); - case ISD::INSERT_VECTOR_ELT: return LowerHvxInsertElement(Op, DAG); - case ISD::EXTRACT_SUBVECTOR: return LowerHvxExtractSubvector(Op, DAG); - case ISD::EXTRACT_VECTOR_ELT: return LowerHvxExtractElement(Op, DAG); - - case ISD::ANY_EXTEND: return LowerHvxAnyExt(Op, DAG); - case ISD::SIGN_EXTEND: return LowerHvxSignExt(Op, DAG); - case ISD::ZERO_EXTEND: return LowerHvxZeroExt(Op, DAG); + case ISD::BUILD_VECTOR: return LowerHvxBuildVector(Op, DAG); + case ISD::CONCAT_VECTORS: return LowerHvxConcatVectors(Op, DAG); + case ISD::INSERT_SUBVECTOR: return LowerHvxInsertSubvector(Op, DAG); + case ISD::INSERT_VECTOR_ELT: return LowerHvxInsertElement(Op, DAG); + case ISD::EXTRACT_SUBVECTOR: return LowerHvxExtractSubvector(Op, DAG); + case ISD::EXTRACT_VECTOR_ELT: return LowerHvxExtractElement(Op, DAG); + + case ISD::LOAD: return LowerHvxUnalignedLoad(Op, DAG); + case ISD::ANY_EXTEND: return LowerHvxAnyExt(Op, DAG); + case ISD::SIGN_EXTEND: return LowerHvxSignExt(Op, DAG); + case ISD::ZERO_EXTEND: return LowerHvxZeroExt(Op, DAG); case ISD::SRA: case ISD::SHL: - case ISD::SRL: return LowerHvxShift(Op, DAG); - case ISD::MUL: return LowerHvxMul(Op, DAG); + case ISD::SRL: return LowerHvxShift(Op, DAG); + case ISD::MUL: return LowerHvxMul(Op, DAG); case ISD::MULHS: - case ISD::MULHU: return LowerHvxMulh(Op, DAG); - case ISD::ANY_EXTEND_VECTOR_INREG: return LowerHvxExtend(Op, DAG); + case ISD::MULHU: return LowerHvxMulh(Op, DAG); + case ISD::ANY_EXTEND_VECTOR_INREG: return LowerHvxExtend(Op, DAG); case ISD::SETCC: - case ISD::INTRINSIC_VOID: return Op; + case ISD::INTRINSIC_VOID: return Op; } #ifndef NDEBUG Op.dumpr(&DAG); diff --git a/llvm/lib/Target/Hexagon/HexagonPatterns.td b/llvm/lib/Target/Hexagon/HexagonPatterns.td index 6559881c59f..70969e283c0 100644 --- a/llvm/lib/Target/Hexagon/HexagonPatterns.td +++ b/llvm/lib/Target/Hexagon/HexagonPatterns.td @@ -109,16 +109,6 @@ def IsOrAdd: PatFrag<(ops node:$A, node:$B), (or node:$A, node:$B), [{ return isOrEquivalentToAdd(N); }]>; -def IsVecOff : PatLeaf<(i32 imm), [{ - int32_t V = N->getSExtValue(); - int32_t VecSize = HRI->getSpillSize(Hexagon::HvxVRRegClass); - assert(isPowerOf2_32(VecSize)); - if ((uint32_t(V) & (uint32_t(VecSize)-1)) != 0) - return false; - int32_t L = Log2_32(VecSize); - return isInt<4>(V >> L); -}]>; - def IsPow2_32: PatLeaf<(i32 imm), [{ uint32_t V = N->getZExtValue(); return isPowerOf2_32(V); @@ -249,23 +239,6 @@ def: Pat<(IsOrAdd (i32 AddrFI:$Rs), s32_0ImmPred:$off), (PS_fi (i32 AddrFI:$Rs), imm:$off)>; -def alignedload: PatFrag<(ops node:$a), (load $a), [{ - return isAlignedMemNode(dyn_cast<MemSDNode>(N)); -}]>; - -def unalignedload: PatFrag<(ops node:$a), (load $a), [{ - return !isAlignedMemNode(dyn_cast<MemSDNode>(N)); -}]>; - -def alignedstore: PatFrag<(ops node:$v, node:$a), (store $v, $a), [{ - return isAlignedMemNode(dyn_cast<MemSDNode>(N)); -}]>; - -def unalignedstore: PatFrag<(ops node:$v, node:$a), (store $v, $a), [{ - return !isAlignedMemNode(dyn_cast<MemSDNode>(N)); -}]>; - - // Converters from unary/binary SDNode to PatFrag. class pf1<SDNode Op> : PatFrag<(ops node:$a), (Op node:$a)>; class pf2<SDNode Op> : PatFrag<(ops node:$a, node:$b), (Op node:$a, node:$b)>; diff --git a/llvm/lib/Target/Hexagon/HexagonPatternsHVX.td b/llvm/lib/Target/Hexagon/HexagonPatternsHVX.td index 50081799bf7..a3dc8d3dabc 100644 --- a/llvm/lib/Target/Hexagon/HexagonPatternsHVX.td +++ b/llvm/lib/Target/Hexagon/HexagonPatternsHVX.td @@ -16,6 +16,12 @@ def HwLen2: SDNodeXForm<imm, [{ return CurDAG->getTargetConstant(ST.getVectorLength()/2, SDLoc(N), MVT::i32); }]>; +def NHwLen: SDNodeXForm<imm, [{ + const auto &ST = static_cast<const HexagonSubtarget&>(CurDAG->getSubtarget()); + return CurDAG->getTargetConstant(-int(ST.getVectorLength()), SDLoc(N), + MVT::i32); +}]>; + def Q2V: OutPatFrag<(ops node:$Qs), (V6_vandqrt $Qs, (A2_tfrsi -1))>; def Combinev: OutPatFrag<(ops node:$Vs, node:$Vt), @@ -32,10 +38,12 @@ def Combineq: OutPatFrag<(ops node:$Qs, node:$Qt), def LoVec: OutPatFrag<(ops node:$Vs), (EXTRACT_SUBREG $Vs, vsub_lo)>; def HiVec: OutPatFrag<(ops node:$Vs), (EXTRACT_SUBREG $Vs, vsub_hi)>; -def HexagonVZERO: SDNode<"HexagonISD::VZERO", SDTVecLeaf>; -def HexagonQCAT: SDNode<"HexagonISD::QCAT", SDTVecBinOp>; -def HexagonQTRUE: SDNode<"HexagonISD::QTRUE", SDTVecLeaf>; -def HexagonQFALSE: SDNode<"HexagonISD::QFALSE", SDTVecLeaf>; +def HexagonVZERO: SDNode<"HexagonISD::VZERO", SDTVecLeaf>; +def HexagonQCAT: SDNode<"HexagonISD::QCAT", SDTVecBinOp>; +def HexagonQTRUE: SDNode<"HexagonISD::QTRUE", SDTVecLeaf>; +def HexagonQFALSE: SDNode<"HexagonISD::QFALSE", SDTVecLeaf>; +def HexagonVALIGNADDR: SDNode<"HexagonISD::VALIGNADDR", SDTIntUnaryOp>; + def vzero: PatFrag<(ops), (HexagonVZERO)>; def qtrue: PatFrag<(ops), (HexagonQTRUE)>; def qfalse: PatFrag<(ops), (HexagonQFALSE)>; @@ -43,6 +51,7 @@ def qcat: PatFrag<(ops node:$Qs, node:$Qt), (HexagonQCAT node:$Qs, node:$Qt)>; def qnot: PatFrag<(ops node:$Qs), (xor node:$Qs, qtrue)>; +def valignaddr: PatFrag<(ops node:$Addr), (HexagonVALIGNADDR node:$Addr)>; def VSxtb: OutPatFrag<(ops node:$Vs), (V6_vunpackb $Vs)>; def VSxth: OutPatFrag<(ops node:$Vs), (V6_vunpackh $Vs)>; @@ -62,41 +71,75 @@ def SplatH: SDNodeXForm<imm, [{ return CurDAG->getTargetConstant(V << 16 | V, SDLoc(N), MVT::i32); }]>; +def IsVecOff : PatLeaf<(i32 imm), [{ + int32_t V = N->getSExtValue(); + int32_t VecSize = HRI->getSpillSize(Hexagon::HvxVRRegClass); + assert(isPowerOf2_32(VecSize)); + if ((uint32_t(V) & (uint32_t(VecSize)-1)) != 0) + return false; + int32_t L = Log2_32(VecSize); + return isInt<4>(V >> L); +}]>; + + +def alignedload: PatFrag<(ops node:$a), (load $a), [{ + return isAlignedMemNode(dyn_cast<MemSDNode>(N)); +}]>; + +def unalignedload: PatFrag<(ops node:$a), (load $a), [{ + return !isAlignedMemNode(dyn_cast<MemSDNode>(N)); +}]>; + +def alignedstore: PatFrag<(ops node:$v, node:$a), (store $v, $a), [{ + return isAlignedMemNode(dyn_cast<MemSDNode>(N)); +}]>; + +def unalignedstore: PatFrag<(ops node:$v, node:$a), (store $v, $a), [{ + return !isAlignedMemNode(dyn_cast<MemSDNode>(N)); +}]>; + // HVX loads -multiclass HvxLd_pat<InstHexagon MI, PatFrag Load, ValueType VT, +multiclass HvxLd_pat<InstHexagon MI, PatFrag Load, ValueType ResType, PatFrag ImmPred> { - def: Pat<(VT (Load I32:$Rt)), (MI I32:$Rt, 0)>; - def: Pat<(VT (Load (add I32:$Rt, ImmPred:$s))), (MI I32:$Rt, imm:$s)>; + def: Pat<(ResType (Load I32:$Rt)), + (MI I32:$Rt, 0)>; + def: Pat<(ResType (Load (add I32:$Rt, ImmPred:$s))), + (MI I32:$Rt, imm:$s)>; // The HVX selection code for shuffles can generate vector constants. // Calling "Select" on the resulting loads from CP fails without these // patterns. - def: Pat<(VT (Load (HexagonCP tconstpool:$A))), (MI (A2_tfrsi imm:$A), 0)>; - def: Pat<(VT (Load (HexagonAtPcrel tconstpool:$A))), + def: Pat<(ResType (Load (HexagonCP tconstpool:$A))), + (MI (A2_tfrsi imm:$A), 0)>; + def: Pat<(ResType (Load (HexagonAtPcrel tconstpool:$A))), (MI (C4_addipc imm:$A), 0)>; } -let Predicates = [UseHVX] in { - multiclass HvxLdVs_pat<InstHexagon MI, PatFrag Load> { - defm: HvxLd_pat<MI, Load, VecI8, IsVecOff>; - defm: HvxLd_pat<MI, Load, VecI16, IsVecOff>; - defm: HvxLd_pat<MI, Load, VecI32, IsVecOff>; - } - defm: HvxLdVs_pat<V6_vL32b_nt_ai, alignednontemporalload>; - defm: HvxLdVs_pat<V6_vL32b_ai, alignedload>; - defm: HvxLdVs_pat<V6_vL32Ub_ai, unalignedload>; - - multiclass HvxLdWs_pat<InstHexagon MI, PatFrag Load> { - defm: HvxLd_pat<MI, Load, VecPI8, IsVecOff>; - defm: HvxLd_pat<MI, Load, VecPI16, IsVecOff>; - defm: HvxLd_pat<MI, Load, VecPI32, IsVecOff>; +multiclass HvxLda_pat<InstHexagon MI, PatFrag Load, ValueType ResType, + PatFrag ImmPred> { + let AddedComplexity = 50 in { + def: Pat<(ResType (Load (valignaddr I32:$Rt))), + (MI I32:$Rt, 0)>; + def: Pat<(ResType (Load (add (valignaddr I32:$Rt), ImmPred:$Off))), + (MI I32:$Rt, imm:$Off)>; } - defm: HvxLdWs_pat<PS_vloadrw_nt_ai, alignednontemporalload>; - defm: HvxLdWs_pat<PS_vloadrw_ai, alignedload>; - defm: HvxLdWs_pat<PS_vloadrwu_ai, unalignedload>; + defm: HvxLd_pat<MI, Load, ResType, ImmPred>; } +let Predicates = [UseHVX] in { + defm: HvxLda_pat<V6_vL32b_nt_ai, alignednontemporalload, VecI8, IsVecOff>; + defm: HvxLda_pat<V6_vL32b_nt_ai, alignednontemporalload, VecI16, IsVecOff>; + defm: HvxLda_pat<V6_vL32b_nt_ai, alignednontemporalload, VecI32, IsVecOff>; + + defm: HvxLda_pat<V6_vL32b_ai, alignedload, VecI8, IsVecOff>; + defm: HvxLda_pat<V6_vL32b_ai, alignedload, VecI16, IsVecOff>; + defm: HvxLda_pat<V6_vL32b_ai, alignedload, VecI32, IsVecOff>; + + defm: HvxLd_pat<V6_vL32Ub_ai, unalignedload, VecI8, IsVecOff>; + defm: HvxLd_pat<V6_vL32Ub_ai, unalignedload, VecI16, IsVecOff>; + defm: HvxLd_pat<V6_vL32Ub_ai, unalignedload, VecI32, IsVecOff>; +} // HVX stores @@ -109,23 +152,17 @@ multiclass HvxSt_pat<InstHexagon MI, PatFrag Store, PatFrag ImmPred, } let Predicates = [UseHVX] in { - multiclass HvxStVs_pat<InstHexagon MI, PatFrag Store> { - defm: HvxSt_pat<MI, Store, IsVecOff, HVI8>; - defm: HvxSt_pat<MI, Store, IsVecOff, HVI16>; - defm: HvxSt_pat<MI, Store, IsVecOff, HVI32>; - } - defm: HvxStVs_pat<V6_vS32b_nt_ai, alignednontemporalstore>; - defm: HvxStVs_pat<V6_vS32b_ai, alignedstore>; - defm: HvxStVs_pat<V6_vS32Ub_ai, unalignedstore>; - - multiclass HvxStWs_pat<InstHexagon MI, PatFrag Store> { - defm: HvxSt_pat<MI, Store, IsVecOff, HWI8>; - defm: HvxSt_pat<MI, Store, IsVecOff, HWI16>; - defm: HvxSt_pat<MI, Store, IsVecOff, HWI32>; - } - defm: HvxStWs_pat<PS_vstorerw_nt_ai, alignednontemporalstore>; - defm: HvxStWs_pat<PS_vstorerw_ai, alignedstore>; - defm: HvxStWs_pat<PS_vstorerwu_ai, unalignedstore>; + defm: HvxSt_pat<V6_vS32b_nt_ai, alignednontemporalstore, IsVecOff, HVI8>; + defm: HvxSt_pat<V6_vS32b_nt_ai, alignednontemporalstore, IsVecOff, HVI16>; + defm: HvxSt_pat<V6_vS32b_nt_ai, alignednontemporalstore, IsVecOff, HVI32>; + + defm: HvxSt_pat<V6_vS32b_ai, alignedstore, IsVecOff, HVI8>; + defm: HvxSt_pat<V6_vS32b_ai, alignedstore, IsVecOff, HVI16>; + defm: HvxSt_pat<V6_vS32b_ai, alignedstore, IsVecOff, HVI32>; + + defm: HvxSt_pat<V6_vS32Ub_ai, unalignedstore, IsVecOff, HVI8>; + defm: HvxSt_pat<V6_vS32Ub_ai, unalignedstore, IsVecOff, HVI16>; + defm: HvxSt_pat<V6_vS32Ub_ai, unalignedstore, IsVecOff, HVI32>; } @@ -138,6 +175,8 @@ let Predicates = [UseHVX] in { def: Pat<(VecPI16 vzero), (Combinev (V6_vd0), (V6_vd0))>; def: Pat<(VecPI32 vzero), (Combinev (V6_vd0), (V6_vd0))>; + def: Pat<(valignaddr I32:$Rs), (A2_andir I32:$Rs, (NHwLen (i32 0)))>; + def: Pat<(VecPI8 (concat_vectors HVI8:$Vs, HVI8:$Vt)), (Combinev HvxVR:$Vt, HvxVR:$Vs)>; def: Pat<(VecPI16 (concat_vectors HVI16:$Vs, HVI16:$Vt)), |

