aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2003-07-18 00:26:51 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2003-07-18 00:26:51 +0000
commit3e4093b64f2e2623bba32e733e7e8f08efc700ac (patch)
tree3875a0446ee77a593d30fb10e6a14b62fcc0f4ec /gcc/fold-const.c
parent35c77862c921a82a9d2bc4175dc041bd1e99e2bd (diff)
downloadgcc-3e4093b64f2e2623bba32e733e7e8f08efc700ac.zip
gcc-3e4093b64f2e2623bba32e733e7e8f08efc700ac.tar.gz
gcc-3e4093b64f2e2623bba32e733e7e8f08efc700ac.tar.bz2
fold-const.c (const_binop): Avoid performing the FP operation at compile-time...
* fold-const.c (const_binop): Avoid performing the FP operation at compile-time, if either operand is NaN and we honor signaling NaNs, or if we're dividing by zero and either flag_trapping_math is set or the desired mode doesn't support infinities. (fold_initializer): New function to fold an expression ignoring any potential run-time exceptions or traps. * tree.h (fold_initializer): Prototype here. * c-typeck.c (build_binary_op): Move to the end of the file so that intializer_stack is in scope. If constructing an initializer, i.e. when initializer_stack is not NULL, use fold_initializer to fold expressions. * simplify-rtx.c (simplify_binary_operation): Likewise, avoid performing FP operations at compile-time, if they would raise an exception at run-time. From-SVN: r69533
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r--gcc/fold-const.c48
1 files changed, 44 insertions, 4 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 95a68bc..32c145e 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -1228,14 +1228,31 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
if (TREE_CODE (arg1) == REAL_CST)
{
+ enum machine_mode mode;
REAL_VALUE_TYPE d1;
REAL_VALUE_TYPE d2;
REAL_VALUE_TYPE value;
- tree t;
+ tree t, type;
d1 = TREE_REAL_CST (arg1);
d2 = TREE_REAL_CST (arg2);
+ type = TREE_TYPE (arg1);
+ mode = TYPE_MODE (type);
+
+ /* Don't perform operation if we honor signaling NaNs and
+ either operand is a NaN. */
+ if (HONOR_SNANS (mode)
+ && (REAL_VALUE_ISNAN (d1) || REAL_VALUE_ISNAN (d2)))
+ return NULL_TREE;
+
+ /* Don't perform operation if it would raise a division
+ by zero exception. */
+ if (code == RDIV_EXPR
+ && REAL_VALUES_EQUAL (d2, dconst0)
+ && (flag_trapping_math || ! MODE_HAS_INFINITIES (mode)))
+ return NULL_TREE;
+
/* If either operand is a NaN, just return it. Otherwise, set up
for floating-point trap; we return an overflow. */
if (REAL_VALUE_ISNAN (d1))
@@ -1245,9 +1262,7 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
REAL_ARITHMETIC (value, code, d1, d2);
- t = build_real (TREE_TYPE (arg1),
- real_value_truncate (TYPE_MODE (TREE_TYPE (arg1)),
- value));
+ t = build_real (type, real_value_truncate (mode, value));
TREE_OVERFLOW (t)
= (force_fit_type (t, 0)
@@ -7886,6 +7901,31 @@ fold (tree expr)
} /* switch (code) */
}
+/* Perform constant folding and related simplification of intializer
+ expression EXPR. This behaves identically to "fold" but ignores
+ potential run-time traps and exceptions that fold must preserve. */
+
+tree
+fold_initializer (tree expr)
+{
+ int saved_signaling_nans = flag_signaling_nans;
+ int saved_trapping_math = flag_trapping_math;
+ int saved_trapv = flag_trapv;
+ tree result;
+
+ flag_signaling_nans = 0;
+ flag_trapping_math = 0;
+ flag_trapv = 0;
+
+ result = fold (expr);
+
+ flag_signaling_nans = saved_signaling_nans;
+ flag_trapping_math = saved_trapping_math;
+ flag_trapv = saved_trapv;
+
+ return result;
+}
+
/* Determine if first argument is a multiple of second argument. Return 0 if
it is not, or we cannot easily determined it to be.