re PR middle-end/91450 (__builtin_mul_overflow(A,B,R) wrong code if product < 0, *R is unsigned, and !(A&B))
PR middle-end/91450 * internal-fn.c (expand_mul_overflow): For s1 * s2 -> ur, if one operand is negative and one non-negative, compare the non-negative one against 0 rather than comparing s1 & s2 against 0. Otherwise, don't compare (s1 & s2) == 0, but compare separately both s1 == 0 and s2 == 0, unless one of them is known to be negative. Remove tem2 variable, use tem where tem2 has been used before. * gcc.c-torture/execute/pr91450-1.c: New test. * gcc.c-torture/execute/pr91450-2.c: New test. From-SVN: r278437
This commit is contained in:
parent
655b60f966
commit
beeac4c271
5 changed files with 194 additions and 11 deletions
|
@ -1,3 +1,13 @@
|
|||
2019-11-19 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR middle-end/91450
|
||||
* internal-fn.c (expand_mul_overflow): For s1 * s2 -> ur, if one
|
||||
operand is negative and one non-negative, compare the non-negative
|
||||
one against 0 rather than comparing s1 & s2 against 0. Otherwise,
|
||||
don't compare (s1 & s2) == 0, but compare separately both s1 == 0
|
||||
and s2 == 0, unless one of them is known to be negative. Remove
|
||||
tem2 variable, use tem where tem2 has been used before.
|
||||
|
||||
2019-11-19 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* doc/invoke.texi (-gno-internal-reset-location-views): Fix typo.
|
||||
|
|
|
@ -1409,7 +1409,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
|
|||
/* s1 * s2 -> ur */
|
||||
if (!uns0_p && !uns1_p && unsr_p)
|
||||
{
|
||||
rtx tem, tem2;
|
||||
rtx tem;
|
||||
switch (pos_neg0 | pos_neg1)
|
||||
{
|
||||
case 1: /* Both operands known to be non-negative. */
|
||||
|
@ -1439,10 +1439,8 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
|
|||
ops.op2 = NULL_TREE;
|
||||
ops.location = loc;
|
||||
res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
|
||||
tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
|
||||
OPTAB_LIB_WIDEN);
|
||||
do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode,
|
||||
NULL_RTX, NULL, done_label,
|
||||
do_compare_rtx_and_jump (pos_neg0 == 1 ? op0 : op1, const0_rtx, EQ,
|
||||
true, mode, NULL_RTX, NULL, done_label,
|
||||
profile_probability::very_likely ());
|
||||
goto do_error_label;
|
||||
}
|
||||
|
@ -1473,16 +1471,23 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
|
|||
arg1 = error_mark_node;
|
||||
emit_jump (do_main_label);
|
||||
emit_label (after_negate_label);
|
||||
tem2 = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
|
||||
tem = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
|
||||
OPTAB_LIB_WIDEN);
|
||||
do_compare_rtx_and_jump (tem2, const0_rtx, GE, false, mode, NULL_RTX,
|
||||
NULL, do_main_label, profile_probability::very_likely ());
|
||||
do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
|
||||
NULL, do_main_label,
|
||||
profile_probability::very_likely ());
|
||||
/* One argument is negative here, the other positive. This
|
||||
overflows always, unless one of the arguments is 0. But
|
||||
if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
|
||||
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, profile_probability::very_likely ());
|
||||
if (pos_neg0 != 2)
|
||||
do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
|
||||
NULL, do_main_label,
|
||||
profile_probability::very_unlikely ());
|
||||
if (pos_neg1 != 2)
|
||||
do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
|
||||
NULL, do_main_label,
|
||||
profile_probability::very_unlikely ());
|
||||
expand_arith_set_overflow (lhs, target);
|
||||
emit_label (do_main_label);
|
||||
goto do_main;
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
2019-11-19 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR middle-end/91450
|
||||
* gcc.c-torture/execute/pr91450-1.c: New test.
|
||||
* gcc.c-torture/execute/pr91450-2.c: New test.
|
||||
|
||||
PR c++/92504
|
||||
* g++.dg/gomp/pr92504.C: New test.
|
||||
|
||||
|
|
88
gcc/testsuite/gcc.c-torture/execute/pr91450-1.c
Normal file
88
gcc/testsuite/gcc.c-torture/execute/pr91450-1.c
Normal file
|
@ -0,0 +1,88 @@
|
|||
/* PR middle-end/91450 */
|
||||
|
||||
__attribute__((noipa)) unsigned long long
|
||||
foo (int a, int b)
|
||||
{
|
||||
unsigned long long r;
|
||||
if (!__builtin_mul_overflow (a, b, &r))
|
||||
__builtin_abort ();
|
||||
return r;
|
||||
}
|
||||
|
||||
__attribute__((noipa)) unsigned long long
|
||||
bar (int a, int b)
|
||||
{
|
||||
unsigned long long r;
|
||||
if (a >= 0)
|
||||
return 0;
|
||||
if (!__builtin_mul_overflow (a, b, &r))
|
||||
__builtin_abort ();
|
||||
return r;
|
||||
}
|
||||
|
||||
__attribute__((noipa)) unsigned long long
|
||||
baz (int a, int b)
|
||||
{
|
||||
unsigned long long r;
|
||||
if (b >= 0)
|
||||
return 0;
|
||||
if (!__builtin_mul_overflow (a, b, &r))
|
||||
__builtin_abort ();
|
||||
return r;
|
||||
}
|
||||
|
||||
__attribute__((noipa)) unsigned long long
|
||||
qux (int a, int b)
|
||||
{
|
||||
unsigned long long r;
|
||||
if (a >= 0)
|
||||
return 0;
|
||||
if (b < 0)
|
||||
return 0;
|
||||
if (!__builtin_mul_overflow (a, b, &r))
|
||||
__builtin_abort ();
|
||||
return r;
|
||||
}
|
||||
|
||||
__attribute__((noipa)) unsigned long long
|
||||
quux (int a, int b)
|
||||
{
|
||||
unsigned long long r;
|
||||
if (a < 0)
|
||||
return 0;
|
||||
if (b >= 0)
|
||||
return 0;
|
||||
if (!__builtin_mul_overflow (a, b, &r))
|
||||
__builtin_abort ();
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
if (foo (-4, 2) != -8ULL)
|
||||
__builtin_abort ();
|
||||
if (foo (2, -4) != -8ULL)
|
||||
__builtin_abort ();
|
||||
if (bar (-4, 2) != -8ULL)
|
||||
__builtin_abort ();
|
||||
if (baz (2, -4) != -8ULL)
|
||||
__builtin_abort ();
|
||||
if (qux (-4, 2) != -8ULL)
|
||||
__builtin_abort ();
|
||||
if (quux (2, -4) != -8ULL)
|
||||
__builtin_abort ();
|
||||
if (foo (-2, 1) != -2ULL)
|
||||
__builtin_abort ();
|
||||
if (foo (1, -2) != -2ULL)
|
||||
__builtin_abort ();
|
||||
if (bar (-2, 1) != -2ULL)
|
||||
__builtin_abort ();
|
||||
if (baz (1, -2) != -2ULL)
|
||||
__builtin_abort ();
|
||||
if (qux (-2, 1) != -2ULL)
|
||||
__builtin_abort ();
|
||||
if (quux (1, -2) != -2ULL)
|
||||
__builtin_abort ();
|
||||
return 0;
|
||||
}
|
76
gcc/testsuite/gcc.c-torture/execute/pr91450-2.c
Normal file
76
gcc/testsuite/gcc.c-torture/execute/pr91450-2.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
/* PR middle-end/91450 */
|
||||
|
||||
__attribute__((noipa)) void
|
||||
foo (int a, int b)
|
||||
{
|
||||
unsigned long long r;
|
||||
if (__builtin_mul_overflow (a, b, &r))
|
||||
__builtin_abort ();
|
||||
if (r != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
__attribute__((noipa)) void
|
||||
bar (int a, int b)
|
||||
{
|
||||
unsigned long long r;
|
||||
if (a >= 0)
|
||||
return;
|
||||
if (__builtin_mul_overflow (a, b, &r))
|
||||
__builtin_abort ();
|
||||
if (r != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
__attribute__((noipa)) void
|
||||
baz (int a, int b)
|
||||
{
|
||||
unsigned long long r;
|
||||
if (b >= 0)
|
||||
return;
|
||||
if (__builtin_mul_overflow (a, b, &r))
|
||||
__builtin_abort ();
|
||||
if (r != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
__attribute__((noipa)) void
|
||||
qux (int a, int b)
|
||||
{
|
||||
unsigned long long r;
|
||||
if (a >= 0)
|
||||
return;
|
||||
if (b < 0)
|
||||
return;
|
||||
if (__builtin_mul_overflow (a, b, &r))
|
||||
__builtin_abort ();
|
||||
if (r != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
__attribute__((noipa)) void
|
||||
quux (int a, int b)
|
||||
{
|
||||
unsigned long long r;
|
||||
if (a < 0)
|
||||
return;
|
||||
if (b >= 0)
|
||||
return;
|
||||
if (__builtin_mul_overflow (a, b, &r))
|
||||
__builtin_abort ();
|
||||
if (r != 0)
|
||||
__builtin_abort ();
|
||||
}
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
foo (-4, 0);
|
||||
foo (0, -4);
|
||||
foo (0, 0);
|
||||
bar (-4, 0);
|
||||
baz (0, -4);
|
||||
qux (-4, 0);
|
||||
quux (0, -4);
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue