This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: limiting call clobbered registers for library functions

On 01/29/15 10:32, Richard Henderson wrote:
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
problem ?

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
Richard is precisely correct, you can make a call in the asm output of a pattern, but not express the call in the RTL.

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.
(define_insn "zero_extendpsisi2"
  [(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
  jsr ___zero_extendpsisi2_%0
  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.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]