[m-dev.] for review: eliminate cast_to_unsigned
Fergus Henderson
fjh at cs.mu.OZ.AU
Sat Jan 20 01:50:39 AEDT 2001
Estimated hours taken: 3
Delete the `cast_to_unsigned' unary operator from builtin_ops, and
replace it with an `unsigned_le' binary operator for doing unsigned
less-then-or-equal comparisons.
This change makes the semantics and typing of the builtin operators
more consistent.
compiler/builtin_ops.m:
Delete the `cast_to_unsigned' unary_op.
Add a new `unsigned_le' binary_op.
compiler/dense_switch.m:
compiler/lookup_switch.m:
compiler/ml_simplify_switch.m:
Use `binop(unsigned_le, X, Y)' rather than
`binop(<=, unop(cast_to_unsigned, X), Y)'.
compiler/bytecode.m:
compiler/c_util.m:
compiler/llds.m:
compiler/llds_out.m:
compiler/mlds_to_gcc.m:
compiler/mlds_to_il.m:
compiler/opt_debug.m:
compiler/vn_util.m:
compiler/vn_cost.m:
Delete code for handling `cast_to_unsigned'
and instead add code for handling `unsigned_le'.
compiler/vn_cost.m:
Also add `mktag' and `unmktag' as zero_cost_unops.
compiler/c_util.m:
Add a new procedure `c_util__unsigned_comparison_op',
for use by llds_out.m.
Workspace: /home/hg/fjh/gcc-cvs/gcc/mercury
Index: compiler/builtin_ops.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/builtin_ops.m,v
retrieving revision 1.4
diff -u -d -r1.4 builtin_ops.m
--- compiler/builtin_ops.m 2000/12/14 02:04:27 1.4
+++ compiler/builtin_ops.m 2001/01/19 06:17:35
@@ -26,7 +26,6 @@
; unmktag
; mkbody
; unmkbody
- ; cast_to_unsigned
; hash_string
; bitwise_complement
; (not).
@@ -56,10 +55,11 @@
; str_gt
; str_le
; str_ge
- ; (<) % integer comparions
+ ; (<) % signed integer comparions
; (>)
; (<=)
; (>=)
+ ; unsigned_le % unsigned integer comparison
; float_plus
; float_minus
; float_times
Index: compiler/bytecode.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/bytecode.m,v
retrieving revision 1.44
diff -u -d -r1.44 bytecode.m
--- compiler/bytecode.m 2001/01/18 03:51:26 1.44
+++ compiler/bytecode.m 2001/01/19 07:47:45
@@ -1049,6 +1049,7 @@
binop_code(float_le, 33).
binop_code(float_ge, 34).
binop_code(body, 35).
+binop_code(unsigned_le, 36).
:- pred binop_debug(binary_op, string).
:- mode binop_debug(in, out) is det.
@@ -1089,6 +1090,7 @@
binop_debug(float_le, "float_le").
binop_debug(float_ge, "float_ge").
binop_debug(body, "body").
+binop_debug(unsigned_le, "unsigned_le").
:- pred unop_code(unary_op, int).
:- mode unop_code(in, out) is det.
@@ -1098,7 +1100,8 @@
unop_code(unmktag, 2).
unop_code(mkbody, 3).
unop_code(unmkbody, 4).
-unop_code(cast_to_unsigned, 5).
+% We used to use value `5' for cast_to_unsigned.
+% This is now no longer used.
unop_code(hash_string, 6).
unop_code(bitwise_complement, 7).
unop_code((not), 8).
@@ -1111,7 +1114,6 @@
unop_debug(unmktag, "unmktag").
unop_debug(mkbody, "mkbody").
unop_debug(unmkbody, "unmkbody").
-unop_debug(cast_to_unsigned, "cast_to_unsigned").
unop_debug(hash_string, "has_string").
unop_debug(bitwise_complement, "bitwise_complement").
unop_debug((not), "not").
Index: compiler/c_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/c_util.m,v
retrieving revision 1.6
diff -u -d -r1.6 c_util.m
--- compiler/c_util.m 2000/10/16 01:33:30 1.6
+++ compiler/c_util.m 2001/01/19 07:18:44
@@ -84,13 +84,19 @@
:- pred c_util__float_compare_op(binary_op, string).
:- mode c_util__float_compare_op(in, out) is semidet.
- % The operator returned with be either a prefix operator
+ % The operator returned will be an infix operator.
+ % The arguments should be cast to MR_Unsigned,
+ % and the result will be a boolean.
+:- pred c_util__unsigned_compare_op(binary_op, string).
+:- mode c_util__unsigned_compare_op(in, out) is semidet.
+
+ % The operator returned will be either a prefix operator
% or a macro or function name. The operand needs
% to be placed in parentheses after the operator name.
:- pred c_util__unary_prefix_op(unary_op, string).
:- mode c_util__unary_prefix_op(in, out) is det.
- % The operator returned with be an infix operator.
+ % The operator returned will be an infix operator.
% The arguments should be integer or booleans
% and the result will be an integer or a boolean.
:- pred c_util__binary_infix_op(binary_op, string).
@@ -208,7 +214,6 @@
c_util__unary_prefix_op(hash_string, "MR_hash_string").
c_util__unary_prefix_op(bitwise_complement, "~").
c_util__unary_prefix_op(not, "!").
-c_util__unary_prefix_op(cast_to_unsigned, "(MR_Unsigned)").
c_util__string_compare_op(str_eq, "==").
c_util__string_compare_op(str_ne, "!=").
@@ -217,6 +222,8 @@
c_util__string_compare_op(str_lt, "<").
c_util__string_compare_op(str_gt, ">").
+c_util__unsigned_compare_op(unsigned_le, "<=").
+
c_util__float_op(float_plus, "+").
c_util__float_op(float_minus, "-").
c_util__float_op(float_times, "*").
@@ -228,8 +235,6 @@
c_util__float_compare_op(float_ge, ">=").
c_util__float_compare_op(float_lt, "<").
c_util__float_compare_op(float_gt, ">").
-
-%-----------------------------------------------------------------------------%
c_util__binary_infix_op(+, "+").
c_util__binary_infix_op(-, "-").
Index: compiler/dense_switch.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/dense_switch.m,v
retrieving revision 1.39
diff -u -d -r1.39 dense_switch.m
--- compiler/dense_switch.m 2000/11/23 04:32:34 1.39
+++ compiler/dense_switch.m 2001/01/19 06:20:29
@@ -139,7 +139,7 @@
{ CanFail = can_fail },
{ Difference is EndVal - StartVal },
code_info__fail_if_rval_is_false(
- binop(<=, unop(cast_to_unsigned, Index),
+ binop(unsigned_le, Index,
const(int_const(Difference))), RangeCheck)
;
{ CanFail = cannot_fail },
Index: compiler/llds.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds.m,v
retrieving revision 1.272
diff -u -d -r1.272 llds.m
--- compiler/llds.m 2001/01/18 01:18:44 1.272
+++ compiler/llds.m 2001/01/19 07:47:50
@@ -1159,7 +1159,6 @@
llds__unop_return_type(unmktag, word).
llds__unop_return_type(mkbody, word).
llds__unop_return_type(unmkbody, word).
-llds__unop_return_type(cast_to_unsigned, unsigned).
llds__unop_return_type(hash_string, integer).
llds__unop_return_type(bitwise_complement, integer).
llds__unop_return_type(not, bool).
@@ -1169,7 +1168,6 @@
llds__unop_arg_type(unmktag, word).
llds__unop_arg_type(mkbody, word).
llds__unop_arg_type(unmkbody, word).
-llds__unop_arg_type(cast_to_unsigned, word).
llds__unop_arg_type(hash_string, word).
llds__unop_arg_type(bitwise_complement, integer).
llds__unop_arg_type(not, bool).
@@ -1199,6 +1197,7 @@
llds__binop_return_type((>), bool).
llds__binop_return_type((<=), bool).
llds__binop_return_type((>=), bool).
+llds__binop_return_type(unsigned_le, bool).
llds__binop_return_type(float_plus, float).
llds__binop_return_type(float_minus, float).
llds__binop_return_type(float_times, float).
Index: compiler/llds_out.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/llds_out.m,v
retrieving revision 1.170
diff -u -d -r1.170 llds_out.m
--- compiler/llds_out.m 2001/01/18 01:18:46 1.170
+++ compiler/llds_out.m 2001/01/19 07:48:50
@@ -3613,12 +3613,6 @@
( { types_match(DesiredType, ActualType) } ->
% no casting needed
output_rval(Rval)
- ; { Rval = unop(cast_to_unsigned, _) } ->
- % cast_to_unsigned overrides the ordinary type
- % XXX this is a bit of a hack; we should probably
- % eliminate cast_to_unsigned and instead use
- % special unsigned operators
- output_rval(Rval)
;
% We need to convert to the right type first.
% Convertions to/from float must be treated specially;
@@ -3794,6 +3788,16 @@
output_binary_op(Op),
io__write_string(" "),
output_rval(Y),
+ io__write_string(")")
+ ;
+ { c_util__unsigned_compare_op(Op, OpStr) }
+ ->
+ io__write_string("("),
+ output_rval_as_type(X, unsigned),
+ io__write_string(" "),
+ io__write_string(OpStr),
+ io__write_string(" "),
+ output_rval_as_type(Y, unsigned),
io__write_string(")")
;
io__write_string("("),
Index: compiler/lookup_switch.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/lookup_switch.m,v
retrieving revision 1.41
diff -u -d -r1.41 lookup_switch.m
--- compiler/lookup_switch.m 2000/11/23 04:32:26 1.41
+++ compiler/lookup_switch.m 2001/01/19 06:27:54
@@ -300,7 +300,7 @@
{ NeedRangeCheck = can_fail },
{ Difference is EndVal - StartVal },
code_info__fail_if_rval_is_false(
- binop(<=, unop(cast_to_unsigned, Index),
+ binop(unsigned_le, Index,
const(int_const(Difference))), RangeCheck)
;
{ NeedRangeCheck = cannot_fail },
Index: compiler/mlds_to_gcc.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_gcc.m,v
retrieving revision 1.22
diff -u -d -r1.22 mlds_to_gcc.m
--- compiler/mlds_to_gcc.m 2001/01/19 05:31:49 1.22
+++ compiler/mlds_to_gcc.m 2001/01/19 07:19:02
@@ -67,7 +67,7 @@
% - implement annotation in gcc tree to force tailcalls
% - improve code for switches with default_is_unreachable.
% (We already do a reasonably good job, so this is a low priority.)
-% One way would be to implement computed_goto and cast_to_unsigned,
+% One way would be to implement computed_goto and unsigned_le,
% and change target_supports_computed_goto_2(asm) in ml_switch_gen.m
% to `yes'.
%
@@ -3113,11 +3113,6 @@
gcc__build_int(TagBits, TagBitsExpr),
gcc__build_binop(gcc__rshift_expr, 'MR_intptr_t',
Arg, TagBitsExpr, Expr).
-build_unop_expr(cast_to_unsigned, _, _) -->
- % cast_to_unsigned is only needed for dense (computed_goto) switches,
- % and we set target_supports_computed_goto to no for this target,
- % so we shouldn't get any of these
- { unexpected(this_file, "cast_to_unsigned") }.
build_unop_expr(hash_string, Arg, Expr) -->
gcc__build_func_addr_expr(gcc__hash_string_func_decl,
HashStringFuncExpr),
@@ -3146,6 +3141,25 @@
gcc__build_int(0, Zero),
gcc__build_binop(CorrespondingIntOp, gcc__boolean_type_node,
GCC_Call, Zero, Expr)
+ ; { unsigned_compare_op(BinaryOp, _GCC_BinaryOp) } ->
+ % XXX This is not implemented yet, because we don't have
+ % 'MR_Unsigned'. But unsigned_le is only needed for dense
+ % (computed_goto) switches, and we set
+ % target_supports_computed_goto to no for this target,
+ % so we shouldn't get any of these.
+ { unexpected(this_file, "unsigned comparison operator") }
+ /***
+ %
+ % Treat unsigned comparison operators specially:
+ % convert the arguments to unsigned.
+ %
+ build_rval(Arg1, DefnInfo, GCC_Arg1),
+ build_rval(Arg2, DefnInfo, GCC_Arg2),
+ gcc__convert_type(GCC_Arg1, 'MR_Unsigned', GCC_UnsignedArg1),
+ gcc__convert_type(GCC_Arg2, 'MR_Unsigned', GCC_UnsignedArg2),
+ gcc__build_binop(GCC_BinaryOp, gcc__boolean_type_node,
+ GCC_UnsignedArg1, GCC_UnsignedArg2, Expr)
+ ***/
;
%
% the usual case: just build a gcc tree node for the expr.
@@ -3166,6 +3180,10 @@
string_compare_op(str_le, gcc__le_expr).
string_compare_op(str_ge, gcc__ge_expr).
+:- pred unsigned_compare_op(builtin_ops__binary_op, gcc__op).
+:- mode unsigned_compare_op(in, out) is semidet.
+unsigned_compare_op(unsigned_le, gcc__le_expr).
+
% Convert one of our operators to the corresponding
% gcc operator. Also compute the gcc return type.
:- pred convert_binary_op(builtin_ops__binary_op, gcc__op, gcc__type).
@@ -3202,6 +3220,7 @@
convert_binary_op((>), gcc__gt_expr, gcc__boolean_type_node).
convert_binary_op((<=), gcc__le_expr, gcc__boolean_type_node).
convert_binary_op((>=), gcc__ge_expr, gcc__boolean_type_node).
+convert_binary_op(unsigned_le, _, _) :- unexpected(this_file, "unsigned_le").
convert_binary_op(float_plus, gcc__plus_expr, 'MR_Float').
convert_binary_op(float_minus, gcc__minus_expr, 'MR_Float').
convert_binary_op(float_times, gcc__mult_expr, 'MR_Float').
Index: compiler/mlds_to_il.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_il.m,v
retrieving revision 1.9
diff -u -d -r1.9 mlds_to_il.m
--- compiler/mlds_to_il.m 2001/01/17 00:52:28 1.9
+++ compiler/mlds_to_il.m 2001/01/19 06:53:27
@@ -1304,7 +1304,6 @@
unaryop_to_il(std_unop(mkbody), _, comment_node("mkbody (a no-op)")) --> [].
unaryop_to_il(std_unop(unmkbody), _, comment_node("unmkbody (a no-op)")) --> [].
-unaryop_to_il(std_unop(cast_to_unsigned), _, instr_node(conv(uint32))) --> [].
% XXX implement this using string__hash
unaryop_to_il(std_unop(hash_string), _,
throw_unimplemented("unimplemented hash_string unop")) --> [].
@@ -1461,6 +1460,8 @@
binaryop_to_il((>), node([cgt(signed)])) --> [].
binaryop_to_il((<=), node([cgt(signed), ldc(int32, i(0)), ceq])) --> [].
binaryop_to_il((>=), node([clt(signed), ldc(int32, i(0)), ceq])) --> [].
+binaryop_to_il(unsigned_le, node([cgt(unsigned), ldc(int32, i(0)), ceq])) -->
+ [].
% Floating pointer operations.
binaryop_to_il(float_plus, throw_unimplemented("floating point")) --> [].
Index: compiler/ml_simplify_switch.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_simplify_switch.m,v
retrieving revision 1.1
diff -u -d -r1.1 ml_simplify_switch.m
--- compiler/ml_simplify_switch.m 2000/11/21 13:37:43 1.1
+++ compiler/ml_simplify_switch.m 2001/01/19 06:28:11
@@ -266,7 +266,7 @@
{ NeedRangeCheck = yes }
->
{ Difference is LastVal - FirstVal },
- { InRange = binop(<=, unop(std_unop(cast_to_unsigned), Index),
+ { InRange = binop(unsigned_le, Index,
const(int_const(Difference))) },
{ Else = yes(mlds__statement(
block([], DefaultStatements),
Index: compiler/opt_debug.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/opt_debug.m,v
retrieving revision 1.111
diff -u -d -r1.111 opt_debug.m
--- compiler/opt_debug.m 2001/01/18 01:18:51 1.111
+++ compiler/opt_debug.m 2001/01/19 07:47:53
@@ -866,7 +866,6 @@
opt_debug__dump_unop(not, "not").
opt_debug__dump_unop(hash_string, "hash_string").
opt_debug__dump_unop(bitwise_complement, "bitwise_complement").
-opt_debug__dump_unop(cast_to_unsigned, "cast_to_unsigned").
opt_debug__dump_binop(Op, String) :-
llds_out__binary_op_to_string(Op, String).
Index: compiler/vn_cost.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_cost.m,v
retrieving revision 1.44
diff -u -d -r1.44 vn_cost.m
--- compiler/vn_cost.m 2000/10/13 04:05:25 1.44
+++ compiler/vn_cost.m 2001/01/19 06:32:20
@@ -397,7 +397,10 @@
:- pred vn_cost__zero_cost_unop(unary_op).
:- mode vn_cost__zero_cost_unop(in) is semidet.
-vn_cost__zero_cost_unop(cast_to_unsigned).
+% This assumes that we're using low tags.
+% For high tags, it should be mkbody and unmkbody instead.
+vn_cost__zero_cost_unop(mktag).
+vn_cost__zero_cost_unop(unmktag).
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
Index: compiler/vn_util.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/vn_util.m,v
retrieving revision 1.70
diff -u -d -r1.70 vn_util.m
--- compiler/vn_util.m 2000/10/13 04:05:30 1.70
+++ compiler/vn_util.m 2001/01/19 07:01:46
@@ -217,14 +217,10 @@
:- pred vn_util__vnrval_may_share_vn(vnrval).
:- mode vn_util__vnrval_may_share_vn(in) is semidet.
-vn_util__vnrval_may_share_vn(Vnrval) :-
- (
- Vnrval = vn_unop(cast_to_unsigned, _)
- ->
- fail
- ;
- true
- ).
+vn_util__vnrval_may_share_vn(_Vnrval) :-
+ % Currently any vnrval may share vn.
+ % We used to fail here for `cast_to_unsigned' operators.
+ semidet_succeed.
% Simplify the vnrval by partially evaluating expressions involving
% constants. To make this simpler, swap the arguments of commutative
@@ -774,6 +770,11 @@
false, Vnrval),
VnTables = VnTables0
;
+ Binop = unsigned_le,
+ vn_util__simplify_int_compare_op(unsigned_le, Vn1, Vnrval1,
+ Vn2, Vnrval2, true, Vnrval),
+ VnTables = VnTables0
+ ;
Binop = (float_eq),
vn_util__simplify_float_compare_op(float_eq, Vn1, Vnrval1,
Vn2, Vnrval2, true, Vnrval),
@@ -905,6 +906,25 @@
)
;
vn_util__const_if_equal_vns(Vn1, Vn2, ResultIfEqual, Vnrval)
+ ).
+
+ % unsigned_le(X, Y) performs an unsigned less-than-or-equal
+ % comparison. It should succeed iff the C expression
+ % `(MR_Unsigned)(X) < (MR_Unsigned)(Y)' evaluates to true.
+:- pred unsigned_le(int::in, int::in) is semidet.
+unsigned_le(X, Y) :-
+ ( X < 0, Y >= 0 ->
+ % when cast to unsigned, X will be a big positive number,
+ % and Y will be smaller, so we must fail
+ fail
+ ; X >= 0, Y < 0 ->
+ % when cast to unsigned, Y will be a big positive number,
+ % and X will be smaller, so we must succeed
+ true
+ ;
+ % if they both have the same sign, then we can just do
+ % an ordinary comparison.
+ X =< Y
).
:- pred float_eq(float::in, float::in) is semidet.
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
| of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to: mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions: mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------
More information about the developers
mailing list