Skip to content

Commit 8ea447b

Browse files
authored
[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.
1 parent 10fbbb6 commit 8ea447b

File tree

4 files changed

+50
-22
lines changed

4 files changed

+50
-22
lines changed

llvm/include/llvm/CodeGen/SelectionDAG.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,7 +1113,8 @@ class SelectionDAG {
11131113
SDValue Mask, SDValue EVL);
11141114

11151115
/// Returns sum of the base pointer and offset.
1116-
/// Unlike getObjectPtrOffset this does not set NoUnsignedWrap by default.
1116+
/// Unlike getObjectPtrOffset this does not set NoUnsignedWrap and InBounds by
1117+
/// default.
11171118
LLVM_ABI SDValue
11181119
getMemBasePlusOffset(SDValue Base, TypeSize Offset, const SDLoc &DL,
11191120
const SDNodeFlags Flags = SDNodeFlags());
@@ -1123,15 +1124,18 @@ class SelectionDAG {
11231124

11241125
/// Create an add instruction with appropriate flags when used for
11251126
/// addressing some offset of an object. i.e. if a load is split into multiple
1126-
/// components, create an add nuw from the base pointer to the offset.
1127+
/// components, create an add nuw (or ptradd nuw inbounds) from the base
1128+
/// pointer to the offset.
11271129
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, TypeSize Offset) {
1128-
return getMemBasePlusOffset(Ptr, Offset, SL, SDNodeFlags::NoUnsignedWrap);
1130+
return getMemBasePlusOffset(
1131+
Ptr, Offset, SL, SDNodeFlags::NoUnsignedWrap | SDNodeFlags::InBounds);
11291132
}
11301133

11311134
SDValue getObjectPtrOffset(const SDLoc &SL, SDValue Ptr, SDValue Offset) {
11321135
// The object itself can't wrap around the address space, so it shouldn't be
11331136
// possible for the adds of the offsets to the split parts to overflow.
1134-
return getMemBasePlusOffset(Ptr, Offset, SL, SDNodeFlags::NoUnsignedWrap);
1137+
return getMemBasePlusOffset(
1138+
Ptr, Offset, SL, SDNodeFlags::NoUnsignedWrap | SDNodeFlags::InBounds);
11351139
}
11361140

11371141
/// Return a new CALLSEQ_START node, that starts new call frame, in which

llvm/include/llvm/CodeGen/TargetLowering.h

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5649,17 +5649,35 @@ class LLVM_ABI TargetLowering : public TargetLoweringBase {
56495649
/// Get a pointer to vector element \p Idx located in memory for a vector of
56505650
/// type \p VecVT starting at a base address of \p VecPtr. If \p Idx is out of
56515651
/// bounds the returned pointer is unspecified, but will be within the vector
5652-
/// bounds.
5653-
SDValue getVectorElementPointer(SelectionDAG &DAG, SDValue VecPtr, EVT VecVT,
5654-
SDValue Index) const;
5652+
/// bounds. \p PtrArithFlags can be used to mark that arithmetic within the
5653+
/// vector in memory is known to not wrap or to be inbounds.
5654+
SDValue getVectorElementPointer(
5655+
SelectionDAG &DAG, SDValue VecPtr, EVT VecVT, SDValue Index,
5656+
const SDNodeFlags PtrArithFlags = SDNodeFlags()) const;
5657+
5658+
/// Get a pointer to vector element \p Idx located in memory for a vector of
5659+
/// type \p VecVT starting at a base address of \p VecPtr. If \p Idx is out of
5660+
/// bounds the returned pointer is unspecified, but will be within the vector
5661+
/// bounds. \p VecPtr is guaranteed to point to the beginning of a memory
5662+
/// location large enough for the vector.
5663+
SDValue getInboundsVectorElementPointer(SelectionDAG &DAG, SDValue VecPtr,
5664+
EVT VecVT, SDValue Index) const {
5665+
return getVectorElementPointer(DAG, VecPtr, VecVT, Index,
5666+
SDNodeFlags::NoUnsignedWrap |
5667+
SDNodeFlags::InBounds);
5668+
}
56555669

56565670
/// Get a pointer to a sub-vector of type \p SubVecVT at index \p Idx located
56575671
/// in memory for a vector of type \p VecVT starting at a base address of
56585672
/// \p VecPtr. If \p Idx plus the size of \p SubVecVT is out of bounds the
56595673
/// returned pointer is unspecified, but the value returned will be such that
5660-
/// the entire subvector would be within the vector bounds.
5661-
SDValue getVectorSubVecPointer(SelectionDAG &DAG, SDValue VecPtr, EVT VecVT,
5662-
EVT SubVecVT, SDValue Index) const;
5674+
/// the entire subvector would be within the vector bounds. \p PtrArithFlags
5675+
/// can be used to mark that arithmetic within the vector in memory is known
5676+
/// to not wrap or to be inbounds.
5677+
SDValue
5678+
getVectorSubVecPointer(SelectionDAG &DAG, SDValue VecPtr, EVT VecVT,
5679+
EVT SubVecVT, SDValue Index,
5680+
const SDNodeFlags PtrArithFlags = SDNodeFlags()) const;
56635681

56645682
/// Method for building the DAG expansion of ISD::[US][MIN|MAX]. This
56655683
/// method accepts integers as its arguments.

llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22760,7 +22760,10 @@ SDValue DAGCombiner::replaceStoreOfInsertLoad(StoreSDNode *ST) {
2276022760
NewPtr = DAG.getMemBasePlusOffset(Ptr, TypeSize::getFixed(COffset), DL);
2276122761
PointerInfo = ST->getPointerInfo().getWithOffset(COffset);
2276222762
} else {
22763-
NewPtr = TLI.getVectorElementPointer(DAG, Ptr, Value.getValueType(), Idx);
22763+
// The original DAG loaded the entire vector from memory, so arithmetic
22764+
// within it must be inbounds.
22765+
NewPtr = TLI.getInboundsVectorElementPointer(DAG, Ptr, Value.getValueType(),
22766+
Idx);
2276422767
}
2276522768

2276622769
return DAG.getStore(Chain, DL, Elt, NewPtr, PointerInfo, ST->getAlign(),

llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10668,19 +10668,20 @@ static SDValue clampDynamicVectorIndex(SelectionDAG &DAG, SDValue Idx,
1066810668
DAG.getConstant(MaxIndex, dl, IdxVT));
1066910669
}
1067010670

10671-
SDValue TargetLowering::getVectorElementPointer(SelectionDAG &DAG,
10672-
SDValue VecPtr, EVT VecVT,
10673-
SDValue Index) const {
10671+
SDValue
10672+
TargetLowering::getVectorElementPointer(SelectionDAG &DAG, SDValue VecPtr,
10673+
EVT VecVT, SDValue Index,
10674+
const SDNodeFlags PtrArithFlags) const {
1067410675
return getVectorSubVecPointer(
1067510676
DAG, VecPtr, VecVT,
1067610677
EVT::getVectorVT(*DAG.getContext(), VecVT.getVectorElementType(), 1),
10677-
Index);
10678+
Index, PtrArithFlags);
1067810679
}
1067910680

10680-
SDValue TargetLowering::getVectorSubVecPointer(SelectionDAG &DAG,
10681-
SDValue VecPtr, EVT VecVT,
10682-
EVT SubVecVT,
10683-
SDValue Index) const {
10681+
SDValue
10682+
TargetLowering::getVectorSubVecPointer(SelectionDAG &DAG, SDValue VecPtr,
10683+
EVT VecVT, EVT SubVecVT, SDValue Index,
10684+
const SDNodeFlags PtrArithFlags) const {
1068410685
SDLoc dl(Index);
1068510686
// Make sure the index type is big enough to compute in.
1068610687
Index = DAG.getZExtOrTrunc(Index, dl, VecPtr.getValueType());
@@ -10704,7 +10705,7 @@ SDValue TargetLowering::getVectorSubVecPointer(SelectionDAG &DAG,
1070410705

1070510706
Index = DAG.getNode(ISD::MUL, dl, IdxVT, Index,
1070610707
DAG.getConstant(EltSize, dl, IdxVT));
10707-
return DAG.getMemBasePlusOffset(VecPtr, Index, dl);
10708+
return DAG.getMemBasePlusOffset(VecPtr, Index, dl, PtrArithFlags);
1070810709
}
1070910710

1071010711
//===----------------------------------------------------------------------===//
@@ -12382,8 +12383,10 @@ SDValue TargetLowering::scalarizeExtractedVectorLoad(EVT ResultVT,
1238212383
!IsFast)
1238312384
return SDValue();
1238412385

12385-
SDValue NewPtr =
12386-
getVectorElementPointer(DAG, OriginalLoad->getBasePtr(), InVecVT, EltNo);
12386+
// The original DAG loaded the entire vector from memory, so arithmetic
12387+
// within it must be inbounds.
12388+
SDValue NewPtr = getInboundsVectorElementPointer(
12389+
DAG, OriginalLoad->getBasePtr(), InVecVT, EltNo);
1238712390

1238812391
// We are replacing a vector load with a scalar load. The new load must have
1238912392
// identical memory op ordering to the original.

0 commit comments

Comments
 (0)