Skip to content

Commit

Permalink
Take parameter kind into account when deciding function purity.
Browse files Browse the repository at this point in the history
  • Loading branch information
bbannier committed Jan 22, 2024
1 parent bf471e2 commit 1c99d1c
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 0 deletions.
19 changes: 19 additions & 0 deletions hilti/toolchain/src/compiler/optimizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <hilti/ast/declarations/global-variable.h>
#include <hilti/ast/declarations/imported-module.h>
#include <hilti/ast/declarations/local-variable.h>
#include <hilti/ast/declarations/parameter.h>
#include <hilti/ast/declarations/type.h>
#include <hilti/ast/detail/visitor.h>
#include <hilti/ast/expressions/assign.h>
Expand Down Expand Up @@ -1987,6 +1988,24 @@ struct PureFunctionVisitor : OptimizerVisitor, visitor::PreOrder<bool, PureFunct
continue;
}

else if ( const auto& param = decl.tryAs<declaration::Parameter>() ) {
// Reference provide interior mutability regardless of the
// mutability of the param so mark such accesses not as pure.
if ( type::isReferenceType(param->type()) )
return {};

switch ( param->kind() ) {
// Access to `copy` or `in` parameters is side-effect free.
case declaration::parameter::Kind::Copy: [[fallthrough]];
case declaration::parameter::Kind::In:
continue;

// Any other access could have side-effects.
case declaration::parameter::Kind::InOut: [[fallthrough]];
case declaration::parameter::Kind::Unknown: return {};
}
}

else
// Do not mark this function pure if it references any other kinds of IDs.
return {};
Expand Down
24 changes: 24 additions & 0 deletions tests/Baseline/hilti.optimization.pure_function/opt.hlt
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,30 @@ method method void T::pure4() &pure {
self;
}

function void fn_pure5(uint<64> in_param) &pure {
in_param += 42;
}

function void fn_pure6(copy uint<64> copy_param) &pure {
copy_param += 42;
}

function void fn_not_pure2(inout uint<64> inout_param) {
inout_param += 42;
}

function void fn_not_pure3(strong_ref<uint<64>> in_param) {
(*in_param) += 42;
}

function void fn_not_pure4(copy strong_ref<uint<64>> copy_param) {
(*copy_param) += 42;
}

function void fn_not_pure2(inout strong_ref<uint<64>> inout_param) {
(*inout_param) += 42;
}

t.pure4();

}
2 changes: 2 additions & 0 deletions tests/Baseline/hilti.optimization.pure_function/output
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@
[debug/optimizer] marking member 'pure' as pure (<...>/pure_function.hlt:31:5)
[debug/optimizer] marking member 'pure2' as pure (<...>/pure_function.hlt:32:5)
[debug/optimizer] marking member 'T::pure4' as pure (<...>/pure_function.hlt:43:7-46:2)
[debug/optimizer] marking function 'fn_pure5' as pure
[debug/optimizer] marking function 'fn_pure6' as pure
[debug/optimizer] marking function 'fn_pure' as pure
10 changes: 10 additions & 0 deletions tests/hilti/optimization/pure_function.hlt
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,14 @@ method void T::pure4() {
global T t;
t.pure4();

# Parameter access is side-effect free for `in` and `copy` parameters if they are not of reference type.
function void fn_pure5(uint<64> in_param) { in_param += 42; }
function void fn_pure6(copy uint<64> copy_param) { copy_param += 42; }
function void fn_not_pure2(inout uint<64> inout_param) { inout_param += 42; }

function void fn_not_pure3(strong_ref<uint<64>> in_param) { *in_param += 42; }
function void fn_not_pure4(copy strong_ref<uint<64>> copy_param) { *copy_param += 42; }
function void fn_not_pure2(inout strong_ref<uint<64>> inout_param) { *inout_param += 42; }


}

0 comments on commit 1c99d1c

Please sign in to comment.