Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 39 additions & 12 deletions llvm/lib/Analysis/DependenceAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1582,6 +1582,23 @@ static const SCEV *minusSCEVNoSignedOverflow(const SCEV *A, const SCEV *B,
return nullptr;
}

/// Returns the absolute value of \p A. In the context of dependence analysis,
/// we need an absolute value in a mathematical sense. If \p A is the signed
/// minimum value, we cannot represent it unless extending the original type.
/// Thus if we cannot prove that \p A is not the signed minimum value, returns
/// nullptr.
static const SCEV *absSCEVNoSignedOverflow(const SCEV *A, ScalarEvolution &SE) {
IntegerType *Ty = cast<IntegerType>(A->getType());
if (!Ty)
return nullptr;

const SCEV *SMin =
SE.getConstant(APInt::getSignedMinValue(Ty->getBitWidth()));
if (!SE.isKnownPredicate(CmpInst::ICMP_NE, A, SMin))
return nullptr;
return SE.getAbsExpr(A, /*IsNSW=*/true);
}

/// Returns true iff \p Test is enabled.
static bool isDependenceTestEnabled(DependenceTestType Test) {
if (EnableDependenceTest == DependenceTestType::All)
Expand Down Expand Up @@ -1669,21 +1686,25 @@ bool DependenceInfo::strongSIVtest(const SCEV *Coeff, const SCEV *SrcConst,
LLVM_DEBUG(dbgs() << ", " << *Delta->getType() << "\n");

// check that |Delta| < iteration count
if (const SCEV *UpperBound =
collectUpperBound(CurSrcLoop, Delta->getType())) {
bool IsDeltaLarge = [&] {
const SCEV *UpperBound = collectUpperBound(CurSrcLoop, Delta->getType());
if (!UpperBound)
return false;

LLVM_DEBUG(dbgs() << "\t UpperBound = " << *UpperBound);
LLVM_DEBUG(dbgs() << ", " << *UpperBound->getType() << "\n");
const SCEV *AbsDelta =
SE->isKnownNonNegative(Delta) ? Delta : SE->getNegativeSCEV(Delta);
const SCEV *AbsCoeff =
SE->isKnownNonNegative(Coeff) ? Coeff : SE->getNegativeSCEV(Coeff);
const SCEV *AbsDelta = absSCEVNoSignedOverflow(Delta, *SE);
const SCEV *AbsCoeff = absSCEVNoSignedOverflow(Coeff, *SE);
if (!AbsDelta || !AbsCoeff)
return false;
const SCEV *Product = SE->getMulExpr(UpperBound, AbsCoeff);
if (isKnownPredicate(CmpInst::ICMP_SGT, AbsDelta, Product)) {
// Distance greater than trip count - no dependence
++StrongSIVindependence;
++StrongSIVsuccesses;
return true;
}
return isKnownPredicate(CmpInst::ICMP_SGT, AbsDelta, Product);
}();
if (IsDeltaLarge) {
// Distance greater than trip count - no dependence
++StrongSIVindependence;
++StrongSIVsuccesses;
return true;
}

// Can we compute distance?
Expand Down Expand Up @@ -2259,6 +2280,9 @@ bool DependenceInfo::weakZeroSrcSIVtest(
const SCEVConstant *ConstCoeff = dyn_cast<SCEVConstant>(DstCoeff);
if (!ConstCoeff)
return false;

// Since ConstCoeff is constant, !isKnownNegative means it's non-negative.
// TODO: Bail out if it's a signed minimum value.
const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
? SE->getNegativeSCEV(ConstCoeff)
: ConstCoeff;
Expand Down Expand Up @@ -2369,6 +2393,9 @@ bool DependenceInfo::weakZeroDstSIVtest(
const SCEVConstant *ConstCoeff = dyn_cast<SCEVConstant>(SrcCoeff);
if (!ConstCoeff)
return false;

// Since ConstCoeff is constant, !isKnownNegative means it's non-negative.
// TODO: Bail out if it's a signed minimum value.
const SCEV *AbsCoeff = SE->isKnownNegative(ConstCoeff)
? SE->getNegativeSCEV(ConstCoeff)
: ConstCoeff;
Expand Down
48 changes: 48 additions & 0 deletions llvm/test/Analysis/DependenceAnalysis/compute-absolute-value.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
; RUN: opt < %s -disable-output "-passes=print<da>" 2>&1 | FileCheck %s

; for (i = 0; i < 3; i++) {
; a[-k * i] = 1;
; a[-k * i + (2 * k + 1)] = 2;
; }
;
; When k = -1, dependency exists between the two stores. Accesses will be:
;
; - a[-k * i] : a[ 0], a[-1], a[-2]
; - a[-k * i + (2 * k + 1)] : a[-1], a[-2], a[-3]
;
; We cannot determine the sign of `k` and `2*k + 1` at compile time,
;
define void @unknown_sign(ptr %a, i64 %k) {
; CHECK-LABEL: 'unknown_sign'
; CHECK-NEXT: Src: store i8 1, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.0, align 1
; CHECK-NEXT: da analyze - none!
; CHECK-NEXT: Src: store i8 1, ptr %idx.0, align 1 --> Dst: store i8 2, ptr %idx.1, align 1
; CHECK-NEXT: da analyze - output [<>]!
; CHECK-NEXT: Src: store i8 2, ptr %idx.1, align 1 --> Dst: store i8 2, ptr %idx.1, align 1
; CHECK-NEXT: da analyze - none!
;
entry:
%k.neg = sub nsw i64 0, %k
%kk = mul nsw i64 %k, 2
%subscript.1.init = add i64 1, %kk
br label %loop

loop:
%i = phi i64 [ 0, %entry ], [ %i.next, %loop ]
%subscript.0 = phi i64 [ 0, %entry ], [ %subscript.0.next, %loop ]
%subscript.1 = phi i64 [ %subscript.1.init, %entry ], [ %subscript.1.next, %loop ]
%idx.0 = getelementptr i8, ptr %a, i64 %subscript.0
%idx.1 = getelementptr i8, ptr %a, i64 %subscript.1
store i8 1, ptr %idx.0
store i8 2, ptr %idx.1
%i.next = add i64 %i, 1
%subscript.0.next = add nsw i64 %subscript.0, %k.neg
%subscript.1.next = add nsw i64 %subscript.1, %k.neg
%cond.exit = icmp eq i64 %i.next, 3
br i1 %cond.exit, label %exit, label %loop

exit:
ret void
}