[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