Skip to content

Commit 4d8dda5

Browse files
committed
[SDAG] Introduce inbounds flag for pointer arithmetic
This patch introduces an inbounds SDNodeFlag, to show that a pointer addition SDNode implements an inbounds getelementptr operation (i.e., the pointer operand is in bounds wrt. the 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. A follow-up patch will start using it for AMDGPU's flat memory instructions, where the immediate offset must not affect the memory aperture of the address. A similar patch for gMIR and GlobalISel will follow. For SWDEV-516125.
1 parent 5d1a65b commit 4d8dda5

File tree

4 files changed

+14
-3
lines changed

4 files changed

+14
-3
lines changed

Diff for: llvm/include/llvm/CodeGen/SelectionDAGNodes.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -415,12 +415,15 @@ struct SDNodeFlags {
415415
Unpredictable = 1 << 13,
416416
// Compare instructions which may carry the samesign flag.
417417
SameSign = 1 << 14,
418+
// Pointer arithmetic instructions that remain in bounds, e.g., implementing
419+
// an inbounds GEP.
420+
InBounds = 1 << 15,
418421

419422
// NOTE: Please update LargestValue in LLVM_DECLARE_ENUM_AS_BITMASK below
420423
// the class definition when adding new flags.
421424

422425
PoisonGeneratingFlags = NoUnsignedWrap | NoSignedWrap | Exact | Disjoint |
423-
NonNeg | NoNaNs | NoInfs | SameSign,
426+
NonNeg | NoNaNs | NoInfs | SameSign | InBounds,
424427
FastMathFlags = NoNaNs | NoInfs | NoSignedZeros | AllowReciprocal |
425428
AllowContract | ApproximateFuncs | AllowReassociation,
426429
};
@@ -455,6 +458,7 @@ struct SDNodeFlags {
455458
void setAllowReassociation(bool b) { setFlag<AllowReassociation>(b); }
456459
void setNoFPExcept(bool b) { setFlag<NoFPExcept>(b); }
457460
void setUnpredictable(bool b) { setFlag<Unpredictable>(b); }
461+
void setInBounds(bool b) { setFlag<InBounds>(b); }
458462

459463
// These are accessors for each flag.
460464
bool hasNoUnsignedWrap() const { return Flags & NoUnsignedWrap; }
@@ -472,6 +476,7 @@ struct SDNodeFlags {
472476
bool hasAllowReassociation() const { return Flags & AllowReassociation; }
473477
bool hasNoFPExcept() const { return Flags & NoFPExcept; }
474478
bool hasUnpredictable() const { return Flags & Unpredictable; }
479+
bool hasInBounds() const { return Flags & InBounds; }
475480

476481
bool operator==(const SDNodeFlags &Other) const {
477482
return Flags == Other.Flags;
@@ -481,7 +486,7 @@ struct SDNodeFlags {
481486
};
482487

483488
LLVM_DECLARE_ENUM_AS_BITMASK(decltype(SDNodeFlags::None),
484-
SDNodeFlags::SameSign);
489+
SDNodeFlags::InBounds);
485490

486491
inline SDNodeFlags operator|(SDNodeFlags LHS, SDNodeFlags RHS) {
487492
LHS |= RHS;

Diff for: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -4293,6 +4293,7 @@ void SelectionDAGBuilder::visitGetElementPtr(const User &I) {
42934293
if (NW.hasNoUnsignedWrap() ||
42944294
(int64_t(Offset) >= 0 && NW.hasNoUnsignedSignedWrap()))
42954295
Flags |= SDNodeFlags::NoUnsignedWrap;
4296+
Flags.setInBounds(NW.isInBounds());
42964297

42974298
N = DAG.getNode(ISD::ADD, dl, N.getValueType(), N,
42984299
DAG.getConstant(Offset, dl, N.getValueType()), Flags);
@@ -4336,6 +4337,7 @@ void SelectionDAGBuilder::visitGetElementPtr(const User &I) {
43364337
if (NW.hasNoUnsignedWrap() ||
43374338
(Offs.isNonNegative() && NW.hasNoUnsignedSignedWrap()))
43384339
Flags.setNoUnsignedWrap(true);
4340+
Flags.setInBounds(NW.isInBounds());
43394341

43404342
OffsVal = DAG.getSExtOrTrunc(OffsVal, dl, N.getValueType());
43414343

@@ -4398,6 +4400,7 @@ void SelectionDAGBuilder::visitGetElementPtr(const User &I) {
43984400
// pointer index type (add nuw).
43994401
SDNodeFlags AddFlags;
44004402
AddFlags.setNoUnsignedWrap(NW.hasNoUnsignedWrap());
4403+
AddFlags.setInBounds(NW.isInBounds());
44014404

44024405
N = DAG.getNode(ISD::ADD, dl, N.getValueType(), N, IdxN, AddFlags);
44034406
}

Diff for: llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,9 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const {
663663
if (getFlags().hasSameSign())
664664
OS << " samesign";
665665

666+
if (getFlags().hasInBounds())
667+
OS << " inbounds";
668+
666669
if (getFlags().hasNonNeg())
667670
OS << " nneg";
668671

Diff for: llvm/test/CodeGen/X86/merge-store-partially-alias-loads.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
; DBGDAG-LABEL: Optimized legalized selection DAG: %bb.0 'merge_store_partial_overlap_load:'
1717
; DBGDAG: [[ENTRYTOKEN:t[0-9]+]]: ch,glue = EntryToken
1818
; DBGDAG-DAG: [[BASEPTR:t[0-9]+]]: i64,ch = CopyFromReg [[ENTRYTOKEN]],
19-
; DBGDAG-DAG: [[ADDPTR:t[0-9]+]]: i64 = add {{(nuw )?}}[[BASEPTR]], Constant:i64<2>
19+
; DBGDAG-DAG: [[ADDPTR:t[0-9]+]]: i64 = add {{(nuw )?}}{{(inbounds )?}}[[BASEPTR]], Constant:i64<2>
2020

2121
; DBGDAG-DAG: [[LD2:t[0-9]+]]: i16,ch = load<(load (s16) from %ir.tmp81, align 1)> [[ENTRYTOKEN]], [[BASEPTR]], undef:i64
2222
; DBGDAG-DAG: [[LD1:t[0-9]+]]: i8,ch = load<(load (s8) from %ir.tmp12)> [[ENTRYTOKEN]], [[ADDPTR]], undef:i64

0 commit comments

Comments
 (0)