Skip to content

Commit d4fe78e

Browse files
ritter-x2amikolaj-pirog
authored andcommitted
[SDAG] Introduce inbounds flag for ISD::PTRADD (llvm#162477)
This patch introduces SDNodeFlags::InBounds, to show that an ISD::PTRADD SDNode implements an inbounds getelementptr operation (i.e., the pointer operand is in bounds wrt. an allocated object it is based on, and the arithmetic does not change that). The flag is set in the DAG construction when lowering inbounds GEPs. Inbounds information is useful in the ISel when selecting memory instructions that perform address computations whose intermediate steps must be in the same memory region as the final result. Follow-up patches to propagate the flag in DAGCombines and to use it when lowering AMDGPU's flat memory instructions, where the immediate offset must not affect the memory aperture of the address (similar to this GISel patch: llvm#153001), are planned. This mirrors llvm#150900, which has introduced a similar flag in GlobalISel. This patch supersedes llvm#131862, which previously attempted to introduce an SDNodeFlags::InBounds flag. The difference between this PR and llvm#131862 is that there is now an ISD::PTRADD opcode (PR llvm#140017) and the InBounds flag is only defined to apply to ISD::PTRADD DAG nodes. It is therefore unambiguous that in-bounds-ness refers to a memory object into which the left operand of the PTRADD node points (in contrast to llvm#131862, where InBounds would have applied to commutative ISD::ADD nodes, so that the semantics would be more difficult to reason about). For SWDEV-516125.
1 parent 439e467 commit d4fe78e

File tree

4 files changed

+23
-3
lines changed

4 files changed

+23
-3
lines changed

llvm/include/llvm/CodeGen/SelectionDAGNodes.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -418,12 +418,21 @@ struct SDNodeFlags {
418418
Unpredictable = 1 << 13,
419419
// Compare instructions which may carry the samesign flag.
420420
SameSign = 1 << 14,
421+
// ISD::PTRADD operations that remain in bounds, i.e., the left operand is
422+
// an address in a memory object in which the result of the operation also
423+
// lies. WARNING: Since SDAG generally uses integers instead of pointer
424+
// types, a PTRADD's pointer operand is effectively the result of an
425+
// implicit inttoptr cast. Therefore, when an inbounds PTRADD uses a
426+
// pointer P, transformations cannot assume that P has the provenance
427+
// implied by its producer as, e.g, operations between producer and PTRADD
428+
// that affect the provenance may have been optimized away.
429+
InBounds = 1 << 15,
421430

422431
// NOTE: Please update LargestValue in LLVM_DECLARE_ENUM_AS_BITMASK below
423432
// the class definition when adding new flags.
424433

425434
PoisonGeneratingFlags = NoUnsignedWrap | NoSignedWrap | Exact | Disjoint |
426-
NonNeg | NoNaNs | NoInfs | SameSign,
435+
NonNeg | NoNaNs | NoInfs | SameSign | InBounds,
427436
FastMathFlags = NoNaNs | NoInfs | NoSignedZeros | AllowReciprocal |
428437
AllowContract | ApproximateFuncs | AllowReassociation,
429438
};
@@ -458,6 +467,7 @@ struct SDNodeFlags {
458467
void setAllowReassociation(bool b) { setFlag<AllowReassociation>(b); }
459468
void setNoFPExcept(bool b) { setFlag<NoFPExcept>(b); }
460469
void setUnpredictable(bool b) { setFlag<Unpredictable>(b); }
470+
void setInBounds(bool b) { setFlag<InBounds>(b); }
461471

462472
// These are accessors for each flag.
463473
bool hasNoUnsignedWrap() const { return Flags & NoUnsignedWrap; }
@@ -475,6 +485,7 @@ struct SDNodeFlags {
475485
bool hasAllowReassociation() const { return Flags & AllowReassociation; }
476486
bool hasNoFPExcept() const { return Flags & NoFPExcept; }
477487
bool hasUnpredictable() const { return Flags & Unpredictable; }
488+
bool hasInBounds() const { return Flags & InBounds; }
478489

479490
bool operator==(const SDNodeFlags &Other) const {
480491
return Flags == Other.Flags;
@@ -484,7 +495,7 @@ struct SDNodeFlags {
484495
};
485496

486497
LLVM_DECLARE_ENUM_AS_BITMASK(decltype(SDNodeFlags::None),
487-
SDNodeFlags::SameSign);
498+
SDNodeFlags::InBounds);
488499

489500
inline SDNodeFlags operator|(SDNodeFlags LHS, SDNodeFlags RHS) {
490501
LHS |= RHS;

llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8620,7 +8620,10 @@ SDValue SelectionDAG::getMemBasePlusOffset(SDValue Ptr, SDValue Offset,
86208620
if (TLI->shouldPreservePtrArith(this->getMachineFunction().getFunction(),
86218621
BasePtrVT))
86228622
return getNode(ISD::PTRADD, DL, BasePtrVT, Ptr, Offset, Flags);
8623-
return getNode(ISD::ADD, DL, BasePtrVT, Ptr, Offset, Flags);
8623+
// InBounds only applies to PTRADD, don't set it if we generate ADD.
8624+
SDNodeFlags AddFlags = Flags;
8625+
AddFlags.setInBounds(false);
8626+
return getNode(ISD::ADD, DL, BasePtrVT, Ptr, Offset, AddFlags);
86248627
}
86258628

86268629
/// Returns true if memcpy source is constant data.

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4390,6 +4390,7 @@ void SelectionDAGBuilder::visitGetElementPtr(const User &I) {
43904390
if (NW.hasNoUnsignedWrap() ||
43914391
(int64_t(Offset) >= 0 && NW.hasNoUnsignedSignedWrap()))
43924392
Flags |= SDNodeFlags::NoUnsignedWrap;
4393+
Flags.setInBounds(NW.isInBounds());
43934394

43944395
N = DAG.getMemBasePlusOffset(
43954396
N, DAG.getConstant(Offset, dl, N.getValueType()), dl, Flags);
@@ -4433,6 +4434,7 @@ void SelectionDAGBuilder::visitGetElementPtr(const User &I) {
44334434
if (NW.hasNoUnsignedWrap() ||
44344435
(Offs.isNonNegative() && NW.hasNoUnsignedSignedWrap()))
44354436
Flags.setNoUnsignedWrap(true);
4437+
Flags.setInBounds(NW.isInBounds());
44364438

44374439
OffsVal = DAG.getSExtOrTrunc(OffsVal, dl, N.getValueType());
44384440

@@ -4502,6 +4504,7 @@ void SelectionDAGBuilder::visitGetElementPtr(const User &I) {
45024504
// pointer index type (add nuw).
45034505
SDNodeFlags AddFlags;
45044506
AddFlags.setNoUnsignedWrap(NW.hasNoUnsignedWrap());
4507+
AddFlags.setInBounds(NW.isInBounds());
45054508

45064509
N = DAG.getMemBasePlusOffset(N, IdxN, dl, AddFlags);
45074510
}

llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,9 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const {
689689
if (getFlags().hasSameSign())
690690
OS << " samesign";
691691

692+
if (getFlags().hasInBounds())
693+
OS << " inbounds";
694+
692695
if (getFlags().hasNonNeg())
693696
OS << " nneg";
694697

0 commit comments

Comments
 (0)