[m-dev.] diff: fix switches in IL

Fergus Henderson fjh at cs.mu.OZ.AU
Fri Nov 10 01:47:42 AEDT 2000


On 09-Nov-2000, Tyson Dowd <trd at cs.mu.OZ.AU> wrote:
> compiler/mlds_to_il.m:
> 	Implement cast_to_unsigned unop.
...
> @@ -1300,8 +1296,7 @@
>  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), _,
> -	throw_unimplemented("unimplemented cast_to_unsigned unop")) --> [].
> +unaryop_to_il(std_unop(cast_to_unsigned), _, instr_node(conv(uint32))) --> [].

I'm afraid that won't not be sufficient.
`cast_to_unsigned' is a bit of a hack, unfortunately.
The way we use it is not just to convert a value to unsigned, but
actually to change the semantics of the enclosing operator so that it
is e.g. an unsigned comparison rather than a signed comparison.

For the MLDS back-end, currently it is only used in ml_dense_switch.m,
where we have

                { InRange = binop(<=, unop(std_unop(cast_to_unsigned), Index),
                                const(int_const(Difference))) },

This is adapted from similar code in dense_switch.m for the LLDS back-end.
I didn't notice this issue when I was writing ml_dense_switch.m,
otherwise I probably would have done something different.

On thing we could do is to add additional unsigned operators,
either in the standard builtin_ops__binary_op or perhaps just in the
MLDS.  In particular we need unsigned versions of `<=', `div', and `mod'.

Another approach we could take is just to avoid using cast_to_unsigned.
Unsigned `<=' is used in dense switches and lookup switches.
It's used to do a range check with a single comparison.
For that, there is another alternative: we could output the test as
`Index >= 0 && Index <= Max', i.e.

                { InRange = binop(and,
				binop(>=, Index, const(int_const(0))),
				binop(<=, Index,
					const(int_const(Max))) },

instead of as `((Unsigned) Index) <= Max', and rely on the back-end
optimizing that test into a single comparison.  GNU C does that
optimization, and for other C compilers and other back-ends we could
also do it ourselves in mlds_to_c.m/mlds_to_il.m.

Unsigned `div' and `mod' are used in lookup switches, but that can
easily be avoided by using `>>' and `&' instead -- this would probably
be a good idea for the IL back-end (and the JVM back-end) anyway;
currently we're relying on the C compiler to optimize unsigned
division or modulus by a constant into shift or and, and while
any decent C compiler ought to do that, a JIT compiler might not.

Any comments as to which of these two approaches is preferable?

-- 
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