diff options
Diffstat (limited to 'gcc/testsuite/gcc.dg/builtin-arith-overflow-1.c')
-rw-r--r-- | gcc/testsuite/gcc.dg/builtin-arith-overflow-1.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.dg/builtin-arith-overflow-1.c b/gcc/testsuite/gcc.dg/builtin-arith-overflow-1.c new file mode 100644 index 0000000..b9c1517 --- /dev/null +++ b/gcc/testsuite/gcc.dg/builtin-arith-overflow-1.c @@ -0,0 +1,132 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -fdump-tree-optimized -g" } */ + +/* SUB_OVERFLOW should be folded into unsigned subtraction, + because ovf is never used. */ +__attribute__((noinline, noclone)) int +fn1 (int x, unsigned int y) +{ + int res; + int ovf = __builtin_sub_overflow (x, y, &res); + int res2 = res; + int res3 = res2 - 2; + (void) ovf; + return res; +} + +/* MUL_OVERFLOW should be folded into unsigned multiplication, + because ovf is never used. */ +__attribute__((noinline, noclone)) int +fn2 (char x, long int y) +{ + short int res; + int ovf = __builtin_mul_overflow (x, y, &res); + int res2 = res; + int res3 = res2 - 2; + (void) ovf; + return res; +} + +#if __SIZEOF_INT__ > __SIZEOF_SHORT__ && __SIZEOF_INT__ > 1 +/* ADD_OVERFLOW should be folded into unsigned addition, + because it never overflows. */ +__attribute__((noinline, noclone)) int +fn3 (char x, unsigned short y, int *ovf) +{ + int res; + *ovf = __builtin_add_overflow (x, y, &res); + return res; +} +#endif + +/* MUL_OVERFLOW should be folded into unsigned multiplication, + because it never overflows. */ +__attribute__((noinline, noclone)) long int +fn4 (long int x, long int y, int *ovf) +{ + long int res; + x &= 65535; + y = (y & 65535) - 32768; + *ovf = __builtin_mul_overflow (x, y, &res); + return res; +} + +#if __SIZEOF_INT__ > 1 +/* MUL_OVERFLOW should be folded into unsigned multiplication, + because it always overflows. */ +__attribute__((noinline, noclone)) signed char +fn5 (long int x, long int y, int *ovf) +{ + signed char res; + x = (x & 63) + (__SCHAR_MAX__ / 4); + y = (y & 3) + 5; + *ovf = __builtin_mul_overflow (x, y, &res); + return res; +} +#endif + +/* ADD_OVERFLOW should be folded into unsigned additrion, + because it never overflows. */ +__attribute__((noinline, noclone)) unsigned char +fn6 (unsigned char x, unsigned char y, int *ovf) +{ + unsigned char res; + x = (x & 63) + ((unsigned char) ~0 - 66); + y = (y & 3); + *ovf = __builtin_add_overflow (x, y, &res); + return res; +} + +/* ADD_OVERFLOW should be folded into unsigned additrion, + because it always overflows. */ +__attribute__((noinline, noclone)) unsigned char +fn7 (unsigned char x, unsigned char y, int *ovf) +{ + unsigned char res; + x = (x & 15) + ((unsigned char) ~0 - 15); + y = (y & 3) + 16; + *ovf = __builtin_add_overflow (x, y, &res); + return res; +} + +int +main () +{ + int ovf; + if (fn1 (-10, __INT_MAX__) != (int) (-10U - __INT_MAX__) + || fn2 (0, 0) != 0 + || fn2 (32, 16383) != (short int) 524256ULL) + __builtin_abort (); +#if __SIZEOF_INT__ > __SIZEOF_SHORT__ && __SIZEOF_INT__ > 1 + if (fn3 (__SCHAR_MAX__, (unsigned short) ~0, &ovf) != (int) (__SCHAR_MAX__ + (unsigned short) ~0) + || ovf + || fn3 (-__SCHAR_MAX__ - 1, 0, &ovf) != (int) (-__SCHAR_MAX__ - 1) + || ovf) + __builtin_abort (); +#endif + if (fn4 (65535, 0, &ovf) != 65535L * -32768 || ovf) + __builtin_abort (); +#if __SIZEOF_INT__ > 1 + if (fn5 (0, 0, &ovf) != (signed char) (__SCHAR_MAX__ / 4 * 5) + || !ovf + || fn5 (63, 3, &ovf) != (signed char) ((__SCHAR_MAX__ / 4 + 63) * 8) + || !ovf) + __builtin_abort (); +#endif + if (fn6 (0, 0, &ovf) != (unsigned char) ~0 - 66 + || ovf + || fn6 (63, 3, &ovf) != (unsigned char) ~0 + || ovf) + __builtin_abort (); + if (fn7 (0, 0, &ovf) != 0 + || !ovf + || fn7 (63, 3, &ovf) != 18 + || !ovf) + __builtin_abort (); + return 0; +} + +/* { dg-final { scan-tree-dump-not "ADD_OVERFLOW" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "SUB_OVERFLOW" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "MUL_OVERFLOW" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ |