Index: include/polly/Support/SCEVValidator.h =================================================================== --- include/polly/Support/SCEVValidator.h +++ include/polly/Support/SCEVValidator.h @@ -73,6 +73,16 @@ /// @returns The constant factor in @p M and the rest of @p M. std::pair extractConstantFactor(const llvm::SCEV *M, llvm::ScalarEvolution &SE); + +struct SCEVInterval { + const llvm::SCEV *Min; + const llvm::SCEV *Max; + SCEVInterval() : Min(nullptr), Max(nullptr) {} + SCEVInterval(const llvm::SCEV *Min, const llvm::SCEV *Max) + : Min(Min), Max(Max) {} +}; + +SCEVInterval getInterval(const llvm::SCEV *Expr, llvm::ScalarEvolution &SE); } #endif Index: lib/Analysis/ScopInfo.cpp =================================================================== --- lib/Analysis/ScopInfo.cpp +++ lib/Analysis/ScopInfo.cpp @@ -2030,6 +2030,23 @@ for (auto *Parameter : Parameters) { ConstantRange SRange = SE->getSignedRange(Parameter); Context = addRangeBoundsToSet(Context, SRange, PDim++, isl_dim_param); + + SCEVInterval SI = getInterval(Parameter, *SE); + if (SI.Min && SI.Min != Parameter && + isAffineExpr(&getRegion(), nullptr, SI.Min, *SE)) { + auto *PPWA = getPwAffOnly(Parameter); + auto *MinPWA = getPwAffOnly(SI.Min); + auto *MinSet = isl_set_params(isl_pw_aff_ge_set(PPWA, MinPWA)); + Context = isl_set_intersect(Context, MinSet); + } + + if (SI.Max && SI.Max != Parameter && + isAffineExpr(&getRegion(), nullptr, SI.Max, *SE)) { + auto *PPWA = getPwAffOnly(Parameter); + auto *MaxPWA = getPwAffOnly(SI.Max); + auto *MaxSet = isl_set_params(isl_pw_aff_le_set(PPWA, MaxPWA)); + Context = isl_set_intersect(Context, MaxSet); + } } } Index: lib/Support/SCEVValidator.cpp =================================================================== --- lib/Support/SCEVValidator.cpp +++ lib/Support/SCEVValidator.cpp @@ -631,4 +631,125 @@ return std::make_pair(ConstPart, LeftOver); } + +/// @brief +struct SCEVIntervalAnalysis + : public SCEVVisitor { +private: + ScalarEvolution &SE; + +public: + SCEVIntervalAnalysis(ScalarEvolution &SE) : SE(SE) {} + + SCEVInterval visitConstant(const SCEVConstant *Constant) { + return SCEVInterval(Constant, Constant); + } + + SCEVInterval visitTruncateExpr(const SCEVTruncateExpr *Expr) { + return SCEVInterval(); + } + + SCEVInterval visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) { + return SCEVInterval(); + } + + SCEVInterval visitSignExtendExpr(const SCEVSignExtendExpr *Expr) { + return visit(Expr->getOperand()); + } + + SCEVInterval visitAddExpr(const SCEVAddExpr *Expr) { + return SCEVInterval(); + // SCEVInterval Return = visit(Expr->getOperand(0)); + // if (!Return.Min || !Return.Max) + // return SCEVInterval(); + + // for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) { + // SCEVInterval Op = visit(Expr->getOperand(i)); + // if (!Op.Min || !Op.Max) + // return SCEVInterval(); + + // Return.Min = SE.getSMinExpr(Return.Min, Op.Min); + //} + // return Return; + } + + SCEVInterval visitMulExpr(const SCEVMulExpr *Expr) { return SCEVInterval(); } + + SCEVInterval visitUDivExpr(const SCEVUDivExpr *Expr) { + return SCEVInterval(); + } + + SCEVInterval visitAddRecExpr(const SCEVAddRecExpr *Expr) { + auto *StartSCEV = Expr->getStart(); + auto *StepSCEV = Expr->getStepRecurrence(SE); + auto *TripCountSCEV = SE.getMaxBackedgeTakenCount(Expr->getLoop()); + if (Expr->getType() == TripCountSCEV->getType()) { + /* No Op */ + } else if (TripCountSCEV->getType()->getScalarSizeInBits() > + Expr->getType()->getScalarSizeInBits()) { + auto *Ty = TripCountSCEV->getType(); + StartSCEV = SE.getSignExtendExpr(StartSCEV, Ty); + StepSCEV = SE.getSignExtendExpr(StepSCEV, Ty); + } else { + TripCountSCEV = SE.getSignExtendExpr(TripCountSCEV, Expr->getType()); + } + + SCEVInterval Start = visit(StartSCEV); + SCEVInterval Step = visit(StepSCEV); + bool IsKnowPos = SE.isKnownPositive(StepSCEV); + bool IsKnowNeg = !IsKnowPos && SE.isKnownNegative(StepSCEV); + if (!IsKnowPos && !IsKnowNeg) + return SCEVInterval(); + + auto *Min = IsKnowPos ? Start.Min : nullptr; + auto *Max = IsKnowNeg ? Start.Max : nullptr; + if (isa(TripCountSCEV)) + return SCEVInterval(Min, Max); + + SCEVInterval TripCount = visit(TripCountSCEV); + if (!TripCount.Max || !Step.Max) + return SCEVInterval(Min, Max); + + auto *MaxOffset = SE.getMulExpr(TripCount.Max, Step.Max); + if ((IsKnowPos && !Start.Max) || (!IsKnowPos && !Start.Min)) + return SCEVInterval(Min, Max); + + if (IsKnowPos) + Max = SE.getAddExpr(Start.Max, MaxOffset); + else + Min = SE.getAddExpr(Start.Min, MaxOffset); + + return SCEVInterval(Min, Max); + } + + SCEVInterval visitSMaxExpr(const SCEVSMaxExpr *Expr) { + SCEVInterval Return = visit(Expr->getOperand(0)); + if (!Return.Min || !Return.Max) + return SCEVInterval(); + + for (int i = 1, e = Expr->getNumOperands(); i < e; ++i) { + SCEVInterval Op = visit(Expr->getOperand(i)); + if (!Op.Min || !Op.Max) + return SCEVInterval(); + + Return.Min = SE.getSMaxExpr(Return.Min, Op.Min); + Return.Max = SE.getSMaxExpr(Return.Max, Op.Max); + } + + return Return; + } + + SCEVInterval visitUMaxExpr(const SCEVUMaxExpr *Expr) { + return SCEVInterval(); + } + + SCEVInterval visitUnknown(const SCEVUnknown *Expr) { + return SCEVInterval(Expr, Expr); + } +}; + +SCEVInterval getInterval(const SCEV *Expr, ScalarEvolution &SE) { + SCEVIntervalAnalysis SIA(SE); + return SIA.visit(Expr); +} }