6 #ifndef JLM_LLVM_OPT_SCALAR_EVOLUTION_HPP
7 #define JLM_LLVM_OPT_SCALAR_EVOLUTION_HPP
19 virtual ~SCEV() noexcept = default;
24 virtual std::unique_ptr<
SCEV>
28 static std::unique_ptr<T>
31 auto cloned = scev.Clone();
32 auto * ptr =
dynamic_cast<T *
>(cloned.release());
34 return std::unique_ptr<T>(ptr);
53 return std::make_unique<SCEVUnknown>();
56 static std::unique_ptr<SCEVUnknown>
59 return std::make_unique<SCEVUnknown>();
79 std::ostringstream oss;
90 static std::unique_ptr<SCEVInit>
93 return std::make_unique<SCEVInit>(prePointer);
116 std::ostringstream oss;
121 std::unique_ptr<SCEV>
124 return std::make_unique<SCEVPlaceholder>(*
PrePointer_);
127 static std::unique_ptr<SCEVPlaceholder>
130 return std::make_unique<SCEVPlaceholder>(
PrePointer_);
153 return std::to_string(
Value_);
156 std::unique_ptr<SCEV>
159 return std::make_unique<SCEVConstant>(
Value_);
162 static std::unique_ptr<SCEVConstant>
165 return std::make_unique<SCEVConstant>(value);
223 SCEVAddExpr(std::unique_ptr<SCEV> left, std::unique_ptr<SCEV> right)
230 std::ostringstream oss;
233 oss <<
"(" << leftStr <<
" + " << rightStr <<
")";
237 std::unique_ptr<SCEV>
242 return std::make_unique<SCEVAddExpr>(std::move(leftClone), std::move(rightClone));
245 static std::unique_ptr<SCEVAddExpr>
246 Create(std::unique_ptr<SCEV> left, std::unique_ptr<SCEV> right)
248 return std::make_unique<SCEVAddExpr>(std::move(left), std::move(right));
255 SCEVMulExpr(std::unique_ptr<SCEV> left, std::unique_ptr<SCEV> right)
262 std::ostringstream oss;
265 oss <<
"(" << leftStr <<
" * " << rightStr <<
")";
269 std::unique_ptr<SCEV>
274 return std::make_unique<SCEVMulExpr>(std::move(leftClone), std::move(rightClone));
277 static std::unique_ptr<SCEVMulExpr>
278 Create(std::unique_ptr<SCEV> left, std::unique_ptr<SCEV> right)
280 return std::make_unique<SCEVMulExpr>(std::move(left), std::move(right));
291 template<
typename... Args>
298 template<
typename... Args>
362 template<
typename... Args>
407 return &chrec.
GetLoop() != θ
410 std::optional<std::unique_ptr<SCEV>>
424 newRec->AddOperand(operand->Clone());
438 std::ostringstream oss;
440 for (
size_t i = 0; i <
Operands_.size(); ++i)
450 std::unique_ptr<SCEV>
453 auto copy = std::make_unique<SCEVChainRecurrence>(*
Loop_, *
Output_);
456 copy->AddOperand(op->Clone());
461 static std::unique_ptr<SCEVChainRecurrence>
464 return std::make_unique<SCEVChainRecurrence>(loop, output);
467 template<
typename... Args>
468 static std::unique_ptr<SCEVChainRecurrence>
471 return std::make_unique<SCEVChainRecurrence>(loop, output, std::forward<Args>(
operands)...);
488 template<
typename... Args>
496 std::ostringstream oss;
498 for (
size_t i = 0; i <
Operands_.size(); ++i)
508 std::unique_ptr<SCEV>
511 auto copy = std::make_unique<SCEVNAryAddExpr>();
514 copy->AddOperand(op->Clone());
519 template<
typename... Args>
520 static std::unique_ptr<SCEVNAryAddExpr>
523 return std::make_unique<SCEVNAryAddExpr>(std::forward<Args>(
operands)...);
536 template<
typename... Args>
544 std::ostringstream oss;
546 for (
size_t i = 0; i <
Operands_.size(); ++i)
556 std::unique_ptr<SCEV>
559 auto copy = std::make_unique<SCEVNAryMulExpr>();
562 copy->AddOperand(op->Clone());
567 template<
typename... Args>
568 static std::unique_ptr<SCEVNAryMulExpr>
571 return std::make_unique<SCEVNAryMulExpr>(std::forward<Args>(
operands)...);
631 std::unordered_map<const rvsdg::Output *, std::unique_ptr<
SCEV>>
634 std::unordered_map<const rvsdg::ThetaNode *,
size_t>
640 std::optional<
size_t>
662 [[nodiscard]] static
bool
683 static std::optional<
size_t>
687 const rvsdg::SimpleOperation * comparisonOperation);
699 static std::optional<
size_t>
711 static std::unique_ptr<
SCEV>
714 std::unique_ptr<
SCEV>
723 static std::vector<rvsdg::Output *>
729 std::unique_ptr<
SCEV>
731 const rvsdg::SimpleNode & gepNode,
733 const rvsdg::Type & type);
743 std::optional<std::unique_ptr<
SCEV>>
748 rvsdg::Output & output,
750 rvsdg::ThetaNode & thetaNode);
754 rvsdg::Output & output,
755 const
SCEV & scevTree,
756 rvsdg::ThetaNode & thetaNode);
765 static std::unique_ptr<
SCEV>
772 rvsdg::Output & output);
781 static std::unique_ptr<
SCEV>
790 static std::unique_ptr<
SCEV>
813 rvsdg::Output & currentOutput,
814 const rvsdg::Output & originalOutput,
816 std::unordered_set<const rvsdg::Output *> & visited,
817 std::unordered_set<const rvsdg::Output *> & recursionStack);
static jlm::util::StatisticsCollector statisticsCollector
static std::unique_ptr< SCEVAddExpr > Create(std::unique_ptr< SCEV > left, std::unique_ptr< SCEV > right)
SCEVAddExpr(std::unique_ptr< SCEV > left, std::unique_ptr< SCEV > right)
std::unique_ptr< SCEV > Clone() const override
std::string DebugString() const override
SCEV * GetLeftOperand() const
std::unique_ptr< SCEV > RightOperand_
void SetLeftOperand(std::unique_ptr< SCEV > op)
SCEVBinaryExpr(std::unique_ptr< SCEV > left, std::unique_ptr< SCEV > right)
std::unique_ptr< SCEV > LeftOperand_
SCEV * GetRightOperand() const
void SetRightOperand(std::unique_ptr< SCEV > op)
SCEVChainRecurrence(rvsdg::ThetaNode &theta, rvsdg::Output &output, Args &&... operands)
rvsdg::ThetaNode & GetLoop() const noexcept
SCEV * GetStartValue() const
static bool IsQuadratic(const SCEVChainRecurrence &chrec)
static bool IsConstant(const SCEVChainRecurrence &chrec)
std::unique_ptr< SCEV > Clone() const override
std::string DebugString() const override
SCEVChainRecurrence(rvsdg::ThetaNode &theta, rvsdg::Output &output)
rvsdg::Output & GetOutput() const noexcept
static std::unique_ptr< SCEVChainRecurrence > Create(rvsdg::ThetaNode &loop, rvsdg::Output &output, Args &&... operands)
std::optional< std::unique_ptr< SCEV > > GetStep() const
static std::unique_ptr< SCEVChainRecurrence > Create(rvsdg::ThetaNode &loop, rvsdg::Output &output)
void AddOperandToFront(const std::unique_ptr< SCEV > &initScev)
static bool IsInvariantInLoop(const SCEVChainRecurrence &chrec, const rvsdg::ThetaNode &theta)
static bool IsAffine(const SCEVChainRecurrence &chrec)
std::unique_ptr< SCEV > Clone() const override
SCEVConstant(const int64_t value)
static bool IsNonZero(const SCEVConstant *c)
static std::unique_ptr< SCEVConstant > Create(const int64_t value)
std::string DebugString() const override
rvsdg::Output & GetPrePointer() const noexcept
rvsdg::Output * PrePointer_
static std::unique_ptr< SCEVInit > Create(rvsdg::Output &prePointer)
std::string DebugString() const override
SCEVInit(rvsdg::Output &pre)
std::unique_ptr< SCEV > Clone() const override
std::string DebugString() const override
SCEVMulExpr(std::unique_ptr< SCEV > left, std::unique_ptr< SCEV > right)
std::unique_ptr< SCEV > Clone() const override
static std::unique_ptr< SCEVMulExpr > Create(std::unique_ptr< SCEV > left, std::unique_ptr< SCEV > right)
static std::unique_ptr< SCEVNAryAddExpr > Create(Args &&... operands)
SCEVNAryAddExpr(Args &&... operands)
std::string DebugString() const override
std::unique_ptr< SCEV > Clone() const override
SCEV * GetOperand(const size_t index) const
size_t NumOperands() const
std::vector< std::unique_ptr< SCEV > > Operands_
SCEVNAryExpr(Args &&... operands)
void RemoveOperand(const size_t index)
void AddOperands(Args &&... operands)
void AddOperand(std::unique_ptr< SCEV > scev)
std::vector< SCEV * > GetOperands() const
void ReplaceOperand(const size_t index, const std::unique_ptr< SCEV > &operand)
SCEVNAryMulExpr(Args &&... operands)
static std::unique_ptr< SCEVNAryMulExpr > Create(Args &&... operands)
std::string DebugString() const override
std::unique_ptr< SCEV > Clone() const override
std::string DebugString() const override
rvsdg::Output * PrePointer_
std::unique_ptr< SCEV > Clone() const override
SCEVPlaceholder(rvsdg::Output &pre)
static std::unique_ptr< SCEVPlaceholder > Create(rvsdg::Output &PrePointer_)
rvsdg::Output & GetPrePointer() const noexcept
std::unique_ptr< SCEV > Clone() const override
static std::unique_ptr< SCEVUnknown > Create()
std::string DebugString() const override
virtual ~SCEV() noexcept=default
static std::unique_ptr< T > CloneAs(const SCEV &scev)
virtual std::unique_ptr< SCEV > Clone() const =0
virtual std::string DebugString() const =0
std::unordered_map< rvsdg::Output *, DependencyInfo > DependencyMap
std::unordered_map< rvsdg::Output *, DependencyMap > DependencyGraph
static std::unique_ptr< SCEVChainRecurrence > ComputeProductOfChrecs(SCEVChainRecurrence *lhsChrec, SCEVChainRecurrence *rhsChrec, rvsdg::Output &output)
std::optional< std::unique_ptr< SCEV > > TryReplaceInitForSCEV(const SCEV &scev, rvsdg::Output &output)
std::unique_ptr< SCEVChainRecurrence > GetOrCreateStepForSCEV(rvsdg::Output &output, const SCEV &scevTree, rvsdg::ThetaNode &thetaNode)
std::unordered_map< const rvsdg::Output *, std::unique_ptr< SCEVChainRecurrence > > GetChrecMap() const
void PerformSCEVAnalysis(rvsdg::ThetaNode &thetaNode)
void Run(rvsdg::RvsdgModule &rvsdgModule, util::StatisticsCollector &statisticsCollector) override
Perform RVSDG transformation.
static void FindDependenciesForSCEV(const SCEV &scev, DependencyMap &dependencies, DependencyOp op)
static bool IsStepZero(const SCEV &stepSCEV)
static std::unique_ptr< SCEV > ApplyMulFolding(SCEV *lhsOperand, SCEV *rhsOperand, rvsdg::Output &output)
Apply folding rules for multiplication to combine two SCEV operands into one.
static std::unique_ptr< SCEV > FoldNAryExpression(SCEVNAryExpr &expression, rvsdg::Output &output)
Try to combine the constants in an n-ary expression (Add or Mul) into themselves.
static std::optional< size_t > SolveQuadraticEquation(int64_t a, int64_t b, int64_t c)
Tries to find a solution to the quadratic equation a^2 x + b x + c = 0 using integer arithmetic.
DependencyGraph CreateDependencyGraph(const rvsdg::ThetaNode &thetaNode) const
static std::unique_ptr< SCEV > ApplyAddFolding(SCEV *lhsOperand, SCEV *rhsOperand, rvsdg::Output &output)
Apply folding rules for addition to combine two SCEV operands into one.
static bool HasCycleThroughOthers(rvsdg::Output ¤tOutput, const rvsdg::Output &originalOutput, DependencyGraph &dependencyGraph, std::unordered_set< const rvsdg::Output * > &visited, std::unordered_set< const rvsdg::Output * > &recursionStack)
~ScalarEvolution() noexcept override
std::unique_ptr< Context > Context_
static bool IsStepPositive(const SCEV &stepSCEV)
void CombineChrecsAcrossLoops()
static bool CanCreateChainRecurrence(rvsdg::Output &output, DependencyGraph &dependencyGraph)
std::unique_ptr< SCEV > ComputeSCEVForGepInnerOffset(const rvsdg::SimpleNode &gepNode, size_t inputIndex, const rvsdg::Type &type)
std::optional< size_t > GetPredictedTripCount(rvsdg::ThetaNode &thetaNode)
static bool StructurallyEqual(const SCEV &a, const SCEV &b)
static bool IsUnknown(const SCEV &scev)
std::unordered_map< const rvsdg::Output *, std::unique_ptr< SCEV > > GetSCEVMap() const
static bool IsStepNegative(const SCEV &stepSCEV)
static std::vector< rvsdg::Output * > TopologicalSort(DependencyGraph &dependencyGraph)
std::unique_ptr< SCEV > GetOrCreateSCEVForOutput(rvsdg::Output &output)
std::unique_ptr< SCEVChainRecurrence > GetOrCreateChainRecurrence(rvsdg::Output &output, const SCEV &scev, rvsdg::ThetaNode &thetaNode)
std::unordered_map< const rvsdg::ThetaNode *, size_t > GetTripCountMap() const noexcept
static std::unique_ptr< SCEV > GetNegativeSCEV(const SCEV &scev)
void AnalyzeRegion(rvsdg::Region ®ion)
static std::optional< size_t > ComputeBackedgeTakenCountForChrec(const SCEVChainRecurrence &chrec, int64_t bound, const rvsdg::SimpleOperation *comparisonOperation)
virtual std::string debug_string() const
Id getRegionId() const noexcept
rvsdg::Region * subregion() const noexcept
Global memory state passed between functions.
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)
DependencyInfo(const int c=0, const DependencyOp op=DependencyOp::None)