On Tue, 16 Apr 2019, Jakub Jelinek wrote:

> On Tue, Apr 16, 2019 at 06:21:25PM +0200, Eric Botcazou wrote:
> > > The runtime check assures that at runtime, the upper 32 bits of pseudo 104
> > > must be always 0 (in this case, in some other case could be sign bit
> > > copies).
> > 
> > OK, as Richard pointed out, that's not sufficient if we allow...
> > 
> > > The question is if it would be valid say for forward propagation to first
> > > propagate (or combine) the pseudo 97 into the (subreg/s/v:SI (reg:DI 104)
> > > 0), then hoisting it before the jump_insn 16, have the subreg optimized
> > > away and miscompile later on.
> > 
> > ...this to happen.  So we could clear SUBREG_PROMOTED_VAR_P as soon as the 
> > SUBREG is rewritten, but this looks quite fragile.  The safest route is 
> > probably not to use SUBREG_PROMOTED_VAR_P in this conditional context.
> > 
> > > That means either that the hoisting pass is buggy, or that 
> > > SUBREG_PROMOTED_*
> > > is only safe at the function boundary (function arguments and return 
> > > value)
> > > and not elsewhere.
> > 
> > I think that Richard's characterization is correct:
> > 
> > "Note that likely SUBREG_PROMOTED_VAR_P wasn't designed to communicate
> > zero-extend info (can't you use a REG_EQUIV note somehow?) but it has
> > to be information that is valid everywhere in the function unless
> > data dependences force its motion (thus a conditional doesn't do)."
> > 
> > i.e. this also works for a local variable that is always accessed with the 
> > SUBREG_PROMOTED_VAR_P semantics.
> 
> Ok, here is a patch that just removes all of that SUBREG_PROMOTED_SET then,
> as even for the opN_small_p we can't actually guarantee that for the whole
> function, only for where the pseudo with the SSA_NAME for which we get the
> range appears.  On the bright side, the generated code at least for the
> particular testcase has somewhat different RA decisions, but isn't
> significantly worse.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK.

Richard.

> 2019-04-16  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR middle-end/90095
>       * internal-fn.c (expand_mul_overflow): Don't set SUBREG_PROMOTED_VAR_P
>       on lowpart SUBREGs.
> 
>       * gcc.dg/pr90095-1.c: New test.
>       * gcc.dg/pr90095-2.c: New test.
> 
> --- gcc/internal-fn.c.jj      2019-04-15 19:45:22.384444646 +0200
> +++ gcc/internal-fn.c 2019-04-16 15:18:56.614708804 +0200
> @@ -1753,22 +1753,9 @@ expand_mul_overflow (location_t loc, tre
>         /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
>            hmode to mode, the multiplication will never overflow.  We can
>            do just one hmode x hmode => mode widening multiplication.  */
> -       rtx lopart0s = lopart0, lopart1s = lopart1;
> -       if (GET_CODE (lopart0) == SUBREG)
> -         {
> -           lopart0s = shallow_copy_rtx (lopart0);
> -           SUBREG_PROMOTED_VAR_P (lopart0s) = 1;
> -           SUBREG_PROMOTED_SET (lopart0s, uns ? SRP_UNSIGNED : SRP_SIGNED);
> -         }
> -       if (GET_CODE (lopart1) == SUBREG)
> -         {
> -           lopart1s = shallow_copy_rtx (lopart1);
> -           SUBREG_PROMOTED_VAR_P (lopart1s) = 1;
> -           SUBREG_PROMOTED_SET (lopart1s, uns ? SRP_UNSIGNED : SRP_SIGNED);
> -         }
>         tree halfstype = build_nonstandard_integer_type (hprec, uns);
> -       ops.op0 = make_tree (halfstype, lopart0s);
> -       ops.op1 = make_tree (halfstype, lopart1s);
> +       ops.op0 = make_tree (halfstype, lopart0);
> +       ops.op1 = make_tree (halfstype, lopart1);
>         ops.code = WIDEN_MULT_EXPR;
>         ops.type = type;
>         rtx thisres
> --- gcc/testsuite/gcc.dg/pr90095-1.c.jj       2019-04-16 13:45:22.614772955 
> +0200
> +++ gcc/testsuite/gcc.dg/pr90095-1.c  2019-04-16 13:45:22.614772955 +0200
> @@ -0,0 +1,18 @@
> +/* PR middle-end/90095 */
> +/* { dg-do run } */
> +/* { dg-options "-Os -fno-tree-bit-ccp" } */
> +
> +unsigned long long a;
> +unsigned int b;
> +
> +int
> +main ()
> +{
> +  unsigned int c = 255, d = c |= b;
> +  if (__CHAR_BIT__ != 8 || __SIZEOF_INT__ != 4 || __SIZEOF_LONG_LONG__ != 8)
> +    return 0;
> +  d = __builtin_mul_overflow (-(unsigned long long) d, (unsigned char) - c, 
> &a);
> +  if (d != 0)
> +    __builtin_abort ();
> +  return 0;
> +}
> --- gcc/testsuite/gcc.dg/pr90095-2.c.jj       2019-04-16 15:20:14.728414325 
> +0200
> +++ gcc/testsuite/gcc.dg/pr90095-2.c  2019-04-16 15:20:29.597167928 +0200
> @@ -0,0 +1,5 @@
> +/* PR middle-end/90095 */
> +/* { dg-do run } */
> +/* { dg-options "-Os -fno-tree-bit-ccp -fno-split-wide-types" } */
> +
> +#include "pr90095-1.c"
> 
> 
>       Jakub
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Linux GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany;
GF: Felix Imendörffer, Mary Higgins, Sri Rasiah; HRB 21284 (AG Nürnberg)

Reply via email to