[m-dev.] for review: MLDS->C back-end: efficiency improvements
Peter Ross
peter.ross at miscrit.be
Wed Jan 17 23:52:38 AEDT 2001
On Wed, Jan 17, 2001 at 11:35:22PM +1100, Fergus Henderson wrote:
> Estimated hours taken: 5
>
> Some efficiency improvements to the MLDS->C back-end.
> In particular, use GCC's __builtin_setjmp/__builtin_longjmp(),
> and generate better code for switches whose default case is
> unreachable.
>
> These changes also help to ensure that the MLDS->C back-end should
> generate exactly the same assembler code as the MLDS->GCC back-end,
> which makes it easier to debug the latter (by using `diff' on the
> generated `.s' files).
>
> compiler/mlds_to_c.m:
> For unreachable default cases, use `MR_assert(0)' rather than
> `assert(0)'. This improves efficiency, since `MR_assert' is
> disabled unless you compile with -DMR_LOWLEVEL_DEBUG.
> These checks were useful in debugging the MLDS back-end, but
> it's probably not worth keeping them enabled by default now.
>
> Put the default case first, so that if it is empty (as it will
> be if the default is unreachable and MR_assert() is not enabled),
> it gets merged with.
>
with what?
> Replace an obsolete comment about a problem with setjmp() and
> volatile with a comment explaining how that problem was fixed.
>
> Generate calls to MR_builtin_setjmp() and MR_builtin_longjmp()
> rather than to setjmp() and longjmp().
>
I would prefer MR_setjmp() and MR_longjmp() because that is the more
general case.
> runtime/mercury.h:
> Define MR_builtin_setjmp() and MR_builtin_longjmp().
> These expand to __builtin_setjmp()/__builtin_longjmp() for GNU C
> and to the standard setjmp()/longjmp() otherwise.
>
> compiler/ml_code_gen.m:
> Add some comments about __builtin_setjmp() and __builtin_longjmp().
>
> Workspace: /home/hg/fjh/gcc-cvs/gcc/mercury
> Index: compiler/ml_code_gen.m
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/compiler/ml_code_gen.m,v
> retrieving revision 1.72
> diff -u -d -r1.72 ml_code_gen.m
> --- compiler/ml_code_gen.m 2000/12/14 08:02:18 1.72
> +++ compiler/ml_code_gen.m 2001/01/17 12:25:52
> @@ -150,6 +150,7 @@
> % There's several different ways of handling commits:
> % - using catch/throw
> % - using setjmp/longjmp
> +% - using GCC's __builtin_setjmp/__builtin_longjmp
> % - exiting nested functions via gotos to
> % their containing functions
> %
> @@ -158,6 +159,17 @@
> % The comments below show the MLDS try_commit/do_commit version first,
> % but for clarity I've also included sample code using each of the three
> % different techniques.
> +%
> +% Note that if we're using GCC's __builtin_longjmp(),
> +% then it is important that the call to __builtin_longjmp() be
> +% put in its own function, to ensure that it is not in the same
> +% function as the __builtin_setjmp().
> +% The code generation schema below does that automatically.
> +% We will need to be careful with MLDS optimizations to
> +% ensure that we preserve that invariant, though.
> +% (Alternatively, we could just call a function that
> +% calls __builtin_longjmp() rather than calling it directly.
> +% But that would be a little less efficient.)
> %
I can see this being a gotcha that is going to get us at some stage. I
would prefer to see some sort of check added to avoid this problem.
Maybe we should add a pass which traverses the MLDS just before output
and checks for any problems.
> % If those methods turn out to be too inefficient,
> % another alternative would be to change the generated
> Index: runtime/mercury.h
> ===================================================================
> RCS file: /home/mercury1/repository/mercury/runtime/mercury.h,v
> retrieving revision 1.32
> diff -u -d -r1.32 mercury.h
> --- runtime/mercury.h 2001/01/14 03:10:53 1.32
> +++ runtime/mercury.h 2001/01/17 12:13:13
> @@ -70,6 +70,22 @@
> typedef void MR_CALL (*MR_Cont) (void *); /* for --no-gcc-nested-functions */
>
> /*
> +** The jmp_buf type used by MR_builtin_setjmp()
> +** to save the stack context when implementing commits.
> +*/
> +#ifdef __GNUC__
> + /*
> + ** For GCC, we use `__builtin_setjmp' and `__builtin_longjmp'.
> + ** These are documented (in gcc/builtins.c in the GCC source code)
> + ** as taking as their parameter a pointer to an array of five words.
s/as taking as/as taking for/
reads slightly better to me.
> + */
> + typedef void *MR_builtin_jmp_buf[5];
> +#else
> + /* Otherwise we use the standard jmp_buf type */
> + typedef jmp_buf MR_builtin_jmp_buf;
> +#endif
> +
> +/*
> ** The types uses to represent the Mercury builtin types,
> ** MR_Char, MR_Float, MR_Integer, MR_String, and MR_ConstString,
> ** are defined in mercury_types.h and mercury_float.h.
> @@ -277,6 +293,24 @@
> /*
> ** Macro / inline function definitions
> */
> +
> +/*
> +** These macros expand to the either the standard setjmp()/longjmp()
> +** or to the GNU __builtin_setjmp() and __builtin_longjmp().
> +** The GNU versions are the same as the standard versions,
> +** except that they are more efficient, and that they have two
> +** restrictions:
> +** 1. The second argument to __builtin_longjmp() must always be `1'.
> +** 2. The call to __builtin_longjmp() must not be in the same
> +** function as the call to __builtin_setjmp().
> +*/
> +#ifdef __GNUC__
> + #define MR_builtin_setjmp(buf) __builtin_setjmp((buf))
> + #define MR_builtin_longjmp(buf, val) __builtin_longjmp((buf), (val))
> +#else
> + #define MR_builtin_setjmp(buf) setjmp((buf))
> + #define MR_builtin_longjmp(buf, val) longjmp((buf), (val))
> +#endif
>
--------------------------------------------------------------------------
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