Skip to content

Commit

Permalink
PSCEV] Create AddRec for Phis in cases of possible integer overflow,
Browse files Browse the repository at this point in the history
using runtime checks

Extend the SCEVPredicateRewriter to work a bit harder when it encounters an
UnknownSCEV for a Phi node; Try to build an AddRecurrence also for Phi nodes
whose update chain involves casts that can be ignored under the proper runtime
overflow test. This is one step towards addressing PR30654.

Differential revision: http://reviews.llvm.org/D30041

llvm-svn: 308299
  • Loading branch information
dnuzman committed Jul 18, 2017
1 parent 71483f2 commit ca4fd18
Show file tree
Hide file tree
Showing 3 changed files with 648 additions and 25 deletions.
48 changes: 36 additions & 12 deletions llvm/include/llvm/Analysis/ScalarEvolution.h
Expand Up @@ -237,17 +237,15 @@ struct FoldingSetTrait<SCEVPredicate> : DefaultFoldingSetTrait<SCEVPredicate> {
};

/// This class represents an assumption that two SCEV expressions are equal,
/// and this can be checked at run-time. We assume that the left hand side is
/// a SCEVUnknown and the right hand side a constant.
/// and this can be checked at run-time.
class SCEVEqualPredicate final : public SCEVPredicate {
/// We assume that LHS == RHS, where LHS is a SCEVUnknown and RHS a
/// constant.
const SCEVUnknown *LHS;
const SCEVConstant *RHS;
/// We assume that LHS == RHS.
const SCEV *LHS;
const SCEV *RHS;

public:
SCEVEqualPredicate(const FoldingSetNodeIDRef ID, const SCEVUnknown *LHS,
const SCEVConstant *RHS);
SCEVEqualPredicate(const FoldingSetNodeIDRef ID, const SCEV *LHS,
const SCEV *RHS);

/// Implementation of the SCEVPredicate interface
bool implies(const SCEVPredicate *N) const override;
Expand All @@ -256,10 +254,10 @@ class SCEVEqualPredicate final : public SCEVPredicate {
const SCEV *getExpr() const override;

/// Returns the left hand side of the equality.
const SCEVUnknown *getLHS() const { return LHS; }
const SCEV *getLHS() const { return LHS; }

/// Returns the right hand side of the equality.
const SCEVConstant *getRHS() const { return RHS; }
const SCEV *getRHS() const { return RHS; }

/// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const SCEVPredicate *P) {
Expand Down Expand Up @@ -1241,6 +1239,14 @@ class ScalarEvolution {
SmallVector<const SCEV *, 4> NewOp(Operands.begin(), Operands.end());
return getAddRecExpr(NewOp, L, Flags);
}

/// Checks if \p SymbolicPHI can be rewritten as an AddRecExpr under some
/// Predicates. If successful return these <AddRecExpr, Predicates>;
/// The function is intended to be called from PSCEV (the caller will decide
/// whether to actually add the predicates and carry out the rewrites).
Optional<std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>>>
createAddRecFromPHIWithCasts(const SCEVUnknown *SymbolicPHI);

/// Returns an expression for a GEP
///
/// \p GEP The GEP. The indices contained in the GEP itself are ignored,
Expand Down Expand Up @@ -1675,8 +1681,7 @@ class ScalarEvolution {
return F.getParent()->getDataLayout();
}

const SCEVPredicate *getEqualPredicate(const SCEVUnknown *LHS,
const SCEVConstant *RHS);
const SCEVPredicate *getEqualPredicate(const SCEV *LHS, const SCEV *RHS);

const SCEVPredicate *
getWrapPredicate(const SCEVAddRecExpr *AR,
Expand All @@ -1692,6 +1697,19 @@ class ScalarEvolution {
SmallPtrSetImpl<const SCEVPredicate *> &Preds);

private:
/// Similar to createAddRecFromPHI, but with the additional flexibility of
/// suggesting runtime overflow checks in case casts are encountered.
/// If successful, the analysis records that for this loop, \p SymbolicPHI,
/// which is the UnknownSCEV currently representing the PHI, can be rewritten
/// into an AddRec, assuming some predicates; The function then returns the
/// AddRec and the predicates as a pair, and caches this pair in
/// PredicatedSCEVRewrites.
/// If the analysis is not successful, a mapping from the \p SymbolicPHI to
/// itself (with no predicates) is recorded, and a nullptr with an empty
/// predicates vector is returned as a pair.
Optional<std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>>>
createAddRecFromPHIWithCastsImpl(const SCEVUnknown *SymbolicPHI);

/// Compute the backedge taken count knowing the interval difference, the
/// stride and presence of the equality in the comparison.
const SCEV *computeBECount(const SCEV *Delta, const SCEV *Stride,
Expand Down Expand Up @@ -1722,6 +1740,12 @@ class ScalarEvolution {
FoldingSet<SCEVPredicate> UniquePreds;
BumpPtrAllocator SCEVAllocator;

/// Cache tentative mappings from UnknownSCEVs in a Loop, to a SCEV expression
/// they can be rewritten into under certain predicates.
DenseMap<std::pair<const SCEVUnknown *, const Loop *>,
std::pair<const SCEV *, SmallVector<const SCEVPredicate *, 3>>>
PredicatedSCEVRewrites;

/// The head of a linked list of all SCEVUnknown values that have been
/// allocated. This is used by releaseMemory to locate them all and call
/// their destructors.
Expand Down

0 comments on commit ca4fd18

Please sign in to comment.