summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>2005-01-21 17:54:26 +0000
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>2005-01-21 17:54:26 +0000
commita47b9d7927305dd956767900ce235bffc4e9310d (patch)
tree87965b49d99f08cdf39d5e6360e95fccbda397a3 /gcc
parent3d6475e0ba3a4748eb325a8d13f513cfd0adc77c (diff)
downloadgcc-a47b9d7927305dd956767900ce235bffc4e9310d.tar.gz
PR rtl-optimization/576
* real.c (real_arithmetic): Change return type from void to bool to return an indication that the result may be inexact. * real.h (real_arithmeric): Update prototype. * fold-const.c (const_binop): Don't constant fold floating point expressions when the user specifies -frounding-math and the result may depend upon the run-time rounding mode. (fold_convert_const_real_from_real): Clean-up. (fold_initializer): Ignore flag_rounding_math for initializers. * simplify-rtx.c (simplify_binary_operation): Likewise, don't constant fold FP operations with flag_rounding_math if the result may depend upon the run-time rounding mode. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@94020 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/fold-const.c33
-rw-r--r--gcc/real.c18
-rw-r--r--gcc/real.h2
-rw-r--r--gcc/simplify-rtx.c21
5 files changed, 58 insertions, 31 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2525350e7f0..7c07cc430f8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+2005-01-21 Roger Sayle <roger@eyesopen.com>
+
+ PR rtl-optimization/576
+ * real.c (real_arithmetic): Change return type from void to bool
+ to return an indication that the result may be inexact.
+ * real.h (real_arithmeric): Update prototype.
+ * fold-const.c (const_binop): Don't constant fold floating
+ point expressions when the user specifies -frounding-math and
+ the result may depend upon the run-time rounding mode.
+ (fold_convert_const_real_from_real): Clean-up.
+ (fold_initializer): Ignore flag_rounding_math for initializers.
+ * simplify-rtx.c (simplify_binary_operation): Likewise, don't
+ constant fold FP operations with flag_rounding_math if the
+ result may depend upon the run-time rounding mode.
+
2005-01-21 Tom Tromey <tromey@redhat.com>
* c-cppbuiltin.c (define__GNUC__): Correct assertion.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index cdefe7611fb..cb822ed2ec5 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -1482,6 +1482,8 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
REAL_VALUE_TYPE d1;
REAL_VALUE_TYPE d2;
REAL_VALUE_TYPE value;
+ REAL_VALUE_TYPE result;
+ bool inexact;
tree t, type;
d1 = TREE_REAL_CST (arg1);
@@ -1510,9 +1512,18 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
else if (REAL_VALUE_ISNAN (d2))
return arg2;
- REAL_ARITHMETIC (value, code, d1, d2);
+ inexact = real_arithmetic (&value, code, &d1, &d2);
+ real_convert (&result, mode, &value);
- t = build_real (type, real_value_truncate (mode, value));
+ /* Don't constant fold this floating point operation if the
+ result may dependent upon the run-time rounding mode and
+ flag_rounding_math is set. */
+
+ if (flag_rounding_math
+ && (inexact || !real_identical (&result, &value)))
+ return NULL_TREE;
+
+ t = build_real (type, result);
TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1) | TREE_OVERFLOW (arg2);
TREE_CONSTANT_OVERFLOW (t)
@@ -1808,20 +1819,11 @@ fold_convert_const_int_from_real (enum tree_code code, tree type, tree arg1)
static tree
fold_convert_const_real_from_real (tree type, tree arg1)
{
+ REAL_VALUE_TYPE value;
tree t;
- if (REAL_VALUE_ISNAN (TREE_REAL_CST (arg1)))
- {
- /* We make a copy of ARG1 so that we don't modify an
- existing constant tree. */
- t = copy_node (arg1);
- TREE_TYPE (t) = type;
- return t;
- }
-
- t = build_real (type,
- real_value_truncate (TYPE_MODE (type),
- TREE_REAL_CST (arg1)));
+ real_convert (&value, TYPE_MODE (type), &TREE_REAL_CST (arg1));
+ t = build_real (type, value);
TREE_OVERFLOW (t) = TREE_OVERFLOW (arg1);
TREE_CONSTANT_OVERFLOW (t)
@@ -9506,17 +9508,20 @@ fold_initializer (tree expr)
{
int saved_signaling_nans = flag_signaling_nans;
int saved_trapping_math = flag_trapping_math;
+ int saved_rounding_math = flag_rounding_math;
int saved_trapv = flag_trapv;
tree result;
flag_signaling_nans = 0;
flag_trapping_math = 0;
+ flag_rounding_math = 0;
flag_trapv = 0;
result = fold (expr);
flag_signaling_nans = saved_signaling_nans;
flag_trapping_math = saved_trapping_math;
+ flag_rounding_math = saved_rounding_math;
flag_trapv = saved_trapv;
return result;
diff --git a/gcc/real.c b/gcc/real.c
index 5871d1e037c..a748b87b33a 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -972,9 +972,10 @@ do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a)
}
/* Perform the binary or unary operation described by CODE.
- For a unary operation, leave OP1 NULL. */
+ For a unary operation, leave OP1 NULL. This function returns
+ true if the result may be inexact due to loss of precision. */
-void
+bool
real_arithmetic (REAL_VALUE_TYPE *r, int icode, const REAL_VALUE_TYPE *op0,
const REAL_VALUE_TYPE *op1)
{
@@ -983,20 +984,16 @@ real_arithmetic (REAL_VALUE_TYPE *r, int icode, const REAL_VALUE_TYPE *op0,
switch (code)
{
case PLUS_EXPR:
- do_add (r, op0, op1, 0);
- break;
+ return do_add (r, op0, op1, 0);
case MINUS_EXPR:
- do_add (r, op0, op1, 1);
- break;
+ return do_add (r, op0, op1, 1);
case MULT_EXPR:
- do_multiply (r, op0, op1);
- break;
+ return do_multiply (r, op0, op1);
case RDIV_EXPR:
- do_divide (r, op0, op1);
- break;
+ return do_divide (r, op0, op1);
case MIN_EXPR:
if (op1->cl == rvc_nan)
@@ -1033,6 +1030,7 @@ real_arithmetic (REAL_VALUE_TYPE *r, int icode, const REAL_VALUE_TYPE *op0,
default:
gcc_unreachable ();
}
+ return false;
}
/* Legacy. Similar, but return the result directly. */
diff --git a/gcc/real.h b/gcc/real.h
index c477be11b62..b7cf3bb2f04 100644
--- a/gcc/real.h
+++ b/gcc/real.h
@@ -160,7 +160,7 @@ extern const struct real_format *
/* Declare functions in real.c. */
/* Binary or unary arithmetic on tree_code. */
-extern void real_arithmetic (REAL_VALUE_TYPE *, int, const REAL_VALUE_TYPE *,
+extern bool real_arithmetic (REAL_VALUE_TYPE *, int, const REAL_VALUE_TYPE *,
const REAL_VALUE_TYPE *);
/* Compare reals by tree_code. */
diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c
index 91df355b9ac..92567fe3c41 100644
--- a/gcc/simplify-rtx.c
+++ b/gcc/simplify-rtx.c
@@ -1288,12 +1288,13 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
}
else
{
- REAL_VALUE_TYPE f0, f1, value;
+ REAL_VALUE_TYPE f0, f1, value, result;
+ bool inexact;
REAL_VALUE_FROM_CONST_DOUBLE (f0, trueop0);
REAL_VALUE_FROM_CONST_DOUBLE (f1, trueop1);
- f0 = real_value_truncate (mode, f0);
- f1 = real_value_truncate (mode, f1);
+ real_convert (&f0, mode, &f0);
+ real_convert (&f1, mode, &f1);
if (HONOR_SNANS (mode)
&& (REAL_VALUE_ISNAN (f0) || REAL_VALUE_ISNAN (f1)))
@@ -1339,10 +1340,18 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
/* Inf * 0 = NaN plus exception. */
return 0;
- REAL_ARITHMETIC (value, rtx_to_tree_code (code), f0, f1);
+ inexact = real_arithmetic (&value, rtx_to_tree_code (code),
+ &f0, &f1);
+ real_convert (&result, mode, &value);
- value = real_value_truncate (mode, value);
- return CONST_DOUBLE_FROM_REAL_VALUE (value, mode);
+ /* Don't constant fold this floating point operation if the
+ result may dependent upon the run-time rounding mode and
+ flag_rounding_math is set. */
+ if (flag_rounding_math
+ && (inexact || !real_identical (&result, &value)))
+ return NULL_RTX;
+
+ return CONST_DOUBLE_FROM_REAL_VALUE (result, mode);
}
}