This is the mail archive of the
mailing list for the GCC project.
Re: limiting call clobbered registers for library functions
- From: Jeff Law <law at redhat dot com>
- To: Richard Henderson <rth at redhat dot com>, pshortis at dataworx dot com dot au, gcc at gcc dot gnu dot org
- Date: Thu, 29 Jan 2015 12:52:00 -0700
- Subject: Re: limiting call clobbered registers for library functions
- Authentication-results: sourceware.org; auth=none
- References: <54CA069F dot 1060203 at dataworx dot com dot au> <54CA6E9D dot 6050202 at redhat dot com>
On 01/29/15 10:32, Richard Henderson wrote:
Richard is precisely correct, you can make a call in the asm output of a
pattern, but not express the call in the RTL.
On 01/29/2015 02:08 AM, Paul Shortis wrote:
I've ported GCC to a small 16 bit CPU that has single bit shifts. So I've
handled variable / multi-bit shifts using a mix of inline shifts and calls to
assembler support functions.
The calls to the asm library functions clobber only one (by const) or two
(variable) registers but of course calling these functions causes all of the
standard call clobbered registers to be considered clobbered, thus wasting lots
of candidate registers for use in expressions surrounding these shifts and
causing unnecessary register saves in the surrounding function prologue/epilogue.
I've scrutinized and cloned the actions of other ports that do the same,
however I'm unable to convince the various passes that only r1 and r2 can be
clobbered by these library calls.
Is anyone able to point me in the proper direction for a solution to this
You wind up writing a pattern that contains a call,
but isn't represented in rtl as a call.
The SH port does this for its shifts too. See
The trick here is expressing how parameters are passed and any clobbers.
The example that comes to my mind is the PSI extensions in the mn102
port (long deprecated).
;; The last alternative is necessary because the second operand might
;; have been the frame pointer. The frame pointer would get replaced
;; by (plus (stack_pointer) (const_int)).
;; Reload would think that it only needed a PSImode register in
;; push_reload and at the start of allocate_reload_regs. However,
;; at the end of allocate_reload_reg it would realize that the
;; reload register must also be valid for SImode, and if it was
;; not valid reload would abort.
[(set (match_operand:SI 0 "register_operand" "=d,?d,?*d,?*d")
(zero_extend:SI (match_operand:PSI 1 "extendpsi_operand"
mov %L1,%L0\;movbu %H1,%H0
mov %1,%L0\;jsr ___zero_extendpsisi2_%0
mov a3,%L0\;add %Z1,%L0\;jsr ___zero_extendpsisi2_%0"
[(set_attr "cc" "clobber")])
Except for the memory->register case these extensions were implemented
by a library call. But we don't express the call in RTL and the library
call did not follow the usual mn102 calling conventions. In fact, we
created a specialized ABI for the extension calls.
If you look closely, you'll probably realize we actually had multiple
zero_extendpsisi2 routines in libgcc (4 in total). One with d0 as its
input & result, another with d1, another with d2 and last one with d3.
That avoided lots of register shuffling, but without bloating the
library with 16 variants had we allowed the input and output operand to
be in different registers.
We did similar things for psi->si sign extensions, some truncations,
some negations, prologue/epilogue.