Jlm
operators.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2014 2015 Nico Reißmann <nico.reissmann@gmail.com>
3  * See COPYING for terms of redistribution.
4  */
5 
6 #ifndef JLM_LLVM_IR_OPERATORS_OPERATORS_HPP
7 #define JLM_LLVM_IR_OPERATORS_OPERATORS_HPP
8 
10 #include <jlm/llvm/ir/tac.hpp>
11 #include <jlm/llvm/ir/types.hpp>
12 #include <jlm/rvsdg/binary.hpp>
14 #include <jlm/rvsdg/control.hpp>
16 #include <jlm/rvsdg/type.hpp>
17 #include <jlm/rvsdg/unary.hpp>
18 
19 #include <llvm/ADT/APFloat.h>
20 
21 namespace jlm::llvm
22 {
23 
32 {
33 public:
34  ~SsaPhiOperation() noexcept override;
35 
37  std::vector<ControlFlowGraphNode *> incomingNodes,
38  const std::shared_ptr<const jlm::rvsdg::Type> & type)
39  : SimpleOperation({ incomingNodes.size(), type }, { type }),
40  IncomingNodes_(std::move(incomingNodes))
41  {}
42 
43  SsaPhiOperation(const SsaPhiOperation &) = default;
44 
46  operator=(const SsaPhiOperation &) = delete;
47 
49  operator=(SsaPhiOperation &&) = delete;
50 
51  bool
52  operator==(const Operation & other) const noexcept override;
53 
54  std::string
55  debug_string() const override;
56 
57  [[nodiscard]] std::unique_ptr<Operation>
58  copy() const override;
59 
60  const std::shared_ptr<const rvsdg::Type> &
61  Type() const noexcept
62  {
63  return result(0);
64  }
65 
67  GetIncomingNode(size_t n) const noexcept
68  {
69  JLM_ASSERT(n < narguments());
70  return IncomingNodes_[n];
71  }
72 
73  static std::unique_ptr<llvm::ThreeAddressCode>
75  const std::vector<std::pair<const Variable *, ControlFlowGraphNode *>> & arguments,
76  std::shared_ptr<const jlm::rvsdg::Type> type)
77  {
78  std::vector<ControlFlowGraphNode *> basicBlocks;
79  std::vector<const Variable *> operands;
80  for (const auto & argument : arguments)
81  {
82  basicBlocks.push_back(argument.second);
83  operands.push_back(argument.first);
84  }
85 
86  auto phi = std::make_unique<SsaPhiOperation>(std::move(basicBlocks), std::move(type));
87  return ThreeAddressCode::create(std::move(phi), operands);
88  }
89 
90 private:
91  std::vector<ControlFlowGraphNode *> IncomingNodes_;
92 };
93 
95 {
96 public:
97  ~AssignmentOperation() noexcept override;
98 
99  explicit AssignmentOperation(const std::shared_ptr<const rvsdg::Type> & type)
100  : SimpleOperation({ type, type }, {})
101  {}
102 
104 
106 
107  bool
108  operator==(const Operation & other) const noexcept override;
109 
110  [[nodiscard]] std::string
111  debug_string() const override;
112 
113  [[nodiscard]] std::unique_ptr<Operation>
114  copy() const override;
115 
116  static std::unique_ptr<llvm::ThreeAddressCode>
117  create(const Variable * rhs, const Variable * lhs)
118  {
119  if (rhs->type() != lhs->type())
120  throw util::Error("LHS and RHS of assignment must have same type.");
121 
122  auto operation = std::make_unique<AssignmentOperation>(rhs->Type());
123  return ThreeAddressCode::create(std::move(operation), { lhs, rhs });
124  }
125 };
126 
128 {
129 public:
130  ~SelectOperation() noexcept override;
131 
132  explicit SelectOperation(const std::shared_ptr<const rvsdg::Type> & type)
134  {}
135 
136  bool
137  operator==(const Operation & other) const noexcept override;
138 
139  std::string
140  debug_string() const override;
141 
142  [[nodiscard]] std::unique_ptr<Operation>
143  copy() const override;
144 
145  [[nodiscard]] const jlm::rvsdg::Type &
146  type() const noexcept
147  {
148  return *result(0);
149  }
150 
151  [[nodiscard]] const std::shared_ptr<const jlm::rvsdg::Type> &
152  Type() const noexcept
153  {
154  return result(0);
155  }
156 
157  static std::unique_ptr<llvm::ThreeAddressCode>
158  create(const llvm::Variable * p, const llvm::Variable * t, const llvm::Variable * f)
159  {
160  auto op = std::make_unique<SelectOperation>(t->Type());
161  return ThreeAddressCode::create(std::move(op), { p, t, f });
162  }
163 };
164 
166 {
167 public:
168  ~VectorSelectOperation() noexcept override;
169 
170 private:
172  const std::shared_ptr<const VectorType> & pt,
173  const std::shared_ptr<const VectorType> & vt)
174  : SimpleOperation({ pt, vt, vt }, { vt })
175  {}
176 
177 public:
178  bool
179  operator==(const Operation & other) const noexcept override;
180 
181  [[nodiscard]] std::string
182  debug_string() const override;
183 
184  [[nodiscard]] std::unique_ptr<Operation>
185  copy() const override;
186 
187  [[nodiscard]] const rvsdg::Type &
188  type() const noexcept
189  {
190  return *result(0);
191  }
192 
193  [[nodiscard]] const std::shared_ptr<const rvsdg::Type> &
194  Type() const noexcept
195  {
196  return result(0);
197  }
198 
199  size_t
200  size() const noexcept
201  {
202  return dynamic_cast<const VectorType *>(&type())->size();
203  }
204 
205  static std::unique_ptr<llvm::ThreeAddressCode>
206  create(const Variable * p, const Variable * t, const Variable * f)
207  {
208  if (is<FixedVectorType>(p->type()) && is<FixedVectorType>(t->type()))
209  return createVectorSelectTac<FixedVectorType>(p, t, f);
210 
211  if (is<ScalableVectorType>(p->type()) && is<ScalableVectorType>(t->type()))
212  return createVectorSelectTac<ScalableVectorType>(p, t, f);
213 
214  throw util::Error("Expected vector types as operands.");
215  }
216 
217 private:
218  template<typename T>
219  static std::unique_ptr<ThreeAddressCode>
220  createVectorSelectTac(const Variable * p, const Variable * t, const Variable * f)
221  {
222  auto fvt = static_cast<const T *>(&t->type());
223  auto pt = T::Create(jlm::rvsdg::BitType::Create(1), fvt->size());
224  auto vt = T::Create(fvt->Type(), fvt->size());
225  auto op = std::unique_ptr<VectorSelectOperation>(new VectorSelectOperation(pt, vt));
226  return ThreeAddressCode::create(std::move(op), { p, t, f });
227  }
228 };
229 
231 {
232 public:
234 
236  const fpsize size,
237  std::shared_ptr<const rvsdg::BitType> type)
238  : UnaryOperation(FloatingPointType::Create(size), std::move(type))
239  {}
240 
242  std::shared_ptr<const FloatingPointType> fpt,
243  std::shared_ptr<const jlm::rvsdg::BitType> type)
244  : UnaryOperation(std::move(fpt), std::move(type))
245  {}
246 
248  std::shared_ptr<const jlm::rvsdg::Type> srctype,
249  std::shared_ptr<const jlm::rvsdg::Type> dsttype)
250  : UnaryOperation(srctype, dsttype)
251  {
252  auto st = dynamic_cast<const FloatingPointType *>(srctype.get());
253  if (!st)
254  throw util::Error("expected floating point type.");
255 
256  auto dt = dynamic_cast<const jlm::rvsdg::BitType *>(dsttype.get());
257  if (!dt)
258  throw util::Error("expected bitstring type.");
259  }
260 
261  bool
262  operator==(const Operation & other) const noexcept override;
263 
264  [[nodiscard]] std::string
265  debug_string() const override;
266 
267  [[nodiscard]] std::unique_ptr<Operation>
268  copy() const override;
269 
271  can_reduce_operand(const jlm::rvsdg::Output * output) const noexcept override;
272 
275  const override;
276 
277  static std::unique_ptr<llvm::ThreeAddressCode>
278  create(const Variable * operand, const std::shared_ptr<const jlm::rvsdg::Type> & type)
279  {
280  auto st = std::dynamic_pointer_cast<const FloatingPointType>(operand->Type());
281  if (!st)
282  throw util::Error("expected floating point type.");
283 
284  auto dt = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(type);
285  if (!dt)
286  throw util::Error("expected bitstring type.");
287 
288  auto op =
289  std::make_unique<FloatingPointToUnsignedIntegerOperation>(std::move(st), std::move(dt));
290  return ThreeAddressCode::create(std::move(op), { operand });
291  }
292 };
293 
295 {
296 public:
298 
300  const fpsize size,
301  std::shared_ptr<const jlm::rvsdg::BitType> type)
302  : UnaryOperation(FloatingPointType::Create(size), std::move(type))
303  {}
304 
306  std::shared_ptr<const FloatingPointType> fpt,
307  std::shared_ptr<const jlm::rvsdg::BitType> type)
308  : UnaryOperation(std::move(fpt), std::move(type))
309  {}
310 
312  std::shared_ptr<const jlm::rvsdg::Type> srctype,
313  std::shared_ptr<const jlm::rvsdg::Type> dsttype)
314  : UnaryOperation(srctype, dsttype)
315  {
316  auto st = dynamic_cast<const FloatingPointType *>(srctype.get());
317  if (!st)
318  throw util::Error("expected floating point type.");
319 
320  auto dt = dynamic_cast<const jlm::rvsdg::BitType *>(dsttype.get());
321  if (!dt)
322  throw util::Error("expected bitstring type.");
323  }
324 
325  bool
326  operator==(const Operation & other) const noexcept override;
327 
328  [[nodiscard]] std::string
329  debug_string() const override;
330 
331  [[nodiscard]] std::unique_ptr<Operation>
332  copy() const override;
333 
335  can_reduce_operand(const jlm::rvsdg::Output * output) const noexcept override;
336 
339  const override;
340 
341  static std::unique_ptr<llvm::ThreeAddressCode>
342  create(const Variable * operand, const std::shared_ptr<const jlm::rvsdg::Type> & type)
343  {
344  auto st = std::dynamic_pointer_cast<const FloatingPointType>(operand->Type());
345  if (!st)
346  throw util::Error("expected floating point type.");
347 
348  auto dt = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(type);
349  if (!dt)
350  throw util::Error("expected bitstring type.");
351 
352  auto op = std::make_unique<FloatingPointToSignedIntegerOperation>(std::move(st), std::move(dt));
353  return ThreeAddressCode::create(std::move(op), { operand });
354  }
355 };
356 
358 {
359 public:
360  ~ControlToIntOperation() noexcept override;
361 
363  std::shared_ptr<const rvsdg::ControlType> srctype,
364  std::shared_ptr<const jlm::rvsdg::BitType> dsttype)
365  : SimpleOperation({ std::move(srctype) }, { std::move(dsttype) })
366  {}
367 
368  bool
369  operator==(const Operation & other) const noexcept override;
370 
371  [[nodiscard]] std::string
372  debug_string() const override;
373 
374  [[nodiscard]] std::unique_ptr<Operation>
375  copy() const override;
376 
377  static std::unique_ptr<llvm::ThreeAddressCode>
378  create(const Variable * operand, const std::shared_ptr<const jlm::rvsdg::Type> & type)
379  {
380  auto st = std::dynamic_pointer_cast<const rvsdg::ControlType>(operand->Type());
381  if (!st)
382  throw util::Error("expected control type.");
383 
384  auto dt = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(type);
385  if (!dt)
386  throw util::Error("expected bitstring type.");
387 
388  auto op = std::make_unique<ControlToIntOperation>(std::move(st), std::move(dt));
389  return ThreeAddressCode::create(std::move(op), { operand });
390  }
391 };
392 
394 {
395 public:
396  ~BranchOperation() noexcept override;
397 
398  explicit BranchOperation(std::shared_ptr<const rvsdg::ControlType> type)
399  : SimpleOperation({ std::move(type) }, {})
400  {}
401 
402  bool
403  operator==(const Operation & other) const noexcept override;
404 
405  [[nodiscard]] std::string
406  debug_string() const override;
407 
408  [[nodiscard]] std::unique_ptr<Operation>
409  copy() const override;
410 
411  inline size_t
412  nalternatives() const noexcept
413  {
414  return std::static_pointer_cast<const rvsdg::ControlType>(argument(0))->nalternatives();
415  }
416 
417  static std::unique_ptr<llvm::ThreeAddressCode>
418  create(size_t nalternatives, const Variable * operand)
419  {
420  auto op = std::make_unique<BranchOperation>(rvsdg::ControlType::Create(nalternatives));
421  return ThreeAddressCode::create(std::move(op), { operand });
422  }
423 };
424 
430 {
431 public:
432  ~ConstantPointerNullOperation() noexcept override;
433 
434  explicit ConstantPointerNullOperation(std::shared_ptr<const PointerType> pointerType)
435  : SimpleOperation({}, { std::move(pointerType) })
436  {}
437 
438  bool
439  operator==(const Operation & other) const noexcept override;
440 
441  [[nodiscard]] std::string
442  debug_string() const override;
443 
444  [[nodiscard]] std::unique_ptr<Operation>
445  copy() const override;
446 
447  [[nodiscard]] const PointerType &
448  GetPointerType() const noexcept
449  {
450  return *util::assertedCast<const PointerType>(result(0).get());
451  }
452 
453  static std::unique_ptr<llvm::ThreeAddressCode>
454  Create(std::shared_ptr<const rvsdg::Type> type)
455  {
456  auto operation = std::make_unique<ConstantPointerNullOperation>(CheckAndExtractType(type));
457  return ThreeAddressCode::create(std::move(operation), {});
458  }
459 
460  static jlm::rvsdg::Output *
461  Create(rvsdg::Region * region, std::shared_ptr<const rvsdg::Type> type)
462  {
463  return rvsdg::CreateOpNode<ConstantPointerNullOperation>(*region, CheckAndExtractType(type))
464  .output(0);
465  }
466 
467 private:
468  static const std::shared_ptr<const PointerType>
469  CheckAndExtractType(std::shared_ptr<const jlm::rvsdg::Type> type)
470  {
471  if (auto pointerType = std::dynamic_pointer_cast<const PointerType>(type))
472  return pointerType;
473 
474  throw util::Error("expected pointer type.");
475  }
476 };
477 
479 {
480 public:
481  ~IntegerToPointerOperation() noexcept override;
482 
484  std::shared_ptr<const jlm::rvsdg::BitType> btype,
485  std::shared_ptr<const PointerType> ptype)
486  : UnaryOperation(std::move(btype), std::move(ptype))
487  {}
488 
490  std::shared_ptr<const jlm::rvsdg::Type> srctype,
491  std::shared_ptr<const jlm::rvsdg::Type> dsttype)
492  : UnaryOperation(srctype, dsttype)
493  {
494  auto at = dynamic_cast<const jlm::rvsdg::BitType *>(srctype.get());
495  if (!at)
496  throw util::Error("expected bitstring type.");
497 
498  auto pt = dynamic_cast<const PointerType *>(dsttype.get());
499  if (!pt)
500  throw util::Error("expected pointer type.");
501  }
502 
503  bool
504  operator==(const Operation & other) const noexcept override;
505 
506  [[nodiscard]] std::string
507  debug_string() const override;
508 
509  [[nodiscard]] std::unique_ptr<Operation>
510  copy() const override;
511 
513  can_reduce_operand(const jlm::rvsdg::Output * output) const noexcept override;
514 
517  const override;
518 
519  inline size_t
520  nbits() const noexcept
521  {
522  return std::static_pointer_cast<const jlm::rvsdg::BitType>(argument(0))->nbits();
523  }
524 
525  static std::unique_ptr<llvm::ThreeAddressCode>
526  create(const Variable * argument, std::shared_ptr<const jlm::rvsdg::Type> type)
527  {
528  auto at = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(argument->Type());
529  if (!at)
530  throw util::Error("expected bitstring type.");
531 
532  auto pt = std::dynamic_pointer_cast<const PointerType>(type);
533  if (!pt)
534  throw util::Error("expected pointer type.");
535 
536  auto op = std::make_unique<IntegerToPointerOperation>(at, pt);
537  return ThreeAddressCode::create(std::move(op), { argument });
538  }
539 
540  static jlm::rvsdg::Output *
541  create(jlm::rvsdg::Output * operand, std::shared_ptr<const jlm::rvsdg::Type> type)
542  {
543  auto ot = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(operand->Type());
544  if (!ot)
545  throw util::Error("expected bitstring type.");
546 
547  auto pt = std::dynamic_pointer_cast<const PointerType>(type);
548  if (!pt)
549  throw util::Error("expected pointer type.");
550 
551  return rvsdg::CreateOpNode<IntegerToPointerOperation>({ operand }, ot, pt).output(0);
552  }
553 };
554 
556 {
557 public:
558  ~PtrToIntOperation() noexcept override;
559 
561  std::shared_ptr<const PointerType> ptype,
562  std::shared_ptr<const jlm::rvsdg::BitType> btype)
563  : UnaryOperation(std::move(ptype), std::move(btype))
564  {}
565 
567  std::shared_ptr<const jlm::rvsdg::Type> srctype,
568  std::shared_ptr<const jlm::rvsdg::Type> dsttype)
569  : UnaryOperation(srctype, dsttype)
570  {
571  auto pt = dynamic_cast<const PointerType *>(srctype.get());
572  if (!pt)
573  throw util::Error("expected pointer type.");
574 
575  auto bt = dynamic_cast<const jlm::rvsdg::BitType *>(dsttype.get());
576  if (!bt)
577  throw util::Error("expected bitstring type.");
578  }
579 
580  bool
581  operator==(const Operation & other) const noexcept override;
582 
583  [[nodiscard]] std::string
584  debug_string() const override;
585 
586  [[nodiscard]] std::unique_ptr<Operation>
587  copy() const override;
588 
590  can_reduce_operand(const jlm::rvsdg::Output * output) const noexcept override;
591 
594  const override;
595 
596  inline size_t
597  nbits() const noexcept
598  {
599  return std::static_pointer_cast<const rvsdg::BitType>(result(0))->nbits();
600  }
601 
602  static std::unique_ptr<llvm::ThreeAddressCode>
603  create(const Variable * argument, const std::shared_ptr<const jlm::rvsdg::Type> & type)
604  {
605  auto pt = std::dynamic_pointer_cast<const PointerType>(argument->Type());
606  if (!pt)
607  throw util::Error("expected pointer type.");
608 
609  auto bt = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(type);
610  if (!bt)
611  throw util::Error("expected bitstring type.");
612 
613  auto op = std::make_unique<PtrToIntOperation>(std::move(pt), std::move(bt));
614  return ThreeAddressCode::create(std::move(op), { argument });
615  }
616 };
617 
618 /* Constant Data Array operator */
619 
621 {
622 public:
623  ~ConstantDataArray() noexcept override;
624 
625  ConstantDataArray(const std::shared_ptr<const jlm::rvsdg::Type> & type, size_t size)
627  {
628  if (size == 0)
629  throw util::Error("size equals zero.");
630  }
631 
632  bool
633  operator==(const Operation & other) const noexcept override;
634 
635  [[nodiscard]] std::string
636  debug_string() const override;
637 
638  [[nodiscard]] std::unique_ptr<Operation>
639  copy() const override;
640 
641  size_t
642  size() const noexcept
643  {
644  return std::static_pointer_cast<const ArrayType>(result(0))->nelements();
645  }
646 
647  const jlm::rvsdg::Type &
648  type() const noexcept
649  {
650  return std::static_pointer_cast<const ArrayType>(result(0))->element_type();
651  }
652 
653  static std::unique_ptr<llvm::ThreeAddressCode>
654  create(const std::vector<const Variable *> & elements)
655  {
656  if (elements.size() == 0)
657  throw util::Error("expected at least one element.");
658 
659  auto vt = elements[0]->Type();
660  if (vt->Kind() != rvsdg::TypeKind::Value)
661  throw util::Error("expected value type.");
662 
663  auto op = std::make_unique<ConstantDataArray>(std::move(vt), elements.size());
664  return ThreeAddressCode::create(std::move(op), elements);
665  }
666 
667  static jlm::rvsdg::Output *
668  Create(const std::vector<jlm::rvsdg::Output *> & elements)
669  {
670  if (elements.empty())
671  throw util::Error("Expected at least one element.");
672 
673  auto valueType = elements[0]->Type();
674  if (valueType->Kind() != rvsdg::TypeKind::Value)
675  {
676  throw util::Error("Expected value type.");
677  }
678 
679  return rvsdg::CreateOpNode<ConstantDataArray>(elements, std::move(valueType), elements.size())
680  .output(0);
681  }
682 };
683 
684 enum class cmp
685 {
686  eq,
687  ne,
688  gt,
689  ge,
690  lt,
691  le
692 };
693 
695 {
696 public:
697  ~PtrCmpOperation() noexcept override;
698 
699  PtrCmpOperation(const std::shared_ptr<const PointerType> & ptype, const llvm::cmp & cmp)
700  : BinaryOperation({ ptype, ptype }, jlm::rvsdg::BitType::Create(1)),
701  cmp_(cmp)
702  {}
703 
704  bool
705  operator==(const Operation & other) const noexcept override;
706 
707  [[nodiscard]] std::string
708  debug_string() const override;
709 
710  [[nodiscard]] std::unique_ptr<Operation>
711  copy() const override;
712 
715  const noexcept override;
716 
720  jlm::rvsdg::Output * op1,
721  jlm::rvsdg::Output * op2) const override;
722 
723  inline llvm::cmp
724  cmp() const noexcept
725  {
726  return cmp_;
727  }
728 
729  static std::unique_ptr<llvm::ThreeAddressCode>
730  create(const llvm::cmp & cmp, const Variable * op1, const Variable * op2)
731  {
732  auto pt = std::dynamic_pointer_cast<const PointerType>(op1->Type());
733  if (!pt)
734  throw util::Error("expected pointer type.");
735 
736  auto op = std::make_unique<PtrCmpOperation>(std::move(pt), cmp);
737  return ThreeAddressCode::create(std::move(op), { op1, op2 });
738  }
739 
740 private:
742 };
743 
745 {
746 public:
747  ~ZExtOperation() noexcept override;
748 
750  : UnaryOperation(rvsdg::BitType::Create(nsrcbits), rvsdg::BitType::Create(ndstbits))
751  {
752  if (ndstbits < nsrcbits)
753  throw util::Error("# destination bits must be greater than # source bits.");
754  }
755 
757  const std::shared_ptr<const jlm::rvsdg::BitType> & srctype,
758  const std::shared_ptr<const jlm::rvsdg::BitType> & dsttype)
759  : UnaryOperation(srctype, dsttype)
760  {
761  if (dsttype->nbits() < srctype->nbits())
762  throw util::Error("# destination bits must be greater than # source bits.");
763  }
764 
766  std::shared_ptr<const jlm::rvsdg::Type> srctype,
767  std::shared_ptr<const jlm::rvsdg::Type> dsttype)
768  : UnaryOperation(srctype, dsttype)
769  {
770  auto st = dynamic_cast<const jlm::rvsdg::BitType *>(srctype.get());
771  if (!st)
772  throw util::Error("expected bitstring type.");
773 
774  auto dt = dynamic_cast<const jlm::rvsdg::BitType *>(dsttype.get());
775  if (!dt)
776  throw util::Error("expected bitstring type.");
777 
778  if (dt->nbits() < st->nbits())
779  throw util::Error("# destination bits must be greater than # source bits.");
780  }
781 
782  bool
783  operator==(const Operation & other) const noexcept override;
784 
785  [[nodiscard]] std::string
786  debug_string() const override;
787 
788  [[nodiscard]] std::unique_ptr<Operation>
789  copy() const override;
790 
792  can_reduce_operand(const jlm::rvsdg::Output * operand) const noexcept override;
793 
796  const override;
797 
798  inline size_t
799  nsrcbits() const noexcept
800  {
801  return std::static_pointer_cast<const rvsdg::BitType>(argument(0))->nbits();
802  }
803 
804  inline size_t
805  ndstbits() const noexcept
806  {
807  return std::static_pointer_cast<const rvsdg::BitType>(result(0))->nbits();
808  }
809 
810  static std::unique_ptr<llvm::ThreeAddressCode>
811  create(const Variable * operand, const std::shared_ptr<const jlm::rvsdg::Type> & type)
812  {
813  auto operandBitType = CheckAndExtractBitType(operand->Type());
814  auto resultBitType = CheckAndExtractBitType(type);
815 
816  auto operation =
817  std::make_unique<ZExtOperation>(std::move(operandBitType), std::move(resultBitType));
818  return ThreeAddressCode::create(std::move(operation), { operand });
819  }
820 
821  static rvsdg::Output &
822  Create(rvsdg::Output & operand, const std::shared_ptr<const rvsdg::Type> & resultType)
823  {
824  auto operandBitType = CheckAndExtractBitType(operand.Type());
825  auto resultBitType = CheckAndExtractBitType(resultType);
826 
827  return *rvsdg::CreateOpNode<ZExtOperation>(
828  { &operand },
829  std::move(operandBitType),
830  std::move(resultBitType))
831  .output(0);
832  }
833 
834 private:
835  static std::shared_ptr<const rvsdg::BitType>
836  CheckAndExtractBitType(const std::shared_ptr<const rvsdg::Type> & type)
837  {
838  if (auto bitType = std::dynamic_pointer_cast<const rvsdg::BitType>(type))
839  {
840  return bitType;
841  }
842 
843  throw util::TypeError("BitType", type->debug_string());
844  }
845 };
846 
847 /* floating point constant operator */
848 
849 class ConstantFP final : public rvsdg::SimpleOperation
850 {
851 public:
852  ~ConstantFP() noexcept override;
853 
854  inline ConstantFP(const fpsize & size, const ::llvm::APFloat & constant)
857  {}
858 
859  ConstantFP(std::shared_ptr<const FloatingPointType> fpt, const ::llvm::APFloat & constant)
860  : SimpleOperation({}, { std::move(fpt) }),
862  {}
863 
864  bool
865  operator==(const Operation & other) const noexcept override;
866 
867  [[nodiscard]] std::string
868  debug_string() const override;
869 
870  [[nodiscard]] std::unique_ptr<Operation>
871  copy() const override;
872 
873  inline const ::llvm::APFloat &
874  constant() const noexcept
875  {
876  return constant_;
877  }
878 
879  inline const fpsize &
880  size() const noexcept
881  {
882  return std::static_pointer_cast<const FloatingPointType>(result(0))->size();
883  }
884 
885  static std::unique_ptr<llvm::ThreeAddressCode>
886  create(const ::llvm::APFloat & constant, const std::shared_ptr<const jlm::rvsdg::Type> & type)
887  {
888  auto ft = std::dynamic_pointer_cast<const FloatingPointType>(type);
889  if (!ft)
890  throw util::Error("expected floating point type.");
891 
892  auto op = std::make_unique<ConstantFP>(std::move(ft), constant);
893  return ThreeAddressCode::create(std::move(op), {});
894  }
895 
896 private:
897  /* FIXME: I would not like to use the APFloat here,
898  but I don't have a replacement right now. */
899  ::llvm::APFloat constant_;
900 };
901 
902 /* floating point comparison operator */
903 
904 enum class fpcmp
905 {
906  TRUE,
907  FALSE,
908  oeq,
909  ogt,
910  oge,
911  olt,
912  ole,
913  one,
914  ord,
915  ueq,
916  ugt,
917  uge,
918  ult,
919  ule,
920  une,
921  uno
922 };
923 
925 {
926 public:
927  ~FCmpOperation() noexcept override;
928 
929  FCmpOperation(const fpcmp & cmp, const fpsize & size)
930  : BinaryOperation(
933  cmp_(cmp)
934  {}
935 
936  FCmpOperation(const fpcmp & cmp, const std::shared_ptr<const FloatingPointType> & fpt)
937  : BinaryOperation({ fpt, fpt }, jlm::rvsdg::BitType::Create(1)),
938  cmp_(cmp)
939  {}
940 
941  bool
942  operator==(const Operation & other) const noexcept override;
943 
944  [[nodiscard]] std::string
945  debug_string() const override;
946 
947  [[nodiscard]] std::unique_ptr<Operation>
948  copy() const override;
949 
952  const noexcept override;
953 
957  jlm::rvsdg::Output * op1,
958  jlm::rvsdg::Output * op2) const override;
959 
960  inline const fpcmp &
961  cmp() const noexcept
962  {
963  return cmp_;
964  }
965 
966  inline const fpsize &
967  size() const noexcept
968  {
969  return std::static_pointer_cast<const FloatingPointType>(argument(0))->size();
970  }
971 
972  static std::unique_ptr<llvm::ThreeAddressCode>
973  create(const fpcmp & cmp, const Variable * op1, const Variable * op2)
974  {
975  auto ft = std::dynamic_pointer_cast<const FloatingPointType>(op1->Type());
976  if (!ft)
977  throw util::Error("expected floating point type.");
978 
979  auto op = std::make_unique<FCmpOperation>(cmp, std::move(ft));
980  return ThreeAddressCode::create(std::move(op), { op1, op2 });
981  }
982 
983 private:
985 };
986 
992 {
993 public:
994  ~UndefValueOperation() noexcept override;
995 
996  explicit UndefValueOperation(std::shared_ptr<const jlm::rvsdg::Type> type)
997  : SimpleOperation({}, { std::move(type) })
998  {}
999 
1001 
1003  operator=(const UndefValueOperation &) = delete;
1004 
1007 
1008  bool
1009  operator==(const Operation & other) const noexcept override;
1010 
1011  [[nodiscard]] std::string
1012  debug_string() const override;
1013 
1014  [[nodiscard]] std::unique_ptr<Operation>
1015  copy() const override;
1016 
1017  [[nodiscard]] const rvsdg::Type &
1018  GetType() const noexcept
1019  {
1020  return *result(0);
1021  }
1022 
1023  static jlm::rvsdg::Output *
1024  Create(rvsdg::Region & region, std::shared_ptr<const jlm::rvsdg::Type> type)
1025  {
1026  return rvsdg::CreateOpNode<UndefValueOperation>(region, std::move(type)).output(0);
1027  }
1028 
1029  static std::unique_ptr<llvm::ThreeAddressCode>
1030  Create(std::shared_ptr<const jlm::rvsdg::Type> type)
1031  {
1032  auto operation = std::make_unique<UndefValueOperation>(std::move(type));
1033  return ThreeAddressCode::create(std::move(operation), {});
1034  }
1035 
1036  static std::unique_ptr<llvm::ThreeAddressCode>
1037  Create(std::shared_ptr<const jlm::rvsdg::Type> type, const std::string & name)
1038  {
1039  auto operation = std::make_unique<UndefValueOperation>(std::move(type));
1040  return ThreeAddressCode::create(std::move(operation), {}, { name });
1041  }
1042 
1043  static std::unique_ptr<llvm::ThreeAddressCode>
1044  Create(std::unique_ptr<ThreeAddressCodeVariable> result)
1045  {
1046  auto & type = result->Type();
1047 
1048  std::vector<std::unique_ptr<ThreeAddressCodeVariable>> results;
1049  results.push_back(std::move(result));
1050 
1051  auto operation = std::make_unique<UndefValueOperation>(type);
1052  return ThreeAddressCode::create(std::move(operation), {}, std::move(results));
1053  }
1054 };
1055 
1061 {
1062 public:
1063  ~PoisonValueOperation() noexcept override;
1064 
1065  explicit PoisonValueOperation(std::shared_ptr<const jlm::rvsdg::Type> type)
1066  : SimpleOperation({}, { std::move(type) })
1067  {}
1068 
1070 
1072 
1074  operator=(const PoisonValueOperation &) = delete;
1075 
1078 
1079  bool
1080  operator==(const Operation & other) const noexcept override;
1081 
1082  std::string
1083  debug_string() const override;
1084 
1085  [[nodiscard]] std::unique_ptr<Operation>
1086  copy() const override;
1087 
1088  const jlm::rvsdg::Type &
1089  GetType() const noexcept
1090  {
1091  return *result(0).get();
1092  }
1093 
1094  static std::unique_ptr<llvm::ThreeAddressCode>
1095  Create(const std::shared_ptr<const jlm::rvsdg::Type> & type)
1096  {
1097  auto valueType = CheckAndConvertType(type);
1098 
1099  auto operation = std::make_unique<PoisonValueOperation>(std::move(valueType));
1100  return ThreeAddressCode::create(std::move(operation), {});
1101  }
1102 
1103  static jlm::rvsdg::Output *
1104  Create(rvsdg::Region * region, const std::shared_ptr<const jlm::rvsdg::Type> & type)
1105  {
1106  auto valueType = CheckAndConvertType(type);
1107 
1108  return rvsdg::CreateOpNode<PoisonValueOperation>(*region, std::move(valueType)).output(0);
1109  }
1110 
1111 private:
1112  static std::shared_ptr<const jlm::rvsdg::Type>
1113  CheckAndConvertType(const std::shared_ptr<const jlm::rvsdg::Type> & type)
1114  {
1115  if (type->Kind() == rvsdg::TypeKind::Value)
1116  return type;
1117 
1118  throw util::Error("Expected value type.");
1119  }
1120 };
1121 
1122 /* floating point arithmetic operator */
1123 
1124 enum class fpop
1125 {
1126  add,
1127  sub,
1128  mul,
1129  div,
1130  mod
1131 };
1132 
1134 {
1135 public:
1136  ~FBinaryOperation() noexcept override;
1137 
1138  FBinaryOperation(const llvm::fpop & op, const fpsize & size)
1139  : BinaryOperation(
1142  op_(op)
1143  {}
1144 
1145  FBinaryOperation(const llvm::fpop & op, const std::shared_ptr<const FloatingPointType> & fpt)
1146  : BinaryOperation({ fpt, fpt }, fpt),
1147  op_(op)
1148  {}
1149 
1150  bool
1151  operator==(const Operation & other) const noexcept override;
1152 
1153  [[nodiscard]] std::string
1154  debug_string() const override;
1155 
1156  [[nodiscard]] std::unique_ptr<Operation>
1157  copy() const override;
1158 
1161  const noexcept override;
1162 
1166  jlm::rvsdg::Output * op1,
1167  jlm::rvsdg::Output * op2) const override;
1168 
1169  inline const llvm::fpop &
1170  fpop() const noexcept
1171  {
1172  return op_;
1173  }
1174 
1175  inline const fpsize &
1176  size() const noexcept
1177  {
1178  return std::static_pointer_cast<const FloatingPointType>(result(0))->size();
1179  }
1180 
1181  static std::unique_ptr<llvm::ThreeAddressCode>
1182  create(const llvm::fpop & fpop, const Variable * op1, const Variable * op2)
1183  {
1184  auto ft = std::dynamic_pointer_cast<const FloatingPointType>(op1->Type());
1185  if (!ft)
1186  throw util::Error("expected floating point type.");
1187 
1188  auto op = std::make_unique<FBinaryOperation>(fpop, ft);
1189  return ThreeAddressCode::create(std::move(op), { op1, op2 });
1190  }
1191 
1192 private:
1194 };
1195 
1197 {
1198 public:
1199  ~FPExtOperation() noexcept override;
1200 
1203  {
1204  if (srcsize == fpsize::flt && dstsize == fpsize::half)
1205  throw util::Error("destination type size must be bigger than source type size.");
1206  }
1207 
1209  const std::shared_ptr<const FloatingPointType> & srctype,
1210  const std::shared_ptr<const FloatingPointType> & dsttype)
1211  : UnaryOperation(srctype, dsttype)
1212  {
1213  if (srctype->size() == fpsize::flt && dsttype->size() == fpsize::half)
1214  throw util::Error("destination type size must be bigger than source type size.");
1215  }
1216 
1218  std::shared_ptr<const jlm::rvsdg::Type> srctype,
1219  std::shared_ptr<const jlm::rvsdg::Type> dsttype)
1220  : UnaryOperation(srctype, dsttype)
1221  {
1222  auto st = dynamic_cast<const FloatingPointType *>(srctype.get());
1223  if (!st)
1224  throw util::Error("expected floating point type.");
1225 
1226  auto dt = dynamic_cast<const FloatingPointType *>(dsttype.get());
1227  if (!dt)
1228  throw util::Error("expected floating point type.");
1229 
1230  if (st->size() == fpsize::flt && dt->size() == fpsize::half)
1231  throw util::Error("destination type size must be bigger than source type size.");
1232  }
1233 
1234  bool
1235  operator==(const Operation & other) const noexcept override;
1236 
1237  [[nodiscard]] std::string
1238  debug_string() const override;
1239 
1240  [[nodiscard]] std::unique_ptr<Operation>
1241  copy() const override;
1242 
1244  can_reduce_operand(const jlm::rvsdg::Output * output) const noexcept override;
1245 
1248  const override;
1249 
1250  inline const fpsize &
1251  srcsize() const noexcept
1252  {
1253  return std::static_pointer_cast<const FloatingPointType>(argument(0))->size();
1254  }
1255 
1256  inline const fpsize &
1257  dstsize() const noexcept
1258  {
1259  return std::static_pointer_cast<const FloatingPointType>(result(0))->size();
1260  }
1261 
1262  static std::unique_ptr<llvm::ThreeAddressCode>
1263  create(const Variable * operand, const std::shared_ptr<const jlm::rvsdg::Type> & type)
1264  {
1265  auto st = std::dynamic_pointer_cast<const FloatingPointType>(operand->Type());
1266  if (!st)
1267  throw util::Error("expected floating point type.");
1268 
1269  auto dt = std::dynamic_pointer_cast<const FloatingPointType>(type);
1270  if (!dt)
1271  throw util::Error("expected floating point type.");
1272 
1273  auto op = std::make_unique<FPExtOperation>(std::move(st), std::move(dt));
1274  return ThreeAddressCode::create(std::move(op), { operand });
1275  }
1276 };
1277 
1279 {
1280 public:
1281  ~FNegOperation() noexcept override;
1282 
1283  explicit FNegOperation(const fpsize & size)
1285  {}
1286 
1287  explicit FNegOperation(const std::shared_ptr<const FloatingPointType> & fpt)
1288  : UnaryOperation(fpt, fpt)
1289  {}
1290 
1291  bool
1292  operator==(const Operation & other) const noexcept override;
1293 
1294  [[nodiscard]] std::string
1295  debug_string() const override;
1296 
1297  [[nodiscard]] std::unique_ptr<Operation>
1298  copy() const override;
1299 
1301  can_reduce_operand(const jlm::rvsdg::Output * output) const noexcept override;
1302 
1305  const override;
1306 
1307  const fpsize &
1308  size() const noexcept
1309  {
1310  return std::static_pointer_cast<const FloatingPointType>(argument(0))->size();
1311  }
1312 
1313  static std::unique_ptr<llvm::ThreeAddressCode>
1314  create(const Variable * operand)
1315  {
1316  auto type = std::dynamic_pointer_cast<const FloatingPointType>(operand->Type());
1317  if (!type)
1318  throw util::Error("expected floating point type.");
1319 
1320  auto op = std::make_unique<FNegOperation>(std::move(type));
1321  return ThreeAddressCode::create(std::move(op), { operand });
1322  }
1323 };
1324 
1326 {
1327 public:
1328  ~FPTruncOperation() noexcept override;
1329 
1332  {
1334  || (srcsize == fpsize::dbl && dstsize == fpsize::dbl))
1335  throw util::Error("destination tpye size must be smaller than source size type.");
1336  }
1337 
1339  const std::shared_ptr<const FloatingPointType> & srctype,
1340  const std::shared_ptr<const FloatingPointType> & dsttype)
1341  : UnaryOperation(srctype, dsttype)
1342  {
1343  if (srctype->size() == fpsize::flt && dsttype->size() == fpsize::half)
1344  throw util::Error("destination type size must be bigger than source type size.");
1345  }
1346 
1348  std::shared_ptr<const jlm::rvsdg::Type> srctype,
1349  std::shared_ptr<const jlm::rvsdg::Type> dsttype)
1350  : UnaryOperation(srctype, dsttype)
1351  {
1352  auto st = dynamic_cast<const FloatingPointType *>(srctype.get());
1353  if (!st)
1354  throw util::Error("expected floating point type.");
1355 
1356  auto dt = dynamic_cast<const FloatingPointType *>(dsttype.get());
1357  if (!dt)
1358  throw util::Error("expected floating point type.");
1359 
1360  if (st->size() == fpsize::half || (st->size() == fpsize::flt && dt->size() != fpsize::half)
1361  || (st->size() == fpsize::dbl && dt->size() == fpsize::dbl))
1362  throw util::Error("destination type size must be smaller than source size type.");
1363  }
1364 
1365  bool
1366  operator==(const Operation & other) const noexcept override;
1367 
1368  [[nodiscard]] std::string
1369  debug_string() const override;
1370 
1371  [[nodiscard]] std::unique_ptr<Operation>
1372  copy() const override;
1373 
1375  can_reduce_operand(const jlm::rvsdg::Output * output) const noexcept override;
1376 
1379  const override;
1380 
1381  inline const fpsize &
1382  srcsize() const noexcept
1383  {
1384  return std::static_pointer_cast<const FloatingPointType>(argument(0))->size();
1385  }
1386 
1387  inline const fpsize &
1388  dstsize() const noexcept
1389  {
1390  return std::static_pointer_cast<const FloatingPointType>(result(0))->size();
1391  }
1392 
1393  static std::unique_ptr<llvm::ThreeAddressCode>
1394  create(const Variable * operand, std::shared_ptr<const jlm::rvsdg::Type> type)
1395  {
1396  auto st = std::dynamic_pointer_cast<const FloatingPointType>(operand->Type());
1397  if (!st)
1398  throw util::Error("expected floating point type.");
1399 
1400  auto dt = std::dynamic_pointer_cast<const FloatingPointType>(type);
1401  if (!dt)
1402  throw util::Error("expected floating point type.");
1403 
1404  auto op = std::make_unique<FPTruncOperation>(std::move(st), std::move(dt));
1405  return ThreeAddressCode::create(std::move(op), { operand });
1406  }
1407 };
1408 
1410 {
1411 public:
1412  ~VariadicArgumentListOperation() noexcept override;
1413 
1414  explicit VariadicArgumentListOperation(std::vector<std::shared_ptr<const jlm::rvsdg::Type>> types)
1415  : SimpleOperation(std::move(types), { VariableArgumentType::Create() })
1416  {}
1417 
1419 
1422 
1425 
1426  bool
1427  operator==(const Operation & other) const noexcept override;
1428 
1429  [[nodiscard]] std::string
1430  debug_string() const override;
1431 
1432  [[nodiscard]] std::unique_ptr<Operation>
1433  copy() const override;
1434 
1435  static std::unique_ptr<llvm::ThreeAddressCode>
1436  create(const std::vector<const Variable *> & arguments)
1437  {
1438  std::vector<std::shared_ptr<const jlm::rvsdg::Type>> operands;
1439  for (const auto & argument : arguments)
1440  operands.push_back(argument->Type());
1441 
1442  auto op = std::make_unique<VariadicArgumentListOperation>(std::move(operands));
1443  return ThreeAddressCode::create(std::move(op), arguments);
1444  }
1445 
1446  static rvsdg::Output *
1447  Create(rvsdg::Region & region, const std::vector<rvsdg::Output *> & operands)
1448  {
1449  std::vector<std::shared_ptr<const rvsdg::Type>> operandTypes;
1450  operandTypes.reserve(operands.size());
1451  for (auto & operand : operands)
1452  operandTypes.emplace_back(operand->Type());
1453 
1454  return operands.empty()
1455  ? rvsdg::CreateOpNode<VariadicArgumentListOperation>(region, std::move(operandTypes))
1456  .output(0)
1457  : rvsdg::CreateOpNode<VariadicArgumentListOperation>(operands, std::move(operandTypes))
1458  .output(0);
1459  }
1460 };
1461 
1463 {
1464 public:
1465  ~BitCastOperation() noexcept override;
1466 
1468  std::shared_ptr<const jlm::rvsdg::Type> srctype,
1469  std::shared_ptr<const jlm::rvsdg::Type> dsttype)
1470  : UnaryOperation(srctype, dsttype)
1471  {
1472  check_types(srctype, dsttype);
1473  }
1474 
1476 
1477  explicit BitCastOperation(Operation &&) = delete;
1478 
1480  operator=(const Operation &) = delete;
1481 
1483  operator=(Operation &&) = delete;
1484 
1485  bool
1486  operator==(const Operation & other) const noexcept override;
1487 
1488  [[nodiscard]] std::string
1489  debug_string() const override;
1490 
1491  [[nodiscard]] std::unique_ptr<Operation>
1492  copy() const override;
1493 
1495  can_reduce_operand(const jlm::rvsdg::Output * output) const noexcept override;
1496 
1499  const override;
1500 
1501  static std::unique_ptr<llvm::ThreeAddressCode>
1502  create(const Variable * operand, std::shared_ptr<const jlm::rvsdg::Type> type)
1503  {
1504  auto pair = check_types(operand->Type(), type);
1505 
1506  auto op = std::make_unique<BitCastOperation>(pair.first, pair.second);
1507  return ThreeAddressCode::create(std::move(op), { operand });
1508  }
1509 
1510  static jlm::rvsdg::Output *
1511  create(jlm::rvsdg::Output * operand, std::shared_ptr<const jlm::rvsdg::Type> rtype)
1512  {
1513  auto pair = check_types(operand->Type(), rtype);
1514  return rvsdg::CreateOpNode<BitCastOperation>({ operand }, pair.first, pair.second).output(0);
1515  }
1516 
1517 private:
1518  static std::pair<std::shared_ptr<const jlm::rvsdg::Type>, std::shared_ptr<const jlm::rvsdg::Type>>
1520  const std::shared_ptr<const jlm::rvsdg::Type> & otype,
1521  const std::shared_ptr<const jlm::rvsdg::Type> & rtype)
1522  {
1523  if (otype->Kind() != rvsdg::TypeKind::Value)
1524  throw util::Error("expected value type.");
1525 
1526  if (rtype->Kind() != rvsdg::TypeKind::Value)
1527  throw util::Error("expected value type.");
1528 
1529  return std::make_pair(otype, rtype);
1530  }
1531 };
1532 
1534 {
1535 public:
1536  ~ConstantStruct() override;
1537 
1538  inline ConstantStruct(std::shared_ptr<const StructType> type)
1540  {}
1541 
1542  bool
1543  operator==(const Operation & other) const noexcept override;
1544 
1545  [[nodiscard]] std::string
1546  debug_string() const override;
1547 
1548  [[nodiscard]] std::unique_ptr<Operation>
1549  copy() const override;
1550 
1551  const StructType &
1552  type() const noexcept
1553  {
1554  return *std::static_pointer_cast<const StructType>(result(0));
1555  }
1556 
1557  static std::unique_ptr<llvm::ThreeAddressCode>
1559  const std::vector<const Variable *> & elements,
1560  const std::shared_ptr<const jlm::rvsdg::Type> & type)
1561  {
1562  auto structType = CheckAndExtractStructType(type);
1563 
1564  auto op = std::make_unique<ConstantStruct>(std::move(structType));
1565  return ThreeAddressCode::create(std::move(op), elements);
1566  }
1567 
1568  static rvsdg::Output &
1570  rvsdg::Region &,
1571  const std::vector<rvsdg::Output *> & operands,
1572  std::shared_ptr<const rvsdg::Type> resultType)
1573  {
1574  auto structType = CheckAndExtractStructType(std::move(resultType));
1575  return *rvsdg::CreateOpNode<ConstantStruct>(operands, std::move(structType)).output(0);
1576  }
1577 
1578 private:
1579  static inline std::vector<std::shared_ptr<const rvsdg::Type>>
1581  {
1582  std::vector<std::shared_ptr<const rvsdg::Type>> types;
1583  for (size_t n = 0; n < type.numElements(); n++)
1584  types.push_back(type.getElementType(n));
1585 
1586  return types;
1587  }
1588 
1589  static std::shared_ptr<const StructType>
1590  CheckAndExtractStructType(std::shared_ptr<const rvsdg::Type> type)
1591  {
1592  if (auto structType = std::dynamic_pointer_cast<const StructType>(type))
1593  {
1594  return structType;
1595  }
1596 
1597  throw util::TypeError("StructType", type->debug_string());
1598  }
1599 };
1600 
1602 {
1603 public:
1604  ~TruncOperation() noexcept override;
1605 
1607  const std::shared_ptr<const jlm::rvsdg::BitType> & otype,
1608  const std::shared_ptr<const jlm::rvsdg::BitType> & rtype)
1609  : UnaryOperation(otype, rtype)
1610  {
1611  if (otype->nbits() < rtype->nbits())
1612  throw util::Error("expected operand's #bits to be larger than results' #bits.");
1613  }
1614 
1616  std::shared_ptr<const jlm::rvsdg::Type> optype,
1617  std::shared_ptr<const jlm::rvsdg::Type> restype)
1618  : UnaryOperation(optype, restype)
1619  {
1620  auto ot = dynamic_cast<const jlm::rvsdg::BitType *>(optype.get());
1621  if (!ot)
1622  throw util::Error("expected bits type.");
1623 
1624  auto rt = dynamic_cast<const jlm::rvsdg::BitType *>(restype.get());
1625  if (!rt)
1626  throw util::Error("expected bits type.");
1627 
1628  if (ot->nbits() < rt->nbits())
1629  throw util::Error("expected operand's #bits to be larger than results' #bits.");
1630  }
1631 
1632  bool
1633  operator==(const Operation & other) const noexcept override;
1634 
1635  [[nodiscard]] std::string
1636  debug_string() const override;
1637 
1638  [[nodiscard]] std::unique_ptr<Operation>
1639  copy() const override;
1640 
1642  can_reduce_operand(const jlm::rvsdg::Output * operand) const noexcept override;
1643 
1646  const override;
1647 
1648  inline size_t
1649  nsrcbits() const noexcept
1650  {
1651  return std::static_pointer_cast<const rvsdg::BitType>(argument(0))->nbits();
1652  }
1653 
1654  inline size_t
1655  ndstbits() const noexcept
1656  {
1657  return std::static_pointer_cast<const rvsdg::BitType>(result(0))->nbits();
1658  }
1659 
1660  static std::unique_ptr<llvm::ThreeAddressCode>
1661  create(const Variable * operand, const std::shared_ptr<const jlm::rvsdg::Type> & type)
1662  {
1663  auto ot = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(operand->Type());
1664  if (!ot)
1665  throw util::Error("expected bits type.");
1666 
1667  auto rt = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(type);
1668  if (!rt)
1669  throw util::Error("expected bits type.");
1670 
1671  auto op = std::make_unique<TruncOperation>(std::move(ot), std::move(rt));
1672  return ThreeAddressCode::create(std::move(op), { operand });
1673  }
1674 
1675  static jlm::rvsdg::Output *
1677  {
1678  auto ot = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(operand->Type());
1679  if (!ot)
1680  throw util::Error("expected bits type.");
1681 
1682  return rvsdg::CreateOpNode<TruncOperation>(
1683  { operand },
1684  std::move(ot),
1686  .output(0);
1687  }
1688 };
1689 
1691 {
1692 public:
1693  ~UIToFPOperation() noexcept override;
1694 
1696  std::shared_ptr<const jlm::rvsdg::BitType> srctype,
1697  std::shared_ptr<const FloatingPointType> dsttype)
1698  : UnaryOperation(std::move(srctype), std::move(dsttype))
1699  {}
1700 
1702  std::shared_ptr<const jlm::rvsdg::Type> optype,
1703  std::shared_ptr<const jlm::rvsdg::Type> restype)
1704  : UnaryOperation(optype, restype)
1705  {
1706  auto st = dynamic_cast<const jlm::rvsdg::BitType *>(optype.get());
1707  if (!st)
1708  throw util::Error("expected bits type.");
1709 
1710  auto rt = dynamic_cast<const FloatingPointType *>(restype.get());
1711  if (!rt)
1712  throw util::Error("expected floating point type.");
1713  }
1714 
1715  bool
1716  operator==(const Operation & other) const noexcept override;
1717 
1718  [[nodiscard]] std::string
1719  debug_string() const override;
1720 
1721  [[nodiscard]] std::unique_ptr<Operation>
1722  copy() const override;
1723 
1725  can_reduce_operand(const jlm::rvsdg::Output * operand) const noexcept override;
1726 
1729  const override;
1730 
1731  static std::unique_ptr<llvm::ThreeAddressCode>
1732  create(const Variable * operand, const std::shared_ptr<const jlm::rvsdg::Type> & type)
1733  {
1734  auto st = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(operand->Type());
1735  if (!st)
1736  throw util::Error("expected bits type.");
1737 
1738  auto rt = std::dynamic_pointer_cast<const FloatingPointType>(type);
1739  if (!rt)
1740  throw util::Error("expected floating point type.");
1741 
1742  auto op = std::make_unique<UIToFPOperation>(std::move(st), std::move(rt));
1743  return ThreeAddressCode::create(std::move(op), { operand });
1744  }
1745 };
1746 
1748 {
1749 public:
1750  ~SIToFPOperation() noexcept override;
1751 
1753  std::shared_ptr<const jlm::rvsdg::BitType> srctype,
1754  std::shared_ptr<const FloatingPointType> dsttype)
1755  : UnaryOperation(std::move(srctype), std::move(dsttype))
1756  {}
1757 
1759  std::shared_ptr<const jlm::rvsdg::Type> srctype,
1760  std::shared_ptr<const jlm::rvsdg::Type> dsttype)
1761  : UnaryOperation(srctype, dsttype)
1762  {
1763  auto st = dynamic_cast<const jlm::rvsdg::BitType *>(srctype.get());
1764  if (!st)
1765  throw util::Error("expected bits type.");
1766 
1767  auto rt = dynamic_cast<const FloatingPointType *>(dsttype.get());
1768  if (!rt)
1769  throw util::Error("expected floating point type.");
1770  }
1771 
1772  bool
1773  operator==(const Operation & other) const noexcept override;
1774 
1775  [[nodiscard]] std::string
1776  debug_string() const override;
1777 
1778  [[nodiscard]] std::unique_ptr<Operation>
1779  copy() const override;
1780 
1782  can_reduce_operand(const jlm::rvsdg::Output * output) const noexcept override;
1783 
1786  const override;
1787 
1788  static std::unique_ptr<llvm::ThreeAddressCode>
1789  create(const Variable * operand, const std::shared_ptr<const jlm::rvsdg::Type> & type)
1790  {
1791  auto st = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(operand->Type());
1792  if (!st)
1793  throw util::Error("expected bits type.");
1794 
1795  auto rt = std::dynamic_pointer_cast<const FloatingPointType>(type);
1796  if (!rt)
1797  throw util::Error("expected floating point type.");
1798 
1799  auto op = std::make_unique<SIToFPOperation>(std::move(st), std::move(rt));
1800  return ThreeAddressCode::create(std::move(op), { operand });
1801  }
1802 };
1803 
1805 {
1806 public:
1807  ~ConstantArrayOperation() noexcept override;
1808 
1809  ConstantArrayOperation(const std::shared_ptr<const jlm::rvsdg::Type> & type, size_t size)
1811  {
1812  if (size == 0)
1813  throw util::Error("size equals zero.\n");
1814  }
1815 
1816  bool
1817  operator==(const Operation & other) const noexcept override;
1818 
1819  [[nodiscard]] std::string
1820  debug_string() const override;
1821 
1822  [[nodiscard]] std::unique_ptr<Operation>
1823  copy() const override;
1824 
1825  size_t
1826  size() const noexcept
1827  {
1828  return std::static_pointer_cast<const ArrayType>(result(0))->nelements();
1829  }
1830 
1831  const jlm::rvsdg::Type &
1832  type() const noexcept
1833  {
1834  return std::static_pointer_cast<const ArrayType>(result(0))->element_type();
1835  }
1836 
1837  static std::unique_ptr<llvm::ThreeAddressCode>
1838  create(const std::vector<const Variable *> & elements)
1839  {
1840  if (elements.size() == 0)
1841  throw util::Error("expected at least one element.\n");
1842 
1843  auto vt = elements[0]->Type();
1844  if (vt->Kind() != rvsdg::TypeKind::Value)
1845  throw util::Error("expected value Type.\n");
1846 
1847  auto op = std::make_unique<ConstantArrayOperation>(vt, elements.size());
1848  return ThreeAddressCode::create(std::move(op), elements);
1849  }
1850 
1851  static rvsdg::Output *
1852  Create(const std::vector<rvsdg::Output *> & operands)
1853  {
1854  if (operands.empty())
1855  throw util::Error("Expected at least one element.\n");
1856 
1857  auto valueType = operands[0]->Type();
1858  if (valueType->Kind() != rvsdg::TypeKind::Value)
1859  {
1860  throw util::Error("Expected value type.\n");
1861  }
1862 
1863  return rvsdg::CreateOpNode<ConstantArrayOperation>(operands, valueType, operands.size())
1864  .output(0);
1865  }
1866 };
1867 
1869 {
1870 public:
1871  ~ConstantAggregateZeroOperation() noexcept override;
1872 
1873  explicit ConstantAggregateZeroOperation(std::shared_ptr<const rvsdg::Type> type)
1874  : SimpleOperation({}, { type })
1875  {
1876  auto st = dynamic_cast<const StructType *>(type.get());
1877  auto at = dynamic_cast<const ArrayType *>(type.get());
1878  auto vt = dynamic_cast<const VectorType *>(type.get());
1879  if (!st && !at && !vt)
1880  throw util::Error("expected array, struct, or vector type.\n");
1881  }
1882 
1883  bool
1884  operator==(const Operation & other) const noexcept override;
1885 
1886  [[nodiscard]] std::string
1887  debug_string() const override;
1888 
1889  [[nodiscard]] std::unique_ptr<Operation>
1890  copy() const override;
1891 
1892  static std::unique_ptr<llvm::ThreeAddressCode>
1893  create(std::shared_ptr<const jlm::rvsdg::Type> type)
1894  {
1895  auto op = std::make_unique<ConstantAggregateZeroOperation>(std::move(type));
1896  return ThreeAddressCode::create(std::move(op), {});
1897  }
1898 
1899  static jlm::rvsdg::Output *
1900  Create(rvsdg::Region & region, std::shared_ptr<const jlm::rvsdg::Type> type)
1901  {
1902  return rvsdg::CreateOpNode<ConstantAggregateZeroOperation>(region, std::move(type)).output(0);
1903  }
1904 };
1905 
1907 {
1908 public:
1909  ~ExtractElementOperation() noexcept override;
1910 
1912  const std::shared_ptr<const VectorType> & vtype,
1913  const std::shared_ptr<const jlm::rvsdg::BitType> & btype)
1914  : SimpleOperation({ vtype, btype }, { vtype->Type() })
1915  {}
1916 
1917  bool
1918  operator==(const Operation & other) const noexcept override;
1919 
1920  [[nodiscard]] std::string
1921  debug_string() const override;
1922 
1923  [[nodiscard]] std::unique_ptr<Operation>
1924  copy() const override;
1925 
1926  static inline std::unique_ptr<llvm::ThreeAddressCode>
1927  create(const llvm::Variable * vector, const llvm::Variable * index)
1928  {
1929  auto vt = std::dynamic_pointer_cast<const VectorType>(vector->Type());
1930  if (!vt)
1931  throw util::Error("expected vector type.");
1932 
1933  auto bt = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(index->Type());
1934  if (!bt)
1935  throw util::Error("expected bit type.");
1936 
1937  auto op = std::make_unique<ExtractElementOperation>(vt, bt);
1938  return ThreeAddressCode::create(std::move(op), { vector, index });
1939  }
1940 };
1941 
1943 {
1944 public:
1945  ~ShuffleVectorOperation() noexcept override;
1946 
1948  const std::shared_ptr<const FixedVectorType> & v,
1949  const std::vector<int> & mask)
1950  : SimpleOperation({ v, v }, { v }),
1951  Mask_(mask)
1952  {}
1953 
1955  const std::shared_ptr<const ScalableVectorType> & v,
1956  const std::vector<int> & mask)
1957  : SimpleOperation({ v, v }, { v }),
1958  Mask_(mask)
1959  {}
1960 
1961  bool
1962  operator==(const Operation & other) const noexcept override;
1963 
1964  [[nodiscard]] std::string
1965  debug_string() const override;
1966 
1967  [[nodiscard]] std::unique_ptr<Operation>
1968  copy() const override;
1969 
1970  const ::llvm::ArrayRef<int>
1971  Mask() const
1972  {
1973  return Mask_;
1974  }
1975 
1976  static std::unique_ptr<llvm::ThreeAddressCode>
1977  create(const Variable * v1, const Variable * v2, const std::vector<int> & mask)
1978  {
1979  if (is<FixedVectorType>(v1->type()) && is<FixedVectorType>(v2->type()))
1980  return CreateShuffleVectorTac<FixedVectorType>(v1, v2, mask);
1981 
1982  if (is<ScalableVectorType>(v1->type()) && is<ScalableVectorType>(v2->type()))
1983  return CreateShuffleVectorTac<ScalableVectorType>(v1, v2, mask);
1984 
1985  throw util::Error("Expected vector types as operands.");
1986  }
1987 
1988 private:
1989  template<typename T>
1990  static std::unique_ptr<ThreeAddressCode>
1991  CreateShuffleVectorTac(const Variable * v1, const Variable * v2, const std::vector<int> & mask)
1992  {
1993  auto vt = std::static_pointer_cast<const T>(v1->Type());
1994  auto op = std::make_unique<ShuffleVectorOperation>(vt, mask);
1995  return ThreeAddressCode::create(std::move(op), { v1, v2 });
1996  }
1997 
1998  std::vector<int> Mask_;
1999 };
2000 
2002 {
2003 public:
2004  ~ConstantVectorOperation() noexcept override;
2005 
2006  explicit ConstantVectorOperation(const std::shared_ptr<const VectorType> & vt)
2007  : SimpleOperation({ vt->size(), vt->Type() }, { vt })
2008  {}
2009 
2010  bool
2011  operator==(const Operation & other) const noexcept override;
2012 
2013  [[nodiscard]] std::string
2014  debug_string() const override;
2015 
2016  [[nodiscard]] std::unique_ptr<Operation>
2017  copy() const override;
2018 
2019  static inline std::unique_ptr<llvm::ThreeAddressCode>
2021  const std::vector<const Variable *> & operands,
2022  const std::shared_ptr<const jlm::rvsdg::Type> & type)
2023  {
2024  auto vt = std::dynamic_pointer_cast<const VectorType>(type);
2025  if (!vt)
2026  throw util::Error("expected vector type.");
2027 
2028  auto op = std::make_unique<ConstantVectorOperation>(vt);
2029  return ThreeAddressCode::create(std::move(op), operands);
2030  }
2031 };
2032 
2034 {
2035 public:
2036  ~InsertElementOperation() noexcept override;
2037 
2039  const std::shared_ptr<const VectorType> & vectype,
2040  const std::shared_ptr<const jlm::rvsdg::Type> & vtype,
2041  const std::shared_ptr<const jlm::rvsdg::BitType> & btype)
2042  : SimpleOperation({ vectype, vtype, btype }, { vectype })
2043  {
2044  if (vectype->type() != *vtype)
2045  {
2046  auto received = vtype->debug_string();
2047  auto expected = vectype->type().debug_string();
2048  throw util::Error(jlm::util::strfmt("expected ", expected, ", got ", received));
2049  }
2050  }
2051 
2052  bool
2053  operator==(const Operation & other) const noexcept override;
2054 
2055  [[nodiscard]] std::string
2056  debug_string() const override;
2057 
2058  [[nodiscard]] std::unique_ptr<Operation>
2059  copy() const override;
2060 
2061  static inline std::unique_ptr<llvm::ThreeAddressCode>
2062  create(const llvm::Variable * vector, const llvm::Variable * value, const llvm::Variable * index)
2063  {
2064  auto vct = std::dynamic_pointer_cast<const VectorType>(vector->Type());
2065  if (!vct)
2066  throw util::Error("expected vector type.");
2067 
2068  auto vt = value->Type();
2069  if (vt->Kind() != rvsdg::TypeKind::Value)
2070  throw util::Error("expected value type.");
2071 
2072  auto bt = std::dynamic_pointer_cast<const jlm::rvsdg::BitType>(index->Type());
2073  if (!bt)
2074  throw util::Error("expected bit type.");
2075 
2076  auto op = std::make_unique<InsertElementOperation>(vct, vt, bt);
2077  return ThreeAddressCode::create(std::move(op), { vector, value, index });
2078  }
2079 };
2080 
2082 {
2083 public:
2084  ~VectorUnaryOperation() noexcept override;
2085 
2087  const rvsdg::UnaryOperation & op,
2088  const std::shared_ptr<const VectorType> & operand,
2089  const std::shared_ptr<const VectorType> & result)
2090  : SimpleOperation({ operand }, { result }),
2091  op_(op.copy())
2092  {
2093  if (operand->type() != *op.argument(0))
2094  {
2095  auto received = operand->type().debug_string();
2096  auto expected = op.argument(0)->debug_string();
2097  throw util::Error(jlm::util::strfmt("expected ", expected, ", got ", received));
2098  }
2099 
2100  if (result->type() != *op.result(0))
2101  {
2102  auto received = result->type().debug_string();
2103  auto expected = op.result(0)->debug_string();
2104  throw util::Error(jlm::util::strfmt("expected ", expected, ", got ", received));
2105  }
2106  }
2107 
2109  : SimpleOperation(other),
2110  op_(other.op_->copy())
2111  {}
2112 
2114  : SimpleOperation(other),
2115  op_(std::move(other.op_))
2116  {}
2117 
2120  {
2121  if (this != &other)
2122  op_ = other.op_->copy();
2123 
2124  return *this;
2125  }
2126 
2128  operator=(VectorUnaryOperation && other) noexcept
2129  {
2130  if (this != &other)
2131  op_ = std::move(other.op_);
2132 
2133  return *this;
2134  }
2135 
2136  const rvsdg::UnaryOperation &
2137  operation() const noexcept
2138  {
2139  return *static_cast<const rvsdg::UnaryOperation *>(op_.get());
2140  }
2141 
2142  bool
2143  operator==(const Operation & other) const noexcept override;
2144 
2145  [[nodiscard]] std::string
2146  debug_string() const override;
2147 
2148  [[nodiscard]] std::unique_ptr<Operation>
2149  copy() const override;
2150 
2151  static inline std::unique_ptr<llvm::ThreeAddressCode>
2153  const rvsdg::UnaryOperation & unop,
2154  const llvm::Variable * operand,
2155  const std::shared_ptr<const jlm::rvsdg::Type> & type)
2156  {
2157  auto vct1 = std::dynamic_pointer_cast<const VectorType>(operand->Type());
2158  auto vct2 = std::dynamic_pointer_cast<const VectorType>(type);
2159  if (!vct1 || !vct2)
2160  throw util::Error("expected vector type.");
2161 
2162  auto op = std::make_unique<VectorUnaryOperation>(unop, vct1, vct2);
2163  return ThreeAddressCode::create(std::move(op), { operand });
2164  }
2165 
2166 private:
2167  std::unique_ptr<Operation> op_;
2168 };
2169 
2171 {
2172 public:
2173  ~VectorBinaryOperation() noexcept override;
2174 
2176  const rvsdg::BinaryOperation & binop,
2177  const std::shared_ptr<const VectorType> & op1,
2178  const std::shared_ptr<const VectorType> & op2,
2179  const std::shared_ptr<const VectorType> & result)
2180  : SimpleOperation({ op1, op2 }, { result }),
2181  op_(binop.copy())
2182  {
2183  if (*op1 != *op2)
2184  throw util::Error("expected the same vector types.");
2185 
2186  if (op1->type() != *binop.argument(0))
2187  {
2188  auto received = op1->type().debug_string();
2189  auto expected = binop.argument(0)->debug_string();
2190  throw util::Error(jlm::util::strfmt("expected ", expected, ", got ", received));
2191  }
2192 
2193  if (result->type() != *binop.result(0))
2194  {
2195  auto received = result->type().debug_string();
2196  auto expected = binop.result(0)->debug_string();
2197  throw util::Error(jlm::util::strfmt("expected ", expected, ", got ", received));
2198  }
2199  }
2200 
2202  : SimpleOperation(other),
2203  op_(other.op_->copy())
2204  {}
2205 
2207  : SimpleOperation(other),
2208  op_(std::move(other.op_))
2209  {}
2210 
2213  {
2214  if (this != &other)
2215  op_ = other.op_->copy();
2216 
2217  return *this;
2218  }
2219 
2222  {
2223  if (this != &other)
2224  op_ = std::move(other.op_);
2225 
2226  return *this;
2227  }
2228 
2229  const rvsdg::BinaryOperation &
2230  operation() const noexcept
2231  {
2232  return *static_cast<const rvsdg::BinaryOperation *>(op_.get());
2233  }
2234 
2235  bool
2236  operator==(const Operation & other) const noexcept override;
2237 
2238  [[nodiscard]] std::string
2239  debug_string() const override;
2240 
2241  [[nodiscard]] std::unique_ptr<Operation>
2242  copy() const override;
2243 
2244  static inline std::unique_ptr<llvm::ThreeAddressCode>
2246  const rvsdg::BinaryOperation & binop,
2247  const llvm::Variable * op1,
2248  const llvm::Variable * op2,
2249  const std::shared_ptr<const jlm::rvsdg::Type> & type)
2250  {
2251  auto vct1 = std::dynamic_pointer_cast<const VectorType>(op1->Type());
2252  auto vct2 = std::dynamic_pointer_cast<const VectorType>(op2->Type());
2253  auto vct3 = std::dynamic_pointer_cast<const VectorType>(type);
2254  if (!vct1 || !vct2 || !vct3)
2255  throw util::Error("expected vector type.");
2256 
2257  auto op = std::make_unique<VectorBinaryOperation>(binop, vct1, vct2, vct3);
2258  return ThreeAddressCode::create(std::move(op), { op1, op2 });
2259  }
2260 
2261 private:
2262  std::unique_ptr<Operation> op_;
2263 };
2264 
2266 {
2267 public:
2268  ~ConstantDataVectorOperation() noexcept override;
2269 
2270 private:
2271  explicit ConstantDataVectorOperation(const std::shared_ptr<const VectorType> & vt)
2272  : SimpleOperation({ vt->size(), vt->Type() }, { vt })
2273  {}
2274 
2275 public:
2276  bool
2277  operator==(const Operation & other) const noexcept override;
2278 
2279  [[nodiscard]] std::string
2280  debug_string() const override;
2281 
2282  [[nodiscard]] std::unique_ptr<Operation>
2283  copy() const override;
2284 
2285  size_t
2286  size() const noexcept
2287  {
2288  return std::static_pointer_cast<const VectorType>(result(0))->size();
2289  }
2290 
2291  const jlm::rvsdg::Type &
2292  type() const noexcept
2293  {
2294  return std::static_pointer_cast<const VectorType>(result(0))->type();
2295  }
2296 
2297  static std::unique_ptr<ThreeAddressCode>
2298  Create(const std::vector<const Variable *> & elements)
2299  {
2300  if (elements.empty())
2301  throw util::Error("Expected at least one element.");
2302 
2303  auto vt = elements[0]->Type();
2304  if (vt->Kind() != rvsdg::TypeKind::Value)
2305  throw util::Error("Expected value type.");
2306 
2307  auto op = std::unique_ptr<ConstantDataVectorOperation>(
2308  new ConstantDataVectorOperation(FixedVectorType::Create(vt, elements.size())));
2309  return ThreeAddressCode::create(std::move(op), elements);
2310  }
2311 };
2312 
2314 {
2315  typedef std::vector<unsigned>::const_iterator const_iterator;
2316 
2317 public:
2318  ~ExtractValueOperation() noexcept override;
2319 
2321  const std::shared_ptr<const jlm::rvsdg::Type> & aggtype,
2322  const std::vector<unsigned> & indices)
2323  : SimpleOperation({ aggtype }, { dsttype(aggtype, indices) }),
2324  indices_(indices)
2325  {
2326  if (indices.empty())
2327  throw util::Error("expected at least one index.");
2328  }
2329 
2330  bool
2331  operator==(const Operation & other) const noexcept override;
2332 
2333  [[nodiscard]] std::string
2334  debug_string() const override;
2335 
2336  [[nodiscard]] std::unique_ptr<Operation>
2337  copy() const override;
2338 
2340  begin() const
2341  {
2342  return indices_.begin();
2343  }
2344 
2346  end() const
2347  {
2348  return indices_.end();
2349  }
2350 
2351  const jlm::rvsdg::Type &
2352  type() const noexcept
2353  {
2354  return *argument(0);
2355  }
2356 
2357  static inline std::unique_ptr<llvm::ThreeAddressCode>
2358  create(const llvm::Variable * aggregate, const std::vector<unsigned> & indices)
2359  {
2360  auto op = std::make_unique<ExtractValueOperation>(aggregate->Type(), indices);
2361  return ThreeAddressCode::create(std::move(op), { aggregate });
2362  }
2363 
2364 private:
2365  static inline std::vector<std::shared_ptr<const rvsdg::Type>>
2367  const std::shared_ptr<const jlm::rvsdg::Type> & aggtype,
2368  const std::vector<unsigned> & indices)
2369  {
2370  std::shared_ptr<const jlm::rvsdg::Type> type = aggtype;
2371  for (const auto & index : indices)
2372  {
2373  if (auto st = std::dynamic_pointer_cast<const StructType>(type))
2374  {
2375  if (index >= st->numElements())
2376  throw util::Error("extractvalue index out of bound.");
2377 
2378  type = st->getElementType(index);
2379  }
2380  else if (auto at = std::dynamic_pointer_cast<const ArrayType>(type))
2381  {
2382  if (index >= at->nelements())
2383  throw util::Error("extractvalue index out of bound.");
2384 
2385  type = at->GetElementType();
2386  }
2387  else
2388  throw util::Error("expected struct or array type.");
2389  }
2390 
2391  return { type };
2392  }
2393 
2394  std::vector<unsigned> indices_;
2395 };
2396 
2403 {
2404 public:
2405  ~MallocOperation() noexcept override;
2406 
2407  explicit MallocOperation(std::shared_ptr<const rvsdg::BitType> type)
2408  : SimpleOperation(
2409  { std::move(type), IOStateType::Create() },
2411  {}
2412 
2413  bool
2414  operator==(const Operation & other) const noexcept override;
2415 
2416  [[nodiscard]] std::string
2417  debug_string() const override;
2418 
2419  [[nodiscard]] std::unique_ptr<Operation>
2420  copy() const override;
2421 
2422  const rvsdg::BitType &
2423  getSizeType() const noexcept
2424  {
2425  return *std::static_pointer_cast<const rvsdg::BitType>(argument(0));
2426  }
2427 
2430  {
2431  JLM_ASSERT(narguments() == 2 && nresults() == 3);
2432  return rvsdg::FunctionType({ argument(0), argument(1) }, { result(0), result(1), result(2) });
2433  }
2434 
2435  static rvsdg::Input &
2436  sizeInput(const rvsdg::Node & node)
2437  {
2438  JLM_ASSERT(is<MallocOperation>(node.GetOperation()));
2439  auto & size = *node.input(0);
2440  JLM_ASSERT(is<rvsdg::BitType>(size.Type()));
2441  return size;
2442  }
2443 
2444  static rvsdg::Input &
2446  {
2447  JLM_ASSERT(is<MallocOperation>(node.GetOperation()));
2448  auto & ioState = *node.input(1);
2449  JLM_ASSERT(is<IOStateType>(ioState.Type()));
2450  return ioState;
2451  }
2452 
2453  static rvsdg::Output &
2455  {
2456  JLM_ASSERT(is<MallocOperation>(node.GetOperation()));
2457  auto & address = *node.output(0);
2458  JLM_ASSERT(is<PointerType>(address.Type()));
2459  return address;
2460  }
2461 
2462  static rvsdg::Output &
2464  {
2465  JLM_ASSERT(is<MallocOperation>(node.GetOperation()));
2466  auto & ioState = *node.output(1);
2467  JLM_ASSERT(is<IOStateType>(ioState.Type()));
2468  return ioState;
2469  }
2470 
2471  static rvsdg::Output &
2473  {
2474  JLM_ASSERT(is<MallocOperation>(node.GetOperation()));
2475  auto & memoryState = *node.output(2);
2476  JLM_ASSERT(is<MemoryStateType>(memoryState.Type()));
2477  return memoryState;
2478  }
2479 
2480  static std::unique_ptr<ThreeAddressCode>
2481  createTac(const Variable * size, const Variable * ioState)
2482  {
2483  auto bitType = checkAndExtractSizeType(size->Type());
2484  auto op = std::make_unique<MallocOperation>(std::move(bitType));
2485  return ThreeAddressCode::create(std::move(op), { size, ioState });
2486  }
2487 
2488  static rvsdg::SimpleNode &
2490  {
2491  auto bitType = checkAndExtractSizeType(size.Type());
2492  return rvsdg::CreateOpNode<MallocOperation>({ &size, &ioState }, std::move(bitType));
2493  }
2494 
2495 private:
2496  static std::shared_ptr<const rvsdg::BitType>
2497  checkAndExtractSizeType(const std::shared_ptr<const rvsdg::Type> & type)
2498  {
2499  if (auto bitType = std::dynamic_pointer_cast<const rvsdg::BitType>(type))
2500  return bitType;
2501 
2502  throw std::runtime_error("Expected bits type.");
2503  }
2504 };
2505 
2512 {
2513 public:
2514  ~FreeOperation() noexcept override;
2515 
2516  explicit FreeOperation(size_t numMemoryStates)
2517  : SimpleOperation(CreateOperandTypes(numMemoryStates), CreateResultTypes(numMemoryStates))
2518  {}
2519 
2520  bool
2521  operator==(const Operation & other) const noexcept override;
2522 
2523  [[nodiscard]] std::string
2524  debug_string() const override;
2525 
2526  [[nodiscard]] std::unique_ptr<Operation>
2527  copy() const override;
2528 
2533  [[nodiscard]] static rvsdg::Input &
2534  addressInput(const rvsdg::Node & node) noexcept
2535  {
2536  JLM_ASSERT(is<FreeOperation>(&node));
2537  const auto input = node.input(0);
2538  JLM_ASSERT(is<PointerType>(input->Type()));
2539  return *input;
2540  }
2541 
2542  [[nodiscard]] static rvsdg::Input &
2544  {
2545  JLM_ASSERT(is<MemoryStateType>(output.Type()));
2546  auto [freeNode, freeOperation] = rvsdg::TryGetSimpleNodeAndOptionalOp<FreeOperation>(output);
2547  JLM_ASSERT(freeOperation);
2548  const auto input = freeNode->input(output.index() + 1);
2549  JLM_ASSERT(is<MemoryStateType>(input->Type()));
2550  return *input;
2551  }
2552 
2553  static std::unique_ptr<llvm::ThreeAddressCode>
2555  const Variable * pointer,
2556  const std::vector<const Variable *> & memoryStates,
2557  const Variable * iOState)
2558  {
2559  std::vector<const Variable *> operands;
2560  operands.push_back(pointer);
2561  operands.insert(operands.end(), memoryStates.begin(), memoryStates.end());
2562  operands.push_back(iOState);
2563 
2564  auto operation = std::make_unique<FreeOperation>(memoryStates.size());
2565  return ThreeAddressCode::create(std::move(operation), operands);
2566  }
2567 
2568  static std::vector<jlm::rvsdg::Output *>
2570  jlm::rvsdg::Output * pointer,
2571  const std::vector<jlm::rvsdg::Output *> & memoryStates,
2572  jlm::rvsdg::Output * iOState)
2573  {
2574  std::vector<jlm::rvsdg::Output *> operands;
2575  operands.push_back(pointer);
2576  operands.insert(operands.end(), memoryStates.begin(), memoryStates.end());
2577  operands.push_back(iOState);
2578 
2579  return outputs(&rvsdg::CreateOpNode<FreeOperation>(operands, memoryStates.size()));
2580  }
2581 
2582 private:
2583  static std::vector<std::shared_ptr<const rvsdg::Type>>
2584  CreateOperandTypes(size_t numMemoryStates)
2585  {
2586  std::vector<std::shared_ptr<const rvsdg::Type>> memoryStates(
2587  numMemoryStates,
2589 
2590  std::vector<std::shared_ptr<const rvsdg::Type>> types({ PointerType::Create() });
2591  types.insert(types.end(), memoryStates.begin(), memoryStates.end());
2592  types.emplace_back(IOStateType::Create());
2593 
2594  return types;
2595  }
2596 
2597  static std::vector<std::shared_ptr<const rvsdg::Type>>
2598  CreateResultTypes(size_t numMemoryStates)
2599  {
2600  std::vector<std::shared_ptr<const rvsdg::Type>> types(
2601  numMemoryStates,
2603  types.emplace_back(IOStateType::Create());
2604 
2605  return types;
2606  }
2607 };
2608 
2609 }
2610 
2611 #endif
static std::shared_ptr< const ArrayType > Create(std::shared_ptr< const Type > type, size_t nelements)
Definition: types.hpp:98
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:61
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *rhs, const Variable *lhs)
Definition: operators.hpp:117
~AssignmentOperation() noexcept override
std::string debug_string() const override
Definition: operators.cpp:55
AssignmentOperation(const AssignmentOperation &)=default
AssignmentOperation(AssignmentOperation &&)=default
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:48
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:718
std::string debug_string() const override
Definition: operators.cpp:725
static std::pair< std::shared_ptr< const jlm::rvsdg::Type >, std::shared_ptr< const jlm::rvsdg::Type > > check_types(const std::shared_ptr< const jlm::rvsdg::Type > &otype, const std::shared_ptr< const jlm::rvsdg::Type > &rtype)
Definition: operators.hpp:1519
BitCastOperation(const BitCastOperation &)=default
BitCastOperation(Operation &&)=delete
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:736
static jlm::rvsdg::Output * create(jlm::rvsdg::Output *operand, std::shared_ptr< const jlm::rvsdg::Type > rtype)
Definition: operators.hpp:1511
jlm::rvsdg::Output * reduce_operand(jlm::rvsdg::unop_reduction_path_t path, jlm::rvsdg::Output *output) const override
Definition: operators.cpp:748
BitCastOperation & operator=(Operation &&)=delete
jlm::rvsdg::unop_reduction_path_t can_reduce_operand(const jlm::rvsdg::Output *output) const noexcept override
Definition: operators.cpp:742
BitCastOperation & operator=(const Operation &)=delete
~BitCastOperation() noexcept override
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: operators.hpp:1502
std::string debug_string() const override
Definition: operators.cpp:209
size_t nalternatives() const noexcept
Definition: operators.hpp:412
~BranchOperation() noexcept override
static std::unique_ptr< llvm::ThreeAddressCode > create(size_t nalternatives, const Variable *operand)
Definition: operators.hpp:418
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:215
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:202
static std::unique_ptr< llvm::ThreeAddressCode > create(std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: operators.hpp:1893
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:913
~ConstantAggregateZeroOperation() noexcept override
static jlm::rvsdg::Output * Create(rvsdg::Region &region, std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: operators.hpp:1900
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:900
std::string debug_string() const override
Definition: operators.cpp:907
const jlm::rvsdg::Type & type() const noexcept
Definition: operators.hpp:1832
~ConstantArrayOperation() noexcept override
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:892
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:879
std::string debug_string() const override
Definition: operators.cpp:886
static rvsdg::Output * Create(const std::vector< rvsdg::Output * > &operands)
Definition: operators.hpp:1852
static std::unique_ptr< llvm::ThreeAddressCode > create(const std::vector< const Variable * > &elements)
Definition: operators.hpp:1838
size_t size() const noexcept
Definition: operators.hpp:1826
static jlm::rvsdg::Output * Create(const std::vector< jlm::rvsdg::Output * > &elements)
Definition: operators.hpp:668
static std::unique_ptr< llvm::ThreeAddressCode > create(const std::vector< const Variable * > &elements)
Definition: operators.hpp:654
const jlm::rvsdg::Type & type() const noexcept
Definition: operators.hpp:648
size_t size() const noexcept
Definition: operators.hpp:642
~ConstantDataArray() noexcept override
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:323
std::string debug_string() const override
Definition: operators.cpp:317
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:310
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:1048
static std::unique_ptr< ThreeAddressCode > Create(const std::vector< const Variable * > &elements)
Definition: operators.hpp:2298
const jlm::rvsdg::Type & type() const noexcept
Definition: operators.hpp:2292
~ConstantDataVectorOperation() noexcept override
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:1061
ConstantDataVectorOperation(const std::shared_ptr< const VectorType > &vt)
Definition: operators.hpp:2271
std::string debug_string() const override
Definition: operators.cpp:1055
~ConstantFP() noexcept override
const fpsize & size() const noexcept
Definition: operators.hpp:880
ConstantFP(std::shared_ptr< const FloatingPointType > fpt, const ::llvm::APFloat &constant)
Definition: operators.hpp:859
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:445
::llvm::APFloat constant_
Definition: operators.hpp:899
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:424
const ::llvm::APFloat & constant() const noexcept
Definition: operators.hpp:874
std::string debug_string() const override
Definition: operators.cpp:431
static std::unique_ptr< llvm::ThreeAddressCode > create(const ::llvm::APFloat &constant, const std::shared_ptr< const jlm::rvsdg::Type > &type)
Definition: operators.hpp:886
ConstantPointerNullOperation class.
Definition: operators.hpp:430
std::string debug_string() const override
Definition: operators.cpp:230
static jlm::rvsdg::Output * Create(rvsdg::Region *region, std::shared_ptr< const rvsdg::Type > type)
Definition: operators.hpp:461
static const std::shared_ptr< const PointerType > CheckAndExtractType(std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: operators.hpp:469
static std::unique_ptr< llvm::ThreeAddressCode > Create(std::shared_ptr< const rvsdg::Type > type)
Definition: operators.hpp:454
const PointerType & GetPointerType() const noexcept
Definition: operators.hpp:448
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:223
~ConstantPointerNullOperation() noexcept override
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:236
static rvsdg::Output & Create(rvsdg::Region &, const std::vector< rvsdg::Output * > &operands, std::shared_ptr< const rvsdg::Type > resultType)
Definition: operators.hpp:1569
static std::vector< std::shared_ptr< const rvsdg::Type > > create_srctypes(const StructType &type)
Definition: operators.hpp:1580
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:759
static std::shared_ptr< const StructType > CheckAndExtractStructType(std::shared_ptr< const rvsdg::Type > type)
Definition: operators.hpp:1590
std::string debug_string() const override
Definition: operators.cpp:766
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:772
ConstantStruct(std::shared_ptr< const StructType > type)
Definition: operators.hpp:1538
static std::unique_ptr< llvm::ThreeAddressCode > create(const std::vector< const Variable * > &elements, const std::shared_ptr< const jlm::rvsdg::Type > &type)
Definition: operators.hpp:1558
const StructType & type() const noexcept
Definition: operators.hpp:1552
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:963
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:976
static std::unique_ptr< llvm::ThreeAddressCode > create(const std::vector< const Variable * > &operands, const std::shared_ptr< const jlm::rvsdg::Type > &type)
Definition: operators.hpp:2020
~ConstantVectorOperation() noexcept override
std::string debug_string() const override
Definition: operators.cpp:970
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:181
std::string debug_string() const override
Definition: operators.cpp:188
~ControlToIntOperation() noexcept override
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, const std::shared_ptr< const jlm::rvsdg::Type > &type)
Definition: operators.hpp:378
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:194
std::string debug_string() const override
Definition: operators.cpp:928
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:921
~ExtractElementOperation() noexcept override
static std::unique_ptr< llvm::ThreeAddressCode > create(const llvm::Variable *vector, const llvm::Variable *index)
Definition: operators.hpp:1927
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:934
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:1069
std::vector< unsigned > indices_
Definition: operators.hpp:2394
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:1082
const_iterator end() const
Definition: operators.hpp:2346
const_iterator begin() const
Definition: operators.hpp:2340
std::string debug_string() const override
Definition: operators.cpp:1076
static std::vector< std::shared_ptr< const rvsdg::Type > > dsttype(const std::shared_ptr< const jlm::rvsdg::Type > &aggtype, const std::vector< unsigned > &indices)
Definition: operators.hpp:2366
const jlm::rvsdg::Type & type() const noexcept
Definition: operators.hpp:2352
~ExtractValueOperation() noexcept override
std::vector< unsigned >::const_iterator const_iterator
Definition: operators.hpp:2315
static std::unique_ptr< llvm::ThreeAddressCode > create(const llvm::Variable *aggregate, const std::vector< unsigned > &indices)
Definition: operators.hpp:2358
const fpsize & size() const noexcept
Definition: operators.hpp:1176
const llvm::fpop & fpop() const noexcept
Definition: operators.hpp:1170
std::string debug_string() const override
Definition: operators.cpp:552
jlm::rvsdg::binop_reduction_path_t can_reduce_operand_pair(const jlm::rvsdg::Output *op1, const jlm::rvsdg::Output *op2) const noexcept override
Definition: operators.cpp:571
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:565
static std::unique_ptr< llvm::ThreeAddressCode > create(const llvm::fpop &fpop, const Variable *op1, const Variable *op2)
Definition: operators.hpp:1182
FBinaryOperation(const llvm::fpop &op, const std::shared_ptr< const FloatingPointType > &fpt)
Definition: operators.hpp:1145
jlm::rvsdg::Output * reduce_operand_pair(jlm::rvsdg::binop_reduction_path_t path, jlm::rvsdg::Output *op1, jlm::rvsdg::Output *op2) const override
Definition: operators.cpp:578
~FBinaryOperation() noexcept override
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:545
jlm::rvsdg::binop_reduction_path_t can_reduce_operand_pair(const jlm::rvsdg::Output *op1, const jlm::rvsdg::Output *op2) const noexcept override
Definition: operators.cpp:488
const fpcmp & cmp() const noexcept
Definition: operators.hpp:961
~FCmpOperation() noexcept override
FCmpOperation(const fpcmp &cmp, const std::shared_ptr< const FloatingPointType > &fpt)
Definition: operators.hpp:936
std::string debug_string() const override
Definition: operators.cpp:460
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:453
jlm::rvsdg::Output * reduce_operand_pair(jlm::rvsdg::binop_reduction_path_t path, jlm::rvsdg::Output *op1, jlm::rvsdg::Output *op2) const override
Definition: operators.cpp:494
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:482
static std::unique_ptr< llvm::ThreeAddressCode > create(const fpcmp &cmp, const Variable *op1, const Variable *op2)
Definition: operators.hpp:973
const fpsize & size() const noexcept
Definition: operators.hpp:967
const fpsize & size() const noexcept
Definition: operators.hpp:1308
jlm::rvsdg::Output * reduce_operand(jlm::rvsdg::unop_reduction_path_t path, jlm::rvsdg::Output *output) const override
Definition: operators.cpp:647
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:622
jlm::rvsdg::unop_reduction_path_t can_reduce_operand(const jlm::rvsdg::Output *output) const noexcept override
Definition: operators.cpp:641
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:635
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand)
Definition: operators.hpp:1314
~FNegOperation() noexcept override
std::string debug_string() const override
Definition: operators.cpp:629
FNegOperation(const std::shared_ptr< const FloatingPointType > &fpt)
Definition: operators.hpp:1287
FPExtOperation(std::shared_ptr< const jlm::rvsdg::Type > srctype, std::shared_ptr< const jlm::rvsdg::Type > dsttype)
Definition: operators.hpp:1217
const fpsize & dstsize() const noexcept
Definition: operators.hpp:1257
~FPExtOperation() noexcept override
std::string debug_string() const override
Definition: operators.cpp:596
jlm::rvsdg::Output * reduce_operand(jlm::rvsdg::unop_reduction_path_t path, jlm::rvsdg::Output *output) const override
Definition: operators.cpp:614
jlm::rvsdg::unop_reduction_path_t can_reduce_operand(const jlm::rvsdg::Output *output) const noexcept override
Definition: operators.cpp:608
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:589
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:602
const fpsize & srcsize() const noexcept
Definition: operators.hpp:1251
FPExtOperation(const std::shared_ptr< const FloatingPointType > &srctype, const std::shared_ptr< const FloatingPointType > &dsttype)
Definition: operators.hpp:1208
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, const std::shared_ptr< const jlm::rvsdg::Type > &type)
Definition: operators.hpp:1263
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:655
FPTruncOperation(const std::shared_ptr< const FloatingPointType > &srctype, const std::shared_ptr< const FloatingPointType > &dsttype)
Definition: operators.hpp:1338
const fpsize & dstsize() const noexcept
Definition: operators.hpp:1388
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: operators.hpp:1394
const fpsize & srcsize() const noexcept
Definition: operators.hpp:1382
jlm::rvsdg::unop_reduction_path_t can_reduce_operand(const jlm::rvsdg::Output *output) const noexcept override
Definition: operators.cpp:674
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:668
std::string debug_string() const override
Definition: operators.cpp:662
~FPTruncOperation() noexcept override
jlm::rvsdg::Output * reduce_operand(jlm::rvsdg::unop_reduction_path_t path, jlm::rvsdg::Output *output) const override
Definition: operators.cpp:680
FPTruncOperation(std::shared_ptr< const jlm::rvsdg::Type > srctype, std::shared_ptr< const jlm::rvsdg::Type > dsttype)
Definition: operators.hpp:1347
static std::shared_ptr< const FixedVectorType > Create(std::shared_ptr< const rvsdg::Type > type, size_t size)
Definition: types.hpp:402
jlm::rvsdg::Output * reduce_operand(jlm::rvsdg::unop_reduction_path_t path, jlm::rvsdg::Output *output) const override
Definition: operators.cpp:172
jlm::rvsdg::unop_reduction_path_t can_reduce_operand(const jlm::rvsdg::Output *output) const noexcept override
Definition: operators.cpp:166
FloatingPointToSignedIntegerOperation(std::shared_ptr< const jlm::rvsdg::Type > srctype, std::shared_ptr< const jlm::rvsdg::Type > dsttype)
Definition: operators.hpp:311
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:147
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, const std::shared_ptr< const jlm::rvsdg::Type > &type)
Definition: operators.hpp:342
FloatingPointToSignedIntegerOperation(std::shared_ptr< const FloatingPointType > fpt, std::shared_ptr< const jlm::rvsdg::BitType > type)
Definition: operators.hpp:305
std::string debug_string() const override
Definition: operators.cpp:154
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:160
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:112
FloatingPointToUnsignedIntegerOperation(std::shared_ptr< const jlm::rvsdg::Type > srctype, std::shared_ptr< const jlm::rvsdg::Type > dsttype)
Definition: operators.hpp:247
jlm::rvsdg::Output * reduce_operand(jlm::rvsdg::unop_reduction_path_t path, jlm::rvsdg::Output *output) const override
Definition: operators.cpp:137
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, const std::shared_ptr< const jlm::rvsdg::Type > &type)
Definition: operators.hpp:278
jlm::rvsdg::unop_reduction_path_t can_reduce_operand(const jlm::rvsdg::Output *output) const noexcept override
Definition: operators.cpp:131
FloatingPointToUnsignedIntegerOperation(std::shared_ptr< const FloatingPointType > fpt, std::shared_ptr< const jlm::rvsdg::BitType > type)
Definition: operators.hpp:241
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:125
static std::shared_ptr< const FloatingPointType > Create(fpsize size)
Definition: types.cpp:117
static rvsdg::Input & addressInput(const rvsdg::Node &node) noexcept
Definition: operators.hpp:2534
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:1113
static std::vector< std::shared_ptr< const rvsdg::Type > > CreateResultTypes(size_t numMemoryStates)
Definition: operators.hpp:2598
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:1126
static std::vector< std::shared_ptr< const rvsdg::Type > > CreateOperandTypes(size_t numMemoryStates)
Definition: operators.hpp:2584
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *pointer, const std::vector< const Variable * > &memoryStates, const Variable *iOState)
Definition: operators.hpp:2554
static rvsdg::Input & mapMemoryStateOutputToInput(rvsdg::Output &output) noexcept
Definition: operators.hpp:2543
~FreeOperation() noexcept override
static std::vector< jlm::rvsdg::Output * > Create(jlm::rvsdg::Output *pointer, const std::vector< jlm::rvsdg::Output * > &memoryStates, jlm::rvsdg::Output *iOState)
Definition: operators.hpp:2569
std::string debug_string() const override
Definition: operators.cpp:1120
static std::shared_ptr< const IOStateType > Create()
Definition: types.cpp:343
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:984
std::string debug_string() const override
Definition: operators.cpp:992
~InsertElementOperation() noexcept override
static std::unique_ptr< llvm::ThreeAddressCode > create(const llvm::Variable *vector, const llvm::Variable *value, const llvm::Variable *index)
Definition: operators.hpp:2062
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:998
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:257
std::string debug_string() const override
Definition: operators.cpp:251
size_t nbits() const noexcept
Definition: operators.hpp:520
jlm::rvsdg::unop_reduction_path_t can_reduce_operand(const jlm::rvsdg::Output *output) const noexcept override
Definition: operators.cpp:263
~IntegerToPointerOperation() noexcept override
static jlm::rvsdg::Output * create(jlm::rvsdg::Output *operand, std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: operators.hpp:541
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:244
jlm::rvsdg::Output * reduce_operand(jlm::rvsdg::unop_reduction_path_t path, jlm::rvsdg::Output *output) const override
Definition: operators.cpp:269
IntegerToPointerOperation(std::shared_ptr< const jlm::rvsdg::Type > srctype, std::shared_ptr< const jlm::rvsdg::Type > dsttype)
Definition: operators.hpp:489
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *argument, std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: operators.hpp:526
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:1090
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:1103
static rvsdg::Output & ioStateOutput(const rvsdg::Node &node)
Definition: operators.hpp:2463
static rvsdg::Input & ioStateInput(const rvsdg::Node &node)
Definition: operators.hpp:2445
static std::unique_ptr< ThreeAddressCode > createTac(const Variable *size, const Variable *ioState)
Definition: operators.hpp:2481
std::string debug_string() const override
Definition: operators.cpp:1097
~MallocOperation() noexcept override
static rvsdg::Input & sizeInput(const rvsdg::Node &node)
Definition: operators.hpp:2436
static rvsdg::SimpleNode & createNode(rvsdg::Output &size, rvsdg::Output &ioState)
Definition: operators.hpp:2489
static rvsdg::Output & addressOutput(const rvsdg::Node &node)
Definition: operators.hpp:2454
static rvsdg::Output & memoryStateOutput(const rvsdg::Node &node)
Definition: operators.hpp:2472
static std::shared_ptr< const rvsdg::BitType > checkAndExtractSizeType(const std::shared_ptr< const rvsdg::Type > &type)
Definition: operators.hpp:2497
const rvsdg::BitType & getSizeType() const noexcept
Definition: operators.hpp:2423
rvsdg::FunctionType getFunctionType() const
Definition: operators.hpp:2429
static std::shared_ptr< const MemoryStateType > Create()
Definition: types.cpp:379
PointerType class.
Definition: types.hpp:25
static std::shared_ptr< const PointerType > Create()
Definition: types.cpp:45
PoisonValueOperation class.
Definition: operators.hpp:1061
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:524
static std::shared_ptr< const jlm::rvsdg::Type > CheckAndConvertType(const std::shared_ptr< const jlm::rvsdg::Type > &type)
Definition: operators.hpp:1113
PoisonValueOperation(PoisonValueOperation &&)=delete
~PoisonValueOperation() noexcept override
PoisonValueOperation & operator=(PoisonValueOperation &&)=delete
std::string debug_string() const override
Definition: operators.cpp:531
const jlm::rvsdg::Type & GetType() const noexcept
Definition: operators.hpp:1089
PoisonValueOperation & operator=(const PoisonValueOperation &)=delete
static std::unique_ptr< llvm::ThreeAddressCode > Create(const std::shared_ptr< const jlm::rvsdg::Type > &type)
Definition: operators.hpp:1095
PoisonValueOperation(const PoisonValueOperation &)=default
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:537
static jlm::rvsdg::Output * Create(rvsdg::Region *region, const std::shared_ptr< const jlm::rvsdg::Type > &type)
Definition: operators.hpp:1104
~PtrCmpOperation() noexcept override
llvm::cmp cmp() const noexcept
Definition: operators.hpp:724
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:331
static std::unique_ptr< llvm::ThreeAddressCode > create(const llvm::cmp &cmp, const Variable *op1, const Variable *op2)
Definition: operators.hpp:730
jlm::rvsdg::binop_reduction_path_t can_reduce_operand_pair(const jlm::rvsdg::Output *op1, const jlm::rvsdg::Output *op2) const noexcept override
Definition: operators.cpp:358
std::string debug_string() const override
Definition: operators.cpp:338
jlm::rvsdg::Output * reduce_operand_pair(jlm::rvsdg::binop_reduction_path_t path, jlm::rvsdg::Output *op1, jlm::rvsdg::Output *op2) const override
Definition: operators.cpp:365
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:352
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:290
PtrToIntOperation(std::shared_ptr< const jlm::rvsdg::Type > srctype, std::shared_ptr< const jlm::rvsdg::Type > dsttype)
Definition: operators.hpp:566
std::string debug_string() const override
Definition: operators.cpp:284
jlm::rvsdg::unop_reduction_path_t can_reduce_operand(const jlm::rvsdg::Output *output) const noexcept override
Definition: operators.cpp:296
jlm::rvsdg::Output * reduce_operand(jlm::rvsdg::unop_reduction_path_t path, jlm::rvsdg::Output *output) const override
Definition: operators.cpp:302
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *argument, const std::shared_ptr< const jlm::rvsdg::Type > &type)
Definition: operators.hpp:603
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:277
~PtrToIntOperation() noexcept override
size_t nbits() const noexcept
Definition: operators.hpp:597
~SIToFPOperation() noexcept override
jlm::rvsdg::unop_reduction_path_t can_reduce_operand(const jlm::rvsdg::Output *output) const noexcept override
Definition: operators.cpp:865
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, const std::shared_ptr< const jlm::rvsdg::Type > &type)
Definition: operators.hpp:1789
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:859
jlm::rvsdg::Output * reduce_operand(jlm::rvsdg::unop_reduction_path_t path, jlm::rvsdg::Output *output) const override
Definition: operators.cpp:871
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:846
std::string debug_string() const override
Definition: operators.cpp:853
SIToFPOperation(std::shared_ptr< const jlm::rvsdg::Type > srctype, std::shared_ptr< const jlm::rvsdg::Type > dsttype)
Definition: operators.hpp:1758
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:69
const std::shared_ptr< const jlm::rvsdg::Type > & Type() const noexcept
Definition: operators.hpp:152
std::string debug_string() const override
Definition: operators.cpp:76
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:82
static std::unique_ptr< llvm::ThreeAddressCode > create(const llvm::Variable *p, const llvm::Variable *t, const llvm::Variable *f)
Definition: operators.hpp:158
~SelectOperation() noexcept override
const jlm::rvsdg::Type & type() const noexcept
Definition: operators.hpp:146
const ::llvm::ArrayRef< int > Mask() const
Definition: operators.hpp:1971
std::string debug_string() const override
Definition: operators.cpp:949
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:955
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *v1, const Variable *v2, const std::vector< int > &mask)
Definition: operators.hpp:1977
ShuffleVectorOperation(const std::shared_ptr< const ScalableVectorType > &v, const std::vector< int > &mask)
Definition: operators.hpp:1954
static std::unique_ptr< ThreeAddressCode > CreateShuffleVectorTac(const Variable *v1, const Variable *v2, const std::vector< int > &mask)
Definition: operators.hpp:1991
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:942
~ShuffleVectorOperation() noexcept override
ControlFlowGraphNode * GetIncomingNode(size_t n) const noexcept
Definition: operators.hpp:67
SsaPhiOperation(const SsaPhiOperation &)=default
static std::unique_ptr< llvm::ThreeAddressCode > create(const std::vector< std::pair< const Variable *, ControlFlowGraphNode * >> &arguments, std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: operators.hpp:74
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition: operators.hpp:61
std::string debug_string() const override
Definition: operators.cpp:25
SsaPhiOperation & operator=(SsaPhiOperation &&)=delete
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:18
SsaPhiOperation & operator=(const SsaPhiOperation &)=delete
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:40
~SsaPhiOperation() noexcept override
std::vector< ControlFlowGraphNode * > IncomingNodes_
Definition: operators.hpp:91
StructType class.
Definition: types.hpp:184
std::string debug_string() const override
Definition: types.cpp:229
size_t numElements() const noexcept
Definition: types.hpp:219
std::shared_ptr< const Type > getElementType(const size_t index) const noexcept
Definition: types.hpp:225
static std::unique_ptr< llvm::ThreeAddressCode > create(std::unique_ptr< rvsdg::SimpleOperation > operation, const std::vector< const Variable * > &operands)
Definition: tac.hpp:135
std::string debug_string() const override
Definition: operators.cpp:787
~TruncOperation() noexcept override
jlm::rvsdg::unop_reduction_path_t can_reduce_operand(const jlm::rvsdg::Output *operand) const noexcept override
Definition: operators.cpp:799
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:780
size_t ndstbits() const noexcept
Definition: operators.hpp:1655
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, const std::shared_ptr< const jlm::rvsdg::Type > &type)
Definition: operators.hpp:1661
jlm::rvsdg::Output * reduce_operand(jlm::rvsdg::unop_reduction_path_t path, jlm::rvsdg::Output *operand) const override
Definition: operators.cpp:805
TruncOperation(std::shared_ptr< const jlm::rvsdg::Type > optype, std::shared_ptr< const jlm::rvsdg::Type > restype)
Definition: operators.hpp:1615
static jlm::rvsdg::Output * create(size_t ndstbits, jlm::rvsdg::Output *operand)
Definition: operators.hpp:1676
size_t nsrcbits() const noexcept
Definition: operators.hpp:1649
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:793
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:813
std::string debug_string() const override
Definition: operators.cpp:820
UIToFPOperation(std::shared_ptr< const jlm::rvsdg::Type > optype, std::shared_ptr< const jlm::rvsdg::Type > restype)
Definition: operators.hpp:1701
jlm::rvsdg::unop_reduction_path_t can_reduce_operand(const jlm::rvsdg::Output *operand) const noexcept override
Definition: operators.cpp:832
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, const std::shared_ptr< const jlm::rvsdg::Type > &type)
Definition: operators.hpp:1732
jlm::rvsdg::Output * reduce_operand(jlm::rvsdg::unop_reduction_path_t path, jlm::rvsdg::Output *operand) const override
Definition: operators.cpp:838
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:826
~UIToFPOperation() noexcept override
UndefValueOperation class.
Definition: operators.hpp:992
UndefValueOperation & operator=(UndefValueOperation &&)=delete
~UndefValueOperation() noexcept override
static jlm::rvsdg::Output * Create(rvsdg::Region &region, std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: operators.hpp:1024
std::string debug_string() const override
Definition: operators.cpp:510
static std::unique_ptr< llvm::ThreeAddressCode > Create(std::shared_ptr< const jlm::rvsdg::Type > type, const std::string &name)
Definition: operators.hpp:1037
UndefValueOperation(const UndefValueOperation &)=default
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:516
static std::unique_ptr< llvm::ThreeAddressCode > Create(std::unique_ptr< ThreeAddressCodeVariable > result)
Definition: operators.hpp:1044
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:503
const rvsdg::Type & GetType() const noexcept
Definition: operators.hpp:1018
UndefValueOperation & operator=(const UndefValueOperation &)=delete
static std::unique_ptr< llvm::ThreeAddressCode > Create(std::shared_ptr< const jlm::rvsdg::Type > type)
Definition: operators.hpp:1030
static std::shared_ptr< const VariableArgumentType > Create()
Definition: types.cpp:180
const jlm::rvsdg::Type & type() const noexcept
Definition: variable.hpp:56
const std::shared_ptr< const jlm::rvsdg::Type > Type() const noexcept
Definition: variable.hpp:62
static rvsdg::Output * Create(rvsdg::Region &region, const std::vector< rvsdg::Output * > &operands)
Definition: operators.hpp:1447
VariadicArgumentListOperation(const VariadicArgumentListOperation &)=default
static std::unique_ptr< llvm::ThreeAddressCode > create(const std::vector< const Variable * > &arguments)
Definition: operators.hpp:1436
std::string debug_string() const override
Definition: operators.cpp:704
~VariadicArgumentListOperation() noexcept override
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:710
VariadicArgumentListOperation & operator=(VariadicArgumentListOperation &&)=delete
VariadicArgumentListOperation & operator=(const VariadicArgumentListOperation &)=delete
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:688
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:1027
std::string debug_string() const override
Definition: operators.cpp:1034
static std::unique_ptr< llvm::ThreeAddressCode > create(const rvsdg::BinaryOperation &binop, const llvm::Variable *op1, const llvm::Variable *op2, const std::shared_ptr< const jlm::rvsdg::Type > &type)
Definition: operators.hpp:2245
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:1040
VectorBinaryOperation(const VectorBinaryOperation &other)
Definition: operators.hpp:2201
const rvsdg::BinaryOperation & operation() const noexcept
Definition: operators.hpp:2230
std::unique_ptr< Operation > op_
Definition: operators.hpp:2262
~VectorBinaryOperation() noexcept override
VectorBinaryOperation & operator=(const VectorBinaryOperation &other)
Definition: operators.hpp:2212
VectorBinaryOperation & operator=(VectorBinaryOperation &&other) noexcept
Definition: operators.hpp:2221
VectorBinaryOperation(VectorBinaryOperation &&other) noexcept
Definition: operators.hpp:2206
size_t size() const noexcept
Definition: operators.hpp:200
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:103
const rvsdg::Type & type() const noexcept
Definition: operators.hpp:188
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition: operators.hpp:194
static std::unique_ptr< ThreeAddressCode > createVectorSelectTac(const Variable *p, const Variable *t, const Variable *f)
Definition: operators.hpp:220
std::string debug_string() const override
Definition: operators.cpp:97
VectorSelectOperation(const std::shared_ptr< const VectorType > &pt, const std::shared_ptr< const VectorType > &vt)
Definition: operators.hpp:171
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:90
~VectorSelectOperation() noexcept override
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *p, const Variable *t, const Variable *f)
Definition: operators.hpp:206
std::unique_ptr< Operation > op_
Definition: operators.hpp:2167
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:1006
~VectorUnaryOperation() noexcept override
VectorUnaryOperation(const VectorUnaryOperation &other)
Definition: operators.hpp:2108
static std::unique_ptr< llvm::ThreeAddressCode > create(const rvsdg::UnaryOperation &unop, const llvm::Variable *operand, const std::shared_ptr< const jlm::rvsdg::Type > &type)
Definition: operators.hpp:2152
VectorUnaryOperation & operator=(VectorUnaryOperation &&other) noexcept
Definition: operators.hpp:2128
VectorUnaryOperation & operator=(const VectorUnaryOperation &other)
Definition: operators.hpp:2119
std::string debug_string() const override
Definition: operators.cpp:1013
VectorUnaryOperation(VectorUnaryOperation &&other) noexcept
Definition: operators.hpp:2113
const rvsdg::UnaryOperation & operation() const noexcept
Definition: operators.hpp:2137
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:1019
std::string debug_string() const override
Definition: operators.cpp:383
size_t nsrcbits() const noexcept
Definition: operators.hpp:799
jlm::rvsdg::Output * reduce_operand(jlm::rvsdg::unop_reduction_path_t path, jlm::rvsdg::Output *operand) const override
Definition: operators.cpp:405
static std::unique_ptr< llvm::ThreeAddressCode > create(const Variable *operand, const std::shared_ptr< const jlm::rvsdg::Type > &type)
Definition: operators.hpp:811
bool operator==(const Operation &other) const noexcept override
Definition: operators.cpp:376
ZExtOperation(std::shared_ptr< const jlm::rvsdg::Type > srctype, std::shared_ptr< const jlm::rvsdg::Type > dsttype)
Definition: operators.hpp:765
~ZExtOperation() noexcept override
ZExtOperation(const std::shared_ptr< const jlm::rvsdg::BitType > &srctype, const std::shared_ptr< const jlm::rvsdg::BitType > &dsttype)
Definition: operators.hpp:756
static std::shared_ptr< const rvsdg::BitType > CheckAndExtractBitType(const std::shared_ptr< const rvsdg::Type > &type)
Definition: operators.hpp:836
static rvsdg::Output & Create(rvsdg::Output &operand, const std::shared_ptr< const rvsdg::Type > &resultType)
Definition: operators.hpp:822
std::unique_ptr< Operation > copy() const override
Definition: operators.cpp:389
jlm::rvsdg::unop_reduction_path_t can_reduce_operand(const jlm::rvsdg::Output *operand) const noexcept override
Definition: operators.cpp:395
size_t ndstbits() const noexcept
Definition: operators.hpp:805
BinaryOperation(const std::vector< std::shared_ptr< const jlm::rvsdg::Type >> operands, std::shared_ptr< const jlm::rvsdg::Type > result)
Definition: binary.hpp:37
static std::shared_ptr< const BitType > Create(std::size_t nbits)
Creates bit type of specified width.
Definition: type.cpp:45
static std::shared_ptr< const ControlType > Create(std::size_t nalternatives)
Instantiates control type.
Definition: control.cpp:50
Function type class.
virtual const Operation & GetOperation() const noexcept=0
NodeInput * input(size_t index) const noexcept
Definition: node.hpp:615
NodeOutput * output(size_t index) const noexcept
Definition: node.hpp:650
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition: node.hpp:366
Represent acyclic RVSDG subgraphs.
Definition: region.hpp:213
const std::shared_ptr< const rvsdg::Type > & argument(size_t index) const noexcept
Definition: operation.cpp:23
const std::shared_ptr< const rvsdg::Type > & result(size_t index) const noexcept
Definition: operation.cpp:36
size_t nresults() const noexcept
Definition: operation.cpp:30
SimpleOperation(std::vector< std::shared_ptr< const jlm::rvsdg::Type >> operands, std::vector< std::shared_ptr< const jlm::rvsdg::Type >> results)
Definition: operation.hpp:61
size_t narguments() const noexcept
Definition: operation.cpp:17
Unary operator.
Definition: unary.hpp:26
UnaryOperation(std::shared_ptr< const jlm::rvsdg::Type > operand, std::shared_ptr< const jlm::rvsdg::Type > result)
Definition: unary.hpp:30
#define JLM_ASSERT(x)
Definition: common.hpp:16
Global memory state passed between functions.
static ControlFlowGraphNode * aggregate(ControlFlowGraphNode *, ControlFlowGraphNode *, AggregationMap &)
size_t unop_reduction_path_t
Definition: unary.hpp:18
static std::string type(const Node *n)
Definition: view.cpp:255
size_t binop_reduction_path_t
Definition: binary.hpp:19
@ Value
Designate a value type.
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)
Definition: node.hpp:1049
static std::vector< jlm::rvsdg::Output * > outputs(const Node *node)
Definition: node.hpp:1058
static std::string strfmt(Args... args)
Definition: strfmt.hpp:35