From: Roger Sayle Date: Tue, 20 Dec 2005 04:17:58 +0000 (+0000) Subject: combine.c (try_combine): Improve splitting of binary operators by taking advantage... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c2c22cd6345a8e6f58702c5e406fc78cd33ef959;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 69bfe7ada7c..b4890837d2c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2005-12-19 Roger Sayle + + * combine.c (try_combine): Improve splitting of binary operators + by taking advantage of reassociative transformations. + 2005-12-19 Jeff Law * tree-ssa-dom.c (thread_across_edge): Do not use local_fold. diff --git a/gcc/combine.c b/gcc/combine.c index f21a17cd4d5..afbf840127a 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.