Skip to content

Commit 5cdb757

Browse files
authored
[Delinearization] Remove isKnownNonNegative (#171817)
Delinearization has its own `isKnownNonNegative` function, which wraps `ScalarEvolution::isKnownNonNegative` and adds additional logic. The additional logic is that, for a pointer addrec `{a,+,b}`, if the pointer has `inbounds` and both `a` and `b` are known to be non-negative, then the addrec is also known non-negative (i.e., it doesn't wrap). This reasoning is incorrect. If the GEP and/or load/store using the pointer are not unconditionally executed in the loop, then the addrec can still wrap. Even though no actual example has been found where this causes a miscompilation (probably because the subsequent checks fail so the validation also fails), simply replacing it with `ScalarEvolution::isKnownNonNegative` is safer, especially it doesn't cause any regressions in the existing tests. Resolve #169811
1 parent 366f3ac commit 5cdb757

File tree

3 files changed

+9
-35
lines changed

3 files changed

+9
-35
lines changed

llvm/include/llvm/Analysis/Delinearization.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,12 +143,10 @@ bool delinearizeFixedSizeArray(ScalarEvolution &SE, const SCEV *Expr,
143143

144144
/// Check that each subscript in \p Subscripts is within the corresponding size
145145
/// in \p Sizes. For the outermost dimension, the subscript being negative is
146-
/// allowed. If \p Ptr is not nullptr, it may be used to get information from
147-
/// the IR pointer value, which may help in the validation.
146+
/// allowed.
148147
bool validateDelinearizationResult(ScalarEvolution &SE,
149148
ArrayRef<const SCEV *> Sizes,
150-
ArrayRef<const SCEV *> Subscripts,
151-
const Value *Ptr = nullptr);
149+
ArrayRef<const SCEV *> Subscripts);
152150

153151
/// Gathers the individual index expressions from a GEP instruction.
154152
///

llvm/lib/Analysis/Delinearization.cpp

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -666,26 +666,6 @@ bool llvm::delinearizeFixedSizeArray(ScalarEvolution &SE, const SCEV *Expr,
666666
return !Subscripts.empty();
667667
}
668668

669-
static bool isKnownNonNegative(ScalarEvolution *SE, const SCEV *S,
670-
const Value *Ptr) {
671-
bool Inbounds = false;
672-
if (auto *SrcGEP = dyn_cast<GetElementPtrInst>(Ptr))
673-
Inbounds = SrcGEP->isInBounds();
674-
if (Inbounds) {
675-
if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S)) {
676-
if (AddRec->isAffine()) {
677-
// We know S is for Ptr, the operand on a load/store, so doesn't wrap.
678-
// If both parts are NonNegative, the end result will be NonNegative
679-
if (SE->isKnownNonNegative(AddRec->getStart()) &&
680-
SE->isKnownNonNegative(AddRec->getOperand(1)))
681-
return true;
682-
}
683-
}
684-
}
685-
686-
return SE->isKnownNonNegative(S);
687-
}
688-
689669
/// Compare to see if S is less than Size, using
690670
///
691671
/// isKnownNegative(S - Size)
@@ -755,8 +735,7 @@ static bool isKnownLessThan(ScalarEvolution *SE, const SCEV *S,
755735

756736
bool llvm::validateDelinearizationResult(ScalarEvolution &SE,
757737
ArrayRef<const SCEV *> Sizes,
758-
ArrayRef<const SCEV *> Subscripts,
759-
const Value *Ptr) {
738+
ArrayRef<const SCEV *> Subscripts) {
760739
// Sizes and Subscripts are as follows:
761740
//
762741
// Sizes: [UNK][S_2]...[S_n]
@@ -780,7 +759,7 @@ bool llvm::validateDelinearizationResult(ScalarEvolution &SE,
780759
for (size_t I = 1; I < Sizes.size(); ++I) {
781760
const SCEV *Size = Sizes[I - 1];
782761
const SCEV *Subscript = Subscripts[I];
783-
if (!isKnownNonNegative(&SE, Subscript, Ptr))
762+
if (!SE.isKnownNonNegative(Subscript))
784763
return false;
785764
if (!isKnownLessThan(&SE, Subscript, Size))
786765
return false;
@@ -943,8 +922,7 @@ void printDelinearization(raw_ostream &O, Function *F, LoopInfo *LI,
943922
O << "[" << *Subscripts[i] << "]";
944923
O << "\n";
945924

946-
bool IsValid = validateDelinearizationResult(
947-
*SE, Sizes, Subscripts, getLoadStorePointerOperand(&Inst));
925+
bool IsValid = validateDelinearizationResult(*SE, Sizes, Subscripts);
948926
O << "Delinearization validation: " << (IsValid ? "Succeeded" : "Failed")
949927
<< "\n";
950928
}

llvm/lib/Analysis/DependenceAnalysis.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3287,8 +3287,8 @@ bool DependenceInfo::tryDelinearizeFixedSize(
32873287
// iff the subscripts are positive and are less than the range of the
32883288
// dimension.
32893289
if (!DisableDelinearizationChecks) {
3290-
if (!validateDelinearizationResult(*SE, SrcSizes, SrcSubscripts, SrcPtr) ||
3291-
!validateDelinearizationResult(*SE, DstSizes, DstSubscripts, DstPtr)) {
3290+
if (!validateDelinearizationResult(*SE, SrcSizes, SrcSubscripts) ||
3291+
!validateDelinearizationResult(*SE, DstSizes, DstSubscripts)) {
32923292
SrcSubscripts.clear();
32933293
DstSubscripts.clear();
32943294
return false;
@@ -3307,8 +3307,6 @@ bool DependenceInfo::tryDelinearizeParametricSize(
33073307
const SCEV *DstAccessFn, SmallVectorImpl<const SCEV *> &SrcSubscripts,
33083308
SmallVectorImpl<const SCEV *> &DstSubscripts) {
33093309

3310-
Value *SrcPtr = getLoadStorePointerOperand(Src);
3311-
Value *DstPtr = getLoadStorePointerOperand(Dst);
33123310
const SCEVUnknown *SrcBase =
33133311
dyn_cast<SCEVUnknown>(SE->getPointerBase(SrcAccessFn));
33143312
const SCEVUnknown *DstBase =
@@ -3353,8 +3351,8 @@ bool DependenceInfo::tryDelinearizeParametricSize(
33533351
// FIXME: It may be better to record these sizes and add them as constraints
33543352
// to the dependency checks.
33553353
if (!DisableDelinearizationChecks)
3356-
if (!validateDelinearizationResult(*SE, Sizes, SrcSubscripts, SrcPtr) ||
3357-
!validateDelinearizationResult(*SE, Sizes, DstSubscripts, DstPtr))
3354+
if (!validateDelinearizationResult(*SE, Sizes, SrcSubscripts) ||
3355+
!validateDelinearizationResult(*SE, Sizes, DstSubscripts))
33583356
return false;
33593357

33603358
return true;

0 commit comments

Comments
 (0)