Mercurial > hg > CbC > CbC_llvm
comparison lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp @ 148:63bd29f05246
merged
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 14 Aug 2019 19:46:37 +0900 |
parents | c2174574ed3a |
children |
comparison
equal
deleted
inserted
replaced
146:3fc4d5c3e21e | 148:63bd29f05246 |
---|---|
1 //===-- HexagonISelDAGToDAGHVX.cpp ----------------------------------------===// | 1 //===-- HexagonISelDAGToDAGHVX.cpp ----------------------------------------===// |
2 // | 2 // |
3 // The LLVM Compiler Infrastructure | 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 // | 4 // See https://llvm.org/LICENSE.txt for license information. |
5 // This file is distributed under the University of Illinois Open Source | 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 // License. See LICENSE.TXT for details. | |
7 // | 6 // |
8 //===----------------------------------------------------------------------===// | 7 //===----------------------------------------------------------------------===// |
9 | 8 |
10 #include "Hexagon.h" | 9 #include "Hexagon.h" |
11 #include "HexagonISelDAGToDAG.h" | 10 #include "HexagonISelDAGToDAG.h" |
118 if (Color == ColorKind::None) | 117 if (Color == ColorKind::None) |
119 return ColorKind::Red; | 118 return ColorKind::Red; |
120 return Color == ColorKind::Red ? ColorKind::Black : ColorKind::Red; | 119 return Color == ColorKind::Red ? ColorKind::Black : ColorKind::Red; |
121 } | 120 } |
122 | 121 |
123 void dump() const; | 122 LLVM_DUMP_METHOD void dump() const; |
124 | 123 |
125 private: | 124 private: |
126 ArrayRef<Node> Order; | 125 ArrayRef<Node> Order; |
127 MapType Colors; | 126 MapType Colors; |
128 std::set<Node> Needed; | 127 std::set<Node> Needed; |
257 } | 256 } |
258 Colors[N] = ColorN; | 257 Colors[N] = ColorN; |
259 Colors[C] = ColorC; | 258 Colors[C] = ColorC; |
260 } | 259 } |
261 | 260 |
262 // Explicitly assign "None" all all uncolored nodes. | 261 // Explicitly assign "None" to all uncolored nodes. |
263 for (unsigned I = 0; I != Order.size(); ++I) | 262 for (unsigned I = 0; I != Order.size(); ++I) |
264 if (Colors.count(I) == 0) | 263 if (Colors.count(I) == 0) |
265 Colors[I] = ColorKind::None; | 264 Colors[I] = ColorKind::None; |
266 | 265 |
267 return true; | 266 return true; |
268 } | 267 } |
269 | 268 |
270 LLVM_DUMP_METHOD | 269 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
271 void Coloring::dump() const { | 270 void Coloring::dump() const { |
272 dbgs() << "{ Order: {"; | 271 dbgs() << "{ Order: {"; |
273 for (unsigned I = 0; I != Order.size(); ++I) { | 272 for (unsigned I = 0; I != Order.size(); ++I) { |
274 Node P = Order[I]; | 273 Node P = Order[I]; |
275 if (P != Ignore) | 274 if (P != Ignore) |
307 dbgs() << " Colors: {\n"; | 306 dbgs() << " Colors: {\n"; |
308 for (auto C : Colors) | 307 for (auto C : Colors) |
309 dbgs() << " " << C.first << " -> " << ColorKindToName(C.second) << "\n"; | 308 dbgs() << " " << C.first << " -> " << ColorKindToName(C.second) << "\n"; |
310 dbgs() << " }\n}\n"; | 309 dbgs() << " }\n}\n"; |
311 } | 310 } |
311 #endif | |
312 | 312 |
313 namespace { | 313 namespace { |
314 // Base class of for reordering networks. They don't strictly need to be | 314 // Base class of for reordering networks. They don't strictly need to be |
315 // permutations, as outputs with repeated occurrences of an input element | 315 // permutations, as outputs with repeated occurrences of an input element |
316 // are allowed. | 316 // are allowed. |
649 Undef = 0x80000000, | 649 Undef = 0x80000000, |
650 Index = 0x0FFFFFFF, // Mask of the index value. | 650 Index = 0x0FFFFFFF, // Mask of the index value. |
651 IndexBits = 28, | 651 IndexBits = 28, |
652 }; | 652 }; |
653 | 653 |
654 LLVM_DUMP_METHOD | |
654 void print(raw_ostream &OS, const SelectionDAG &G) const; | 655 void print(raw_ostream &OS, const SelectionDAG &G) const; |
655 | 656 |
656 private: | 657 private: |
657 OpRef(unsigned N) : OpN(N) {} | 658 OpRef(unsigned N) : OpN(N) {} |
658 }; | 659 }; |
661 NodeTemplate() = default; | 662 NodeTemplate() = default; |
662 unsigned Opc = 0; | 663 unsigned Opc = 0; |
663 MVT Ty = MVT::Other; | 664 MVT Ty = MVT::Other; |
664 std::vector<OpRef> Ops; | 665 std::vector<OpRef> Ops; |
665 | 666 |
666 void print(raw_ostream &OS, const SelectionDAG &G) const; | 667 LLVM_DUMP_METHOD void print(raw_ostream &OS, const SelectionDAG &G) const; |
667 }; | 668 }; |
668 | 669 |
669 struct ResultStack { | 670 struct ResultStack { |
670 ResultStack(SDNode *Inp) | 671 ResultStack(SDNode *Inp) |
671 : InpNode(Inp), InpTy(Inp->getValueType(0).getSimpleVT()) {} | 672 : InpNode(Inp), InpTy(Inp->getValueType(0).getSimpleVT()) {} |
697 BaseType::const_iterator begin() const { return List.begin(); } | 698 BaseType::const_iterator begin() const { return List.begin(); } |
698 BaseType::const_iterator end() const { return List.end(); } | 699 BaseType::const_iterator end() const { return List.end(); } |
699 | 700 |
700 BaseType List; | 701 BaseType List; |
701 | 702 |
703 LLVM_DUMP_METHOD | |
702 void print(raw_ostream &OS, const SelectionDAG &G) const; | 704 void print(raw_ostream &OS, const SelectionDAG &G) const; |
703 }; | 705 }; |
704 } // namespace | 706 } // namespace |
705 | 707 |
708 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) | |
706 void OpRef::print(raw_ostream &OS, const SelectionDAG &G) const { | 709 void OpRef::print(raw_ostream &OS, const SelectionDAG &G) const { |
707 if (isValue()) { | 710 if (isValue()) { |
708 OpV.getNode()->print(OS, &G); | 711 OpV.getNode()->print(OS, &G); |
709 return; | 712 return; |
710 } | 713 } |
750 OS << '[' << I << "] "; | 753 OS << '[' << I << "] "; |
751 List[I].print(OS, G); | 754 List[I].print(OS, G); |
752 OS << '\n'; | 755 OS << '\n'; |
753 } | 756 } |
754 } | 757 } |
758 #endif | |
755 | 759 |
756 namespace { | 760 namespace { |
757 struct ShuffleMask { | 761 struct ShuffleMask { |
758 ShuffleMask(ArrayRef<int> M) : Mask(M) { | 762 ShuffleMask(ArrayRef<int> M) : Mask(M) { |
759 for (unsigned I = 0, E = Mask.size(); I != E; ++I) { | 763 for (unsigned I = 0, E = Mask.size(); I != E; ++I) { |
774 } | 778 } |
775 ShuffleMask hi() const { | 779 ShuffleMask hi() const { |
776 size_t H = Mask.size()/2; | 780 size_t H = Mask.size()/2; |
777 return ShuffleMask(Mask.take_back(H)); | 781 return ShuffleMask(Mask.take_back(H)); |
778 } | 782 } |
783 | |
784 void print(raw_ostream &OS) const { | |
785 OS << "MinSrc:" << MinSrc << ", MaxSrc:" << MaxSrc << " {"; | |
786 for (int M : Mask) | |
787 OS << ' ' << M; | |
788 OS << " }"; | |
789 } | |
779 }; | 790 }; |
780 } // namespace | 791 } // namespace |
781 | 792 |
782 // -------------------------------------------------------------------- | 793 // -------------------------------------------------------------------- |
783 // The HvxSelector class. | 794 // The HvxSelector class. |
811 return MVT::getVectorVT(ElemTy, NumElems); | 822 return MVT::getVectorVT(ElemTy, NumElems); |
812 } | 823 } |
813 | 824 |
814 void selectShuffle(SDNode *N); | 825 void selectShuffle(SDNode *N); |
815 void selectRor(SDNode *N); | 826 void selectRor(SDNode *N); |
827 void selectVAlign(SDNode *N); | |
816 | 828 |
817 private: | 829 private: |
818 void materialize(const ResultStack &Results); | 830 void materialize(const ResultStack &Results); |
819 | 831 |
820 SDValue getVectorConstant(ArrayRef<uint8_t> Data, const SDLoc &dl); | 832 SDValue getVectorConstant(ArrayRef<uint8_t> Data, const SDLoc &dl); |
909 int N = Mask.size(); | 921 int N = Mask.size(); |
910 return 2*Sum == N*(N-1); | 922 return 2*Sum == N*(N-1); |
911 } | 923 } |
912 | 924 |
913 bool HvxSelector::selectVectorConstants(SDNode *N) { | 925 bool HvxSelector::selectVectorConstants(SDNode *N) { |
914 // Constant vectors are generated as loads from constant pools or | 926 // Constant vectors are generated as loads from constant pools or as |
915 // as VSPLATs of a constant value. | 927 // splats of a constant value. Since they are generated during the |
916 // Since they are generated during the selection process, the main | 928 // selection process, the main selection algorithm is not aware of them. |
917 // selection algorithm is not aware of them. Select them directly | 929 // Select them directly here. |
918 // here. | |
919 SmallVector<SDNode*,4> Nodes; | 930 SmallVector<SDNode*,4> Nodes; |
920 SetVector<SDNode*> WorkQ; | 931 SetVector<SDNode*> WorkQ; |
932 | |
933 // The one-use test for VSPLATW's operand may fail due to dead nodes | |
934 // left over in the DAG. | |
935 DAG.RemoveDeadNodes(); | |
921 | 936 |
922 // The DAG can change (due to CSE) during selection, so cache all the | 937 // The DAG can change (due to CSE) during selection, so cache all the |
923 // unselected nodes first to avoid traversing a mutating DAG. | 938 // unselected nodes first to avoid traversing a mutating DAG. |
924 | 939 |
925 auto IsNodeToSelect = [] (SDNode *N) { | 940 auto IsNodeToSelect = [] (SDNode *N) { |
926 if (N->isMachineOpcode()) | 941 if (N->isMachineOpcode()) |
927 return false; | 942 return false; |
928 unsigned Opc = N->getOpcode(); | 943 switch (N->getOpcode()) { |
929 if (Opc == HexagonISD::VSPLAT || Opc == HexagonISD::VZERO) | 944 case HexagonISD::VZERO: |
930 return true; | 945 case HexagonISD::VSPLATW: |
931 if (Opc == ISD::BITCAST) { | |
932 // Only select bitcasts of VSPLATs. | |
933 if (N->getOperand(0).getOpcode() == HexagonISD::VSPLAT) | |
934 return true; | 946 return true; |
935 } | 947 case ISD::LOAD: { |
936 if (Opc == ISD::LOAD) { | 948 SDValue Addr = cast<LoadSDNode>(N)->getBasePtr(); |
937 SDValue Addr = cast<LoadSDNode>(N)->getBasePtr(); | 949 unsigned AddrOpc = Addr.getOpcode(); |
938 unsigned AddrOpc = Addr.getOpcode(); | 950 if (AddrOpc == HexagonISD::AT_PCREL || AddrOpc == HexagonISD::CP) |
939 if (AddrOpc == HexagonISD::AT_PCREL || AddrOpc == HexagonISD::CP) | 951 if (Addr.getOperand(0).getOpcode() == ISD::TargetConstantPool) |
940 if (Addr.getOperand(0).getOpcode() == ISD::TargetConstantPool) | 952 return true; |
941 return true; | 953 } |
942 } | 954 break; |
943 return false; | 955 } |
956 // Make sure to select the operand of VSPLATW. | |
957 bool IsSplatOp = N->hasOneUse() && | |
958 N->use_begin()->getOpcode() == HexagonISD::VSPLATW; | |
959 return IsSplatOp; | |
944 }; | 960 }; |
945 | 961 |
946 WorkQ.insert(N); | 962 WorkQ.insert(N); |
947 for (unsigned i = 0; i != WorkQ.size(); ++i) { | 963 for (unsigned i = 0; i != WorkQ.size(); ++i) { |
948 SDNode *W = WorkQ[i]; | 964 SDNode *W = WorkQ[i]; |
1040 return OpRef::fail(); | 1056 return OpRef::fail(); |
1041 | 1057 |
1042 int VecLen = SM.Mask.size(); | 1058 int VecLen = SM.Mask.size(); |
1043 MVT Ty = getSingleVT(MVT::i8); | 1059 MVT Ty = getSingleVT(MVT::i8); |
1044 | 1060 |
1061 auto IsExtSubvector = [] (ShuffleMask M) { | |
1062 assert(M.MinSrc >= 0 && M.MaxSrc >= 0); | |
1063 for (int I = 0, E = M.Mask.size(); I != E; ++I) { | |
1064 if (M.Mask[I] >= 0 && M.Mask[I]-I != M.MinSrc) | |
1065 return false; | |
1066 } | |
1067 return true; | |
1068 }; | |
1069 | |
1045 if (SM.MaxSrc - SM.MinSrc < int(HwLen)) { | 1070 if (SM.MaxSrc - SM.MinSrc < int(HwLen)) { |
1071 if (SM.MinSrc == 0 || SM.MinSrc == int(HwLen) || !IsExtSubvector(SM)) { | |
1072 // If the mask picks elements from only one of the operands, return | |
1073 // that operand, and update the mask to use index 0 to refer to the | |
1074 // first element of that operand. | |
1075 // If the mask extracts a subvector, it will be handled below, so | |
1076 // skip it here. | |
1077 if (SM.MaxSrc < int(HwLen)) { | |
1078 memcpy(NewMask.data(), SM.Mask.data(), sizeof(int)*VecLen); | |
1079 return Va; | |
1080 } | |
1081 if (SM.MinSrc >= int(HwLen)) { | |
1082 for (int I = 0; I != VecLen; ++I) { | |
1083 int M = SM.Mask[I]; | |
1084 if (M != -1) | |
1085 M -= HwLen; | |
1086 NewMask[I] = M; | |
1087 } | |
1088 return Vb; | |
1089 } | |
1090 } | |
1091 int MinSrc = SM.MinSrc; | |
1046 if (SM.MaxSrc < int(HwLen)) { | 1092 if (SM.MaxSrc < int(HwLen)) { |
1047 memcpy(NewMask.data(), SM.Mask.data(), sizeof(int)*VecLen); | 1093 Vb = Va; |
1048 return Va; | 1094 } else if (SM.MinSrc > int(HwLen)) { |
1049 } | 1095 Va = Vb; |
1050 if (SM.MinSrc >= int(HwLen)) { | 1096 MinSrc = SM.MinSrc - HwLen; |
1051 for (int I = 0; I != VecLen; ++I) { | |
1052 int M = SM.Mask[I]; | |
1053 if (M != -1) | |
1054 M -= HwLen; | |
1055 NewMask[I] = M; | |
1056 } | |
1057 return Vb; | |
1058 } | 1097 } |
1059 const SDLoc &dl(Results.InpNode); | 1098 const SDLoc &dl(Results.InpNode); |
1060 SDValue S = DAG.getTargetConstant(SM.MinSrc, dl, MVT::i32); | 1099 if (isUInt<3>(MinSrc) || isUInt<3>(HwLen-MinSrc)) { |
1061 if (isUInt<3>(SM.MinSrc)) { | 1100 bool IsRight = isUInt<3>(MinSrc); // Right align. |
1062 Results.push(Hexagon::V6_valignbi, Ty, {Vb, Va, S}); | 1101 SDValue S = DAG.getTargetConstant(IsRight ? MinSrc : HwLen-MinSrc, |
1102 dl, MVT::i32); | |
1103 unsigned Opc = IsRight ? Hexagon::V6_valignbi | |
1104 : Hexagon::V6_vlalignbi; | |
1105 Results.push(Opc, Ty, {Vb, Va, S}); | |
1063 } else { | 1106 } else { |
1107 SDValue S = DAG.getTargetConstant(MinSrc, dl, MVT::i32); | |
1064 Results.push(Hexagon::A2_tfrsi, MVT::i32, {S}); | 1108 Results.push(Hexagon::A2_tfrsi, MVT::i32, {S}); |
1065 unsigned Top = Results.top(); | 1109 unsigned Top = Results.top(); |
1066 Results.push(Hexagon::V6_valignb, Ty, {Vb, Va, OpRef::res(Top)}); | 1110 Results.push(Hexagon::V6_valignb, Ty, {Vb, Va, OpRef::res(Top)}); |
1067 } | 1111 } |
1068 for (int I = 0; I != VecLen; ++I) { | 1112 for (int I = 0; I != VecLen; ++I) { |
1285 Bytes[I] = 0xFF; | 1329 Bytes[I] = 0xFF; |
1286 } | 1330 } |
1287 return vmuxp(Bytes, L, R, Results); | 1331 return vmuxp(Bytes, L, R, Results); |
1288 } | 1332 } |
1289 | 1333 |
1334 namespace { | |
1335 struct Deleter : public SelectionDAG::DAGNodeDeletedListener { | |
1336 template <typename T> | |
1337 Deleter(SelectionDAG &D, T &C) | |
1338 : SelectionDAG::DAGNodeDeletedListener(D, [&C] (SDNode *N, SDNode *E) { | |
1339 C.erase(N); | |
1340 }) {} | |
1341 }; | |
1342 | |
1343 template <typename T> | |
1344 struct NullifyingVector : public T { | |
1345 DenseMap<SDNode*, SDNode**> Refs; | |
1346 NullifyingVector(T &&V) : T(V) { | |
1347 for (unsigned i = 0, e = T::size(); i != e; ++i) { | |
1348 SDNode *&N = T::operator[](i); | |
1349 Refs[N] = &N; | |
1350 } | |
1351 } | |
1352 void erase(SDNode *N) { | |
1353 auto F = Refs.find(N); | |
1354 if (F != Refs.end()) | |
1355 *F->second = nullptr; | |
1356 } | |
1357 }; | |
1358 } | |
1359 | |
1290 bool HvxSelector::scalarizeShuffle(ArrayRef<int> Mask, const SDLoc &dl, | 1360 bool HvxSelector::scalarizeShuffle(ArrayRef<int> Mask, const SDLoc &dl, |
1291 MVT ResTy, SDValue Va, SDValue Vb, | 1361 MVT ResTy, SDValue Va, SDValue Vb, |
1292 SDNode *N) { | 1362 SDNode *N) { |
1293 DEBUG_WITH_TYPE("isel", {dbgs() << __func__ << '\n';}); | 1363 DEBUG_WITH_TYPE("isel", {dbgs() << __func__ << '\n';}); |
1294 MVT ElemTy = ResTy.getVectorElementType(); | 1364 MVT ElemTy = ResTy.getVectorElementType(); |
1295 assert(ElemTy == MVT::i8); | 1365 assert(ElemTy == MVT::i8); |
1296 unsigned VecLen = Mask.size(); | 1366 unsigned VecLen = Mask.size(); |
1297 bool HavePairs = (2*HwLen == VecLen); | 1367 bool HavePairs = (2*HwLen == VecLen); |
1298 MVT SingleTy = getSingleVT(MVT::i8); | 1368 MVT SingleTy = getSingleVT(MVT::i8); |
1299 | 1369 |
1370 // The prior attempts to handle this shuffle may have left a bunch of | |
1371 // dead nodes in the DAG (such as constants). These nodes will be added | |
1372 // at the end of DAG's node list, which at that point had already been | |
1373 // sorted topologically. In the main selection loop, the node list is | |
1374 // traversed backwards from the root node, which means that any new | |
1375 // nodes (from the end of the list) will not be visited. | |
1376 // Scalarization will replace the shuffle node with the scalarized | |
1377 // expression, and if that expression reused any if the leftoever (dead) | |
1378 // nodes, these nodes would not be selected (since the "local" selection | |
1379 // only visits nodes that are not in AllNodes). | |
1380 // To avoid this issue, remove all dead nodes from the DAG now. | |
1381 DAG.RemoveDeadNodes(); | |
1382 DenseSet<SDNode*> AllNodes; | |
1383 for (SDNode &S : DAG.allnodes()) | |
1384 AllNodes.insert(&S); | |
1385 | |
1386 Deleter DUA(DAG, AllNodes); | |
1387 | |
1300 SmallVector<SDValue,128> Ops; | 1388 SmallVector<SDValue,128> Ops; |
1389 LLVMContext &Ctx = *DAG.getContext(); | |
1390 MVT LegalTy = Lower.getTypeToTransformTo(Ctx, ElemTy).getSimpleVT(); | |
1301 for (int I : Mask) { | 1391 for (int I : Mask) { |
1302 if (I < 0) { | 1392 if (I < 0) { |
1303 Ops.push_back(ISel.selectUndef(dl, ElemTy)); | 1393 Ops.push_back(ISel.selectUndef(dl, LegalTy)); |
1304 continue; | 1394 continue; |
1305 } | 1395 } |
1306 SDValue Vec; | 1396 SDValue Vec; |
1307 unsigned M = I; | 1397 unsigned M = I; |
1308 if (M < VecLen) { | 1398 if (M < VecLen) { |
1318 Vec = DAG.getTargetExtractSubreg(Hexagon::vsub_hi, dl, SingleTy, Vec); | 1408 Vec = DAG.getTargetExtractSubreg(Hexagon::vsub_hi, dl, SingleTy, Vec); |
1319 M -= HwLen; | 1409 M -= HwLen; |
1320 } | 1410 } |
1321 } | 1411 } |
1322 SDValue Idx = DAG.getConstant(M, dl, MVT::i32); | 1412 SDValue Idx = DAG.getConstant(M, dl, MVT::i32); |
1323 SDValue Ex = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, ElemTy, {Vec, Idx}); | 1413 SDValue Ex = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, LegalTy, {Vec, Idx}); |
1324 SDValue L = Lower.LowerOperation(Ex, DAG); | 1414 SDValue L = Lower.LowerOperation(Ex, DAG); |
1325 assert(L.getNode()); | 1415 assert(L.getNode()); |
1326 Ops.push_back(L); | 1416 Ops.push_back(L); |
1327 } | 1417 } |
1328 | 1418 |
1342 LV = Lower.LowerOperation(BV, DAG); | 1432 LV = Lower.LowerOperation(BV, DAG); |
1343 } | 1433 } |
1344 | 1434 |
1345 assert(!N->use_empty()); | 1435 assert(!N->use_empty()); |
1346 ISel.ReplaceNode(N, LV.getNode()); | 1436 ISel.ReplaceNode(N, LV.getNode()); |
1347 DAG.RemoveDeadNodes(); | 1437 |
1348 | 1438 if (AllNodes.count(LV.getNode())) { |
1349 std::deque<SDNode*> SubNodes; | 1439 DAG.RemoveDeadNodes(); |
1350 SubNodes.push_back(LV.getNode()); | 1440 return true; |
1441 } | |
1442 | |
1443 // The lowered build-vector node will now need to be selected. It needs | |
1444 // to be done here because this node and its submodes are not included | |
1445 // in the main selection loop. | |
1446 // Implement essentially the same topological ordering algorithm as is | |
1447 // used in SelectionDAGISel. | |
1448 | |
1449 SetVector<SDNode*> SubNodes, TmpQ; | |
1450 std::map<SDNode*,unsigned> NumOps; | |
1451 | |
1452 SubNodes.insert(LV.getNode()); | |
1351 for (unsigned I = 0; I != SubNodes.size(); ++I) { | 1453 for (unsigned I = 0; I != SubNodes.size(); ++I) { |
1352 for (SDValue Op : SubNodes[I]->ops()) | 1454 unsigned OpN = 0; |
1353 SubNodes.push_back(Op.getNode()); | 1455 SDNode *S = SubNodes[I]; |
1354 } | 1456 for (SDValue Op : S->ops()) { |
1355 while (!SubNodes.empty()) { | 1457 if (AllNodes.count(Op.getNode())) |
1356 SDNode *S = SubNodes.front(); | 1458 continue; |
1357 SubNodes.pop_front(); | 1459 SubNodes.insert(Op.getNode()); |
1358 if (S->use_empty()) | 1460 ++OpN; |
1359 continue; | 1461 } |
1360 // This isn't great, but users need to be selected before any nodes that | 1462 NumOps.insert({S, OpN}); |
1361 // they use. (The reason is to match larger patterns, and avoid nodes that | 1463 if (OpN == 0) |
1362 // cannot be matched on their own, e.g. ValueType, TokenFactor, etc.). | 1464 TmpQ.insert(S); |
1363 bool PendingUser = llvm::any_of(S->uses(), [&SubNodes](const SDNode *U) { | 1465 } |
1364 return llvm::any_of(SubNodes, [U](const SDNode *T) { | 1466 |
1365 return T == U; | 1467 for (unsigned I = 0; I != TmpQ.size(); ++I) { |
1366 }); | 1468 SDNode *S = TmpQ[I]; |
1367 }); | 1469 for (SDNode *U : S->uses()) { |
1368 if (PendingUser) | 1470 if (!SubNodes.count(U)) |
1369 SubNodes.push_back(S); | 1471 continue; |
1370 else | 1472 auto F = NumOps.find(U); |
1473 assert(F != NumOps.end()); | |
1474 assert(F->second > 0); | |
1475 if (!--F->second) | |
1476 TmpQ.insert(F->first); | |
1477 } | |
1478 } | |
1479 assert(SubNodes.size() == TmpQ.size()); | |
1480 NullifyingVector<decltype(TmpQ)::vector_type> Queue(TmpQ.takeVector()); | |
1481 | |
1482 Deleter DUQ(DAG, Queue); | |
1483 for (SDNode *S : reverse(Queue)) | |
1484 if (S != nullptr) | |
1371 ISel.Select(S); | 1485 ISel.Select(S); |
1372 } | |
1373 | 1486 |
1374 DAG.RemoveDeadNodes(); | 1487 DAG.RemoveDeadNodes(); |
1375 return true; | 1488 return true; |
1376 } | 1489 } |
1377 | 1490 |
1926 << HavePairs << '\n'; | 2039 << HavePairs << '\n'; |
1927 }); | 2040 }); |
1928 // If the mask is all -1's, generate "undef". | 2041 // If the mask is all -1's, generate "undef". |
1929 if (!UseLeft && !UseRight) { | 2042 if (!UseLeft && !UseRight) { |
1930 ISel.ReplaceNode(N, ISel.selectUndef(SDLoc(SN), ResTy).getNode()); | 2043 ISel.ReplaceNode(N, ISel.selectUndef(SDLoc(SN), ResTy).getNode()); |
1931 DAG.RemoveDeadNode(N); | |
1932 return; | 2044 return; |
1933 } | 2045 } |
1934 | 2046 |
1935 SDValue Vec0 = N->getOperand(0); | 2047 SDValue Vec0 = N->getOperand(0); |
1936 SDValue Vec1 = N->getOperand(1); | 2048 SDValue Vec1 = N->getOperand(1); |
1982 | 2094 |
1983 if (!NewN) | 2095 if (!NewN) |
1984 NewN = DAG.getMachineNode(Hexagon::V6_vror, dl, Ty, {VecV, RotV}); | 2096 NewN = DAG.getMachineNode(Hexagon::V6_vror, dl, Ty, {VecV, RotV}); |
1985 | 2097 |
1986 ISel.ReplaceNode(N, NewN); | 2098 ISel.ReplaceNode(N, NewN); |
2099 } | |
2100 | |
2101 void HvxSelector::selectVAlign(SDNode *N) { | |
2102 SDValue Vv = N->getOperand(0); | |
2103 SDValue Vu = N->getOperand(1); | |
2104 SDValue Rt = N->getOperand(2); | |
2105 SDNode *NewN = DAG.getMachineNode(Hexagon::V6_valignb, SDLoc(N), | |
2106 N->getValueType(0), {Vv, Vu, Rt}); | |
2107 ISel.ReplaceNode(N, NewN); | |
1987 DAG.RemoveDeadNode(N); | 2108 DAG.RemoveDeadNode(N); |
1988 } | 2109 } |
1989 | 2110 |
1990 void HexagonDAGToDAGISel::SelectHvxShuffle(SDNode *N) { | 2111 void HexagonDAGToDAGISel::SelectHvxShuffle(SDNode *N) { |
1991 HvxSelector(*this, *CurDAG).selectShuffle(N); | 2112 HvxSelector(*this, *CurDAG).selectShuffle(N); |
1992 } | 2113 } |
1993 | 2114 |
1994 void HexagonDAGToDAGISel::SelectHvxRor(SDNode *N) { | 2115 void HexagonDAGToDAGISel::SelectHvxRor(SDNode *N) { |
1995 HvxSelector(*this, *CurDAG).selectRor(N); | 2116 HvxSelector(*this, *CurDAG).selectRor(N); |
2117 } | |
2118 | |
2119 void HexagonDAGToDAGISel::SelectHvxVAlign(SDNode *N) { | |
2120 HvxSelector(*this, *CurDAG).selectVAlign(N); | |
1996 } | 2121 } |
1997 | 2122 |
1998 void HexagonDAGToDAGISel::SelectV65GatherPred(SDNode *N) { | 2123 void HexagonDAGToDAGISel::SelectV65GatherPred(SDNode *N) { |
1999 const SDLoc &dl(N); | 2124 const SDLoc &dl(N); |
2000 SDValue Chain = N->getOperand(0); | 2125 SDValue Chain = N->getOperand(0); |
2025 | 2150 |
2026 SDVTList VTs = CurDAG->getVTList(MVT::Other); | 2151 SDVTList VTs = CurDAG->getVTList(MVT::Other); |
2027 SDValue Ops[] = { Address, Predicate, Base, Modifier, Offset, Chain }; | 2152 SDValue Ops[] = { Address, Predicate, Base, Modifier, Offset, Chain }; |
2028 SDNode *Result = CurDAG->getMachineNode(Opcode, dl, VTs, Ops); | 2153 SDNode *Result = CurDAG->getMachineNode(Opcode, dl, VTs, Ops); |
2029 | 2154 |
2030 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); | 2155 MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand(); |
2031 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand(); | 2156 CurDAG->setNodeMemRefs(cast<MachineSDNode>(Result), {MemOp}); |
2032 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); | 2157 |
2033 | 2158 ReplaceNode(N, Result); |
2034 ReplaceUses(N, Result); | |
2035 CurDAG->RemoveDeadNode(N); | |
2036 } | 2159 } |
2037 | 2160 |
2038 void HexagonDAGToDAGISel::SelectV65Gather(SDNode *N) { | 2161 void HexagonDAGToDAGISel::SelectV65Gather(SDNode *N) { |
2039 const SDLoc &dl(N); | 2162 const SDLoc &dl(N); |
2040 SDValue Chain = N->getOperand(0); | 2163 SDValue Chain = N->getOperand(0); |
2064 | 2187 |
2065 SDVTList VTs = CurDAG->getVTList(MVT::Other); | 2188 SDVTList VTs = CurDAG->getVTList(MVT::Other); |
2066 SDValue Ops[] = { Address, Base, Modifier, Offset, Chain }; | 2189 SDValue Ops[] = { Address, Base, Modifier, Offset, Chain }; |
2067 SDNode *Result = CurDAG->getMachineNode(Opcode, dl, VTs, Ops); | 2190 SDNode *Result = CurDAG->getMachineNode(Opcode, dl, VTs, Ops); |
2068 | 2191 |
2069 MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); | 2192 MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand(); |
2070 MemOp[0] = cast<MemIntrinsicSDNode>(N)->getMemOperand(); | 2193 CurDAG->setNodeMemRefs(cast<MachineSDNode>(Result), {MemOp}); |
2071 cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); | 2194 |
2072 | 2195 ReplaceNode(N, Result); |
2073 ReplaceUses(N, Result); | |
2074 CurDAG->RemoveDeadNode(N); | |
2075 } | 2196 } |
2076 | 2197 |
2077 void HexagonDAGToDAGISel::SelectHVXDualOutput(SDNode *N) { | 2198 void HexagonDAGToDAGISel::SelectHVXDualOutput(SDNode *N) { |
2078 unsigned IID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue(); | 2199 unsigned IID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue(); |
2079 SDNode *Result; | 2200 SDNode *Result; |
2112 ReplaceUses(N, Result); | 2233 ReplaceUses(N, Result); |
2113 ReplaceUses(SDValue(N, 0), SDValue(Result, 0)); | 2234 ReplaceUses(SDValue(N, 0), SDValue(Result, 0)); |
2114 ReplaceUses(SDValue(N, 1), SDValue(Result, 1)); | 2235 ReplaceUses(SDValue(N, 1), SDValue(Result, 1)); |
2115 CurDAG->RemoveDeadNode(N); | 2236 CurDAG->RemoveDeadNode(N); |
2116 } | 2237 } |
2117 | |
2118 |