Skip to content

Commit 8adcc8a

Browse files
ritter-x2adavidchisnalljrtc27arichardsonrgwott
authored
[SelectionDAG] Introduce ISD::PTRADD (#140017)
This opcode represents the addition of a pointer value (first operand) and an integer offset (second operand). PTRADD nodes are only generated if the TargetMachine opts in by overriding TargetMachine::shouldPreservePtrArith(). The PTRADD node and respective visitPTRADD() function were adapted by @rgwott from the CHERI/Morello LLVM tree. Original authors: @davidchisnall, @jrtc27, @arichardson. The changes in this PR were extracted from PR #105669. --------- Co-authored-by: David Chisnall <[email protected]> Co-authored-by: Jessica Clarke <[email protected]> Co-authored-by: Alexander Richardson <[email protected]> Co-authored-by: Rodolfo Wottrich <[email protected]>
1 parent 4528942 commit 8adcc8a

File tree

8 files changed

+50
-15
lines changed

8 files changed

+50
-15
lines changed

llvm/include/llvm/CodeGen/ISDOpcodes.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1511,6 +1511,11 @@ enum NodeType {
15111511
// Outputs: [rv], output chain, glue
15121512
PATCHPOINT,
15131513

1514+
// PTRADD represents pointer arithmetic semantics, for targets that opt in
1515+
// using shouldPreservePtrArith().
1516+
// ptr = PTRADD ptr, offset
1517+
PTRADD,
1518+
15141519
// Vector Predication
15151520
#define BEGIN_REGISTER_VP_SDNODE(VPSDID, ...) VPSDID,
15161521
#include "llvm/IR/VPIntrinsics.def"

llvm/include/llvm/CodeGen/SelectionDAGNodes.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ class SDValue {
213213
inline bool isTargetOpcode() const;
214214
inline bool isMachineOpcode() const;
215215
inline bool isUndef() const;
216+
inline bool isAnyAdd() const;
216217
inline unsigned getMachineOpcode() const;
217218
inline const DebugLoc &getDebugLoc() const;
218219
inline void dump() const;
@@ -697,6 +698,11 @@ END_TWO_BYTE_PACK()
697698
return NodeType == ISD::UNDEF || NodeType == ISD::POISON;
698699
}
699700

701+
/// Returns true if the node type is ADD or PTRADD.
702+
bool isAnyAdd() const {
703+
return NodeType == ISD::ADD || NodeType == ISD::PTRADD;
704+
}
705+
700706
/// Test if this node is a memory intrinsic (with valid pointer information).
701707
bool isMemIntrinsic() const { return SDNodeBits.IsMemIntrinsic; }
702708

@@ -1270,6 +1276,8 @@ inline bool SDValue::isUndef() const {
12701276
return Node->isUndef();
12711277
}
12721278

1279+
inline bool SDValue::isAnyAdd() const { return Node->isAnyAdd(); }
1280+
12731281
inline bool SDValue::use_empty() const {
12741282
return !Node->hasAnyUseOfValue(ResNo);
12751283
}

llvm/include/llvm/CodeGen/TargetLowering.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3487,6 +3487,15 @@ class TargetLoweringBase {
34873487
/// doing arithmetic on boolean types
34883488
virtual bool shouldExpandCmpUsingSelects(EVT VT) const { return false; }
34893489

3490+
/// True if target has some particular form of dealing with pointer arithmetic
3491+
/// semantics for pointers with the given value type. False if pointer
3492+
/// arithmetic should not be preserved for passes such as instruction
3493+
/// selection, and can fallback to regular arithmetic.
3494+
/// This should be removed when PTRADD nodes are widely supported by backends.
3495+
virtual bool shouldPreservePtrArith(const Function &F, EVT PtrVT) const {
3496+
return false;
3497+
}
3498+
34903499
/// Does this target support complex deinterleaving
34913500
virtual bool isComplexDeinterleavingSupported() const { return false; }
34923501

llvm/include/llvm/Target/TargetSelectionDAG.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ def tblockaddress: SDNode<"ISD::TargetBlockAddress", SDTPtrLeaf, [],
407407

408408
def add : SDNode<"ISD::ADD" , SDTIntBinOp ,
409409
[SDNPCommutative, SDNPAssociative]>;
410-
def ptradd : SDNode<"ISD::ADD" , SDTPtrAddOp, []>;
410+
def ptradd : SDNode<"ISD::PTRADD" , SDTPtrAddOp, []>;
411411
def sub : SDNode<"ISD::SUB" , SDTIntBinOp>;
412412
def mul : SDNode<"ISD::MUL" , SDTIntBinOp,
413413
[SDNPCommutative, SDNPAssociative]>;

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,8 @@ namespace {
417417
SDValue visitMERGE_VALUES(SDNode *N);
418418
SDValue visitADD(SDNode *N);
419419
SDValue visitADDLike(SDNode *N);
420-
SDValue visitADDLikeCommutative(SDValue N0, SDValue N1, SDNode *LocReference);
420+
SDValue visitADDLikeCommutative(SDValue N0, SDValue N1,
421+
SDNode *LocReference);
421422
SDValue visitSUB(SDNode *N);
422423
SDValue visitADDSAT(SDNode *N);
423424
SDValue visitSUBSAT(SDNode *N);
@@ -1100,7 +1101,7 @@ bool DAGCombiner::reassociationCanBreakAddressingModePattern(unsigned Opc,
11001101
// (load/store (add, (add, x, y), offset2)) ->
11011102
// (load/store (add, (add, x, offset2), y)).
11021103

1103-
if (N0.getOpcode() != ISD::ADD)
1104+
if (!N0.isAnyAdd())
11041105
return false;
11051106

11061107
// Check for vscale addressing modes.
@@ -2393,7 +2394,7 @@ static bool canFoldInAddressingMode(SDNode *N, SDNode *Use, SelectionDAG &DAG,
23932394
}
23942395

23952396
TargetLowering::AddrMode AM;
2396-
if (N->getOpcode() == ISD::ADD) {
2397+
if (N->isAnyAdd()) {
23972398
AM.HasBaseReg = true;
23982399
ConstantSDNode *Offset = dyn_cast<ConstantSDNode>(N->getOperand(1));
23992400
if (Offset)

llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5642,7 +5642,7 @@ bool SelectionDAG::isADDLike(SDValue Op, bool NoWrap) const {
56425642

56435643
bool SelectionDAG::isBaseWithConstantOffset(SDValue Op) const {
56445644
return Op.getNumOperands() == 2 && isa<ConstantSDNode>(Op.getOperand(1)) &&
5645-
(Op.getOpcode() == ISD::ADD || isADDLike(Op));
5645+
(Op.isAnyAdd() || isADDLike(Op));
56465646
}
56475647

56485648
bool SelectionDAG::isKnownNeverNaN(SDValue Op, bool SNaN,
@@ -7351,10 +7351,18 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
73517351
case ISD::OR:
73527352
case ISD::XOR:
73537353
case ISD::ADD:
7354+
case ISD::PTRADD:
73547355
case ISD::SUB:
73557356
assert(VT.isInteger() && "This operator does not apply to FP types!");
73567357
assert(N1.getValueType() == N2.getValueType() &&
73577358
N1.getValueType() == VT && "Binary operator types must match!");
7359+
// The equal operand types requirement is unnecessarily strong for PTRADD.
7360+
// However, the SelectionDAGBuilder does not generate PTRADDs with different
7361+
// operand types, and we'd need to re-implement GEP's non-standard wrapping
7362+
// logic everywhere where PTRADDs may be folded or combined to properly
7363+
// support them. If/when we introduce pointer types to the SDAG, we will
7364+
// need to relax this constraint.
7365+
73587366
// (X ^|+- 0) -> X. This commonly occurs when legalizing i64 values, so
73597367
// it's worth handling here.
73607368
if (N2CV && N2CV->isZero())
@@ -7717,6 +7725,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
77177725
std::swap(N1, N2);
77187726
} else {
77197727
switch (Opcode) {
7728+
case ISD::PTRADD:
77207729
case ISD::SUB:
77217730
// fold op(undef, arg2) -> undef, fold op(poison, arg2) ->poison.
77227731
return N1.getOpcode() == ISD::POISON ? getPOISON(VT) : getUNDEF(VT);
@@ -7744,6 +7753,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, const SDLoc &DL, EVT VT,
77447753
return getConstant(0, DL, VT);
77457754
[[fallthrough]];
77467755
case ISD::ADD:
7756+
case ISD::PTRADD:
77477757
case ISD::SUB:
77487758
case ISD::UDIV:
77497759
case ISD::SDIV:
@@ -8165,6 +8175,9 @@ SDValue SelectionDAG::getMemBasePlusOffset(SDValue Ptr, SDValue Offset,
81658175
const SDNodeFlags Flags) {
81668176
assert(Offset.getValueType().isInteger());
81678177
EVT BasePtrVT = Ptr.getValueType();
8178+
if (TLI->shouldPreservePtrArith(this->getMachineFunction().getFunction(),
8179+
BasePtrVT))
8180+
return getNode(ISD::PTRADD, DL, BasePtrVT, Ptr, Offset, Flags);
81688181
return getNode(ISD::ADD, DL, BasePtrVT, Ptr, Offset, Flags);
81698182
}
81708183

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4284,8 +4284,8 @@ void SelectionDAGBuilder::visitGetElementPtr(const User &I) {
42844284
(int64_t(Offset) >= 0 && NW.hasNoUnsignedSignedWrap()))
42854285
Flags |= SDNodeFlags::NoUnsignedWrap;
42864286

4287-
N = DAG.getNode(ISD::ADD, dl, N.getValueType(), N,
4288-
DAG.getConstant(Offset, dl, N.getValueType()), Flags);
4287+
N = DAG.getMemBasePlusOffset(
4288+
N, DAG.getConstant(Offset, dl, N.getValueType()), dl, Flags);
42894289
}
42904290
} else {
42914291
// IdxSize is the width of the arithmetic according to IR semantics.
@@ -4329,7 +4329,7 @@ void SelectionDAGBuilder::visitGetElementPtr(const User &I) {
43294329

43304330
OffsVal = DAG.getSExtOrTrunc(OffsVal, dl, N.getValueType());
43314331

4332-
N = DAG.getNode(ISD::ADD, dl, N.getValueType(), N, OffsVal, Flags);
4332+
N = DAG.getMemBasePlusOffset(N, OffsVal, dl, Flags);
43334333
continue;
43344334
}
43354335

@@ -4389,7 +4389,7 @@ void SelectionDAGBuilder::visitGetElementPtr(const User &I) {
43894389
SDNodeFlags AddFlags;
43904390
AddFlags.setNoUnsignedWrap(NW.hasNoUnsignedWrap());
43914391

4392-
N = DAG.getNode(ISD::ADD, dl, N.getValueType(), N, IdxN, AddFlags);
4392+
N = DAG.getMemBasePlusOffset(N, IdxN, dl, AddFlags);
43934393
}
43944394
}
43954395

@@ -9173,8 +9173,7 @@ bool SelectionDAGBuilder::visitMemPCpyCall(const CallInst &I) {
91739173
Size = DAG.getSExtOrTrunc(Size, sdl, Dst.getValueType());
91749174

91759175
// Adjust return pointer to point just past the last dst byte.
9176-
SDValue DstPlusSize = DAG.getNode(ISD::ADD, sdl, Dst.getValueType(),
9177-
Dst, Size);
9176+
SDValue DstPlusSize = DAG.getMemBasePlusOffset(Dst, Size, sdl);
91789177
setValue(&I, DstPlusSize);
91799178
return true;
91809179
}
@@ -11265,10 +11264,9 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
1126511264
MachineFunction &MF = CLI.DAG.getMachineFunction();
1126611265
Align HiddenSRetAlign = MF.getFrameInfo().getObjectAlign(DemoteStackIdx);
1126711266
for (unsigned i = 0; i < NumValues; ++i) {
11268-
SDValue Add =
11269-
CLI.DAG.getNode(ISD::ADD, CLI.DL, PtrVT, DemoteStackSlot,
11270-
CLI.DAG.getConstant(Offsets[i], CLI.DL, PtrVT),
11271-
SDNodeFlags::NoUnsignedWrap);
11267+
SDValue Add = CLI.DAG.getMemBasePlusOffset(
11268+
DemoteStackSlot, CLI.DAG.getConstant(Offsets[i], CLI.DL, PtrVT),
11269+
CLI.DL, SDNodeFlags::NoUnsignedWrap);
1127211270
SDValue L = CLI.DAG.getLoad(
1127311271
RetTys[i], CLI.DL, CLI.Chain, Add,
1127411272
MachinePointerInfo::getFixedStack(CLI.DAG.getMachineFunction(),

llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
270270

271271
// Binary operators
272272
case ISD::ADD: return "add";
273+
case ISD::PTRADD: return "ptradd";
273274
case ISD::SUB: return "sub";
274275
case ISD::MUL: return "mul";
275276
case ISD::MULHU: return "mulhu";

0 commit comments

Comments
 (0)