Skip to content

Commit 6efa019

Browse files
committed
f
1 parent 7d88b11 commit 6efa019

File tree

8 files changed

+41
-57
lines changed

8 files changed

+41
-57
lines changed

libyul/backends/evm/ssa/ControlFlow.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ using namespace solidity::yul::ssa;
2424

2525
ControlFlowLiveness::ControlFlowLiveness(ControlFlow const& _controlFlow):
2626
controlFlow(_controlFlow),
27-
mainLiveness(std::make_unique<LivenessAnalysis>(*_controlFlow.mainGraph)),
27+
mainLiveness(std::make_unique<LivenessAnalysis>(*_controlFlow.functionGraph(0u))),
2828
functionLiveness(_controlFlow.functionGraphs | ranges::views::transform([](auto const& _cfg) { return std::make_unique<LivenessAnalysis>(*_cfg); }) | ranges::to<std::vector>)
2929
{ }
3030

libyul/backends/evm/ssa/ControlFlow.h

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#include <libyul/AST.h>
2525
#include <libyul/Scope.h>
2626

27+
#include <range/v3/algorithm/find_if.hpp>
28+
2729
namespace solidity::yul::ssa
2830
{
2931

@@ -46,25 +48,31 @@ struct ControlFlowLiveness{
4648

4749
struct ControlFlow
4850
{
49-
std::unique_ptr<SSACFG> mainGraph{std::make_unique<SSACFG>()};
50-
std::vector<std::unique_ptr<SSACFG>> functionGraphs{};
51-
std::vector<std::tuple<Scope::Function const*, SSACFG const*>> functionGraphMapping{};
51+
using ID = std::uint32_t;
5252

53-
SSACFG const* functionGraph(Scope::Function const* _function)
53+
SSACFG const* functionGraph(Scope::Function const* _function) const
5454
{
55-
auto it = std::find_if(functionGraphMapping.begin(), functionGraphMapping.end(), [_function](auto const& tup) { return _function == std::get<0>(tup); });
55+
auto it = ranges::find_if(functionGraphMapping, [_function](auto const& tup) { return _function == std::get<0>(tup); });
5656
if (it != functionGraphMapping.end())
5757
return std::get<1>(*it);
5858
return nullptr;
5959
}
6060

61+
SSACFG const* functionGraph(ID const _id) const
62+
{
63+
return functionGraphs.at(_id).get();
64+
}
65+
66+
std::vector<std::unique_ptr<SSACFG>> functionGraphs{};
67+
std::vector<std::tuple<Scope::Function const*, SSACFG const*>> functionGraphMapping{};
68+
6169
std::string toDot(ControlFlowLiveness const* _liveness=nullptr, SSACFGStackLayout const* _stackLayout = nullptr) const
6270
{
6371
if (_liveness)
6472
yulAssert(&_liveness->controlFlow.get() == this);
6573
std::ostringstream output;
6674
output << "digraph SSACFG {\nnodesep=0.7;\ngraph[rankdir=LR, fontname=\"DejaVu Sans\"]\nnode[shape=box,fontname=\"DejaVu Sans\"];\n\n";
67-
output << mainGraph->toDot(false, std::nullopt, _liveness ? _liveness->mainLiveness.get() : nullptr, _stackLayout);
75+
output << functionGraph(0u)->toDot(false, std::nullopt, _liveness ? _liveness->mainLiveness.get() : nullptr, _stackLayout);
6876

6977
for (size_t index=0; index < functionGraphs.size(); ++index)
7078
output << functionGraphs[index]->toDot(

libyul/backends/evm/ssa/OperationForwardShuffler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ class OperationForwardShuffler
4545
bool _generateJunk
4646
)
4747
{
48-
yulAssert(ranges::none_of(_args, [](auto const& _slot) { return std::holds_alternative<ssa::JunkSlot>(_slot); }));
48+
yulAssert(ranges::none_of(_args, [](auto const& _slot) { return _slot.isJunk(); }));
4949

5050
constexpr std::size_t maxIterations = 1000;
5151
std::size_t i = 0;

libyul/backends/evm/ssa/SSACFGBuilder.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,14 @@ std::unique_ptr<ControlFlow> SSACFGBuilder::build(
7272
ControlFlowSideEffectsCollector sideEffects(_dialect, _block);
7373

7474
auto controlFlow = std::make_unique<ControlFlow>();
75-
SSACFGBuilder builder(*controlFlow, *controlFlow->mainGraph, _analysisInfo, sideEffects, _dialect, _keepLiteralAssignments);
76-
builder.m_currentBlock = controlFlow->mainGraph->makeBlock(debugDataOf(_block));
75+
controlFlow->functionGraphs.emplace_back(std::make_unique<SSACFG>());
76+
SSACFGBuilder builder(*controlFlow, *controlFlow->functionGraphs.at(0), _analysisInfo, sideEffects, _dialect, _keepLiteralAssignments);
77+
builder.m_currentBlock = controlFlow->functionGraphs.at(0)->makeBlock(debugDataOf(_block));
7778
builder.sealBlock(builder.m_currentBlock);
7879
builder(_block);
7980
if (!builder.blockInfo(builder.m_currentBlock).sealed)
8081
builder.sealBlock(builder.m_currentBlock);
81-
controlFlow->mainGraph->block(builder.m_currentBlock).exit = SSACFG::BasicBlock::MainExit{};
82+
controlFlow->functionGraphs.at(0)->block(builder.m_currentBlock).exit = SSACFG::BasicBlock::MainExit{};
8283
builder.cleanUnreachable();
8384
return controlFlow;
8485
}
@@ -109,7 +110,7 @@ SSACFG::ValueId SSACFGBuilder::tryRemoveTrivialPhi(SSACFG::ValueId _phi)
109110
m_graph.block(phiInfo->block).phis.erase(_phi);
110111

111112
std::vector<SSACFG::ValueId> phiUses;
112-
for (size_t blockIdValue = 0; blockIdValue < m_graph.numBlocks(); ++blockIdValue)
113+
for (SSACFG::BlockId::ValueType blockIdValue = 0; blockIdValue < m_graph.numBlocks(); ++blockIdValue)
113114
{
114115
auto& block = m_graph.block(SSACFG::BlockId{blockIdValue});
115116
for (auto blockPhi: block.phis)

libyul/backends/evm/ssa/Stack.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,13 +142,16 @@ struct NoOpStackManipulationCallbacks
142142
static_assert(StackManipulationCallbackConcept<NoOpStackManipulationCallbacks>);
143143

144144
template<
145-
StackManipulationCallbackConcept Callbacks = NoOpStackManipulationCallbacks,
146-
CanBeFreelyGeneratedConcept CanBeFreelyGenerated = SlotCanBeFreelyGenerated
145+
StackManipulationCallbackConcept CallbacksType = NoOpStackManipulationCallbacks,
146+
CanBeFreelyGeneratedConcept CanBeFreelyGeneratedType = SlotCanBeFreelyGenerated
147147
>
148148
class Stack
149149
{
150150
static size_t constexpr reachableStackDepth = 16;
151151
public:
152+
using Callbacks = CallbacksType;
153+
using CanBeFreelyGenerated = CanBeFreelyGeneratedType;
154+
152155
using Slot = StackSlot;
153156
using Data = std::vector<Slot>;
154157

test/libyul/Misctest.cpp

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33

44

55
#include <boost/test/unit_test.hpp>
6+
#include <fmt/ranges.h>
67

7-
#include <libyul/backends/evm/ssa/LivenessAnalysis.h>
8-
#include <libyul/backends/evm/SSACFGStack.h>
98
#include <libyul/backends/evm/SSACFGStackShuffler.h>
9+
#include <libyul/backends/evm/ssa/LivenessAnalysis.h>
1010

1111
#include <range/v3/view/concat.hpp>
1212

@@ -60,18 +60,7 @@ struct PrintCallback
6060
std::optional<std::function<void()>> callback;
6161
};
6262

63-
struct SlotCanBeFreelyGenerated
64-
{
65-
using Slot = SourceSlot;
66-
bool operator()(Slot const& _slot) const
67-
{
68-
return canBeFreelyGenerated(_slot);
69-
}
70-
71-
solidity::yul::ssa::SlotCanBeFreelyGenerated<solidity::yul::ssa::StackSlot> canBeFreelyGenerated;
72-
};
73-
74-
using TestStack = solidity::yul::ssa::Stack<SourceSlot, PrintCallback, SlotCanBeFreelyGenerated>;
63+
using TestStack = solidity::yul::ssa::Stack<PrintCallback>;
7564

7665

7766

@@ -117,7 +106,6 @@ BOOST_AUTO_TEST_CASE(yo)
117106
if (stack)
118107
std::cout << ssa::stackToString(stack->data(), *cfg) << std::endl;
119108
});
120-
SlotCanBeFreelyGenerated canBeFreelyGenerated{.canBeFreelyGenerated = {cfg.get()}};
121109

122110
FunctionCall funDeposit {
123111
.debugData = nullptr,
@@ -131,17 +119,17 @@ BOOST_AUTO_TEST_CASE(yo)
131119
auto const v139 = cfg->newVariable({0});
132120
auto const v141 = cfg->newVariable({0});
133121

134-
std::vector<SourceSlot> slotsRef {
122+
std::vector slotsRef {
135123
// ssa::JunkSlot{}, ssa::JunkSlot{}, ssa::JunkSlot{}, ssa::JunkSlot{}, ssa::JunkSlot{},
136-
v113, v115, v119, v136, /*ssa::JunkSlot{}, ssa::JunkSlot{},*/ v139, v141
124+
SourceSlot::makeValueIDSlot(v113), SourceSlot::makeValueIDSlot(v115), SourceSlot::makeValueIDSlot(v119), SourceSlot::makeValueIDSlot(v136), /*ssa::JunkSlot{}, ssa::JunkSlot{},*/ SourceSlot::makeValueIDSlot(v139), SourceSlot::makeValueIDSlot(v141)
137125
};
138126
ssa::LivenessAnalysis::LivenessData liveness({{v113, 1}, {v115, 1}, {v119, 1}});
139-
TestStack::Data args{thirtytwo, zero, v139, v136, two, v141};
127+
TestStack::Data args{SourceSlot::makeValueIDSlot(thirtytwo), SourceSlot::makeValueIDSlot(zero), SourceSlot::makeValueIDSlot(v139), SourceSlot::makeValueIDSlot(v136), SourceSlot::makeValueIDSlot(two), SourceSlot::makeValueIDSlot(v141)};
140128
std::vector<SourceSlot> final;
141129

142130
{
143131
auto slots = slotsRef;
144-
stack = std::make_shared<TestStack>(slots, callback, canBeFreelyGenerated);
132+
stack = std::make_shared<TestStack>(slots, callback, TestStack::CanBeFreelyGenerated{});
145133

146134
// fun_deposit([JUNK x 6, v58, v59, JUNK, v67, v68, JUNK, v76, v77, v79] -> { [] } + [ReturnLabel[fun_deposit], v79, v77, v76, v68, v67, v59, v58])
147135
// mstore([JUNK x 7, v48, v49] -> { [v49] } + [v48, v49]) -> DUP1 + SWAP2 + SWAP1 + -> [JUNK x 7, v49]
@@ -165,14 +153,14 @@ BOOST_AUTO_TEST_CASE(yo)
165153
{
166154
constexpr auto SlotIsCompatible = [](TestStack::Slot const& _source, TestStack::Slot const& _target) { return std::holds_alternative<ssa::JunkSlot>(_target) || _source == _target; };
167155
auto slots = slotsRef;
168-
stack = std::make_shared<TestStack>(slots, callback, canBeFreelyGenerated);
156+
stack = std::make_shared<TestStack>(slots, callback, TestStack::CanBeFreelyGenerated{});
169157
std::cout << fmt::format("\n\nAnd now with A*:\n") << std::flush;
170158
TestStack::Data tail(final.begin(), final.begin() + static_cast<size_t>(final.size() - args.size()));
171159
ssa::BlockForwardAStarShuffler<TestStack, SlotIsCompatible>::shuffle(*stack, tail, args);
172160
}
173161
{
174162
auto slots = slotsRef;
175-
stack = std::make_shared<TestStack>(slots, callback, canBeFreelyGenerated);
163+
stack = std::make_shared<TestStack>(slots, callback, TestStack::CanBeFreelyGenerated{});
176164

177165
std::cout << fmt::format("\n\nAnd now with Daniel shuffler:\n") << std::flush;
178166
DanielShuffler<TestStack>::shuffle(*stack, {}, final);

test/libyul/SSAStackShufflingTest.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
#include <test/Common.h>
2828

29-
#include <libyul/backends/evm/SSACFGStack.h>
3029
#include <libyul/backends/evm/SSACFGStackLayout.h>
3130

3231
#include <liblangutil/Scanner.h>
@@ -54,11 +53,11 @@ SSAStackShufflingTest::Stack::Data SSAStackShufflingTest::parse(std::string cons
5453
{
5554
std::string literal = scanner.currentLiteral();
5655
if (literal.find("0x") != std::string::npos || scanner.currentToken() == Token::Number)
57-
stackData.emplace_back(m_cfg->newLiteral(DebugData::create(), u256(literal)));
56+
stackData.emplace_back(ssa::StackSlot::makeValueIDSlot(m_cfg->newLiteral(DebugData::create(), u256(literal))));
5857
else if (literal == "JUNK")
59-
stackData.emplace_back(ssa::JunkSlot{});
58+
stackData.emplace_back(ssa::StackSlot::makeJunkSlot());
6059
else
61-
stackData.emplace_back(m_cfg->newVariable({0}));
60+
stackData.emplace_back(ssa::StackSlot::makeValueIDSlot({0}));
6261
scanner.next();
6362
}
6463
if (scanner.currentToken() != Token::RBrack)

test/libyul/SSAStackShufflingTest.h

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,16 @@
2121
#include <test/TestCase.h>
2222

2323
#include <libyul/backends/evm/ControlFlowGraph.h>
24-
#include <libyul/backends/evm/SSACFGStack.h>
24+
#include <libyul/backends/evm/ssa/Stack.h>
2525

2626
#include <map>
2727

2828
using namespace solidity::frontend::test;
2929

3030
namespace solidity::yul::test
3131
{
32-
using TestSlot = std::variant<ssa::SSACFG::ValueId, ssa::JunkSlot>;
3332
struct PrintCallback
3433
{
35-
using Slot = TestSlot;
3634
void swap(size_t)
3735
{
3836
++numOps;
@@ -41,7 +39,7 @@ struct PrintCallback
4139
{
4240
++numOps;
4341
}
44-
void push(Slot const&)
42+
void push(ssa::StackSlot const&)
4543
{
4644
++numOps;
4745
}
@@ -51,23 +49,10 @@ struct PrintCallback
5149
}
5250

5351
size_t numOps{};
54-
//todo ssa::Stack<PrintCallback>* self;
55-
};
56-
struct SlotCanBeFreelyGenerated
57-
{
58-
using Slot = TestSlot;
59-
bool operator()(Slot const& _slot) const
60-
{
61-
if (std::holds_alternative<ssa::SSACFG::ValueId>(_slot))
62-
return m_cfg->isLiteralValue(std::get<ssa::SSACFG::ValueId>(_slot));
63-
return std::holds_alternative<ssa::JunkSlot>(_slot);
64-
}
65-
66-
ssa::SSACFG const* m_cfg;
6752
};
6853
class SSAStackShufflingTest final: public TestCase
6954
{
70-
using Stack = ssa::Stack<TestSlot, PrintCallback, SlotCanBeFreelyGenerated>;
55+
using Stack = ssa::Stack<PrintCallback>;
7156
public:
7257
static std::unique_ptr<TestCase> create(Config const& _config)
7358
{

0 commit comments

Comments
 (0)