Jlm
Loading...
Searching...
No Matches
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
12namespace jlm::llvm
13{
14class SCEV
15{
16 friend class ScalarEvolution;
17
18public:
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
38class SCEVUnknown final : public SCEV
39{
40public:
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
63class SCEVInit final : public SCEV
64{
65public:
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
96private:
98};
99
100class SCEVPlaceholder final : public SCEV
101{
102public:
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
133private:
135};
136
137class SCEVConstant final : public SCEV
138{
139public:
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
174private:
175 int64_t Value_;
176};
177
178class SCEVBinaryExpr : public SCEV
179{
180public:
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
215protected:
216 std::unique_ptr<SCEV> LeftOperand_;
217 std::unique_ptr<SCEV> RightOperand_;
218};
219
220class SCEVAddExpr final : public SCEVBinaryExpr
221{
222public:
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
252class SCEVMulExpr final : public SCEVBinaryExpr
253{
254public:
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
284class SCEVNAryExpr : public SCEV
285{
286public:
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 *>
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
345 {
346 return Operands_.size();
347 }
348
349protected:
350 std::vector<std::unique_ptr<SCEV>> Operands_;
351};
352
354{
355public:
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
474protected:
477};
478
479class SCEVNAryAddExpr final : public SCEVNAryExpr
480{
481 friend class ScalarEvolution;
482
483public:
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
527class SCEVNAryMulExpr final : public SCEVNAryExpr
528{
529 friend class ScalarEvolution;
530
531public:
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
580public:
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
609
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
665private:
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
SCEVAddExpr(std::unique_ptr< SCEV > left, std::unique_ptr< SCEV > right)
static std::unique_ptr< SCEVAddExpr > Create(std::unique_ptr< SCEV > left, std::unique_ptr< SCEV > right)
std::string DebugString() const override
std::unique_ptr< SCEV > Clone() 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 std::unique_ptr< SCEVChainRecurrence > Create(rvsdg::ThetaNode &loop, rvsdg::Output &output, Args &&... operands)
rvsdg::Output & GetOutput() const noexcept
static std::unique_ptr< SCEVChainRecurrence > Create(rvsdg::ThetaNode &loop, rvsdg::Output &output)
static bool IsQuadratic(const SCEVChainRecurrence &chrec)
static bool IsConstant(const SCEVChainRecurrence &chrec)
std::optional< std::unique_ptr< SCEV > > GetStep() const
std::string DebugString() const override
SCEVChainRecurrence(rvsdg::ThetaNode &theta, rvsdg::Output &output)
std::unique_ptr< SCEV > Clone() const override
void AddOperandToFront(const std::unique_ptr< SCEV > &initScev)
static bool IsInvariantInLoop(const SCEVChainRecurrence &chrec, const rvsdg::ThetaNode &theta)
static bool IsAffine(const SCEVChainRecurrence &chrec)
SCEVConstant(const int64_t value)
std::unique_ptr< SCEV > Clone() const override
static std::unique_ptr< SCEVConstant > Create(const int64_t value)
static bool IsNonZero(const SCEVConstant *c)
std::string DebugString() const override
rvsdg::Output * PrePointer_
std::string DebugString() const override
SCEVInit(rvsdg::Output &pre)
static std::unique_ptr< SCEVInit > Create(rvsdg::Output &prePointer)
std::unique_ptr< SCEV > Clone() const override
rvsdg::Output & GetPrePointer() const noexcept
static std::unique_ptr< SCEVMulExpr > Create(std::unique_ptr< SCEV > left, std::unique_ptr< SCEV > right)
std::string DebugString() const override
SCEVMulExpr(std::unique_ptr< SCEV > left, std::unique_ptr< SCEV > right)
std::unique_ptr< SCEV > Clone() const override
SCEVNAryAddExpr(Args &&... operands)
std::string DebugString() const override
std::unique_ptr< SCEV > Clone() const override
static std::unique_ptr< SCEVNAryAddExpr > Create(Args &&... operands)
std::vector< std::unique_ptr< SCEV > > Operands_
SCEVNAryExpr(Args &&... operands)
void RemoveOperand(const size_t index)
void AddOperands(Args &&... operands)
SCEV * GetOperand(const size_t index) const
void AddOperand(std::unique_ptr< SCEV > scev)
void ReplaceOperand(const size_t index, const std::unique_ptr< SCEV > &operand)
std::vector< SCEV * > GetOperands() const
SCEVNAryMulExpr(Args &&... operands)
std::string DebugString() const override
std::unique_ptr< SCEV > Clone() const override
static std::unique_ptr< SCEVNAryMulExpr > Create(Args &&... operands)
std::unique_ptr< SCEV > Clone() const override
std::string DebugString() const override
rvsdg::Output & GetPrePointer() const noexcept
SCEVPlaceholder(rvsdg::Output &pre)
static std::unique_ptr< SCEVPlaceholder > Create(rvsdg::Output &PrePointer_)
std::unique_ptr< SCEV > Clone() const override
std::string DebugString() const override
static std::unique_ptr< SCEVUnknown > Create()
virtual ~SCEV() noexcept=default
virtual std::unique_ptr< SCEV > Clone() const =0
static std::unique_ptr< T > CloneAs(const SCEV &scev)
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:278
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.
DependencyInfo(const int c=0, const DependencyOp op=DependencyOp::None)