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

Tyson Dowd trd at cs.mu.OZ.AU
Fri Nov 10 12:41:16 AEDT 2000


On 10-Nov-2000, Fergus Henderson <fjh at cs.mu.OZ.AU> wrote:
> 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.

Right, this is an instance of the C syntax creeping into MLDS.
I like to fix these problems by adding the right operations to MLDS to
express the semantics you want.

I think it's a really dumb idea to have *any* unop operate on the
enclosing operator (although in C syntax it does this indirectly).

unsigned as an unary operator could have the property of making the *enclosed*
operation an unsigned variant of that operation.

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

cast_to_unsigned would now always mean "turn this integer value into its
unsigned equivalent".

Actually, perhaps would be better handled using 
		unop(unsigned, cast(SomeNumericType))

cast_to_unsigned could be banned from MLDS altogether.

You could also use it for
		unop(unsigned, const(int_const(X)))
to create unsigned integer constants (although we don't have a type for
such an entity yet).


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

Or you could do this, but this adds several specific version of
operations.

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

We could also do this with an unsigned unop.

Since you want readability for the MLDS, I think the unsigned unop would
be better, since it would generate the readable (if somewhat cryptic)
	((Unsinged Index) <= Max
in GNU C.

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

I could teach the code generator or the peephole optimizer about that
one.

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

I like unsigned as an operator.

If there is a big problem with this (and there might well be), then
unsigned variants of some operations would be OK.

-- 
       Tyson Dowd           # 
                            #  Surreal humour isn't everyone's cup of fur.
     trd at cs.mu.oz.au        # 
http://www.cs.mu.oz.au/~trd #
--------------------------------------------------------------------------
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