Patchwork [8/9] Extend simple_rhs_p

login
register
mail settings
Submitter zhroma@ispras.ru
Date July 21, 2011, 4:30 p.m.
Message ID <1311265834-2144-9-git-send-email-zhroma@ispras.ru>
Download mbox | patch
Permalink /patch/106101/
State New
Headers show

Comments

zhroma@ispras.ru - July 21, 2011, 4:30 p.m.
This patch adds a multiply-and-add instruction expression to
simple_rhs_p function.  When debugging my sms patches, the following
situation was found.  Imagine a loop, with constant step > 1, where "n"
and "fin" is unknown at compile time.

for (c = n * step + fin; c != fin; c -= step) ...;

c is a pseudo-register and is initialized as one multiply-and-add rtl
instruction before the loop.  In this case, get_simple_loop_desc
function gives a non-null infinite condition which looks like:
(c - fin)%step == 0
It's obviously always true when you try to substitute the initialization
expression. But no substitution is done, because the exression is not
simple_rhs_p.  So, this patch allows get_simple_loop_desc analysis to be
more precise.  How can this influence other optimizations?

2011-07-20  Roman Zhuykov  <zhroma@ispras.ru>
	* loop-iv.c (simple_rhs_p): Support multiply-and-add operations.
---
 gcc/loop-iv.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)

Patch

diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c
index 83d2501..dbb7728 100644
--- a/gcc/loop-iv.c
+++ b/gcc/loop-iv.c
@@ -1340,9 +1340,15 @@  simple_rhs_p (rtx rhs)
     case AND:
       op0 = XEXP (rhs, 0);
       op1 = XEXP (rhs, 1);
-      /* Allow reg OP const and reg OP reg.  */
+      /* Allow op0 to be reg or expression like "reg mult const".
+       * Allow op1 to be reg or const.  */
       if (!(REG_P (op0) && !HARD_REGISTER_P (op0))
-	  && !function_invariant_p (op0))
+	  && !function_invariant_p (op0)
+	  && !(((GET_CODE (op0) == ASHIFT)
+		|| (GET_CODE (op0) == ASHIFTRT)
+		|| (GET_CODE (op0) == LSHIFTRT)
+		|| (GET_CODE (op0) == MULT)
+	       ) && simple_rhs_p (op0)))
 	return false;
       if (!(REG_P (op1) && !HARD_REGISTER_P (op1))
 	  && !function_invariant_p (op1))