On Thu, Oct 26, 2017 at 2:06 PM, Richard Biener
<richard.guent...@gmail.com> wrote:
> On Mon, Oct 23, 2017 at 1:25 PM, Richard Sandiford
> <richard.sandif...@linaro.org> wrote:
>> This patch adds a stub helper routine to provide the mode
>> of a scalar shift amount, given the mode of the values
>> being shifted.
>>
>> One long-standing problem has been to decide what this mode
>> should be for arbitrary rtxes (as opposed to those directly
>> tied to a target pattern).  Is it the mode of the shifted
>> elements?  Is it word_mode?  Or maybe QImode?  Is it whatever
>> the corresponding target pattern says?  (In which case what
>> should the mode be when the target doesn't have a pattern?)
>>
>> For now the patch picks word_mode, which should be safe on
>> all targets but could perhaps become suboptimal if the helper
>> routine is used more often than it is in this patch.  As it
>> stands the patch does not change the generated code.
>>
>> The patch also adds a helper function that constructs rtxes
>> for constant shift amounts, again given the mode of the value
>> being shifted.  As well as helping with the SVE patches, this
>> is one step towards allowing CONST_INTs to have a real mode.
>
> I think gen_shift_amount_mode is flawed and while encapsulating
> constant shift amount RTX generation into a gen_int_shift_amount
> looks good to me I'd rather have that ??? in this function (and
> I'd use the mode of the RTX shifted, not word_mode...).
>
> In the end it's up to insn recognizing to convert the op to the
> expected mode and for generic RTL it's us that should decide
> on the mode -- on GENERIC the shift amount has to be an
> integer so why not simply use a mode that is large enough to
> make the constant fit?
>
> Just throwing in some comments here, RTL isn't my primary
> expertise.

To add a little bit - shift amounts is maybe the only(?) place
where a modeless CONST_INT makes sense!  So "fixing"
that first sounds backwards.

Richard.

> Richard.
>
>>
>> 2017-10-23  Richard Sandiford  <richard.sandif...@linaro.org>
>>             Alan Hayward  <alan.hayw...@arm.com>
>>             David Sherwood  <david.sherw...@arm.com>
>>
>> gcc/
>>         * target.h (get_shift_amount_mode): New function.
>>         * emit-rtl.h (gen_int_shift_amount): Declare.
>>         * emit-rtl.c (gen_int_shift_amount): New function.
>>         * asan.c (asan_emit_stack_protection): Use gen_int_shift_amount
>>         instead of GEN_INT.
>>         * calls.c (shift_return_value): Likewise.
>>         * cse.c (fold_rtx): Likewise.
>>         * dse.c (find_shift_sequence): Likewise.
>>         * expmed.c (init_expmed_one_mode, store_bit_field_1, expand_shift_1)
>>         (expand_shift, expand_smod_pow2): Likewise.
>>         * lower-subreg.c (shift_cost): Likewise.
>>         * simplify-rtx.c (simplify_unary_operation_1): Likewise.
>>         (simplify_binary_operation_1): Likewise.
>>         * combine.c (try_combine, find_split_point, force_int_to_mode)
>>         (simplify_shift_const_1, simplify_shift_const): Likewise.
>>         (change_zero_ext): Likewise.  Use simplify_gen_binary.
>>         * optabs.c (expand_superword_shift, expand_doubleword_mult)
>>         (expand_unop): Use gen_int_shift_amount instead of GEN_INT.
>>         (expand_binop): Likewise.  Use get_shift_amount_mode instead
>>         of word_mode as the mode of a CONST_INT shift amount.
>>         (shift_amt_for_vec_perm_mask): Add a machine_mode argument.
>>         Use gen_int_shift_amount instead of GEN_INT.
>>         (expand_vec_perm): Update caller accordingly.  Use
>>         gen_int_shift_amount instead of GEN_INT.
>>
>> Index: gcc/target.h
>> ===================================================================
>> --- gcc/target.h        2017-10-23 11:47:06.643477568 +0100
>> +++ gcc/target.h        2017-10-23 11:47:11.277288162 +0100
>> @@ -209,6 +209,17 @@ #define HOOKSTRUCT(FRAGMENT) FRAGMENT
>>
>>  extern struct gcc_target targetm;
>>
>> +/* Return the mode that should be used to hold a scalar shift amount
>> +   when shifting values of the given mode.  */
>> +/* ??? This could in principle be generated automatically from the .md
>> +   shift patterns, but for now word_mode should be universally OK.  */
>> +
>> +inline scalar_int_mode
>> +get_shift_amount_mode (machine_mode)
>> +{
>> +  return word_mode;
>> +}
>> +
>>  #ifdef GCC_TM_H
>>
>>  #ifndef CUMULATIVE_ARGS_MAGIC
>> Index: gcc/emit-rtl.h
>> ===================================================================
>> --- gcc/emit-rtl.h      2017-10-23 11:47:06.643477568 +0100
>> +++ gcc/emit-rtl.h      2017-10-23 11:47:11.274393237 +0100
>> @@ -369,6 +369,7 @@ extern void set_reg_attrs_for_parm (rtx,
>>  extern void set_reg_attrs_for_decl_rtl (tree t, rtx x);
>>  extern void adjust_reg_mode (rtx, machine_mode);
>>  extern int mem_expr_equal_p (const_tree, const_tree);
>> +extern rtx gen_int_shift_amount (machine_mode, HOST_WIDE_INT);
>>
>>  extern bool need_atomic_barrier_p (enum memmodel, bool);
>>
>> Index: gcc/emit-rtl.c
>> ===================================================================
>> --- gcc/emit-rtl.c      2017-10-23 11:47:06.643477568 +0100
>> +++ gcc/emit-rtl.c      2017-10-23 11:47:11.273428262 +0100
>> @@ -6478,6 +6478,15 @@ need_atomic_barrier_p (enum memmodel mod
>>      }
>>  }
>>
>> +/* Return a constant shift amount for shifting a value of mode MODE
>> +   by VALUE bits.  */
>> +
>> +rtx
>> +gen_int_shift_amount (machine_mode mode, HOST_WIDE_INT value)
>> +{
>> +  return gen_int_mode (value, get_shift_amount_mode (mode));
>> +}
>> +
>>  /* Initialize fields of rtl_data related to stack alignment.  */
>>
>>  void
>> Index: gcc/asan.c
>> ===================================================================
>> --- gcc/asan.c  2017-10-23 11:47:06.643477568 +0100
>> +++ gcc/asan.c  2017-10-23 11:47:11.270533336 +0100
>> @@ -1388,7 +1388,7 @@ asan_emit_stack_protection (rtx base, rt
>>    TREE_ASM_WRITTEN (id) = 1;
>>    emit_move_insn (mem, expand_normal (build_fold_addr_expr (decl)));
>>    shadow_base = expand_binop (Pmode, lshr_optab, base,
>> -                             GEN_INT (ASAN_SHADOW_SHIFT),
>> +                             gen_int_shift_amount (Pmode, 
>> ASAN_SHADOW_SHIFT),
>>                               NULL_RTX, 1, OPTAB_DIRECT);
>>    shadow_base
>>      = plus_constant (Pmode, shadow_base,
>> Index: gcc/calls.c
>> ===================================================================
>> --- gcc/calls.c 2017-10-23 11:47:06.643477568 +0100
>> +++ gcc/calls.c 2017-10-23 11:47:11.270533336 +0100
>> @@ -2749,15 +2749,17 @@ shift_return_value (machine_mode mode, b
>>    HOST_WIDE_INT shift;
>>
>>    gcc_assert (REG_P (value) && HARD_REGISTER_P (value));
>> -  shift = GET_MODE_BITSIZE (GET_MODE (value)) - GET_MODE_BITSIZE (mode);
>> +  machine_mode value_mode = GET_MODE (value);
>> +  shift = GET_MODE_BITSIZE (value_mode) - GET_MODE_BITSIZE (mode);
>>    if (shift == 0)
>>      return false;
>>
>>    /* Use ashr rather than lshr for right shifts.  This is for the benefit
>>       of the MIPS port, which requires SImode values to be sign-extended
>>       when stored in 64-bit registers.  */
>> -  if (!force_expand_binop (GET_MODE (value), left_p ? ashl_optab : 
>> ashr_optab,
>> -                          value, GEN_INT (shift), value, 1, OPTAB_WIDEN))
>> +  if (!force_expand_binop (value_mode, left_p ? ashl_optab : ashr_optab,
>> +                          value, gen_int_shift_amount (value_mode, shift),
>> +                          value, 1, OPTAB_WIDEN))
>>      gcc_unreachable ();
>>    return true;
>>  }
>> Index: gcc/cse.c
>> ===================================================================
>> --- gcc/cse.c   2017-10-23 11:47:03.707058235 +0100
>> +++ gcc/cse.c   2017-10-23 11:47:11.273428262 +0100
>> @@ -3611,9 +3611,9 @@ fold_rtx (rtx x, rtx_insn *insn)
>>                       || INTVAL (const_arg1) < 0))
>>                 {
>>                   if (SHIFT_COUNT_TRUNCATED)
>> -                   canon_const_arg1 = GEN_INT (INTVAL (const_arg1)
>> -                                               & (GET_MODE_UNIT_BITSIZE 
>> (mode)
>> -                                                  - 1));
>> +                   canon_const_arg1 = gen_int_shift_amount
>> +                     (mode, (INTVAL (const_arg1)
>> +                             & (GET_MODE_UNIT_BITSIZE (mode) - 1)));
>>                   else
>>                     break;
>>                 }
>> @@ -3660,9 +3660,9 @@ fold_rtx (rtx x, rtx_insn *insn)
>>                       || INTVAL (inner_const) < 0))
>>                 {
>>                   if (SHIFT_COUNT_TRUNCATED)
>> -                   inner_const = GEN_INT (INTVAL (inner_const)
>> -                                          & (GET_MODE_UNIT_BITSIZE (mode)
>> -                                             - 1));
>> +                   inner_const = gen_int_shift_amount
>> +                     (mode, (INTVAL (inner_const)
>> +                             & (GET_MODE_UNIT_BITSIZE (mode) - 1)));
>>                   else
>>                     break;
>>                 }
>> @@ -3692,7 +3692,8 @@ fold_rtx (rtx x, rtx_insn *insn)
>>                   /* As an exception, we can turn an ASHIFTRT of this
>>                      form into a shift of the number of bits - 1.  */
>>                   if (code == ASHIFTRT)
>> -                   new_const = GEN_INT (GET_MODE_UNIT_BITSIZE (mode) - 1);
>> +                   new_const = gen_int_shift_amount
>> +                     (mode, GET_MODE_UNIT_BITSIZE (mode) - 1);
>>                   else if (!side_effects_p (XEXP (y, 0)))
>>                     return CONST0_RTX (mode);
>>                   else
>> Index: gcc/dse.c
>> ===================================================================
>> --- gcc/dse.c   2017-10-23 11:47:06.643477568 +0100
>> +++ gcc/dse.c   2017-10-23 11:47:11.273428262 +0100
>> @@ -1605,8 +1605,9 @@ find_shift_sequence (int access_size,
>>                                      store_mode, byte);
>>           if (ret && CONSTANT_P (ret))
>>             {
>> +             rtx shift_rtx = gen_int_shift_amount (new_mode, shift);
>>               ret = simplify_const_binary_operation (LSHIFTRT, new_mode,
>> -                                                    ret, GEN_INT (shift));
>> +                                                    ret, shift_rtx);
>>               if (ret && CONSTANT_P (ret))
>>                 {
>>                   byte = subreg_lowpart_offset (read_mode, new_mode);
>> @@ -1642,7 +1643,8 @@ find_shift_sequence (int access_size,
>>          of one dsp where the cost of these two was not the same.  But
>>          this really is a rare case anyway.  */
>>        target = expand_binop (new_mode, lshr_optab, new_reg,
>> -                            GEN_INT (shift), new_reg, 1, OPTAB_DIRECT);
>> +                            gen_int_shift_amount (new_mode, shift),
>> +                            new_reg, 1, OPTAB_DIRECT);
>>
>>        shift_seq = get_insns ();
>>        end_sequence ();
>> Index: gcc/expmed.c
>> ===================================================================
>> --- gcc/expmed.c        2017-10-23 11:47:06.643477568 +0100
>> +++ gcc/expmed.c        2017-10-23 11:47:11.274393237 +0100
>> @@ -222,7 +222,8 @@ init_expmed_one_mode (struct init_expmed
>>           PUT_MODE (all->zext, wider_mode);
>>           PUT_MODE (all->wide_mult, wider_mode);
>>           PUT_MODE (all->wide_lshr, wider_mode);
>> -         XEXP (all->wide_lshr, 1) = GEN_INT (mode_bitsize);
>> +         XEXP (all->wide_lshr, 1)
>> +           = gen_int_shift_amount (wider_mode, mode_bitsize);
>>
>>           set_mul_widen_cost (speed, wider_mode,
>>                               set_src_cost (all->wide_mult, wider_mode, 
>> speed));
>> @@ -908,12 +909,14 @@ store_bit_field_1 (rtx str_rtx, unsigned
>>              to make sure that for big-endian machines the higher order
>>              bits are used.  */
>>           if (new_bitsize < BITS_PER_WORD && BYTES_BIG_ENDIAN && !backwards)
>> -           value_word = simplify_expand_binop (word_mode, lshr_optab,
>> -                                               value_word,
>> -                                               GEN_INT (BITS_PER_WORD
>> -                                                        - new_bitsize),
>> -                                               NULL_RTX, true,
>> -                                               OPTAB_LIB_WIDEN);
>> +           {
>> +             int shift = BITS_PER_WORD - new_bitsize;
>> +             rtx shift_rtx = gen_int_shift_amount (word_mode, shift);
>> +             value_word = simplify_expand_binop (word_mode, lshr_optab,
>> +                                                 value_word, shift_rtx,
>> +                                                 NULL_RTX, true,
>> +                                                 OPTAB_LIB_WIDEN);
>> +           }
>>
>>           if (!store_bit_field_1 (op0, new_bitsize,
>>                                   bitnum + bit_offset,
>> @@ -2366,8 +2369,9 @@ expand_shift_1 (enum tree_code code, mac
>>        if (CONST_INT_P (op1)
>>           && ((unsigned HOST_WIDE_INT) INTVAL (op1) >=
>>               (unsigned HOST_WIDE_INT) GET_MODE_BITSIZE (scalar_mode)))
>> -       op1 = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (op1)
>> -                      % GET_MODE_BITSIZE (scalar_mode));
>> +       op1 = gen_int_shift_amount (mode,
>> +                                   (unsigned HOST_WIDE_INT) INTVAL (op1)
>> +                                   % GET_MODE_BITSIZE (scalar_mode));
>>        else if (GET_CODE (op1) == SUBREG
>>                && subreg_lowpart_p (op1)
>>                && SCALAR_INT_MODE_P (GET_MODE (SUBREG_REG (op1)))
>> @@ -2384,7 +2388,8 @@ expand_shift_1 (enum tree_code code, mac
>>        && IN_RANGE (INTVAL (op1), GET_MODE_BITSIZE (scalar_mode) / 2 + left,
>>                    GET_MODE_BITSIZE (scalar_mode) - 1))
>>      {
>> -      op1 = GEN_INT (GET_MODE_BITSIZE (scalar_mode) - INTVAL (op1));
>> +      op1 = gen_int_shift_amount (mode, (GET_MODE_BITSIZE (scalar_mode)
>> +                                        - INTVAL (op1)));
>>        left = !left;
>>        code = left ? LROTATE_EXPR : RROTATE_EXPR;
>>      }
>> @@ -2464,8 +2469,8 @@ expand_shift_1 (enum tree_code code, mac
>>               if (op1 == const0_rtx)
>>                 return shifted;
>>               else if (CONST_INT_P (op1))
>> -               other_amount = GEN_INT (GET_MODE_BITSIZE (scalar_mode)
>> -                                       - INTVAL (op1));
>> +               other_amount = gen_int_shift_amount
>> +                 (mode, GET_MODE_BITSIZE (scalar_mode) - INTVAL (op1));
>>               else
>>                 {
>>                   other_amount
>> @@ -2538,8 +2543,9 @@ expand_shift_1 (enum tree_code code, mac
>>  expand_shift (enum tree_code code, machine_mode mode, rtx shifted,
>>               int amount, rtx target, int unsignedp)
>>  {
>> -  return expand_shift_1 (code, mode,
>> -                        shifted, GEN_INT (amount), target, unsignedp);
>> +  return expand_shift_1 (code, mode, shifted,
>> +                        gen_int_shift_amount (mode, amount),
>> +                        target, unsignedp);
>>  }
>>
>>  /* Likewise, but return 0 if that cannot be done.  */
>> @@ -3855,7 +3861,7 @@ expand_smod_pow2 (scalar_int_mode mode,
>>         {
>>           HOST_WIDE_INT masklow = (HOST_WIDE_INT_1 << logd) - 1;
>>           signmask = force_reg (mode, signmask);
>> -         shift = GEN_INT (GET_MODE_BITSIZE (mode) - logd);
>> +         shift = gen_int_shift_amount (mode, GET_MODE_BITSIZE (mode) - 
>> logd);
>>
>>           /* Use the rtx_cost of a LSHIFTRT instruction to determine
>>              which instruction sequence to use.  If logical right shifts
>> Index: gcc/lower-subreg.c
>> ===================================================================
>> --- gcc/lower-subreg.c  2017-10-23 11:47:06.643477568 +0100
>> +++ gcc/lower-subreg.c  2017-10-23 11:47:11.274393237 +0100
>> @@ -129,7 +129,7 @@ shift_cost (bool speed_p, struct cost_rt
>>    PUT_CODE (rtxes->shift, code);
>>    PUT_MODE (rtxes->shift, mode);
>>    PUT_MODE (rtxes->source, mode);
>> -  XEXP (rtxes->shift, 1) = GEN_INT (op1);
>> +  XEXP (rtxes->shift, 1) = gen_int_shift_amount (mode, op1);
>>    return set_src_cost (rtxes->shift, mode, speed_p);
>>  }
>>
>> Index: gcc/simplify-rtx.c
>> ===================================================================
>> --- gcc/simplify-rtx.c  2017-10-23 11:47:06.643477568 +0100
>> +++ gcc/simplify-rtx.c  2017-10-23 11:47:11.277288162 +0100
>> @@ -1165,7 +1165,8 @@ simplify_unary_operation_1 (enum rtx_cod
>>           if (STORE_FLAG_VALUE == 1)
>>             {
>>               temp = simplify_gen_binary (ASHIFTRT, inner, XEXP (op, 0),
>> -                                         GEN_INT (isize - 1));
>> +                                         gen_int_shift_amount (inner,
>> +                                                               isize - 1));
>>               if (int_mode == inner)
>>                 return temp;
>>               if (GET_MODE_PRECISION (int_mode) > isize)
>> @@ -1175,7 +1176,8 @@ simplify_unary_operation_1 (enum rtx_cod
>>           else if (STORE_FLAG_VALUE == -1)
>>             {
>>               temp = simplify_gen_binary (LSHIFTRT, inner, XEXP (op, 0),
>> -                                         GEN_INT (isize - 1));
>> +                                         gen_int_shift_amount (inner,
>> +                                                               isize - 1));
>>               if (int_mode == inner)
>>                 return temp;
>>               if (GET_MODE_PRECISION (int_mode) > isize)
>> @@ -2679,7 +2681,8 @@ simplify_binary_operation_1 (enum rtx_co
>>         {
>>           val = wi::exact_log2 (rtx_mode_t (trueop1, mode));
>>           if (val >= 0)
>> -           return simplify_gen_binary (ASHIFT, mode, op0, GEN_INT (val));
>> +           return simplify_gen_binary (ASHIFT, mode, op0,
>> +                                       gen_int_shift_amount (mode, val));
>>         }
>>
>>        /* x*2 is x+x and x*(-1) is -x */
>> @@ -3303,7 +3306,8 @@ simplify_binary_operation_1 (enum rtx_co
>>        /* Convert divide by power of two into shift.  */
>>        if (CONST_INT_P (trueop1)
>>           && (val = exact_log2 (UINTVAL (trueop1))) > 0)
>> -       return simplify_gen_binary (LSHIFTRT, mode, op0, GEN_INT (val));
>> +       return simplify_gen_binary (LSHIFTRT, mode, op0,
>> +                                   gen_int_shift_amount (mode, val));
>>        break;
>>
>>      case DIV:
>> @@ -3423,10 +3427,12 @@ simplify_binary_operation_1 (enum rtx_co
>>           && IN_RANGE (INTVAL (trueop1),
>>                        GET_MODE_UNIT_PRECISION (mode) / 2 + (code == ROTATE),
>>                        GET_MODE_UNIT_PRECISION (mode) - 1))
>> -       return simplify_gen_binary (code == ROTATE ? ROTATERT : ROTATE,
>> -                                   mode, op0,
>> -                                   GEN_INT (GET_MODE_UNIT_PRECISION (mode)
>> -                                            - INTVAL (trueop1)));
>> +       {
>> +         int new_amount = GET_MODE_UNIT_PRECISION (mode) - INTVAL (trueop1);
>> +         rtx new_amount_rtx = gen_int_shift_amount (mode, new_amount);
>> +         return simplify_gen_binary (code == ROTATE ? ROTATERT : ROTATE,
>> +                                     mode, op0, new_amount_rtx);
>> +       }
>>  #endif
>>        /* FALLTHRU */
>>      case ASHIFTRT:
>> @@ -3466,8 +3472,8 @@ simplify_binary_operation_1 (enum rtx_co
>>               == GET_MODE_BITSIZE (inner_mode) - GET_MODE_BITSIZE (int_mode))
>>           && subreg_lowpart_p (op0))
>>         {
>> -         rtx tmp = GEN_INT (INTVAL (XEXP (SUBREG_REG (op0), 1))
>> -                            + INTVAL (op1));
>> +         rtx tmp = gen_int_shift_amount
>> +           (inner_mode, INTVAL (XEXP (SUBREG_REG (op0), 1)) + INTVAL (op1));
>>           tmp = simplify_gen_binary (code, inner_mode,
>>                                      XEXP (SUBREG_REG (op0), 0),
>>                                      tmp);
>> @@ -3478,7 +3484,8 @@ simplify_binary_operation_1 (enum rtx_co
>>         {
>>           val = INTVAL (op1) & (GET_MODE_UNIT_PRECISION (mode) - 1);
>>           if (val != INTVAL (op1))
>> -           return simplify_gen_binary (code, mode, op0, GEN_INT (val));
>> +           return simplify_gen_binary (code, mode, op0,
>> +                                       gen_int_shift_amount (mode, val));
>>         }
>>        break;
>>
>> Index: gcc/combine.c
>> ===================================================================
>> --- gcc/combine.c       2017-10-23 11:47:06.643477568 +0100
>> +++ gcc/combine.c       2017-10-23 11:47:11.272463287 +0100
>> @@ -3773,8 +3773,9 @@ try_combine (rtx_insn *i3, rtx_insn *i2,
>>               && INTVAL (XEXP (*split, 1)) > 0
>>               && (i = exact_log2 (UINTVAL (XEXP (*split, 1)))) >= 0)
>>             {
>> +             rtx i_rtx = gen_int_shift_amount (split_mode, i);
>>               SUBST (*split, gen_rtx_ASHIFT (split_mode,
>> -                                            XEXP (*split, 0), GEN_INT (i)));
>> +                                            XEXP (*split, 0), i_rtx));
>>               /* Update split_code because we may not have a multiply
>>                  anymore.  */
>>               split_code = GET_CODE (*split);
>> @@ -3788,8 +3789,10 @@ try_combine (rtx_insn *i3, rtx_insn *i2,
>>               && (i = exact_log2 (UINTVAL (XEXP (XEXP (*split, 0), 1)))) >= 
>> 0)
>>             {
>>               rtx nsplit = XEXP (*split, 0);
>> +             rtx i_rtx = gen_int_shift_amount (GET_MODE (nsplit), i);
>>               SUBST (XEXP (*split, 0), gen_rtx_ASHIFT (GET_MODE (nsplit),
>> -                                            XEXP (nsplit, 0), GEN_INT (i)));
>> +                                                      XEXP (nsplit, 0),
>> +                                                      i_rtx));
>>               /* Update split_code because we may not have a multiply
>>                  anymore.  */
>>               split_code = GET_CODE (*split);
>> @@ -5057,12 +5060,12 @@ find_split_point (rtx *loc, rtx_insn *in
>>                                       GET_MODE (XEXP (SET_SRC (x), 0))))))
>>             {
>>               machine_mode mode = GET_MODE (XEXP (SET_SRC (x), 0));
>> -
>> +             rtx pos_rtx = gen_int_shift_amount (mode, pos);
>>               SUBST (SET_SRC (x),
>>                      gen_rtx_NEG (mode,
>>                                   gen_rtx_LSHIFTRT (mode,
>>                                                     XEXP (SET_SRC (x), 0),
>> -                                                   GEN_INT (pos))));
>> +                                                   pos_rtx)));
>>
>>               split = find_split_point (&SET_SRC (x), insn, true);
>>               if (split && split != &SET_SRC (x))
>> @@ -5120,11 +5123,11 @@ find_split_point (rtx *loc, rtx_insn *in
>>             {
>>               unsigned HOST_WIDE_INT mask
>>                 = (HOST_WIDE_INT_1U << len) - 1;
>> +             rtx pos_rtx = gen_int_shift_amount (mode, pos);
>>               SUBST (SET_SRC (x),
>>                      gen_rtx_AND (mode,
>>                                   gen_rtx_LSHIFTRT
>> -                                 (mode, gen_lowpart (mode, inner),
>> -                                  GEN_INT (pos)),
>> +                                 (mode, gen_lowpart (mode, inner), pos_rtx),
>>                                   gen_int_mode (mask, mode)));
>>
>>               split = find_split_point (&SET_SRC (x), insn, true);
>> @@ -5133,14 +5136,15 @@ find_split_point (rtx *loc, rtx_insn *in
>>             }
>>           else
>>             {
>> +             int left_bits = GET_MODE_PRECISION (mode) - len - pos;
>> +             int right_bits = GET_MODE_PRECISION (mode) - len;
>>               SUBST (SET_SRC (x),
>>                      gen_rtx_fmt_ee
>>                      (unsignedp ? LSHIFTRT : ASHIFTRT, mode,
>>                       gen_rtx_ASHIFT (mode,
>>                                       gen_lowpart (mode, inner),
>> -                                     GEN_INT (GET_MODE_PRECISION (mode)
>> -                                              - len - pos)),
>> -                     GEN_INT (GET_MODE_PRECISION (mode) - len)));
>> +                                     gen_int_shift_amount (mode, 
>> left_bits)),
>> +                     gen_int_shift_amount (mode, right_bits)));
>>
>>               split = find_split_point (&SET_SRC (x), insn, true);
>>               if (split && split != &SET_SRC (x))
>> @@ -8915,10 +8919,11 @@ force_int_to_mode (rtx x, scalar_int_mod
>>           /* Must be more sign bit copies than the mask needs.  */
>>           && ((int) num_sign_bit_copies (XEXP (x, 0), GET_MODE (XEXP (x, 0)))
>>               >= exact_log2 (mask + 1)))
>> -       x = simplify_gen_binary (LSHIFTRT, xmode, XEXP (x, 0),
>> -                                GEN_INT (GET_MODE_PRECISION (xmode)
>> -                                         - exact_log2 (mask + 1)));
>> -
>> +       {
>> +         int nbits = GET_MODE_PRECISION (xmode) - exact_log2 (mask + 1);
>> +         x = simplify_gen_binary (LSHIFTRT, xmode, XEXP (x, 0),
>> +                                  gen_int_shift_amount (xmode, nbits));
>> +       }
>>        goto shiftrt;
>>
>>      case ASHIFTRT:
>> @@ -10415,7 +10420,7 @@ simplify_shift_const_1 (enum rtx_code co
>>  {
>>    enum rtx_code orig_code = code;
>>    rtx orig_varop = varop;
>> -  int count;
>> +  int count, log2;
>>    machine_mode mode = result_mode;
>>    machine_mode shift_mode;
>>    scalar_int_mode tmode, inner_mode, int_mode, int_varop_mode, 
>> int_result_mode;
>> @@ -10618,13 +10623,11 @@ simplify_shift_const_1 (enum rtx_code co
>>              is cheaper.  But it is still better on those machines to
>>              merge two shifts into one.  */
>>           if (CONST_INT_P (XEXP (varop, 1))
>> -             && exact_log2 (UINTVAL (XEXP (varop, 1))) >= 0)
>> +             && (log2 = exact_log2 (UINTVAL (XEXP (varop, 1)))) >= 0)
>>             {
>> -             varop
>> -               = simplify_gen_binary (ASHIFT, GET_MODE (varop),
>> -                                      XEXP (varop, 0),
>> -                                      GEN_INT (exact_log2 (
>> -                                               UINTVAL (XEXP (varop, 1)))));
>> +             rtx log2_rtx = gen_int_shift_amount (GET_MODE (varop), log2);
>> +             varop = simplify_gen_binary (ASHIFT, GET_MODE (varop),
>> +                                          XEXP (varop, 0), log2_rtx);
>>               continue;
>>             }
>>           break;
>> @@ -10632,13 +10635,11 @@ simplify_shift_const_1 (enum rtx_code co
>>         case UDIV:
>>           /* Similar, for when divides are cheaper.  */
>>           if (CONST_INT_P (XEXP (varop, 1))
>> -             && exact_log2 (UINTVAL (XEXP (varop, 1))) >= 0)
>> +             && (log2 = exact_log2 (UINTVAL (XEXP (varop, 1)))) >= 0)
>>             {
>> -             varop
>> -               = simplify_gen_binary (LSHIFTRT, GET_MODE (varop),
>> -                                      XEXP (varop, 0),
>> -                                      GEN_INT (exact_log2 (
>> -                                               UINTVAL (XEXP (varop, 1)))));
>> +             rtx log2_rtx = gen_int_shift_amount (GET_MODE (varop), log2);
>> +             varop = simplify_gen_binary (LSHIFTRT, GET_MODE (varop),
>> +                                          XEXP (varop, 0), log2_rtx);
>>               continue;
>>             }
>>           break;
>> @@ -10773,10 +10774,10 @@ simplify_shift_const_1 (enum rtx_code co
>>
>>               mask_rtx = gen_int_mode (nonzero_bits (varop, int_varop_mode),
>>                                        int_result_mode);
>> -
>> +             rtx count_rtx = gen_int_shift_amount (int_result_mode, count);
>>               mask_rtx
>>                 = simplify_const_binary_operation (code, int_result_mode,
>> -                                                  mask_rtx, GEN_INT 
>> (count));
>> +                                                  mask_rtx, count_rtx);
>>
>>               /* Give up if we can't compute an outer operation to use.  */
>>               if (mask_rtx == 0
>> @@ -10832,9 +10833,10 @@ simplify_shift_const_1 (enum rtx_code co
>>               if (code == ASHIFTRT && int_mode != int_result_mode)
>>                 break;
>>
>> +             rtx count_rtx = gen_int_shift_amount (int_result_mode, count);
>>               rtx new_rtx = simplify_const_binary_operation (code, int_mode,
>>                                                              XEXP (varop, 0),
>> -                                                            GEN_INT 
>> (count));
>> +                                                            count_rtx);
>>               varop = gen_rtx_fmt_ee (code, int_mode, new_rtx, XEXP (varop, 
>> 1));
>>               count = 0;
>>               continue;
>> @@ -10900,7 +10902,7 @@ simplify_shift_const_1 (enum rtx_code co
>>               && (new_rtx = simplify_const_binary_operation
>>                   (code, int_result_mode,
>>                    gen_int_mode (INTVAL (XEXP (varop, 1)), int_result_mode),
>> -                  GEN_INT (count))) != 0
>> +                  gen_int_shift_amount (int_result_mode, count))) != 0
>>               && CONST_INT_P (new_rtx)
>>               && merge_outer_ops (&outer_op, &outer_const, GET_CODE (varop),
>>                                   INTVAL (new_rtx), int_result_mode,
>> @@ -11043,7 +11045,7 @@ simplify_shift_const_1 (enum rtx_code co
>>               && (new_rtx = simplify_const_binary_operation
>>                   (ASHIFT, int_result_mode,
>>                    gen_int_mode (INTVAL (XEXP (varop, 1)), int_result_mode),
>> -                  GEN_INT (count))) != 0
>> +                  gen_int_shift_amount (int_result_mode, count))) != 0
>>               && CONST_INT_P (new_rtx)
>>               && merge_outer_ops (&outer_op, &outer_const, PLUS,
>>                                   INTVAL (new_rtx), int_result_mode,
>> @@ -11064,7 +11066,7 @@ simplify_shift_const_1 (enum rtx_code co
>>               && (new_rtx = simplify_const_binary_operation
>>                   (code, int_result_mode,
>>                    gen_int_mode (INTVAL (XEXP (varop, 1)), int_result_mode),
>> -                  GEN_INT (count))) != 0
>> +                  gen_int_shift_amount (int_result_mode, count))) != 0
>>               && CONST_INT_P (new_rtx)
>>               && merge_outer_ops (&outer_op, &outer_const, XOR,
>>                                   INTVAL (new_rtx), int_result_mode,
>> @@ -11119,12 +11121,12 @@ simplify_shift_const_1 (enum rtx_code co
>>                       - GET_MODE_UNIT_PRECISION (GET_MODE (varop)))))
>>             {
>>               rtx varop_inner = XEXP (varop, 0);
>> -
>> -             varop_inner
>> -               = gen_rtx_LSHIFTRT (GET_MODE (varop_inner),
>> -                                   XEXP (varop_inner, 0),
>> -                                   GEN_INT
>> -                                   (count + INTVAL (XEXP (varop_inner, 
>> 1))));
>> +             int new_count = count + INTVAL (XEXP (varop_inner, 1));
>> +             rtx new_count_rtx = gen_int_shift_amount (GET_MODE 
>> (varop_inner),
>> +                                                       new_count);
>> +             varop_inner = gen_rtx_LSHIFTRT (GET_MODE (varop_inner),
>> +                                             XEXP (varop_inner, 0),
>> +                                             new_count_rtx);
>>               varop = gen_rtx_TRUNCATE (GET_MODE (varop), varop_inner);
>>               count = 0;
>>               continue;
>> @@ -11176,7 +11178,8 @@ simplify_shift_const_1 (enum rtx_code co
>>      x = NULL_RTX;
>>
>>    if (x == NULL_RTX)
>> -    x = simplify_gen_binary (code, shift_mode, varop, GEN_INT (count));
>> +    x = simplify_gen_binary (code, shift_mode, varop,
>> +                            gen_int_shift_amount (shift_mode, count));
>>
>>    /* If we were doing an LSHIFTRT in a wider mode than it was originally,
>>       turn off all the bits that the shift would have turned off.  */
>> @@ -11238,7 +11241,8 @@ simplify_shift_const (rtx x, enum rtx_co
>>      return tem;
>>
>>    if (!x)
>> -    x = simplify_gen_binary (code, GET_MODE (varop), varop, GEN_INT 
>> (count));
>> +    x = simplify_gen_binary (code, GET_MODE (varop), varop,
>> +                            gen_int_shift_amount (GET_MODE (varop), count));
>>    if (GET_MODE (x) != result_mode)
>>      x = gen_lowpart (result_mode, x);
>>    return x;
>> @@ -11429,8 +11433,9 @@ change_zero_ext (rtx pat)
>>           if (BITS_BIG_ENDIAN)
>>             start = GET_MODE_PRECISION (inner_mode) - size - start;
>>
>> -         if (start)
>> -           x = gen_rtx_LSHIFTRT (inner_mode, XEXP (x, 0), GEN_INT (start));
>> +         if (start != 0)
>> +           x = gen_rtx_LSHIFTRT (inner_mode, XEXP (x, 0),
>> +                                 gen_int_shift_amount (inner_mode, start));
>>           else
>>             x = XEXP (x, 0);
>>           if (mode != inner_mode)
>> Index: gcc/optabs.c
>> ===================================================================
>> --- gcc/optabs.c        2017-10-23 11:47:06.643477568 +0100
>> +++ gcc/optabs.c        2017-10-23 11:47:11.276323187 +0100
>> @@ -431,8 +431,9 @@ expand_superword_shift (optab binoptab,
>>        if (binoptab != ashr_optab)
>>         emit_move_insn (outof_target, CONST0_RTX (word_mode));
>>        else
>> -       if (!force_expand_binop (word_mode, binoptab,
>> -                                outof_input, GEN_INT (BITS_PER_WORD - 1),
>> +       if (!force_expand_binop (word_mode, binoptab, outof_input,
>> +                                gen_int_shift_amount (word_mode,
>> +                                                      BITS_PER_WORD - 1),
>>                                  outof_target, unsignedp, methods))
>>           return false;
>>      }
>> @@ -789,7 +790,8 @@ expand_doubleword_mult (machine_mode mod
>>  {
>>    int low = (WORDS_BIG_ENDIAN ? 1 : 0);
>>    int high = (WORDS_BIG_ENDIAN ? 0 : 1);
>> -  rtx wordm1 = umulp ? NULL_RTX : GEN_INT (BITS_PER_WORD - 1);
>> +  rtx wordm1 = (umulp ? NULL_RTX
>> +               : gen_int_shift_amount (word_mode, BITS_PER_WORD - 1));
>>    rtx product, adjust, product_high, temp;
>>
>>    rtx op0_high = operand_subword_force (op0, high, mode);
>> @@ -1185,7 +1187,7 @@ expand_binop (machine_mode mode, optab b
>>        unsigned int bits = GET_MODE_PRECISION (int_mode);
>>
>>        if (CONST_INT_P (op1))
>> -        newop1 = GEN_INT (bits - INTVAL (op1));
>> +       newop1 = gen_int_shift_amount (int_mode, bits - INTVAL (op1));
>>        else if (targetm.shift_truncation_mask (int_mode) == bits - 1)
>>          newop1 = negate_rtx (GET_MODE (op1), op1);
>>        else
>> @@ -1399,11 +1401,11 @@ expand_binop (machine_mode mode, optab b
>>        shift_mask = targetm.shift_truncation_mask (word_mode);
>>        op1_mode = (GET_MODE (op1) != VOIDmode
>>                   ? as_a <scalar_int_mode> (GET_MODE (op1))
>> -                 : word_mode);
>> +                 : get_shift_amount_mode (word_mode));
>>
>>        /* Apply the truncation to constant shifts.  */
>>        if (double_shift_mask > 0 && CONST_INT_P (op1))
>> -       op1 = GEN_INT (INTVAL (op1) & double_shift_mask);
>> +       op1 = gen_int_mode (INTVAL (op1) & double_shift_mask, op1_mode);
>>
>>        if (op1 == CONST0_RTX (op1_mode))
>>         return op0;
>> @@ -1513,7 +1515,7 @@ expand_binop (machine_mode mode, optab b
>>        else
>>         {
>>           rtx into_temp1, into_temp2, outof_temp1, outof_temp2;
>> -         rtx first_shift_count, second_shift_count;
>> +         HOST_WIDE_INT first_shift_count, second_shift_count;
>>           optab reverse_unsigned_shift, unsigned_shift;
>>
>>           reverse_unsigned_shift = (left_shift ^ (shift_count < 
>> BITS_PER_WORD)
>> @@ -1524,20 +1526,24 @@ expand_binop (machine_mode mode, optab b
>>
>>           if (shift_count > BITS_PER_WORD)
>>             {
>> -             first_shift_count = GEN_INT (shift_count - BITS_PER_WORD);
>> -             second_shift_count = GEN_INT (2 * BITS_PER_WORD - shift_count);
>> +             first_shift_count = shift_count - BITS_PER_WORD;
>> +             second_shift_count = 2 * BITS_PER_WORD - shift_count;
>>             }
>>           else
>>             {
>> -             first_shift_count = GEN_INT (BITS_PER_WORD - shift_count);
>> -             second_shift_count = GEN_INT (shift_count);
>> +             first_shift_count = BITS_PER_WORD - shift_count;
>> +             second_shift_count = shift_count;
>>             }
>> +         rtx first_shift_count_rtx
>> +           = gen_int_shift_amount (word_mode, first_shift_count);
>> +         rtx second_shift_count_rtx
>> +           = gen_int_shift_amount (word_mode, second_shift_count);
>>
>>           into_temp1 = expand_binop (word_mode, unsigned_shift,
>> -                                    outof_input, first_shift_count,
>> +                                    outof_input, first_shift_count_rtx,
>>                                      NULL_RTX, unsignedp, next_methods);
>>           into_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
>> -                                    into_input, second_shift_count,
>> +                                    into_input, second_shift_count_rtx,
>>                                      NULL_RTX, unsignedp, next_methods);
>>
>>           if (into_temp1 != 0 && into_temp2 != 0)
>> @@ -1550,10 +1556,10 @@ expand_binop (machine_mode mode, optab b
>>             emit_move_insn (into_target, inter);
>>
>>           outof_temp1 = expand_binop (word_mode, unsigned_shift,
>> -                                     into_input, first_shift_count,
>> +                                     into_input, first_shift_count_rtx,
>>                                       NULL_RTX, unsignedp, next_methods);
>>           outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift,
>> -                                     outof_input, second_shift_count,
>> +                                     outof_input, second_shift_count_rtx,
>>                                       NULL_RTX, unsignedp, next_methods);
>>
>>           if (inter != 0 && outof_temp1 != 0 && outof_temp2 != 0)
>> @@ -2793,25 +2799,29 @@ expand_unop (machine_mode mode, optab un
>>
>>           if (optab_handler (rotl_optab, mode) != CODE_FOR_nothing)
>>             {
>> -             temp = expand_binop (mode, rotl_optab, op0, GEN_INT (8), 
>> target,
>> -                                  unsignedp, OPTAB_DIRECT);
>> +             temp = expand_binop (mode, rotl_optab, op0,
>> +                                  gen_int_shift_amount (mode, 8),
>> +                                  target, unsignedp, OPTAB_DIRECT);
>>               if (temp)
>>                 return temp;
>>              }
>>
>>           if (optab_handler (rotr_optab, mode) != CODE_FOR_nothing)
>>             {
>> -             temp = expand_binop (mode, rotr_optab, op0, GEN_INT (8), 
>> target,
>> -                                  unsignedp, OPTAB_DIRECT);
>> +             temp = expand_binop (mode, rotr_optab, op0,
>> +                                  gen_int_shift_amount (mode, 8),
>> +                                  target, unsignedp, OPTAB_DIRECT);
>>               if (temp)
>>                 return temp;
>>             }
>>
>>           last = get_last_insn ();
>>
>> -         temp1 = expand_binop (mode, ashl_optab, op0, GEN_INT (8), NULL_RTX,
>> +         temp1 = expand_binop (mode, ashl_optab, op0,
>> +                               gen_int_shift_amount (mode, 8), NULL_RTX,
>>                                 unsignedp, OPTAB_WIDEN);
>> -         temp2 = expand_binop (mode, lshr_optab, op0, GEN_INT (8), NULL_RTX,
>> +         temp2 = expand_binop (mode, lshr_optab, op0,
>> +                               gen_int_shift_amount (mode, 8), NULL_RTX,
>>                                 unsignedp, OPTAB_WIDEN);
>>           if (temp1 && temp2)
>>             {
>> @@ -5369,11 +5379,11 @@ vector_compare_rtx (machine_mode cmp_mod
>>  }
>>
>>  /* Checks if vec_perm mask SEL is a constant equivalent to a shift of the 
>> first
>> -   vec_perm operand, assuming the second operand is a constant vector of 
>> zeroes.
>> -   Return the shift distance in bits if so, or NULL_RTX if the vec_perm is 
>> not a
>> -   shift.  */
>> +   vec_perm operand (which has mode OP0_MODE), assuming the second
>> +   operand is a constant vector of zeroes.  Return the shift distance in
>> +   bits if so, or NULL_RTX if the vec_perm is not a shift.  */
>>  static rtx
>> -shift_amt_for_vec_perm_mask (rtx sel)
>> +shift_amt_for_vec_perm_mask (machine_mode op0_mode, rtx sel)
>>  {
>>    unsigned int i, first, nelt = GET_MODE_NUNITS (GET_MODE (sel));
>>    unsigned int bitsize = GET_MODE_UNIT_BITSIZE (GET_MODE (sel));
>> @@ -5393,7 +5403,7 @@ shift_amt_for_vec_perm_mask (rtx sel)
>>         return NULL_RTX;
>>      }
>>
>> -  return GEN_INT (first * bitsize);
>> +  return gen_int_shift_amount (op0_mode, first * bitsize);
>>  }
>>
>>  /* A subroutine of expand_vec_perm for expanding one vec_perm insn.  */
>> @@ -5473,7 +5483,7 @@ expand_vec_perm (machine_mode mode, rtx
>>           && (shift_code != CODE_FOR_nothing
>>               || shift_code_qi != CODE_FOR_nothing))
>>         {
>> -         shift_amt = shift_amt_for_vec_perm_mask (sel);
>> +         shift_amt = shift_amt_for_vec_perm_mask (mode, sel);
>>           if (shift_amt)
>>             {
>>               struct expand_operand ops[3];
>> @@ -5563,7 +5573,8 @@ expand_vec_perm (machine_mode mode, rtx
>>                                    NULL, 0, OPTAB_DIRECT);
>>        else
>>         sel = expand_simple_binop (selmode, ASHIFT, sel,
>> -                                  GEN_INT (exact_log2 (u)),
>> +                                  gen_int_shift_amount (selmode,
>> +                                                        exact_log2 (u)),
>>                                    NULL, 0, OPTAB_DIRECT);
>>        gcc_assert (sel != NULL);
>>

Reply via email to