Jlm
Loading...
Searching...
No Matches
ArithmeticWithOverflowIntrinsicOperations.hpp
Go to the documentation of this file.
1/*
2 * Copyright 2026 Nico Reißmann <nico.reissmann@gmail.com>
3 * See COPYING for terms of redistribution.
4 */
5
6#ifndef JLM_LLVM_IR_OPERATORS_ARITHMETICWITHOVERFLOWINTRINSICOPERATIONS_HPP
7#define JLM_LLVM_IR_OPERATORS_ARITHMETICWITHOVERFLOWINTRINSICOPERATIONS_HPP
8
9#include <jlm/llvm/ir/tac.hpp>
10#include <jlm/llvm/ir/types.hpp>
13
14namespace jlm::llvm
15{
16
24{
25public:
26 ~SAddWithOverflowOperation() noexcept override;
27
28 explicit SAddWithOverflowOperation(const std::shared_ptr<const rvsdg::Type> & type)
30 { type, type },
32 {
33 checkOperandType(type);
34 }
35
36 bool
37 operator==(const Operation & other) const noexcept override;
38
39 std::string
40 debug_string() const override;
41
42 [[nodiscard]] std::unique_ptr<Operation>
43 copy() const override;
44
45 [[nodiscard]] std::shared_ptr<const rvsdg::Type>
46 getOperandType() const noexcept
47 {
48 return argument(0);
49 }
50
51 [[nodiscard]] std::shared_ptr<const rvsdg::Type>
52 getResultType() const noexcept
53 {
54 return result(0);
55 }
56
57 static std::unique_ptr<ThreeAddressCode>
58 createTac(const Variable & operand1, const Variable & operand2)
59 {
60 auto operation = std::make_unique<SAddWithOverflowOperation>(operand1.Type());
61 return ThreeAddressCode::create(std::move(operation), { &operand1, &operand2 });
62 }
63
64 static rvsdg::SimpleNode &
65 createNode(rvsdg::Output & operand1, rvsdg::Output & operand2)
66 {
68 { &operand1, &operand2 },
69 operand1.Type());
70 }
71
72private:
73 static void
74 checkOperandType(const std::shared_ptr<const rvsdg::Type> & type);
75};
76
84{
85public:
86 ~UAddWithOverflowOperation() noexcept override;
87
88 explicit UAddWithOverflowOperation(const std::shared_ptr<const rvsdg::Type> & type)
90 { type, type },
92 {
93 checkOperandType(type);
94 }
95
96 bool
97 operator==(const Operation & other) const noexcept override;
98
99 std::string
100 debug_string() const override;
101
102 [[nodiscard]] std::unique_ptr<Operation>
103 copy() const override;
104
105 [[nodiscard]] std::shared_ptr<const rvsdg::Type>
106 getOperandType() const noexcept
107 {
108 return argument(0);
109 }
110
111 [[nodiscard]] std::shared_ptr<const rvsdg::Type>
112 getResultType() const noexcept
113 {
114 return result(0);
115 }
116
117 static std::unique_ptr<ThreeAddressCode>
118 createTac(const Variable & operand1, const Variable & operand2)
119 {
120 auto operation = std::make_unique<UAddWithOverflowOperation>(operand1.Type());
121 return ThreeAddressCode::create(std::move(operation), { &operand1, &operand2 });
122 }
123
124 static rvsdg::SimpleNode &
125 createNode(rvsdg::Output & operand1, rvsdg::Output & operand2)
126 {
128 { &operand1, &operand2 },
129 operand1.Type());
130 }
131
132private:
133 static void
134 checkOperandType(const std::shared_ptr<const rvsdg::Type> & type);
135};
136
144{
145public:
146 ~SSubWithOverflowOperation() noexcept override;
147
148 explicit SSubWithOverflowOperation(const std::shared_ptr<const rvsdg::Type> & type)
150 { type, type },
151 { StructType::CreateLiteral({ type, rvsdg::BitType::Create(1) }, false) })
152 {
153 checkOperandType(type);
154 }
155
156 bool
157 operator==(const Operation & other) const noexcept override;
158
159 std::string
160 debug_string() const override;
161
162 [[nodiscard]] std::unique_ptr<Operation>
163 copy() const override;
164
165 [[nodiscard]] std::shared_ptr<const rvsdg::Type>
166 getOperandType() const noexcept
167 {
168 return argument(0);
169 }
170
171 [[nodiscard]] std::shared_ptr<const rvsdg::Type>
172 getResultType() const noexcept
173 {
174 return result(0);
175 }
176
177 static std::unique_ptr<ThreeAddressCode>
178 createTac(const Variable & operand1, const Variable & operand2)
179 {
180 auto operation = std::make_unique<SSubWithOverflowOperation>(operand1.Type());
181 return ThreeAddressCode::create(std::move(operation), { &operand1, &operand2 });
182 }
183
184 static rvsdg::SimpleNode &
185 createNode(rvsdg::Output & operand1, rvsdg::Output & operand2)
186 {
188 { &operand1, &operand2 },
189 operand1.Type());
190 }
191
192private:
193 static void
194 checkOperandType(const std::shared_ptr<const rvsdg::Type> & type);
195};
196
204{
205public:
206 ~SMulWithOverflowOperation() noexcept override;
207
208 explicit SMulWithOverflowOperation(const std::shared_ptr<const rvsdg::Type> & type)
210 { type, type },
211 { StructType::CreateLiteral({ type, rvsdg::BitType::Create(1) }, false) })
212 {
213 checkOperandType(type);
214 }
215
216 bool
217 operator==(const Operation & other) const noexcept override;
218
219 std::string
220 debug_string() const override;
221
222 [[nodiscard]] std::unique_ptr<Operation>
223 copy() const override;
224
225 [[nodiscard]] std::shared_ptr<const rvsdg::Type>
226 getOperandType() const noexcept
227 {
228 return argument(0);
229 }
230
231 [[nodiscard]] std::shared_ptr<const rvsdg::Type>
232 getResultType() const noexcept
233 {
234 return result(0);
235 }
236
237 static std::unique_ptr<ThreeAddressCode>
238 createTac(const Variable & operand1, const Variable & operand2)
239 {
240 auto operation = std::make_unique<SMulWithOverflowOperation>(operand1.Type());
241 return ThreeAddressCode::create(std::move(operation), { &operand1, &operand2 });
242 }
243
244 static rvsdg::SimpleNode &
245 createNode(rvsdg::Output & operand1, rvsdg::Output & operand2)
246 {
248 { &operand1, &operand2 },
249 operand1.Type());
250 }
251
252private:
253 static void
254 checkOperandType(const std::shared_ptr<const rvsdg::Type> & type);
255};
256
264{
265public:
266 ~UMulWithOverflowOperation() noexcept override;
267
268 explicit UMulWithOverflowOperation(const std::shared_ptr<const rvsdg::Type> & type)
270 { type, type },
271 { StructType::CreateLiteral({ type, rvsdg::BitType::Create(1) }, false) })
272 {
273 checkOperandType(type);
274 }
275
276 bool
277 operator==(const Operation & other) const noexcept override;
278
279 std::string
280 debug_string() const override;
281
282 [[nodiscard]] std::unique_ptr<Operation>
283 copy() const override;
284
285 [[nodiscard]] std::shared_ptr<const rvsdg::Type>
286 getOperandType() const noexcept
287 {
288 return argument(0);
289 }
290
291 [[nodiscard]] std::shared_ptr<const rvsdg::Type>
292 getResultType() const noexcept
293 {
294 return result(0);
295 }
296
297 static std::unique_ptr<ThreeAddressCode>
298 createTac(const Variable & operand1, const Variable & operand2)
299 {
300 auto operation = std::make_unique<UMulWithOverflowOperation>(operand1.Type());
301 return ThreeAddressCode::create(std::move(operation), { &operand1, &operand2 });
302 }
303
304 static rvsdg::SimpleNode &
305 createNode(rvsdg::Output & operand1, rvsdg::Output & operand2)
306 {
308 { &operand1, &operand2 },
309 operand1.Type());
310 }
311
312private:
313 static void
314 checkOperandType(const std::shared_ptr<const rvsdg::Type> & type);
315};
316
317}
318
319#endif
static rvsdg::SimpleNode & createNode(rvsdg::Output &operand1, rvsdg::Output &operand2)
static void checkOperandType(const std::shared_ptr< const rvsdg::Type > &type)
static std::unique_ptr< ThreeAddressCode > createTac(const Variable &operand1, const Variable &operand2)
~SAddWithOverflowOperation() noexcept override
std::shared_ptr< const rvsdg::Type > getOperandType() const noexcept
std::unique_ptr< Operation > copy() const override
std::shared_ptr< const rvsdg::Type > getResultType() const noexcept
bool operator==(const Operation &other) const noexcept override
std::unique_ptr< Operation > copy() const override
bool operator==(const Operation &other) const noexcept override
static rvsdg::SimpleNode & createNode(rvsdg::Output &operand1, rvsdg::Output &operand2)
std::shared_ptr< const rvsdg::Type > getOperandType() const noexcept
static std::unique_ptr< ThreeAddressCode > createTac(const Variable &operand1, const Variable &operand2)
~SMulWithOverflowOperation() noexcept override
std::shared_ptr< const rvsdg::Type > getResultType() const noexcept
static void checkOperandType(const std::shared_ptr< const rvsdg::Type > &type)
std::unique_ptr< Operation > copy() const override
~SSubWithOverflowOperation() noexcept override
static void checkOperandType(const std::shared_ptr< const rvsdg::Type > &type)
std::shared_ptr< const rvsdg::Type > getOperandType() const noexcept
static std::unique_ptr< ThreeAddressCode > createTac(const Variable &operand1, const Variable &operand2)
bool operator==(const Operation &other) const noexcept override
std::shared_ptr< const rvsdg::Type > getResultType() const noexcept
static rvsdg::SimpleNode & createNode(rvsdg::Output &operand1, rvsdg::Output &operand2)
static std::shared_ptr< const StructType > CreateLiteral(std::vector< std::shared_ptr< const Type > > types, bool isPacked)
Definition types.hpp:334
static std::unique_ptr< llvm::ThreeAddressCode > create(std::unique_ptr< rvsdg::SimpleOperation > operation, const std::vector< const Variable * > &operands)
Definition tac.hpp:135
static void checkOperandType(const std::shared_ptr< const rvsdg::Type > &type)
bool operator==(const Operation &other) const noexcept override
std::shared_ptr< const rvsdg::Type > getResultType() const noexcept
std::shared_ptr< const rvsdg::Type > getOperandType() const noexcept
~UAddWithOverflowOperation() noexcept override
static std::unique_ptr< ThreeAddressCode > createTac(const Variable &operand1, const Variable &operand2)
std::unique_ptr< Operation > copy() const override
static rvsdg::SimpleNode & createNode(rvsdg::Output &operand1, rvsdg::Output &operand2)
static std::unique_ptr< ThreeAddressCode > createTac(const Variable &operand1, const Variable &operand2)
std::shared_ptr< const rvsdg::Type > getOperandType() const noexcept
std::shared_ptr< const rvsdg::Type > getResultType() const noexcept
bool operator==(const Operation &other) const noexcept override
static rvsdg::SimpleNode & createNode(rvsdg::Output &operand1, rvsdg::Output &operand2)
static void checkOperandType(const std::shared_ptr< const rvsdg::Type > &type)
std::unique_ptr< Operation > copy() const override
~UMulWithOverflowOperation() noexcept override
const std::shared_ptr< const jlm::rvsdg::Type > Type() const noexcept
Definition variable.hpp:62
static std::shared_ptr< const BitType > Create(std::size_t nbits)
Creates bit type of specified width.
Definition type.cpp:45
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition node.hpp:366
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
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
Global memory state passed between functions.
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
Definition node.hpp:872