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

Marek Polacek <mpolacek at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |mpolacek at gcc dot gnu.org

--- Comment #3 from Marek Polacek <mpolacek at gcc dot gnu.org> ---
Re-adding richi's comment.  I'm going to try the following.

--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> ---
We emit

    int k = -2147483648;
  return x + ((sizetype) ((long unsigned int) k * 4) + 18446744065119617028);

and it seems we end up zero-extending k.  I believe that's because of the
(premature) optimization in pointer_int_sum:

  /* If what we are about to multiply by the size of the elements
     contains a constant term, apply distributive law
     and multiply that constant term separately.
     This helps produce common subexpressions.  */
  if ((TREE_CODE (intop) == PLUS_EXPR || TREE_CODE (intop) == MINUS_EXPR)
      && !TREE_CONSTANT (intop)
      && TREE_CONSTANT (TREE_OPERAND (intop, 1))
      && TREE_CONSTANT (size_exp)
      /* If the constant comes from pointer subtraction,
         skip this optimization--it would cause an error.  */
      && TREE_CODE (TREE_TYPE (TREE_OPERAND (intop, 0))) == INTEGER_TYPE
      /* If the constant is unsigned, and smaller than the pointer size,
         then we must skip this optimization.  This is because it could cause
         an overflow error if the constant is negative but INTOP is not.  */
      && (!TYPE_UNSIGNED (TREE_TYPE (intop))
          || (TYPE_PRECISION (TREE_TYPE (intop))
              == TYPE_PRECISION (TREE_TYPE (ptrop)))))
    {
      enum tree_code subcode = resultcode;
      tree int_type = TREE_TYPE (intop);
      if (TREE_CODE (intop) == MINUS_EXPR)
        subcode = (subcode == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR);
      /* Convert both subexpression types to the type of intop,
         because weird cases involving pointer arithmetic
         can result in a sum or difference with different type args.  */
      ptrop = build_binary_op (EXPR_LOCATION (TREE_OPERAND (intop, 1)),
                               subcode, ptrop,
                               convert (int_type, TREE_OPERAND (intop, 1)),
                               true);
      intop = convert (int_type, TREE_OPERAND (intop, 0));
    }


compilable testcase:

int * __attribute__((__noinline__, __noclone__))
foo(int x[])
{
  int k = (-__INT_MAX__ - 1);
  return x + (k - __INT_MAX__);
}

I suggest trying to remove the above...  (doing so fixes the testcase)

Reply via email to