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
(define_expand "ashlsi3"
[(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[2]) && !TARGET_DYNSHIFT)
{
emit_move_insn (gen_rtx_REG (SImode, R4_REG), operands[1]);
rtx funcaddr = gen_reg_rtx (Pmode);
function_symbol (funcaddr, "__ashlsi3_r0", SFUNC_STATIC);
emit_insn (gen_ashlsi3_d_call (operands[0], operands[2], funcaddr));
DONE;
}
})
...
;; 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.
(define_insn "ashlsi3_d_call"
[(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")
(const_int 31))))
(use (match_operand:SI 2 "arith_reg_operand" "r"))
(clobber (reg:SI T_REG))
(clobber (reg:SI PR_REG))]
"TARGET_SH1 && !TARGET_DYNSHIFT"
"jsr @%2%#"
[(set_attr "type" "sfunc")
(set_attr "needs_delay_slot" "yes")])
r~