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

            Bug ID: 90469
           Summary: -ftree-vrp optimizaion causes 'signed overflow' and
                    'unreachable code' assumptions without warning.
           Product: gcc
           Version: 8.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: prg.j.a.h at centrum dot cz
  Target Milestone: ---

Compiling with and without -ftree-vrp produces different code. Although the
code mixes signed and unsigned conversions and the code is disputable I think
that the compiler should at least issue warnings. e.g. "warning: assuming
signed overflow does not occur when assuming that X < (c - Y) is always false
[-Wstrict-overflow]" and "warning: expression is always true..."

The discussed code is in the conversion.c:
```
#include <stdbool.h>
#include <stdint.h>

bool convert(int32_t *ptr_data, int32_t offset_f);

bool convert(int32_t *ptr_data, int32_t offset_f)
{
  bool result = false;

  uint32_t data_uns = *((uint32_t*)ptr_data);

  if (offset_f >= 0)
  {
    // TODO
  }
  else
  {
    if (data_uns <= (uint32_t)(INT32_MAX - offset_f))
    {
      result = true;
      *ptr_data = (int32_t)data_uns + offset_f;
    }
  }

  return result;
}
```

"Unit" test:
```
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>

extern bool convert(int32_t *ptr_data, int32_t offset_f);

int main(void)
{
  int32_t data = -300;
  int32_t offset = -INT32_MAX;
  const int32_t expected_data = 2147483349;
  const bool expected_result = true;

  bool result = convert(&data, offset);

  printf("Data: %d ?= %d\n", data, expected_data);
  printf("Result: %s ?= %s\n", result ? "true" : "false", expected_result ?
"true" : "false");

  return 0;
}
```

The code is compiled with command:
- for X86 gcc 8.3.0:
gcc-8 -std=c99 -save-temps=obj -O3 -Wall -Werror -o conversion.c.obj -c
conversion.c
gcc-8 -std=c99 -O3 -o main main.c conversion.c.obj

- for ARM cortex-m7 gcc 8.2.1:
arm-none-eabi-gcc -std=c99 -mthumb -mcpu=cortex-m7 -save-temps=obj -O3 -Wall
-Werror -o conversion.c.obj -c conversion.c

Workaround:
- option 1: replace 'if (data_uns <= (uint32_t)(INT32_MAX - offset_f))' with
'if (data_uns <= ((uint32_t)INT32_MAX - (uint32_t)offset_f))'
- option 2: use -fno-tree-vrp
- it works on gcc 7.3.0 (x86) and gcc 7.3.1 (arm)

The dissassembly for x86:
```
--- bad-x86.s   2019-05-13 17:20:19.655385900 +0200
+++ good-x86.s  2019-05-13 17:20:58.491385900 +0200
@@ -6,23 +6,25 @@
 convert:
 .LFB0:
        .cfi_startproc
        xorl    %eax, %eax
        testl   %esi, %esi
        js      .L6
 .L1:
        ret
        .p2align 4,,10
        .p2align 3
 .L6:
-       movl    (%rdi), %edx
-       testl   %edx, %edx
-       js      .L1
-       addl    %edx, %esi
+       movl    $2147483647, %edx
+       movl    (%rdi), %ecx
+       subl    %esi, %edx
+       cmpl    %ecx, %edx
+       jb      .L1
+       addl    %ecx, %esi
        movl    $1, %eax
        movl    %esi, (%rdi)
        ret
        .cfi_endproc
 .LFE0:
        .size   convert, .-convert
        .ident  "GCC: (Ubuntu 8.3.0-6ubuntu1~18.04) 8.3.0"
        .section        .note.GNU-stack,"",@progbits
```

Disassembly for ARM:
```
--- bad-st.s    2019-05-13 17:17:40.345885900 +0200
+++ good-st.s   2019-05-13 17:18:31.964385900 +0200
@@ -22,21 +22,23 @@
 convert:
        @ args = 0, pretend = 0, frame = 0
        @ frame_needed = 0, uses_anonymous_args = 0
        @ link register save eliminated.
        cmp     r1, #0
        blt     .L6
 .L4:
        movs    r3, #0
        mov     r0, r3
        bx      lr
 .L6:
-       ldr     r3, [r0]
-       cmp     r3, #0
-       blt     .L4
-       add     r1, r1, r3
+       mvn     r3, #-2147483648
+       ldr     r2, [r0]
+       subs    r3, r3, r1
+       cmp     r3, r2
+       bcc     .L4
+       add     r1, r1, r2
        movs    r3, #1
        str     r1, [r0]
        mov     r0, r3
        bx      lr
        .size   convert, .-convert
        .ident  "GCC: (GNU Tools for Arm Embedded Processors 8-2018-q4-major)
8.2.1 20181213 (release) [gcc-8-branch revision 267074]"
```

Reply via email to