This is the mail archive of the
mailing list for the GCC project.
Re: limiting call clobbered registers for library functions
- From: Richard Henderson <rth at redhat dot com>
- To: pshortis at dataworx dot com dot au, gcc at gcc dot gnu dot org
- Date: Thu, 29 Jan 2015 09:32:13 -0800
- 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>
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
[(set (match_operand:SI 0 "arith_reg_operand" "")
(ashift:SI (match_operand:SI 1 "arith_reg_operand" "")
(match_operand:SI 2 "shift_count_operand" "")))]
/* Expand a library call for the dynamic shift. */
if (!CONST_INT_P (operands) && !TARGET_DYNSHIFT)
emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands);
rtx funcaddr = gen_reg_rtx (Pmode);
function_symbol (funcaddr, "__ashlsi3_r0", SFUNC_STATIC);
emit_insn (gen_ashlsi3_d_call (operands, operands, funcaddr));
;; If dynamic shifts are not available use a library function.
;; By specifying the pattern we reduce the number of call clobbered regs.
;; In order to make combine understand the truncation of the shift amount
;; operand we have to allow it to use pseudo regs for the shift operands.
[(set (match_operand:SI 0 "arith_reg_dest" "=z")
(ashift:SI (reg:SI R4_REG)
(and:SI (match_operand:SI 1 "arith_reg_operand" "z")
(use (match_operand:SI 2 "arith_reg_operand" "r"))
(clobber (reg:SI T_REG))
(clobber (reg:SI PR_REG))]
"TARGET_SH1 && !TARGET_DYNSHIFT"
[(set_attr "type" "sfunc")
(set_attr "needs_delay_slot" "yes")])