Jlm
Loading...
Searching...
No Matches
IntegerOperations.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2025 Nico Reißmann <nico.reissmann@gmail.com>
3 * See COPYING for terms of redistribution.
4 */
5
8
9namespace jlm::llvm
10{
11
12template<typename TBinOp>
15{
16 static_assert(std::is_base_of_v<IntegerBinaryOperation, TBinOp>);
17
18 if constexpr (std::is_same_v<TBinOp, IntegerEqOperation>)
19 return IntegerValueRepresentation(r1.eq(r2));
20 else if constexpr (std::is_same_v<TBinOp, IntegerNeOperation>)
21 return IntegerValueRepresentation(r1.ne(r2));
22 else if constexpr (std::is_same_v<TBinOp, IntegerSgeOperation>)
23 return IntegerValueRepresentation(r1.sge(r2));
24 else if constexpr (std::is_same_v<TBinOp, IntegerSgtOperation>)
25 return IntegerValueRepresentation(r1.sgt(r2));
26 else if constexpr (std::is_same_v<TBinOp, IntegerSleOperation>)
27 return IntegerValueRepresentation(r1.sle(r2));
28 else if constexpr (std::is_same_v<TBinOp, IntegerSltOperation>)
29 return IntegerValueRepresentation(r1.slt(r2));
30 else if constexpr (std::is_same_v<TBinOp, IntegerUgeOperation>)
31 return IntegerValueRepresentation(r1.uge(r2));
32 else if constexpr (std::is_same_v<TBinOp, IntegerUgtOperation>)
33 return IntegerValueRepresentation(r1.ugt(r2));
34 else if constexpr (std::is_same_v<TBinOp, IntegerUleOperation>)
35 return IntegerValueRepresentation(r1.ule(r2));
36 else if constexpr (std::is_same_v<TBinOp, IntegerUltOperation>)
37 return IntegerValueRepresentation(r1.ult(r2));
38 else if constexpr (std::is_same_v<TBinOp, IntegerAddOperation>)
39 return IntegerValueRepresentation(r1.add(r2));
40 else if constexpr (std::is_same_v<TBinOp, IntegerSubOperation>)
41 return IntegerValueRepresentation(r1.sub(r2));
42 else if constexpr (std::is_same_v<TBinOp, IntegerMulOperation>)
43 return IntegerValueRepresentation(r1.mul(r2));
44 else if constexpr (std::is_same_v<TBinOp, IntegerSDivOperation>)
45 return IntegerValueRepresentation(r1.sdiv(r2));
46 else if constexpr (std::is_same_v<TBinOp, IntegerUDivOperation>)
47 return IntegerValueRepresentation(r1.udiv(r2));
48 else if constexpr (std::is_same_v<TBinOp, IntegerSRemOperation>)
49 return IntegerValueRepresentation(r1.smod(r2));
50 else if constexpr (std::is_same_v<TBinOp, IntegerURemOperation>)
51 return IntegerValueRepresentation(r1.umod(r2));
52 else if constexpr (std::is_same_v<TBinOp, IntegerAShrOperation>)
54 else if constexpr (std::is_same_v<TBinOp, IntegerShlOperation>)
55 return IntegerValueRepresentation(r1.shl(r2.to_uint()));
56 else if constexpr (std::is_same_v<TBinOp, IntegerLShrOperation>)
57 return IntegerValueRepresentation(r1.shr(r2.to_uint()));
58 else if constexpr (std::is_same_v<TBinOp, IntegerOrOperation>)
59 return IntegerValueRepresentation(r1.lor(r2));
60 else if constexpr (std::is_same_v<TBinOp, IntegerAndOperation>)
61 return IntegerValueRepresentation(r1.land(r2));
62 else if constexpr (std::is_same_v<TBinOp, IntegerXorOperation>)
63 return IntegerValueRepresentation(r1.lxor(r2));
64 else
65 static_assert(sizeof(TBinOp) == 0, "Unsupported binary operation!");
66}
67
75template<typename TBinOp>
76static std::optional<std::vector<rvsdg::Output *>>
77foldBinaryOperationConstants(const std::vector<rvsdg::Output *> & operands)
78{
79 static_assert(std::is_base_of_v<IntegerBinaryOperation, TBinOp>);
80
81 JLM_ASSERT(operands.size() == 2);
82 auto & operand1 = *operands[0];
83 auto & operand2 = *operands[1];
84
85 const auto & tracedOperand1 = llvm::traceOutput(operand1, false);
86 auto [c1Node, c1Operation] =
88 if (!c1Operation)
89 return std::nullopt;
90
91 const auto & tracedOperand2 = llvm::traceOutput(operand2, false);
92 auto [c2Node, c2Operation] =
94 if (!c2Operation)
95 return std::nullopt;
96
97 auto & c1Representation = c1Operation->Representation();
98 auto & c2Representation = c2Operation->Representation();
99 const auto & resultRepresentation =
100 foldBinaryOperation<TBinOp>(c1Representation, c2Representation);
101
102 auto result =
103 IntegerConstantOperation::Create(*operand1.region(), resultRepresentation).output(0);
104
105 return std::vector<rvsdg::Output *>({ result });
106}
107
108static std::optional<std::vector<rvsdg::Output *>>
109normalizeIdenticalOperands(const std::vector<rvsdg::Output *> & operands, const std::int64_t result)
110{
111 JLM_ASSERT(result == 0 || result == 1);
112 JLM_ASSERT(operands.size() == 2);
113 auto & operand1 = *operands[0];
114 auto & operand2 = *operands[1];
115
116 const auto & tracedOperand1 = llvm::traceOutput(operand1, true);
117 const auto & tracedOperand2 = llvm::traceOutput(operand2, true);
118 if (&tracedOperand1 == &tracedOperand2)
119 {
120 return outputs(&IntegerConstantOperation::Create(*operand1.region(), 1, result));
121 }
122
123 return std::nullopt;
124}
125
127
128std::unique_ptr<rvsdg::Operation>
130{
131 return std::make_unique<IntegerConstantOperation>(*this);
132}
133
134std::string
136{
137 if (Representation().is_known() && Representation().nbits() <= 64)
138 return util::strfmt("I", Representation().nbits(), "(", Representation().to_uint(), ")");
139
140 return Representation().str();
141}
142
143bool
144IntegerConstantOperation::operator==(const Operation & other) const noexcept
145{
146 const auto constant = dynamic_cast<const IntegerConstantOperation *>(&other);
147 return constant && constant->Representation() == Representation();
148}
149
151
152IntegerAddOperation::~IntegerAddOperation() noexcept = default;
153
154bool
155IntegerAddOperation::operator==(const Operation & other) const noexcept
156{
157 const auto addOperation = dynamic_cast<const IntegerAddOperation *>(&other);
158 return addOperation && addOperation->Type() == Type();
159}
160
161std::string
163{
164 return "IAdd";
165}
166
167std::unique_ptr<rvsdg::Operation>
169{
170 return std::make_unique<IntegerAddOperation>(*this);
171}
172
179
188
191{
192 return flags::associative | flags::commutative;
193}
194
195std::optional<std::vector<rvsdg::Output *>>
197 const IntegerAddOperation &,
198 const std::vector<rvsdg::Output *> & operands)
199{
200 return foldBinaryOperationConstants<IntegerAddOperation>(operands);
201}
202
204
205bool
206IntegerSubOperation::operator==(const Operation & other) const noexcept
207{
208 const auto subOperation = dynamic_cast<const IntegerSubOperation *>(&other);
209 return subOperation && subOperation->Type() == Type();
210}
211
212std::string
214{
215 return "ISub";
216}
217
218std::unique_ptr<rvsdg::Operation>
220{
221 return std::make_unique<IntegerSubOperation>(*this);
222}
223
230
239
242{
243 return flags::none;
244}
245
246std::optional<std::vector<rvsdg::Output *>>
248 const IntegerSubOperation & operation,
249 const std::vector<rvsdg::Output *> & operands)
250{
251 JLM_ASSERT(operands.size() == 2);
252 const auto & operand1 = *operands[0];
253 const auto & operand2 = *operands[1];
254
255 auto & tracedOperand1 = llvm::traceOutput(operand1, false);
256 auto & tracedOperand2 = llvm::traceOutput(operand2, false);
257
258 if (&tracedOperand1 != &tracedOperand2)
259 return std::nullopt;
260
261 return rvsdg::outputs(
262 &IntegerConstantOperation::Create(*operand1.region(), operation.Type().nbits(), 0));
263}
264
265std::optional<std::vector<rvsdg::Output *>>
267 const IntegerSubOperation &,
268 const std::vector<rvsdg::Output *> & operands)
269{
270 return foldBinaryOperationConstants<IntegerSubOperation>(operands);
271}
272
274
275bool
276IntegerMulOperation::operator==(const Operation & other) const noexcept
277{
278 const auto mulOperation = dynamic_cast<const IntegerMulOperation *>(&other);
279 return mulOperation && mulOperation->Type() == Type();
280}
281
282std::string
284{
285 return "IMul";
286}
287
288std::unique_ptr<rvsdg::Operation>
290{
291 return std::make_unique<IntegerMulOperation>(*this);
292}
293
300
309
312{
313 return flags::associative | flags::commutative;
314}
315
316std::optional<std::vector<rvsdg::Output *>>
318 const IntegerMulOperation &,
319 const std::vector<rvsdg::Output *> & operands)
320{
321 return foldBinaryOperationConstants<IntegerMulOperation>(operands);
322}
323
325
326bool
327IntegerSDivOperation::operator==(const Operation & other) const noexcept
328{
329 const auto sdivOperation = dynamic_cast<const IntegerSDivOperation *>(&other);
330 return sdivOperation && sdivOperation->Type() == Type();
331}
332
333std::string
335{
336 return "ISDiv";
337}
338
339std::unique_ptr<rvsdg::Operation>
341{
342 return std::make_unique<IntegerSDivOperation>(*this);
343}
344
351
360
363{
364 return flags::none;
365}
366
367std::optional<std::vector<rvsdg::Output *>>
369 const IntegerSDivOperation &,
370 const std::vector<rvsdg::Output *> & operands)
371{
372 return foldBinaryOperationConstants<IntegerSDivOperation>(operands);
373}
374
376
377bool
378IntegerUDivOperation::operator==(const Operation & other) const noexcept
379{
380 const auto udivOperation = dynamic_cast<const IntegerUDivOperation *>(&other);
381 return udivOperation && udivOperation->Type() == Type();
382}
383
384std::string
386{
387 return "IUDiv";
388}
389
390std::unique_ptr<rvsdg::Operation>
392{
393 return std::make_unique<IntegerUDivOperation>(*this);
394}
395
402
411
414{
415 return flags::none;
416}
417
418std::optional<std::vector<rvsdg::Output *>>
420 const IntegerUDivOperation &,
421 const std::vector<rvsdg::Output *> & operands)
422{
423 return foldBinaryOperationConstants<IntegerUDivOperation>(operands);
424}
425
427
428bool
429IntegerSRemOperation::operator==(const Operation & other) const noexcept
430{
431 const auto smodOperation = dynamic_cast<const IntegerSRemOperation *>(&other);
432 return smodOperation && smodOperation->Type() == Type();
433}
434
435std::string
437{
438 return "ISMod";
439}
440
441std::unique_ptr<rvsdg::Operation>
443{
444 return std::make_unique<IntegerSRemOperation>(*this);
445}
446
453
462
465{
466 return flags::none;
467}
468
469std::optional<std::vector<rvsdg::Output *>>
471 const IntegerSRemOperation &,
472 const std::vector<rvsdg::Output *> & operands)
473{
474 return foldBinaryOperationConstants<IntegerSRemOperation>(operands);
475}
476
478
479bool
480IntegerURemOperation::operator==(const Operation & other) const noexcept
481{
482 const auto umodOperation = dynamic_cast<const IntegerURemOperation *>(&other);
483 return umodOperation && umodOperation->Type() == Type();
484}
485
486std::string
488{
489 return "IUMod";
490}
491
492std::unique_ptr<rvsdg::Operation>
494{
495 return std::make_unique<IntegerURemOperation>(*this);
496}
497
504
513
516{
517 return flags::none;
518}
519
520std::optional<std::vector<rvsdg::Output *>>
522 const IntegerURemOperation &,
523 const std::vector<rvsdg::Output *> & operands)
524{
525 return foldBinaryOperationConstants<IntegerURemOperation>(operands);
526}
527
529
530bool
531IntegerAShrOperation::operator==(const Operation & other) const noexcept
532{
533 const auto ashrOperation = dynamic_cast<const IntegerAShrOperation *>(&other);
534 return ashrOperation && ashrOperation->Type() == Type();
535}
536
537std::string
539{
540 return "IAShr";
541}
542
543std::unique_ptr<rvsdg::Operation>
545{
546 return std::make_unique<IntegerAShrOperation>(*this);
547}
548
555
564
567{
568 return flags::none;
569}
570
571std::optional<std::vector<rvsdg::Output *>>
573 const IntegerAShrOperation &,
574 const std::vector<rvsdg::Output *> & operands)
575{
576 return foldBinaryOperationConstants<IntegerAShrOperation>(operands);
577}
578
580
581bool
582IntegerShlOperation::operator==(const Operation & other) const noexcept
583{
584 const auto shlOperation = dynamic_cast<const IntegerShlOperation *>(&other);
585 return shlOperation && shlOperation->Type() == Type();
586}
587
588std::string
590{
591 return "IShl";
592}
593
594std::unique_ptr<rvsdg::Operation>
596{
597 return std::make_unique<IntegerShlOperation>(*this);
598}
599
606
615
618{
619 return flags::none;
620}
621
622std::optional<std::vector<rvsdg::Output *>>
624 const IntegerShlOperation &,
625 const std::vector<rvsdg::Output *> & operands)
626{
627 return foldBinaryOperationConstants<IntegerShlOperation>(operands);
628}
629
631
632bool
633IntegerLShrOperation::operator==(const Operation & other) const noexcept
634{
635 const auto shrOperation = dynamic_cast<const IntegerLShrOperation *>(&other);
636 return shrOperation && shrOperation->Type() == Type();
637}
638
639std::string
641{
642 return "IShr";
643}
644
645std::unique_ptr<rvsdg::Operation>
647{
648 return std::make_unique<IntegerLShrOperation>(*this);
649}
650
657
666
669{
670 return flags::none;
671}
672
673std::optional<std::vector<rvsdg::Output *>>
675 const IntegerLShrOperation &,
676 const std::vector<rvsdg::Output *> & operands)
677{
678 return foldBinaryOperationConstants<IntegerLShrOperation>(operands);
679}
680
682
683bool
684IntegerAndOperation::operator==(const Operation & other) const noexcept
685{
686 const auto andOperation = dynamic_cast<const IntegerAndOperation *>(&other);
687 return andOperation && andOperation->Type() == Type();
688}
689
690std::string
692{
693 return "IAnd";
694}
695
696std::unique_ptr<rvsdg::Operation>
698{
699 return std::make_unique<IntegerAndOperation>(*this);
700}
701
708
717
720{
721 return flags::associative | flags::commutative;
722}
723
724std::optional<std::vector<rvsdg::Output *>>
726 const IntegerAndOperation &,
727 const std::vector<rvsdg::Output *> & operands)
728{
729 return foldBinaryOperationConstants<IntegerAndOperation>(operands);
730}
731
732IntegerOrOperation::~IntegerOrOperation() noexcept = default;
733
734bool
735IntegerOrOperation::operator==(const Operation & other) const noexcept
736{
737 const auto orOperation = dynamic_cast<const IntegerOrOperation *>(&other);
738 return orOperation && orOperation->Type() == Type();
739}
740
741std::string
743{
744 return "IOr";
745}
746
747std::unique_ptr<rvsdg::Operation>
749{
750 return std::make_unique<IntegerOrOperation>(*this);
751}
752
759
768
771{
772 return flags::associative | flags::commutative;
773}
774
775std::optional<std::vector<rvsdg::Output *>>
777 const IntegerOrOperation &,
778 const std::vector<rvsdg::Output *> & operands)
779{
780 return foldBinaryOperationConstants<IntegerOrOperation>(operands);
781}
782
783std::optional<std::vector<rvsdg::Output *>>
785 const IntegerOrOperation &,
786 const std::vector<rvsdg::Output *> & operands)
787{
788 JLM_ASSERT(operands.size() == 2);
789 auto & operand1 = *operands[0];
790 auto & operand2 = *operands[1];
791
792 const auto & tracedOperand1 = llvm::traceOutput(operand1, true);
793 auto [c1Node, c1Operation] =
795 if (c1Operation && c1Operation->Representation().isZero())
796 {
797 return std::vector({ &operand2 });
798 }
799
800 const auto & tracedOperand2 = llvm::traceOutput(operand2, true);
801 auto [c2Node, c2Operation] =
803 if (c2Operation && c2Operation->Representation().isZero())
804 {
805 return std::vector({ &operand1 });
806 }
807
808 return std::nullopt;
809}
810
812
813bool
814IntegerXorOperation::operator==(const Operation & other) const noexcept
815{
816 const auto xorOperation = dynamic_cast<const IntegerXorOperation *>(&other);
817 return xorOperation && xorOperation->Type() == Type();
818}
819
820std::string
822{
823 return "IXor";
824}
825
826std::unique_ptr<rvsdg::Operation>
828{
829 return std::make_unique<IntegerXorOperation>(*this);
830}
831
838
847
850{
851 return flags::associative | flags::commutative;
852}
853
854std::optional<std::vector<rvsdg::Output *>>
856 const IntegerXorOperation &,
857 const std::vector<rvsdg::Output *> & operands)
858{
859 return foldBinaryOperationConstants<IntegerXorOperation>(operands);
860}
861
862IntegerEqOperation::~IntegerEqOperation() noexcept = default;
863
864bool
865IntegerEqOperation::operator==(const Operation & other) const noexcept
866{
867 const auto eqOperation = dynamic_cast<const IntegerEqOperation *>(&other);
868 return eqOperation && eqOperation->result(0) == result(0);
869}
870
871std::string
873{
874 return "IEq";
875}
876
877std::unique_ptr<rvsdg::Operation>
879{
880 return std::make_unique<IntegerEqOperation>(*this);
881}
882
889
898
901{
902 return flags::commutative;
903}
904
905std::optional<std::vector<rvsdg::Output *>>
907 const IntegerEqOperation &,
908 const std::vector<rvsdg::Output *> & operands)
909{
910 return foldBinaryOperationConstants<IntegerEqOperation>(operands);
911}
912
913std::optional<std::vector<rvsdg::Output *>>
915 const IntegerEqOperation &,
916 const std::vector<rvsdg::Output *> & operands)
917{
918 return llvm::normalizeIdenticalOperands(operands, 1);
919}
920
921IntegerNeOperation::~IntegerNeOperation() noexcept = default;
922
923bool
924IntegerNeOperation::operator==(const Operation & other) const noexcept
925{
926 const auto neOperation = dynamic_cast<const IntegerNeOperation *>(&other);
927 return neOperation && neOperation->result(0) == result(0);
928}
929
930std::string
932{
933 return "INe";
934}
935
936std::unique_ptr<rvsdg::Operation>
938{
939 return std::make_unique<IntegerNeOperation>(*this);
940}
941
948
957
960{
961 return flags::commutative;
962}
963
964std::optional<std::vector<rvsdg::Output *>>
966 const IntegerNeOperation &,
967 const std::vector<rvsdg::Output *> & operands)
968{
969 return foldBinaryOperationConstants<IntegerNeOperation>(operands);
970}
971
972std::optional<std::vector<rvsdg::Output *>>
974 const IntegerNeOperation &,
975 const std::vector<rvsdg::Output *> & operands)
976{
977 return llvm::normalizeIdenticalOperands(operands, 0);
978}
979
981
982bool
983IntegerSgeOperation::operator==(const Operation & other) const noexcept
984{
985 const auto sgeOperation = dynamic_cast<const IntegerSgeOperation *>(&other);
986 return sgeOperation && sgeOperation->result(0) == result(0);
987}
988
989std::string
991{
992 return "ISge";
993}
994
995std::unique_ptr<rvsdg::Operation>
997{
998 return std::make_unique<IntegerSgeOperation>(*this);
999}
1000
1007
1016
1019{
1020 return flags::none;
1021}
1022
1023std::optional<std::vector<rvsdg::Output *>>
1025 const IntegerSgeOperation &,
1026 const std::vector<rvsdg::Output *> & operands)
1027{
1028 return foldBinaryOperationConstants<IntegerSgeOperation>(operands);
1029}
1030
1031std::optional<std::vector<rvsdg::Output *>>
1033 const IntegerSgeOperation &,
1034 const std::vector<rvsdg::Output *> & operands)
1035{
1036 return llvm::normalizeIdenticalOperands(operands, 1);
1037}
1038
1040
1041bool
1042IntegerSgtOperation::operator==(const Operation & other) const noexcept
1043{
1044 const auto sgtOperation = dynamic_cast<const IntegerSgtOperation *>(&other);
1045 return sgtOperation && sgtOperation->result(0) == result(0);
1046}
1047
1048std::string
1050{
1051 return "ISgt";
1052}
1053
1054std::unique_ptr<rvsdg::Operation>
1056{
1057 return std::make_unique<IntegerSgtOperation>(*this);
1058}
1059
1066
1075
1078{
1079 return flags::none;
1080}
1081
1082std::optional<std::vector<rvsdg::Output *>>
1084 const IntegerSgtOperation &,
1085 const std::vector<rvsdg::Output *> & operands)
1086{
1087 return foldBinaryOperationConstants<IntegerSgtOperation>(operands);
1088}
1089
1090std::optional<std::vector<rvsdg::Output *>>
1092 const IntegerSgtOperation &,
1093 const std::vector<rvsdg::Output *> & operands)
1094{
1095 return llvm::normalizeIdenticalOperands(operands, 0);
1096}
1097
1099
1100bool
1101IntegerSleOperation::operator==(const Operation & other) const noexcept
1102{
1103 const auto sleOperation = dynamic_cast<const IntegerSleOperation *>(&other);
1104 return sleOperation && sleOperation->result(0) == result(0);
1105}
1106
1107std::string
1109{
1110 return "ISle";
1111}
1112
1113std::unique_ptr<rvsdg::Operation>
1115{
1116 return std::make_unique<IntegerSleOperation>(*this);
1117}
1118
1125
1134
1137{
1138 return flags::none;
1139}
1140
1141std::optional<std::vector<rvsdg::Output *>>
1143 const IntegerSleOperation &,
1144 const std::vector<rvsdg::Output *> & operands)
1145{
1146 return foldBinaryOperationConstants<IntegerSleOperation>(operands);
1147}
1148
1149std::optional<std::vector<rvsdg::Output *>>
1151 const IntegerSleOperation &,
1152 const std::vector<rvsdg::Output *> & operands)
1153{
1154 return llvm::normalizeIdenticalOperands(operands, 1);
1155}
1156
1158
1159bool
1160IntegerSltOperation::operator==(const Operation & other) const noexcept
1161{
1162 const auto sltOperation = dynamic_cast<const IntegerSltOperation *>(&other);
1163 return sltOperation && sltOperation->result(0) == result(0);
1164}
1165
1166std::string
1168{
1169 return "ISlt";
1170}
1171
1172std::unique_ptr<rvsdg::Operation>
1174{
1175 return std::make_unique<IntegerSltOperation>(*this);
1176}
1177
1184
1193
1196{
1197 return flags::none;
1198}
1199
1200std::optional<std::vector<rvsdg::Output *>>
1202 const IntegerSltOperation &,
1203 const std::vector<rvsdg::Output *> & operands)
1204{
1205 return foldBinaryOperationConstants<IntegerSltOperation>(operands);
1206}
1207
1208std::optional<std::vector<rvsdg::Output *>>
1210 const IntegerSltOperation &,
1211 const std::vector<rvsdg::Output *> & operands)
1212{
1213 return llvm::normalizeIdenticalOperands(operands, 0);
1214}
1215
1217
1218bool
1219IntegerUgeOperation::operator==(const Operation & other) const noexcept
1220{
1221 const auto ugeOperation = dynamic_cast<const IntegerUgeOperation *>(&other);
1222 return ugeOperation && ugeOperation->result(0) == result(0);
1223}
1224
1225std::string
1227{
1228 return "IUge";
1229}
1230
1231std::unique_ptr<rvsdg::Operation>
1233{
1234 return std::make_unique<IntegerUgeOperation>(*this);
1235}
1236
1243
1252
1255{
1256 return flags::none;
1257}
1258
1259std::optional<std::vector<rvsdg::Output *>>
1261 const IntegerUgeOperation &,
1262 const std::vector<rvsdg::Output *> & operands)
1263{
1264 return foldBinaryOperationConstants<IntegerUgeOperation>(operands);
1265}
1266
1267std::optional<std::vector<rvsdg::Output *>>
1269 const IntegerUgeOperation &,
1270 const std::vector<rvsdg::Output *> & operands)
1271{
1272 return llvm::normalizeIdenticalOperands(operands, 1);
1273}
1274
1276
1277bool
1278IntegerUgtOperation::operator==(const Operation & other) const noexcept
1279{
1280 const auto ugtOperation = dynamic_cast<const IntegerUgtOperation *>(&other);
1281 return ugtOperation && ugtOperation->result(0) == result(0);
1282}
1283
1284std::string
1286{
1287 return "IUgt";
1288}
1289
1290std::unique_ptr<rvsdg::Operation>
1292{
1293 return std::make_unique<IntegerUgtOperation>(*this);
1294}
1295
1302
1311
1314{
1315 return flags::none;
1316}
1317
1318std::optional<std::vector<rvsdg::Output *>>
1320 const IntegerUgtOperation &,
1321 const std::vector<rvsdg::Output *> & operands)
1322{
1323 return foldBinaryOperationConstants<IntegerUgtOperation>(operands);
1324}
1325
1326std::optional<std::vector<rvsdg::Output *>>
1328 const IntegerUgtOperation &,
1329 const std::vector<rvsdg::Output *> & operands)
1330{
1331 return llvm::normalizeIdenticalOperands(operands, 0);
1332}
1333
1335
1336bool
1337IntegerUleOperation::operator==(const Operation & other) const noexcept
1338{
1339 const auto uleOperation = dynamic_cast<const IntegerUleOperation *>(&other);
1340 return uleOperation && uleOperation->result(0) == result(0);
1341}
1342
1343std::string
1345{
1346 return "IUle";
1347}
1348
1349std::unique_ptr<rvsdg::Operation>
1351{
1352 return std::make_unique<IntegerUleOperation>(*this);
1353}
1354
1361
1370
1373{
1374 return flags::none;
1375}
1376
1377std::optional<std::vector<rvsdg::Output *>>
1379 const IntegerUleOperation &,
1380 const std::vector<rvsdg::Output *> & operands)
1381{
1382 return foldBinaryOperationConstants<IntegerUleOperation>(operands);
1383}
1384
1385std::optional<std::vector<rvsdg::Output *>>
1387 const IntegerUleOperation &,
1388 const std::vector<rvsdg::Output *> & operands)
1389{
1390 return llvm::normalizeIdenticalOperands(operands, 1);
1391}
1392
1394
1395bool
1396IntegerUltOperation::operator==(const Operation & other) const noexcept
1397{
1398 const auto ultOperation = dynamic_cast<const IntegerUltOperation *>(&other);
1399 return ultOperation && ultOperation->result(0) == result(0);
1400}
1401
1402std::string
1404{
1405 return "IUlt";
1406}
1407
1408std::unique_ptr<rvsdg::Operation>
1410{
1411 return std::make_unique<IntegerUltOperation>(*this);
1412}
1413
1420
1429
1432{
1433 return flags::none;
1434}
1435
1436std::optional<std::vector<rvsdg::Output *>>
1438 const IntegerUltOperation &,
1439 const std::vector<rvsdg::Output *> & operands)
1440{
1441 return foldBinaryOperationConstants<IntegerUltOperation>(operands);
1442}
1443
1444std::optional<std::vector<rvsdg::Output *>>
1446 const IntegerUltOperation &,
1447 const std::vector<rvsdg::Output *> & operands)
1448{
1449 return llvm::normalizeIdenticalOperands(operands, 0);
1450}
1451
1452}
std::unique_ptr< Operation > copy() const override
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerAShrOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::string debug_string() const override
enum flags flags() const noexcept override
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
~IntegerAShrOperation() noexcept override
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
enum flags flags() const noexcept override
std::string debug_string() const override
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerAddOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::unique_ptr< Operation > copy() const override
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
std::unique_ptr< Operation > copy() const override
enum flags flags() const noexcept override
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerAndOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::string debug_string() const override
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
~IntegerAndOperation() noexcept override
~IntegerBinaryOperation() noexcept override
const rvsdg::BitType & Type() const noexcept
static rvsdg::Node & Create(rvsdg::Region &region, IntegerValueRepresentation representation)
bool operator==(const Operation &other) const noexcept override
const IntegerValueRepresentation & Representation() const noexcept
std::unique_ptr< Operation > copy() const override
std::string debug_string() const override
enum flags flags() const noexcept override
std::string debug_string() const override
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerEqOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > normalizeIdenticalOperands(const IntegerEqOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::unique_ptr< Operation > copy() const override
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
~IntegerEqOperation() noexcept override
~IntegerLShrOperation() noexcept override
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerLShrOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::string debug_string() const override
std::unique_ptr< Operation > copy() const override
enum flags flags() const noexcept override
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
~IntegerMulOperation() noexcept override
std::string debug_string() const override
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerMulOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::unique_ptr< Operation > copy() const override
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
enum flags flags() const noexcept override
std::string debug_string() const override
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerNeOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::unique_ptr< Operation > copy() const override
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
enum flags flags() const noexcept override
~IntegerNeOperation() noexcept override
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
static std::optional< std::vector< rvsdg::Output * > > normalizeIdenticalOperands(const IntegerNeOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerOrOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::unique_ptr< Operation > copy() const override
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
~IntegerOrOperation() noexcept override
enum flags flags() const noexcept override
std::string debug_string() const override
static std::optional< std::vector< rvsdg::Output * > > normalizeIdempotent(const IntegerOrOperation &operation, const std::vector< rvsdg::Output * > &operands)
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerSDivOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::string debug_string() const override
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
~IntegerSDivOperation() noexcept override
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
std::unique_ptr< Operation > copy() const override
enum flags flags() const noexcept override
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerSRemOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::string debug_string() const override
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
~IntegerSRemOperation() noexcept override
std::unique_ptr< Operation > copy() const override
enum flags flags() const noexcept override
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerSgeOperation &operation, const std::vector< rvsdg::Output * > &operands)
enum flags flags() const noexcept override
std::unique_ptr< Operation > copy() const override
std::string debug_string() const override
~IntegerSgeOperation() noexcept override
static std::optional< std::vector< rvsdg::Output * > > normalizeIdenticalOperands(const IntegerSgeOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerSgtOperation &operation, const std::vector< rvsdg::Output * > &operands)
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
std::string debug_string() const override
std::unique_ptr< Operation > copy() const override
enum flags flags() const noexcept override
static std::optional< std::vector< rvsdg::Output * > > normalizeIdenticalOperands(const IntegerSgtOperation &operation, const std::vector< rvsdg::Output * > &operands)
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
~IntegerSgtOperation() noexcept override
std::unique_ptr< Operation > copy() const override
~IntegerShlOperation() noexcept override
enum flags flags() const noexcept override
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
std::string debug_string() const override
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerShlOperation &operation, const std::vector< rvsdg::Output * > &operands)
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
std::string debug_string() const override
enum flags flags() const noexcept override
~IntegerSleOperation() noexcept override
std::unique_ptr< Operation > copy() const override
static std::optional< std::vector< rvsdg::Output * > > normalizeIdenticalOperands(const IntegerSleOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerSleOperation &operation, const std::vector< rvsdg::Output * > &operands)
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
std::unique_ptr< Operation > copy() const override
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
std::string debug_string() const override
static std::optional< std::vector< rvsdg::Output * > > normalizeIdenticalOperands(const IntegerSltOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerSltOperation &operation, const std::vector< rvsdg::Output * > &operands)
enum flags flags() const noexcept override
~IntegerSltOperation() noexcept override
~IntegerSubOperation() noexcept override
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
std::string debug_string() const override
enum flags flags() const noexcept override
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerSubOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > normalizeAdditiveInverse(const IntegerSubOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::unique_ptr< Operation > copy() const override
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerUDivOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::string debug_string() const override
~IntegerUDivOperation() noexcept override
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
enum flags flags() const noexcept override
std::unique_ptr< Operation > copy() const override
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
std::unique_ptr< Operation > copy() const override
std::string debug_string() const override
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
enum flags flags() const noexcept override
~IntegerURemOperation() noexcept override
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerURemOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerUgeOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::string debug_string() const override
static std::optional< std::vector< rvsdg::Output * > > normalizeIdenticalOperands(const IntegerUgeOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::unique_ptr< Operation > copy() const override
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
~IntegerUgeOperation() noexcept override
enum flags flags() const noexcept override
enum flags flags() const noexcept override
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
static std::optional< std::vector< rvsdg::Output * > > normalizeIdenticalOperands(const IntegerUgtOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::string debug_string() const override
std::unique_ptr< Operation > copy() const override
~IntegerUgtOperation() noexcept override
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerUgtOperation &operation, const std::vector< rvsdg::Output * > &operands)
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
enum flags flags() const noexcept override
std::string debug_string() const override
~IntegerUleOperation() noexcept override
static std::optional< std::vector< rvsdg::Output * > > normalizeIdenticalOperands(const IntegerUleOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::unique_ptr< Operation > copy() const override
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerUleOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::unique_ptr< Operation > copy() const override
enum flags flags() const noexcept override
std::string debug_string() const override
~IntegerUltOperation() noexcept override
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
static std::optional< std::vector< rvsdg::Output * > > normalizeIdenticalOperands(const IntegerUltOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerUltOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::string debug_string() const override
rvsdg::Output * reduce_operand_pair(rvsdg::binop_reduction_path_t path, rvsdg::Output *op1, rvsdg::Output *op2) const override
~IntegerXorOperation() noexcept override
enum flags flags() const noexcept override
static std::optional< std::vector< rvsdg::Output * > > foldConstants(const IntegerXorOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::unique_ptr< Operation > copy() const override
rvsdg::binop_reduction_path_t can_reduce_operand_pair(const rvsdg::Output *op1, const rvsdg::Output *op2) const noexcept override
size_t nbits() const noexcept
Definition type.hpp:26
BitValueRepresentation shl(size_t shift) const
void udiv(const BitValueRepresentation &divisor, BitValueRepresentation &quotient, BitValueRepresentation &remainder) const
BitValueRepresentation smod(const BitValueRepresentation &other) const
void mul(const BitValueRepresentation &factor1, const BitValueRepresentation &factor2, BitValueRepresentation &product) const
char sgt(const BitValueRepresentation &other) const
char sge(const BitValueRepresentation &other) const
BitValueRepresentation sdiv(const BitValueRepresentation &other) const
char ne(const BitValueRepresentation &other) const
char ule(const BitValueRepresentation &other) const
char ult(const BitValueRepresentation &other) const
char lor(char a, char b) const noexcept
char ugt(const BitValueRepresentation &other) const
char eq(const BitValueRepresentation &other) const
char lxor(char a, char b) const noexcept
BitValueRepresentation sub(const BitValueRepresentation &other) const
char slt(const BitValueRepresentation &other) const
BitValueRepresentation ashr(size_t shift) const
BitValueRepresentation shr(size_t shift) const
BitValueRepresentation umod(const BitValueRepresentation &other) const
char sle(const BitValueRepresentation &other) const
char land(char a, char b) const noexcept
char uge(const BitValueRepresentation &other) const
char add(char a, char b, char c) const noexcept
NodeOutput * output(size_t index) const noexcept
Definition node.hpp:650
const std::shared_ptr< const rvsdg::Type > & result(size_t index) const noexcept
Definition operation.cpp:36
#define JLM_ASSERT(x)
Definition common.hpp:16
Global memory state passed between functions.
static std::optional< std::vector< rvsdg::Output * > > normalizeIdenticalOperands(const std::vector< rvsdg::Output * > &operands, const std::int64_t result)
rvsdg::BitValueRepresentation IntegerValueRepresentation
rvsdg::Output & traceOutput(rvsdg::Output &output, bool mayEnterSubregions, const rvsdg::Region *withinRegion)
Definition Trace.cpp:84
static IntegerValueRepresentation foldBinaryOperation(const IntegerValueRepresentation &r1, const IntegerValueRepresentation &r2)
static std::optional< std::vector< rvsdg::Output * > > foldBinaryOperationConstants(const std::vector< rvsdg::Output * > &operands)
static std::vector< jlm::rvsdg::Output * > outputs(const Node *node)
Definition node.hpp:1058
size_t binop_reduction_path_t
Definition binary.hpp:19
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
Definition node.hpp:872
static const binop_reduction_path_t binop_reduction_none
Definition binary.hpp:203
static std::string strfmt(Args... args)
Definition strfmt.hpp:35