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
10#include <jlm/util/common.hpp>
11
12namespace jlm::llvm
13{
14
15BitCastOperation::~BitCastOperation() noexcept = default;
16
17bool
18BitCastOperation::operator==(const Operation & other) const noexcept
19{
20 auto op = dynamic_cast<const BitCastOperation *>(&other);
21 return op && op->argument(0) == argument(0) && op->result(0) == result(0);
22}
23
24std::string
26{
27 return util::strfmt(
28 "BitCast[",
30 " -> ",
31 result(0)->debug_string(),
32 "]");
33}
34
35std::unique_ptr<rvsdg::Operation>
37{
38 return std::make_unique<BitCastOperation>(*this);
39}
40
41SExtOperation::~SExtOperation() noexcept = default;
42
43bool
44SExtOperation::operator==(const Operation & other) const noexcept
45{
46 auto op = dynamic_cast<const SExtOperation *>(&other);
47 return op && op->argument(0) == argument(0) && op->result(0) == result(0);
48}
49
50std::string
52{
53 return util::strfmt("SExt[", nsrcbits(), " -> ", ndstbits(), "]");
54}
55
56std::unique_ptr<rvsdg::Operation>
58{
59 return std::make_unique<SExtOperation>(*this);
60}
61
62std::optional<std::vector<rvsdg::Output *>>
64 const SExtOperation & operation,
65 const std::vector<rvsdg::Output *> & operands)
66{
67 JLM_ASSERT(operands.size() == 1);
68 auto & operand = *operands[0];
69
70 const auto & tracedOperand = llvm::traceOutput(operand, true);
71 auto [constantNode, constantOperation] =
73 if (!constantOperation)
74 return std::nullopt;
75
76 const auto & resultRepresentation =
77 constantOperation->Representation().sext(operation.ndstbits() - operation.nsrcbits());
78
79 auto result = IntegerConstantOperation::Create(*operand.region(), resultRepresentation).output(0);
80
81 return std::vector<rvsdg::Output *>({ result });
82}
83
84ZExtOperation::~ZExtOperation() noexcept = default;
85
86bool
87ZExtOperation::operator==(const Operation & other) const noexcept
88{
89 const auto op = dynamic_cast<const ZExtOperation *>(&other);
90 return op && op->argument(0) == argument(0) && op->result(0) == result(0);
91}
92
93std::string
95{
96 return util::strfmt("ZExt[", nsrcbits(), " -> ", ndstbits(), "]");
97}
98
99std::unique_ptr<rvsdg::Operation>
101{
102 return std::make_unique<ZExtOperation>(*this);
103}
104
105std::optional<std::vector<rvsdg::Output *>>
107 const ZExtOperation & operation,
108 const std::vector<rvsdg::Output *> & operands)
109{
110 JLM_ASSERT(operands.size() == 1);
111 auto & operand = *operands[0];
112
113 const auto & tracedOperand = llvm::traceOutput(operand, true);
114 auto [constantNode, constantOperation] =
116 if (!constantOperation)
117 return std::nullopt;
118
119 const auto & resultRepresentation =
120 constantOperation->Representation().zext(operation.ndstbits() - operation.nsrcbits());
121
122 auto result = IntegerConstantOperation::Create(*operand.region(), resultRepresentation).output(0);
123
124 return std::vector<rvsdg::Output *>({ result });
125}
126
127TruncOperation::~TruncOperation() noexcept = default;
128
129bool
130TruncOperation::operator==(const Operation & other) const noexcept
131{
132 const auto op = dynamic_cast<const TruncOperation *>(&other);
133 return op && op->argument(0) == argument(0) && op->result(0) == result(0);
134}
135
136std::string
138{
139 return util::strfmt("Trunc[", nsrcbits(), " -> ", ndstbits(), "]");
140}
141
142std::unique_ptr<rvsdg::Operation>
144{
145 return std::make_unique<TruncOperation>(*this);
146}
147
148std::optional<std::vector<rvsdg::Output *>>
150 const TruncOperation & operation,
151 const std::vector<rvsdg::Output *> & operands)
152{
153 JLM_ASSERT(operands.size() == 1);
154 auto & operand = *operands[0];
155
156 const auto & tracedOperand = llvm::traceOutput(operand, true);
157 auto [constantNode, constantOperation] =
159 if (!constantOperation)
160 return std::nullopt;
161
162 const auto & resultRepresentation =
163 constantOperation->Representation().trunc(operation.ndstbits());
164
165 auto result = IntegerConstantOperation::Create(*operand.region(), resultRepresentation).output(0);
166
167 return std::vector<rvsdg::Output *>({ result });
168}
169
170PtrToIntOperation::~PtrToIntOperation() noexcept = default;
171
172bool
173PtrToIntOperation::operator==(const Operation & other) const noexcept
174{
175 const auto op = dynamic_cast<const PtrToIntOperation *>(&other);
176 return op && op->argument(0) == argument(0) && op->result(0) == result(0);
177}
178
179std::string
181{
182 return "PtrToInt";
183}
184
185std::unique_ptr<rvsdg::Operation>
187{
188 return std::make_unique<PtrToIntOperation>(*this);
189}
190
191FPExtOperation::~FPExtOperation() noexcept = default;
192
193bool
194FPExtOperation::operator==(const Operation & other) const noexcept
195{
196 const auto op = dynamic_cast<const FPExtOperation *>(&other);
197 return op && op->srcsize() == srcsize() && op->dstsize() == dstsize();
198}
199
200std::string
202{
203 return "FPExt";
204}
205
206std::unique_ptr<rvsdg::Operation>
208{
209 return std::make_unique<FPExtOperation>(*this);
210}
211
212static const ::llvm::fltSemantics &
214{
215 switch (size)
216 {
217 case fpsize::half:
218 return ::llvm::APFloat::IEEEhalf();
219 case fpsize::flt:
220 return ::llvm::APFloat::IEEEsingle();
221 case fpsize::dbl:
222 return ::llvm::APFloat::IEEEdouble();
223 case fpsize::x86fp80:
224 return ::llvm::APFloat::x87DoubleExtended();
225 case fpsize::fp128:
226 return ::llvm::APFloat::IEEEquad();
227 default:
228 JLM_UNREACHABLE("Unknown float size");
229 }
230}
231
232std::optional<std::vector<rvsdg::Output *>>
234 const FPExtOperation & operation,
235 const std::vector<rvsdg::Output *> & operands)
236{
237 JLM_ASSERT(operands.size() == 1);
238 auto & operand = *operands[0];
239
240 const auto & tracedOperand = llvm::traceOutput(operand, true);
241 auto [constantNode, constantOperation] =
243 if (!constantOperation)
244 return std::nullopt;
245
246 bool ignored = false;
247 ::llvm::APFloat resultRepresentation = constantOperation->constant();
248 resultRepresentation.convert(
249 mapToLlvmFltSemantics(operation.dstsize()),
250 ::llvm::APFloat::rmNearestTiesToEven,
251 &ignored);
252
253 auto & resultNode =
254 ConstantFP::createNode(*operand.region(), operation.dstsize(), resultRepresentation);
255
256 return std::vector<rvsdg::Output *>({ resultNode.output(0) });
257}
258
259FPTruncOperation::~FPTruncOperation() noexcept = default;
260
261bool
262FPTruncOperation::operator==(const Operation & other) const noexcept
263{
264 const auto op = dynamic_cast<const FPTruncOperation *>(&other);
265 return op && op->srcsize() == srcsize() && op->dstsize() == dstsize();
266}
267
268std::string
270{
271 return "FPTrunc";
272}
273
274std::unique_ptr<rvsdg::Operation>
276{
277 return std::make_unique<FPTruncOperation>(*this);
278}
279
280std::optional<std::vector<rvsdg::Output *>>
282 const FPTruncOperation & operation,
283 const std::vector<rvsdg::Output *> & operands)
284{
285 JLM_ASSERT(operands.size() == 1);
286 auto & operand = *operands[0];
287
288 const auto & tracedOperand = llvm::traceOutput(operand, true);
289 auto [constantNode, constantOperation] =
291 if (!constantOperation)
292 return std::nullopt;
293
294 bool ignored = false;
295 ::llvm::APFloat resultRepresentation = constantOperation->constant();
296 resultRepresentation.convert(
297 mapToLlvmFltSemantics(operation.dstsize()),
298 ::llvm::APFloat::rmNearestTiesToEven,
299 &ignored);
300
301 auto & resultNode =
302 ConstantFP::createNode(*operand.region(), operation.dstsize(), resultRepresentation);
303
304 return std::vector<rvsdg::Output *>({ resultNode.output(0) });
305}
306
307UIToFPOperation::~UIToFPOperation() noexcept = default;
308
309bool
310UIToFPOperation::operator==(const Operation & other) const noexcept
311{
312 const auto op = dynamic_cast<const UIToFPOperation *>(&other);
313 return op && op->argument(0) == argument(0) && op->result(0) == result(0);
314}
315
316std::string
318{
319 return "UIToFP";
320}
321
322std::unique_ptr<rvsdg::Operation>
324{
325 return std::make_unique<UIToFPOperation>(*this);
326}
327
328SIToFPOperation::~SIToFPOperation() noexcept = default;
329
330bool
331SIToFPOperation::operator==(const Operation & other) const noexcept
332{
333 const auto op = dynamic_cast<const SIToFPOperation *>(&other);
334 return op && op->argument(0) == argument(0) && op->result(0) == result(0);
335}
336
337std::string
339{
340 return "SIToFP";
341}
342
343std::unique_ptr<rvsdg::Operation>
345{
346 return std::make_unique<SIToFPOperation>(*this);
347}
348
349IntToPtrOperation::~IntToPtrOperation() noexcept = default;
350
351bool
352IntToPtrOperation::operator==(const Operation & other) const noexcept
353{
354 const auto op = dynamic_cast<const IntToPtrOperation *>(&other);
355 return op && op->argument(0) == argument(0);
356}
357
358std::string
360{
361 return "IntToPtr";
362}
363
364std::unique_ptr<rvsdg::Operation>
366{
367 return std::make_unique<IntToPtrOperation>(*this);
368}
369
370FPToUIOperation::~FPToUIOperation() noexcept = default;
371
372bool
373FPToUIOperation::operator==(const Operation & other) const noexcept
374{
375 const auto op = dynamic_cast<const FPToUIOperation *>(&other);
376 return op && op->argument(0) == argument(0) && op->result(0) == result(0);
377}
378
379std::string
381{
382 return "FpToUInt";
383}
384
385std::unique_ptr<rvsdg::Operation>
387{
388 return std::make_unique<FPToUIOperation>(*this);
389}
390
391FPToSIOperation::~FPToSIOperation() noexcept = default;
392
393bool
394FPToSIOperation::operator==(const Operation & other) const noexcept
395{
396 const auto op = dynamic_cast<const FPToSIOperation *>(&other);
397 return op && op->argument(0) == argument(0) && op->result(0) == result(0);
398}
399
400std::string
402{
403 return "FpToSInt";
404}
405
406std::unique_ptr<rvsdg::Operation>
408{
409 return std::make_unique<FPToSIOperation>(*this);
410}
411
413
414bool
415ControlToIntOperation::operator==(const Operation & other) const noexcept
416{
417 auto op = dynamic_cast<const ControlToIntOperation *>(&other);
418 return op && op->argument(0) == argument(0) && op->result(0) == result(0);
419}
420
421std::string
423{
424 return "ControlToInt";
425}
426
427std::unique_ptr<rvsdg::Operation>
429{
430 return std::make_unique<ControlToIntOperation>(*this);
431}
432
435
437 std::shared_ptr<const rvsdg::FunctionType> fn)
438 : UnaryOperation(fn, PointerType::Create()),
439 FunctionType_(std::move(fn))
440{}
441
442bool
443FunctionToPointerOperation::operator==(const Operation & other) const noexcept
444{
445 if (auto o = dynamic_cast<const FunctionToPointerOperation *>(&other))
446 {
447 return *FunctionType() == *o->FunctionType();
448 }
449 else
450 {
451 return false;
452 }
453}
454
455[[nodiscard]] std::string
457{
458 return "FunPtr(" + FunctionType()->debug_string() + ")";
459}
460
461[[nodiscard]] std::unique_ptr<rvsdg::Operation>
463{
464 return Create(FunctionType());
465}
466
467std::unique_ptr<FunctionToPointerOperation>
468FunctionToPointerOperation::Create(std::shared_ptr<const rvsdg::FunctionType> fn)
469{
470 return std::make_unique<FunctionToPointerOperation>(std::move(fn));
471}
472
473std::optional<std::vector<rvsdg::Output *>>
475 const FunctionToPointerOperation & operation,
476 const std::vector<rvsdg::Output *> & operands)
477{
478 JLM_ASSERT(operands.size() == 1);
479 const auto & operand = *operands[0];
480
481 if (const auto node = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(operand))
482 {
483 if (const auto ptrToFnOperation =
484 dynamic_cast<const PointerToFunctionOperation *>(&node->GetOperation()))
485 {
486 if (*ptrToFnOperation->FunctionType() == *operation.FunctionType())
487 {
488 return std::vector({ node->input(0)->origin() });
489 }
490 }
491 }
492
493 return std::nullopt;
494}
495
498
500 std::shared_ptr<const rvsdg::FunctionType> fn)
501 : UnaryOperation(PointerType::Create(), fn),
502 FunctionType_(std::move(fn))
503{}
504
505bool
506PointerToFunctionOperation::operator==(const Operation & other) const noexcept
507{
508 if (auto o = dynamic_cast<const PointerToFunctionOperation *>(&other))
509 {
510 return *FunctionType() == *o->FunctionType();
511 }
512 else
513 {
514 return false;
515 }
516}
517
518[[nodiscard]] std::string
520{
521 return "PtrFun(" + FunctionType()->debug_string() + ")";
522}
523
524[[nodiscard]] std::unique_ptr<rvsdg::Operation>
526{
527 return Create(FunctionType());
528}
529
530std::optional<std::vector<rvsdg::Output *>>
532 const PointerToFunctionOperation & operation,
533 const std::vector<rvsdg::Output *> & operands)
534{
535 JLM_ASSERT(operands.size() == 1);
536 const auto & operand = *operands[0];
537
538 if (const auto node = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(operand))
539 {
540 if (const auto fnToPtrOperation =
541 dynamic_cast<const FunctionToPointerOperation *>(&node->GetOperation()))
542 {
543 if (*fnToPtrOperation->FunctionType() == *operation.FunctionType())
544 {
545 return std::vector({ node->input(0)->origin() });
546 }
547 }
548 }
549
550 return std::nullopt;
551}
552
553std::unique_ptr<PointerToFunctionOperation>
554PointerToFunctionOperation::Create(std::shared_ptr<const rvsdg::FunctionType> fn)
555{
556 return std::make_unique<PointerToFunctionOperation>(std::move(fn));
557}
558
559}
std::string debug_string() const override
std::unique_ptr< Operation > copy() const override
~BitCastOperation() noexcept override
static rvsdg::Node & createNode(rvsdg::Region &region, fpsize size, const ::llvm::APFloat &constant)
std::string debug_string() const override
~ControlToIntOperation() noexcept override
std::unique_ptr< Operation > copy() const override
const fpsize & srcsize() const noexcept
static std::optional< std::vector< rvsdg::Output * > > foldConstant(const FPExtOperation &operation, const std::vector< rvsdg::Output * > &operands)
~FPExtOperation() noexcept override
std::string debug_string() const override
std::unique_ptr< Operation > copy() const override
const fpsize & dstsize() const noexcept
~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
static std::optional< std::vector< rvsdg::Output * > > foldConstant(const FPTruncOperation &operation, const std::vector< rvsdg::Output * > &operands)
const fpsize & dstsize() const noexcept
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
#define JLM_UNREACHABLE(msg)
Definition common.hpp:43
Global memory state passed between functions.
rvsdg::Output & traceOutput(rvsdg::Output &output, bool mayEnterSubregions, const rvsdg::Region *withinRegion)
Definition Trace.cpp:84
static const ::llvm::fltSemantics & mapToLlvmFltSemantics(const fpsize size)
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