diff options
Diffstat (limited to 'lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp')
| -rw-r--r-- | lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp | 70 |
1 files changed, 39 insertions, 31 deletions
diff --git a/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp b/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp index 537f97c9a987..8b6c571dee02 100644 --- a/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp +++ b/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp @@ -756,11 +756,11 @@ struct ShuffleMask { ShuffleMask lo() const { size_t H = Mask.size()/2; - return ShuffleMask({Mask.data(), H}); + return ShuffleMask(Mask.take_front(H)); } ShuffleMask hi() const { size_t H = Mask.size()/2; - return ShuffleMask({Mask.data()+H, H}); + return ShuffleMask(Mask.take_back(H)); } }; @@ -836,15 +836,6 @@ namespace llvm { }; } -// Return a submask of A that is shorter than A by |C| elements: -// - if C > 0, return a submask of A that starts at position C, -// - if C <= 0, return a submask of A that starts at 0 (reduce A by |C|). -static ArrayRef<int> subm(ArrayRef<int> A, int C) { - if (C > 0) - return { A.data()+C, A.size()-C }; - return { A.data(), A.size()+C }; -} - static void splitMask(ArrayRef<int> Mask, MutableArrayRef<int> MaskL, MutableArrayRef<int> MaskR) { unsigned VecLen = Mask.size(); @@ -910,21 +901,38 @@ bool HvxSelector::selectVectorConstants(SDNode *N) { // Since they are generated during the selection process, the main // selection algorithm is not aware of them. Select them directly // here. - if (!N->isMachineOpcode() && N->getOpcode() == ISD::LOAD) { - SDValue Addr = cast<LoadSDNode>(N)->getBasePtr(); - unsigned AddrOpc = Addr.getOpcode(); - if (AddrOpc == HexagonISD::AT_PCREL || AddrOpc == HexagonISD::CP) { - if (Addr.getOperand(0).getOpcode() == ISD::TargetConstantPool) { - ISel.Select(N); - return true; - } + SmallVector<SDNode*,4> Loads; + SmallVector<SDNode*,16> WorkQ; + + // The DAG can change (due to CSE) during selection, so cache all the + // unselected nodes first to avoid traversing a mutating DAG. + + auto IsLoadToSelect = [] (SDNode *N) { + if (!N->isMachineOpcode() && N->getOpcode() == ISD::LOAD) { + SDValue Addr = cast<LoadSDNode>(N)->getBasePtr(); + unsigned AddrOpc = Addr.getOpcode(); + if (AddrOpc == HexagonISD::AT_PCREL || AddrOpc == HexagonISD::CP) + if (Addr.getOperand(0).getOpcode() == ISD::TargetConstantPool) + return true; } + return false; + }; + + WorkQ.push_back(N); + for (unsigned i = 0; i != WorkQ.size(); ++i) { + SDNode *W = WorkQ[i]; + if (IsLoadToSelect(W)) { + Loads.push_back(W); + continue; + } + for (unsigned j = 0, f = W->getNumOperands(); j != f; ++j) + WorkQ.push_back(W->getOperand(j).getNode()); } - bool Selected = false; - for (unsigned I = 0, E = N->getNumOperands(); I != E; ++I) - Selected = selectVectorConstants(N->getOperand(I).getNode()) || Selected; - return Selected; + for (SDNode *L : Loads) + ISel.Select(L); + + return !Loads.empty(); } void HvxSelector::materialize(const ResultStack &Results) { @@ -1159,8 +1167,8 @@ OpRef HvxSelector::vmuxp(ArrayRef<uint8_t> Bytes, OpRef Va, OpRef Vb, ResultStack &Results) { DEBUG_WITH_TYPE("isel", {dbgs() << __func__ << '\n';}); size_t S = Bytes.size() / 2; - OpRef L = vmuxs({Bytes.data(), S}, OpRef::lo(Va), OpRef::lo(Vb), Results); - OpRef H = vmuxs({Bytes.data()+S, S}, OpRef::hi(Va), OpRef::hi(Vb), Results); + OpRef L = vmuxs(Bytes.take_front(S), OpRef::lo(Va), OpRef::lo(Vb), Results); + OpRef H = vmuxs(Bytes.drop_front(S), OpRef::hi(Va), OpRef::hi(Vb), Results); return concat(L, H, Results); } @@ -1435,7 +1443,7 @@ OpRef HvxSelector::contracting(ShuffleMask SM, OpRef Va, OpRef Vb, return OpRef::fail(); // Examine the rest of the mask. for (int I = L; I < N; I += L) { - auto S = findStrip(subm(SM.Mask,I), 1, N-I); + auto S = findStrip(SM.Mask.drop_front(I), 1, N-I); // Check whether the mask element at the beginning of each strip // increases by 2L each time. if (S.first - Strip.first != 2*I) @@ -1465,7 +1473,7 @@ OpRef HvxSelector::contracting(ShuffleMask SM, OpRef Va, OpRef Vb, std::pair<int,unsigned> PrevS = Strip; bool Flip = false; for (int I = L; I < N; I += L) { - auto S = findStrip(subm(SM.Mask,I), 1, N-I); + auto S = findStrip(SM.Mask.drop_front(I), 1, N-I); if (S.second != PrevS.second) return OpRef::fail(); int Diff = Flip ? PrevS.first - S.first + 2*L @@ -1524,7 +1532,7 @@ OpRef HvxSelector::expanding(ShuffleMask SM, OpRef Va, ResultStack &Results) { // First, check the non-ignored strips. for (int I = 2*L; I < 2*N; I += 2*L) { - auto S = findStrip(subm(SM.Mask,I), 1, N-I); + auto S = findStrip(SM.Mask.drop_front(I), 1, N-I); if (S.second != unsigned(L)) return OpRef::fail(); if (2*S.first != I) @@ -1532,7 +1540,7 @@ OpRef HvxSelector::expanding(ShuffleMask SM, OpRef Va, ResultStack &Results) { } // Check the -1s. for (int I = L; I < 2*N; I += 2*L) { - auto S = findStrip(subm(SM.Mask,I), 0, N-I); + auto S = findStrip(SM.Mask.drop_front(I), 0, N-I); if (S.first != -1 || S.second != unsigned(L)) return OpRef::fail(); } @@ -1666,8 +1674,8 @@ OpRef HvxSelector::perfect(ShuffleMask SM, OpRef Va, ResultStack &Results) { if (!isPowerOf2_32(X)) return OpRef::fail(); // Check the other segments of Mask. - for (int J = 0; J < VecLen; J += I) { - if (XorPow2(subm(SM.Mask, -J), I) != X) + for (int J = I; J < VecLen; J += I) { + if (XorPow2(SM.Mask.slice(J, I), I) != X) return OpRef::fail(); } Perm[Log2_32(X)] = Log2_32(I)-1; |
