[m-rev.] diff: compile time simplification of uint operations
Julien Fischer
jfischer at opturion.com
Mon May 22 18:09:24 AEST 2017
Compile time simplification of uint operations.
compiler/simplify_goal_call.m:
Avoid the check for division by zero in uint.(/) and uint.(rem) when
the second operand is a non-zero constant.
Replace uint.(<<) and uint.(>>) with their unchecked variants if the
second operand is within the range [0, target_bits_per_uint).
Julien.
diff --git a/compiler/simplify_goal_call.m b/compiler/simplify_goal_call.m
index 1a2d90016..4f0c56fee 100644
--- a/compiler/simplify_goal_call.m
+++ b/compiler/simplify_goal_call.m
@@ -103,6 +103,7 @@
:- import_module pair.
:- import_module require.
:- import_module string.
+:- import_module uint.
:- import_module varset.
%---------------------------------------------------------------------------%
@@ -675,6 +676,10 @@ simplify_improve_library_call(InstMap0, ModuleName, PredName, ModeNum, Args,
ModuleName = "int",
simplify_improve_int_call(InstMap0, PredName, ModeNum, Args,
ImprovedGoalExpr, GoalInfo0, ImprovedGoalInfo, !Info)
+ ;
+ ModuleName = "uint",
+ simplify_improve_uint_call(InstMap0, PredName, ModeNum, Args,
+ ImprovedGoalExpr, GoalInfo0, ImprovedGoalInfo, !Info)
),
simplify_info_set_should_requantify(!Info).
@@ -946,6 +951,83 @@ simplify_make_int_binary_op_goal_expr(Info, Op, IsBuiltin, X, Y, Z,
GoalExpr = plain_call(OpPredId, OpProcId, OpArgs, IsBuiltin,
MaybeUnifyContext, OpSymName).
+:- pred simplify_improve_uint_call(instmap::in, string::in, int::in,
+ list(prog_var)::in, hlds_goal_expr::out,
+ hlds_goal_info::in, hlds_goal_info::out,
+ simplify_info::in, simplify_info::out) is semidet.
+
+simplify_improve_uint_call(InstMap0, PredName, _ModeNum, Args, ImprovedGoalExpr,
+ !GoalInfo, !Info) :-
+ simplify_info_get_module_info(!.Info, ModuleInfo),
+ module_info_get_globals(ModuleInfo, Globals),
+ globals.lookup_bool_option(Globals, pregenerated_dist, no),
+ target_bits_per_int(Globals, bits_per_int(TargetBitsPerInt)),
+ (
+ ( PredName = "/"
+ ; PredName = "//"
+ ),
+ Args = [X, Y, Z],
+ instmap_lookup_var(InstMap0, Y, InstY),
+ InstY = bound(_, _, [bound_functor(uint_const(YVal), [])]),
+ YVal \= cast_from_int(0),
+ Op = "unchecked_quotient",
+ simplify_make_uint_binary_op_goal_expr(!.Info, Op, inline_builtin,
+ X, Y, Z, ImprovedGoalExpr)
+ ;
+ PredName = "rem",
+ Args = [X, Y, Z],
+ instmap_lookup_var(InstMap0, Y, InstY),
+ InstY = bound(_, _, [bound_functor(uint_const(YVal), [])]),
+ YVal \= cast_from_int(0),
+ Op = "unchecked_rem",
+ simplify_make_uint_binary_op_goal_expr(!.Info, Op, inline_builtin,
+ X, Y, Z, ImprovedGoalExpr)
+ ;
+ PredName = "<<",
+ Args = [X, Y, Z],
+ instmap_lookup_var(InstMap0, Y, InstY),
+ InstY = bound(_, _, [bound_functor(int_const(YVal), [])]),
+ YVal >= 0,
+ YVal < TargetBitsPerInt,
+ Op = "unchecked_left_shift",
+ simplify_make_uint_binary_op_goal_expr(!.Info, Op, inline_builtin,
+ X, Y, Z, ImprovedGoalExpr)
+ ;
+ PredName = ">>",
+ Args = [X, Y, Z],
+ instmap_lookup_var(InstMap0, Y, InstY),
+ InstY = bound(_, _, [bound_functor(int_const(YVal), [])]),
+ YVal >= 0,
+ YVal < TargetBitsPerInt,
+ Op = "unchecked_right_shift",
+ simplify_make_uint_binary_op_goal_expr(!.Info, Op, inline_builtin,
+ X, Y, Z, ImprovedGoalExpr)
+ ).
+
+:- pred simplify_make_uint_binary_op_goal_expr(simplify_info::in,
+ string::in, builtin_state::in,
+ prog_var::in, prog_var::in, prog_var::in, hlds_goal_expr::out) is det.
+
+simplify_make_uint_binary_op_goal_expr(Info, Op, IsBuiltin, X, Y, Z,
+ GoalExpr) :-
+ UIntModuleSymName = mercury_std_lib_module_name(unqualified("uint")),
+ OpSymName = qualified(UIntModuleSymName, Op),
+ simplify_info_get_module_info(Info, ModuleInfo),
+ module_info_get_predicate_table(ModuleInfo, PredTable),
+ predicate_table_lookup_func_sym_arity(PredTable, is_fully_qualified,
+ OpSymName, 2, OpPredIds),
+ ( if OpPredIds = [OpPredIdPrime] then
+ OpPredId = OpPredIdPrime
+ else
+ unexpected($module, $pred, "cannot find " ++ Op)
+ ),
+ OpProcIdInt = 0,
+ proc_id_to_int(OpProcId, OpProcIdInt),
+ OpArgs = [X, Y, Z],
+ MaybeUnifyContext = no,
+ GoalExpr = plain_call(OpPredId, OpProcId, OpArgs, IsBuiltin,
+ MaybeUnifyContext, OpSymName).
+
%---------------------------------------------------------------------------%
:- end_module check_hlds.simplify.simplify_goal_call.
%---------------------------------------------------------------------------%
More information about the reviews
mailing list