diff options
author | Roger Sayle <roger@eyesopen.com> | 2005-12-20 04:17:58 +0000 |
---|---|---|
committer | Roger Sayle <sayle@gcc.gnu.org> | 2005-12-20 04:17:58 +0000 |
commit | c2c22cd6345a8e6f58702c5e406fc78cd33ef959 (patch) | |
tree | 1121e7afb1420aa893aff3d3c880fafde6862df0 | |
parent | ea65cd378bf9c6457a2a400e2f2fef92514d06bb (diff) | |
download | gcc-c2c22cd6345a8e6f58702c5e406fc78cd33ef959.zip gcc-c2c22cd6345a8e6f58702c5e406fc78cd33ef959.tar.gz gcc-c2c22cd6345a8e6f58702c5e406fc78cd33ef959.tar.bz2 |
combine.c (try_combine): Improve splitting of binary operators by taking advantage of reassociative...
* combine.c (try_combine): Improve splitting of binary operators
by taking advantage of reassociative transformations.
From-SVN: r108834
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/combine.c | 67 |
2 files changed, 70 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 69bfe7a..b489083 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2005-12-19 Roger Sayle <roger@eyesopen.com> + + * combine.c (try_combine): Improve splitting of binary operators + by taking advantage of reassociative transformations. + 2005-12-19 Jeff Law <law@redhat.com> * tree-ssa-dom.c (thread_across_edge): Do not use local_fold. diff --git a/gcc/combine.c b/gcc/combine.c index f21a17c..afbf840 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -2527,6 +2527,8 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) rtx newdest = i2dest; enum rtx_code split_code = GET_CODE (*split); enum machine_mode split_mode = GET_MODE (*split); + bool subst_done = false; + newi2pat = NULL_RTX; /* Get NEWDEST as a register in the proper mode. We have already validated that we can do this. */ @@ -2572,8 +2574,69 @@ try_combine (rtx i3, rtx i2, rtx i1, int *new_direct_jump_p) } #endif - newi2pat = gen_rtx_SET (VOIDmode, newdest, *split); - SUBST (*split, newdest); + /* Attempt to split binary operators using arithmetic identities. */ + if (BINARY_P (SET_SRC (newpat)) + && split_mode == GET_MODE (SET_SRC (newpat)) + && ! side_effects_p (SET_SRC (newpat))) + { + rtx setsrc = SET_SRC (newpat); + enum machine_mode mode = GET_MODE (setsrc); + enum rtx_code code = GET_CODE (setsrc); + rtx src_op0 = XEXP (setsrc, 0); + rtx src_op1 = XEXP (setsrc, 1); + + /* Split "X = Y op Y" as "Z = Y; X = Z op Z". */ + if (rtx_equal_p (src_op0, src_op1)) + { + newi2pat = gen_rtx_SET (VOIDmode, newdest, src_op0); + SUBST (XEXP (setsrc, 0), newdest); + SUBST (XEXP (setsrc, 1), newdest); + subst_done = true; + } + /* Split "((P op Q) op R) op S" where op is PLUS or MULT. */ + else if ((code == PLUS || code == MULT) + && GET_CODE (src_op0) == code + && GET_CODE (XEXP (src_op0, 0)) == code + && (INTEGRAL_MODE_P (mode) + || (FLOAT_MODE_P (mode) + && flag_unsafe_math_optimizations))) + { + rtx p = XEXP (XEXP (src_op0, 0), 0); + rtx q = XEXP (XEXP (src_op0, 0), 1); + rtx r = XEXP (src_op0, 1); + rtx s = src_op1; + + /* Split both "((X op Y) op X) op Y" and + "((X op Y) op Y) op X" as "T op T" where T is + "X op Y". */ + if ((rtx_equal_p (p,r) && rtx_equal_p (q,s)) + || (rtx_equal_p (p,s) && rtx_equal_p (q,r))) + { + newi2pat = gen_rtx_SET (VOIDmode, newdest, + XEXP (src_op0, 0)); + SUBST (XEXP (setsrc, 0), newdest); + SUBST (XEXP (setsrc, 1), newdest); + subst_done = true; + } + /* Split "((X op X) op Y) op Y)" as "T op T" where + T is "X op Y". */ + else if (rtx_equal_p (p,q) && rtx_equal_p (r,s)) + { + rtx tmp = simplify_gen_binary (code, mode, p, r); + newi2pat = gen_rtx_SET (VOIDmode, newdest, tmp); + SUBST (XEXP (setsrc, 0), newdest); + SUBST (XEXP (setsrc, 1), newdest); + subst_done = true; + } + } + } + + if (!subst_done) + { + newi2pat = gen_rtx_SET (VOIDmode, newdest, *split); + SUBST (*split, newdest); + } + i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes); /* recog_for_combine might have added CLOBBERs to newi2pat. |