Skip to content

Commit

Permalink
Add optimizer pass removing dead code.
Browse files Browse the repository at this point in the history
  • Loading branch information
bbannier committed May 10, 2023
1 parent 0df13a5 commit b93a7b9
Show file tree
Hide file tree
Showing 17 changed files with 190 additions and 81 deletions.
53 changes: 53 additions & 0 deletions hilti/toolchain/src/compiler/optimizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@
#include <hilti/ast/expressions/logical-or.h>
#include <hilti/ast/expressions/ternary.h>
#include <hilti/ast/node.h>
#include <hilti/ast/operators/function.h>
#include <hilti/ast/operators/struct.h>
#include <hilti/ast/operators/tuple.h>
#include <hilti/ast/scope-lookup.h>
#include <hilti/ast/statements/block.h>
#include <hilti/ast/statements/declaration.h>
#include <hilti/ast/statements/expression.h>
#include <hilti/ast/type.h>
#include <hilti/ast/types/bool.h>
#include <hilti/ast/types/enum.h>
Expand Down Expand Up @@ -1622,6 +1625,55 @@ struct DeadStoreVisitor : OptimizerVisitor, visitor::PreOrder<bool, DeadStoreVis
}
};

struct DeadCodeVisitor : OptimizerVisitor, visitor::PreOrder<bool, DeadCodeVisitor> {
bool prune_uses(Node& node) override {
bool any_modification = false;

while ( true ) {
bool modified = false;

for ( auto i : this->walk(&node) ) {
if ( auto x = dispatch(i) )
modified = modified || *x;
}

if ( ! modified )
break;

any_modification = true;
}

return any_modification;
}

result_t operator()(const Module& m, position_t p) {
_current_module = &p.node.as<Module>();
return false;
}

result_t operator()(const statement::Expression& x, position_t p) {
if ( auto ctor = x.expression().tryAs<expression::Ctor>();
ctor && (ctor->isConstant() || ! hasChildWithSideEffects(x)) ) {
HILTI_DEBUG(logging::debug::Optimizer,
util::fmt("removing side-effect free dead code (%s)", x.meta().location()));
removeNode(p);
return true;
}

return false;
}

bool hasChildWithSideEffects(const Node& node) const {
auto v = visitor::PreOrder<>();
auto walk = v.walk(node);

return std::any_of(walk.begin(), walk.end(), [](auto&& child) {
return child.node.template isA<operator_::struct_::MemberCall>() ||
child.node.template isA<operator_::function::Call>();
});
}
};

void Optimizer::run() {
util::timing::Collector _("hilti/compiler/optimizer");

Expand Down Expand Up @@ -1667,6 +1719,7 @@ void Optimizer::run() {
{{"constant_folding", []() { return std::make_unique<ConstantFoldingVisitor>(); }},
{"functions", []() { return std::make_unique<FunctionVisitor>(); }},
{"members", []() { return std::make_unique<MemberVisitor>(); }},
{"dead_code", []() { return std::make_unique<DeadCodeVisitor>(); }},
{"dead_store", []() { return std::make_unique<DeadStoreVisitor>(); }},
{"types", []() { return std::make_unique<TypeVisitor>(); }}};

Expand Down
10 changes: 0 additions & 10 deletions tests/Baseline/hilti.optimization.const/log
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,3 @@
[debug/optimizer] inlining constant 'Foo::t'
[debug/optimizer] inlining constant 'Foo::t'
[debug/optimizer] inlining constant 'Foo::t'
[debug/optimizer] removing declaration for unused function hilti::abort
[debug/optimizer] removing declaration for unused function hilti::current_time
[debug/optimizer] removing declaration for unused function hilti::debug
[debug/optimizer] removing declaration for unused function hilti::debugDedent
[debug/optimizer] removing declaration for unused function hilti::debugIndent
[debug/optimizer] removing declaration for unused function hilti::exception_what
[debug/optimizer] removing declaration for unused function hilti::mktime
[debug/optimizer] removing declaration for unused function hilti::printValues
[debug/optimizer] removing declaration for unused function hilti::profiler_start
[debug/optimizer] removing declaration for unused function hilti::profiler_stop
4 changes: 4 additions & 0 deletions tests/Baseline/hilti.optimization.dead_code/opt.hlt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
### BTest baseline data generated by btest-diff. Do not edit. Use "btest -U/-u" to update. Requires BTest >= 0.63.
module foo {

}
2 changes: 2 additions & 0 deletions tests/Baseline/hilti.optimization.unimplemented_hook/log
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@
[debug/optimizer] removing declaration for unused hook function Foo::global_unimplemented_void
[debug/optimizer] removing declaration for unused hook function Foo::global_unimplemented_int64
[debug/optimizer] removing field for unused method Foo::X::unimplemented
[debug/optimizer] removing side-effect free dead code (<...>/unimplemented_hook.hlt:29:1)
[debug/optimizer] removing side-effect free dead code (<...>/unimplemented_hook.hlt:35:1)
[debug/optimizer] removing field for unused method Foo::X::unimplemented_void
[debug/optimizer] removing field for unused method Foo::X::unimplemented_int64
2 changes: 0 additions & 2 deletions tests/Baseline/hilti.optimization.unimplemented_hook/opt.hlt
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ method hook void X::implemented() {
}

global_implemented();
default<void>();
x.implemented();
default<void>();

}
15 changes: 15 additions & 0 deletions tests/Baseline/spicy.optimization.default-parser-functions/log
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,21 @@
[debug/optimizer] removing field for unused method foo::__register_foo_P2::<anon-struct-9>::parse1
[debug/optimizer] removing field for unused method foo::__register_foo_P2::<anon-struct-9>::parse2
[debug/optimizer] removing field for unused method foo::__register_foo_P2::<anon-struct-9>::parse3
[debug/optimizer] removing side-effect free dead code (<...>/default-parser-functions.spicy:12:11)
[debug/optimizer] removing side-effect free dead code (<...>/default-parser-functions.spicy:12:11)
[debug/optimizer] removing side-effect free dead code (<...>/default-parser-functions.spicy:12:11)
[debug/optimizer] removing side-effect free dead code (<...>/default-parser-functions.spicy:12:11)
[debug/optimizer] removing side-effect free dead code (<...>/default-parser-functions.spicy:12:11)
[debug/optimizer] removing side-effect free dead code (<...>/default-parser-functions.spicy:14:18)
[debug/optimizer] removing side-effect free dead code (<...>/default-parser-functions.spicy:14:18)
[debug/optimizer] removing side-effect free dead code (<...>/default-parser-functions.spicy:14:18)
[debug/optimizer] removing side-effect free dead code (<...>/default-parser-functions.spicy:14:18)
[debug/optimizer] removing side-effect free dead code (<...>/default-parser-functions.spicy:14:18)
[debug/optimizer] removing side-effect free dead code (<...>/default-parser-functions.spicy:16:18-21:2)
[debug/optimizer] removing side-effect free dead code (<...>/default-parser-functions.spicy:16:18-21:2)
[debug/optimizer] removing side-effect free dead code (<...>/default-parser-functions.spicy:16:18-21:2)
[debug/optimizer] removing side-effect free dead code (<...>/default-parser-functions.spicy:16:18-21:2)
[debug/optimizer] removing side-effect free dead code (<...>/default-parser-functions.spicy:17:5)
[debug/optimizer] removing unused member 'foo::P0::__begin'
[debug/optimizer] removing unused member 'foo::P0::__filters'
[debug/optimizer] removing unused member 'foo::P0::__offset'
Expand Down
10 changes: 0 additions & 10 deletions tests/Baseline/spicy.optimization.default-parser-functions/opt.hlt
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ method method tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::Rec
try {
hilti::debugIndent("spicy");
(*self).__error = __error;
default<void>();
__error = (*self).__error;
local strong_ref<stream> filtered = Null;

Expand All @@ -64,15 +63,12 @@ method method tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::Rec

}
catch ( hilti::SystemException __except ) {
default<void>();
(*self).__error = __error;
default<void>();
__error = (*self).__error;
throw;
}

(*self).__error = __error;
default<void>();
__error = (*self).__error;
return __result;
}
Expand All @@ -81,7 +77,6 @@ method method tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::Rec
# "<...>/default-parser-functions.spicy:14:18"
local tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::RecoverableFailure>> __result;
(*self).__error = __error;
default<void>();
__error = (*self).__error;
hilti::debugDedent("spicy");
__result = (__cur, __lah, __lahe, __error);
Expand Down Expand Up @@ -162,7 +157,6 @@ method method tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::Rec
try {
hilti::debugIndent("spicy");
(*self).__error = __error;
default<void>();
__error = (*self).__error;
local strong_ref<stream> filtered = Null;

Expand All @@ -173,13 +167,11 @@ method method tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::Rec
catch ( hilti::SystemException __except ) {
(*self).__on_0x25_error(hilti::exception_what(__except));
(*self).__error = __error;
default<void>();
__error = (*self).__error;
throw;
}

(*self).__error = __error;
default<void>();
__error = (*self).__error;
return __result;
}
Expand All @@ -199,7 +191,6 @@ method method tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::Rec
# End parsing production: Variable: x -> uint<8>

(*self).__error = __error;
default<void>();
__error = (*self).__error;
# "<...>/default-parser-functions.spicy:18:8"

Expand All @@ -216,7 +207,6 @@ method method tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::Rec
(*self).__on_y((*self).y);
__error = (*self).__error;
(*self).__error = __error;
default<void>();
__error = (*self).__error;
hilti::debugDedent("spicy");
__result = (__cur, __lah, __lahe, __error);
Expand Down
31 changes: 31 additions & 0 deletions tests/Baseline/spicy.optimization.feature_requirements/log
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,37 @@
[debug/optimizer] removing field for unused method foo::__register_foo_X6::<anon-struct-21>::parse1
[debug/optimizer] removing field for unused method foo::__register_foo_X6::<anon-struct-21>::parse2
[debug/optimizer] removing field for unused method foo::__register_foo_X6::<anon-struct-21>::parse3
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:13:11-15:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:13:11-15:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:13:11-15:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:13:11-15:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:18:11-20:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:18:11-20:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:18:11-20:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:18:11-20:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:23:11)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:23:11)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:23:11)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:23:11)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:23:11)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:26:11-28:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:26:11-28:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:26:11-28:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:26:11-28:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:26:11-28:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:32:11-34:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:32:11-34:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:32:11-34:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:32:11-34:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:32:11-34:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:36:18-40:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:36:18-40:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:36:18-40:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:36:18-40:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:43:11-46:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:43:11-46:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:43:11-46:2)
[debug/optimizer] removing side-effect free dead code (<...>/feature_requirements.spicy:43:11-46:2)
[debug/optimizer] removing unused member 'foo::X0::__begin'
[debug/optimizer] removing unused member 'foo::X0::__filters'
[debug/optimizer] removing unused member 'foo::X0::__parser'
Expand Down
13 changes: 0 additions & 13 deletions tests/Baseline/spicy.optimization.feature_requirements/opt.hlt
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,6 @@ method method tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::Rec
try {
hilti::debugIndent("spicy");
(*self).__error = __error;
default<void>();
__error = (*self).__error;
local strong_ref<stream> filtered = Null;

Expand All @@ -137,18 +136,15 @@ method method tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::Rec

}
catch ( hilti::SystemException __except ) {
default<void>();

spicy_rt::filter_forward_eod(self);

(*self).__error = __error;
default<void>();
__error = (*self).__error;
throw;
}

(*self).__error = __error;
default<void>();
__error = (*self).__error;
return __result;
}
Expand All @@ -157,7 +153,6 @@ method method tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::Rec
# "<...>/feature_requirements.spicy:32:11-34:2"
local tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::RecoverableFailure>> __result;
(*self).__error = __error;
default<void>();
__error = (*self).__error;

spicy_rt::filter_forward_eod(self);
Expand Down Expand Up @@ -265,18 +260,15 @@ method method tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::Rec

}
catch ( hilti::SystemException __except ) {
default<void>();

spicy_rt::filter_disconnect(self);

(*self).__error = __error;
default<void>();
__error = (*self).__error;
throw;
}

(*self).__error = __error;
default<void>();
__error = (*self).__error;
return __result;
}
Expand All @@ -285,7 +277,6 @@ method method tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::Rec
# "<...>/feature_requirements.spicy:36:18-40:2"
local tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::RecoverableFailure>> __result;
(*self).__error = __error;
default<void>();
__error = (*self).__error;

spicy_rt::filter_disconnect(self);
Expand Down Expand Up @@ -376,16 +367,13 @@ method method tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::Rec

}
catch ( hilti::SystemException __except ) {
default<void>();
(*(*self).data).close();
(*self).__error = __error;
default<void>();
__error = (*self).__error;
throw;
}

(*self).__error = __error;
default<void>();
__error = (*self).__error;
return __result;
}
Expand All @@ -394,7 +382,6 @@ method method tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::Rec
# "<...>/feature_requirements.spicy:43:11-46:2"
local tuple<view<stream>, int<64>, iterator<stream>, optional<hilti::RecoverableFailure>> __result;
(*self).__error = __error;
default<void>();
__error = (*self).__error;
(*(*self).data).close();
hilti::debugDedent("spicy");
Expand Down
25 changes: 25 additions & 0 deletions tests/Baseline/spicy.optimization.unused-functions/log
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,31 @@
[debug/optimizer] removing field for unused method foo::__register_foo_D::<anon-struct-13>::parse1
[debug/optimizer] removing field for unused method foo::__register_foo_D::<anon-struct-13>::parse2
[debug/optimizer] removing field for unused method foo::__register_foo_D::<anon-struct-13>::parse3
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:18:10)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:18:10)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:18:10)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:18:10)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:18:10)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:21:17)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:21:17)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:21:17)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:21:17)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:21:17)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:24:10)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:24:10)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:24:10)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:24:10)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:24:10)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:25:17-27:2)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:25:17-27:2)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:25:17-27:2)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:25:17-27:2)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:25:17-27:2)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:30:10-32:2)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:30:10-32:2)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:30:10-32:2)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:30:10-32:2)
[debug/optimizer] removing side-effect free dead code (<...>/unused-functions.spicy:30:10-32:2)
[debug/optimizer] removing unused member 'foo::A::__begin'
[debug/optimizer] removing unused member 'foo::A::__filters'
[debug/optimizer] removing unused member 'foo::A::__offset'
Expand Down
Loading

0 comments on commit b93a7b9

Please sign in to comment.