Jlm
unroll.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Nico Reißmann <nico.reissmann@gmail.com>
3  * See COPYING for terms of redistribution.
4  */
5 
6 #ifndef JLM_LLVM_OPT_UNROLL_HPP
7 #define JLM_LLVM_OPT_UNROLL_HPP
8 
9 #include <jlm/llvm/ir/Trace.hpp>
10 #include <jlm/rvsdg/bitstring.hpp>
11 #include <jlm/rvsdg/theta.hpp>
13 #include <jlm/util/common.hpp>
14 
15 namespace jlm::llvm
16 {
17 
18 class LlvmRvsdgModule;
19 
24 {
25 public:
26  class Statistics;
27 
28  ~LoopUnrolling() noexcept override;
29 
30  explicit LoopUnrolling(const size_t factor)
32  factor_(factor)
33  {}
34 
43  void
44  Run(rvsdg::RvsdgModule & module, util::StatisticsCollector & statisticsCollector) override;
45 
46 private:
47  size_t factor_;
48 };
49 
50 class LoopUnrollInfo final
51 {
52 public:
53  ~LoopUnrollInfo() noexcept = default;
54 
55 private:
57  rvsdg::SimpleNode * cmpnode,
58  rvsdg::SimpleNode * armnode,
59  rvsdg::Output * idv,
60  rvsdg::Output * step,
61  rvsdg::Output * end)
62  : end_(end),
63  step_(step),
66  idv_(idv)
67  {}
68 
69 public:
70  LoopUnrollInfo(const LoopUnrollInfo &) = delete;
71 
73 
75  operator=(const LoopUnrollInfo &) = delete;
76 
78  operator=(LoopUnrollInfo &&) = delete;
79 
80  inline rvsdg::ThetaNode *
81  theta() const noexcept
82  {
83  auto node = idv()->region()->node();
84  return util::assertedCast<rvsdg::ThetaNode>(node);
85  }
86 
87  inline bool
88  has_known_init() const noexcept
89  {
90  return is_known(init());
91  }
92 
93  inline bool
94  has_known_step() const noexcept
95  {
96  return is_known(step());
97  }
98 
99  inline bool
100  has_known_end() const noexcept
101  {
102  return is_known(end());
103  }
104 
105  inline bool
106  is_known() const noexcept
107  {
108  return has_known_init() && has_known_step() && has_known_end();
109  }
110 
111  std::unique_ptr<jlm::rvsdg::BitValueRepresentation>
112  niterations() const noexcept;
113 
114  rvsdg::SimpleNode *
115  cmpnode() const noexcept
116  {
117  return cmpnode_;
118  }
119 
120  [[nodiscard]] const rvsdg::SimpleOperation &
121  cmpoperation() const noexcept
122  {
123  return cmpnode()->GetOperation();
124  }
125 
126  inline rvsdg::SimpleNode *
127  armnode() const noexcept
128  {
129  return armnode_;
130  }
131 
132  [[nodiscard]] const rvsdg::SimpleOperation &
133  armoperation() const noexcept
134  {
135  return armnode()->GetOperation();
136  }
137 
138  inline rvsdg::Output *
139  idv() const noexcept
140  {
141  return idv_;
142  }
143 
144  inline jlm::rvsdg::Output *
145  init() const noexcept
146  {
147  return theta()->MapPreLoopVar(*idv()).input->origin();
148  }
149 
151  init_value() const noexcept
152  {
153  return value(init());
154  }
155 
156  inline rvsdg::Output *
157  step() const noexcept
158  {
159  return step_;
160  }
161 
163  step_value() const noexcept
164  {
165  return value(step());
166  }
167 
168  inline rvsdg::Output *
169  end() const noexcept
170  {
171  return end_;
172  }
173 
175  end_value() const noexcept
176  {
177  return value(end());
178  }
179 
180  inline bool
181  is_additive() const noexcept
182  {
183  return jlm::rvsdg::is<jlm::rvsdg::bitadd_op>(armnode());
184  }
185 
186  inline bool
187  is_subtractive() const noexcept
188  {
189  return jlm::rvsdg::is<jlm::rvsdg::bitsub_op>(armnode());
190  }
191 
192  inline size_t
193  nbits() const noexcept
194  {
195  JLM_ASSERT(dynamic_cast<const jlm::rvsdg::BitCompareOperation *>(&cmpnode()->GetOperation()));
196  return static_cast<const rvsdg::BitCompareOperation *>(&cmpnode()->GetOperation())
197  ->type()
198  .nbits();
199  }
200 
202  remainder(size_t factor) const noexcept
203  {
204  return niterations()->umod({ nbits(), (int64_t)factor });
205  }
206 
207  static std::unique_ptr<LoopUnrollInfo>
209 
210 private:
211  bool
212  is_known(const rvsdg::Output * output) const noexcept
213  {
214  auto & tracedOutput = llvm::traceOutput(*output);
215  auto [_, constantOperation] =
216  rvsdg::TryGetSimpleNodeAndOptionalOp<rvsdg::BitConstantOperation>(tracedOutput);
217  return constantOperation && constantOperation->value().is_known();
218  }
219 
221  value(const rvsdg::Output * output) const noexcept
222  {
223  if (!is_known(output))
224  return nullptr;
225 
226  auto & tracedOutput = llvm::traceOutput(*output);
227  auto [_, constantOperation] =
228  rvsdg::TryGetSimpleNodeAndOptionalOp<rvsdg::BitConstantOperation>(tracedOutput);
229  return constantOperation == nullptr ? nullptr : &constantOperation->value();
230  }
231 
237 };
238 
246 void
247 unroll(rvsdg::ThetaNode * node, size_t factor);
248 
249 }
250 
251 #endif
rvsdg::Output * idv() const noexcept
Definition: unroll.hpp:139
std::unique_ptr< jlm::rvsdg::BitValueRepresentation > niterations() const noexcept
Definition: unroll.cpp:112
bool is_subtractive() const noexcept
Definition: unroll.hpp:187
rvsdg::Output * end() const noexcept
Definition: unroll.hpp:169
const rvsdg::SimpleOperation & cmpoperation() const noexcept
Definition: unroll.hpp:121
LoopUnrollInfo(LoopUnrollInfo &&)=delete
const rvsdg::BitValueRepresentation * value(const rvsdg::Output *output) const noexcept
Definition: unroll.hpp:221
~LoopUnrollInfo() noexcept=default
rvsdg::Output * end_
Definition: unroll.hpp:232
rvsdg::SimpleNode * armnode() const noexcept
Definition: unroll.hpp:127
rvsdg::Output * idv_
Definition: unroll.hpp:236
bool has_known_init() const noexcept
Definition: unroll.hpp:88
bool is_additive() const noexcept
Definition: unroll.hpp:181
bool has_known_end() const noexcept
Definition: unroll.hpp:100
jlm::rvsdg::Output * init() const noexcept
Definition: unroll.hpp:145
static std::unique_ptr< LoopUnrollInfo > create(rvsdg::ThetaNode *theta)
Definition: unroll.cpp:135
rvsdg::Output * step() const noexcept
Definition: unroll.hpp:157
const jlm::rvsdg::BitValueRepresentation * end_value() const noexcept
Definition: unroll.hpp:175
bool is_known() const noexcept
Definition: unroll.hpp:106
bool is_known(const rvsdg::Output *output) const noexcept
Definition: unroll.hpp:212
LoopUnrollInfo & operator=(LoopUnrollInfo &&)=delete
const rvsdg::SimpleOperation & armoperation() const noexcept
Definition: unroll.hpp:133
bool has_known_step() const noexcept
Definition: unroll.hpp:94
rvsdg::ThetaNode * theta() const noexcept
Definition: unroll.hpp:81
size_t nbits() const noexcept
Definition: unroll.hpp:193
rvsdg::SimpleNode * cmpnode_
Definition: unroll.hpp:234
rvsdg::SimpleNode * cmpnode() const noexcept
Definition: unroll.hpp:115
jlm::rvsdg::BitValueRepresentation remainder(size_t factor) const noexcept
Definition: unroll.hpp:202
rvsdg::SimpleNode * armnode_
Definition: unroll.hpp:235
rvsdg::Output * step_
Definition: unroll.hpp:233
LoopUnrollInfo & operator=(const LoopUnrollInfo &)=delete
const jlm::rvsdg::BitValueRepresentation * step_value() const noexcept
Definition: unroll.hpp:163
const jlm::rvsdg::BitValueRepresentation * init_value() const noexcept
Definition: unroll.hpp:151
LoopUnrollInfo(const LoopUnrollInfo &)=delete
Optimization that attempts to unroll loops (thetas).
Definition: unroll.hpp:24
~LoopUnrolling() noexcept override
void Run(rvsdg::RvsdgModule &module, util::StatisticsCollector &statisticsCollector) override
Definition: unroll.cpp:525
Output * origin() const noexcept
Definition: node.hpp:58
rvsdg::Region * region() const noexcept
Definition: node.cpp:151
rvsdg::StructuralNode * node() const noexcept
Definition: region.hpp:369
const SimpleOperation & GetOperation() const noexcept override
Definition: simple-node.cpp:48
LoopVar MapPreLoopVar(const rvsdg::Output &argument) const
Maps variable at start of loop iteration to full varibale description.
Definition: theta.cpp:140
Represents an RVSDG transformation.
Transformation(std::string_view Name)
#define JLM_ASSERT(x)
Definition: common.hpp:16
Global memory state passed between functions.
rvsdg::Output & traceOutput(rvsdg::Output &output)
Definition: Trace.cpp:39
void unroll(rvsdg::ThetaNode *otheta, size_t factor)
Definition: unroll.cpp:482
static std::string type(const Node *n)
Definition: view.cpp:255
rvsdg::Input * input
Variable at loop entry (input to theta).
Definition: theta.hpp:54