|
14 | 14 |
|
15 | 15 | using namespace llvm;
|
16 | 16 |
|
| 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 | + |
17 | 21 | static const MVT LegalV64[] = { MVT::v64i8, MVT::v32i16, MVT::v16i32 };
|
18 | 22 | static const MVT LegalW64[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
|
19 | 23 | static const MVT LegalV128[] = { MVT::v128i8, MVT::v64i16, MVT::v32i32 };
|
@@ -218,9 +222,56 @@ HexagonTargetLowering::initializeHVXLowering() {
|
218 | 222 | setOperationAction(ISD::SIGN_EXTEND_INREG, T, Legal);
|
219 | 223 | }
|
220 | 224 |
|
| 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 | + |
221 | 241 | setTargetDAGCombine(ISD::VSELECT);
|
222 | 242 | }
|
223 | 243 |
|
| 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 | + |
224 | 275 | SDValue
|
225 | 276 | HexagonTargetLowering::getInt(unsigned IntId, MVT ResTy, ArrayRef<SDValue> Ops,
|
226 | 277 | const SDLoc &dl, SelectionDAG &DAG) const {
|
@@ -1801,6 +1852,39 @@ HexagonTargetLowering::SplitHvxMemOp(SDValue Op, SelectionDAG &DAG) const {
|
1801 | 1852 | llvm_unreachable(Name.c_str());
|
1802 | 1853 | }
|
1803 | 1854 |
|
| 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 | + |
1804 | 1888 | SDValue
|
1805 | 1889 | HexagonTargetLowering::LowerHvxOperation(SDValue Op, SelectionDAG &DAG) const {
|
1806 | 1890 | unsigned Opc = Op.getOpcode();
|
@@ -1879,6 +1963,14 @@ HexagonTargetLowering::LowerHvxOperationWrapper(SDNode *N,
|
1879 | 1963 | SDValue Op(N, 0);
|
1880 | 1964 |
|
1881 | 1965 | 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 | + } |
1882 | 1974 | case ISD::MLOAD:
|
1883 | 1975 | if (isHvxPairTy(ty(Op))) {
|
1884 | 1976 | SDValue S = SplitHvxMemOp(Op, DAG);
|
@@ -1939,6 +2031,16 @@ HexagonTargetLowering::PerformHvxDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
|
1939 | 2031 |
|
1940 | 2032 | bool
|
1941 | 2033 | 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 | + } |
1942 | 2044 | // If the type of any result, or any operand type are HVX vector types,
|
1943 | 2045 | // this is an HVX operation.
|
1944 | 2046 | auto IsHvxTy = [this] (EVT Ty) {
|
|
0 commit comments