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

--- Comment #89 from Alexander Klepikov <klepikov.alex+bugs at gmail dot com> 
---
Here's what I did

sh.md:

(define_expand "ashrsi3"
  [(parallel [(set (match_operand:SI 0 "arith_reg_dest" "")
                   (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "")
                                (match_operand:SI 2 "nonmemory_operand" "")))
              (clobber (reg:SI T_REG))])]
  ""
{
  if (expand_ashiftrt (operands))
    DONE;
  if (!CONST_INT_P (operands[2]))
    FAIL;
  int value = INTVAL (operands[2]) & 31;
  emit_insn (gen_ashrsi3_n_call (operands[0], operands[1], GEN_INT(value)));
  DONE;
})

(define_insn_and_split "ashrsi3_n_call"
  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
        (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
                (match_operand:SI 2 "const_int_operand")))
        (clobber (reg:SI T_REG))]
  "TARGET_SH1"
  "#"
  "&& can_create_pseudo_p ()"
  [(const_int 0)]
{
    char func[18];
    int value;
    rtx wrk;

    cfun->machine->ashrsi3_libcall_expanded++;

    if (expand_ashiftrt (operands))
      DONE;
    if (!CONST_INT_P (operands[2]))
      FAIL;
    value = INTVAL (operands[2]) & 31;

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

    wrk = gen_reg_rtx (Pmode);
    /* Load the value into an arg reg and call a helper.  */
    emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
    sprintf (func, "__ashiftrt_r4_%d", value);
    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;
})


sh.cc:

bool
expand_ashiftrt (rtx *operands)
{
  rtx wrk;
  int value;

  if (TARGET_DYNSHIFT)
    {
      if (!CONST_INT_P (operands[2]))
        {
          rtx count = copy_to_mode_reg (SImode, operands[2]);
          emit_insn (gen_negsi2 (count, count));
          emit_insn (gen_ashrsi3_d (operands[0], operands[1], count));
          return true;
        }
      else if (ashiftrt_insns[INTVAL (operands[2]) & 31]
               > 1 + SH_DYNAMIC_SHIFT_COST)
        {
          rtx count
            = force_reg (SImode, GEN_INT (- (INTVAL (operands[2]) & 31)));
          emit_insn (gen_ashrsi3_d (operands[0], operands[1], count));
          return true;
        }
    }
  if (!CONST_INT_P (operands[2]))
    return false;

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

  if (value == 31)
    {
      /* If we are called from abs expansion, arrange things so that we
         we can use a single MT instruction that doesn't clobber the source,
         if LICM can hoist out the load of the constant zero.  */
      if (currently_expanding_to_rtl)
        {
          emit_insn (gen_cmpgtsi_t (force_reg (SImode, CONST0_RTX (SImode)),
                                    operands[1]));
          emit_insn (gen_mov_neg_si_t (operands[0], get_t_reg_rtx ()));
          return true;
        }
      emit_insn (gen_ashrsi2_31 (operands[0], operands[1]));
      return true;
    }
  else if (value >= 16 && value <= 19)
    {
      wrk = gen_reg_rtx (SImode);
      emit_insn (gen_ashrsi2_16 (wrk, operands[1]));
      value -= 16;
      while (value--)
        gen_ashift (ASHIFTRT, 1, wrk);
      emit_move_insn (operands[0], wrk);
      return true;
    }
  /* Expand a short sequence inline, longer call a magic routine.  */
  else if (value <= 5)
    {
      wrk = gen_reg_rtx (SImode);
      emit_move_insn (wrk, operands[1]);
      while (value--)
        gen_ashift (ASHIFTRT, 1, wrk);
      emit_move_insn (operands[0], wrk);
      return true;
    }
  return false;
}


Now GCC falls into infinite loop when compiling this:

int f_short_rshift_signed(char v){
    return v >> 5;
}

It looks like it splits and then combines again.

Reply via email to