6 #ifndef JLM_LLVM_OPT_SCALAR_EVOLUTION_HPP
7 #define JLM_LLVM_OPT_SCALAR_EVOLUTION_HPP
21 virtual ~SCEV() noexcept = default;
26 virtual std::unique_ptr<
SCEV>
45 return std::make_unique<SCEVUnknown>();
65 std::ostringstream oss;
66 oss <<
"Init(" << PrePointer_->debug_string() <<
")";
73 return std::make_unique<SCEVInit>(*PrePointer_);
96 std::ostringstream oss;
97 oss <<
"PH(" << PrePointer_->debug_string() <<
")";
101 std::unique_ptr<SCEV>
104 return std::make_unique<SCEVPlaceholder>(*PrePointer_);
127 return std::to_string(Value_);
130 std::unique_ptr<SCEV>
133 return std::make_unique<SCEVConstant>(Value_);
148 SCEVAddExpr(std::unique_ptr<SCEV> left, std::unique_ptr<SCEV> right)
149 : LeftOperand_{ std::move(left) },
150 RightOperand_{ std::move(right) }
156 return LeftOperand_.get();
162 return RightOperand_.get();
168 LeftOperand_ = std::move(op);
174 RightOperand_ = std::move(op);
180 std::ostringstream oss;
181 const std::string leftStr = LeftOperand_ ? LeftOperand_->DebugString() :
"null";
182 const std::string rightStr = RightOperand_ ? RightOperand_->DebugString() :
"null";
183 oss <<
"(" << leftStr <<
" + " << rightStr <<
")";
187 std::unique_ptr<SCEV>
190 std::unique_ptr<SCEV> leftClone = LeftOperand_ ? LeftOperand_->Clone() :
nullptr;
191 std::unique_ptr<SCEV> rightClone = RightOperand_ ? RightOperand_->Clone() :
nullptr;
192 return std::make_unique<SCEVAddExpr>(std::move(leftClone), std::move(rightClone));
213 Operands_.push_back(std::move(scev));
225 return Operands_[0].get();
231 Operands_.insert(Operands_.begin(), initScev->Clone());
234 std::vector<const SCEV *>
237 std::vector<const SCEV *>
operands{};
238 for (
auto & op : Operands_)
248 return Operands_.at(index).get();
254 std::ostringstream oss;
256 for (
size_t i = 0; i < Operands_.size(); ++i)
258 oss << Operands_.at(i)->DebugString();
259 if (i < Operands_.size() - 1)
262 oss <<
"}" <<
"<" << Loop_->DebugString() <<
">";
266 std::unique_ptr<SCEV>
269 auto copy = std::make_unique<SCEVChainRecurrence>(*Loop_);
270 for (
const auto & op : Operands_)
272 copy->AddOperand(op->Clone());
291 template<
typename... Args>
295 (AddOperand(std::forward<Args>(
operands)), ...);
298 template<
typename... Args>
302 (AddOperand(std::forward<Args>(
operands)), ...);
308 Operands_.push_back(std::move(scev));
311 std::vector<const SCEV *>
314 std::vector<const SCEV *>
operands{};
315 for (
auto & op : Operands_)
325 return Operands_.at(index).get();
331 std::ostringstream oss;
333 for (
size_t i = 0; i < Operands_.size(); ++i)
335 oss << Operands_.at(i)->DebugString();
336 if (i < Operands_.size() - 1)
343 std::unique_ptr<SCEV>
346 auto copy = std::make_unique<SCEVNAryAddExpr>();
347 for (
const auto & op : Operands_)
349 copy->AddOperand(op->Clone());
368 typedef std::unordered_map<const rvsdg::Output *, std::unordered_map<const rvsdg::Output *, int>>
386 Run(rvsdg::RvsdgModule & rvsdgModule, util::StatisticsCollector & statisticsCollector) override;
389 PerformSCEVAnalysis(const rvsdg::ThetaNode & thetaNode);
392 StructurallyEqual(const
SCEV & a, const
SCEV & b);
396 std::unordered_map<const rvsdg::Output *, std::unique_ptr<
SCEV>> UniqueSCEVs_;
401 AnalyzeRegion(const rvsdg::Region & region);
403 std::unique_ptr<
SCEV>
404 GetOrCreateSCEVForOutput(const rvsdg::Output & output);
406 std::optional<const
SCEV *>
407 TryGetSCEVForOutput(const rvsdg::Output & output);
410 CreateDependencyGraph(const rvsdg::ThetaNode & thetaNode) const;
412 static std::unordered_map<const rvsdg::Output *,
int>
413 FindDependenciesForSCEV(const
SCEV & currentSCEV, const rvsdg::Output & currentIV);
415 static std::vector<const rvsdg::Output *>
419 CreateChainRecurrence(
420 const rvsdg::Output & IV,
421 const
SCEV & scevTree,
422 const rvsdg::ThetaNode & thetaNode);
424 static std::unique_ptr<
SCEV>
425 ApplyFolding(
SCEV * lhsOperand,
SCEV * rhsOperand);
428 IsValidInductionVariable(const rvsdg::Output & variable,
IVDependencyGraph & dependencyGraph);
440 HasCycleThroughOthers(
441 const rvsdg::Output & currentIV,
442 const rvsdg::Output & originalIV,
444 std::unordered_set<const rvsdg::Output *> & visited,
445 std::unordered_set<const rvsdg::Output *> & recursionStack);
void SetLeftOperand(std::unique_ptr< SCEV > op)
std::unique_ptr< SCEV > LeftOperand_
SCEV * GetRightOperand() const
SCEVAddExpr(std::unique_ptr< SCEV > left, std::unique_ptr< SCEV > right)
std::unique_ptr< SCEV > RightOperand_
std::unique_ptr< SCEV > Clone() const override
SCEV * GetLeftOperand() const
std::string DebugString() const override
void SetRightOperand(std::unique_ptr< SCEV > op)
SCEV * GetOperand(const size_t index) const
const rvsdg::ThetaNode * GetLoop() const
SCEV * GetStartValue() const
std::unique_ptr< SCEV > Clone() const override
std::string DebugString() const override
SCEVChainRecurrence(const rvsdg::ThetaNode &theta)
const rvsdg::ThetaNode * Loop_
void AddOperandToFront(const std::unique_ptr< SCEV > &initScev)
std::vector< std::unique_ptr< SCEV > > Operands_
void AddOperand(std::unique_ptr< SCEV > scev)
std::vector< const SCEV * > GetOperands() const
std::unique_ptr< SCEV > Clone() const override
SCEVConstant(const int64_t value)
std::string DebugString() const override
const rvsdg::Output * PrePointer_
std::string DebugString() const override
const rvsdg::Output * GetPrePointer() const
std::unique_ptr< SCEV > Clone() const override
SCEVInit(const rvsdg::Output &pre)
void AddOperand(std::unique_ptr< SCEV > scev)
std::vector< std::unique_ptr< SCEV > > Operands_
SCEVNAryAddExpr(Args &&... operands)
std::string DebugString() const override
std::unique_ptr< SCEV > Clone() const override
void AddOperands(Args &&... operands)
SCEV * GetOperand(const size_t index) const
std::vector< const SCEV * > GetOperands() const
std::string DebugString() const override
std::unique_ptr< SCEV > Clone() const override
const rvsdg::Output * PrePointer_
SCEVPlaceholder(const rvsdg::Output &pre)
const rvsdg::Output * GetPrePointer() const
std::unique_ptr< SCEV > Clone() const override
std::string DebugString() const override
virtual ~SCEV() noexcept=default
virtual std::unique_ptr< SCEV > Clone() const =0
virtual std::string DebugString() const =0
util::HashSet< const rvsdg::Output * > InductionVariableSet
~ScalarEvolution() noexcept override
std::unordered_map< const rvsdg::Output *, std::unordered_map< const rvsdg::Output *, int > > IVDependencyGraph
Global memory state passed between functions.
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)