https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54089

--- Comment #95 from Oleg Endo <olegendo at gcc dot gnu.org> ---
(In reply to Oleg Endo from comment #93)
> (In reply to Alexander Klepikov from comment #92)
> > I remembered why I used two different insns - first to eliminate infinite
> > loop with help of marking insn with attribute, and second because I could
> > not set attribute when emitting insn from C code. Whe have 'get_attr_*'
> > functions but we have not 'set_attr_*'.
> 
> Yes, I thought so.  I'll give it a try myself with your patch ... please
> hold on.

Finally could have a look at it, sorry for the delay.

The infinite loop is in splitting of the 'ashrsi3_n_call' pattern with the
constant 1.  This is because 'ashrsi3_n_call' match overlaps with the 'shar'
pattern.

One quick fix is to put the condition into the first string.  A nicer way would
be to use a predicate which would constrain the operand[2] to "not 1".  But
it's the first and only use so quick version is OK.

In addition, that pattern (not only the split condition) should be matched only
before register allocation, so the 'can_create_pseudo_p' check is moved.

Another point is that you had the 'cfun->machine->ashrsi3_libcall_expanded++;'
in the wrong place.  It was counting up even if it wouldn't have emitted the
libcall.

This seems to work:

(define_insn_and_split "ashrsi3_n_call"
  [(set (match_operand:SI 0 "arith_reg_dest")
        (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand")
                     (match_operand:SI 2 "const_int_operand")))
        (clobber (reg:SI T_REG))]
  "TARGET_SH1 && can_create_pseudo_p () && operands[2] != const1_rtx"
  "#"
  "&& 1"
  [(const_int 0)]
{
  if (expand_ashiftrt (operands))
    DONE;

  if (dump_file)
    fprintf(dump_file, "ashrsi3_n_call: Expanding ashrsi3 libcall\n");

  cfun->machine->ashrsi3_libcall_expanded++;

  int value = INTVAL (operands[2]) & 31;

  char func[18];
  sprintf (func, "__ashiftrt_r4_%d", value);

  emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);

  rtx wrk = gen_reg_rtx (Pmode);
  rtx lab = function_symbol (wrk, func, SFUNC_STATIC).lab;
  emit_insn (gen_ashrsi3_n (GEN_INT (value), wrk, lab));
  emit_move_insn (operands[0], gen_rtx_REG (SImode, 4));
  DONE;
})


However, there is one case from  your previous posts in PR 49263:

int f_rshift(char v){
    return v >> S;
}

This will not work on SH2 and expand to a libcall.  On SH4 the combine pass
converts it into:

Successfully matched this instruction:
(set (reg:SI 166)
    (ashiftrt:SI (reg/v:SI 164 [ v ])
        (const_int 31 [0x1f])))

But it doesn't even try to do so with the 'ashrsi3_n_call' pattern.  Not sure
why ...

Reply via email to