[llvm] r325169 - [Hexagon] Split HVX vector pair loads/stores, expand unaligned loads
Krzysztof Parzyszek via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 14 12:46:06 PST 2018
Author: kparzysz
Date: Wed Feb 14 12:46:06 2018
New Revision: 325169
URL: http://llvm.org/viewvc/llvm-project?rev=325169&view=rev
Log:
[Hexagon] Split HVX vector pair loads/stores, expand unaligned loads
Added:
llvm/trunk/test/CodeGen/Hexagon/autohvx/isel-expand-unaligned-loads.ll
Modified:
llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp
llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.h
llvm/trunk/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
llvm/trunk/lib/Target/Hexagon/HexagonPatterns.td
llvm/trunk/lib/Target/Hexagon/HexagonPatternsHVX.td
llvm/trunk/test/CodeGen/Hexagon/select-instr-align.ll
Modified: llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp?rev=325169&r1=325168&r2=325169&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp Wed Feb 14 12:46:06 2018
@@ -1727,6 +1727,7 @@ const char* HexagonTargetLowering::getTa
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::getPreferredVecto
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
Modified: llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.h?rev=325169&r1=325168&r2=325169&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.h (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.h Wed Feb 14 12:46:06 2018
@@ -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)
Modified: llvm/trunk/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp?rev=325169&r1=325168&r2=325169&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp Wed Feb 14 12:46:06 2018
@@ -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::initializeHVXLowe
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::initializeHVXLowe
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(SDV
}
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(SD
}
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
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
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);
Modified: llvm/trunk/lib/Target/Hexagon/HexagonPatterns.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonPatterns.td?rev=325169&r1=325168&r2=325169&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonPatterns.td (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonPatterns.td Wed Feb 14 12:46:06 2018
@@ -109,16 +109,6 @@ def IsOrAdd: PatFrag<(ops node:$A, node:
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_
(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)>;
Modified: llvm/trunk/lib/Target/Hexagon/HexagonPatternsHVX.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonPatternsHVX.td?rev=325169&r1=325168&r2=325169&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonPatternsHVX.td (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonPatternsHVX.td Wed Feb 14 12:46:06 2018
@@ -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,
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:
(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, Pat
}
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)),
Added: llvm/trunk/test/CodeGen/Hexagon/autohvx/isel-expand-unaligned-loads.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Hexagon/autohvx/isel-expand-unaligned-loads.ll?rev=325169&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Hexagon/autohvx/isel-expand-unaligned-loads.ll (added)
+++ llvm/trunk/test/CodeGen/Hexagon/autohvx/isel-expand-unaligned-loads.ll Wed Feb 14 12:46:06 2018
@@ -0,0 +1,26 @@
+; RUN: llc -march=hexagon -disable-packetizer < %s | FileCheck %s
+
+; CHECK-LABEL: test_00:
+; CHECK-DAG: v[[V00:[0-9]+]] = vmem(r[[B00:[0-9]+]]+#0)
+; CHECK-DAG: v[[V01:[0-9]+]] = vmem(r[[B00]]+#1)
+; CHECK: valign(v[[V01]],v[[V00]],r[[B00]])
+define void @test_00(<64 x i8>* %p, <64 x i8>* %q) #0 {
+ %v0 = load <64 x i8>, <64 x i8>* %p, align 1
+ store <64 x i8> %v0, <64 x i8>* %q, align 1
+ ret void
+}
+
+; CHECK-LABEL: test_01:
+; CHECK-DAG: v[[V10:[0-9]+]] = vmem(r[[B01:[0-9]+]]+#0)
+; CHECK-DAG: v[[V11:[0-9]+]] = vmem(r[[B01]]+#1)
+; CHECK-DAG: v[[V12:[0-9]+]] = vmem(r[[B01]]+#2)
+; CHECK: }
+; CHECK-DAG: valign(v[[V11]],v[[V10]],r[[B01]])
+; CHECK-DAG: valign(v[[V12]],v[[V11]],r[[B01]])
+define void @test_01(<128 x i8>* %p, <128 x i8>* %q) #0 {
+ %v0 = load <128 x i8>, <128 x i8>* %p, align 1
+ store <128 x i8> %v0, <128 x i8>* %q, align 1
+ ret void
+}
+
+attributes #0 = { nounwind "target-cpu"="hexagonv60" "target-features"="+hvx,+hvx-length64b" }
Modified: llvm/trunk/test/CodeGen/Hexagon/select-instr-align.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Hexagon/select-instr-align.ll?rev=325169&r1=325168&r2=325169&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Hexagon/select-instr-align.ll (original)
+++ llvm/trunk/test/CodeGen/Hexagon/select-instr-align.ll Wed Feb 14 12:46:06 2018
@@ -1,31 +1,31 @@
-; RUN: llc -march=hexagon -mcpu=hexagonv60 -mattr=+hvxv60,hvx-length64b < %s | FileCheck %s
+; RUN: llc -march=hexagon -hvx-expand-unaligned-loads=0 < %s | FileCheck %s
+
; CHECK-LABEL: aligned_load:
; CHECK: = vmem({{.*}})
-; CHECK-LABEL: aligned_store:
-; CHECK: vmem({{.*}}) =
-; CHECK-LABEL: unaligned_load:
-; CHECK: = vmemu({{.*}})
-; CHECK-LABEL: unaligned_store:
-; CHECK: vmemu({{.*}}) =
-
-define <16 x i32> @aligned_load(<16 x i32>* %p, <16 x i32> %a) {
+define <16 x i32> @aligned_load(<16 x i32>* %p, <16 x i32> %a) #0 {
%v = load <16 x i32>, <16 x i32>* %p, align 64
ret <16 x i32> %v
}
-define void @aligned_store(<16 x i32>* %p, <16 x i32> %a) {
+; CHECK-LABEL: aligned_store:
+; CHECK: vmem({{.*}}) =
+define void @aligned_store(<16 x i32>* %p, <16 x i32> %a) #0 {
store <16 x i32> %a, <16 x i32>* %p, align 64
ret void
}
-define <16 x i32> @unaligned_load(<16 x i32>* %p, <16 x i32> %a) {
+; CHECK-LABEL: unaligned_load:
+; CHECK: = vmemu({{.*}})
+define <16 x i32> @unaligned_load(<16 x i32>* %p, <16 x i32> %a) #0 {
%v = load <16 x i32>, <16 x i32>* %p, align 32
ret <16 x i32> %v
}
-define void @unaligned_store(<16 x i32>* %p, <16 x i32> %a) {
+; CHECK-LABEL: unaligned_store:
+; CHECK: vmemu({{.*}}) =
+define void @unaligned_store(<16 x i32>* %p, <16 x i32> %a) #0 {
store <16 x i32> %a, <16 x i32>* %p, align 32
ret void
}
-
+attributes #0 = { nounwind "target-cpu"="hexagonv60" "target-features"="+hvxv60,+hvx-length64b" }
More information about the llvm-commits
mailing list