@@ -347,6 +347,9 @@ class SystemZDAGToDAGISel : public SelectionDAGISel {
347
347
// Try to expand a boolean SELECT_CCMASK using an IPM sequence.
348
348
SDValue expandSelectBoolean (SDNode *Node);
349
349
350
+ // Convert ATOMIC_LOADs to LOADs to facilitate instruction selection.
351
+ void convertATOMIC_LOADs (SDNode *Node, unsigned Depth = 0 );
352
+
350
353
public:
351
354
static char ID;
352
355
@@ -1513,6 +1516,10 @@ bool SystemZDAGToDAGISel::storeLoadIsAligned(SDNode *N) const {
1513
1516
MachineMemOperand *MMO = MemAccess->getMemOperand ();
1514
1517
assert (MMO && " Expected a memory operand." );
1515
1518
1519
+ // These instructions are not atomic.
1520
+ if (MMO->isAtomic ())
1521
+ return false ;
1522
+
1516
1523
// The memory access must have a proper alignment and no index register.
1517
1524
if (MemAccess->getAlign ().value () < StoreSize ||
1518
1525
!MemAccess->getOffset ().isUndef ())
@@ -1545,6 +1552,37 @@ bool SystemZDAGToDAGISel::storeLoadIsAligned(SDNode *N) const {
1545
1552
return true ;
1546
1553
}
1547
1554
1555
+ // This is a hack to convert ATOMIC_LOADs to LOADs in the last minute just
1556
+ // before instruction selection begins. It would have been easier if
1557
+ // ATOMIC_LOAD nodes would instead always be built by SelectionDAGBuilder as
1558
+ // LOADs with an atomic MMO and properly handled as such in DAGCombiner, but
1559
+ // until that changes they need to remain as ATOMIC_LOADs until all
1560
+ // DAGCombining is done. Convert Node or any of its operands from
1561
+ // ATOMIC_LOAD to LOAD.
1562
+ void SystemZDAGToDAGISel::convertATOMIC_LOADs (SDNode *Node, unsigned Depth) {
1563
+ if (Depth > 1 ) // Chain operands are also followed so this seems enough.
1564
+ return ;
1565
+ if (Node->getOpcode () == ISD::ATOMIC_LOAD) {
1566
+ auto *ALoad = cast<AtomicSDNode>(Node);
1567
+ // It seems necessary to morph the node as it is not yet being selected.
1568
+ LoadSDNode *Ld = cast<LoadSDNode>(CurDAG->MorphNodeTo (
1569
+ ALoad, ISD::LOAD, CurDAG->getVTList (ALoad->getValueType (0 ), MVT::Other),
1570
+ {ALoad->getChain (), ALoad->getBasePtr ()}));
1571
+ // Sanity check the morph. The extension type for an extending load
1572
+ // should have been set prior to instruction selection and remain in the
1573
+ // morphed node.
1574
+ assert (((SDNode *)Ld) == ((SDNode *)ALoad) && " Bad CSE on atomic load." );
1575
+ assert (Ld->getMemOperand ()->isAtomic () && " Broken MMO." );
1576
+ ISD::LoadExtType ETy = Ld->getExtensionType ();
1577
+ bool IsNonExt = Ld->getMemoryVT ().getSizeInBits () ==
1578
+ Ld->getValueType (0 ).getSizeInBits ();
1579
+ assert (IsNonExt == (ETy == ISD::NON_EXTLOAD) && " Bad extension type." );
1580
+ return ;
1581
+ }
1582
+ for (SDValue Op : Node->ops ())
1583
+ convertATOMIC_LOADs (Op.getNode (), ++Depth);
1584
+ }
1585
+
1548
1586
void SystemZDAGToDAGISel::Select (SDNode *Node) {
1549
1587
// If we have a custom node, we already have selected!
1550
1588
if (Node->isMachineOpcode ()) {
@@ -1553,6 +1591,9 @@ void SystemZDAGToDAGISel::Select(SDNode *Node) {
1553
1591
return ;
1554
1592
}
1555
1593
1594
+ // Prepare any ATOMIC_LOAD to be selected as a LOAD with an atomic MMO.
1595
+ convertATOMIC_LOADs (Node);
1596
+
1556
1597
unsigned Opcode = Node->getOpcode ();
1557
1598
switch (Opcode) {
1558
1599
case ISD::OR:
@@ -1742,6 +1783,31 @@ void SystemZDAGToDAGISel::Select(SDNode *Node) {
1742
1783
}
1743
1784
break ;
1744
1785
}
1786
+
1787
+ case ISD::ATOMIC_STORE: {
1788
+ auto *AtomOp = cast<AtomicSDNode>(Node);
1789
+ // Store FP values directly without first moving to a GPR.
1790
+ EVT SVT = AtomOp->getMemoryVT ();
1791
+ SDValue StoredVal = AtomOp->getVal ();
1792
+ if (SVT.isInteger () && StoredVal->getOpcode () == ISD::BITCAST &&
1793
+ StoredVal->getOperand (0 ).getValueType ().isFloatingPoint ()) {
1794
+ StoredVal = StoredVal->getOperand (0 );
1795
+ SVT = StoredVal.getValueType ();
1796
+ }
1797
+ StoreSDNode *St = cast<StoreSDNode>(CurDAG->getTruncStore (
1798
+ AtomOp->getChain (), SDLoc (AtomOp), StoredVal, AtomOp->getBasePtr (), SVT,
1799
+ AtomOp->getMemOperand ()));
1800
+ assert (St->getMemOperand ()->isAtomic () && " Broken MMO." );
1801
+ SDNode *Chain = St;
1802
+ // We have to enforce sequential consistency by performing a
1803
+ // serialization operation after the store.
1804
+ if (AtomOp->getSuccessOrdering () == AtomicOrdering::SequentiallyConsistent)
1805
+ Chain = CurDAG->getMachineNode (SystemZ::Serialize, SDLoc (AtomOp),
1806
+ MVT::Other, SDValue (Chain, 0 ));
1807
+ ReplaceNode (Node, Chain);
1808
+ SelectCode (St);
1809
+ return ;
1810
+ }
1745
1811
}
1746
1812
1747
1813
SelectCode (Node);
0 commit comments