31
31
#include < libsolutil/StringUtils.h>
32
32
#include < libsolutil/Visitor.h>
33
33
34
+ #include < range/v3/algorithm/find_if.hpp>
34
35
#include < range/v3/algorithm/replace.hpp>
35
36
#include < range/v3/range/conversion.hpp>
36
37
#include < range/v3/view/drop_last.hpp>
@@ -52,28 +53,28 @@ SSAControlFlowGraphBuilder::SSAControlFlowGraphBuilder(
52
53
AsmAnalysisInfo const & _analysisInfo,
53
54
ControlFlowSideEffectsCollector const & _sideEffects,
54
55
Dialect const & _dialect,
55
- bool _keepLiteralAssignments
56
+ bool _literalsAsPushConstants
56
57
):
57
58
m_controlFlow (_controlFlow),
58
59
m_graph (_graph),
59
60
m_info (_analysisInfo),
60
61
m_sideEffects (_sideEffects),
61
62
m_dialect (_dialect),
62
- m_keepLiteralAssignments (_keepLiteralAssignments )
63
+ m_literalsAsPushConstants (_literalsAsPushConstants )
63
64
{
64
65
}
65
66
66
67
std::unique_ptr<ControlFlow> SSAControlFlowGraphBuilder::build (
67
68
AsmAnalysisInfo const & _analysisInfo,
68
69
Dialect const & _dialect,
69
70
Block const & _block,
70
- bool _keepLiteralAssignments
71
+ bool _literalsAsPushConstants
71
72
)
72
73
{
73
74
ControlFlowSideEffectsCollector sideEffects (_dialect, _block);
74
75
75
76
auto controlFlow = std::make_unique<ControlFlow>();
76
- SSAControlFlowGraphBuilder builder (*controlFlow, *controlFlow->mainGraph , _analysisInfo, sideEffects, _dialect, _keepLiteralAssignments );
77
+ SSAControlFlowGraphBuilder builder (*controlFlow, *controlFlow->mainGraph , _analysisInfo, sideEffects, _dialect, _literalsAsPushConstants );
77
78
builder.m_currentBlock = controlFlow->mainGraph ->makeBlock (debugDataOf (_block));
78
79
builder.sealBlock (builder.m_currentBlock );
79
80
builder (_block);
@@ -86,7 +87,6 @@ std::unique_ptr<ControlFlow> SSAControlFlowGraphBuilder::build(
86
87
87
88
SSACFG::ValueId SSAControlFlowGraphBuilder::tryRemoveTrivialPhi (SSACFG::ValueId _phi)
88
89
{
89
- // TODO: double-check if this is sane
90
90
auto const * phiInfo = std::get_if<SSACFG::PhiValue>(&m_graph.valueInfo (_phi));
91
91
yulAssert (phiInfo);
92
92
yulAssert (blockInfo (phiInfo->block ).sealed );
@@ -190,8 +190,8 @@ void SSAControlFlowGraphBuilder::cleanUnreachable()
190
190
191
191
std::set<SSACFG::ValueId> maybeTrivialPhi;
192
192
for (auto it = block.entries .begin (); it != block.entries .end ();)
193
- if (reachabilityCheck.visited .count (*it))
194
- it++ ;
193
+ if (reachabilityCheck.visited .contains (*it))
194
+ ++it ;
195
195
else
196
196
it = block.entries .erase (it);
197
197
for (auto phi: block.phis )
@@ -211,10 +211,7 @@ void SSAControlFlowGraphBuilder::cleanUnreachable()
211
211
}
212
212
}
213
213
214
- void SSAControlFlowGraphBuilder::buildFunctionGraph (
215
- Scope::Function const * _function,
216
- FunctionDefinition const * _functionDefinition
217
- )
214
+ void SSAControlFlowGraphBuilder::buildFunctionGraph (Scope::Function const * _function, FunctionDefinition const * _functionDefinition)
218
215
{
219
216
m_controlFlow.functionGraphs .emplace_back (std::make_unique<SSACFG>());
220
217
auto & cfg = *m_controlFlow.functionGraphs .back ();
@@ -240,7 +237,7 @@ void SSAControlFlowGraphBuilder::buildFunctionGraph(
240
237
cfg.arguments = arguments;
241
238
cfg.returns = returns;
242
239
243
- SSAControlFlowGraphBuilder builder (m_controlFlow, cfg, m_info, m_sideEffects, m_dialect, m_keepLiteralAssignments );
240
+ SSAControlFlowGraphBuilder builder (m_controlFlow, cfg, m_info, m_sideEffects, m_dialect, m_literalsAsPushConstants );
244
241
builder.m_currentBlock = cfg.entry ;
245
242
builder.m_functionDefinitions = m_functionDefinitions;
246
243
for (auto && [var, varId]: cfg.arguments )
@@ -255,6 +252,19 @@ void SSAControlFlowGraphBuilder::buildFunctionGraph(
255
252
builder.cleanUnreachable ();
256
253
}
257
254
255
+ SSACFG::ValueId SSAControlFlowGraphBuilder::moveLiteralToVariable (SSACFG::ValueId const _value)
256
+ {
257
+ yulAssert (!m_literalsAsPushConstants);
258
+ yulAssert (m_graph.isLiteralValue (_value));
259
+ SSACFG::Operation assignment{
260
+ .outputs = {m_graph.newVariable (m_currentBlock)},
261
+ .kind = SSACFG::LiteralAssignment{},
262
+ .inputs = {_value}
263
+ };
264
+ currentBlock ().operations .emplace_back (assignment);
265
+ return assignment.outputs .back ();
266
+ }
267
+
258
268
void SSAControlFlowGraphBuilder::operator ()(ExpressionStatement const & _expressionStatement)
259
269
{
260
270
auto const * functionCall = std::get_if<FunctionCall>(&_expressionStatement.expression );
@@ -541,16 +551,8 @@ void SSAControlFlowGraphBuilder::assign(std::vector<std::reference_wrapper<Scope
541
551
542
552
for (auto const & [var, value]: ranges::zip_view (_variables, rhs))
543
553
{
544
- if (m_keepLiteralAssignments && m_graph.isLiteralValue (value))
545
- {
546
- SSACFG::Operation assignment{
547
- .outputs = {m_graph.newVariable (m_currentBlock)},
548
- .kind = SSACFG::LiteralAssignment{},
549
- .inputs = {value}
550
- };
551
- currentBlock ().operations .emplace_back (assignment);
552
- writeVariable (var, m_currentBlock, assignment.outputs .back ());
553
- }
554
+ if (!m_literalsAsPushConstants && m_graph.isLiteralValue (value))
555
+ writeVariable (var, m_currentBlock, moveLiteralToVariable (value));
554
556
else
555
557
writeVariable (var, m_currentBlock, value);
556
558
}
@@ -567,7 +569,15 @@ std::vector<SSACFG::ValueId> SSAControlFlowGraphBuilder::visitFunctionCall(Funct
567
569
SSACFG::Operation result{{}, SSACFG::BuiltinCall{_call.debugData , builtin, _call}, {}};
568
570
for (auto && [idx, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse)
569
571
if (!builtin.literalArgument (idx).has_value ())
570
- result.inputs .emplace_back (std::visit (*this , arg));
572
+ {
573
+ if (!m_literalsAsPushConstants && std::holds_alternative<Literal>(arg))
574
+ {
575
+ auto const lit = m_graph.newLiteral (debugDataOf (currentBlock ()), std::get<Literal>(arg).value .value ());
576
+ result.inputs .emplace_back (moveLiteralToVariable (lit));
577
+ }
578
+ else
579
+ result.inputs .emplace_back (std::visit (*this , arg));
580
+ }
571
581
for (size_t i = 0 ; i < builtin.numReturns ; ++i)
572
582
result.outputs .emplace_back (m_graph.newVariable (m_currentBlock));
573
583
canContinue = builtin.controlFlowSideEffects .canContinue ;
@@ -582,7 +592,15 @@ std::vector<SSACFG::ValueId> SSAControlFlowGraphBuilder::visitFunctionCall(Funct
582
592
canContinue = m_sideEffects.functionSideEffects ().at (definition).canContinue ;
583
593
SSACFG::Operation result{{}, SSACFG::Call{debugDataOf (_call), function, _call, canContinue}, {}};
584
594
for (auto const & arg: _call.arguments | ranges::views::reverse)
585
- result.inputs .emplace_back (std::visit (*this , arg));
595
+ {
596
+ if (!m_literalsAsPushConstants && std::holds_alternative<Literal>(arg))
597
+ {
598
+ auto const lit = m_graph.newLiteral (debugDataOf (currentBlock ()), std::get<Literal>(arg).value .value ());
599
+ result.inputs .emplace_back (moveLiteralToVariable (lit));
600
+ }
601
+ else
602
+ result.inputs .emplace_back (std::visit (*this , arg));
603
+ }
586
604
for (size_t i = 0 ; i < function.numReturns ; ++i)
587
605
result.outputs .emplace_back (m_graph.newVariable (m_currentBlock));
588
606
return result;
@@ -747,9 +765,8 @@ void SSAControlFlowGraphBuilder::tableJump(
747
765
748
766
FunctionDefinition const * SSAControlFlowGraphBuilder::findFunctionDefinition (Scope::Function const * _function) const
749
767
{
750
- auto it = std::find_if (
751
- m_functionDefinitions.begin (),
752
- m_functionDefinitions.end (),
768
+ auto it = ranges::find_if (
769
+ m_functionDefinitions,
753
770
[&_function](auto const & _entry) { return std::get<0 >(_entry) == _function; }
754
771
);
755
772
if (it != m_functionDefinitions.end ())
0 commit comments