mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-09 19:02:18 +00:00
Estimated hours taken: 0.1 Branches: main Remove the reference to `int:^/2' operator in the constant propagation pass since that operator was changed into the field access operator some time ago. compiler/const_prop.m: Remove the reference to `int:^/2'.
407 lines
14 KiB
Mathematica
407 lines
14 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% Copyright (C) 1997-2004 The University of Melbourne.
|
|
% This file may only be copied under the terms of the GNU General
|
|
% Public License - see the file COPYING in the Mercury distribution.
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% file: const_prop.m
|
|
% main author: conway.
|
|
%
|
|
% This module provides the facility to evaluate calls at compile time -
|
|
% transforming them to simpler goals such as construction unifications.
|
|
%
|
|
% XXX We should check for overflow.
|
|
%
|
|
%------------------------------------------------------------------------------%
|
|
|
|
:- module transform_hlds__const_prop.
|
|
|
|
:- interface.
|
|
|
|
:- import_module hlds__hlds_module, hlds__hlds_goal, hlds__hlds_pred.
|
|
:- import_module parse_tree__prog_data, hlds__instmap.
|
|
:- import_module list.
|
|
|
|
:- pred evaluate_builtin(pred_id, proc_id, list(prog_var), hlds_goal_info,
|
|
hlds_goal_expr, hlds_goal_info, instmap,
|
|
module_info, module_info).
|
|
:- mode evaluate_builtin(in, in, in, in, out, out, in, in, out) is semidet.
|
|
|
|
%------------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
:- import_module check_hlds__det_analysis.
|
|
:- import_module check_hlds__inst_match.
|
|
:- import_module check_hlds__mode_util.
|
|
:- import_module check_hlds__modes.
|
|
:- import_module check_hlds__type_util.
|
|
:- import_module hlds__goal_util.
|
|
:- import_module hlds__hlds_data.
|
|
:- import_module hlds__hlds_goal.
|
|
:- import_module hlds__hlds_out.
|
|
:- import_module hlds__instmap.
|
|
:- import_module hlds__passes_aux.
|
|
:- import_module hlds__quantification.
|
|
:- import_module libs__globals.
|
|
:- import_module libs__options.
|
|
:- import_module ll_backend__code_aux.
|
|
:- import_module ll_backend__code_util.
|
|
:- import_module ll_backend__follow_code.
|
|
:- import_module parse_tree__inst.
|
|
:- import_module parse_tree__prog_data.
|
|
|
|
:- import_module bool, list, int, float, map, require, string.
|
|
:- import_module std_util.
|
|
|
|
%------------------------------------------------------------------------------%
|
|
|
|
evaluate_builtin(PredId, ProcId, Args, GoalInfo0, Goal, GoalInfo,
|
|
InstMap, ModuleInfo0, ModuleInfo) :-
|
|
predicate_module(ModuleInfo0, PredId, ModuleName),
|
|
predicate_name(ModuleInfo0, PredId, PredName),
|
|
proc_id_to_int(ProcId, ProcInt),
|
|
LookupVarInsts = (pred(V::in, J::out) is det :-
|
|
instmap__lookup_var(InstMap, V, VInst),
|
|
J = V - VInst
|
|
),
|
|
list__map(LookupVarInsts, Args, ArgInsts),
|
|
evaluate_builtin_2(ModuleName, PredName, ProcInt, ArgInsts, GoalInfo0,
|
|
Goal, GoalInfo, ModuleInfo0, ModuleInfo).
|
|
|
|
:- pred evaluate_builtin_2(module_name, string, int,
|
|
list(pair(prog_var, (inst))), hlds_goal_info, hlds_goal_expr,
|
|
hlds_goal_info, module_info, module_info).
|
|
:- mode evaluate_builtin_2(in, in, in, in, in, out, out, in, out) is semidet.
|
|
|
|
% Module_info is not actually used at the moment.
|
|
|
|
evaluate_builtin_2(Module, Pred, ModeNum, Args, GoalInfo0, Goal, GoalInfo,
|
|
ModuleInfo, ModuleInfo) :-
|
|
% -- not yet:
|
|
% Module = qualified(unqualified("std"), Mod),
|
|
Module = unqualified(Mod),
|
|
(
|
|
Args = [X, Y],
|
|
evaluate_builtin_bi(Mod, Pred, ModeNum, X, Y, W, Cons)
|
|
->
|
|
make_construction(W, Cons, Goal),
|
|
goal_info_get_instmap_delta(GoalInfo0, Delta0),
|
|
W = Var - _WInst,
|
|
instmap_delta_set(Delta0, Var,
|
|
bound(unique, [functor(Cons, [])]), Delta),
|
|
goal_info_set_instmap_delta(GoalInfo0, Delta, GoalInfo)
|
|
;
|
|
Args = [X, Y, Z],
|
|
evaluate_builtin_tri(Mod, Pred, ModeNum, X, Y, Z, W, Cons)
|
|
->
|
|
make_construction(W, Cons, Goal),
|
|
goal_info_get_instmap_delta(GoalInfo0, Delta0),
|
|
W = Var - _WInst,
|
|
instmap_delta_set(Delta0, Var,
|
|
bound(unique, [functor(Cons, [])]), Delta),
|
|
goal_info_set_instmap_delta(GoalInfo0, Delta, GoalInfo)
|
|
;
|
|
evaluate_builtin_test(Mod, Pred, ModeNum, Args, Result)
|
|
->
|
|
make_true_or_fail(Result, GoalInfo0, Goal, GoalInfo)
|
|
;
|
|
fail
|
|
).
|
|
|
|
%------------------------------------------------------------------------------%
|
|
|
|
:- pred evaluate_builtin_bi(string, string, int,
|
|
pair(prog_var, (inst)), pair(prog_var, (inst)),
|
|
pair(prog_var, (inst)), cons_id).
|
|
:- mode evaluate_builtin_bi(in, in, in, in, in, out, out) is semidet.
|
|
|
|
% Integer arithmetic
|
|
|
|
evaluate_builtin_bi("int", "+", 0, X, Z, Z, int_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
ZVal = XVal.
|
|
|
|
evaluate_builtin_bi("int", "-", 0, X, Z, Z, int_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
ZVal = -XVal.
|
|
|
|
evaluate_builtin_bi("int", "\\", 0, X, Z, Z, int_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
ZVal = \ XVal.
|
|
|
|
% Floating point arithmetic
|
|
|
|
evaluate_builtin_bi("float", "+", 0, X, Z, Z, int_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
ZVal = XVal.
|
|
|
|
evaluate_builtin_bi("float", "-", 0, X, Z, Z, int_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
ZVal = -XVal.
|
|
|
|
%------------------------------------------------------------------------------%
|
|
|
|
:- pred evaluate_builtin_tri(string, string, int,
|
|
pair(prog_var, (inst)), pair(prog_var, (inst)),
|
|
pair(prog_var, (inst)), pair(prog_var, (inst)), cons_id).
|
|
:- mode evaluate_builtin_tri(in, in, in, in, in, in, out, out) is semidet.
|
|
|
|
%
|
|
% Integer arithmetic
|
|
%
|
|
evaluate_builtin_tri("int", "+", 0, X, Y, Z, Z, int_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
ZVal = XVal + YVal.
|
|
evaluate_builtin_tri("int", "+", 1, X, Y, Z, X, int_const(XVal)) :-
|
|
Z = _ZVar - bound(_ZUniq, [functor(int_const(ZVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
XVal = ZVal - YVal.
|
|
evaluate_builtin_tri("int", "+", 2, X, Y, Z, Y, int_const(YVal)) :-
|
|
Z = _ZVar - bound(_ZUniq, [functor(int_const(ZVal), [])]),
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
YVal = ZVal - XVal.
|
|
|
|
evaluate_builtin_tri("int", "-", 0, X, Y, Z, Z, int_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
ZVal = XVal - YVal.
|
|
evaluate_builtin_tri("int", "-", 1, X, Y, Z, X, int_const(XVal)) :-
|
|
Z = _ZVar - bound(_ZUniq, [functor(int_const(ZVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
XVal = YVal + ZVal.
|
|
evaluate_builtin_tri("int", "-", 2, X, Y, Z, Y, int_const(YVal)) :-
|
|
Z = _ZVar - bound(_ZUniq, [functor(int_const(ZVal), [])]),
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
YVal = XVal - ZVal.
|
|
|
|
evaluate_builtin_tri("int", "*", 0, X, Y, Z, Z, int_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
ZVal = XVal * YVal.
|
|
|
|
% This isn't actually a builtin.
|
|
evaluate_builtin_tri("int", "//", 0, X, Y, Z, Z, int_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
YVal \= 0,
|
|
ZVal = XVal // YVal.
|
|
|
|
evaluate_builtin_tri("int", "unchecked_quotient", 0, X, Y, Z, Z,
|
|
int_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
YVal \= 0,
|
|
ZVal = unchecked_quotient(XVal, YVal).
|
|
|
|
% This isn't actually a builtin.
|
|
evaluate_builtin_tri("int", "mod", 0, X, Y, Z, Z, int_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
YVal \= 0,
|
|
ZVal = XVal mod YVal.
|
|
|
|
% This isn't actually a builtin.
|
|
evaluate_builtin_tri("int", "rem", 0, X, Y, Z, Z, int_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
YVal \= 0,
|
|
ZVal = XVal rem YVal.
|
|
|
|
evaluate_builtin_tri("int", "unchecked_rem", 0, X, Y, Z, Z, int_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
YVal \= 0,
|
|
ZVal = unchecked_rem(XVal, YVal).
|
|
|
|
evaluate_builtin_tri("int", "unchecked_left_shift",
|
|
0, X, Y, Z, Z, int_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
ZVal = unchecked_left_shift(XVal, YVal).
|
|
|
|
% This isn't actually a builtin.
|
|
evaluate_builtin_tri("int", "<<", 0, X, Y, Z, Z, int_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
ZVal = XVal << YVal.
|
|
|
|
evaluate_builtin_tri("int", "unchecked_right_shift",
|
|
0, X, Y, Z, Z, int_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
ZVal = unchecked_right_shift(XVal, YVal).
|
|
|
|
% This isn't actually a builtin.
|
|
evaluate_builtin_tri("int", ">>", 0, X, Y, Z, Z, int_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
ZVal = XVal >> YVal.
|
|
|
|
evaluate_builtin_tri("int", "/\\", 0, X, Y, Z, Z, int_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
ZVal = XVal /\ YVal.
|
|
|
|
evaluate_builtin_tri("int", "\\/", 0, X, Y, Z, Z, int_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
ZVal = XVal \/ YVal.
|
|
|
|
evaluate_builtin_tri("int", "xor", 0, X, Y, Z, Z, int_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
ZVal = XVal `xor` YVal.
|
|
|
|
%
|
|
% float arithmetic
|
|
%
|
|
|
|
evaluate_builtin_tri("float", "+", 0, X, Y, Z, Z, float_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(float_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(float_const(YVal), [])]),
|
|
ZVal = XVal + YVal.
|
|
|
|
evaluate_builtin_tri("float", "-", 0, X, Y, Z, Z, float_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(float_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(float_const(YVal), [])]),
|
|
ZVal = XVal - YVal.
|
|
|
|
evaluate_builtin_tri("float", "*", 0, X, Y, Z, Z, float_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(float_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(float_const(YVal), [])]),
|
|
ZVal = XVal * YVal.
|
|
|
|
% This isn't actually a builtin.
|
|
evaluate_builtin_tri("float", "/", 0, X, Y, Z, Z, float_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(float_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(float_const(YVal), [])]),
|
|
YVal \= 0.0,
|
|
ZVal = XVal / YVal.
|
|
|
|
evaluate_builtin_tri("float", "unchecked_quotient", 0, X, Y, Z, Z,
|
|
float_const(ZVal)) :-
|
|
X = _XVar - bound(_XUniq, [functor(float_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(float_const(YVal), [])]),
|
|
YVal \= 0.0,
|
|
ZVal = unchecked_quotient(XVal, YVal).
|
|
|
|
% This isn't actually a builtin.
|
|
evaluate_builtin_tri("string", Name, _, X, Y, Z, Z, string_const(ZVal)) :-
|
|
( Name = "++"
|
|
; Name = "append"
|
|
),
|
|
X = _XVar - bound(_XUniq, [functor(string_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(string_const(YVal), [])]),
|
|
|
|
% We can only do the append if Z is free (this allows
|
|
% us to ignore the mode number and pick up both the
|
|
% predicate and function versions of append)
|
|
Z = _ZVar - free,
|
|
ZVal = XVal ++ YVal.
|
|
|
|
%------------------------------------------------------------------------------%
|
|
|
|
:- pred evaluate_builtin_test(string, string, int,
|
|
list(pair(prog_var, inst)), bool).
|
|
:- mode evaluate_builtin_test(in, in, in, in, out) is semidet.
|
|
|
|
% Integer comparisons
|
|
|
|
evaluate_builtin_test("int", "<", 0, Args, Result) :-
|
|
Args = [X, Y],
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
( XVal < YVal ->
|
|
Result = yes
|
|
;
|
|
Result = no
|
|
).
|
|
evaluate_builtin_test("int", "=<", 0, Args, Result) :-
|
|
Args = [X, Y],
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
( XVal =< YVal ->
|
|
Result = yes
|
|
;
|
|
Result = no
|
|
).
|
|
evaluate_builtin_test("int", ">", 0, Args, Result) :-
|
|
Args = [X, Y],
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
( XVal > YVal ->
|
|
Result = yes
|
|
;
|
|
Result = no
|
|
).
|
|
evaluate_builtin_test("int", ">=", 0, Args, Result) :-
|
|
Args = [X, Y],
|
|
X = _XVar - bound(_XUniq, [functor(int_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(int_const(YVal), [])]),
|
|
( XVal >= YVal ->
|
|
Result = yes
|
|
;
|
|
Result = no
|
|
).
|
|
|
|
% Float comparisons
|
|
|
|
evaluate_builtin_test("float", "<", 0, Args, Result) :-
|
|
Args = [X, Y],
|
|
X = _XVar - bound(_XUniq, [functor(float_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(float_const(YVal), [])]),
|
|
( XVal < YVal ->
|
|
Result = yes
|
|
;
|
|
Result = no
|
|
).
|
|
evaluate_builtin_test("float", "=<", 0, Args, Result) :-
|
|
Args = [X, Y],
|
|
X = _XVar - bound(_XUniq, [functor(float_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(float_const(YVal), [])]),
|
|
( XVal =< YVal ->
|
|
Result = yes
|
|
;
|
|
Result = no
|
|
).
|
|
evaluate_builtin_test("float", ">", 0, Args, Result) :-
|
|
Args = [X, Y],
|
|
X = _XVar - bound(_XUniq, [functor(float_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(float_const(YVal), [])]),
|
|
( XVal > YVal ->
|
|
Result = yes
|
|
;
|
|
Result = no
|
|
).
|
|
evaluate_builtin_test("float", ">=", 0, Args, Result) :-
|
|
Args = [X, Y],
|
|
X = _XVar - bound(_XUniq, [functor(float_const(XVal), [])]),
|
|
Y = _YVar - bound(_YUniq, [functor(float_const(YVal), [])]),
|
|
( XVal >= YVal ->
|
|
Result = yes
|
|
;
|
|
Result = no
|
|
).
|
|
|
|
%------------------------------------------------------------------------------%
|
|
|
|
% recompute_instmap_delta is run by simplify.m if anything changes,
|
|
% so the insts are not important here.
|
|
:- pred make_construction(pair(prog_var, inst), cons_id, hlds_goal_expr).
|
|
:- mode make_construction(in, in, out) is det.
|
|
|
|
make_construction(Var - _, ConsId, Goal) :-
|
|
make_const_construction(Var, ConsId, Goal - _).
|
|
|
|
%------------------------------------------------------------------------------%
|
|
|
|
:- pred make_true_or_fail(bool, hlds_goal_info, hlds_goal_expr, hlds_goal_info).
|
|
:- mode make_true_or_fail(in, in, out, out) is det.
|
|
|
|
make_true_or_fail(yes, GoalInfo, conj([]), GoalInfo).
|
|
make_true_or_fail(no, GoalInfo, disj([]), GoalInfo).
|
|
|
|
%------------------------------------------------------------------------------%
|