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~

Reply via email to