Jlm
Loading...
Searching...
No Matches
ConversionOperationsTests.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
6#include <gtest/gtest.h>
7
15#include <jlm/rvsdg/view.hpp>
16
17namespace jlm::llvm
18{
19TEST(ConversionOperationsTests, SExtConstantFolding)
20{
21 using namespace jlm::rvsdg;
22
23 // Arrange
24 Graph graph;
25
26 auto & zero =
28 auto & one =
30
31 auto & node1 = SExtOperation::createNode(32, *zero.output(0));
32 auto & node2 = SExtOperation::createNode(32, *one.output(0));
33
34 auto & x1 = GraphExport::Create(*node1.output(0), "x1");
35 auto & x2 = GraphExport::Create(*node2.output(0), "x2");
36
37 view(graph, stdout);
38
39 // Act
40 ReduceNode<SExtOperation>(SExtOperation::foldConstant, node1);
41 ReduceNode<SExtOperation>(SExtOperation::foldConstant, node2);
42
43 graph.PruneNodes();
44
45 view(graph, stdout);
46
47 // Assert
48 {
49 auto [_, op] = TryGetSimpleNodeAndOptionalOp<IntegerConstantOperation>(*x1.origin());
50 EXPECT_TRUE(op);
51 EXPECT_EQ(op->Representation().to_uint(), 0u);
52 EXPECT_EQ(op->Representation().nbits(), 32u);
53 }
54
55 {
56 auto [_, op] = TryGetSimpleNodeAndOptionalOp<IntegerConstantOperation>(*x2.origin());
57 EXPECT_TRUE(op);
58 EXPECT_EQ(op->Representation().to_int(), -1);
59 EXPECT_EQ(op->Representation().nbits(), 32u);
60 }
61}
62
63TEST(ConversionOperationsTests, ZExtConstantFolding)
64{
65 using namespace jlm::rvsdg;
66
67 // Arrange
68 Graph graph;
69
70 auto & zero =
72 auto & one =
74
75 auto & node1 = ZExtOperation::createNode(32, *zero.output(0));
76 auto & node2 = ZExtOperation::createNode(32, *one.output(0));
77
78 auto & x1 = GraphExport::Create(*node1.output(0), "x1");
79 auto & x2 = GraphExport::Create(*node2.output(0), "x2");
80
81 view(graph, stdout);
82
83 // Act
84 ReduceNode<ZExtOperation>(ZExtOperation::foldConstant, node1);
85 ReduceNode<ZExtOperation>(ZExtOperation::foldConstant, node2);
86
87 graph.PruneNodes();
88
89 view(graph, stdout);
90
91 // Assert
92 {
93 auto [_, op] = TryGetSimpleNodeAndOptionalOp<IntegerConstantOperation>(*x1.origin());
94 EXPECT_TRUE(op);
95 EXPECT_EQ(op->Representation().to_uint(), 0u);
96 EXPECT_EQ(op->Representation().nbits(), 32u);
97 }
98
99 {
100 auto [_, op] = TryGetSimpleNodeAndOptionalOp<IntegerConstantOperation>(*x2.origin());
101 EXPECT_TRUE(op);
102 EXPECT_EQ(op->Representation().to_int(), 1);
103 EXPECT_EQ(op->Representation().nbits(), 32u);
104 }
105}
106
107TEST(ConversionOperationsTests, TruncConstantFolding)
108{
109 using namespace jlm::rvsdg;
110
111 // Arrange
112 auto i1Type = BitType::Create(1);
113
114 Graph graph;
115
116 auto & eight =
118 auto & one =
120
121 auto & node1 = TruncOperation::createNode(*eight.output(0), i1Type);
122 auto & node2 = TruncOperation::createNode(*one.output(0), i1Type);
123
124 auto & x1 = GraphExport::Create(*node1.output(0), "x1");
125 auto & x2 = GraphExport::Create(*node2.output(0), "x2");
126
127 view(graph, stdout);
128
129 // Act
130 ReduceNode<TruncOperation>(TruncOperation::foldConstant, node1);
131 ReduceNode<TruncOperation>(TruncOperation::foldConstant, node2);
132
133 graph.PruneNodes();
134
135 view(graph, stdout);
136
137 // Assert
138 {
139 auto [_, op] = TryGetSimpleNodeAndOptionalOp<IntegerConstantOperation>(*x1.origin());
140 EXPECT_TRUE(op);
141 EXPECT_EQ(op->Representation().to_uint(), 0u);
142 EXPECT_EQ(op->Representation().nbits(), 1u);
143 }
144
145 {
146 auto [_, op] = TryGetSimpleNodeAndOptionalOp<IntegerConstantOperation>(*x2.origin());
147 EXPECT_TRUE(op);
148 EXPECT_EQ(op->Representation().to_uint(), 1u);
149 EXPECT_EQ(op->Representation().nbits(), 1u);
150 }
151}
152
153TEST(ConversionOperationsTests, FunctionToPointerInversion)
154{
155 using namespace jlm::rvsdg;
156
157 // Arrange
158 auto valueType = TestType::createValueType();
159 auto pointerType = PointerType::Create();
160 auto functionType = FunctionType::Create({ valueType }, { valueType });
161
162 Graph graph;
163
164 auto & i0 = GraphImport::Create(graph, pointerType, "i0");
165 auto & i1 = GraphImport::Create(graph, functionType, "i1");
166
167 auto & ptrToFnNode = rvsdg::CreateOpNode<PointerToFunctionOperation>({ &i0 }, functionType);
168
169 auto & fnToPtrNode1 =
170 rvsdg::CreateOpNode<FunctionToPointerOperation>({ ptrToFnNode.output(0) }, functionType);
171
172 auto & fnToPtrNode2 = rvsdg::CreateOpNode<FunctionToPointerOperation>({ &i1 }, functionType);
173
174 auto & x1 = GraphExport::Create(*fnToPtrNode1.output(0), "x1");
175 auto & x2 = GraphExport::Create(*fnToPtrNode2.output(0), "x2");
176
177 view(graph, stdout);
178
179 // Act
180 ReduceNode<FunctionToPointerOperation>(
182 fnToPtrNode1);
183
184 ReduceNode<FunctionToPointerOperation>(
186 fnToPtrNode2);
187
188 graph.PruneNodes();
189
190 view(graph, stdout);
191
192 // Assert
193 // The transformation should have been successful.
194 {
195 EXPECT_EQ(x1.origin(), &i0);
196 }
197
198 // The transformation should have failed.
199 {
200 auto [_, op] = TryGetSimpleNodeAndOptionalOp<FunctionToPointerOperation>(*x2.origin());
201 EXPECT_NE(op, nullptr);
202 }
203}
204
205TEST(ConversionOperationsTests, PointerToFunctionInversion)
206{
207 using namespace jlm::rvsdg;
208
209 // Arrange
210 auto stateType = TestType::createStateType();
211 auto valueType = TestType::createValueType();
212 auto pointerType = PointerType::Create();
213 auto functionType1 = FunctionType::Create({ valueType }, { valueType });
214 auto functionType2 = FunctionType::Create({ stateType }, { stateType });
215
216 Graph graph;
217
218 auto & i0 = GraphImport::Create(graph, functionType1, "i0");
219
220 auto & fnToPtrNode = rvsdg::CreateOpNode<FunctionToPointerOperation>({ &i0 }, functionType1);
221
222 auto & ptrToFnNode1 =
223 rvsdg::CreateOpNode<PointerToFunctionOperation>({ fnToPtrNode.output(0) }, functionType1);
224
225 auto & ptrToFnNode2 =
226 rvsdg::CreateOpNode<PointerToFunctionOperation>({ fnToPtrNode.output(0) }, functionType2);
227
228 auto & x1 = GraphExport::Create(*ptrToFnNode1.output(0), "x1");
229 auto & x2 = GraphExport::Create(*ptrToFnNode2.output(0), "x2");
230
231 view(graph, stdout);
232
233 // Act
234 ReduceNode<PointerToFunctionOperation>(
236 ptrToFnNode1);
237
238 ReduceNode<PointerToFunctionOperation>(
240 ptrToFnNode2);
241
242 graph.PruneNodes();
243
244 view(graph, stdout);
245
246 // Assert
247 // The transformation should have been successful.
248 {
249 EXPECT_EQ(x1.origin(), &i0);
250 }
251
252 // The transformation should have failed as the function types of the FunctionToPointer and
253 // PointerToFunction operations are different.
254 {
255 auto [_, op] = TryGetSimpleNodeAndOptionalOp<PointerToFunctionOperation>(*x2.origin());
256 EXPECT_NE(op, nullptr);
257 }
258}
259
260}
static std::optional< std::vector< rvsdg::Output * > > invertFunctionToPointer(const FunctionToPointerOperation &operation, const std::vector< rvsdg::Output * > &operands)
static rvsdg::Node & Create(rvsdg::Region &region, IntegerValueRepresentation representation)
static std::optional< std::vector< rvsdg::Output * > > invertPointerToFunction(const PointerToFunctionOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::shared_ptr< const PointerType > Create()
Definition types.cpp:45
static std::optional< std::vector< rvsdg::Output * > > foldConstant(const SExtOperation &operation, const std::vector< rvsdg::Output * > &operands)
static rvsdg::SimpleNode & createNode(const size_t numResultBits, rvsdg::Output &operand)
static rvsdg::SimpleNode & createNode(rvsdg::Output &operand, std::shared_ptr< const rvsdg::Type > resultType)
static std::optional< std::vector< rvsdg::Output * > > foldConstant(const TruncOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > foldConstant(const ZExtOperation &operation, const std::vector< rvsdg::Output * > &operands)
static rvsdg::SimpleNode & createNode(const size_t numResultBits, rvsdg::Output &operand)
Region & GetRootRegion() const noexcept
Definition graph.hpp:99
void PruneNodes()
Definition graph.hpp:116
Global memory state passed between functions.
TEST(ControlOperationsTests, foldConstants)
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
Definition node.hpp:872