Skip to content

Commit 154daf1

Browse files
author
Krzysztof Parzyszek
committed
[Hexagon] Widen short vector stores to HVX vectors using masked stores
Also invent a flag -hexagon-hvx-widen=N to set the minimum threshold for widening short vectors to HVX vectors.
1 parent 419c694 commit 154daf1

File tree

4 files changed

+124
-14
lines changed

4 files changed

+124
-14
lines changed

llvm/lib/Target/Hexagon/HexagonISelLowering.cpp

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2064,20 +2064,9 @@ HexagonTargetLowering::getPreferredVectorAction(MVT VT) const {
20642064
return TargetLoweringBase::TypeScalarizeVector;
20652065

20662066
if (Subtarget.useHVXOps()) {
2067-
unsigned HwLen = Subtarget.getVectorLength();
2068-
// If the size of VT is at least half of the vector length,
2069-
// widen the vector. Note: the threshold was not selected in
2070-
// any scientific way.
2071-
ArrayRef<MVT> Tys = Subtarget.getHVXElementTypes();
2072-
if (llvm::find(Tys, ElemTy) != Tys.end()) {
2073-
unsigned HwWidth = 8*HwLen;
2074-
unsigned VecWidth = VT.getSizeInBits();
2075-
if (VecWidth >= HwWidth/2 && VecWidth < HwWidth)
2076-
return TargetLoweringBase::TypeWidenVector;
2077-
}
2078-
// Split vectors of i1 that correspond to (byte) vector pairs.
2079-
if (ElemTy == MVT::i1 && VecLen == 2*HwLen)
2080-
return TargetLoweringBase::TypeSplitVector;
2067+
unsigned Action = getPreferredHvxVectorAction(VT);
2068+
if (Action != ~0u)
2069+
return static_cast<TargetLoweringBase::LegalizeTypeAction>(Action);
20812070
}
20822071

20832072
// Always widen (remaining) vectors of i1.

llvm/lib/Target/Hexagon/HexagonISelLowering.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,8 @@ namespace HexagonISD {
338338

339339
private:
340340
void initializeHVXLowering();
341+
unsigned getPreferredHvxVectorAction(MVT VecTy) const;
342+
341343
void validateConstPtrAlignment(SDValue Ptr, const SDLoc &dl,
342344
unsigned NeedAlign) const;
343345

@@ -473,6 +475,7 @@ namespace HexagonISD {
473475

474476
SDValue SplitHvxPairOp(SDValue Op, SelectionDAG &DAG) const;
475477
SDValue SplitHvxMemOp(SDValue Op, SelectionDAG &DAG) const;
478+
SDValue WidenHvxStore(SDValue Op, SelectionDAG &DAG) const;
476479

477480
std::pair<const TargetRegisterClass*, uint8_t>
478481
findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT)

llvm/lib/Target/Hexagon/HexagonISelLoweringHVX.cpp

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414

1515
using namespace llvm;
1616

17+
static cl::opt<unsigned> HvxWidenThreshold("hexagon-hvx-widen",
18+
cl::Hidden, cl::init(16),
19+
cl::desc("Lower threshold (in bytes) for widening to HVX vectors"));
20+
1721
static const MVT LegalV64[] = { MVT::v64i8, MVT::v32i16, MVT::v16i32 };
1822
static const MVT LegalW64[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
1923
static const MVT LegalV128[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
@@ -218,9 +222,56 @@ HexagonTargetLowering::initializeHVXLowering() {
218222
setOperationAction(ISD::SIGN_EXTEND_INREG, T, Legal);
219223
}
220224

225+
// Handle store widening for short vectors.
226+
std::vector<MVT> ShortTys;
227+
unsigned HwLen = Subtarget.getVectorLength();
228+
for (MVT ElemTy : Subtarget.getHVXElementTypes()) {
229+
if (ElemTy == MVT::i1)
230+
continue;
231+
int ElemWidth = ElemTy.getSizeInBits().getFixedSize();
232+
int MaxElems = (8*HwLen) / ElemWidth;
233+
for (int N = 2; N < MaxElems; N *= 2) {
234+
MVT VecTy = MVT::getVectorVT(ElemTy, N);
235+
auto Action = getPreferredVectorAction(VecTy);
236+
if (Action == TargetLoweringBase::TypeWidenVector)
237+
setOperationAction(ISD::STORE, VecTy, Custom);
238+
}
239+
}
240+
221241
setTargetDAGCombine(ISD::VSELECT);
222242
}
223243

244+
unsigned
245+
HexagonTargetLowering::getPreferredHvxVectorAction(MVT VecTy) const {
246+
MVT ElemTy = VecTy.getVectorElementType();
247+
unsigned VecLen = VecTy.getVectorNumElements();
248+
unsigned HwLen = Subtarget.getVectorLength();
249+
250+
// Split vectors of i1 that correspond to (byte) vector pairs.
251+
if (ElemTy == MVT::i1 && VecLen == 2*HwLen)
252+
return TargetLoweringBase::TypeSplitVector;
253+
// Treat i1 as i8 from now on.
254+
if (ElemTy == MVT::i1)
255+
ElemTy = MVT::i8;
256+
257+
// If the size of VecTy is at least half of the vector length,
258+
// widen the vector. Note: the threshold was not selected in
259+
// any scientific way.
260+
ArrayRef<MVT> Tys = Subtarget.getHVXElementTypes();
261+
if (llvm::find(Tys, ElemTy) != Tys.end()) {
262+
unsigned VecWidth = VecTy.getSizeInBits();
263+
bool HaveThreshold = HvxWidenThreshold.getNumOccurrences() > 0;
264+
if (HaveThreshold && 8*HvxWidenThreshold <= VecWidth)
265+
return TargetLoweringBase::TypeWidenVector;
266+
unsigned HwWidth = 8*HwLen;
267+
if (VecWidth >= HwWidth/2 && VecWidth < HwWidth)
268+
return TargetLoweringBase::TypeWidenVector;
269+
}
270+
271+
// Defer to default.
272+
return ~0u;
273+
}
274+
224275
SDValue
225276
HexagonTargetLowering::getInt(unsigned IntId, MVT ResTy, ArrayRef<SDValue> Ops,
226277
const SDLoc &dl, SelectionDAG &DAG) const {
@@ -1801,6 +1852,39 @@ HexagonTargetLowering::SplitHvxMemOp(SDValue Op, SelectionDAG &DAG) const {
18011852
llvm_unreachable(Name.c_str());
18021853
}
18031854

1855+
SDValue
1856+
HexagonTargetLowering::WidenHvxStore(SDValue Op, SelectionDAG &DAG) const {
1857+
const SDLoc &dl(Op);
1858+
auto *StoreN = cast<StoreSDNode>(Op.getNode());
1859+
assert(StoreN->isUnindexed() && "Not widening indexed stores yet");
1860+
assert(StoreN->getMemoryVT().getVectorElementType() != MVT::i1 &&
1861+
"Not widening stores of i1 yet");
1862+
1863+
SDValue Chain = StoreN->getChain();
1864+
SDValue Base = StoreN->getBasePtr();
1865+
SDValue Offset = DAG.getUNDEF(MVT::i32);
1866+
1867+
SDValue Value = opCastElem(StoreN->getValue(), MVT::i8, DAG);
1868+
MVT ValueTy = ty(Value);
1869+
unsigned ValueLen = ValueTy.getVectorNumElements();
1870+
unsigned HwLen = Subtarget.getVectorLength();
1871+
assert(isPowerOf2_32(ValueLen));
1872+
1873+
for (unsigned Len = ValueLen; Len < HwLen; ) {
1874+
Value = opJoin({DAG.getUNDEF(ty(Value)), Value}, dl, DAG);
1875+
Len = ty(Value).getVectorNumElements(); // This is Len *= 2
1876+
}
1877+
assert(ty(Value).getVectorNumElements() == HwLen); // Paranoia
1878+
1879+
MVT BoolTy = MVT::getVectorVT(MVT::i1, HwLen);
1880+
SDValue StoreQ = getInstr(Hexagon::V6_pred_scalar2, dl, BoolTy,
1881+
{DAG.getConstant(ValueLen, dl, MVT::i32)}, DAG);
1882+
MachineFunction &MF = DAG.getMachineFunction();
1883+
auto *MOp = MF.getMachineMemOperand(StoreN->getMemOperand(), 0, HwLen);
1884+
return DAG.getMaskedStore(Chain, dl, Value, Base, Offset, StoreQ, ty(Value),
1885+
MOp, ISD::UNINDEXED, false, false);
1886+
}
1887+
18041888
SDValue
18051889
HexagonTargetLowering::LowerHvxOperation(SDValue Op, SelectionDAG &DAG) const {
18061890
unsigned Opc = Op.getOpcode();
@@ -1879,6 +1963,14 @@ HexagonTargetLowering::LowerHvxOperationWrapper(SDNode *N,
18791963
SDValue Op(N, 0);
18801964

18811965
switch (Opc) {
1966+
case ISD::STORE: {
1967+
SDValue Value = cast<StoreSDNode>(N)->getValue();
1968+
unsigned Action = getPreferredHvxVectorAction(ty(Value));
1969+
assert(Action == TargetLoweringBase::TypeWidenVector && "Not widening?");
1970+
SDValue Store = WidenHvxStore(SDValue(N, 0), DAG);
1971+
Results.push_back(Store);
1972+
break;
1973+
}
18821974
case ISD::MLOAD:
18831975
if (isHvxPairTy(ty(Op))) {
18841976
SDValue S = SplitHvxMemOp(Op, DAG);
@@ -1939,6 +2031,16 @@ HexagonTargetLowering::PerformHvxDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
19392031

19402032
bool
19412033
HexagonTargetLowering::isHvxOperation(SDNode *N) const {
2034+
if (N->getOpcode() == ISD::STORE) {
2035+
// If it's a store-to-be-widened, treat it as an HVX operation.
2036+
SDValue Val = cast<StoreSDNode>(N)->getValue();
2037+
MVT ValTy = ty(Val);
2038+
if (ValTy.isVector()) {
2039+
auto Action = getPreferredVectorAction(ValTy);
2040+
if (Action == TargetLoweringBase::TypeWidenVector)
2041+
return true;
2042+
}
2043+
}
19422044
// If the type of any result, or any operand type are HVX vector types,
19432045
// this is an HVX operation.
19442046
auto IsHvxTy = [this] (EVT Ty) {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
; RUN: llc -march=hexagon -hexagon-hvx-widen=16 < %s | FileCheck %s
2+
3+
; CHECK-LABEL: f0:
4+
; CHECK: q[[Q0:[0-3]]] = vsetq(r{{[0-9]+}})
5+
; CHECK: if (q[[Q0]]) vmem({{.*}}) = v
6+
define void @f0(<32 x i8>* %a0) #0 {
7+
%v0 = load <32 x i8>, <32 x i8>* %a0, align 128
8+
%v1 = insertelement <32 x i8> undef, i8 1, i32 0
9+
%v2 = shufflevector <32 x i8> %v1, <32 x i8> undef, <32 x i32> zeroinitializer
10+
%v3 = add <32 x i8> %v0, %v2
11+
store <32 x i8> %v3, <32 x i8>* %a0, align 128
12+
ret void
13+
}
14+
15+
attributes #0 = { nounwind "target-cpu"="hexagonv65" "target-features"="+hvx,+hvx-length128b" }
16+

0 commit comments

Comments
 (0)