> On 20 Aug 2026, at 10:41, Richard Biener <[email protected]> wrote:
> 
> On Thu, Aug 20, 2026 at 7:33 AM <[email protected]> wrote:
>> 
>> From: Kyrylo Tkachov <[email protected]>
>> 
>> A VECTOR_CST can encode a stepped series without storing every lane.  The
>> fold-const negate_expr_p checks only the encoded elements.  It can therefore
>> approve a signed vector whose implicit final lane is INT_MIN.
>> 
>>  typedef int v4si __attribute__ ((vector_size (16)));
>> 
>>  const v4si c = { 2147483645, 2147483646, 2147483647,
>>                   (-2147483647 - 1) };
>> 
>>  v4si f (v4si x) { return (-x) - c; }
>>  v4si g (v4si x) { return -(x + c); }
>>  v4si h () { return -c; }
>> 
>> The old predicate lets f and g negate c.  It represents -INT_MIN as INT_MIN,
>> which adds a false signed overflow for defined inputs.  fold_negate_expr_1
>> can also negate the encoded elements of c directly.  This removes the
>> required overflow diagnostic from h when overflow is instrumented.
>> 
>> aarch64 -O2 -fsanitize=signed-integer-overflow
>>         -fsanitize-trap=signed-integer-overflow before:
>> 
>>  h:
>>          adrp    x0, .LANCHOR0
>>          ldr     q0, [x0, #:lo12:.LANCHOR0]
>>          ret
>> 
>> After:
>> 
>>  h:
>>          brk     #1000
>> 
>> Reject a non-wrapping integral stepped vector in negate_expr_p.  Also keep a
>> direct stepped integral negation when sanitizer instrumentation makes 
>> overflow
>> observable.  Guard the wrapping query with the integral lane type so
>> fixed-point vectors continue to use the element checks.
>> 
>> The test checks that f and g do not report overflow for defined inputs.  It
>> also checks that h reports its real INT_MIN negation.
>> 
>> Bootstrapped and tested on aarch64-none-linux-gnu and x86_64-pc-linux-gnu.
>> Ok for trunk?
>> Thanks,
>> Kyrill
>> 
>> gcc/ChangeLog:
>> 
>>        * fold-const.cc (negate_expr_p): Reject non-wrapping stepped vector
>>        constants.
>>        (fold_negate_expr_1): Preserve sanitized stepped integral negations.
>> 
>> gcc/testsuite/ChangeLog:
>> 
>>        * g++.dg/ubsan/fold-negate-vector-1.C: New test.
>> 
>> Signed-off-by: Kyrylo Tkachov <[email protected]>
>> ---
>> gcc/fold-const.cc                             | 13 +++++-
>> .../g++.dg/ubsan/fold-negate-vector-1.C       | 46 +++++++++++++++++++
>> 2 files changed, 57 insertions(+), 2 deletions(-)
>> create mode 100644 gcc/testsuite/g++.dg/ubsan/fold-negate-vector-1.C
>> 
>> diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
>> index 420e3185a2a..b23bbb6f9b3 100644
>> --- a/gcc/fold-const.cc
>> +++ b/gcc/fold-const.cc
>> @@ -406,10 +406,15 @@ negate_expr_p (tree t)
>> 
>>     case VECTOR_CST:
>>       {
>> -       if (FLOAT_TYPE_P (TREE_TYPE (type)) || TYPE_OVERFLOW_WRAPS (type))
>> +       tree etype = TREE_TYPE (type);
>> +       if (FLOAT_TYPE_P (etype)
>> +           || (INTEGRAL_TYPE_P (etype) && TYPE_OVERFLOW_WRAPS (type)))
>>          return true;
>> 
>> -       /* Steps don't prevent negation.  */
>> +       /* An implicit element of a stepped vector can be the minimum
>> +          value.  */
>> +       if (VECTOR_CST_STEPPED_P (t))
> 
> why unconditional here
> 
>> +         return false;
>>        unsigned int count = vector_cst_encoded_nelts (t);
>>        for (unsigned int i = 0; i < count; ++i)
>>          if (!negate_expr_p (VECTOR_CST_ENCODED_ELT (t, i)))
>> @@ -566,6 +571,10 @@ fold_negate_expr_1 (location_t loc, tree t)
>> 
>>     case VECTOR_CST:
>>       {
>> +       if (VECTOR_CST_STEPPED_P (t)
>> +           && TYPE_OVERFLOW_SANITIZED (TREE_TYPE (type)))
> 
> but conditional on TYPE_OVERFLOW_SANITIZED here?

I’ve added a comment in the commit message for the respin that I’ve just sent 
out, now patch 2/4.

Thanks,
Kyrill


> 
>> +         return NULL_TREE;
>> +
>>        tree_vector_builder elts;
>>        elts.new_unary_operation (type, t, true);
>>        unsigned int count = elts.encoded_nelts ();
>> diff --git a/gcc/testsuite/g++.dg/ubsan/fold-negate-vector-1.C 
>> b/gcc/testsuite/g++.dg/ubsan/fold-negate-vector-1.C
>> new file mode 100644
>> index 00000000000..cda0fd9817f
>> --- /dev/null
>> +++ b/gcc/testsuite/g++.dg/ubsan/fold-negate-vector-1.C
>> @@ -0,0 +1,46 @@
>> +// { dg-do run { target int32 } }
>> +// { dg-options "-O2 -Wno-psabi -fsanitize=signed-integer-overflow" }
>> +
>> +#define INT_MAX __INT_MAX__
>> +#define INT_MIN (-INT_MAX - 1)
>> +
>> +typedef int v4si __attribute__ ((vector_size (16)));
>> +
>> +const v4si c = { INT_MAX - 2, INT_MAX - 1, INT_MAX, INT_MIN };
>> +
>> +v4si __attribute__ ((noipa))
>> +f (v4si x)
>> +{
>> +  return (-x) - c;
>> +}
>> +
>> +v4si __attribute__ ((noipa))
>> +g (v4si x)
>> +{
>> +  return -(x + c);
>> +}
>> +
>> +v4si __attribute__ ((noipa))
>> +h ()
>> +{
>> +  return -c;
>> +}
>> +
>> +int
>> +main ()
>> +{
>> +  v4si x = { 0, 0, 0, 1 };
>> +  v4si y = f (x);
>> +  if (y[3] != INT_MAX)
>> +    __builtin_abort ();
>> +
>> +  y = g (x);
>> +  if (y[3] != INT_MAX)
>> +    __builtin_abort ();
>> +
>> +  volatile v4si z = h ();
>> +  if (z[3] != INT_MIN)
>> +    __builtin_abort ();
>> +}
>> +
>> +// { dg-output "negation of -2147483648 cannot be represented in type 
>> 'int'; cast to an unsigned type to negate this value to itself" }
>> --
>> 2.50.1 (Apple Git-155)


Reply via email to