Jlm
Loading...
Searching...
No Matches
ConversionOperations.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2017 Nico Reißmann <nico.reissmann@gmail.com>
3 * See COPYING for terms of redistribution.
4 */
5
9#include <jlm/util/common.hpp>
10
11namespace jlm::llvm
12{
13
14BitCastOperation::~BitCastOperation() noexcept = default;
15
16bool
17BitCastOperation::operator==(const Operation & other) const noexcept
18{
19 auto op = dynamic_cast<const BitCastOperation *>(&other);
20 return op && op->argument(0) == argument(0) && op->result(0) == result(0);
21}
22
23std::string
25{
26 return util::strfmt(
27 "BitCast[",
29 " -> ",
30 result(0)->debug_string(),
31 "]");
32}
33
34std::unique_ptr<rvsdg::Operation>
36{
37 return std::make_unique<BitCastOperation>(*this);
38}
39
40SExtOperation::~SExtOperation() noexcept = default;
41
42bool
43SExtOperation::operator==(const Operation & other) const noexcept
44{
45 auto op = dynamic_cast<const SExtOperation *>(&other);
46 return op && op->argument(0) == argument(0) && op->result(0) == result(0);
47}
48
49std::string
51{
52 return util::strfmt("SExt[", nsrcbits(), " -> ", ndstbits(), "]");
53}
54
55std::unique_ptr<rvsdg::Operation>
57{
58 return std::make_unique<SExtOperation>(*this);
59}
60
61std::optional<std::vector<rvsdg::Output *>>
63 const SExtOperation & operation,
64 const std::vector<rvsdg::Output *> & operands)
65{
66 JLM_ASSERT(operands.size() == 1);
67 auto & operand = *operands[0];
68
69 const auto & tracedOperand = llvm::traceOutput(operand);
70 auto [constantNode, constantOperation] =
72 if (!constantOperation)
73 return std::nullopt;
74
75 const auto & resultRepresentation =
76 constantOperation->Representation().sext(operation.ndstbits() - operation.nsrcbits());
77
78 auto result = IntegerConstantOperation::Create(*operand.region(), resultRepresentation).output(0);
79
80 return std::vector<rvsdg::Output *>({ result });
81}
82
83ZExtOperation::~ZExtOperation() noexcept = default;
84
85bool
86ZExtOperation::operator==(const Operation & other) const noexcept
87{
88 const auto op = dynamic_cast<const ZExtOperation *>(&other);
89 return op && op->argument(0) == argument(0) && op->result(0) == result(0);
90}
91
92std::string
94{
95 return util::strfmt("ZExt[", nsrcbits(), " -> ", ndstbits(), "]");
96}
97
98std::unique_ptr<rvsdg::Operation>
100{
101 return std::make_unique<ZExtOperation>(*this);
102}
103
104std::optional<std::vector<rvsdg::Output *>>
106 const ZExtOperation & operation,
107 const std::vector<rvsdg::Output *> & operands)
108{
109 JLM_ASSERT(operands.size() == 1);
110 auto & operand = *operands[0];
111
112 const auto & tracedOperand = llvm::traceOutput(operand);
113 auto [constantNode, constantOperation] =
115 if (!constantOperation)
116 return std::nullopt;
117
118 const auto & resultRepresentation =
119 constantOperation->Representation().zext(operation.ndstbits() - operation.nsrcbits());
120
121 auto result = IntegerConstantOperation::Create(*operand.region(), resultRepresentation).output(0);
122
123 return std::vector<rvsdg::Output *>({ result });
124}
125
126TruncOperation::~TruncOperation() noexcept = default;
127
128bool
129TruncOperation::operator==(const Operation & other) const noexcept
130{
131 const auto op = dynamic_cast<const TruncOperation *>(&other);
132 return op && op->argument(0) == argument(0) && op->result(0) == result(0);
133}
134
135std::string
137{
138 return util::strfmt("Trunc[", nsrcbits(), " -> ", ndstbits(), "]");
139}
140
141std::unique_ptr<rvsdg::Operation>
143{
144 return std::make_unique<TruncOperation>(*this);
145}
146
147std::optional<std::vector<rvsdg::Output *>>
149 const TruncOperation & operation,
150 const std::vector<rvsdg::Output *> & operands)
151{
152 JLM_ASSERT(operands.size() == 1);
153 auto & operand = *operands[0];
154
155 const auto & tracedOperand = llvm::traceOutput(operand);
156 auto [constantNode, constantOperation] =
158 if (!constantOperation)
159 return std::nullopt;
160
161 const auto & resultRepresentation =
162 constantOperation->Representation().trunc(operation.ndstbits());
163
164 auto result = IntegerConstantOperation::Create(*operand.region(), resultRepresentation).output(0);
165
166 return std::vector<rvsdg::Output *>({ result });
167}
168
169PtrToIntOperation::~PtrToIntOperation() noexcept = default;
170
171bool
172PtrToIntOperation::operator==(const Operation & other) const noexcept
173{
174 const auto op = dynamic_cast<const PtrToIntOperation *>(&other);
175 return op && op->argument(0) == argument(0) && op->result(0) == result(0);
176}
177
178std::string
180{
181 return "PtrToInt";
182}
183
184std::unique_ptr<rvsdg::Operation>
186{
187 return std::make_unique<PtrToIntOperation>(*this);
188}
189
190FPExtOperation::~FPExtOperation() noexcept = default;
191
192bool
193FPExtOperation::operator==(const Operation & other) const noexcept
194{
195 const auto op = dynamic_cast<const FPExtOperation *>(&other);
196 return op && op->srcsize() == srcsize() && op->dstsize() == dstsize();
197}
198
199std::string
201{
202 return "FPExt";
203}
204
205std::unique_ptr<rvsdg::Operation>
207{
208 return std::make_unique<FPExtOperation>(*this);
209}
210
211FPTruncOperation::~FPTruncOperation() noexcept = default;
212
213bool
214FPTruncOperation::operator==(const Operation & other) const noexcept
215{
216 const auto op = dynamic_cast<const FPTruncOperation *>(&other);
217 return op && op->srcsize() == srcsize() && op->dstsize() == dstsize();
218}
219
220std::string
222{
223 return "FPTrunc";
224}
225
226std::unique_ptr<rvsdg::Operation>
228{
229 return std::make_unique<FPTruncOperation>(*this);
230}
231
232UIToFPOperation::~UIToFPOperation() noexcept = default;
233
234bool
235UIToFPOperation::operator==(const Operation & other) const noexcept
236{
237 const auto op = dynamic_cast<const UIToFPOperation *>(&other);
238 return op && op->argument(0) == argument(0) && op->result(0) == result(0);
239}
240
241std::string
243{
244 return "UIToFP";
245}
246
247std::unique_ptr<rvsdg::Operation>
249{
250 return std::make_unique<UIToFPOperation>(*this);
251}
252
253SIToFPOperation::~SIToFPOperation() noexcept = default;
254
255bool
256SIToFPOperation::operator==(const Operation & other) const noexcept
257{
258 const auto op = dynamic_cast<const SIToFPOperation *>(&other);
259 return op && op->argument(0) == argument(0) && op->result(0) == result(0);
260}
261
262std::string
264{
265 return "SIToFP";
266}
267
268std::unique_ptr<rvsdg::Operation>
270{
271 return std::make_unique<SIToFPOperation>(*this);
272}
273
274IntToPtrOperation::~IntToPtrOperation() noexcept = default;
275
276bool
277IntToPtrOperation::operator==(const Operation & other) const noexcept
278{
279 const auto op = dynamic_cast<const IntToPtrOperation *>(&other);
280 return op && op->argument(0) == argument(0);
281}
282
283std::string
285{
286 return "IntToPtr";
287}
288
289std::unique_ptr<rvsdg::Operation>
291{
292 return std::make_unique<IntToPtrOperation>(*this);
293}
294
295FPToUIOperation::~FPToUIOperation() noexcept = default;
296
297bool
298FPToUIOperation::operator==(const Operation & other) const noexcept
299{
300 const auto op = dynamic_cast<const FPToUIOperation *>(&other);
301 return op && op->argument(0) == argument(0) && op->result(0) == result(0);
302}
303
304std::string
306{
307 return "FpToUInt";
308}
309
310std::unique_ptr<rvsdg::Operation>
312{
313 return std::make_unique<FPToUIOperation>(*this);
314}
315
316FPToSIOperation::~FPToSIOperation() noexcept = default;
317
318bool
319FPToSIOperation::operator==(const Operation & other) const noexcept
320{
321 const auto op = dynamic_cast<const FPToSIOperation *>(&other);
322 return op && op->argument(0) == argument(0) && op->result(0) == result(0);
323}
324
325std::string
327{
328 return "FpToSInt";
329}
330
331std::unique_ptr<rvsdg::Operation>
333{
334 return std::make_unique<FPToSIOperation>(*this);
335}
336
338
339bool
340ControlToIntOperation::operator==(const Operation & other) const noexcept
341{
342 auto op = dynamic_cast<const ControlToIntOperation *>(&other);
343 return op && op->argument(0) == argument(0) && op->result(0) == result(0);
344}
345
346std::string
348{
349 return "ControlToInt";
350}
351
352std::unique_ptr<rvsdg::Operation>
354{
355 return std::make_unique<ControlToIntOperation>(*this);
356}
357
360
362 std::shared_ptr<const rvsdg::FunctionType> fn)
363 : UnaryOperation(fn, PointerType::Create()),
364 FunctionType_(std::move(fn))
365{}
366
367bool
368FunctionToPointerOperation::operator==(const Operation & other) const noexcept
369{
370 if (auto o = dynamic_cast<const FunctionToPointerOperation *>(&other))
371 {
372 return *FunctionType() == *o->FunctionType();
373 }
374 else
375 {
376 return false;
377 }
378}
379
380[[nodiscard]] std::string
382{
383 return "FunPtr(" + FunctionType()->debug_string() + ")";
384}
385
386[[nodiscard]] std::unique_ptr<rvsdg::Operation>
388{
389 return Create(FunctionType());
390}
391
392std::unique_ptr<FunctionToPointerOperation>
393FunctionToPointerOperation::Create(std::shared_ptr<const rvsdg::FunctionType> fn)
394{
395 return std::make_unique<FunctionToPointerOperation>(std::move(fn));
396}
397
398std::optional<std::vector<rvsdg::Output *>>
400 const FunctionToPointerOperation & operation,
401 const std::vector<rvsdg::Output *> & operands)
402{
403 JLM_ASSERT(operands.size() == 1);
404 const auto & operand = *operands[0];
405
406 if (const auto node = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(operand))
407 {
408 if (const auto ptrToFnOperation =
409 dynamic_cast<const PointerToFunctionOperation *>(&node->GetOperation()))
410 {
411 if (*ptrToFnOperation->FunctionType() == *operation.FunctionType())
412 {
413 return std::vector({ node->input(0)->origin() });
414 }
415 }
416 }
417
418 return std::nullopt;
419}
420
423
425 std::shared_ptr<const rvsdg::FunctionType> fn)
426 : UnaryOperation(PointerType::Create(), fn),
427 FunctionType_(std::move(fn))
428{}
429
430bool
431PointerToFunctionOperation::operator==(const Operation & other) const noexcept
432{
433 if (auto o = dynamic_cast<const PointerToFunctionOperation *>(&other))
434 {
435 return *FunctionType() == *o->FunctionType();
436 }
437 else
438 {
439 return false;
440 }
441}
442
443[[nodiscard]] std::string
445{
446 return "PtrFun(" + FunctionType()->debug_string() + ")";
447}
448
449[[nodiscard]] std::unique_ptr<rvsdg::Operation>
451{
452 return Create(FunctionType());
453}
454
455std::optional<std::vector<rvsdg::Output *>>
457 const PointerToFunctionOperation & operation,
458 const std::vector<rvsdg::Output *> & operands)
459{
460 JLM_ASSERT(operands.size() == 1);
461 const auto & operand = *operands[0];
462
463 if (const auto node = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(operand))
464 {
465 if (const auto fnToPtrOperation =
466 dynamic_cast<const FunctionToPointerOperation *>(&node->GetOperation()))
467 {
468 if (*fnToPtrOperation->FunctionType() == *operation.FunctionType())
469 {
470 return std::vector({ node->input(0)->origin() });
471 }
472 }
473 }
474
475 return std::nullopt;
476}
477
478std::unique_ptr<PointerToFunctionOperation>
479PointerToFunctionOperation::Create(std::shared_ptr<const rvsdg::FunctionType> fn)
480{
481 return std::make_unique<PointerToFunctionOperation>(std::move(fn));
482}
483
484}
std::string debug_string() const override
std::unique_ptr< Operation > copy() const override
~BitCastOperation() noexcept override
std::string debug_string() const override
~ControlToIntOperation() noexcept override
std::unique_ptr< Operation > copy() const override
const fpsize & srcsize() const noexcept
~FPExtOperation() noexcept override
std::string debug_string() const override
std::unique_ptr< Operation > copy() const override
~FPToSIOperation() noexcept override
std::unique_ptr< Operation > copy() const override
std::string debug_string() const override
~FPToUIOperation() noexcept override
std::unique_ptr< Operation > copy() const override
std::string debug_string() const override
const fpsize & srcsize() const noexcept
std::unique_ptr< Operation > copy() const override
std::string debug_string() const override
~FPTruncOperation() noexcept override
Get address of compiled function object.
std::unique_ptr< Operation > copy() const override
static std::optional< std::vector< rvsdg::Output * > > invertFunctionToPointer(const FunctionToPointerOperation &operation, const std::vector< rvsdg::Output * > &operands)
bool operator==(const Operation &other) const noexcept override
static std::unique_ptr< FunctionToPointerOperation > Create(std::shared_ptr< const rvsdg::FunctionType > fn)
FunctionToPointerOperation(std::shared_ptr< const rvsdg::FunctionType > fn)
const std::shared_ptr< const rvsdg::FunctionType > & FunctionType() const noexcept
std::string debug_string() const override
~IntToPtrOperation() noexcept override
std::unique_ptr< Operation > copy() const override
static rvsdg::Node & Create(rvsdg::Region &region, IntegerValueRepresentation representation)
Interpret pointer as callable function.
static std::optional< std::vector< rvsdg::Output * > > invertPointerToFunction(const PointerToFunctionOperation &operation, const std::vector< rvsdg::Output * > &operands)
PointerToFunctionOperation(std::shared_ptr< const rvsdg::FunctionType > fn)
std::unique_ptr< Operation > copy() const override
bool operator==(const Operation &other) const noexcept override
const std::shared_ptr< const rvsdg::FunctionType > & FunctionType() const noexcept
static std::unique_ptr< PointerToFunctionOperation > Create(std::shared_ptr< const rvsdg::FunctionType > fn)
PointerType class.
Definition types.hpp:25
std::unique_ptr< Operation > copy() const override
std::string debug_string() const override
~PtrToIntOperation() noexcept override
static std::optional< std::vector< rvsdg::Output * > > foldConstant(const SExtOperation &operation, const std::vector< rvsdg::Output * > &operands)
~SExtOperation() noexcept override
std::string debug_string() const override
std::unique_ptr< Operation > copy() const override
size_t nsrcbits() const noexcept
size_t ndstbits() const noexcept
~SIToFPOperation() noexcept override
std::unique_ptr< Operation > copy() const override
std::string debug_string() const override
std::string debug_string() const override
~TruncOperation() noexcept override
size_t ndstbits() const noexcept
static std::optional< std::vector< rvsdg::Output * > > foldConstant(const TruncOperation &operation, const std::vector< rvsdg::Output * > &operands)
size_t nsrcbits() const noexcept
std::unique_ptr< Operation > copy() const override
std::string debug_string() const override
std::unique_ptr< Operation > copy() const override
~UIToFPOperation() noexcept override
std::string debug_string() const override
size_t nsrcbits() const noexcept
static std::optional< std::vector< rvsdg::Output * > > foldConstant(const ZExtOperation &operation, const std::vector< rvsdg::Output * > &operands)
~ZExtOperation() noexcept override
std::unique_ptr< Operation > copy() const override
size_t ndstbits() const noexcept
NodeOutput * output(size_t index) const noexcept
Definition node.hpp:650
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
#define JLM_ASSERT(x)
Definition common.hpp:16
Global memory state passed between functions.
rvsdg::Output & traceOutput(rvsdg::Output &output, const rvsdg::Region *withinRegion)
Definition Trace.cpp:62
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
Definition node.hpp:872
static std::string strfmt(Args... args)
Definition strfmt.hpp:35