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