On Mon, 21 Jan 2019, Jakub Jelinek wrote:

> Hi!
> 
> add_equal_note has special code to handle properly doubleword POPCOUNT and
> similar builtins, e.g. for POPCOUNT if we don't have DImode POPCOUNT, it can
> be expanded as 2 SImode POPCOUNTs added together, but for the REG_EQUAL note
> we want lowpart SImode SUBREG of DImode POPCOUNT.
> 
> Unfortunately, this doesn't really work if the operand is constant and we
> are unlucky enough that it hasn't been folded during GIMPLE optimizations
> - we still need to use DImode POPCOUNT and take subreg of it.
> 
> The following patch fixes it by padding the op0's mode to the function too
> and use it everywhere instead of GET_MODE (op0).  For op1 we don't really
> need that, that is for binary operations where both arguments have the same
> mode or we don't really care about the mode of the last operand (shifts).
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

Richard.

> 2019-01-21  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR target/88905
>       * optabs.c (add_equal_note): Add op0_mode argument, use it instead of
>       GET_MODE (op0).
>       (expand_binop_directly, expand_doubleword_clz,
>       expand_doubleword_popcount, expand_ctz, expand_ffs,
>       expand_unop_direct, maybe_emit_unop_insn): Adjust callers.
> 
>       * gcc.dg/pr88905.c: New test.
> 
> --- gcc/optabs.c.jj   2019-01-01 12:37:17.711965861 +0100
> +++ gcc/optabs.c      2019-01-21 13:56:18.263446049 +0100
> @@ -55,7 +55,7 @@ void debug_optab_libfuncs (void);
>  
>  /* Add a REG_EQUAL note to the last insn in INSNS.  TARGET is being set to
>     the result of operation CODE applied to OP0 (and OP1 if it is a binary
> -   operation).
> +   operation).  OP0_MODE is OP0's mode.
>  
>     If the last insn does not set TARGET, don't do anything, but return 1.
>  
> @@ -64,7 +64,8 @@ void debug_optab_libfuncs (void);
>     try again, ensuring that TARGET is not one of the operands.  */
>  
>  static int
> -add_equal_note (rtx_insn *insns, rtx target, enum rtx_code code, rtx op0, 
> rtx op1)
> +add_equal_note (rtx_insn *insns, rtx target, enum rtx_code code, rtx op0,
> +             rtx op1, machine_mode op0_mode)
>  {
>    rtx_insn *last_insn;
>    rtx set;
> @@ -136,16 +137,16 @@ add_equal_note (rtx_insn *insns, rtx tar
>        case POPCOUNT:
>        case PARITY:
>        case BSWAP:
> -     if (GET_MODE (op0) != VOIDmode && GET_MODE (target) != GET_MODE (op0))
> +     if (op0_mode != VOIDmode && GET_MODE (target) != op0_mode)
>         {
> -         note = gen_rtx_fmt_e (code, GET_MODE (op0), copy_rtx (op0));
> -         if (GET_MODE_UNIT_SIZE (GET_MODE (op0))
> +         note = gen_rtx_fmt_e (code, op0_mode, copy_rtx (op0));
> +         if (GET_MODE_UNIT_SIZE (op0_mode)
>               > GET_MODE_UNIT_SIZE (GET_MODE (target)))
>             note = simplify_gen_unary (TRUNCATE, GET_MODE (target),
> -                                      note, GET_MODE (op0));
> +                                      note, op0_mode);
>           else
>             note = simplify_gen_unary (ZERO_EXTEND, GET_MODE (target),
> -                                      note, GET_MODE (op0));
> +                                      note, op0_mode);
>           break;
>         }
>       /* FALLTHRU */
> @@ -1127,7 +1128,7 @@ expand_binop_directly (enum insn_code ic
>        if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
>         && ! add_equal_note (pat, ops[0].value,
>                              optab_to_code (binoptab),
> -                            ops[1].value, ops[2].value))
> +                            ops[1].value, ops[2].value, mode0))
>       {
>         delete_insns_since (last);
>         return expand_binop (mode, binoptab, op0, op1, NULL_RTX,
> @@ -2298,7 +2299,7 @@ expand_doubleword_clz (scalar_int_mode m
>    seq = get_insns ();
>    end_sequence ();
>  
> -  add_equal_note (seq, target, CLZ, xop0, 0);
> +  add_equal_note (seq, target, CLZ, xop0, NULL_RTX, mode);
>    emit_insn (seq);
>    return target;
>  
> @@ -2340,7 +2341,7 @@ expand_doubleword_popcount (scalar_int_m
>    seq = get_insns ();
>    end_sequence ();
>  
> -  add_equal_note (seq, t, POPCOUNT, op0, 0);
> +  add_equal_note (seq, t, POPCOUNT, op0, NULL_RTX, mode);
>    emit_insn (seq);
>    return t;
>  }
> @@ -2511,7 +2512,7 @@ expand_ctz (scalar_int_mode mode, rtx op
>    seq = get_insns ();
>    end_sequence ();
>  
> -  add_equal_note (seq, temp, CTZ, op0, 0);
> +  add_equal_note (seq, temp, CTZ, op0, NULL_RTX, mode);
>    emit_insn (seq);
>    return temp;
>  }
> @@ -2589,7 +2590,7 @@ expand_ffs (scalar_int_mode mode, rtx op
>    seq = get_insns ();
>    end_sequence ();
>  
> -  add_equal_note (seq, temp, FFS, op0, 0);
> +  add_equal_note (seq, temp, FFS, op0, NULL_RTX, mode);
>    emit_insn (seq);
>    return temp;
>  
> @@ -2736,7 +2737,7 @@ expand_unop_direct (machine_mode mode, o
>         if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
>             && ! add_equal_note (pat, ops[0].value,
>                                  optab_to_code (unoptab),
> -                                ops[1].value, NULL_RTX))
> +                                ops[1].value, NULL_RTX, mode))
>           {
>             delete_insns_since (last);
>             return expand_unop (mode, unoptab, op0, NULL_RTX, unsignedp);
> @@ -3588,7 +3589,8 @@ maybe_emit_unop_insn (enum insn_code ico
>  
>    if (INSN_P (pat) && NEXT_INSN (pat) != NULL_RTX
>        && code != UNKNOWN)
> -    add_equal_note (pat, ops[0].value, code, ops[1].value, NULL_RTX);
> +    add_equal_note (pat, ops[0].value, code, ops[1].value, NULL_RTX,
> +                 GET_MODE (op0));
>  
>    emit_insn (pat);
>  
> --- gcc/testsuite/gcc.dg/pr88905.c.jj 2019-01-21 14:19:17.279746531 +0100
> +++ gcc/testsuite/gcc.dg/pr88905.c    2019-01-21 14:18:56.264091537 +0100
> @@ -0,0 +1,21 @@
> +/* PR target/88905 */
> +/* { dg-do compile } */
> +/* { dg-options "-Og -fno-tree-ccp" } */
> +/* { dg-additional-options "-mabm" { target { i?86-*-* x86_64-*-* } } } */
> +
> +int a, b, c;
> +extern void baz (int);
> +
> +static inline int
> +bar (unsigned u)
> +{
> +  int i = __builtin_popcountll (-(unsigned long long) u);
> +  baz (i & c);
> +  return a + b + c;
> +}
> +
> +void
> +foo (void)
> +{
> +  bar (2376498292ULL);
> +}
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
21284 (AG Nuernberg)

Reply via email to