@@ -828,6 +828,7 @@ namespace llvm {
828
828
void selectVAlign (SDNode *N);
829
829
830
830
private:
831
+ void select (SDNode *ISelN);
831
832
void materialize (const ResultStack &Results);
832
833
833
834
SDValue getVectorConstant (ArrayRef<uint8_t > Data, const SDLoc &dl);
@@ -931,46 +932,19 @@ bool HvxSelector::selectVectorConstants(SDNode *N) {
931
932
SmallVector<SDNode*,4 > Nodes;
932
933
SetVector<SDNode*> WorkQ;
933
934
934
- // The one-use test for VSPLATW's operand may fail due to dead nodes
935
- // left over in the DAG.
936
- DAG.RemoveDeadNodes ();
937
-
938
935
// The DAG can change (due to CSE) during selection, so cache all the
939
936
// unselected nodes first to avoid traversing a mutating DAG.
940
-
941
- auto IsNodeToSelect = [] (SDNode *N) {
942
- if (N->isMachineOpcode ())
943
- return false ;
944
- switch (N->getOpcode ()) {
945
- case HexagonISD::VZERO:
946
- case HexagonISD::VSPLATW:
947
- return true ;
948
- case ISD::LOAD: {
949
- SDValue Addr = cast<LoadSDNode>(N)->getBasePtr ();
950
- unsigned AddrOpc = Addr.getOpcode ();
951
- if (AddrOpc == HexagonISD::AT_PCREL || AddrOpc == HexagonISD::CP)
952
- if (Addr.getOperand (0 ).getOpcode () == ISD::TargetConstantPool)
953
- return true ;
954
- }
955
- break ;
956
- }
957
- // Make sure to select the operand of VSPLATW.
958
- bool IsSplatOp = N->hasOneUse () &&
959
- N->use_begin ()->getOpcode () == HexagonISD::VSPLATW;
960
- return IsSplatOp;
961
- };
962
-
963
937
WorkQ.insert (N);
964
938
for (unsigned i = 0 ; i != WorkQ.size (); ++i) {
965
939
SDNode *W = WorkQ[i];
966
- if (IsNodeToSelect (W) )
940
+ if (!W-> isMachineOpcode () && W-> getOpcode () == HexagonISD::ISEL )
967
941
Nodes.push_back (W);
968
942
for (unsigned j = 0 , f = W->getNumOperands (); j != f; ++j)
969
943
WorkQ.insert (W->getOperand (j).getNode ());
970
944
}
971
945
972
946
for (SDNode *L : Nodes)
973
- ISel. Select (L);
947
+ select (L);
974
948
975
949
return !Nodes.empty ();
976
950
}
@@ -1358,6 +1332,82 @@ namespace {
1358
1332
};
1359
1333
}
1360
1334
1335
+ void HvxSelector::select (SDNode *ISelN) {
1336
+ // What's important here is to select the right set of nodes. The main
1337
+ // selection algorithm loops over nodes in a topological order, i.e. users
1338
+ // are visited before their operands.
1339
+ //
1340
+ // It is an error to have an unselected node with a selected operand, and
1341
+ // there is an assertion in the main selector code to enforce that.
1342
+ //
1343
+ // Such a situation could occur if we selected a node, which is both a
1344
+ // subnode of ISelN, and a subnode of an unrelated (and yet unselected)
1345
+ // node in the DAG.
1346
+ assert (ISelN->getOpcode () == HexagonISD::ISEL);
1347
+ SDNode *N0 = ISelN->getOperand (0 ).getNode ();
1348
+ if (N0->isMachineOpcode ()) {
1349
+ ISel.ReplaceNode (ISelN, N0);
1350
+ return ;
1351
+ }
1352
+
1353
+ // There could have been nodes created (i.e. inserted into the DAG)
1354
+ // that are now dead. Remove them, in case they use any of the nodes
1355
+ // to select (and make them look shared).
1356
+ DAG.RemoveDeadNodes ();
1357
+
1358
+ SetVector<SDNode*> SubNodes, TmpQ;
1359
+ std::map<SDNode*,unsigned > NumOps;
1360
+
1361
+ // Don't want to select N0 if it's shared with another node, except if
1362
+ // it's shared with other ISELs.
1363
+ auto IsISelN = [](SDNode *T) { return T->getOpcode () == HexagonISD::ISEL; };
1364
+ if (llvm::all_of (N0->uses (), IsISelN))
1365
+ SubNodes.insert (N0);
1366
+
1367
+ auto InSubNodes = [&SubNodes](SDNode *T) { return SubNodes.count (T); };
1368
+ for (unsigned I = 0 ; I != SubNodes.size (); ++I) {
1369
+ SDNode *S = SubNodes[I];
1370
+ unsigned OpN = 0 ;
1371
+ // Only add subnodes that are only reachable from N0.
1372
+ for (SDValue Op : S->ops ()) {
1373
+ SDNode *O = Op.getNode ();
1374
+ if (llvm::all_of (O->uses (), InSubNodes)) {
1375
+ SubNodes.insert (O);
1376
+ ++OpN;
1377
+ }
1378
+ }
1379
+ NumOps.insert ({S, OpN});
1380
+ if (OpN == 0 )
1381
+ TmpQ.insert (S);
1382
+ }
1383
+
1384
+ for (unsigned I = 0 ; I != TmpQ.size (); ++I) {
1385
+ SDNode *S = TmpQ[I];
1386
+ for (SDNode *U : S->uses ()) {
1387
+ if (U == ISelN)
1388
+ continue ;
1389
+ auto F = NumOps.find (U);
1390
+ assert (F != NumOps.end ());
1391
+ if (F->second > 0 && !--F->second )
1392
+ TmpQ.insert (F->first );
1393
+ }
1394
+ }
1395
+
1396
+ // Remove the marker.
1397
+ ISel.ReplaceNode (ISelN, N0);
1398
+
1399
+ assert (SubNodes.size () == TmpQ.size ());
1400
+ NullifyingVector<decltype (TmpQ)::vector_type> Queue (TmpQ.takeVector ());
1401
+
1402
+ Deleter DUQ (DAG, Queue);
1403
+ for (SDNode *S : reverse (Queue)) {
1404
+ if (S == nullptr )
1405
+ continue ;
1406
+ DEBUG_WITH_TYPE (" isel" , {dbgs () << " HVX selecting: " ; S->dump (&DAG);});
1407
+ ISel.Select (S);
1408
+ }
1409
+ }
1410
+
1361
1411
bool HvxSelector::scalarizeShuffle (ArrayRef<int > Mask, const SDLoc &dl,
1362
1412
MVT ResTy, SDValue Va, SDValue Vb,
1363
1413
SDNode *N) {
@@ -1379,12 +1429,7 @@ bool HvxSelector::scalarizeShuffle(ArrayRef<int> Mask, const SDLoc &dl,
1379
1429
// nodes, these nodes would not be selected (since the "local" selection
1380
1430
// only visits nodes that are not in AllNodes).
1381
1431
// To avoid this issue, remove all dead nodes from the DAG now.
1382
- DAG.RemoveDeadNodes ();
1383
- DenseSet<SDNode*> AllNodes;
1384
- for (SDNode &S : DAG.allnodes ())
1385
- AllNodes.insert (&S);
1386
-
1387
- Deleter DUA (DAG, AllNodes);
1432
+ // DAG.RemoveDeadNodes();
1388
1433
1389
1434
SmallVector<SDValue,128 > Ops;
1390
1435
LLVMContext &Ctx = *DAG.getContext ();
@@ -1434,57 +1479,9 @@ bool HvxSelector::scalarizeShuffle(ArrayRef<int> Mask, const SDLoc &dl,
1434
1479
}
1435
1480
1436
1481
assert (!N->use_empty ());
1437
- ISel.ReplaceNode (N, LV.getNode ());
1438
-
1439
- if (AllNodes.count (LV.getNode ())) {
1440
- DAG.RemoveDeadNodes ();
1441
- return true ;
1442
- }
1443
-
1444
- // The lowered build-vector node will now need to be selected. It needs
1445
- // to be done here because this node and its submodes are not included
1446
- // in the main selection loop.
1447
- // Implement essentially the same topological ordering algorithm as is
1448
- // used in SelectionDAGISel.
1449
-
1450
- SetVector<SDNode*> SubNodes, TmpQ;
1451
- std::map<SDNode*,unsigned > NumOps;
1452
-
1453
- SubNodes.insert (LV.getNode ());
1454
- for (unsigned I = 0 ; I != SubNodes.size (); ++I) {
1455
- unsigned OpN = 0 ;
1456
- SDNode *S = SubNodes[I];
1457
- for (SDValue Op : S->ops ()) {
1458
- if (AllNodes.count (Op.getNode ()))
1459
- continue ;
1460
- SubNodes.insert (Op.getNode ());
1461
- ++OpN;
1462
- }
1463
- NumOps.insert ({S, OpN});
1464
- if (OpN == 0 )
1465
- TmpQ.insert (S);
1466
- }
1467
-
1468
- for (unsigned I = 0 ; I != TmpQ.size (); ++I) {
1469
- SDNode *S = TmpQ[I];
1470
- for (SDNode *U : S->uses ()) {
1471
- if (!SubNodes.count (U))
1472
- continue ;
1473
- auto F = NumOps.find (U);
1474
- assert (F != NumOps.end ());
1475
- assert (F->second > 0 );
1476
- if (!--F->second )
1477
- TmpQ.insert (F->first );
1478
- }
1479
- }
1480
- assert (SubNodes.size () == TmpQ.size ());
1481
- NullifyingVector<decltype (TmpQ)::vector_type> Queue (TmpQ.takeVector ());
1482
-
1483
- Deleter DUQ (DAG, Queue);
1484
- for (SDNode *S : reverse (Queue))
1485
- if (S != nullptr )
1486
- ISel.Select (S);
1487
-
1482
+ SDValue IS = DAG.getNode (HexagonISD::ISEL, dl, ResTy, LV);
1483
+ ISel.ReplaceNode (N, IS.getNode ());
1484
+ select (IS.getNode ());
1488
1485
DAG.RemoveDeadNodes ();
1489
1486
return true ;
1490
1487
}
@@ -2014,7 +2011,7 @@ SDValue HvxSelector::getVectorConstant(ArrayRef<uint8_t> Data,
2014
2011
SDValue BV = DAG.getBuildVector (VecTy, dl, Elems);
2015
2012
SDValue LV = Lower.LowerOperation (BV, DAG);
2016
2013
DAG.RemoveDeadNode (BV.getNode ());
2017
- return LV ;
2014
+ return DAG. getNode (HexagonISD::ISEL, dl, VecTy, LV) ;
2018
2015
}
2019
2016
2020
2017
void HvxSelector::selectShuffle (SDNode *N) {
0 commit comments