aboutsummaryrefslogtreecommitdiff
path: root/gcc/wide-int.cc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2014-07-04 00:11:21 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2014-07-04 00:11:21 +0200
commitc01d6ad948e9e46fbc3695c7c3f45090c4d82db7 (patch)
tree3f9c19a1394d9950b851dd20a8814dd2e5cfd361 /gcc/wide-int.cc
parentf707da16f714f7fe5a42391748212c84dfec639b (diff)
downloadgcc-c01d6ad948e9e46fbc3695c7c3f45090c4d82db7.zip
gcc-c01d6ad948e9e46fbc3695c7c3f45090c4d82db7.tar.gz
gcc-c01d6ad948e9e46fbc3695c7c3f45090c4d82db7.tar.bz2
re PR tree-optimization/61682 (wrong code at -O3 on x86_64-linux-gnu)
PR tree-optimization/61682 * wide-int.cc (wi::mul_internal): Handle high correctly for umul_ppmm using cases and when one of the operands is equal to 1. * gcc.c-torture/execute/pr61682.c: New test. From-SVN: r212273
Diffstat (limited to 'gcc/wide-int.cc')
-rw-r--r--gcc/wide-int.cc20
1 files changed, 19 insertions, 1 deletions
diff --git a/gcc/wide-int.cc b/gcc/wide-int.cc
index ed7f01b..c33d10e 100644
--- a/gcc/wide-int.cc
+++ b/gcc/wide-int.cc
@@ -1,5 +1,5 @@
/* Operations with very long integers.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2014 Free Software Foundation, Inc.
Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
This file is part of GCC.
@@ -1282,6 +1282,12 @@ wi::mul_internal (HOST_WIDE_INT *val, const HOST_WIDE_INT *op1val,
&& wi::fits_uhwi_p (op1)
&& wi::fits_uhwi_p (op2))
{
+ /* This case never overflows. */
+ if (high)
+ {
+ val[0] = 0;
+ return 1;
+ }
umul_ppmm (val[1], val[0], op1.ulow (), op2.ulow ());
return 1 + (val[1] != 0 || val[0] < 0);
}
@@ -1294,6 +1300,8 @@ wi::mul_internal (HOST_WIDE_INT *val, const HOST_WIDE_INT *op1val,
umul_ppmm (upper, val[0], op1.ulow (), op2.ulow ());
if (needs_overflow)
*overflow = (upper != 0);
+ if (high)
+ val[0] = upper;
return 1;
}
}
@@ -1302,12 +1310,22 @@ wi::mul_internal (HOST_WIDE_INT *val, const HOST_WIDE_INT *op1val,
/* Handle multiplications by 1. */
if (op1 == 1)
{
+ if (high)
+ {
+ val[0] = wi::neg_p (op2, sgn) ? -1 : 0;
+ return 1;
+ }
for (i = 0; i < op2len; i++)
val[i] = op2val[i];
return op2len;
}
if (op2 == 1)
{
+ if (high)
+ {
+ val[0] = wi::neg_p (op1, sgn) ? -1 : 0;
+ return 1;
+ }
for (i = 0; i < op1len; i++)
val[i] = op1val[i];
return op1len;