Jlm
ScalarEvolution.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2025 Andreas Lilleby Hjulstad <andreas.lilleby.hjulstad@gmail.com>
3  * See COPYING for terms of redistribution.
4  */
5 
6 #ifndef JLM_LLVM_OPT_SCALAR_EVOLUTION_HPP
7 #define JLM_LLVM_OPT_SCALAR_EVOLUTION_HPP
8 
9 #include <jlm/rvsdg/theta.hpp>
11 
12 namespace jlm::llvm
13 {
14 class SCEV
15 {
16  friend class ScalarEvolution;
17 
18 public:
19  virtual ~SCEV() noexcept = default;
20 
21  virtual std::string
22  DebugString() const = 0;
23 
24  virtual std::unique_ptr<SCEV>
25  Clone() const = 0;
26 
27  template<typename T>
28  static std::unique_ptr<T>
29  CloneAs(const SCEV & scev)
30  {
31  auto cloned = scev.Clone();
32  auto * ptr = dynamic_cast<T *>(cloned.release());
33  JLM_ASSERT(ptr);
34  return std::unique_ptr<T>(ptr);
35  }
36 };
37 
38 class SCEVUnknown final : public SCEV
39 {
40 public:
41  explicit SCEVUnknown()
42  {}
43 
44  std::string
45  DebugString() const override
46  {
47  return "Unknown";
48  }
49 
50  std::unique_ptr<SCEV>
51  Clone() const override
52  {
53  return std::make_unique<SCEVUnknown>();
54  }
55 
56  static std::unique_ptr<SCEVUnknown>
58  {
59  return std::make_unique<SCEVUnknown>();
60  }
61 };
62 
63 class SCEVInit final : public SCEV
64 {
65 public:
66  explicit SCEVInit(rvsdg::Output & pre)
67  : PrePointer_{ &pre }
68  {}
69 
70  [[nodiscard]] rvsdg::Output &
71  GetPrePointer() const noexcept
72  {
73  return *PrePointer_;
74  }
75 
76  std::string
77  DebugString() const override
78  {
79  std::ostringstream oss;
80  oss << "Init(" << PrePointer_->debug_string() << ")";
81  return oss.str();
82  }
83 
84  std::unique_ptr<SCEV>
85  Clone() const override
86  {
87  return std::make_unique<SCEVInit>(*PrePointer_);
88  }
89 
90  static std::unique_ptr<SCEVInit>
91  Create(rvsdg::Output & prePointer)
92  {
93  return std::make_unique<SCEVInit>(prePointer);
94  }
95 
96 private:
98 };
99 
100 class SCEVPlaceholder final : public SCEV
101 {
102 public:
104  : PrePointer_{ &pre }
105  {}
106 
107  [[nodiscard]] rvsdg::Output &
108  GetPrePointer() const noexcept
109  {
110  return *PrePointer_;
111  }
112 
113  std::string
114  DebugString() const override
115  {
116  std::ostringstream oss;
117  oss << "PH(" << PrePointer_->debug_string() << ")";
118  return oss.str();
119  }
120 
121  std::unique_ptr<SCEV>
122  Clone() const override
123  {
124  return std::make_unique<SCEVPlaceholder>(*PrePointer_);
125  }
126 
127  static std::unique_ptr<SCEVPlaceholder>
129  {
130  return std::make_unique<SCEVPlaceholder>(PrePointer_);
131  }
132 
133 private:
135 };
136 
137 class SCEVConstant final : public SCEV
138 {
139 public:
140  explicit SCEVConstant(const int64_t value)
141  : Value_{ value }
142  {}
143 
144  int64_t
145  GetValue() const
146  {
147  return Value_;
148  }
149 
150  std::string
151  DebugString() const override
152  {
153  return std::to_string(Value_);
154  }
155 
156  std::unique_ptr<SCEV>
157  Clone() const override
158  {
159  return std::make_unique<SCEVConstant>(Value_);
160  }
161 
162  static std::unique_ptr<SCEVConstant>
163  Create(const int64_t value)
164  {
165  return std::make_unique<SCEVConstant>(value);
166  }
167 
168  static bool
170  {
171  return c && c->GetValue() != 0;
172  }
173 
174 private:
175  int64_t Value_;
176 };
177 
178 class SCEVBinaryExpr : public SCEV
179 {
180 public:
182  : LeftOperand_{},
183  RightOperand_{}
184  {}
185 
186  SCEVBinaryExpr(std::unique_ptr<SCEV> left, std::unique_ptr<SCEV> right)
187  : LeftOperand_{ std::move(left) },
188  RightOperand_{ std::move(right) }
189  {}
190 
191  SCEV *
193  {
194  return LeftOperand_.get();
195  }
196 
197  SCEV *
199  {
200  return RightOperand_.get();
201  }
202 
203  void
204  SetLeftOperand(std::unique_ptr<SCEV> op)
205  {
206  LeftOperand_ = std::move(op);
207  }
208 
209  void
210  SetRightOperand(std::unique_ptr<SCEV> op)
211  {
212  RightOperand_ = std::move(op);
213  }
214 
215 protected:
216  std::unique_ptr<SCEV> LeftOperand_;
217  std::unique_ptr<SCEV> RightOperand_;
218 };
219 
220 class SCEVAddExpr final : public SCEVBinaryExpr
221 {
222 public:
223  SCEVAddExpr(std::unique_ptr<SCEV> left, std::unique_ptr<SCEV> right)
224  : SCEVBinaryExpr(std::move(left), std::move(right))
225  {}
226 
227  std::string
228  DebugString() const override
229  {
230  std::ostringstream oss;
231  const std::string leftStr = LeftOperand_ ? LeftOperand_->DebugString() : "null";
232  const std::string rightStr = RightOperand_ ? RightOperand_->DebugString() : "null";
233  oss << "(" << leftStr << " + " << rightStr << ")";
234  return oss.str();
235  }
236 
237  std::unique_ptr<SCEV>
238  Clone() const override
239  {
240  std::unique_ptr<SCEV> leftClone = LeftOperand_ ? LeftOperand_->Clone() : nullptr;
241  std::unique_ptr<SCEV> rightClone = RightOperand_ ? RightOperand_->Clone() : nullptr;
242  return std::make_unique<SCEVAddExpr>(std::move(leftClone), std::move(rightClone));
243  }
244 
245  static std::unique_ptr<SCEVAddExpr>
246  Create(std::unique_ptr<SCEV> left, std::unique_ptr<SCEV> right)
247  {
248  return std::make_unique<SCEVAddExpr>(std::move(left), std::move(right));
249  }
250 };
251 
252 class SCEVMulExpr final : public SCEVBinaryExpr
253 {
254 public:
255  SCEVMulExpr(std::unique_ptr<SCEV> left, std::unique_ptr<SCEV> right)
256  : SCEVBinaryExpr(std::move(left), std::move(right))
257  {}
258 
259  std::string
260  DebugString() const override
261  {
262  std::ostringstream oss;
263  const std::string leftStr = LeftOperand_ ? LeftOperand_->DebugString() : "null";
264  const std::string rightStr = RightOperand_ ? RightOperand_->DebugString() : "null";
265  oss << "(" << leftStr << " * " << rightStr << ")";
266  return oss.str();
267  }
268 
269  std::unique_ptr<SCEV>
270  Clone() const override
271  {
272  std::unique_ptr<SCEV> leftClone = LeftOperand_ ? LeftOperand_->Clone() : nullptr;
273  std::unique_ptr<SCEV> rightClone = RightOperand_ ? RightOperand_->Clone() : nullptr;
274  return std::make_unique<SCEVMulExpr>(std::move(leftClone), std::move(rightClone));
275  }
276 
277  static std::unique_ptr<SCEVMulExpr>
278  Create(std::unique_ptr<SCEV> left, std::unique_ptr<SCEV> right)
279  {
280  return std::make_unique<SCEVMulExpr>(std::move(left), std::move(right));
281  }
282 };
283 
284 class SCEVNAryExpr : public SCEV
285 {
286 public:
287  explicit SCEVNAryExpr()
288  : Operands_{}
289  {}
290 
291  template<typename... Args>
292  explicit SCEVNAryExpr(Args &&... operands)
293  : Operands_{}
294  {
295  (AddOperand(std::forward<Args>(operands)), ...);
296  }
297 
298  template<typename... Args>
299  void
300  AddOperands(Args &&... operands)
301  {
302  (AddOperand(std::forward<Args>(operands)), ...);
303  }
304 
305  void
306  AddOperand(std::unique_ptr<SCEV> scev)
307  {
308  Operands_.push_back(std::move(scev));
309  }
310 
311  void
312  ReplaceOperand(const size_t index, const std::unique_ptr<SCEV> & operand)
313  {
314  Operands_[index] = operand->Clone();
315  }
316 
317  void
318  RemoveOperand(const size_t index)
319  {
320  if (index < Operands_.size())
321  {
322  Operands_.erase(Operands_.begin() + index);
323  }
324  }
325 
326  std::vector<SCEV *>
327  GetOperands() const
328  {
329  std::vector<SCEV *> operands{};
330  for (auto & op : Operands_)
331  {
332  operands.push_back(op.get());
333  }
334  return operands;
335  }
336 
337  SCEV *
338  GetOperand(const size_t index) const
339  {
340  return Operands_.at(index).get();
341  }
342 
343  size_t
344  NumOperands() const
345  {
346  return Operands_.size();
347  }
348 
349 protected:
350  std::vector<std::unique_ptr<SCEV>> Operands_;
351 };
352 
353 class SCEVChainRecurrence final : public SCEVNAryExpr
354 {
355 public:
357  : SCEVNAryExpr(),
358  Loop_{ &theta },
359  Output_{ &output }
360  {}
361 
362  template<typename... Args>
364  rvsdg::ThetaNode & theta,
365  rvsdg::Output & output,
366  Args &&... operands)
367  : SCEVNAryExpr(std::forward<Args>(operands)...),
368  Loop_{ &theta },
369  Output_{ &output }
370  {}
371 
372  [[nodiscard]] rvsdg::ThetaNode &
373  GetLoop() const noexcept
374  {
375  return *Loop_;
376  }
377 
378  [[nodiscard]] rvsdg::Output &
379  GetOutput() const noexcept
380  {
381  return *Output_;
382  }
383 
384  SCEV *
386  {
387  return Operands_[0].get();
388  }
389 
390  bool static IsConstant(const SCEVChainRecurrence & chrec)
391  {
392  return chrec.GetOperands().size() == 1;
393  }
394 
395  bool static IsAffine(const SCEVChainRecurrence & chrec)
396  {
397  return chrec.GetOperands().size() == 2;
398  }
399 
400  bool static IsQuadratic(const SCEVChainRecurrence & chrec)
401  {
402  return chrec.GetOperands().size() == 3;
403  }
404 
405  bool static IsInvariantInLoop(const SCEVChainRecurrence & chrec, const rvsdg::ThetaNode & theta)
406  {
407  return &chrec.GetLoop() != &theta;
408  }
409 
410  std::optional<std::unique_ptr<SCEV>>
411  GetStep() const
412  {
413  if (Operands_.size() < 2)
414  {
415  return std::nullopt;
416  }
417  if (Operands_.size() == 2)
418  {
419  return Operands_[1]->Clone();
420  }
421  auto newRec = SCEVChainRecurrence::Create(*Loop_, *Output_);
422  for (auto & operand : util::IteratorRange(std::next(Operands_.begin()), Operands_.end()))
423  {
424  newRec->AddOperand(operand->Clone());
425  }
426  return newRec;
427  }
428 
429  void
430  AddOperandToFront(const std::unique_ptr<SCEV> & initScev)
431  {
432  Operands_.insert(Operands_.begin(), initScev->Clone());
433  }
434 
435  std::string
436  DebugString() const override
437  {
438  std::ostringstream oss;
439  oss << "{";
440  for (size_t i = 0; i < Operands_.size(); ++i)
441  {
442  oss << Operands_.at(i)->DebugString();
443  if (i < Operands_.size() - 1)
444  oss << ",+,";
445  }
446  oss << "}" << "<" << Loop_->subregion()->getRegionId() << ">";
447  return oss.str();
448  }
449 
450  std::unique_ptr<SCEV>
451  Clone() const override
452  {
453  auto copy = std::make_unique<SCEVChainRecurrence>(*Loop_, *Output_);
454  for (const auto & op : Operands_)
455  {
456  copy->AddOperand(op->Clone());
457  }
458  return copy;
459  }
460 
461  static std::unique_ptr<SCEVChainRecurrence>
463  {
464  return std::make_unique<SCEVChainRecurrence>(loop, output);
465  }
466 
467  template<typename... Args>
468  static std::unique_ptr<SCEVChainRecurrence>
469  Create(rvsdg::ThetaNode & loop, rvsdg::Output & output, Args &&... operands)
470  {
471  return std::make_unique<SCEVChainRecurrence>(loop, output, std::forward<Args>(operands)...);
472  }
473 
474 protected:
477 };
478 
479 class SCEVNAryAddExpr final : public SCEVNAryExpr
480 {
481  friend class ScalarEvolution;
482 
483 public:
484  explicit SCEVNAryAddExpr()
485  : SCEVNAryExpr()
486  {}
487 
488  template<typename... Args>
489  explicit SCEVNAryAddExpr(Args &&... operands)
490  : SCEVNAryExpr(std::forward<Args>(operands)...)
491  {}
492 
493  std::string
494  DebugString() const override
495  {
496  std::ostringstream oss;
497  oss << "(";
498  for (size_t i = 0; i < Operands_.size(); ++i)
499  {
500  oss << Operands_.at(i)->DebugString();
501  if (i < Operands_.size() - 1)
502  oss << " + ";
503  }
504  oss << ")";
505  return oss.str();
506  }
507 
508  std::unique_ptr<SCEV>
509  Clone() const override
510  {
511  auto copy = std::make_unique<SCEVNAryAddExpr>();
512  for (const auto & op : Operands_)
513  {
514  copy->AddOperand(op->Clone());
515  }
516  return copy;
517  }
518 
519  template<typename... Args>
520  static std::unique_ptr<SCEVNAryAddExpr>
521  Create(Args &&... operands)
522  {
523  return std::make_unique<SCEVNAryAddExpr>(std::forward<Args>(operands)...);
524  }
525 };
526 
527 class SCEVNAryMulExpr final : public SCEVNAryExpr
528 {
529  friend class ScalarEvolution;
530 
531 public:
532  explicit SCEVNAryMulExpr()
533  : SCEVNAryExpr()
534  {}
535 
536  template<typename... Args>
537  explicit SCEVNAryMulExpr(Args &&... operands)
538  : SCEVNAryExpr(std::forward<Args>(operands)...)
539  {}
540 
541  std::string
542  DebugString() const override
543  {
544  std::ostringstream oss;
545  oss << "(";
546  for (size_t i = 0; i < Operands_.size(); ++i)
547  {
548  oss << Operands_.at(i)->DebugString();
549  if (i < Operands_.size() - 1)
550  oss << " * ";
551  }
552  oss << ")";
553  return oss.str();
554  }
555 
556  std::unique_ptr<SCEV>
557  Clone() const override
558  {
559  auto copy = std::make_unique<SCEVNAryMulExpr>();
560  for (const auto & op : Operands_)
561  {
562  copy->AddOperand(op->Clone());
563  }
564  return copy;
565  }
566 
567  template<typename... Args>
568  static std::unique_ptr<SCEVNAryMulExpr>
569  Create(Args &&... operands)
570  {
571  return std::make_unique<SCEVNAryMulExpr>(std::forward<Args>(operands)...);
572  }
573 };
574 
576 {
577  class Context;
578  class Statistics;
579 
580 public:
581  enum class DependencyOp
582  {
583  Add,
584  Mul,
585  None,
586  };
587 
589  {
590  // Helper struct to keep track of dependencies between loop variables.
591 
592  int count; // How many times the dependency occurs. A variable can be dependent on other
593  // variables (or itself) multiple times.
594  DependencyOp operation; // The operation of the dependency (Add, Mul or None)
595 
596  explicit DependencyInfo(const int c = 0, const DependencyOp op = DependencyOp::None)
597  : count(c),
598  operation(op)
599  {}
600  };
601 
602  typedef std::unordered_map<rvsdg::Output *, DependencyInfo> DependencyMap;
603 
604  typedef std::unordered_map<rvsdg::Output *, DependencyMap> DependencyGraph;
605 
606  ~ScalarEvolution() noexcept override;
607 
608  ScalarEvolution();
609 
610  ScalarEvolution(const ScalarEvolution &) = delete;
611 
613 
615  operator=(const ScalarEvolution &) = delete;
616 
618  operator=(ScalarEvolution &&) = delete;
619 
624  std::unordered_map<const rvsdg::Output *, std::unique_ptr<SCEVChainRecurrence>>
625  GetChrecMap() const;
626 
631  std::unordered_map<const rvsdg::Output *, std::unique_ptr<SCEV>>
632  GetSCEVMap() const;
633 
634  std::unordered_map<const rvsdg::ThetaNode *, size_t>
635  GetTripCountMap() const noexcept;
636 
637  void
638  Run(rvsdg::RvsdgModule & rvsdgModule, util::StatisticsCollector & statisticsCollector) override;
639 
640  std::optional<size_t>
641  GetPredictedTripCount(rvsdg::ThetaNode & thetaNode);
642 
643  void
644  AnalyzeRegion(rvsdg::Region & region);
645 
650  void
652 
653  static bool
654  StructurallyEqual(const SCEV & a, const SCEV & b);
655 
662  [[nodiscard]] static bool
663  IsUnknown(const SCEV & scev);
664 
665 private:
683  static std::optional<size_t>
685  const SCEVChainRecurrence & chrec,
686  int64_t bound,
687  const rvsdg::SimpleOperation * comparisonOperation);
688 
699  static std::optional<size_t>
700  SolveQuadraticEquation(int64_t a, int64_t b, int64_t c);
701 
702  static bool
703  IsStepNegative(const SCEV & stepSCEV);
704 
705  static bool
706  IsStepPositive(const SCEV & stepSCEV);
707 
708  static bool
709  IsStepZero(const SCEV & stepSCEV);
710 
711  static std::unique_ptr<SCEV>
712  GetNegativeSCEV(const SCEV & scev);
713 
714  std::unique_ptr<SCEV>
715  GetOrCreateSCEVForOutput(rvsdg::Output & output);
716 
718  CreateDependencyGraph(const rvsdg::ThetaNode & thetaNode) const;
719 
720  static void
721  FindDependenciesForSCEV(const SCEV & scev, DependencyMap & dependencies, DependencyOp op);
722 
723  static std::vector<rvsdg::Output *>
724  TopologicalSort(DependencyGraph & dependencyGraph);
725 
726  void
727  PerformSCEVAnalysis(rvsdg::ThetaNode & thetaNode);
728 
729  std::unique_ptr<SCEV>
731  const rvsdg::SimpleNode & gepNode,
732  size_t inputIndex,
733  const rvsdg::Type & type);
734 
743  std::optional<std::unique_ptr<SCEV>>
744  TryReplaceInitForSCEV(const SCEV & scev, rvsdg::Output & output);
745 
746  std::unique_ptr<SCEVChainRecurrence>
748  rvsdg::Output & output,
749  const SCEV & scev,
750  rvsdg::ThetaNode & thetaNode);
751 
752  std::unique_ptr<SCEVChainRecurrence>
754  rvsdg::Output & output,
755  const SCEV & scevTree,
756  rvsdg::ThetaNode & thetaNode);
757 
765  static std::unique_ptr<SCEV>
766  ApplyAddFolding(SCEV * lhsOperand, SCEV * rhsOperand, rvsdg::Output & output);
767 
768  static std::unique_ptr<SCEVChainRecurrence>
770  SCEVChainRecurrence * lhsChrec,
771  SCEVChainRecurrence * rhsChrec,
772  rvsdg::Output & output);
773 
781  static std::unique_ptr<SCEV>
782  ApplyMulFolding(SCEV * lhsOperand, SCEV * rhsOperand, rvsdg::Output & output);
783 
790  static std::unique_ptr<SCEV>
791  FoldNAryExpression(SCEVNAryExpr & expression, rvsdg::Output & output);
792 
808  static bool
809  CanCreateChainRecurrence(rvsdg::Output & output, DependencyGraph & dependencyGraph);
810 
811  static bool
813  rvsdg::Output & currentOutput,
814  const rvsdg::Output & originalOutput,
815  DependencyGraph & dependencyGraph,
816  std::unordered_set<const rvsdg::Output *> & visited,
817  std::unordered_set<const rvsdg::Output *> & recursionStack);
818 
819  std::unique_ptr<Context> Context_;
820 };
821 
822 }
823 
824 #endif
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
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_
void SetRightOperand(std::unique_ptr< SCEV > op)
SCEVChainRecurrence(rvsdg::ThetaNode &theta, rvsdg::Output &output, Args &&... operands)
rvsdg::ThetaNode & GetLoop() const noexcept
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
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
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 &currentOutput, 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)
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 &region)
static std::optional< size_t > ComputeBackedgeTakenCountForChrec(const SCEVChainRecurrence &chrec, int64_t bound, const rvsdg::SimpleOperation *comparisonOperation)
virtual std::string debug_string() const
Definition: node.cpp:168
Id getRegionId() const noexcept
Definition: region.hpp:263
rvsdg::Region * subregion() const noexcept
Definition: theta.hpp:79
Represents an RVSDG transformation.
#define JLM_ASSERT(x)
Definition: common.hpp:16
Global memory state passed between functions.
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)
Definition: node.hpp:1049
DependencyInfo(const int c=0, const DependencyOp op=DependencyOp::None)