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)