Skip to content

Commit ddba819

Browse files
committed
[SystemZ] Don't lower ATOMIC_[LOAD|STORE] to [LOAD|STORE]
(Use PatFrags for loads.) Try to convert to LOAD in select() instead. Was e20dad7
1 parent 9e73656 commit ddba819

File tree

12 files changed

+945
-59
lines changed

12 files changed

+945
-59
lines changed

llvm/include/llvm/CodeGen/SelectionDAGNodes.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,7 @@ BEGIN_TWO_BYTE_PACK()
558558

559559
class LoadSDNodeBitfields {
560560
friend class LoadSDNode;
561+
friend class AtomicSDNode;
561562
friend class VPLoadSDNode;
562563
friend class VPStridedLoadSDNode;
563564
friend class MaskedLoadSDNode;
@@ -1473,6 +1474,16 @@ class AtomicSDNode : public MemSDNode {
14731474
MMO->isAtomic()) && "then why are we using an AtomicSDNode?");
14741475
}
14751476

1477+
void setExtensionType(ISD::LoadExtType ETy) {
1478+
assert(getOpcode() == ISD::ATOMIC_LOAD && "Only used for atomic loads.");
1479+
LoadSDNodeBits.ExtTy = ETy;
1480+
}
1481+
1482+
ISD::LoadExtType getExtensionType() const {
1483+
assert(getOpcode() == ISD::ATOMIC_LOAD && "Only used for atomic loads.");
1484+
return static_cast<ISD::LoadExtType>(LoadSDNodeBits.ExtTy);
1485+
}
1486+
14761487
const SDValue &getBasePtr() const {
14771488
return getOpcode() == ISD::ATOMIC_STORE ? getOperand(2) : getOperand(1);
14781489
}

llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,19 @@ SDValue DAGTypeLegalizer::PromoteIntRes_Atomic0(AtomicSDNode *N) {
340340
N->getMemoryVT(), ResVT,
341341
N->getChain(), N->getBasePtr(),
342342
N->getMemOperand());
343+
if (N->getOpcode() == ISD::ATOMIC_LOAD) {
344+
ISD::LoadExtType ETy = cast<AtomicSDNode>(N)->getExtensionType();
345+
if (ETy == ISD::NON_EXTLOAD) {
346+
if (TLI.getExtendForAtomicOps() == ISD::SIGN_EXTEND)
347+
ETy = ISD::SEXTLOAD;
348+
else if (TLI.getExtendForAtomicOps() == ISD::ZERO_EXTEND)
349+
ETy = ISD::ZEXTLOAD;
350+
else
351+
ETy = ISD::EXTLOAD;
352+
}
353+
cast<AtomicSDNode>(Res)->setExtensionType(ETy);
354+
}
355+
343356
// Legalize the chain result - switch anything that used the old chain to
344357
// use the new one.
345358
ReplaceValueWith(SDValue(N, 1), Res.getValue(1));

llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4037,6 +4037,9 @@ KnownBits SelectionDAG::computeKnownBits(SDValue Op, const APInt &DemandedElts,
40374037
if (Op.getResNo() == 0) {
40384038
if (TLI->getExtendForAtomicOps() == ISD::ZERO_EXTEND)
40394039
Known.Zero.setBitsFrom(MemBits);
4040+
else if (Op->getOpcode() == ISD::ATOMIC_LOAD &&
4041+
cast<AtomicSDNode>(Op)->getExtensionType() == ISD::ZEXTLOAD)
4042+
Known.Zero.setBitsFrom(MemBits);
40404043
}
40414044
break;
40424045
}
@@ -4848,6 +4851,13 @@ unsigned SelectionDAG::ComputeNumSignBits(SDValue Op, const APInt &DemandedElts,
48484851
return VTBits - Tmp + 1;
48494852
if (TLI->getExtendForAtomicOps() == ISD::ZERO_EXTEND)
48504853
return VTBits - Tmp;
4854+
if (Op->getOpcode() == ISD::ATOMIC_LOAD) {
4855+
ISD::LoadExtType ETy = cast<AtomicSDNode>(Op)->getExtensionType();
4856+
if (ETy == ISD::SEXTLOAD)
4857+
return VTBits - Tmp + 1;
4858+
if (ETy == ISD::ZEXTLOAD)
4859+
return VTBits - Tmp;
4860+
}
48514861
}
48524862
break;
48534863
}

llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,18 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const {
828828
} else if (const MemSDNode *M = dyn_cast<MemSDNode>(this)) {
829829
OS << "<";
830830
printMemOperand(OS, *M->getMemOperand(), G);
831+
if (auto *A = dyn_cast<AtomicSDNode>(M))
832+
if (A->getOpcode() == ISD::ATOMIC_LOAD) {
833+
bool doExt = true;
834+
switch (A->getExtensionType()) {
835+
default: doExt = false; break;
836+
case ISD::EXTLOAD: OS << ", anyext"; break;
837+
case ISD::SEXTLOAD: OS << ", sext"; break;
838+
case ISD::ZEXTLOAD: OS << ", zext"; break;
839+
}
840+
if (doExt)
841+
OS << " from " << A->getMemoryVT();
842+
}
831843
OS << ">";
832844
} else if (const BlockAddressSDNode *BA =
833845
dyn_cast<BlockAddressSDNode>(this)) {

llvm/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,9 @@ class SystemZDAGToDAGISel : public SelectionDAGISel {
347347
// Try to expand a boolean SELECT_CCMASK using an IPM sequence.
348348
SDValue expandSelectBoolean(SDNode *Node);
349349

350+
// Convert ATOMIC_LOADs to LOADs to facilitate instruction selection.
351+
void convertATOMIC_LOADs(SDNode *Node, unsigned Depth = 0);
352+
350353
public:
351354
static char ID;
352355

@@ -1513,6 +1516,10 @@ bool SystemZDAGToDAGISel::storeLoadIsAligned(SDNode *N) const {
15131516
MachineMemOperand *MMO = MemAccess->getMemOperand();
15141517
assert(MMO && "Expected a memory operand.");
15151518

1519+
// These instructions are not atomic.
1520+
if (MMO->isAtomic())
1521+
return false;
1522+
15161523
// The memory access must have a proper alignment and no index register.
15171524
if (MemAccess->getAlign().value() < StoreSize ||
15181525
!MemAccess->getOffset().isUndef())
@@ -1545,6 +1552,37 @@ bool SystemZDAGToDAGISel::storeLoadIsAligned(SDNode *N) const {
15451552
return true;
15461553
}
15471554

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+
15481586
void SystemZDAGToDAGISel::Select(SDNode *Node) {
15491587
// If we have a custom node, we already have selected!
15501588
if (Node->isMachineOpcode()) {
@@ -1553,6 +1591,9 @@ void SystemZDAGToDAGISel::Select(SDNode *Node) {
15531591
return;
15541592
}
15551593

1594+
// Prepare any ATOMIC_LOAD to be selected as a LOAD with an atomic MMO.
1595+
convertATOMIC_LOADs(Node);
1596+
15561597
unsigned Opcode = Node->getOpcode();
15571598
switch (Opcode) {
15581599
case ISD::OR:
@@ -1742,6 +1783,31 @@ void SystemZDAGToDAGISel::Select(SDNode *Node) {
17421783
}
17431784
break;
17441785
}
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+
}
17451811
}
17461812

17471813
SelectCode(Node);

0 commit comments

Comments
 (0)