Skip to content

Commit 0af0190

Browse files
committed
Use variables also for literals that are function arguments
1 parent d6a396e commit 0af0190

File tree

15 files changed

+2487
-800
lines changed

15 files changed

+2487
-800
lines changed

libyul/YulStack.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -394,15 +394,15 @@ Json YulStack::cfgJson() const
394394
yulAssert(m_parserResult->analysisInfo, "");
395395
// FIXME: we should not regenerate the cfg, but for now this is sufficient for testing purposes
396396
auto exportCFGFromObject = [&](Object const& _object) -> Json {
397-
// with this set to `true`, assignments of the type `let x := 42` are preserved and added as assignment
398-
// operations to the control flow graphs
399-
bool constexpr keepLiteralAssignments = true;
397+
// with this set to `false`, all literals get their own variable assignments (except for immediate literal
398+
// arguments of builtins)
399+
bool constexpr treatLiteralsAsPushConstants = false;
400400
// NOTE: The block Ids are reset for each object
401401
std::unique_ptr<ControlFlow> controlFlow = SSAControlFlowGraphBuilder::build(
402402
*_object.analysisInfo,
403403
languageToDialect(m_language, m_evmVersion, m_eofVersion),
404404
_object.code()->root(),
405-
keepLiteralAssignments
405+
treatLiteralsAsPushConstants
406406
);
407407
std::unique_ptr<ControlFlowLiveness> liveness = std::make_unique<ControlFlowLiveness>(*controlFlow);
408408
YulControlFlowGraphExporter exporter(*controlFlow, liveness.get());

libyul/backends/evm/SSAControlFlowGraphBuilder.cpp

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
* Transformation of a Yul AST into a control flow graph.
2020
*/
2121

22+
#include "SSAControlFlowGraph.h"
23+
24+
2225
#include <libyul/backends/evm/SSAControlFlowGraphBuilder.h>
2326

2427
#include <libyul/backends/evm/ControlFlow.h>
@@ -52,28 +55,28 @@ SSAControlFlowGraphBuilder::SSAControlFlowGraphBuilder(
5255
AsmAnalysisInfo const& _analysisInfo,
5356
ControlFlowSideEffectsCollector const& _sideEffects,
5457
Dialect const& _dialect,
55-
bool _keepLiteralAssignments
58+
bool _literalsAsPushConstants
5659
):
5760
m_controlFlow(_controlFlow),
5861
m_graph(_graph),
5962
m_info(_analysisInfo),
6063
m_sideEffects(_sideEffects),
6164
m_dialect(_dialect),
62-
m_keepLiteralAssignments(_keepLiteralAssignments)
65+
m_literalsAsPushConstants(_literalsAsPushConstants)
6366
{
6467
}
6568

6669
std::unique_ptr<ControlFlow> SSAControlFlowGraphBuilder::build(
6770
AsmAnalysisInfo const& _analysisInfo,
6871
Dialect const& _dialect,
6972
Block const& _block,
70-
bool _keepLiteralAssignments
73+
bool _literalsAsPushConstants
7174
)
7275
{
7376
ControlFlowSideEffectsCollector sideEffects(_dialect, _block);
7477

7578
auto controlFlow = std::make_unique<ControlFlow>();
76-
SSAControlFlowGraphBuilder builder(*controlFlow, *controlFlow->mainGraph, _analysisInfo, sideEffects, _dialect, _keepLiteralAssignments);
79+
SSAControlFlowGraphBuilder builder(*controlFlow, *controlFlow->mainGraph, _analysisInfo, sideEffects, _dialect, _literalsAsPushConstants);
7780
builder.m_currentBlock = controlFlow->mainGraph->makeBlock(debugDataOf(_block));
7881
builder.sealBlock(builder.m_currentBlock);
7982
builder(_block);
@@ -211,10 +214,7 @@ void SSAControlFlowGraphBuilder::cleanUnreachable()
211214
}
212215
}
213216

214-
void SSAControlFlowGraphBuilder::buildFunctionGraph(
215-
Scope::Function const* _function,
216-
FunctionDefinition const* _functionDefinition
217-
)
217+
void SSAControlFlowGraphBuilder::buildFunctionGraph(Scope::Function const* _function, FunctionDefinition const* _functionDefinition)
218218
{
219219
m_controlFlow.functionGraphs.emplace_back(std::make_unique<SSACFG>());
220220
auto& cfg = *m_controlFlow.functionGraphs.back();
@@ -240,7 +240,7 @@ void SSAControlFlowGraphBuilder::buildFunctionGraph(
240240
cfg.arguments = arguments;
241241
cfg.returns = returns;
242242

243-
SSAControlFlowGraphBuilder builder(m_controlFlow, cfg, m_info, m_sideEffects, m_dialect, m_keepLiteralAssignments);
243+
SSAControlFlowGraphBuilder builder(m_controlFlow, cfg, m_info, m_sideEffects, m_dialect, m_literalsAsPushConstants);
244244
builder.m_currentBlock = cfg.entry;
245245
builder.m_functionDefinitions = m_functionDefinitions;
246246
for (auto&& [var, varId]: cfg.arguments)
@@ -255,6 +255,19 @@ void SSAControlFlowGraphBuilder::buildFunctionGraph(
255255
builder.cleanUnreachable();
256256
}
257257

258+
SSACFG::ValueId SSAControlFlowGraphBuilder::moveLiteralToVariable(SSACFG::ValueId const _value)
259+
{
260+
yulAssert(!m_literalsAsPushConstants);
261+
yulAssert(m_graph.isLiteralValue(_value));
262+
SSACFG::Operation assignment{
263+
.outputs = {m_graph.newVariable(m_currentBlock)},
264+
.kind = SSACFG::LiteralAssignment{},
265+
.inputs = {_value}
266+
};
267+
currentBlock().operations.emplace_back(assignment);
268+
return assignment.outputs.back();
269+
}
270+
258271
void SSAControlFlowGraphBuilder::operator()(ExpressionStatement const& _expressionStatement)
259272
{
260273
auto const* functionCall = std::get_if<FunctionCall>(&_expressionStatement.expression);
@@ -541,16 +554,8 @@ void SSAControlFlowGraphBuilder::assign(std::vector<std::reference_wrapper<Scope
541554

542555
for (auto const& [var, value]: ranges::zip_view(_variables, rhs))
543556
{
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-
}
557+
if (!m_literalsAsPushConstants && m_graph.isLiteralValue(value))
558+
writeVariable(var, m_currentBlock, moveLiteralToVariable(value));
554559
else
555560
writeVariable(var, m_currentBlock, value);
556561
}
@@ -567,7 +572,15 @@ std::vector<SSACFG::ValueId> SSAControlFlowGraphBuilder::visitFunctionCall(Funct
567572
SSACFG::Operation result{{}, SSACFG::BuiltinCall{_call.debugData, builtin, _call}, {}};
568573
for (auto&& [idx, arg]: _call.arguments | ranges::views::enumerate | ranges::views::reverse)
569574
if (!builtin.literalArgument(idx).has_value())
570-
result.inputs.emplace_back(std::visit(*this, arg));
575+
{
576+
if (!m_literalsAsPushConstants && std::holds_alternative<Literal>(arg))
577+
{
578+
auto const lit = m_graph.newLiteral(debugDataOf(currentBlock()), std::get<Literal>(arg).value.value());
579+
result.inputs.emplace_back(moveLiteralToVariable(lit));
580+
}
581+
else
582+
result.inputs.emplace_back(std::visit(*this, arg));
583+
}
571584
for (size_t i = 0; i < builtin.numReturns; ++i)
572585
result.outputs.emplace_back(m_graph.newVariable(m_currentBlock));
573586
canContinue = builtin.controlFlowSideEffects.canContinue;
@@ -582,7 +595,15 @@ std::vector<SSACFG::ValueId> SSAControlFlowGraphBuilder::visitFunctionCall(Funct
582595
canContinue = m_sideEffects.functionSideEffects().at(definition).canContinue;
583596
SSACFG::Operation result{{}, SSACFG::Call{debugDataOf(_call), function, _call, canContinue}, {}};
584597
for (auto const& arg: _call.arguments | ranges::views::reverse)
585-
result.inputs.emplace_back(std::visit(*this, arg));
598+
{
599+
if (!m_literalsAsPushConstants && std::holds_alternative<Literal>(arg))
600+
{
601+
auto const lit = m_graph.newLiteral(debugDataOf(currentBlock()), std::get<Literal>(arg).value.value());
602+
result.inputs.emplace_back(moveLiteralToVariable(lit));
603+
}
604+
else
605+
result.inputs.emplace_back(std::visit(*this, arg));
606+
}
586607
for (size_t i = 0; i < function.numReturns; ++i)
587608
result.outputs.emplace_back(m_graph.newVariable(m_currentBlock));
588609
return result;

libyul/backends/evm/SSAControlFlowGraphBuilder.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class SSAControlFlowGraphBuilder
4545
AsmAnalysisInfo const& _analysisInfo,
4646
ControlFlowSideEffectsCollector const& _sideEffects,
4747
Dialect const& _dialect,
48-
bool _keepLiteralAssignments
48+
bool _literalsAsPushConstants
4949
);
5050
public:
5151
SSAControlFlowGraphBuilder(SSAControlFlowGraphBuilder const&) = delete;
@@ -54,7 +54,7 @@ class SSAControlFlowGraphBuilder
5454
AsmAnalysisInfo const& _analysisInfo,
5555
Dialect const& _dialect,
5656
Block const& _block,
57-
bool _keepLiteralAssignments
57+
bool _literalsAsPushConstants
5858
);
5959

6060
void operator()(ExpressionStatement const& _statement);
@@ -82,6 +82,7 @@ class SSAControlFlowGraphBuilder
8282
std::vector<SSACFG::ValueId> visitFunctionCall(FunctionCall const& _call);
8383
void registerFunctionDefinition(FunctionDefinition const& _functionDefinition);
8484
void buildFunctionGraph(Scope::Function const* _function, FunctionDefinition const* _functionDefinition);
85+
SSACFG::ValueId moveLiteralToVariable(SSACFG::ValueId _value);
8586

8687
SSACFG::ValueId zero();
8788
SSACFG::ValueId readVariable(Scope::Variable const& _variable, SSACFG::BlockId _block);
@@ -94,7 +95,7 @@ class SSAControlFlowGraphBuilder
9495
AsmAnalysisInfo const& m_info;
9596
ControlFlowSideEffectsCollector const& m_sideEffects;
9697
Dialect const& m_dialect;
97-
bool const m_keepLiteralAssignments;
98+
bool const m_literalsAsPushConstants;
9899
std::vector<std::tuple<Scope::Function const*, FunctionDefinition const*>> m_functionDefinitions;
99100
SSACFG::BlockId m_currentBlock;
100101
SSACFG::BasicBlock& currentBlock() { return m_graph.block(m_currentBlock); }

0 commit comments

Comments
 (0)