Commit a86451b9 by Jakub Jelinek Committed by Jakub Jelinek

internal-fn.c (expand_arith_set_overflow): New function.

	* internal-fn.c (expand_arith_set_overflow): New function.
	(expand_addsub_overflow, expand_neg_overflow, expand_mul_overflow):
	Use it.
	(expand_arith_overflow_result_store): Likewise.  Handle precision
	smaller than mode precision.
	* tree-vrp.c (extract_range_basic): For imag part, handle
	properly signed 1-bit precision result.
	* doc/extend.texi (__builtin_add_overflow): Document that last
	argument can't be pointer to enumerated or boolean type.
	(__builtin_add_overflow_p): Document that last argument can't
	have enumerated or boolean type.

	* c-common.c (check_builtin_function_arguments): Require last
	argument of BUILT_IN_*_OVERFLOW_P to have INTEGER_TYPE type.
	Adjust wording of diagnostics for BUILT_IN_*_OVERLFLOW
	if the last argument is pointer to enumerated or boolean type.

	* c-c++-common/builtin-arith-overflow-1.c (generic_wrong_type, f3,
	f4): Adjust expected diagnostics.
	* c-c++-common/torture/builtin-arith-overflow.h (TP): New macro.
	(T): If OVFP is defined, redefine to TP.
	* c-c++-common/torture/builtin-arith-overflow-12.c: Adjust comment.
	* c-c++-common/torture/builtin-arith-overflow-p-1.c: New test.
	* c-c++-common/torture/builtin-arith-overflow-p-2.c: New test.
	* c-c++-common/torture/builtin-arith-overflow-p-3.c: New test.
	* c-c++-common/torture/builtin-arith-overflow-p-4.c: New test.
	* c-c++-common/torture/builtin-arith-overflow-p-5.c: New test.
	* c-c++-common/torture/builtin-arith-overflow-p-6.c: New test.
	* c-c++-common/torture/builtin-arith-overflow-p-7.c: New test.
	* c-c++-common/torture/builtin-arith-overflow-p-8.c: New test.
	* c-c++-common/torture/builtin-arith-overflow-p-9.c: New test.
	* c-c++-common/torture/builtin-arith-overflow-p-10.c: New test.
	* c-c++-common/torture/builtin-arith-overflow-p-11.c: New test.
	* c-c++-common/torture/builtin-arith-overflow-p-12.c: New test.
	* c-c++-common/torture/builtin-arith-overflow-p-13.c: New test.
	* c-c++-common/torture/builtin-arith-overflow-p-14.c: New test.
	* c-c++-common/torture/builtin-arith-overflow-p-15.c: New test.
	* c-c++-common/torture/builtin-arith-overflow-p-16.c: New test.
	* c-c++-common/torture/builtin-arith-overflow-p-17.c: New test.
	* c-c++-common/torture/builtin-arith-overflow-p-18.c: New test.
	* c-c++-common/torture/builtin-arith-overflow-p-19.c: New test.
	* g++.dg/ext/builtin-arith-overflow-1.C: Pass 0 instead of C
	as last argument to __builtin_add_overflow_p.

From-SVN: r237754
parent 43535362
2016-06-24 Jakub Jelinek <jakub@redhat.com>
* internal-fn.c (expand_arith_set_overflow): New function.
(expand_addsub_overflow, expand_neg_overflow, expand_mul_overflow):
Use it.
(expand_arith_overflow_result_store): Likewise. Handle precision
smaller than mode precision.
* tree-vrp.c (extract_range_basic): For imag part, handle
properly signed 1-bit precision result.
* doc/extend.texi (__builtin_add_overflow): Document that last
argument can't be pointer to enumerated or boolean type.
(__builtin_add_overflow_p): Document that last argument can't
have enumerated or boolean type.
2016-06-23 Michael Meissner <meissner@linux.vnet.ibm.com>
Bill Schmidt <wschmidt@linux.vnet.ibm.com>
......
2016-06-24 Jakub Jelinek <jakub@redhat.com>
* c-common.c (check_builtin_function_arguments): Require last
argument of BUILT_IN_*_OVERFLOW_P to have INTEGER_TYPE type.
Adjust wording of diagnostics for BUILT_IN_*_OVERLFLOW
if the last argument is pointer to enumerated or boolean type.
2016-06-22 David Malcolm <dmalcolm@redhat.com>
PR c/70339
......
......@@ -9983,10 +9983,22 @@ check_builtin_function_arguments (location_t loc, vec<location_t> arg_loc,
return false;
}
if (TREE_CODE (TREE_TYPE (args[2])) != POINTER_TYPE
|| TREE_CODE (TREE_TYPE (TREE_TYPE (args[2]))) != INTEGER_TYPE)
|| !INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (args[2]))))
{
error_at (ARG_LOCATION (2), "argument 3 in call to function %qE "
"does not have pointer to integer type", fndecl);
"does not have pointer to integral type", fndecl);
return false;
}
else if (TREE_CODE (TREE_TYPE (TREE_TYPE (args[2]))) == ENUMERAL_TYPE)
{
error_at (ARG_LOCATION (2), "argument 3 in call to function %qE "
"has pointer to enumerated type", fndecl);
return false;
}
else if (TREE_CODE (TREE_TYPE (TREE_TYPE (args[2]))) == BOOLEAN_TYPE)
{
error_at (ARG_LOCATION (2), "argument 3 in call to function %qE "
"has pointer to boolean type", fndecl);
return false;
}
return true;
......@@ -10006,6 +10018,18 @@ check_builtin_function_arguments (location_t loc, vec<location_t> arg_loc,
"%qE does not have integral type", i + 1, fndecl);
return false;
}
if (TREE_CODE (TREE_TYPE (args[2])) == ENUMERAL_TYPE)
{
error_at (ARG_LOCATION (2), "argument 3 in call to function "
"%qE has enumerated type", fndecl);
return false;
}
else if (TREE_CODE (TREE_TYPE (args[2])) == BOOLEAN_TYPE)
{
error_at (ARG_LOCATION (2), "argument 3 in call to function "
"%qE has boolean type", fndecl);
return false;
}
return true;
}
return false;
......
......@@ -9833,8 +9833,8 @@ performed in infinite signed precision, these built-in functions have fully defi
behavior for all argument values.
The first built-in function allows arbitrary integral types for operands and
the result type must be pointer to some integer type, the rest of the built-in
functions have explicit integer types.
the result type must be pointer to some integral type other than enumerated or
Boolean type, the rest of the built-in functions have explicit integer types.
The compiler will attempt to use hardware instructions to implement
these built-in functions where possible, like conditional jump on overflow
......@@ -9879,7 +9879,8 @@ would overflow.
These built-in functions are similar to @code{__builtin_add_overflow},
@code{__builtin_sub_overflow}, or @code{__builtin_mul_overflow}, except that
they don't store the result of the arithmetic operation anywhere and the
last argument is not a pointer, but some integral expression.
last argument is not a pointer, but some expression with integral type other
than enumerated or Boolean type.
The built-in functions promote the first two operands into infinite precision signed type
and perform addition on those promoted operands. The result is then
......
......@@ -405,9 +405,23 @@ get_min_precision (tree arg, signop sign)
return prec + (orig_sign != sign);
}
/* Helper for expand_*_overflow. Set the __imag__ part to true
(1 except for signed:1 type, in which case store -1). */
static void
expand_arith_set_overflow (tree lhs, rtx target)
{
if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs))) == 1
&& !TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs))))
write_complex_part (target, constm1_rtx, true);
else
write_complex_part (target, const1_rtx, true);
}
/* Helper for expand_*_overflow. Store RES into the __real__ part
of TARGET. If RES has larger MODE than __real__ part of TARGET,
set the __imag__ part to 1 if RES doesn't fit into it. */
set the __imag__ part to 1 if RES doesn't fit into it. Similarly
if LHS has smaller precision than its mode. */
static void
expand_arith_overflow_result_store (tree lhs, rtx target,
......@@ -424,7 +438,35 @@ expand_arith_overflow_result_store (tree lhs, rtx target,
do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
EQ, true, mode, NULL_RTX, NULL, done_label,
PROB_VERY_LIKELY);
write_complex_part (target, const1_rtx, true);
expand_arith_set_overflow (lhs, target);
emit_label (done_label);
}
int prec = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (lhs)));
int tgtprec = GET_MODE_PRECISION (tgtmode);
if (prec < tgtprec)
{
rtx_code_label *done_label = gen_label_rtx ();
int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
res = lres;
if (uns)
{
rtx mask
= immed_wide_int_const (wi::shifted_mask (0, prec, false, tgtprec),
tgtmode);
lres = expand_simple_binop (tgtmode, AND, res, mask, NULL_RTX,
true, OPTAB_DIRECT);
}
else
{
lres = expand_shift (LSHIFT_EXPR, tgtmode, res, tgtprec - prec,
NULL_RTX, 1);
lres = expand_shift (RSHIFT_EXPR, tgtmode, lres, tgtprec - prec,
NULL_RTX, 0);
}
do_compare_rtx_and_jump (res, lres,
EQ, true, tgtmode, NULL_RTX, NULL, done_label,
PROB_VERY_LIKELY);
expand_arith_set_overflow (lhs, target);
emit_label (done_label);
}
write_complex_part (target, lres, false);
......@@ -861,7 +903,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
do_pending_stack_adjust ();
}
else if (lhs)
write_complex_part (target, const1_rtx, true);
expand_arith_set_overflow (lhs, target);
/* We're done. */
emit_label (done_label);
......@@ -956,7 +998,7 @@ expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan)
do_pending_stack_adjust ();
}
else if (lhs)
write_complex_part (target, const1_rtx, true);
expand_arith_set_overflow (lhs, target);
/* We're done. */
emit_label (done_label);
......@@ -1082,7 +1124,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
NULL, do_main_label, PROB_VERY_LIKELY);
do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
NULL, do_main_label, PROB_VERY_LIKELY);
write_complex_part (target, const1_rtx, true);
expand_arith_set_overflow (lhs, target);
emit_label (do_main_label);
goto do_main;
default:
......@@ -1213,7 +1255,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
is, thus we can keep do_main code oring in overflow as is. */
do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode, NULL_RTX,
NULL, do_main_label, PROB_VERY_LIKELY);
write_complex_part (target, const1_rtx, true);
expand_arith_set_overflow (lhs, target);
emit_label (do_main_label);
goto do_main;
default:
......@@ -1617,7 +1659,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
do_pending_stack_adjust ();
}
else if (lhs)
write_complex_part (target, const1_rtx, true);
expand_arith_set_overflow (lhs, target);
/* We're done. */
emit_label (done_label);
......@@ -1628,7 +1670,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
rtx_code_label *all_done_label = gen_label_rtx ();
do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
NULL, all_done_label, PROB_VERY_LIKELY);
write_complex_part (target, const1_rtx, true);
expand_arith_set_overflow (lhs, target);
emit_label (all_done_label);
}
......@@ -1639,7 +1681,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
rtx_code_label *set_noovf = gen_label_rtx ();
do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
NULL, all_done_label, PROB_VERY_LIKELY);
write_complex_part (target, const1_rtx, true);
expand_arith_set_overflow (lhs, target);
do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
NULL, set_noovf, PROB_VERY_LIKELY);
do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
......
2016-06-24 Jakub Jelinek <jakub@redhat.com>
* c-c++-common/builtin-arith-overflow-1.c (generic_wrong_type, f3,
f4): Adjust expected diagnostics.
* c-c++-common/torture/builtin-arith-overflow.h (TP): New macro.
(T): If OVFP is defined, redefine to TP.
* c-c++-common/torture/builtin-arith-overflow-12.c: Adjust comment.
* c-c++-common/torture/builtin-arith-overflow-p-1.c: New test.
* c-c++-common/torture/builtin-arith-overflow-p-2.c: New test.
* c-c++-common/torture/builtin-arith-overflow-p-3.c: New test.
* c-c++-common/torture/builtin-arith-overflow-p-4.c: New test.
* c-c++-common/torture/builtin-arith-overflow-p-5.c: New test.
* c-c++-common/torture/builtin-arith-overflow-p-6.c: New test.
* c-c++-common/torture/builtin-arith-overflow-p-7.c: New test.
* c-c++-common/torture/builtin-arith-overflow-p-8.c: New test.
* c-c++-common/torture/builtin-arith-overflow-p-9.c: New test.
* c-c++-common/torture/builtin-arith-overflow-p-10.c: New test.
* c-c++-common/torture/builtin-arith-overflow-p-11.c: New test.
* c-c++-common/torture/builtin-arith-overflow-p-12.c: New test.
* c-c++-common/torture/builtin-arith-overflow-p-13.c: New test.
* c-c++-common/torture/builtin-arith-overflow-p-14.c: New test.
* c-c++-common/torture/builtin-arith-overflow-p-15.c: New test.
* c-c++-common/torture/builtin-arith-overflow-p-16.c: New test.
* c-c++-common/torture/builtin-arith-overflow-p-17.c: New test.
* c-c++-common/torture/builtin-arith-overflow-p-18.c: New test.
* c-c++-common/torture/builtin-arith-overflow-p-19.c: New test.
* g++.dg/ext/builtin-arith-overflow-1.C: Pass 0 instead of C
as last argument to __builtin_add_overflow_p.
2016-06-23 Uros Bizjak <ubizjak@gmail.com>
* g++.dg/vect/pr33834_2.cc: Use dg-additional-options instead of
......
......@@ -118,14 +118,14 @@ generic_wrong_type (int a, int b)
{
void *p = 0;
double d = 0;
int x = __builtin_add_overflow (a, b, p); /* { dg-error "does not have pointer to integer type" } */
x += __builtin_sub_overflow (a, b, &p); /* { dg-error "does not have pointer to integer type" } */
x += __builtin_mul_overflow (a, b, &d); /* { dg-error "does not have pointer to integer type" } */
int x = __builtin_add_overflow (a, b, p); /* { dg-error "does not have pointer to integral type" } */
x += __builtin_sub_overflow (a, b, &p); /* { dg-error "does not have pointer to integral type" } */
x += __builtin_mul_overflow (a, b, &d); /* { dg-error "does not have pointer to integral type" } */
/* Also verify literal arguments. */
x += __builtin_add_overflow (1, 1, p); /* { dg-error "does not have pointer to integer type" } */
x += __builtin_sub_overflow (1, 1, &p); /* { dg-error "does not have pointer to integer type" } */
x += __builtin_mul_overflow (1, 1, &d); /* { dg-error "does not have pointer to integer type" } */
x += __builtin_add_overflow (1, 1, p); /* { dg-error "does not have pointer to integral type" } */
x += __builtin_sub_overflow (1, 1, &p); /* { dg-error "does not have pointer to integral type" } */
x += __builtin_mul_overflow (1, 1, &d); /* { dg-error "does not have pointer to integral type" } */
return x;
}
......@@ -236,8 +236,8 @@ f3 (float fa, int a, _Complex long int ca, double fb, void *pb, int b, enum E eb
x += __builtin_sub_overflow_p (ca, b, eb); /* { dg-error "argument 1 in call to function\[^\n\r]*does not have integral type" } */
x += __builtin_mul_overflow_p (a, fb, bb); /* { dg-error "argument 2 in call to function\[^\n\r]*does not have integral type" } */
x += __builtin_add_overflow_p (a, pb, a); /* { dg-error "argument 2 in call to function\[^\n\r]*does not have integral type" } */
x += __builtin_sub_overflow_p (a, eb, eb);
x += __builtin_mul_overflow_p (a, bb, bb);
x += __builtin_sub_overflow_p (a, eb, eb); /* { dg-error "argument 3 in call to function\[^\n\r]*has enumerated type" } */
x += __builtin_mul_overflow_p (a, bb, bb); /* { dg-error "argument 3 in call to function\[^\n\r]*has boolean type" } */
x += __builtin_add_overflow_p (a, b, fa); /* { dg-error "argument 3 in call to function\[^\n\r]*does not have integral type" } */
x += __builtin_sub_overflow_p (a, b, ca); /* { dg-error "argument 3 in call to function\[^\n\r]*does not have integral type" } */
x += __builtin_mul_overflow_p (a, b, c); /* { dg-error "argument 3 in call to function\[^\n\r]*does not have integral type" } */
......@@ -247,11 +247,11 @@ f3 (float fa, int a, _Complex long int ca, double fb, void *pb, int b, enum E eb
int
f4 (float *fp, double *dp, _Complex int *cp, enum E *ep, bool *bp, long long int *llp)
{
int x = __builtin_add_overflow (1, 2, fp); /* { dg-error "argument 3 in call to function\[^\n\r]*does not have pointer to integer type" } */
x += __builtin_sub_overflow (1, 2, dp); /* { dg-error "argument 3 in call to function\[^\n\r]*does not have pointer to integer type" } */
x += __builtin_mul_overflow (1, 2, cp); /* { dg-error "argument 3 in call to function\[^\n\r]*does not have pointer to integer type" } */
x += __builtin_add_overflow (1, 2, ep); /* { dg-error "argument 3 in call to function\[^\n\r]*does not have pointer to integer type" } */
x += __builtin_sub_overflow (1, 2, bp); /* { dg-error "argument 3 in call to function\[^\n\r]*does not have pointer to integer type" } */
int x = __builtin_add_overflow (1, 2, fp); /* { dg-error "argument 3 in call to function\[^\n\r]*does not have pointer to integral type" } */
x += __builtin_sub_overflow (1, 2, dp); /* { dg-error "argument 3 in call to function\[^\n\r]*does not have pointer to integral type" } */
x += __builtin_mul_overflow (1, 2, cp); /* { dg-error "argument 3 in call to function\[^\n\r]*does not have pointer to integral type" } */
x += __builtin_add_overflow (1, 2, ep); /* { dg-error "argument 3 in call to function\[^\n\r]*has pointer to enumerated type" } */
x += __builtin_sub_overflow (1, 2, bp); /* { dg-error "argument 3 in call to function\[^\n\r]*has pointer to boolean type" } */
x += __builtin_mul_overflow (1, 2, llp);
return x;
}
/* Test __builtin_{add,sub,mul_overflow. */
/* Test __builtin_{add,sub,mul}_overflow. */
/* { dg-do run } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
......
/* Test __builtin_{add,sub,mul}_overflow_p. */
/* { dg-do run } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
#define OVFP
#include "builtin-arith-overflow-1.h"
#define U(s, op) op
TESTS (int, INT_MIN, INT_MAX)
#undef T
#define T(n, t1, t2, tr, v1, v2, vr, b, o) t##n##b ();
int
main ()
{
TESTS (int, INT_MIN, INT_MAX)
return 0;
}
/* Test __builtin_{add,sub}_overflow_p on {,un}signed long int. */
/* { dg-do run } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
typedef signed long int S;
typedef unsigned long int U;
#define COND 1
#define SHIFT ((__SIZEOF_LONG__ - 1) * __CHAR_BIT__)
#define S_MAX __LONG_MAX__
#define S_MIN (-__LONG_MAX__ - 1)
#if __SIZEOF_LONG_LONG__ > __SIZEOF_LONG__
typedef long long int W;
#elif __SIZEOF_INT128__ > __SIZEOF_LONG__
typedef __int128 W;
#else
#undef COND
#define COND 0
#endif
#include "builtin-arith-overflow-p-7.c"
/* Test __builtin_{add,sub}_overflow_p on {,un}signed long long int. */
/* { dg-do run } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
typedef signed long long int S;
typedef unsigned long long int U;
#define COND 1
#define SHIFT ((__SIZEOF_LONG_LONG__ - 1) * __CHAR_BIT__)
#define S_MAX __LONG_LONG_MAX__
#define S_MIN (-__LONG_LONG_MAX__ - 1)
#if __SIZEOF_INT128__ > __SIZEOF_LONG_LONG__
typedef __int128 W;
#else
#undef COND
#define COND 0
#endif
#include "builtin-arith-overflow-p-7.c"
/* Test __builtin_{add,sub,mul}_overflow_p. */
/* { dg-do run } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
#define OVFP
#include "builtin-arith-overflow-12.h"
TESTS (int, INT_MIN, INT_MAX)
#undef T
#define T(n, t1, t2, tr, v1, v2, vr, b, o) t##n##b ();
int
main ()
{
TESTS (int, INT_MIN, INT_MAX)
return 0;
}
/* Test __builtin_{add,sub,mul}_overflow_p. */
/* { dg-do run } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
#define OVFP
#include "builtin-arith-overflow-12.h"
TESTS (long, LONG_MIN, LONG_MAX)
#undef T
#define T(n, t1, t2, tr, v1, v2, vr, b, o) t##n##b ();
int
main ()
{
TESTS (long, LONG_MIN, LONG_MAX)
return 0;
}
/* Test __builtin_{add,sub,mul}_overflow_p. */
/* { dg-do run } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
#define OVFP
#include "builtin-arith-overflow-12.h"
TESTS (long long, LLONG_MIN, LLONG_MAX)
#undef T
#define T(n, t1, t2, tr, v1, v2, vr, b, o) t##n##b ();
int
main ()
{
TESTS (long long, LLONG_MIN, LLONG_MAX)
return 0;
}
/* Test __builtin_{add,sub,mul}_overflow_p. */
/* { dg-do run } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
#define OVFP
#include "builtin-arith-overflow-12.h"
TESTS (char, SCHAR_MIN, SCHAR_MAX)
#undef T
#define T(n, t1, t2, tr, v1, v2, vr, b, o) t##n##b ();
int
main ()
{
TESTS (char, SCHAR_MIN, SCHAR_MAX)
return 0;
}
/* Test __builtin_{add,sub,mul}_overflow_p. */
/* { dg-do run } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
#define OVFP
#include "builtin-arith-overflow-12.h"
TESTS (short, SHRT_MIN, SHRT_MAX)
#undef T
#define T(n, t1, t2, tr, v1, v2, vr, b, o) t##n##b ();
int
main ()
{
TESTS (short, SHRT_MIN, SHRT_MAX)
return 0;
}
/* Test __builtin_{add,sub,mul}_overflow_p. */
/* { dg-do run { target int128 } } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
#define OVFP
#include "builtin-arith-overflow-12.h"
#define INT128_MAX ((signed __int128) (((unsigned __int128) 1 << (__SIZEOF_INT128__ * __CHAR_BIT__ - 1)) - 1))
#define INT128_MIN (-INT128_MAX - 1)
TESTS (__int128, INT128_MIN, INT128_MAX)
#undef T
#define T(n, t1, t2, tr, v1, v2, vr, b, o) t##n##b ();
int
main ()
{
TESTS (__int128, INT128_MIN, INT128_MAX)
return 0;
}
/* Test __builtin_{add,sub,mul}_overflow_p. */
/* { dg-do run } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
#define OVFP
#include "builtin-arith-overflow.h"
#ifdef __SIZEOF_INT128__
#define WTYPE __int128
#else
#define WTYPE long long int
#endif
#define TESTS \
T (100, signed char, signed char, unsigned WTYPE, -1, 0, -1, add, 1) \
T (101, unsigned char, unsigned char, unsigned WTYPE, 5, 5, 10, add, 0) \
T (102, signed char, unsigned short, unsigned WTYPE, 5, 5, 0, sub, 0) \
T (103, signed char, unsigned short, unsigned WTYPE, 5, 6, -1, sub, 1) \
T (104, signed char, signed char, unsigned WTYPE, -1, -1, 1, mul, 0) \
T (105, unsigned char, signed char, unsigned WTYPE, 17, -2, -34, mul, 1) \
T (106, unsigned WTYPE, signed WTYPE, signed char, 5, -2, -10, mul, 0) \
T (107, long long int, long long int, unsigned char, -3, 5, 2, add, 0) \
T (108, long long int, int, unsigned char, -5, 3, -2, add, 1) \
T (109, int, WTYPE, unsigned char, -3, 5, 2, add, 0) \
T (110, unsigned char, unsigned char, unsigned WTYPE, SCHAR_MAX - 1, (unsigned char) SCHAR_MAX + 4, -5, sub, 1)
TESTS
#undef T
#define T(n, t1, t2, tr, v1, v2, vr, b, o) t##n##b ();
int
main ()
{
TESTS
return 0;
}
/* Test __builtin_{add,sub,mul}_overflow_p. */
/* { dg-do run { target c } } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
#include "builtin-arith-overflow.h"
#ifdef __SIZEOF_INT128__
#define WTYPE __int128
#else
#define WTYPE long long int
#endif
struct S
{
signed int s1 : 1;
unsigned int u1 : 1;
signed int s2 : 2;
unsigned int u2 : 2;
signed int s3 : 3;
unsigned int u3 : 3;
signed int s4 : 4;
unsigned int u4 : 4;
signed int s5 : 5;
unsigned int u5 : 5;
signed int s6 : 6;
unsigned int u6 : 6;
signed int s7 : 7;
unsigned int u7 : 7;
} vs;
#define TESTS \
TP (100, signed char, signed char, vs.u2, -1, 0, add, 1) \
TP (101, unsigned char, unsigned char, vs.u4, 5, 5, add, 0) \
TP (102, unsigned char, unsigned char, vs.u3, 5, 3, add, 1) \
TP (103, signed char, unsigned short, vs.u1, 5, 5, sub, 0) \
TP (104, signed char, unsigned short, vs.u1, 6, 5, sub, 0) \
TP (105, signed char, unsigned short, vs.u1, 7, 5, sub, 1) \
TP (106, signed char, unsigned short, vs.u4, 5, 6, sub, 1) \
TP (107, signed char, signed char, vs.u1, -1, -1, mul, 0) \
TP (108, signed char, signed char, vs.s1, -1, -1, mul, 1) \
TP (109, unsigned char, signed char, vs.u6, 17, -2, mul, 1) \
TP (110, unsigned char, signed char, vs.s6, 17, -2, mul, 1) \
TP (111, unsigned char, signed char, vs.s7, 17, -2, mul, 0) \
TP (112, unsigned WTYPE, signed WTYPE, vs.s5, 5, -2, mul, 0) \
TP (113, unsigned WTYPE, signed WTYPE, vs.s4, 5, -2, mul, 1) \
TP (114, long long int, long long int, vs.u2, -3, 5, add, 0) \
TP (115, long long int, long long int, vs.u1, -3, 5, add, 1) \
TP (116, long long int, int, vs.u3, -5, 3, add, 1) \
TP (117, long long int, int, vs.s1, -5, 3, add, 1) \
TP (118, long long int, int, vs.s2, -5, 3, add, 0) \
TP (119, int, WTYPE, vs.u2, -3, 5, add, 0) \
TP (120, int, WTYPE, vs.u1, -3, 5, add, 1) \
TP (121, unsigned char, unsigned char, vs.u6, SCHAR_MAX - 1, (unsigned char) SCHAR_MAX + 4, sub, 1) \
TP (122, unsigned char, unsigned char, vs.s3, SCHAR_MAX - 1, (unsigned char) SCHAR_MAX + 4, sub, 1) \
TP (123, unsigned char, unsigned char, vs.s4, SCHAR_MAX - 1, (unsigned char) SCHAR_MAX + 4, sub, 0) \
TP (124, unsigned int, unsigned int, vs.u7, INT_MAX, 1, add, 1) \
TP (125, unsigned int, unsigned int, vs.u7, 127, 1, add, 1) \
TP (126, unsigned int, unsigned int, vs.u7, 1, 63, add, 0) \
TP (127, int, int, vs.s7, INT_MIN, 1, sub, 1) \
TP (128, int, int, vs.s7, -64, 1, sub, 1) \
TP (129, int, int, vs.s7, -63, 1, sub, 0)
TESTS
#undef TP
#define TP(n, t1, t2, er, v1, v2, b, o) t##n##b ();
int
main ()
{
TESTS
return 0;
}
/* Test __builtin_{add,sub,mul}_overflow_p. */
/* { dg-do run } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
#define OVFP
#include "builtin-arith-overflow-1.h"
#define U(s, op) op
TESTS (long, LONG_MIN, LONG_MAX)
#undef T
#define T(n, t1, t2, tr, v1, v2, vr, b, o) t##n##b ();
int
main ()
{
TESTS (long, LONG_MIN, LONG_MAX)
return 0;
}
/* Test __builtin_{add,sub,mul}_overflow_p. */
/* { dg-do run } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
#define OVFP
#include "builtin-arith-overflow-1.h"
#define U(s, op) op
TESTS (long long, LLONG_MIN, LLONG_MAX)
#undef T
#define T(n, t1, t2, tr, v1, v2, vr, b, o) t##n##b ();
int
main ()
{
TESTS (long long, LLONG_MIN, LLONG_MAX)
return 0;
}
/* Test __builtin_{add,sub,mul}_overflow_p. */
/* { dg-do run } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
#define OVFP
#include "builtin-arith-overflow-1.h"
#define U(s, op) op
TESTS (char, SCHAR_MIN, SCHAR_MAX)
#undef T
#define T(n, t1, t2, tr, v1, v2, vr, b, o) t##n##b ();
int
main ()
{
TESTS (char, SCHAR_MIN, SCHAR_MAX)
return 0;
}
/* Test __builtin_{add,sub,mul}_overflow_p. */
/* { dg-do run } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
#define OVFP
#include "builtin-arith-overflow-1.h"
#define U(s, op) op
TESTS (short, SHRT_MIN, SHRT_MAX)
#undef T
#define T(n, t1, t2, tr, v1, v2, vr, b, o) t##n##b ();
int
main ()
{
TESTS (short, SHRT_MIN, SHRT_MAX)
return 0;
}
/* Test __builtin_{add,sub,mul}_overflow_p. */
/* { dg-do run { target int128 } } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
#define OVFP
#include "builtin-arith-overflow-1.h"
#define INT128_MAX ((signed __int128) (((unsigned __int128) 1 << (__SIZEOF_INT128__ * __CHAR_BIT__ - 1)) - 1))
#define INT128_MIN (-INT128_MAX - 1)
#define U(s, op) op
TESTS (__int128, INT128_MIN, INT128_MAX)
#undef T
#define T(n, t1, t2, tr, v1, v2, vr, b, o) t##n##b ();
int
main ()
{
TESTS (__int128, INT128_MIN, INT128_MAX)
return 0;
}
/* Test __builtin_{add,sub}_overflow_p on {,un}signed char. */
/* { dg-do run } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
#define UCHAR_MAX ((unsigned char) ~0)
#ifndef SHIFT
typedef signed char S;
typedef unsigned char U;
typedef int W;
#define SHIFT 0
#define S_MAX __SCHAR_MAX__
#define S_MIN (-__SCHAR_MAX__ - 1)
#define COND (__SIZEOF_INT__ > 1)
#endif
#define F(n, t1, t2, tr, b) \
__attribute__((noinline, noclone)) void \
n (t1 x, t2 y, int *ovf) \
{ \
*ovf = __builtin_##b##_overflow_p (x, y, \
(tr) 0); \
}
F (spses, S, S, S, add)
F (upueu, U, U, U, add)
F (spseu, S, S, U, add)
F (upues, U, U, S, add)
F (spues, S, U, S, add)
F (upses, U, S, S, add)
F (spueu, S, U, U, add)
F (upseu, U, S, U, add)
F (ssses, S, S, S, sub)
F (usueu, U, U, U, sub)
F (ssseu, S, S, U, sub)
F (usues, U, U, S, sub)
F (ssues, S, U, S, sub)
F (usses, U, S, S, sub)
F (ssueu, S, U, U, sub)
F (usseu, U, S, U, sub)
int
main ()
{
#if COND
int i, j;
for (i = 0; i < UCHAR_MAX; i++)
for (j = 0; j < UCHAR_MAX; j++)
{
S s1 = ((W) i << SHIFT) + S_MIN;
U u1 = ((W) i << SHIFT);
S s2 = ((W) j << SHIFT) + S_MIN;
U u2 = ((W) j << SHIFT);
W w;
int ovf;
#define T(n, t1, t2, tr, op) \
w = ((W) t1##1) op ((W) t2##2); \
n (t1##1, t2##2, &ovf); \
if (ovf != (w != (tr) w)) \
__builtin_abort ();
T (spses, s, s, S, +)
T (upueu, u, u, U, +)
T (spseu, s, s, U, +)
T (upues, u, u, S, +)
T (spues, s, u, S, +)
T (upses, u, s, S, +)
T (spueu, s, u, U, +)
T (upseu, u, s, U, +)
T (ssses, s, s, S, -)
T (usueu, u, u, U, -)
T (ssseu, s, s, U, -)
T (usues, u, u, S, -)
T (ssues, s, u, S, -)
T (usses, u, s, S, -)
T (ssueu, s, u, U, -)
T (usseu, u, s, U, -)
}
#endif
return 0;
}
/* Test __builtin_{add,sub}_overflow_p on {,un}signed short. */
/* { dg-do run } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
typedef signed short int S;
typedef unsigned short int U;
#define COND 1
#define SHIFT ((__SIZEOF_SHORT__ - 1) * __CHAR_BIT__)
#define S_MAX __SHRT_MAX__
#define S_MIN (-__SHRT_MAX__ - 1)
#if __SIZEOF_INT__ > __SIZEOF_SHORT__
typedef int W;
#elif __SIZEOF_LONG__ > __SIZEOF_SHORT__
typedef long int W;
#elif __SIZEOF_LONG_LONG__ > __SIZEOF_SHORT__
typedef long long int W;
#elif __SIZEOF_INT128__ > __SIZEOF_SHORT__
typedef __int128 W;
#else
#undef COND
#define COND 0
#endif
#include "builtin-arith-overflow-p-7.c"
/* Test __builtin_{add,sub}_overflow_p on {,un}signed int. */
/* { dg-do run } */
/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
typedef signed int S;
typedef unsigned int U;
#define COND 1
#define SHIFT ((__SIZEOF_INT__ - 1) * __CHAR_BIT__)
#define S_MAX __INT_MAX__
#define S_MIN (-__INT_MAX__ - 1)
#if __SIZEOF_LONG__ > __SIZEOF_INT__
typedef long int W;
#elif __SIZEOF_LONG_LONG__ > __SIZEOF_INT__
typedef long long int W;
#elif __SIZEOF_INT128__ > __SIZEOF_INT__
typedef __int128 W;
#else
#undef COND
#define COND 0
#endif
#include "builtin-arith-overflow-p-7.c"
......@@ -90,5 +90,70 @@ t##n##b (void) \
if (r2 != (tr) (vr) || v != 7 * o) \
__builtin_abort (); \
}
#define TP(n, t1, t2, er, v1, v2, b, o) \
__attribute__((noinline, noclone)) void \
t##n##_1##b (t1 x, t2 y) \
{ \
if (__builtin_##b##_overflow_p (x, y, er)) \
bar (); \
} \
\
__attribute__((noinline, noclone)) void \
t##n##_2##b (t2 y) \
{ \
t1 x = (v1); \
if (__builtin_##b##_overflow_p (x, y, er)) \
bar (); \
} \
\
__attribute__((noinline, noclone)) void \
t##n##_3##b (t2 y) \
{ \
if (__builtin_##b##_overflow_p ((t1) (v1), y, \
er)) \
bar (); \
} \
\
__attribute__((noinline, noclone)) void \
t##n##_4##b (t1 x) \
{ \
t2 y = (v2); \
if (__builtin_##b##_overflow_p (x, y, er)) \
bar (); \
} \
\
__attribute__((noinline, noclone)) void \
t##n##_5##b (t1 x) \
{ \
if (__builtin_##b##_overflow_p (x, (t2) (v2), \
er)) \
bar (); \
} \
\
__attribute__((noinline, noclone)) void \
t##n##b (void) \
{ \
t1 x = (v1); \
t2 y = (v2); \
v = 0; \
t##n##_1##b (x, y); \
t##n##_2##b (y); \
t##n##_3##b (y); \
t##n##_4##b (x); \
t##n##_5##b (x); \
if (__builtin_##b##_overflow_p (x, y, er)) \
bar (); \
if (__builtin_##b##_overflow_p ((t1) (v1), \
(t2) (v2), \
er)) \
bar (); \
if (v != 7 * o) \
__builtin_abort (); \
}
#ifdef OVFP
#undef T
#define T(n, t1, t2, tr, v1, v2, vr, b, o) \
TP(n, t1, t2, (tr) 0, v1, v2, b, o)
#endif
#define ST(n, t, v1, v2, vr, b, o) \
T (n, t, t, t, v1, v2, vr, b, o)
// { dg-do compile }
enum A { B = 1, C = 2, D = __builtin_add_overflow_p (B, C, C) };
int e[__builtin_add_overflow_p (B, C, C) + 1];
enum A { B = 1, C = 2, D = __builtin_add_overflow_p (B, C, 0) };
int e[__builtin_add_overflow_p (B, C, 0) + 1];
template <int N> int foo (int);
void
bar ()
{
foo <__builtin_add_overflow_p (B, C, C) + 1> (0);
foo <__builtin_add_overflow_p (B, C, 0) + 1> (0);
}
......@@ -4016,6 +4016,9 @@ extract_range_basic (value_range *vr, gimple *stmt)
set_value_range_to_value (vr,
build_int_cst (type, ovf),
NULL);
else if (TYPE_PRECISION (type) == 1
&& !TYPE_UNSIGNED (type))
set_value_range_to_varying (vr);
else
set_value_range (vr, VR_RANGE, build_int_cst (type, 0),
build_int_cst (type, 1), NULL);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment