[llvm] 8ea447b - [SDAG] Set InBounds when when computing offsets into memory objects (#165425)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Oct 31 03:27:58 PDT 2025
Author: Fabian Ritter
Date: 2025-10-31T11:27:55+01:00
New Revision: 8ea447b4c4b007ea1c736f71e569fda621f4fdc8
URL: https://github.com/llvm/llvm-project/commit/8ea447b4c4b007ea1c736f71e569fda621f4fdc8
DIFF: https://github.com/llvm/llvm-project/commit/8ea447b4c4b007ea1c736f71e569fda621f4fdc8.diff
LOG: [SDAG] Set InBounds when when computing offsets into memory objects (#165425)
When a load or store accesses N bytes starting from a pointer P, and we want to
compute an offset pointer within these N bytes after P, we know that the
arithmetic to add the offset must be inbounds. This is for example relevant
when legalizing too-wide memory accesses, when lowering memcpy&Co., or when
optimizing "vector-load -> extractelement" into an offset load.
For SWDEV-516125.
Added:
Modified:
llvm/include/llvm/CodeGen/SelectionDAG.h
llvm/include/llvm/CodeGen/TargetLowering.h
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h
index df6ce0fe1b037..1a5ffb38f2568 100644
--- a/llvm/include/llvm/CodeGen/SelectionDAG.h
+++ b/llvm/include/llvm/CodeGen/SelectionDAG.h
@@ -1113,7 +1113,8 @@ class SelectionDAG {
SDValue Mask, SDValue EVL);
/// Returns sum of the base pointer and offset.
- /// Unlike getObjectPtrOffset this does not set NoUnsignedWrap by default.
+ /// Unlike getObjectPtrOffset this does not set NoUnsignedWrap and InBounds by
+ /// default.
LLVM_ABI SDValue
getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL,
const SDNodeFlags Flags = SDNodeFlags());
@@ -1123,15 +1124,18 @@ class SelectionDAG {
/// Create an add instruction with appropriate flags when used for
/// addressing some offset of an object. i.e. if a load is split into multiple
- /// components, create an add nuw from the base pointer to the offset.
+ /// components, create an add nuw (or ptradd nuw inbounds) from the base
+ /// pointer to the offset.
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset) {
- return getMemBasePlusOffset(Ptr, Offset, SL, SDNodeFlags::NoUnsignedWrap);
+ return getMemBasePlusOffset(
+ Ptr, Offset, SL, SDNodeFlags::NoUnsignedWrap | SDNodeFlags::InBounds);
}
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, SDValue Offset) {
// The object itself can't wrap around the address space, so it shouldn't be
// possible for the adds of the offsets to the split parts to overflow.
- return getMemBasePlusOffset(Ptr, Offset, SL, SDNodeFlags::NoUnsignedWrap);
+ return getMemBasePlusOffset(
+ Ptr, Offset, SL, SDNodeFlags::NoUnsignedWrap | SDNodeFlags::InBounds);
}
/// Return a new CALLSEQ_START node, that starts new call frame, in which
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 1920b98c8a1ef..78f63b4406eb0 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -5649,17 +5649,35 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
/// Get a pointer to vector element \p Idx located in memory for a vector of
/// type \p VecVT starting at a base address of \p VecPtr. If \p Idx is out of
/// bounds the returned pointer is unspecified, but will be within the vector
- /// bounds.
- SDValue getVectorElementPointer(SelectionDAG &DAG, SDValue VecPtr, EVT VecVT,
- SDValue Index) const;
+ /// bounds. \p PtrArithFlags can be used to mark that arithmetic within the
+ /// vector in memory is known to not wrap or to be inbounds.
+ SDValue getVectorElementPointer(
+ SelectionDAG &DAG, SDValue VecPtr, EVT VecVT, SDValue Index,
+ const SDNodeFlags PtrArithFlags = SDNodeFlags()) const;
+
+ /// Get a pointer to vector element \p Idx located in memory for a vector of
+ /// type \p VecVT starting at a base address of \p VecPtr. If \p Idx is out of
+ /// bounds the returned pointer is unspecified, but will be within the vector
+ /// bounds. \p VecPtr is guaranteed to point to the beginning of a memory
+ /// location large enough for the vector.
+ SDValue getInboundsVectorElementPointer(SelectionDAG &DAG, SDValue VecPtr,
+ EVT VecVT, SDValue Index) const {
+ return getVectorElementPointer(DAG, VecPtr, VecVT, Index,
+ SDNodeFlags::NoUnsignedWrap |
+ SDNodeFlags::InBounds);
+ }
/// Get a pointer to a sub-vector of type \p SubVecVT at index \p Idx located
/// in memory for a vector of type \p VecVT starting at a base address of
/// \p VecPtr. If \p Idx plus the size of \p SubVecVT is out of bounds the
/// returned pointer is unspecified, but the value returned will be such that
- /// the entire subvector would be within the vector bounds.
- SDValue getVectorSubVecPointer(SelectionDAG &DAG, SDValue VecPtr, EVT VecVT,
- EVT SubVecVT, SDValue Index) const;
+ /// the entire subvector would be within the vector bounds. \p PtrArithFlags
+ /// can be used to mark that arithmetic within the vector in memory is known
+ /// to not wrap or to be inbounds.
+ SDValue
+ getVectorSubVecPointer(SelectionDAG &DAG, SDValue VecPtr, EVT VecVT,
+ EVT SubVecVT, SDValue Index,
+ const SDNodeFlags PtrArithFlags = SDNodeFlags()) const;
/// Method for building the DAG expansion of ISD::[US][MIN|MAX]. This
/// method accepts integers as its arguments.
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 893556bd85240..bdd6bf025b645 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -22760,7 +22760,10 @@ SDValue DAGCombiner::replaceStoreOfInsertLoad(StoreSDNode *ST) {
NewPtr = DAG.getMemBasePlusOffset(Ptr, TypeSize::getFixed(COffset), DL);
PointerInfo = ST->getPointerInfo().getWithOffset(COffset);
} else {
- NewPtr = TLI.getVectorElementPointer(DAG, Ptr, Value.getValueType(), Idx);
+ // The original DAG loaded the entire vector from memory, so arithmetic
+ // within it must be inbounds.
+ NewPtr = TLI.getInboundsVectorElementPointer(DAG, Ptr, Value.getValueType(),
+ Idx);
}
return DAG.getStore(Chain, DL, Elt, NewPtr, PointerInfo, ST->getAlign(),
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index da4e40953b39a..9bdf82210fed1 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -10668,19 +10668,20 @@ static SDValue clampDynamicVectorIndex(SelectionDAG &DAG, SDValue Idx,
DAG.getConstant(MaxIndex, dl, IdxVT));
}
-SDValue TargetLowering::getVectorElementPointer(SelectionDAG &DAG,
- SDValue VecPtr, EVT VecVT,
- SDValue Index) const {
+SDValue
+TargetLowering::getVectorElementPointer(SelectionDAG &DAG, SDValue VecPtr,
+ EVT VecVT, SDValue Index,
+ const SDNodeFlags PtrArithFlags) const {
return getVectorSubVecPointer(
DAG, VecPtr, VecVT,
EVT::getVectorVT(*DAG.getContext(), VecVT.getVectorElementType(), 1),
- Index);
+ Index, PtrArithFlags);
}
-SDValue TargetLowering::getVectorSubVecPointer(SelectionDAG &DAG,
- SDValue VecPtr, EVT VecVT,
- EVT SubVecVT,
- SDValue Index) const {
+SDValue
+TargetLowering::getVectorSubVecPointer(SelectionDAG &DAG, SDValue VecPtr,
+ EVT VecVT, EVT SubVecVT, SDValue Index,
+ const SDNodeFlags PtrArithFlags) const {
SDLoc dl(Index);
// Make sure the index type is big enough to compute in.
Index = DAG.getZExtOrTrunc(Index, dl, VecPtr.getValueType());
@@ -10704,7 +10705,7 @@ SDValue TargetLowering::getVectorSubVecPointer(SelectionDAG &DAG,
Index = DAG.getNode(ISD::MUL, dl, IdxVT, Index,
DAG.getConstant(EltSize, dl, IdxVT));
- return DAG.getMemBasePlusOffset(VecPtr, Index, dl);
+ return DAG.getMemBasePlusOffset(VecPtr, Index, dl, PtrArithFlags);
}
//===----------------------------------------------------------------------===//
@@ -12382,8 +12383,10 @@ SDValue TargetLowering::scalarizeExtractedVectorLoad(EVT ResultVT,
!IsFast)
return SDValue();
- SDValue NewPtr =
- getVectorElementPointer(DAG, OriginalLoad->getBasePtr(), InVecVT, EltNo);
+ // The original DAG loaded the entire vector from memory, so arithmetic
+ // within it must be inbounds.
+ SDValue NewPtr = getInboundsVectorElementPointer(
+ DAG, OriginalLoad->getBasePtr(), InVecVT, EltNo);
// We are replacing a vector load with a scalar load. The new load must have
// identical memory op ordering to the original.
More information about the llvm-commits
mailing list