diff options
author | Roger Sayle <roger@eyesopen.com> | 2003-07-18 00:26:51 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2003-07-18 00:26:51 +0000 |
commit | 3e4093b64f2e2623bba32e733e7e8f08efc700ac (patch) | |
tree | 3875a0446ee77a593d30fb10e6a14b62fcc0f4ec /gcc/fold-const.c | |
parent | 35c77862c921a82a9d2bc4175dc041bd1e99e2bd (diff) | |
download | gcc-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.c | 48 |
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. |