[SCEV] Introduce SCEVUse, use it instead of const SCEV * (NFCI). (#91961)

This patch introduces SCEVUse, which is a tagged pointer containing the
used const SCEV *, plus extra bits to store NUW/NSW flags that are only
valid at the specific use.

This was suggested by @nikic as an alternative
to https://github.com/llvm/llvm-project/pull/90742.

This patch just updates most SCEV infrastructure to operate on SCEVUse
instead of const SCEV *. It does not introduce any code that makes use
of the use-specific flags yet which I'll share as follow-ups.

Compile-time impact: https://llvm-compile-time-tracker.com/compare.php?from=ee34eb6edccdebc2a752ffecdde5faae6b0d5593&to=5a7727d7819414d2acbc5b6ab740f0fc2363e842&stat=instructions%3Au
This commit is contained in:
Florian Hahn 2026-03-13 16:23:06 +00:00 committed by GitHub
parent c272252bbd
commit f8734a5e10
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 604 additions and 504 deletions

View File

@ -66,6 +66,76 @@ enum SCEVTypes : unsigned short;
LLVM_ABI extern bool VerifySCEV;
class SCEV;
struct SCEVUse : PointerIntPair<const SCEV *, 2> {
SCEVUse() : PointerIntPair() { setFromOpaqueValue(nullptr); }
SCEVUse(const SCEV *S) : PointerIntPair() { setFromOpaqueValue((void *)S); }
SCEVUse(const SCEV *S, unsigned Flags) : PointerIntPair(S, Flags) {}
operator const SCEV *() const { return getPointer(); }
const SCEV *operator->() const { return getPointer(); }
void *getRawPointer() const { return getOpaqueValue(); }
unsigned getFlags() const { return getInt(); }
bool operator==(const SCEVUse &RHS) const {
return getRawPointer() == RHS.getRawPointer();
}
bool operator==(const SCEV *RHS) const { return getRawPointer() == RHS; }
/// Print out the internal representation of this scalar to the specified
/// stream. This should really only be used for debugging purposes.
void print(raw_ostream &OS) const;
/// This method is used for debugging.
void dump() const;
};
/// Provide PointerLikeTypeTraits for SCEVUse, so it can be used with
/// SmallPtrSet, among others.
template <> struct PointerLikeTypeTraits<SCEVUse> {
static inline void *getAsVoidPointer(SCEVUse U) { return U.getOpaqueValue(); }
static inline SCEVUse getFromVoidPointer(void *P) {
SCEVUse U;
U.setFromOpaqueValue(P);
return U;
}
/// The Low bits are used by the PointerIntPair.
static constexpr int NumLowBitsAvailable = 0;
};
template <> struct DenseMapInfo<SCEVUse> {
static inline SCEVUse getEmptyKey() {
uintptr_t Val = static_cast<uintptr_t>(-1);
return PointerLikeTypeTraits<SCEVUse>::getFromVoidPointer((void *)Val);
}
static inline SCEVUse getTombstoneKey() {
uintptr_t Val = static_cast<uintptr_t>(-2);
return PointerLikeTypeTraits<SCEVUse>::getFromVoidPointer((void *)Val);
}
static unsigned getHashValue(SCEVUse U) {
return hash_value(U.getRawPointer());
}
static bool isEqual(const SCEVUse LHS, const SCEVUse RHS) {
return LHS.getRawPointer() == RHS.getRawPointer();
}
};
template <> struct simplify_type<SCEVUse> {
using SimpleType = const SCEV *;
static SimpleType getSimplifiedValue(SCEVUse &Val) {
return Val.getPointer();
}
};
/// This class represents an analyzed expression in the program. These are
/// opaque objects that the client is not allowed to do much with directly.
///
@ -144,7 +214,7 @@ public:
LLVM_ABI Type *getType() const;
/// Return operands of this SCEV expression.
LLVM_ABI ArrayRef<const SCEV *> operands() const;
LLVM_ABI ArrayRef<SCEVUse> operands() const;
/// Return true if the expression is a constant zero.
LLVM_ABI bool isZero() const;
@ -554,6 +624,7 @@ public:
/// Notify this ScalarEvolution that \p User directly uses SCEVs in \p Ops.
LLVM_ABI void registerUser(const SCEV *User, ArrayRef<const SCEV *> Ops);
LLVM_ABI void registerUser(const SCEV *User, ArrayRef<SCEVUse> Ops);
/// Return true if the SCEV expression contains an undef value.
LLVM_ABI bool containsUndefs(const SCEV *S) const;
@ -592,46 +663,47 @@ public:
unsigned Depth = 0);
LLVM_ABI const SCEV *getCastExpr(SCEVTypes Kind, const SCEV *Op, Type *Ty);
LLVM_ABI const SCEV *getAnyExtendExpr(const SCEV *Op, Type *Ty);
LLVM_ABI const SCEV *getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
LLVM_ABI const SCEV *getAddExpr(SmallVectorImpl<SCEVUse> &Ops,
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
unsigned Depth = 0);
const SCEV *getAddExpr(const SCEV *LHS, const SCEV *RHS,
const SCEV *getAddExpr(SCEVUse LHS, SCEVUse RHS,
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
unsigned Depth = 0) {
SmallVector<const SCEV *, 2> Ops = {LHS, RHS};
SmallVector<SCEVUse, 2> Ops = {LHS, RHS};
return getAddExpr(Ops, Flags, Depth);
}
const SCEV *getAddExpr(const SCEV *Op0, const SCEV *Op1, const SCEV *Op2,
const SCEV *getAddExpr(SCEVUse Op0, SCEVUse Op1, SCEVUse Op2,
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
unsigned Depth = 0) {
SmallVector<const SCEV *, 3> Ops = {Op0, Op1, Op2};
SmallVector<SCEVUse, 3> Ops = {Op0, Op1, Op2};
return getAddExpr(Ops, Flags, Depth);
}
LLVM_ABI const SCEV *getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
LLVM_ABI const SCEV *getMulExpr(SmallVectorImpl<SCEVUse> &Ops,
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
unsigned Depth = 0);
const SCEV *getMulExpr(const SCEV *LHS, const SCEV *RHS,
const SCEV *getMulExpr(SCEVUse LHS, SCEVUse RHS,
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
unsigned Depth = 0) {
SmallVector<const SCEV *, 2> Ops = {LHS, RHS};
SmallVector<SCEVUse, 2> Ops = {LHS, RHS};
return getMulExpr(Ops, Flags, Depth);
}
const SCEV *getMulExpr(const SCEV *Op0, const SCEV *Op1, const SCEV *Op2,
const SCEV *getMulExpr(SCEVUse Op0, SCEVUse Op1, SCEVUse Op2,
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
unsigned Depth = 0) {
SmallVector<const SCEV *, 3> Ops = {Op0, Op1, Op2};
SmallVector<SCEVUse, 3> Ops = {Op0, Op1, Op2};
return getMulExpr(Ops, Flags, Depth);
}
LLVM_ABI const SCEV *getUDivExpr(const SCEV *LHS, const SCEV *RHS);
LLVM_ABI const SCEV *getUDivExactExpr(const SCEV *LHS, const SCEV *RHS);
LLVM_ABI const SCEV *getURemExpr(const SCEV *LHS, const SCEV *RHS);
LLVM_ABI const SCEV *getAddRecExpr(const SCEV *Start, const SCEV *Step,
LLVM_ABI const SCEV *getUDivExpr(SCEVUse LHS, SCEVUse RHS);
LLVM_ABI const SCEV *getUDivExactExpr(SCEVUse LHS, SCEVUse RHS);
LLVM_ABI const SCEV *getURemExpr(SCEVUse LHS, SCEVUse RHS);
LLVM_ABI const SCEV *getAddRecExpr(SCEVUse Start, SCEVUse Step, const Loop *L,
SCEV::NoWrapFlags Flags);
LLVM_ABI const SCEV *getAddRecExpr(SmallVectorImpl<SCEVUse> &Operands,
const Loop *L, SCEV::NoWrapFlags Flags);
LLVM_ABI const SCEV *getAddRecExpr(SmallVectorImpl<const SCEV *> &Operands,
const Loop *L, SCEV::NoWrapFlags Flags);
const SCEV *getAddRecExpr(const SmallVectorImpl<const SCEV *> &Operands,
const SCEV *getAddRecExpr(const SmallVectorImpl<SCEVUse> &Operands,
const Loop *L, SCEV::NoWrapFlags Flags) {
SmallVector<const SCEV *, 4> NewOp(Operands.begin(), Operands.end());
SmallVector<SCEVUse, 4> NewOp(Operands.begin(), Operands.end());
return getAddRecExpr(NewOp, L, Flags);
}
@ -649,26 +721,25 @@ public:
/// instead we use IndexExprs.
/// \p IndexExprs The expressions for the indices.
LLVM_ABI const SCEV *getGEPExpr(GEPOperator *GEP,
ArrayRef<const SCEV *> IndexExprs);
LLVM_ABI const SCEV *getGEPExpr(const SCEV *BaseExpr,
ArrayRef<const SCEV *> IndexExprs,
ArrayRef<SCEVUse> IndexExprs);
LLVM_ABI const SCEV *getGEPExpr(SCEVUse BaseExpr,
ArrayRef<SCEVUse> IndexExprs,
Type *SrcElementTy,
GEPNoWrapFlags NW = GEPNoWrapFlags::none());
LLVM_ABI const SCEV *getAbsExpr(const SCEV *Op, bool IsNSW);
LLVM_ABI const SCEV *getMinMaxExpr(SCEVTypes Kind,
SmallVectorImpl<const SCEV *> &Operands);
SmallVectorImpl<SCEVUse> &Operands);
LLVM_ABI const SCEV *
getSequentialMinMaxExpr(SCEVTypes Kind,
SmallVectorImpl<const SCEV *> &Operands);
LLVM_ABI const SCEV *getSMaxExpr(const SCEV *LHS, const SCEV *RHS);
LLVM_ABI const SCEV *getSMaxExpr(SmallVectorImpl<const SCEV *> &Operands);
LLVM_ABI const SCEV *getUMaxExpr(const SCEV *LHS, const SCEV *RHS);
LLVM_ABI const SCEV *getUMaxExpr(SmallVectorImpl<const SCEV *> &Operands);
LLVM_ABI const SCEV *getSMinExpr(const SCEV *LHS, const SCEV *RHS);
LLVM_ABI const SCEV *getSMinExpr(SmallVectorImpl<const SCEV *> &Operands);
LLVM_ABI const SCEV *getUMinExpr(const SCEV *LHS, const SCEV *RHS,
getSequentialMinMaxExpr(SCEVTypes Kind, SmallVectorImpl<SCEVUse> &Operands);
LLVM_ABI const SCEV *getSMaxExpr(SCEVUse LHS, SCEVUse RHS);
LLVM_ABI const SCEV *getSMaxExpr(SmallVectorImpl<SCEVUse> &Operands);
LLVM_ABI const SCEV *getUMaxExpr(SCEVUse LHS, SCEVUse RHS);
LLVM_ABI const SCEV *getUMaxExpr(SmallVectorImpl<SCEVUse> &Operands);
LLVM_ABI const SCEV *getSMinExpr(SCEVUse LHS, SCEVUse RHS);
LLVM_ABI const SCEV *getSMinExpr(SmallVectorImpl<SCEVUse> &Operands);
LLVM_ABI const SCEV *getUMinExpr(SCEVUse LHS, SCEVUse RHS,
bool Sequential = false);
LLVM_ABI const SCEV *getUMinExpr(SmallVectorImpl<const SCEV *> &Operands,
LLVM_ABI const SCEV *getUMinExpr(SmallVectorImpl<SCEVUse> &Operands,
bool Sequential = false);
LLVM_ABI const SCEV *getUnknown(Value *V);
LLVM_ABI const SCEV *getCouldNotCompute();
@ -717,7 +788,7 @@ public:
/// To compute the difference between two unrelated pointers, you can
/// explicitly convert the arguments using getPtrToIntExpr(), for pointer
/// types that support it.
LLVM_ABI const SCEV *getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
LLVM_ABI const SCEV *getMinusSCEV(SCEVUse LHS, SCEVUse RHS,
SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
unsigned Depth = 0);
@ -773,9 +844,8 @@ public:
/// Promote the operands to the wider of the types using zero-extension, and
/// then perform a umin operation with them. N-ary function.
LLVM_ABI const SCEV *
getUMinFromMismatchedTypes(SmallVectorImpl<const SCEV *> &Ops,
bool Sequential = false);
LLVM_ABI const SCEV *getUMinFromMismatchedTypes(SmallVectorImpl<SCEVUse> &Ops,
bool Sequential = false);
/// Transitively follow the chain of pointer-type operands until reaching a
/// SCEV that does not have a single pointer operand. This returns a
@ -2177,7 +2247,7 @@ private:
void forgetBackedgeTakenCounts(const Loop *L, bool Predicated);
/// Drop memoized information for all \p SCEVs.
void forgetMemoizedResults(ArrayRef<const SCEV *> SCEVs);
void forgetMemoizedResults(ArrayRef<SCEVUse> SCEVs);
/// Helper for forgetMemoizedResults.
void forgetMemoizedResultsImpl(const SCEV *S);
@ -2186,7 +2256,7 @@ private:
/// from ValueExprMap and collect SCEV expressions in \p ToForget
void visitAndClearUsers(SmallVectorImpl<Instruction *> &Worklist,
SmallPtrSetImpl<Instruction *> &Visited,
SmallVectorImpl<const SCEV *> &ToForget);
SmallVectorImpl<SCEVUse> &ToForget);
/// Erase Value from ValueExprMap and ExprValueMap.
void eraseValueFromMap(Value *V);
@ -2236,12 +2306,12 @@ private:
/// Return a scope which provides an upper bound on the defining scope for
/// a SCEV with the operands in Ops. The outparam Precise is set if the
/// bound found is a precise bound (i.e. must be the defining scope.)
const Instruction *getDefiningScopeBound(ArrayRef<const SCEV *> Ops,
const Instruction *getDefiningScopeBound(ArrayRef<SCEVUse> Ops,
bool &Precise);
/// Wrapper around the above for cases which don't care if the bound
/// is precise.
const Instruction *getDefiningScopeBound(ArrayRef<const SCEV *> Ops);
const Instruction *getDefiningScopeBound(ArrayRef<SCEVUse> Ops);
/// Given two instructions in the same function, return true if we can
/// prove B must execute given A executes.
@ -2315,16 +2385,16 @@ private:
bool canIVOverflowOnGT(const SCEV *RHS, const SCEV *Stride, bool IsSigned);
/// Get add expr already created or create a new one.
const SCEV *getOrCreateAddExpr(ArrayRef<const SCEV *> Ops,
const SCEV *getOrCreateAddExpr(ArrayRef<SCEVUse> Ops,
SCEV::NoWrapFlags Flags);
/// Get mul expr already created or create a new one.
const SCEV *getOrCreateMulExpr(ArrayRef<const SCEV *> Ops,
const SCEV *getOrCreateMulExpr(ArrayRef<SCEVUse> Ops,
SCEV::NoWrapFlags Flags);
// Get addrec expr already created or create a new one.
const SCEV *getOrCreateAddRecExpr(ArrayRef<const SCEV *> Ops,
const Loop *L, SCEV::NoWrapFlags Flags);
const SCEV *getOrCreateAddRecExpr(ArrayRef<SCEVUse> Ops, const Loop *L,
SCEV::NoWrapFlags Flags);
/// Return x if \p Val is f(x) where f is a 1-1 function.
const SCEV *stripInjectiveFunctions(const SCEV *Val) const;
@ -2337,6 +2407,7 @@ private:
/// Look for a SCEV expression with type `SCEVType` and operands `Ops` in
/// `UniqueSCEVs`. Return if found, else nullptr.
SCEV *findExistingSCEVInCache(SCEVTypes SCEVType, ArrayRef<const SCEV *> Ops);
SCEV *findExistingSCEVInCache(SCEVTypes SCEVType, ArrayRef<SCEVUse> Ops);
/// Get reachable blocks in this function, making limited use of SCEV
/// reasoning about conditions.
@ -2345,8 +2416,7 @@ private:
/// Return the given SCEV expression with a new set of operands.
/// This preserves the origial nowrap flags.
const SCEV *getWithOperands(const SCEV *S,
SmallVectorImpl<const SCEV *> &NewOps);
const SCEV *getWithOperands(const SCEV *S, SmallVectorImpl<SCEVUse> &NewOps);
FoldingSet<SCEV> UniqueSCEVs;
FoldingSet<SCEVPredicate> UniquePreds;

View File

@ -94,9 +94,9 @@ public:
static bool classof(const SCEV *S) { return S->getSCEVType() == scVScale; }
};
inline unsigned short computeExpressionSize(ArrayRef<const SCEV *> Args) {
inline unsigned short computeExpressionSize(ArrayRef<SCEVUse> Args) {
APInt Size(16, 1);
for (const auto *Arg : Args)
for (const SCEV *Arg : Args)
Size = Size.uadd_sat(APInt(16, Arg->getExpressionSize()));
return (unsigned short)Size.getZExtValue();
}
@ -104,19 +104,19 @@ inline unsigned short computeExpressionSize(ArrayRef<const SCEV *> Args) {
/// This is the base class for unary cast operator classes.
class SCEVCastExpr : public SCEV {
protected:
const SCEV *Op;
SCEVUse Op;
Type *Ty;
LLVM_ABI SCEVCastExpr(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy,
const SCEV *op, Type *ty);
SCEVUse op, Type *ty);
public:
const SCEV *getOperand() const { return Op; }
const SCEV *getOperand(unsigned i) const {
SCEVUse getOperand() const { return Op; }
SCEVUse getOperand(unsigned i) const {
assert(i == 0 && "Operand index out of range!");
return Op;
}
ArrayRef<const SCEV *> operands() const { return Op; }
ArrayRef<SCEVUse> operands() const { return Op; }
size_t getNumOperands() const { return 1; }
Type *getType() const { return Ty; }
@ -133,11 +133,12 @@ public:
class SCEVPtrToIntExpr : public SCEVCastExpr {
friend class ScalarEvolution;
SCEVPtrToIntExpr(const FoldingSetNodeIDRef ID, const SCEV *Op, Type *ITy);
SCEVPtrToIntExpr(const FoldingSetNodeIDRef ID, SCEVUse Op, Type *ITy);
public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const SCEV *S) { return S->getSCEVType() == scPtrToInt; }
static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
};
/// This class represents a cast from a pointer to a pointer-sized integer
@ -156,7 +157,7 @@ public:
class SCEVIntegralCastExpr : public SCEVCastExpr {
protected:
LLVM_ABI SCEVIntegralCastExpr(const FoldingSetNodeIDRef ID, SCEVTypes SCEVTy,
const SCEV *op, Type *ty);
SCEVUse op, Type *ty);
public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
@ -171,7 +172,7 @@ public:
class SCEVTruncateExpr : public SCEVIntegralCastExpr {
friend class ScalarEvolution;
SCEVTruncateExpr(const FoldingSetNodeIDRef ID, const SCEV *op, Type *ty);
SCEVTruncateExpr(const FoldingSetNodeIDRef ID, SCEVUse op, Type *ty);
public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
@ -183,7 +184,7 @@ public:
class SCEVZeroExtendExpr : public SCEVIntegralCastExpr {
friend class ScalarEvolution;
SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID, const SCEV *op, Type *ty);
SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID, SCEVUse op, Type *ty);
public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
@ -197,7 +198,7 @@ public:
class SCEVSignExtendExpr : public SCEVIntegralCastExpr {
friend class ScalarEvolution;
SCEVSignExtendExpr(const FoldingSetNodeIDRef ID, const SCEV *op, Type *ty);
SCEVSignExtendExpr(const FoldingSetNodeIDRef ID, SCEVUse op, Type *ty);
public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
@ -214,25 +215,23 @@ protected:
// arrays with its SCEVAllocator, so this class just needs a simple
// pointer rather than a more elaborate vector-like data structure.
// This also avoids the need for a non-trivial destructor.
const SCEV *const *Operands;
const SCEVUse *Operands;
size_t NumOperands;
SCEVNAryExpr(const FoldingSetNodeIDRef ID, enum SCEVTypes T,
const SCEV *const *O, size_t N)
SCEVNAryExpr(const FoldingSetNodeIDRef ID, enum SCEVTypes T, const SCEVUse *O,
size_t N)
: SCEV(ID, T, computeExpressionSize(ArrayRef(O, N))), Operands(O),
NumOperands(N) {}
public:
size_t getNumOperands() const { return NumOperands; }
const SCEV *getOperand(unsigned i) const {
SCEVUse getOperand(unsigned i) const {
assert(i < NumOperands && "Operand index out of range!");
return Operands[i];
}
ArrayRef<const SCEV *> operands() const {
return ArrayRef(Operands, NumOperands);
}
ArrayRef<SCEVUse> operands() const { return ArrayRef(Operands, NumOperands); }
NoWrapFlags getNoWrapFlags(NoWrapFlags Mask = NoWrapMask) const {
return (NoWrapFlags)(SubclassData & Mask);
@ -256,13 +255,14 @@ public:
S->getSCEVType() == scSequentialUMinExpr ||
S->getSCEVType() == scAddRecExpr;
}
static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
};
/// This node is the base class for n'ary commutative operators.
class SCEVCommutativeExpr : public SCEVNAryExpr {
protected:
SCEVCommutativeExpr(const FoldingSetNodeIDRef ID, enum SCEVTypes T,
const SCEV *const *O, size_t N)
const SCEVUse *O, size_t N)
: SCEVNAryExpr(ID, T, O, N) {}
public:
@ -283,11 +283,10 @@ class SCEVAddExpr : public SCEVCommutativeExpr {
Type *Ty;
SCEVAddExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N)
SCEVAddExpr(const FoldingSetNodeIDRef ID, const SCEVUse *O, size_t N)
: SCEVCommutativeExpr(ID, scAddExpr, O, N) {
auto *FirstPointerTypedOp = find_if(operands(), [](const SCEV *Op) {
return Op->getType()->isPointerTy();
});
auto *FirstPointerTypedOp = find_if(
operands(), [](SCEVUse Op) { return Op->getType()->isPointerTy(); });
if (FirstPointerTypedOp != operands().end())
Ty = (*FirstPointerTypedOp)->getType();
else
@ -299,13 +298,14 @@ public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const SCEV *S) { return S->getSCEVType() == scAddExpr; }
static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
};
/// This node represents multiplication of some number of SCEVs.
class SCEVMulExpr : public SCEVCommutativeExpr {
friend class ScalarEvolution;
SCEVMulExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N)
SCEVMulExpr(const FoldingSetNodeIDRef ID, const SCEVUse *O, size_t N)
: SCEVCommutativeExpr(ID, scMulExpr, O, N) {}
public:
@ -313,30 +313,31 @@ public:
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const SCEV *S) { return S->getSCEVType() == scMulExpr; }
static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
};
/// This class represents a binary unsigned division operation.
class SCEVUDivExpr : public SCEV {
friend class ScalarEvolution;
std::array<const SCEV *, 2> Operands;
std::array<SCEVUse, 2> Operands;
SCEVUDivExpr(const FoldingSetNodeIDRef ID, const SCEV *lhs, const SCEV *rhs)
SCEVUDivExpr(const FoldingSetNodeIDRef ID, SCEVUse lhs, SCEVUse rhs)
: SCEV(ID, scUDivExpr, computeExpressionSize({lhs, rhs})) {
Operands[0] = lhs;
Operands[1] = rhs;
}
public:
const SCEV *getLHS() const { return Operands[0]; }
const SCEV *getRHS() const { return Operands[1]; }
SCEVUse getLHS() const { return Operands[0]; }
SCEVUse getRHS() const { return Operands[1]; }
size_t getNumOperands() const { return 2; }
const SCEV *getOperand(unsigned i) const {
SCEVUse getOperand(unsigned i) const {
assert((i == 0 || i == 1) && "Operand index out of range!");
return i == 0 ? getLHS() : getRHS();
}
ArrayRef<const SCEV *> operands() const { return Operands; }
ArrayRef<SCEVUse> operands() const { return Operands; }
Type *getType() const {
// In most cases the types of LHS and RHS will be the same, but in some
@ -364,25 +365,24 @@ class SCEVAddRecExpr : public SCEVNAryExpr {
const Loop *L;
SCEVAddRecExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N,
SCEVAddRecExpr(const FoldingSetNodeIDRef ID, const SCEVUse *O, size_t N,
const Loop *l)
: SCEVNAryExpr(ID, scAddRecExpr, O, N), L(l) {}
public:
Type *getType() const { return getStart()->getType(); }
const SCEV *getStart() const { return Operands[0]; }
SCEVUse getStart() const { return Operands[0]; }
const Loop *getLoop() const { return L; }
/// Constructs and returns the recurrence indicating how much this
/// expression steps by. If this is a polynomial of degree N, it
/// returns a chrec of degree N-1. We cannot determine whether
/// the step recurrence has self-wraparound.
const SCEV *getStepRecurrence(ScalarEvolution &SE) const {
SCEVUse getStepRecurrence(ScalarEvolution &SE) const {
if (isAffine())
return getOperand(1);
return SE.getAddRecExpr(
SmallVector<const SCEV *, 3>(operands().drop_front()), getLoop(),
FlagAnyWrap);
return SE.getAddRecExpr(SmallVector<SCEVUse, 3>(operands().drop_front()),
getLoop(), FlagAnyWrap);
}
/// Return true if this represents an expression A + B*x where A
@ -414,9 +414,9 @@ public:
/// Return the value of this chain of recurrences at the specified iteration
/// number. Takes an explicit list of operands to represent an AddRec.
LLVM_ABI static const SCEV *
evaluateAtIteration(ArrayRef<const SCEV *> Operands, const SCEV *It,
ScalarEvolution &SE);
LLVM_ABI static const SCEV *evaluateAtIteration(ArrayRef<SCEVUse> Operands,
const SCEV *It,
ScalarEvolution &SE);
/// Return the number of iterations of this loop that produce
/// values in the specified constant range. Another way of
@ -449,7 +449,7 @@ class SCEVMinMaxExpr : public SCEVCommutativeExpr {
protected:
/// Note: Constructing subclasses via this constructor is allowed
SCEVMinMaxExpr(const FoldingSetNodeIDRef ID, enum SCEVTypes T,
const SCEV *const *O, size_t N)
const SCEVUse *O, size_t N)
: SCEVCommutativeExpr(ID, T, O, N) {
assert(isMinMaxType(T));
// Min and max never overflow
@ -481,7 +481,7 @@ public:
class SCEVSMaxExpr : public SCEVMinMaxExpr {
friend class ScalarEvolution;
SCEVSMaxExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N)
SCEVSMaxExpr(const FoldingSetNodeIDRef ID, const SCEVUse *O, size_t N)
: SCEVMinMaxExpr(ID, scSMaxExpr, O, N) {}
public:
@ -493,7 +493,7 @@ public:
class SCEVUMaxExpr : public SCEVMinMaxExpr {
friend class ScalarEvolution;
SCEVUMaxExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N)
SCEVUMaxExpr(const FoldingSetNodeIDRef ID, const SCEVUse *O, size_t N)
: SCEVMinMaxExpr(ID, scUMaxExpr, O, N) {}
public:
@ -505,7 +505,7 @@ public:
class SCEVSMinExpr : public SCEVMinMaxExpr {
friend class ScalarEvolution;
SCEVSMinExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N)
SCEVSMinExpr(const FoldingSetNodeIDRef ID, const SCEVUse *O, size_t N)
: SCEVMinMaxExpr(ID, scSMinExpr, O, N) {}
public:
@ -517,7 +517,7 @@ public:
class SCEVUMinExpr : public SCEVMinMaxExpr {
friend class ScalarEvolution;
SCEVUMinExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O, size_t N)
SCEVUMinExpr(const FoldingSetNodeIDRef ID, const SCEVUse *O, size_t N)
: SCEVMinMaxExpr(ID, scUMinExpr, O, N) {}
public:
@ -544,7 +544,7 @@ class SCEVSequentialMinMaxExpr : public SCEVNAryExpr {
protected:
/// Note: Constructing subclasses via this constructor is allowed
SCEVSequentialMinMaxExpr(const FoldingSetNodeIDRef ID, enum SCEVTypes T,
const SCEV *const *O, size_t N)
const SCEVUse *O, size_t N)
: SCEVNAryExpr(ID, T, O, N) {
assert(isSequentialMinMaxType(T));
// Min and max never overflow
@ -571,13 +571,14 @@ public:
static bool classof(const SCEV *S) {
return isSequentialMinMaxType(S->getSCEVType());
}
static bool classof(const SCEVUse *U) { return classof(U->getPointer()); }
};
/// This class represents a sequential/in-order unsigned minimum selection.
class SCEVSequentialUMinExpr : public SCEVSequentialMinMaxExpr {
friend class ScalarEvolution;
SCEVSequentialUMinExpr(const FoldingSetNodeIDRef ID, const SCEV *const *O,
SCEVSequentialUMinExpr(const FoldingSetNodeIDRef ID, const SCEVUse *O,
size_t N)
: SCEVSequentialMinMaxExpr(ID, scSequentialUMinExpr, O, N) {}
@ -715,7 +716,7 @@ public:
case scUMinExpr:
case scSequentialUMinExpr:
case scAddRecExpr:
for (const auto *Op : S->operands()) {
for (const SCEV *Op : S->operands()) {
push(Op);
if (Visitor.isDone())
break;
@ -825,9 +826,9 @@ public:
}
const SCEV *visitAddExpr(const SCEVAddExpr *Expr) {
SmallVector<const SCEV *, 2> Operands;
SmallVector<SCEVUse, 2> Operands;
bool Changed = false;
for (const auto *Op : Expr->operands()) {
for (const SCEV *Op : Expr->operands()) {
Operands.push_back(((SC *)this)->visit(Op));
Changed |= Op != Operands.back();
}
@ -835,9 +836,9 @@ public:
}
const SCEV *visitMulExpr(const SCEVMulExpr *Expr) {
SmallVector<const SCEV *, 2> Operands;
SmallVector<SCEVUse, 2> Operands;
bool Changed = false;
for (const auto *Op : Expr->operands()) {
for (const SCEV *Op : Expr->operands()) {
Operands.push_back(((SC *)this)->visit(Op));
Changed |= Op != Operands.back();
}
@ -852,9 +853,9 @@ public:
}
const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) {
SmallVector<const SCEV *, 2> Operands;
SmallVector<SCEVUse, 2> Operands;
bool Changed = false;
for (const auto *Op : Expr->operands()) {
for (const SCEV *Op : Expr->operands()) {
Operands.push_back(((SC *)this)->visit(Op));
Changed |= Op != Operands.back();
}
@ -864,9 +865,9 @@ public:
}
const SCEV *visitSMaxExpr(const SCEVSMaxExpr *Expr) {
SmallVector<const SCEV *, 2> Operands;
SmallVector<SCEVUse, 2> Operands;
bool Changed = false;
for (const auto *Op : Expr->operands()) {
for (const SCEV *Op : Expr->operands()) {
Operands.push_back(((SC *)this)->visit(Op));
Changed |= Op != Operands.back();
}
@ -874,9 +875,9 @@ public:
}
const SCEV *visitUMaxExpr(const SCEVUMaxExpr *Expr) {
SmallVector<const SCEV *, 2> Operands;
SmallVector<SCEVUse, 2> Operands;
bool Changed = false;
for (const auto *Op : Expr->operands()) {
for (const SCEV *Op : Expr->operands()) {
Operands.push_back(((SC *)this)->visit(Op));
Changed |= Op != Operands.back();
}
@ -884,9 +885,9 @@ public:
}
const SCEV *visitSMinExpr(const SCEVSMinExpr *Expr) {
SmallVector<const SCEV *, 2> Operands;
SmallVector<SCEVUse, 2> Operands;
bool Changed = false;
for (const auto *Op : Expr->operands()) {
for (const SCEV *Op : Expr->operands()) {
Operands.push_back(((SC *)this)->visit(Op));
Changed |= Op != Operands.back();
}
@ -894,9 +895,9 @@ public:
}
const SCEV *visitUMinExpr(const SCEVUMinExpr *Expr) {
SmallVector<const SCEV *, 2> Operands;
SmallVector<SCEVUse, 2> Operands;
bool Changed = false;
for (const auto *Op : Expr->operands()) {
for (const SCEV *Op : Expr->operands()) {
Operands.push_back(((SC *)this)->visit(Op));
Changed |= Op != Operands.back();
}
@ -904,9 +905,9 @@ public:
}
const SCEV *visitSequentialUMinExpr(const SCEVSequentialUMinExpr *Expr) {
SmallVector<const SCEV *, 2> Operands;
SmallVector<SCEVUse, 2> Operands;
bool Changed = false;
for (const auto *Op : Expr->operands()) {
for (const SCEV *Op : Expr->operands()) {
Operands.push_back(((SC *)this)->visit(Op));
Changed |= Op != Operands.back();
}
@ -964,8 +965,8 @@ public:
}
const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) {
SmallVector<const SCEV *, 2> Operands;
for (const SCEV *Op : Expr->operands())
SmallVector<SCEVUse, 2> Operands;
for (SCEVUse Op : Expr->operands())
Operands.push_back(visit(Op));
const Loop *L = Expr->getLoop();

View File

@ -13,6 +13,7 @@
#ifndef LLVM_ANALYSIS_SCALAREVOLUTIONPATTERNMATCH_H
#define LLVM_ANALYSIS_SCALAREVOLUTIONPATTERNMATCH_H
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
namespace llvm {
@ -22,6 +23,11 @@ template <typename Pattern> bool match(const SCEV *S, const Pattern &P) {
return P.match(S);
}
template <typename Pattern> bool match(const SCEVUse U, const Pattern &P) {
const SCEV *S = U.getPointer();
return const_cast<Pattern &>(P).match(S);
}
template <typename Predicate> struct cst_pred_ty : public Predicate {
cst_pred_ty() = default;
cst_pred_ty(uint64_t V) : Predicate(V) {}
@ -159,7 +165,8 @@ template <typename SCEVTy, typename Op0_t> struct SCEVUnaryExpr_match {
bool match(const SCEV *S) const {
auto *E = dyn_cast<SCEVTy>(S);
return E && E->getNumOperands() == 1 && Op0.match(E->getOperand(0));
return E && E->getNumOperands() == 1 &&
Op0.match(E->getOperand(0).getPointer());
}
};
@ -215,9 +222,10 @@ struct SCEVBinaryExpr_match {
auto *E = dyn_cast<SCEVTy>(S);
return E && E->getNumOperands() == 2 &&
((Op0.match(E->getOperand(0)) && Op1.match(E->getOperand(1))) ||
(Commutable && Op0.match(E->getOperand(1)) &&
Op1.match(E->getOperand(0))));
((Op0.match(E->getOperand(0).getPointer()) &&
Op1.match(E->getOperand(1).getPointer())) ||
(Commutable && Op0.match(E->getOperand(1).getPointer()) &&
Op1.match(E->getOperand(0).getPointer())));
}
};

View File

@ -80,6 +80,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/ValueHandle.h"
@ -92,8 +93,6 @@ class DominatorTree;
class Function;
class GetElementPtrInst;
class Instruction;
class ScalarEvolution;
class SCEV;
class TargetLibraryInfo;
class TargetTransformInfo;
class Type;
@ -114,7 +113,7 @@ private:
bool doOneIteration(Function &F);
// Reassociates I for better CSE.
Instruction *tryReassociate(Instruction *I, const SCEV *&OrigSCEV);
Instruction *tryReassociate(Instruction *I, SCEVUse &OrigSCEV);
// Reassociate GEP for better CSE.
Instruction *tryReassociateGEP(GetElementPtrInst *GEP);
@ -143,19 +142,18 @@ private:
Instruction *tryReassociateBinaryOp(Value *LHS, Value *RHS,
BinaryOperator *I);
// Rewrites I to (LHS op RHS) if LHS is computed already.
Instruction *tryReassociatedBinaryOp(const SCEV *LHS, Value *RHS,
Instruction *tryReassociatedBinaryOp(SCEVUse LHS, Value *RHS,
BinaryOperator *I);
// Tries to match Op1 and Op2 by using V.
bool matchTernaryOp(BinaryOperator *I, Value *V, Value *&Op1, Value *&Op2);
// Gets SCEV for (LHS op RHS).
const SCEV *getBinarySCEV(BinaryOperator *I, const SCEV *LHS,
const SCEV *RHS);
SCEVUse getBinarySCEV(BinaryOperator *I, SCEVUse LHS, SCEVUse RHS);
// Returns the closest dominator of \c Dominatee that computes
// \c CandidateExpr. Returns null if not found.
Instruction *findClosestMatchingDominator(const SCEV *CandidateExpr,
Instruction *findClosestMatchingDominator(SCEVUse CandidateExpr,
Instruction *Dominatee);
// Try to match \p I as signed/unsigned Min/Max and reassociate it. \p
@ -163,8 +161,7 @@ private:
// done or not. If reassociation was successful newly generated instruction is
// returned, otherwise nullptr.
template <typename PredT>
Instruction *matchAndReassociateMinOrMax(Instruction *I,
const SCEV *&OrigSCEV);
Instruction *matchAndReassociateMinOrMax(Instruction *I, SCEVUse &OrigSCEV);
// Reassociate Min/Max.
template <typename MaxMinT>

View File

@ -133,7 +133,7 @@ struct SCEVCollectAddRecMultiplies {
bool follow(const SCEV *S) {
if (auto *Mul = dyn_cast<SCEVMulExpr>(S)) {
bool HasAddRec = false;
SmallVector<const SCEV *, 0> Operands;
SmallVector<SCEVUse, 0> Operands;
for (const SCEV *Op : Mul->operands()) {
const SCEVUnknown *Unknown = dyn_cast<SCEVUnknown>(Op);
if (Unknown && !isa<CallInst>(Unknown->getValue())) {
@ -207,7 +207,7 @@ static bool findArrayDimensionsRec(ScalarEvolution &SE,
// End of recursion.
if (Last == 0) {
if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(Step)) {
SmallVector<const SCEV *, 2> Qs;
SmallVector<SCEVUse, 2> Qs;
for (const SCEV *Op : M->operands())
if (!isa<SCEVConstant>(Op))
Qs.push_back(Op);
@ -266,7 +266,7 @@ static const SCEV *removeConstantFactors(ScalarEvolution &SE, const SCEV *T) {
return T;
if (const SCEVMulExpr *M = dyn_cast<SCEVMulExpr>(T)) {
SmallVector<const SCEV *, 2> Factors;
SmallVector<SCEVUse, 2> Factors;
for (const SCEV *Op : M->operands())
if (!isa<SCEVConstant>(Op))
Factors.push_back(Op);

File diff suppressed because it is too large Load Diff

View File

@ -149,7 +149,7 @@ void SCEVDivision::visitAddRecExpr(const SCEVAddRecExpr *Numerator) {
}
void SCEVDivision::visitAddExpr(const SCEVAddExpr *Numerator) {
SmallVector<const SCEV *, 2> Qs, Rs;
SmallVector<SCEVUse, 2> Qs, Rs;
Type *Ty = Denominator->getType();
for (const SCEV *Op : Numerator->operands()) {
@ -175,7 +175,7 @@ void SCEVDivision::visitAddExpr(const SCEVAddExpr *Numerator) {
}
void SCEVDivision::visitMulExpr(const SCEVMulExpr *Numerator) {
SmallVector<const SCEV *, 2> Qs;
SmallVector<SCEVUse, 2> Qs;
Type *Ty = Denominator->getType();
bool FoundDenominatorTerm = false;

View File

@ -46,10 +46,10 @@ struct NormalizeDenormalizeRewriter
const SCEV *
NormalizeDenormalizeRewriter::visitAddRecExpr(const SCEVAddRecExpr *AR) {
SmallVector<const SCEV *, 8> Operands;
SmallVector<SCEVUse, 8> Operands;
transform(AR->operands(), std::back_inserter(Operands),
[&](const SCEV *Op) { return visit(Op); });
[&](SCEVUse Op) { return visit(Op.getPointer()); });
if (!Pred(AR))
return SE.getAddRecExpr(Operands, AR->getLoop(), SCEV::FlagAnyWrap);

View File

@ -2785,7 +2785,7 @@ void ARMTTIImpl::getUnrollingPreferences(Loop *L, ScalarEvolution &SE,
bool Runtime = true;
if (ST->hasLOB()) {
if (SE.hasLoopInvariantBackedgeTakenCount(L)) {
const auto *BETC = SE.getBackedgeTakenCount(L);
const SCEV *BETC = SE.getBackedgeTakenCount(L);
auto *Outer = L->getOutermostLoop();
if ((L != Outer && Outer != L->getParentLoop()) ||
(L != Outer && BETC && !SE.isLoopInvariant(BETC, Outer))) {

View File

@ -1395,9 +1395,9 @@ createReplacement(ICmpInst *ICmp, const Loop *L, BasicBlock *ExitingBB,
// wrap". getLoopInvariantExitCondDuringFirstIterations knows how to deal
// with umin in a smart way, but umin(a, b) - 1 will likely not simplify.
// So we manually construct umin(a - 1, b - 1).
SmallVector<const SCEV *, 4> Elements;
SmallVector<SCEVUse, 4> Elements;
if (auto *UMin = dyn_cast<SCEVUMinExpr>(MaxIter)) {
for (const SCEV *Op : UMin->operands())
for (SCEVUse Op : UMin->operands())
Elements.push_back(SE->getMinusSCEV(Op, SE->getOne(Op->getType())));
MaxIter = SE->getUMinFromMismatchedTypes(Elements);
} else

View File

@ -423,7 +423,7 @@ bool InductiveRangeCheck::reassociateSubLHS(
auto getExprScaledIfOverflow = [&](Instruction::BinaryOps BinOp,
const SCEV *LHS,
const SCEV *RHS) -> const SCEV * {
const SCEV *(ScalarEvolution::*Operation)(const SCEV *, const SCEV *,
const SCEV *(ScalarEvolution::*Operation)(SCEVUse, SCEVUse,
SCEV::NoWrapFlags, unsigned);
switch (BinOp) {
default:

View File

@ -391,9 +391,10 @@ bool LoopDataPrefetch::runOnLoop(Loop *L) {
BasicBlock *BB = P.InsertPt->getParent();
SCEVExpander SCEVE(*SE, "prefaddr");
const SCEV *NextLSCEV = SE->getAddExpr(P.LSCEVAddRec, SE->getMulExpr(
SE->getConstant(P.LSCEVAddRec->getType(), ItersAhead),
P.LSCEVAddRec->getStepRecurrence(*SE)));
const SCEV *NextLSCEV = SE->getAddExpr(
P.LSCEVAddRec,
SE->getMulExpr(SE->getConstant(P.LSCEVAddRec->getType(), ItersAhead),
P.LSCEVAddRec->getStepRecurrence(*SE)));
if (!SCEVE.isSafeToExpand(NextLSCEV))
continue;

View File

@ -1132,7 +1132,7 @@ private:
const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) {
const Loop *ExprL = Expr->getLoop();
SmallVector<const SCEV *, 2> Operands;
SmallVector<SCEVUse, 2> Operands;
if (ExprL == &OldL) {
append_range(Operands, Expr->operands());
return SE.getAddRecExpr(Operands, &NewL, Expr->getNoWrapFlags());
@ -1147,7 +1147,7 @@ private:
return visit(Expr->getStart());
}
for (const SCEV *Op : Expr->operands())
for (SCEVUse Op : Expr->operands())
Operands.push_back(visit(Op));
return SE.getAddRecExpr(Operands, ExprL, Expr->getNoWrapFlags());
}

View File

@ -889,7 +889,7 @@ bool LoopIdiomRecognize::processLoopMemSet(MemSetInst *MSI,
return false;
}
const SCEV *MemsetSizeSCEV = SE->getSCEV(MSI->getLength());
SCEVUse MemsetSizeSCEV = SE->getSCEV(MSI->getLength());
bool IsNegStride = false;
const bool IsConstantSize = isa<ConstantInt>(MSI->getLength());
@ -928,9 +928,9 @@ bool LoopIdiomRecognize::processLoopMemSet(MemSetInst *MSI,
// Compare positive direction PointerStrideSCEV with MemsetSizeSCEV
IsNegStride = PointerStrideSCEV->isNonConstantNegative();
const SCEV *PositiveStrideSCEV =
IsNegStride ? SE->getNegativeSCEV(PointerStrideSCEV)
: PointerStrideSCEV;
SCEVUse PositiveStrideSCEV =
IsNegStride ? SCEVUse(SE->getNegativeSCEV(PointerStrideSCEV))
: SCEVUse(PointerStrideSCEV);
LLVM_DEBUG(dbgs() << " MemsetSizeSCEV: " << *MemsetSizeSCEV << "\n"
<< " PositiveStrideSCEV: " << *PositiveStrideSCEV
<< "\n");

View File

@ -1006,9 +1006,9 @@ static const SCEV *getMinAnalyzeableBackedgeTakenCount(ScalarEvolution &SE,
SmallVector<BasicBlock *, 16> ExitingBlocks;
L->getExitingBlocks(ExitingBlocks);
SmallVector<const SCEV *, 4> ExitCounts;
SmallVector<SCEVUse, 4> ExitCounts;
for (BasicBlock *ExitingBB : ExitingBlocks) {
const SCEV *ExitCount = SE.getExitCount(L, ExitingBB);
SCEVUse ExitCount = SE.getExitCount(L, ExitingBB);
if (isa<SCEVCouldNotCompute>(ExitCount))
continue;
assert(DT.dominates(ExitingBB, L->getLoopLatch()) &&

View File

@ -541,9 +541,8 @@ struct Formula {
/// Recursion helper for initialMatch.
static void DoInitialMatch(const SCEV *S, Loop *L,
SmallVectorImpl<const SCEV *> &Good,
SmallVectorImpl<const SCEV *> &Bad,
ScalarEvolution &SE) {
SmallVectorImpl<SCEVUse> &Good,
SmallVectorImpl<SCEVUse> &Bad, ScalarEvolution &SE) {
// Collect expressions which properly dominate the loop header.
if (SE.properlyDominates(S, L->getHeader())) {
Good.push_back(S);
@ -574,11 +573,11 @@ static void DoInitialMatch(const SCEV *S, Loop *L,
// Handle a multiplication by -1 (negation) if it didn't fold.
if (const SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(S))
if (Mul->getOperand(0)->isAllOnesValue()) {
SmallVector<const SCEV *, 4> Ops(drop_begin(Mul->operands()));
SmallVector<SCEVUse, 4> Ops(drop_begin(Mul->operands()));
const SCEV *NewMul = SE.getMulExpr(Ops);
SmallVector<const SCEV *, 4> MyGood;
SmallVector<const SCEV *, 4> MyBad;
SmallVector<SCEVUse, 4> MyGood;
SmallVector<SCEVUse, 4> MyBad;
DoInitialMatch(NewMul, L, MyGood, MyBad, SE);
const SCEV *NegOne = SE.getSCEV(ConstantInt::getAllOnesValue(
SE.getEffectiveSCEVType(NewMul->getType())));
@ -597,8 +596,8 @@ static void DoInitialMatch(const SCEV *S, Loop *L,
/// Incorporate loop-variant parts of S into this Formula, attempting to keep
/// all loop-invariant and loop-computable values in a single base register.
void Formula::initialMatch(const SCEV *S, Loop *L, ScalarEvolution &SE) {
SmallVector<const SCEV *, 4> Good;
SmallVector<const SCEV *, 4> Bad;
SmallVector<SCEVUse, 4> Good;
SmallVector<SCEVUse, 4> Bad;
DoInitialMatch(S, L, Good, Bad, SE);
if (!Good.empty()) {
const SCEV *Sum = SE.getAddExpr(Good);
@ -877,7 +876,7 @@ static const SCEV *getExactSDiv(const SCEV *LHS, const SCEV *RHS,
// Distribute the sdiv over add operands, if the add doesn't overflow.
if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(LHS)) {
if (IgnoreSignificantBits || isAddSExtable(Add, SE)) {
SmallVector<const SCEV *, 8> Ops;
SmallVector<SCEVUse, 8> Ops;
for (const SCEV *S : Add->operands()) {
const SCEV *Op = getExactSDiv(S, RHS, SE, IgnoreSignificantBits);
if (!Op) return nullptr;
@ -906,7 +905,7 @@ static const SCEV *getExactSDiv(const SCEV *LHS, const SCEV *RHS,
}
}
SmallVector<const SCEV *, 4> Ops;
SmallVector<SCEVUse, 4> Ops;
bool Found = false;
for (const SCEV *S : Mul->operands()) {
if (!Found)
@ -928,7 +927,7 @@ static const SCEV *getExactSDiv(const SCEV *LHS, const SCEV *RHS,
/// If S involves the addition of a constant integer value, return that integer
/// value, and mutate S to point to a new SCEV with that value excluded.
static Immediate ExtractImmediate(const SCEV *&S, ScalarEvolution &SE) {
static Immediate ExtractImmediate(SCEVUse &S, ScalarEvolution &SE) {
const APInt *C;
if (match(S, m_scev_APInt(C))) {
if (C->getSignificantBits() <= 64) {
@ -936,13 +935,13 @@ static Immediate ExtractImmediate(const SCEV *&S, ScalarEvolution &SE) {
return Immediate::getFixed(C->getSExtValue());
}
} else if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(S)) {
SmallVector<const SCEV *, 8> NewOps(Add->operands());
SmallVector<SCEVUse, 8> NewOps(Add->operands());
Immediate Result = ExtractImmediate(NewOps.front(), SE);
if (Result.isNonZero())
S = SE.getAddExpr(NewOps);
return Result;
} else if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S)) {
SmallVector<const SCEV *, 8> NewOps(AR->operands());
SmallVector<SCEVUse, 8> NewOps(AR->operands());
Immediate Result = ExtractImmediate(NewOps.front(), SE);
if (Result.isNonZero())
S = SE.getAddRecExpr(NewOps, AR->getLoop(),
@ -959,20 +958,20 @@ static Immediate ExtractImmediate(const SCEV *&S, ScalarEvolution &SE) {
/// If S involves the addition of a GlobalValue address, return that symbol, and
/// mutate S to point to a new SCEV with that value excluded.
static GlobalValue *ExtractSymbol(const SCEV *&S, ScalarEvolution &SE) {
static GlobalValue *ExtractSymbol(SCEVUse &S, ScalarEvolution &SE) {
if (const SCEVUnknown *U = dyn_cast<SCEVUnknown>(S)) {
if (GlobalValue *GV = dyn_cast<GlobalValue>(U->getValue())) {
S = SE.getConstant(GV->getType(), 0);
return GV;
}
} else if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(S)) {
SmallVector<const SCEV *, 8> NewOps(Add->operands());
SmallVector<SCEVUse, 8> NewOps(Add->operands());
GlobalValue *Result = ExtractSymbol(NewOps.back(), SE);
if (Result)
S = SE.getAddExpr(NewOps);
return Result;
} else if (const SCEVAddRecExpr *AR = dyn_cast<SCEVAddRecExpr>(S)) {
SmallVector<const SCEV *, 8> NewOps(AR->operands());
SmallVector<SCEVUse, 8> NewOps(AR->operands());
GlobalValue *Result = ExtractSymbol(NewOps.front(), SE);
if (Result)
S = SE.getAddRecExpr(NewOps, AR->getLoop(),
@ -2042,11 +2041,13 @@ static bool isAlwaysFoldable(const TargetTransformInfo &TTI,
// Conservatively, create an address with an immediate and a
// base and a scale.
Immediate BaseOffset = ExtractImmediate(S, SE);
GlobalValue *BaseGV = ExtractSymbol(S, SE);
SCEVUse SCopy = S;
Immediate BaseOffset = ExtractImmediate(SCopy, SE);
GlobalValue *BaseGV = ExtractSymbol(SCopy, SE);
// If there's anything else involved, it's not foldable.
if (!S->isZero()) return false;
if (!SCopy->isZero())
return false;
// Fast-path: zero is always foldable.
if (BaseOffset.isZero() && !BaseGV)
@ -2816,7 +2817,9 @@ std::pair<size_t, Immediate> LSRInstance::getUse(const SCEV *&Expr,
LSRUse::KindType Kind,
MemAccessTy AccessTy) {
const SCEV *Copy = Expr;
Immediate Offset = ExtractImmediate(Expr, SE);
SCEVUse ExprUse = Expr;
Immediate Offset = ExtractImmediate(ExprUse, SE);
Expr = ExprUse;
// Basic uses can't accept any offset, for example.
if (!isAlwaysFoldable(TTI, Kind, AccessTy, /*BaseGV=*/ nullptr,
@ -3958,7 +3961,7 @@ void LSRInstance::GenerateReassociationsImpl(LSRUse &LU, unsigned LUIdx,
continue;
// Collect all operands except *J.
SmallVector<const SCEV *, 8> InnerAddOps(std::as_const(AddOps).begin(), J);
SmallVector<SCEVUse, 8> InnerAddOps(std::as_const(AddOps).begin(), J);
InnerAddOps.append(std::next(J), std::as_const(AddOps).end());
// Don't leave just a constant behind in a register if the constant could
@ -4049,7 +4052,7 @@ void LSRInstance::GenerateCombinations(LSRUse &LU, unsigned LUIdx,
// Flatten the representation, i.e., reg1 + 1*reg2 => reg1 + reg2, before
// processing the formula.
Base.unscale();
SmallVector<const SCEV *, 4> Ops;
SmallVector<SCEVUse, 4> Ops;
Formula NewBase = Base;
NewBase.BaseRegs.clear();
Type *CombinedIntegerType = nullptr;
@ -4086,7 +4089,7 @@ void LSRInstance::GenerateCombinations(LSRUse &LU, unsigned LUIdx,
// If we collected at least two registers, generate a formula combining them.
if (Ops.size() > 1) {
SmallVector<const SCEV *, 4> OpsCopy(Ops); // Don't let SE modify Ops.
SmallVector<SCEVUse, 4> OpsCopy(Ops); // Don't let SE modify Ops.
GenerateFormula(SE.getAddExpr(OpsCopy));
}
@ -4105,7 +4108,7 @@ void LSRInstance::GenerateCombinations(LSRUse &LU, unsigned LUIdx,
void LSRInstance::GenerateSymbolicOffsetsImpl(LSRUse &LU, unsigned LUIdx,
const Formula &Base, size_t Idx,
bool IsScaledReg) {
const SCEV *G = IsScaledReg ? Base.ScaledReg : Base.BaseRegs[Idx];
SCEVUse G = IsScaledReg ? Base.ScaledReg : Base.BaseRegs[Idx];
GlobalValue *GV = ExtractSymbol(G, SE);
if (G->isZero() || !GV)
return;
@ -4165,7 +4168,7 @@ void LSRInstance::GenerateConstantOffsetsImpl(
}
};
const SCEV *G = IsScaledReg ? Base.ScaledReg : Base.BaseRegs[Idx];
SCEVUse G = IsScaledReg ? Base.ScaledReg : Base.BaseRegs[Idx];
// With constant offsets and constant steps, we can generate pre-inc
// accesses by having the offset equal the step. So, for access #0 with a
@ -4522,7 +4525,7 @@ void LSRInstance::GenerateCrossUseConstantOffsets() {
DenseMap<const SCEV *, SmallBitVector> UsedByIndicesMap;
SmallVector<const SCEV *, 8> Sequence;
for (const SCEV *Use : RegUses) {
const SCEV *Reg = Use; // Make a copy for ExtractImmediate to modify.
SCEVUse Reg = Use; // Make a copy for ExtractImmediate to modify.
Immediate Imm = ExtractImmediate(Reg, SE);
auto Pair = Map.try_emplace(Reg);
if (Pair.second)
@ -5716,7 +5719,7 @@ Value *LSRInstance::Expand(const LSRUse &LU, const LSRFixup &LF,
Type *IntTy = SE.getEffectiveSCEVType(Ty);
// Build up a list of operands to add together to form the full base.
SmallVector<const SCEV *, 8> Ops;
SmallVector<SCEVUse, 8> Ops;
// Expand the BaseRegs portion.
for (const SCEV *Reg : F.BaseRegs) {

View File

@ -225,7 +225,7 @@ bool NaryReassociatePass::doOneIteration(Function &F) {
for (const auto Node : depth_first(DT)) {
BasicBlock *BB = Node->getBlock();
for (Instruction &OrigI : *BB) {
const SCEV *OrigSCEV = nullptr;
SCEVUse OrigSCEV = nullptr;
if (Instruction *NewI = tryReassociate(&OrigI, OrigSCEV)) {
Changed = true;
OrigI.replaceAllUsesWith(NewI);
@ -234,7 +234,7 @@ bool NaryReassociatePass::doOneIteration(Function &F) {
DeadInsts.push_back(WeakTrackingVH(&OrigI));
// Add the rewritten instruction to SeenExprs; the original
// instruction is deleted.
const SCEV *NewSCEV = SE->getSCEV(NewI);
SCEVUse NewSCEV = SE->getSCEV(NewI);
SeenExprs[NewSCEV].push_back(WeakTrackingVH(NewI));
// Ideally, NewSCEV should equal OldSCEV because tryReassociate(I)
@ -273,7 +273,7 @@ bool NaryReassociatePass::doOneIteration(Function &F) {
template <typename PredT>
Instruction *
NaryReassociatePass::matchAndReassociateMinOrMax(Instruction *I,
const SCEV *&OrigSCEV) {
SCEVUse &OrigSCEV) {
Value *LHS = nullptr;
Value *RHS = nullptr;
@ -292,8 +292,8 @@ NaryReassociatePass::matchAndReassociateMinOrMax(Instruction *I,
return nullptr;
}
Instruction *NaryReassociatePass::tryReassociate(Instruction * I,
const SCEV *&OrigSCEV) {
Instruction *NaryReassociatePass::tryReassociate(Instruction *I,
SCEVUse &OrigSCEV) {
if (!SE->isSCEVable(I->getType()))
return nullptr;
@ -397,7 +397,7 @@ NaryReassociatePass::tryReassociateGEPAtIndex(GetElementPtrInst *GEP,
Value *RHS, Type *IndexedType) {
// Look for GEP's closest dominator that has the same SCEV as GEP except that
// the I-th index is replaced with LHS.
SmallVector<const SCEV *, 4> IndexExprs;
SmallVector<SCEVUse, 4> IndexExprs;
for (Use &Index : GEP->indices())
IndexExprs.push_back(SE->getSCEV(Index));
// Replace the I-th index with LHS.
@ -414,8 +414,7 @@ NaryReassociatePass::tryReassociateGEPAtIndex(GetElementPtrInst *GEP,
// @reassociate_gep_assume for an example of this canonicalization.
IndexExprs[I] = SE->getZeroExtendExpr(IndexExprs[I], GEPArgType);
}
const SCEV *CandidateExpr = SE->getGEPExpr(cast<GEPOperator>(GEP),
IndexExprs);
SCEVUse CandidateExpr = SE->getGEPExpr(cast<GEPOperator>(GEP), IndexExprs);
Value *Candidate = findClosestMatchingDominator(CandidateExpr, GEP);
if (Candidate == nullptr)
@ -481,8 +480,8 @@ Instruction *NaryReassociatePass::tryReassociateBinaryOp(Value *LHS, Value *RHS,
if (LHS->hasOneUse() && matchTernaryOp(I, LHS, A, B)) {
// I = (A op B) op RHS
// = (A op RHS) op B or (B op RHS) op A
const SCEV *AExpr = SE->getSCEV(A), *BExpr = SE->getSCEV(B);
const SCEV *RHSExpr = SE->getSCEV(RHS);
SCEVUse AExpr = SE->getSCEV(A), BExpr = SE->getSCEV(B);
SCEVUse RHSExpr = SE->getSCEV(RHS);
if (BExpr != RHSExpr) {
if (auto *NewI =
tryReassociatedBinaryOp(getBinarySCEV(I, AExpr, RHSExpr), B, I))
@ -497,7 +496,7 @@ Instruction *NaryReassociatePass::tryReassociateBinaryOp(Value *LHS, Value *RHS,
return nullptr;
}
Instruction *NaryReassociatePass::tryReassociatedBinaryOp(const SCEV *LHSExpr,
Instruction *NaryReassociatePass::tryReassociatedBinaryOp(SCEVUse LHSExpr,
Value *RHS,
BinaryOperator *I) {
// Look for the closest dominator LHS of I that computes LHSExpr, and replace
@ -535,9 +534,8 @@ bool NaryReassociatePass::matchTernaryOp(BinaryOperator *I, Value *V,
return false;
}
const SCEV *NaryReassociatePass::getBinarySCEV(BinaryOperator *I,
const SCEV *LHS,
const SCEV *RHS) {
SCEVUse NaryReassociatePass::getBinarySCEV(BinaryOperator *I, SCEVUse LHS,
SCEVUse RHS) {
switch (I->getOpcode()) {
case Instruction::Add:
return SE->getAddExpr(LHS, RHS);
@ -550,7 +548,7 @@ const SCEV *NaryReassociatePass::getBinarySCEV(BinaryOperator *I,
}
Instruction *
NaryReassociatePass::findClosestMatchingDominator(const SCEV *CandidateExpr,
NaryReassociatePass::findClosestMatchingDominator(SCEVUse CandidateExpr,
Instruction *Dominatee) {
auto Pos = SeenExprs.find(CandidateExpr);
if (Pos == SeenExprs.end())
@ -622,12 +620,11 @@ Value *NaryReassociatePass::tryReassociateMinOrMax(Instruction *I,
}))
return nullptr;
auto tryCombination = [&](Value *A, const SCEV *AExpr, Value *B,
const SCEV *BExpr, Value *C,
const SCEV *CExpr) -> Value * {
SmallVector<const SCEV *, 2> Ops1{BExpr, AExpr};
auto tryCombination = [&](Value *A, SCEVUse AExpr, Value *B, SCEVUse BExpr,
Value *C, SCEVUse CExpr) -> Value * {
SmallVector<SCEVUse, 2> Ops1{BExpr, AExpr};
const SCEVTypes SCEVType = convertToSCEVype(m_MaxMin);
const SCEV *R1Expr = SE->getMinMaxExpr(SCEVType, Ops1);
SCEVUse R1Expr = SE->getMinMaxExpr(SCEVType, Ops1);
Instruction *R1MinMax = findClosestMatchingDominator(R1Expr, I);
@ -636,9 +633,8 @@ Value *NaryReassociatePass::tryReassociateMinOrMax(Instruction *I,
LLVM_DEBUG(dbgs() << "NARY: Found common sub-expr: " << *R1MinMax << "\n");
SmallVector<const SCEV *, 2> Ops2{SE->getUnknown(C),
SE->getUnknown(R1MinMax)};
const SCEV *R2Expr = SE->getMinMaxExpr(SCEVType, Ops2);
SmallVector<SCEVUse, 2> Ops2{SE->getUnknown(C), SE->getUnknown(R1MinMax)};
SCEVUse R2Expr = SE->getMinMaxExpr(SCEVType, Ops2);
SCEVExpander Expander(*SE, "nary-reassociate");
Value *NewMinMax = Expander.expandCodeFor(R2Expr, I->getType(), I);
@ -649,9 +645,9 @@ Value *NaryReassociatePass::tryReassociateMinOrMax(Instruction *I,
return NewMinMax;
};
const SCEV *AExpr = SE->getSCEV(A);
const SCEV *BExpr = SE->getSCEV(B);
const SCEV *RHSExpr = SE->getSCEV(RHS);
SCEVUse AExpr = SE->getSCEV(A);
SCEVUse BExpr = SE->getSCEV(B);
SCEVUse RHSExpr = SE->getSCEV(RHS);
if (BExpr != RHSExpr) {
// Try (A op RHS) op B

View File

@ -1086,7 +1086,7 @@ void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForGEP(
if (GEP->getType()->isVectorTy())
return;
SmallVector<const SCEV *, 4> IndexExprs;
SmallVector<SCEVUse, 4> IndexExprs;
for (Use &Idx : GEP->indices())
IndexExprs.push_back(SE->getSCEV(Idx));
@ -1095,12 +1095,12 @@ void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForGEP(
if (GTI.isStruct())
continue;
const SCEV *OrigIndexExpr = IndexExprs[I - 1];
IndexExprs[I - 1] = SE->getZero(OrigIndexExpr->getType());
SCEVUse OrigIndexExpr = IndexExprs[I - 1];
IndexExprs[I - 1] = SE->getZero(OrigIndexExpr.getPointer()->getType());
// The base of this candidate is GEP's base plus the offsets of all
// indices except this current one.
const SCEV *BaseExpr = SE->getGEPExpr(cast<GEPOperator>(GEP), IndexExprs);
SCEVUse BaseExpr = SE->getGEPExpr(cast<GEPOperator>(GEP), IndexExprs);
Value *ArrayIdx = GEP->getOperand(I);
uint64_t ElementSize = GTI.getSequentialElementStride(*DL);
IntegerType *PtrIdxTy = cast<IntegerType>(DL->getIndexType(GEP->getType()));

View File

@ -563,7 +563,7 @@ Value *SCEVExpander::visitAddExpr(const SCEVAddExpr *S) {
if (isa<PointerType>(Sum->getType())) {
// The running sum expression is a pointer. Try to form a getelementptr
// at this level with that as the base.
SmallVector<const SCEV *, 4> NewOps;
SmallVector<SCEVUse, 4> NewOps;
for (; I != E && I->first == CurLoop; ++I) {
// If the operand is SCEVUnknown and not instructions, peek through
// it, to enable more of it to be folded into the GEP.
@ -1336,7 +1336,7 @@ Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) {
if (CanonicalIV &&
SE.getTypeSizeInBits(CanonicalIV->getType()) > SE.getTypeSizeInBits(Ty) &&
!S->getType()->isPointerTy()) {
SmallVector<const SCEV *, 4> NewOps(S->getNumOperands());
SmallVector<SCEVUse, 4> NewOps(S->getNumOperands());
for (unsigned i = 0, e = S->getNumOperands(); i != e; ++i)
NewOps[i] = SE.getAnyExtendExpr(S->getOperand(i), CanonicalIV->getType());
Value *V = expand(SE.getAddRecExpr(NewOps, S->getLoop(),
@ -1360,7 +1360,7 @@ Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) {
S->getNoWrapFlags(SCEV::FlagNUW));
}
SmallVector<const SCEV *, 4> NewOps(S->operands());
SmallVector<SCEVUse, 4> NewOps(S->operands());
NewOps[0] = SE.getConstant(Ty, 0);
const SCEV *Rest = SE.getAddRecExpr(NewOps, L,
S->getNoWrapFlags(SCEV::FlagNW));

View File

@ -537,7 +537,8 @@ public:
const SCEV *NewStep =
SE.getMulExpr(Step, SE.getConstant(Ty, StepMultiplier));
const SCEV *ScaledOffset = SE.getMulExpr(Step, SE.getConstant(Ty, Offset));
const SCEV *NewStart = SE.getAddExpr(Expr->getStart(), ScaledOffset);
const SCEV *NewStart =
SE.getAddExpr(Expr->getStart(), SCEVUse(ScaledOffset));
return SE.getAddRecExpr(NewStart, NewStep, TheLoop, SCEV::FlagAnyWrap);
}

View File

@ -149,11 +149,10 @@ const SCEV *vputils::getSCEVExprForVPValue(const VPValue *V,
}
// Helper to create SCEVs for binary and unary operations.
auto CreateSCEV =
[&](ArrayRef<VPValue *> Ops,
function_ref<const SCEV *(ArrayRef<const SCEV *>)> CreateFn)
auto CreateSCEV = [&](ArrayRef<VPValue *> Ops,
function_ref<const SCEV *(ArrayRef<SCEVUse>)> CreateFn)
-> const SCEV * {
SmallVector<const SCEV *, 2> SCEVOps;
SmallVector<SCEVUse, 2> SCEVOps;
for (VPValue *Op : Ops) {
const SCEV *S = getSCEVExprForVPValue(Op, PSE, L);
if (isa<SCEVCouldNotCompute>(S))
@ -165,46 +164,46 @@ const SCEV *vputils::getSCEVExprForVPValue(const VPValue *V,
VPValue *LHSVal, *RHSVal;
if (match(V, m_Add(m_VPValue(LHSVal), m_VPValue(RHSVal))))
return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<const SCEV *> Ops) {
return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
return SE.getAddExpr(Ops[0], Ops[1], SCEV::FlagAnyWrap, 0);
});
if (match(V, m_Sub(m_VPValue(LHSVal), m_VPValue(RHSVal))))
return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<const SCEV *> Ops) {
return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
return SE.getMinusSCEV(Ops[0], Ops[1], SCEV::FlagAnyWrap, 0);
});
if (match(V, m_Not(m_VPValue(LHSVal)))) {
// not X = xor X, -1 = -1 - X
return CreateSCEV({LHSVal}, [&](ArrayRef<const SCEV *> Ops) {
return CreateSCEV({LHSVal}, [&](ArrayRef<SCEVUse> Ops) {
return SE.getMinusSCEV(SE.getMinusOne(Ops[0]->getType()), Ops[0]);
});
}
if (match(V, m_Mul(m_VPValue(LHSVal), m_VPValue(RHSVal))))
return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<const SCEV *> Ops) {
return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
return SE.getMulExpr(Ops[0], Ops[1], SCEV::FlagAnyWrap, 0);
});
if (match(V,
m_Binary<Instruction::UDiv>(m_VPValue(LHSVal), m_VPValue(RHSVal))))
return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<const SCEV *> Ops) {
return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
return SE.getUDivExpr(Ops[0], Ops[1]);
});
// Handle AND with constant mask: x & (2^n - 1) can be represented as x % 2^n.
const APInt *Mask;
if (match(V, m_c_BinaryAnd(m_VPValue(LHSVal), m_APInt(Mask))) &&
(*Mask + 1).isPowerOf2())
return CreateSCEV({LHSVal}, [&](ArrayRef<const SCEV *> Ops) {
return CreateSCEV({LHSVal}, [&](ArrayRef<SCEVUse> Ops) {
return SE.getURemExpr(Ops[0], SE.getConstant(*Mask + 1));
});
if (match(V, m_Trunc(m_VPValue(LHSVal)))) {
const VPlan *Plan = V->getDefiningRecipe()->getParent()->getPlan();
Type *DestTy = VPTypeAnalysis(*Plan).inferScalarType(V);
return CreateSCEV({LHSVal}, [&](ArrayRef<const SCEV *> Ops) {
return CreateSCEV({LHSVal}, [&](ArrayRef<SCEVUse> Ops) {
return SE.getTruncateExpr(Ops[0], DestTy);
});
}
if (match(V, m_ZExt(m_VPValue(LHSVal)))) {
const VPlan *Plan = V->getDefiningRecipe()->getParent()->getPlan();
Type *DestTy = VPTypeAnalysis(*Plan).inferScalarType(V);
return CreateSCEV({LHSVal}, [&](ArrayRef<const SCEV *> Ops) {
return CreateSCEV({LHSVal}, [&](ArrayRef<SCEVUse> Ops) {
return SE.getZeroExtendExpr(Ops[0], DestTy);
});
}
@ -225,35 +224,35 @@ const SCEV *vputils::getSCEVExprForVPValue(const VPValue *V,
SE.getSignExtendExpr(V2, DestTy), SCEV::FlagNSW);
}
return CreateSCEV({LHSVal}, [&](ArrayRef<const SCEV *> Ops) {
return CreateSCEV({LHSVal}, [&](ArrayRef<SCEVUse> Ops) {
return SE.getSignExtendExpr(Ops[0], DestTy);
});
}
if (match(V,
m_Intrinsic<Intrinsic::umax>(m_VPValue(LHSVal), m_VPValue(RHSVal))))
return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<const SCEV *> Ops) {
return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
return SE.getUMaxExpr(Ops[0], Ops[1]);
});
if (match(V,
m_Intrinsic<Intrinsic::smax>(m_VPValue(LHSVal), m_VPValue(RHSVal))))
return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<const SCEV *> Ops) {
return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
return SE.getSMaxExpr(Ops[0], Ops[1]);
});
if (match(V,
m_Intrinsic<Intrinsic::umin>(m_VPValue(LHSVal), m_VPValue(RHSVal))))
return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<const SCEV *> Ops) {
return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
return SE.getUMinExpr(Ops[0], Ops[1]);
});
if (match(V,
m_Intrinsic<Intrinsic::smin>(m_VPValue(LHSVal), m_VPValue(RHSVal))))
return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<const SCEV *> Ops) {
return CreateSCEV({LHSVal, RHSVal}, [&](ArrayRef<SCEVUse> Ops) {
return SE.getSMinExpr(Ops[0], Ops[1]);
});
ArrayRef<VPValue *> Ops;
Type *SourceElementType;
if (match(V, m_GetElementPtr(SourceElementType, Ops))) {
const SCEV *GEPExpr = CreateSCEV(Ops, [&](ArrayRef<const SCEV *> Ops) {
const SCEV *GEPExpr = CreateSCEV(Ops, [&](ArrayRef<SCEVUse> Ops) {
return SE.getGEPExpr(Ops.front(), Ops.drop_front(), SourceElementType);
});
return PSE.getPredicatedSCEV(GEPExpr);

View File

@ -251,12 +251,12 @@ TEST_F(ScalarEvolutionsTest, CommutativeExprOperandOrder) {
EXPECT_EQ(SE.getMulExpr(B, C), SE.getMulExpr(C, B));
EXPECT_EQ(SE.getMulExpr(A, C), SE.getMulExpr(C, A));
SmallVector<const SCEV *, 3> Ops0 = {A, B, C};
SmallVector<const SCEV *, 3> Ops1 = {A, C, B};
SmallVector<const SCEV *, 3> Ops2 = {B, A, C};
SmallVector<const SCEV *, 3> Ops3 = {B, C, A};
SmallVector<const SCEV *, 3> Ops4 = {C, B, A};
SmallVector<const SCEV *, 3> Ops5 = {C, A, B};
SmallVector<SCEVUse, 3> Ops0 = {A, B, C};
SmallVector<SCEVUse, 3> Ops1 = {A, C, B};
SmallVector<SCEVUse, 3> Ops2 = {B, A, C};
SmallVector<SCEVUse, 3> Ops3 = {B, C, A};
SmallVector<SCEVUse, 3> Ops4 = {C, B, A};
SmallVector<SCEVUse, 3> Ops5 = {C, A, B};
const SCEV *Mul0 = SE.getMulExpr(Ops0);
const SCEV *Mul1 = SE.getMulExpr(Ops1);
@ -542,13 +542,14 @@ TEST_F(ScalarEvolutionsTest, SCEVNormalization) {
auto *L1 = *std::next(LI.begin());
auto *L0 = *std::next(LI.begin(), 2);
auto GetAddRec = [&SE](const Loop *L, std::initializer_list<const SCEV *> Ops) {
SmallVector<const SCEV *, 4> OpsCopy(Ops);
auto GetAddRec = [&SE](const Loop *L,
std::initializer_list<const SCEV *> Ops) {
SmallVector<SCEVUse, 4> OpsCopy(Ops.begin(), Ops.end());
return SE.getAddRecExpr(OpsCopy, L, SCEV::FlagAnyWrap);
};
auto GetAdd = [&SE](std::initializer_list<const SCEV *> Ops) {
SmallVector<const SCEV *, 4> OpsCopy(Ops);
SmallVector<SCEVUse, 4> OpsCopy(Ops.begin(), Ops.end());
return SE.getAddExpr(OpsCopy, SCEV::FlagAnyWrap);
};
@ -1729,7 +1730,7 @@ TEST_F(ScalarEvolutionsTest, ComplexityComparatorIsStrictWeakOrdering2) {
const SCEV *M0 = SE.getNegativeSCEV(P0);
const SCEV *M2 = SE.getNegativeSCEV(P2);
SmallVector<const SCEV *, 6> Ops = {M2, P0, M0, P1, P2};
SmallVector<SCEVUse, 6> Ops = {M2, P0, M0, P1, P2};
// When _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG, this will
// crash if the comparator has the specific caching bug.
SE.getAddExpr(Ops);

View File

@ -873,8 +873,8 @@ TEST_F(ScalarEvolutionExpanderTest, SCEVExpandNonAffineAddRec) {
// Expand {5,+,1,+,1}
auto GetAR3 = [&](ScalarEvolution &SE, Loop *L) -> const SCEVAddRecExpr * {
SmallVector<const SCEV *, 3> Ops = {SE.getConstant(APInt(ARBitWidth, 5)),
SE.getOne(ARType), SE.getOne(ARType)};
SmallVector<SCEVUse, 3> Ops = {SE.getConstant(APInt(ARBitWidth, 5)),
SE.getOne(ARType), SE.getOne(ARType)};
return cast<SCEVAddRecExpr>(SE.getAddRecExpr(Ops, L, SCEV::FlagAnyWrap));
};
TestNoCanonicalIV(GetAR3);
@ -883,9 +883,9 @@ TEST_F(ScalarEvolutionExpanderTest, SCEVExpandNonAffineAddRec) {
// Expand {5,+,1,+,1,+,1}
auto GetAR4 = [&](ScalarEvolution &SE, Loop *L) -> const SCEVAddRecExpr * {
SmallVector<const SCEV *, 4> Ops = {SE.getConstant(APInt(ARBitWidth, 5)),
SE.getOne(ARType), SE.getOne(ARType),
SE.getOne(ARType)};
SmallVector<SCEVUse, 4> Ops = {SE.getConstant(APInt(ARBitWidth, 5)),
SE.getOne(ARType), SE.getOne(ARType),
SE.getOne(ARType)};
return cast<SCEVAddRecExpr>(SE.getAddRecExpr(Ops, L, SCEV::FlagAnyWrap));
};
TestNoCanonicalIV(GetAR4);
@ -894,9 +894,9 @@ TEST_F(ScalarEvolutionExpanderTest, SCEVExpandNonAffineAddRec) {
// Expand {5,+,1,+,1,+,1,+,1}
auto GetAR5 = [&](ScalarEvolution &SE, Loop *L) -> const SCEVAddRecExpr * {
SmallVector<const SCEV *, 5> Ops = {SE.getConstant(APInt(ARBitWidth, 5)),
SE.getOne(ARType), SE.getOne(ARType),
SE.getOne(ARType), SE.getOne(ARType)};
SmallVector<SCEVUse, 5> Ops = {SE.getConstant(APInt(ARBitWidth, 5)),
SE.getOne(ARType), SE.getOne(ARType),
SE.getOne(ARType), SE.getOne(ARType)};
return cast<SCEVAddRecExpr>(SE.getAddRecExpr(Ops, L, SCEV::FlagAnyWrap));
};
TestNoCanonicalIV(GetAR5);

View File

@ -35,7 +35,6 @@ using llvm::Instruction;
using llvm::LoadInst;
using llvm::Loop;
using llvm::LoopInfo;
using llvm::LoopToScevMapT;
using llvm::MapVector;
using llvm::PHINode;
using llvm::ScalarEvolution;

View File

@ -14,6 +14,7 @@
#define POLLY_SUPPORT_IRHELPER_H
#include "llvm/ADT/SetVector.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/ValueHandle.h"
@ -37,7 +38,7 @@ class Scop;
class ScopStmt;
/// Same as llvm/Analysis/ScalarEvolutionExpressions.h
using LoopToScevMapT = llvm::DenseMap<const llvm::Loop *, const llvm::SCEV *>;
using LoopToScevMapT = llvm::DenseMap<const llvm::Loop *, llvm::SCEVUse>;
/// Enumeration of assumptions Polly can take.
enum AssumptionKind {

View File

@ -886,7 +886,7 @@ ScopDetection::getDelinearizationTerms(DetectionContext &Context,
if (auto *AF2 = dyn_cast<SCEVAddRecExpr>(Op))
collectParametricTerms(SE, AF2, Terms);
if (auto *AF2 = dyn_cast<SCEVMulExpr>(Op)) {
SmallVector<const SCEV *, 0> Operands;
SmallVector<SCEVUse, 0> Operands;
for (const SCEV *MulOp : AF2->operands()) {
if (auto *Const = dyn_cast<SCEVConstant>(MulOp))

View File

@ -700,7 +700,7 @@ polly::extractConstantFactor(const SCEV *S, ScalarEvolution &SE) {
}
if (auto *Add = dyn_cast<SCEVAddExpr>(S)) {
SmallVector<const SCEV *, 4> LeftOvers;
SmallVector<SCEVUse, 4> LeftOvers;
auto Op0Pair = extractConstantFactor(Add->getOperand(0), SE);
auto *Factor = Op0Pair.first;
if (SE.isKnownNegative(Factor)) {
@ -729,7 +729,7 @@ polly::extractConstantFactor(const SCEV *S, ScalarEvolution &SE) {
if (!Mul)
return std::make_pair(ConstPart, S);
SmallVector<const SCEV *, 4> LeftOvers;
SmallVector<SCEVUse, 4> LeftOvers;
for (const SCEV *Op : Mul->operands())
if (isa<SCEVConstant>(Op))
ConstPart = cast<SCEVConstant>(SE.getMulExpr(ConstPart, Op));

View File

@ -243,7 +243,7 @@ struct ScopExpander final : SCEVVisitor<ScopExpander, const SCEV *> {
explicit ScopExpander(const Region &R, ScalarEvolution &SE, Function *GenFn,
ScalarEvolution &GenSE, const char *Name,
ValueMapT *VMap, LoopToScevMapT *LoopMap,
ValueMapT *VMap, polly::LoopToScevMapT *LoopMap,
BasicBlock *RTCBB)
: Expander(GenSE, Name, /*PreserveLCSSA=*/false), Name(Name), R(R),
VMap(VMap), LoopMap(LoopMap), RTCBB(RTCBB), GenSE(GenSE), GenFn(GenFn) {
@ -272,7 +272,7 @@ private:
const char *Name;
const Region &R;
ValueMapT *VMap;
LoopToScevMapT *LoopMap;
polly::LoopToScevMapT *LoopMap;
BasicBlock *RTCBB;
DenseMap<const SCEV *, const SCEV *> SCEVCache;
@ -389,50 +389,50 @@ private:
return GenSE.getUDivExpr(visit(E->getLHS()), RHSScev);
}
const SCEV *visitAddExpr(const SCEVAddExpr *E) {
SmallVector<const SCEV *, 4> NewOps;
SmallVector<SCEVUse, 4> NewOps;
for (const SCEV *Op : E->operands())
NewOps.push_back(visit(Op));
return GenSE.getAddExpr(NewOps);
}
const SCEV *visitMulExpr(const SCEVMulExpr *E) {
SmallVector<const SCEV *, 4> NewOps;
SmallVector<SCEVUse, 4> NewOps;
for (const SCEV *Op : E->operands())
NewOps.push_back(visit(Op));
return GenSE.getMulExpr(NewOps);
}
const SCEV *visitUMaxExpr(const SCEVUMaxExpr *E) {
SmallVector<const SCEV *, 4> NewOps;
for (const SCEV *Op : E->operands())
SmallVector<SCEVUse, 4> NewOps;
for (SCEVUse Op : E->operands())
NewOps.push_back(visit(Op));
return GenSE.getUMaxExpr(NewOps);
}
const SCEV *visitSMaxExpr(const SCEVSMaxExpr *E) {
SmallVector<const SCEV *, 4> NewOps;
for (const SCEV *Op : E->operands())
SmallVector<SCEVUse, 4> NewOps;
for (SCEVUse Op : E->operands())
NewOps.push_back(visit(Op));
return GenSE.getSMaxExpr(NewOps);
}
const SCEV *visitUMinExpr(const SCEVUMinExpr *E) {
SmallVector<const SCEV *, 4> NewOps;
for (const SCEV *Op : E->operands())
SmallVector<SCEVUse, 4> NewOps;
for (SCEVUse Op : E->operands())
NewOps.push_back(visit(Op));
return GenSE.getUMinExpr(NewOps);
}
const SCEV *visitSMinExpr(const SCEVSMinExpr *E) {
SmallVector<const SCEV *, 4> NewOps;
for (const SCEV *Op : E->operands())
SmallVector<SCEVUse, 4> NewOps;
for (SCEVUse Op : E->operands())
NewOps.push_back(visit(Op));
return GenSE.getSMinExpr(NewOps);
}
const SCEV *visitSequentialUMinExpr(const SCEVSequentialUMinExpr *E) {
SmallVector<const SCEV *, 4> NewOps;
for (const SCEV *Op : E->operands())
SmallVector<SCEVUse, 4> NewOps;
for (SCEVUse Op : E->operands())
NewOps.push_back(visit(Op));
return GenSE.getUMinExpr(NewOps, /*Sequential=*/true);
}
const SCEV *visitAddRecExpr(const SCEVAddRecExpr *E) {
SmallVector<const SCEV *, 4> NewOps;
for (const SCEV *Op : E->operands())
SmallVector<SCEVUse, 4> NewOps;
for (SCEVUse Op : E->operands())
NewOps.push_back(visit(Op));
const Loop *L = E->getLoop();