diff options
author | Roger Sayle <roger@eyesopen.com> | 2003-08-17 19:24:09 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2003-08-17 19:24:09 +0000 |
commit | dd61aa98caa43a54970c2a4eecf9c4e3f325d14e (patch) | |
tree | 2aba6d2eebdcd078750a157d135eb00b220790dd | |
parent | fde46628fa4b368217a182e8885475fe5279cc2e (diff) | |
download | gcc-dd61aa98caa43a54970c2a4eecf9c4e3f325d14e.zip gcc-dd61aa98caa43a54970c2a4eecf9c4e3f325d14e.tar.gz gcc-dd61aa98caa43a54970c2a4eecf9c4e3f325d14e.tar.bz2 |
simplify-rtx.c (associative_constant_p): New function to test whether an RTX expression is an immediate constant.
* simplify-rtx.c (associative_constant_p): New function to test
whether an RTX expression is an immediate constant.
(simplify_associative_operation): New function to perform some
reassociation optimizations of associative binary expressions.
(simplify_binary_operation): Use simplify_associative_operation
to simplify PLUS, MULT, AND, IOR, XOR, SMIN, SMAX, UMIN and UMAX.
Floating point expressions are only reassociated when unsafe
math optimizations are permitted.
From-SVN: r70521
-rw-r--r-- | gcc/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/simplify-rtx.c | 124 |
2 files changed, 129 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 21a69b2..a0055d8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +2003-08-17 Roger Sayle <roger@eyesopen.com> + + * simplify-rtx.c (associative_constant_p): New function to test + whether an RTX expression is an immediate constant. + (simplify_associative_operation): New function to perform some + reassociation optimizations of associative binary expressions. + (simplify_binary_operation): Use simplify_associative_operation + to simplify PLUS, MULT, AND, IOR, XOR, SMIN, SMAX, UMIN and UMAX. + Floating point expressions are only reassociated when unsafe + math optimizations are permitted. + 2003-08-17 Andreas Jaeger <aj@suse.de> * config/alpha/alpha.md: Remove usage of PARAMS. diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index ab442fa..a5903ad 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -53,6 +53,9 @@ static rtx neg_const_int (enum machine_mode, rtx); static int simplify_plus_minus_op_data_cmp (const void *, const void *); static rtx simplify_plus_minus (enum rtx_code, enum machine_mode, rtx, rtx, int); +static bool associative_constant_p (rtx); +static rtx simplify_associative_operation (enum rtx_code, enum machine_mode, + rtx, rtx); /* Negate a CONST_INT rtx, truncating (because a conversion from a maximally negative number can overflow). */ @@ -854,6 +857,72 @@ simplify_unary_operation (enum rtx_code code, enum machine_mode mode, } } +/* Subroutine of simplify_associative_operation. Return true if rtx OP + is a suitable integer or floating point immediate constant. */ +static bool +associative_constant_p (rtx op) +{ + if (GET_CODE (op) == CONST_INT + || GET_CODE (op) == CONST_DOUBLE) + return true; + op = avoid_constant_pool_reference (op); + return GET_CODE (op) == CONST_INT + || GET_CODE (op) == CONST_DOUBLE; +} + +/* Subroutine of simplify_binary_operation to simplify an associative + binary operation CODE with result mode MODE, operating on OP0 and OP1. + Return 0 if no simplification is possible. */ +static rtx +simplify_associative_operation (enum rtx_code code, enum machine_mode mode, + rtx op0, rtx op1) +{ + rtx tem; + + /* Simplify (x op c1) op c2 as x op (c1 op c2). */ + if (GET_CODE (op0) == code + && associative_constant_p (op1) + && associative_constant_p (XEXP (op0, 1))) + { + tem = simplify_binary_operation (code, mode, XEXP (op0, 1), op1); + if (! tem) + return tem; + return simplify_gen_binary (code, mode, XEXP (op0, 0), tem); + } + + /* Simplify (x op c1) op (y op c2) as (x op y) op (c1 op c2). */ + if (GET_CODE (op0) == code + && GET_CODE (op1) == code + && associative_constant_p (XEXP (op0, 1)) + && associative_constant_p (XEXP (op1, 1))) + { + rtx c = simplify_binary_operation (code, mode, + XEXP (op0, 1), XEXP (op1, 1)); + if (! c) + return 0; + tem = simplify_gen_binary (code, mode, XEXP (op0, 0), XEXP (op1, 0)); + return simplify_gen_binary (code, mode, tem, c); + } + + /* Canonicalize (x op c) op y as (x op y) op c. */ + if (GET_CODE (op0) == code + && associative_constant_p (XEXP (op0, 1))) + { + tem = simplify_gen_binary (code, mode, XEXP (op0, 0), op1); + return simplify_gen_binary (code, mode, tem, XEXP (op0, 1)); + } + + /* Canonicalize x op (y op c) as (x op y) op c. */ + if (GET_CODE (op1) == code + && associative_constant_p (XEXP (op1, 1))) + { + tem = simplify_gen_binary (code, mode, op0, XEXP (op1, 0)); + return simplify_gen_binary (code, mode, tem, XEXP (op1, 1)); + } + + return 0; +} + /* Simplify a binary operation CODE with result mode MODE, operating on OP0 and OP1. Return 0 if no simplification is possible. @@ -1179,6 +1248,16 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode, && GET_CODE (XEXP (op1, 0)) == PLUS)) && (tem = simplify_plus_minus (code, mode, op0, op1, 0)) != 0) return tem; + + /* Reassociate floating point addition only when the user + specifies unsafe math optimizations. */ + if (FLOAT_MODE_P (mode) + && flag_unsafe_math_optimizations) + { + tem = simplify_associative_operation (code, mode, op0, op1); + if (tem) + return tem; + } break; case COMPARE: @@ -1388,6 +1467,16 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode, if (REAL_VALUES_EQUAL (d, dconstm1)) return simplify_gen_unary (NEG, mode, op0, mode); } + + /* Reassociate multiplication, but for floating point MULTs + only when the user specifies unsafe math optimizations. */ + if (! FLOAT_MODE_P (mode) + || flag_unsafe_math_optimizations) + { + tem = simplify_associative_operation (code, mode, op0, op1); + if (tem) + return tem; + } break; case IOR: @@ -1405,6 +1494,9 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode, && ! side_effects_p (op0) && GET_MODE_CLASS (mode) != MODE_CC) return constm1_rtx; + tem = simplify_associative_operation (code, mode, op0, op1); + if (tem) + return tem; break; case XOR: @@ -1417,6 +1509,9 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode, if (trueop0 == trueop1 && ! side_effects_p (op0) && GET_MODE_CLASS (mode) != MODE_CC) return const0_rtx; + tem = simplify_associative_operation (code, mode, op0, op1); + if (tem) + return tem; break; case AND: @@ -1435,6 +1530,9 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode, && ! side_effects_p (op0) && GET_MODE_CLASS (mode) != MODE_CC) return const0_rtx; + tem = simplify_associative_operation (code, mode, op0, op1); + if (tem) + return tem; break; case UDIV: @@ -1524,36 +1622,50 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode, break; case SMIN: - if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (trueop1) == CONST_INT + if (width <= HOST_BITS_PER_WIDE_INT + && GET_CODE (trueop1) == CONST_INT && INTVAL (trueop1) == (HOST_WIDE_INT) 1 << (width -1) && ! side_effects_p (op0)) return op1; - else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) + if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) return op0; + tem = simplify_associative_operation (code, mode, op0, op1); + if (tem) + return tem; break; case SMAX: - if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (trueop1) == CONST_INT + if (width <= HOST_BITS_PER_WIDE_INT + && GET_CODE (trueop1) == CONST_INT && ((unsigned HOST_WIDE_INT) INTVAL (trueop1) == (unsigned HOST_WIDE_INT) GET_MODE_MASK (mode) >> 1) && ! side_effects_p (op0)) return op1; - else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) + if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) return op0; + tem = simplify_associative_operation (code, mode, op0, op1); + if (tem) + return tem; break; case UMIN: if (trueop1 == const0_rtx && ! side_effects_p (op0)) return op1; - else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) + if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) return op0; + tem = simplify_associative_operation (code, mode, op0, op1); + if (tem) + return tem; break; case UMAX: if (trueop1 == constm1_rtx && ! side_effects_p (op0)) return op1; - else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) + if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)) return op0; + tem = simplify_associative_operation (code, mode, op0, op1); + if (tem) + return tem; break; case SS_PLUS: |