public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 7/7] SMS remove dependence on doloop:  To identify read/write register as loop induction variable
@ 2016-05-05  6:07 Shiva Chen
  2016-05-13 12:33 ` Bernd Schmidt
  0 siblings, 1 reply; 3+ messages in thread
From: Shiva Chen @ 2016-05-05  6:07 UTC (permalink / raw)
  To: GCC Patches, bschmidt, Shiva Chen

[-- Attachment #1: Type: text/plain, Size: 335 bytes --]

Hi,

We use loop induction variable analysis to find count_reg.
Without doloop optimization, count_reg might be a READ_WRITE_REG.

E.g.  while (reg < 0x200) { MEM [++reg:SI] = 5}

READ_WRITE_REG won't identify as loop induction variable
and SMS will skip the loop. We modify loop-iv.c to identify this case.

Thanks,
Shiva

[-- Attachment #2: 0007-To-identify-READ_WRITE_REG-as-loop-induction-variabl.patch --]
[-- Type: application/octet-stream, Size: 7660 bytes --]

From af79a5d049efaa896477ea51fe814fdec7eb414d Mon Sep 17 00:00:00 2001
From: shivac <shivac@marvell.com>
Date: Tue, 3 May 2016 14:07:11 +0800
Subject: [PATCH 7/7] To identify READ_WRITE_REG as loop induction variable

	modified:   loop-iv.c
---
 gcc/loop-iv.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 171 insertions(+), 22 deletions(-)

diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c
index fecaf8f..a7cc1a5 100644
--- a/gcc/loop-iv.c
+++ b/gcc/loop-iv.c
@@ -350,10 +350,6 @@ iv_get_reaching_def (rtx_insn *insn, rtx reg, df_ref *def)
 
   adef = DF_REF_CHAIN (use)->ref;
 
-  /* We do not handle setting only part of the register.  */
-  if (DF_REF_FLAGS (adef) & DF_REF_READ_WRITE)
-    return GRD_INVALID;
-
   def_insn = DF_REF_INSN (adef);
   def_bb = DF_REF_BB (adef);
   use_bb = BLOCK_FOR_INSN (insn);
@@ -622,6 +618,62 @@ iv_shift (struct rtx_iv *iv, rtx mby)
   return true;
 }
 
+/* Return rtx expression in INSN which calculate REG result.  */
+
+static rtx
+get_reg_calculate_expr (rtx_insn *insn, rtx reg)
+{
+  int i;
+  rtx set, pattern, dest;
+  rtx expr = NULL_RTX;
+
+  pattern = PATTERN (insn);
+
+  /* Find REG increment/decrement expr in following pattern
+
+     (parallel
+	    (CC = compare (REG - 1, 0))
+	    (REG = REG - 1))
+   */
+  if (GET_CODE (pattern) == PARALLEL)
+    {
+      for (i = XVECLEN (pattern, 0) - 1; i >= 0; i--)
+	if (GET_CODE (XVECEXP (pattern, 0, i)) == SET)
+	  {
+	    if (SET_DEST (XVECEXP (pattern, 0, i)) == reg)
+	      {
+		pattern = XVECEXP (pattern, 0, i);
+		return SET_SRC (pattern);
+	      }
+	  }
+    }
+
+  set = single_set (insn);
+
+  if (!set)
+    return NULL_RTX;
+
+  dest = SET_DEST (set);
+
+  if (GET_CODE (dest) == ZERO_EXTEND
+      || GET_CODE (dest) == SIGN_EXTEND
+      || GET_CODE (dest) == VEC_DUPLICATE)
+    dest = XEXP(dest, 0);
+
+  if (MEM_P (dest))
+    expr = SET_DEST (set);
+  else
+    {
+      expr = find_reg_equal_equiv_note (insn);
+      if (expr)
+	expr = XEXP (expr, 0);
+      else
+	expr = SET_SRC (set);
+    }
+
+  return expr;
+}
+
 /* The recursive part of get_biv_step.  Gets the value of the single value
    defined by DEF wrto initial value of REG inside loop, in shape described
    at get_biv_step.  */
@@ -632,22 +684,17 @@ get_biv_step_1 (df_ref def, rtx reg,
 		enum iv_extend_code *extend, machine_mode outer_mode,
 		rtx *outer_step)
 {
-  rtx set, rhs, op0 = NULL_RTX, op1 = NULL_RTX;
+  rtx rhs, op0 = NULL_RTX, op1 = NULL_RTX;
   rtx next, nextr;
-  enum rtx_code code;
+  enum rtx_code code, addr_code;
   rtx_insn *insn = DF_REF_INSN (def);
   df_ref next_def;
   enum iv_grd_result res;
 
-  set = single_set (insn);
-  if (!set)
-    return false;
+  rhs = get_reg_calculate_expr (insn, reg);
 
-  rhs = find_reg_equal_equiv_note (insn);
-  if (rhs)
-    rhs = XEXP (rhs, 0);
-  else
-    rhs = SET_SRC (set);
+  if (!rhs)
+    return false;
 
   code = GET_CODE (rhs);
   switch (code)
@@ -700,6 +747,19 @@ get_biv_step_1 (df_ref def, rtx reg,
       next = op0;
       break;
 
+    /* Allow READ_WRITE memory reference register
+       identify as IV.  */
+    case MEM:
+      op0 = XEXP (rhs, 0);
+      addr_code = GET_CODE (op0);
+      if (addr_code != POST_INC
+	  && addr_code != POST_DEC
+	  && addr_code != PRE_INC
+	  && addr_code != PRE_DEC)
+	return false;
+      next = XEXP (op0, 0);
+      break;
+
     default:
       return false;
     }
@@ -777,6 +837,21 @@ get_biv_step_1 (df_ref def, rtx reg,
       *extend = (code == SIGN_EXTEND) ? IV_SIGN_EXTEND : IV_ZERO_EXTEND;
       break;
 
+    /* Get inner_step by mode size for READ_WRITE
+       memory reference register.  */
+    case MEM:
+      gcc_assert (GET_CODE (op0) == POST_INC
+		  || GET_CODE (op0) == POST_DEC
+		  || GET_CODE (op0) == PRE_INC
+		  || GET_CODE (op0) == PRE_DEC);
+
+      if (GET_CODE (op0) == POST_INC
+	  || GET_CODE (op0) == PRE_INC)
+	*inner_step = GEN_INT (GET_MODE_SIZE (GET_MODE (rhs)));
+      else
+	*inner_step = GEN_INT (-GET_MODE_SIZE (GET_MODE (rhs)));
+      break;
+
     default:
       return false;
     }
@@ -936,14 +1011,13 @@ iv_analyze_expr (rtx_insn *insn, rtx rhs, machine_mode mode,
   rtx op0 = NULL_RTX, op1 = NULL_RTX;
   struct rtx_iv iv0, iv1;
   enum rtx_code code = GET_CODE (rhs);
+  enum rtx_code addr_code;
   machine_mode omode = mode;
 
   iv->mode = VOIDmode;
   iv->base = NULL_RTX;
   iv->step = NULL_RTX;
 
-  gcc_assert (GET_MODE (rhs) == mode || GET_MODE (rhs) == VOIDmode);
-
   if (CONSTANT_P (rhs)
       || REG_P (rhs)
       || code == SUBREG)
@@ -995,6 +1069,24 @@ iv_analyze_expr (rtx_insn *insn, rtx rhs, machine_mode mode,
 	return false;
       break;
 
+    case MEM:
+      op0 = XEXP (rhs, 0);
+      omode = GET_MODE (op0);
+      addr_code = GET_CODE (op0);
+
+      if (addr_code != POST_INC
+	  && addr_code != POST_DEC
+	  && addr_code != PRE_INC
+	  && addr_code != PRE_DEC)
+	return false;
+      break;
+    case POST_INC:
+    case POST_DEC:
+    case PRE_INC:
+    case PRE_DEC:
+      op0 = XEXP (rhs, 0);
+      break;
+
     default:
       return false;
     }
@@ -1040,6 +1132,9 @@ iv_analyze_expr (rtx_insn *insn, rtx rhs, machine_mode mode,
 	return false;
       break;
 
+    case MEM:
+      break;
+
     default:
       break;
     }
@@ -1056,6 +1151,8 @@ iv_analyze_def (df_ref def, struct rtx_iv *iv)
   rtx_insn *insn = DF_REF_INSN (def);
   rtx reg = DF_REF_REG (def);
   rtx set, rhs;
+  rtx read_write_reg = NULL_RTX, body = NULL_RTX;
+  rtx src, dest;
 
   if (dump_file)
     {
@@ -1085,15 +1182,53 @@ iv_analyze_def (df_ref def, struct rtx_iv *iv)
   if (!set)
     return false;
 
-  if (!REG_P (SET_DEST (set)))
+  dest = SET_DEST (set);
+  src = SET_SRC (set);
+
+  if (GET_CODE (dest) == UNSPEC
+      || GET_CODE (src) == UNSPEC)
     return false;
 
-  gcc_assert (SET_DEST (set) == reg);
-  rhs = find_reg_equal_equiv_note (insn);
-  if (rhs)
-    rhs = XEXP (rhs, 0);
+  if (GET_CODE (dest) == ZERO_EXTEND
+      || GET_CODE (dest) == SIGN_EXTEND
+      || GET_CODE (dest) == VEC_DUPLICATE)
+    dest = XEXP(dest, 0);
+
+  if (GET_CODE (src) == ZERO_EXTEND
+      || GET_CODE (src) == SIGN_EXTEND
+      || GET_CODE (src) == VEC_DUPLICATE)
+    src = XEXP(src, 0);
+
+  if (MEM_P (dest))
+    {
+      body = XEXP(dest, 0);
+      rhs = SET_DEST (set);
+    }
   else
-    rhs = SET_SRC (set);
+    {
+      if (MEM_P (src))
+	body = XEXP(src, 0);
+
+      rhs = find_reg_equal_equiv_note (insn);
+      if (rhs)
+	rhs = XEXP (rhs, 0);
+      else
+	rhs = SET_SRC (set);
+    }
+
+  if (body != NULL_RTX)
+    {
+      /* Should we handle POST_MODIFY?  */
+       if (GET_CODE (body) == POST_INC
+	  || GET_CODE (body) == POST_DEC
+	  || GET_CODE (body) == PRE_INC
+	  || GET_CODE (body) == PRE_DEC)
+	read_write_reg = XEXP(body, 0);
+      else
+	return false;
+    }
+
+  gcc_assert (SET_DEST (set) == reg || read_write_reg == reg);
 
   iv_analyze_expr (insn, rhs, GET_MODE (reg), iv);
   record_iv (def, iv);
@@ -2354,6 +2489,20 @@ iv_number_of_iterations (struct loop *loop, rtx_insn *insn, rtx condition,
     goto fail;
 
   op0 = XEXP (condition, 0);
+
+  /* We would use loop induction variable analysis
+     to get loop iteration count in SMS pass
+     which should work with/without doloop pass
+     active or not.
+
+     With doloop pass enabled, doloop pass would
+     generate pattern as (ne (REG - 1), 0) and
+     we recognize it by following code.  */
+  if (GET_CODE (op0) == PLUS
+      && CONST_INT_P (XEXP (op0, 1))
+      && REG_P (XEXP (op0, 0)))
+    op0 = XEXP (op0, 0);
+
   if (!iv_analyze (insn, op0, &iv0))
     goto fail;
   if (iv0.extend_mode == VOIDmode)
-- 
2.5.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH 7/7] SMS remove dependence on doloop: To identify read/write register as loop induction variable
  2016-05-05  6:07 [PATCH 7/7] SMS remove dependence on doloop: To identify read/write register as loop induction variable Shiva Chen
@ 2016-05-13 12:33 ` Bernd Schmidt
  2016-05-18  9:50   ` Shiva Chen
  0 siblings, 1 reply; 3+ messages in thread
From: Bernd Schmidt @ 2016-05-13 12:33 UTC (permalink / raw)
  To: Shiva Chen, GCC Patches, Shiva Chen

On 05/05/2016 08:03 AM, Shiva Chen wrote:
>
> -  /* We do not handle setting only part of the register.  */
> -  if (DF_REF_FLAGS (adef) & DF_REF_READ_WRITE)
> -    return GRD_INVALID;
> -

This isn't right, at least not without other changes. This prevents 
using references where the register is set as part of a ZERO_EXTRACT or 
STRICT_LOW_PART, and you seem not to handle such cases in the new code.

> +/* Return rtx expression in INSN which calculate REG result.  */
> +
> +static rtx
> +get_reg_calculate_expr (rtx_insn *insn, rtx reg)

Hmm, that comment seems to be not quite accurate, though. The function 
may return either the source of a SET that sets the register, or a MEM 
(where it's not indicated whether the MEM is the source or destination 
of the set, or whether the reg is set in the insn or is part of the address.

I think this interface is pretty bad. I think what you should do is 
check in the caller whether the def is of READ_WRITE type. If so, do a 
FOR_EACH_SUBRTX thing to look for a memory reference containing an 
autoinc expression, otherwise this new function (without the MEM parts) 
could be used. That'll also solve the problem above with the loss of 
DF_REF_READ_WRITE checking.

The walk to find the appropriate MEM would be in a separate function, 
used in the several places that

> +  /* Find REG increment/decrement expr in following pattern
> +
> +     (parallel
> +	    (CC = compare (REG - 1, 0))
> +	    (REG = REG - 1))
> +   */

Comment formatting, "*/" doesn't go on its own line. I think it's best 
not to quote a pattern here since you're not actually looking for it.  A 
better comment would be "For identifying ivs, we can actually ignore any 
other SETs occurring in parallel, so look for one with the correct 
SET_DEST."  I'm not actually sure, however, whether this is valid. It 
would depend on how this information is used later on, and what 
transformation other passes would want to do on the ivs.  Come to think 
of it, this is also true for autoinc ivs, but I guess these would only 
appear when run late as analysis for modulo-sched, so I guess that would 
be OK?

> @@ -2354,6 +2489,20 @@ iv_number_of_iterations (struct loop *loop, rtx_insn *insn, rtx condition,
>       goto fail;
>
>     op0 = XEXP (condition, 0);
> +
> +  /* We would use loop induction variable analysis
> +     to get loop iteration count in SMS pass
> +     which should work with/without doloop pass
> +     active or not.
> +
> +     With doloop pass enabled, doloop pass would
> +     generate pattern as (ne (REG - 1), 0) and
> +     we recognize it by following code.  */
> +  if (GET_CODE (op0) == PLUS
> +      && CONST_INT_P (XEXP (op0, 1))
> +      && REG_P (XEXP (op0, 0)))
> +    op0 = XEXP (op0, 0);

That really looks somewhat suspicious, and I can't really tell whether 
it's right. My instinct says no; how can you just drop a constant on the 
floor?


Bernd

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH 7/7] SMS remove dependence on doloop: To identify read/write register as loop induction variable
  2016-05-13 12:33 ` Bernd Schmidt
@ 2016-05-18  9:50   ` Shiva Chen
  0 siblings, 0 replies; 3+ messages in thread
From: Shiva Chen @ 2016-05-18  9:50 UTC (permalink / raw)
  To: Bernd Schmidt; +Cc: Shiva Chen, GCC Patches

[-- Attachment #1: Type: text/plain, Size: 3414 bytes --]

Hi, Bernd

2016-05-13 20:33 GMT+08:00 Bernd Schmidt <bschmidt@redhat.com>:
> On 05/05/2016 08:03 AM, Shiva Chen wrote:
>>
>>
>> -  /* We do not handle setting only part of the register.  */
>> -  if (DF_REF_FLAGS (adef) & DF_REF_READ_WRITE)
>> -    return GRD_INVALID;
>> -
> This isn't right, at least not without other changes. This prevents using
> references where the register is set as part of a ZERO_EXTRACT or
> STRICT_LOW_PART, and you seem not to handle such cases in the new code.
>
> I think this interface is pretty bad. I think what you should do is check in
> the caller whether the def is of READ_WRITE type. If so, do a
> FOR_EACH_SUBRTX thing to look for a memory reference containing an autoinc
> expression, otherwise this new function (without the MEM parts) could be
> used. That'll also solve the problem above with the loss of
> DF_REF_READ_WRITE checking.
>
> The walk to find the appropriate MEM would be in a separate function, used
> in the several places that

Yes, the interface is bad.
I split the function into read_write_reg_mem and get_reg_calculate_expr.
The function read_write_reg_mem try to find autoinc in memory
reference by FOR_EACH_SUBRTX if the def is READ_WRITE type which fix
the lost of checking as your suggestion.

>> +  /* Find REG increment/decrement expr in following pattern
>> +
>> +     (parallel
>> +           (CC = compare (REG - 1, 0))
>> +           (REG = REG - 1))
>> +   */
>
>
> Comment formatting, "*/" doesn't go on its own line. I think it's best not
> to quote a pattern here since you're not actually looking for it.  A better
> comment would be "For identifying ivs, we can actually ignore any other SETs
> occurring in parallel, so look for one with the correct SET_DEST."  I'm not
> actually sure, however, whether this is valid. It would depend on how this
> information is used later on, and what transformation other passes would
> want to do on the ivs.  Come to think of it, this is also true for autoinc
> ivs, but I guess these would only appear when run late as analysis for
> modulo-sched, so I guess that would be OK?
Thanks for the correctness of the comment.

>> @@ -2354,6 +2489,20 @@ iv_number_of_iterations (struct loop *loop,
>> rtx_insn *insn, rtx condition,
>>       goto fail;
>>
>>     op0 = XEXP (condition, 0);
>> +
>> +  /* We would use loop induction variable analysis
>> +     to get loop iteration count in SMS pass
>> +     which should work with/without doloop pass
>> +     active or not.
>> +
>> +     With doloop pass enabled, doloop pass would
>> +     generate pattern as (ne (REG - 1), 0) and
>> +     we recognize it by following code.  */
>> +  if (GET_CODE (op0) == PLUS
>> +      && CONST_INT_P (XEXP (op0, 1))
>> +      && REG_P (XEXP (op0, 0)))
>> +    op0 = XEXP (op0, 0);
>
>
> That really looks somewhat suspicious, and I can't really tell whether it's
> right. My instinct says no; how can you just drop a constant on the floor?

I think your instinct is right.
op0 and op1 split from loop end condition will through to iv_analyze
and get iv0 and iv1.
The following code will use iv0 and iv1 to estimate loop iteration count.
I think the correct think to do is transfer  (ne (REG - 1), 0)  to (ne
REG, 1) which means setting op0 = REG, op1 = 1.
Then iv1.base could set correctly by iv_analyze.

Thanks for your comments, they're truly helpful.
please correct me if i still missing something.

Shiva

[-- Attachment #2: 0007-To-identify-READ_WRITE_REG-as-loop-induction-variable-v1.patch --]
[-- Type: application/octet-stream, Size: 8480 bytes --]

From d73ebecc7b78aab160af96b9738b81241e8eecd8 Mon Sep 17 00:00:00 2001
From: shivac <shivac@marvell.com>
Date: Tue, 3 May 2016 14:07:11 +0800
Subject: [PATCH 7/7] To identify READ_WRITE_REG as loop induction variable

	modified:   loop-iv.c
---
 gcc/loop-iv.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 186 insertions(+), 24 deletions(-)

diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c
index fecaf8f..10d9fed 100644
--- a/gcc/loop-iv.c
+++ b/gcc/loop-iv.c
@@ -350,10 +350,6 @@ iv_get_reaching_def (rtx_insn *insn, rtx reg, df_ref *def)
 
   adef = DF_REF_CHAIN (use)->ref;
 
-  /* We do not handle setting only part of the register.  */
-  if (DF_REF_FLAGS (adef) & DF_REF_READ_WRITE)
-    return GRD_INVALID;
-
   def_insn = DF_REF_INSN (adef);
   def_bb = DF_REF_BB (adef);
   use_bb = BLOCK_FOR_INSN (insn);
@@ -622,6 +618,87 @@ iv_shift (struct rtx_iv *iv, rtx mby)
   return true;
 }
 
+/* Return memory rtx if the REG is a read/write register
+   for memory reference in INSN.  */
+
+static rtx
+read_write_reg_mem (df_ref def, rtx_insn *insn)
+{
+  rtx reg = DF_REF_REG (def);
+  subrtx_var_iterator::array_type array;
+
+  if (!(DF_REF_FLAGS (def) & DF_REF_READ_WRITE))
+    return NULL_RTX;
+
+  FOR_EACH_SUBRTX_VAR (iter, array, PATTERN (insn), ALL)
+    {
+      rtx x = *iter;
+      if (GET_CODE (x) == MEM)
+	{
+	  enum rtx_code addr_code = GET_CODE (XEXP (x, 0));
+	  if (addr_code == POST_INC
+	      || addr_code == POST_DEC
+	      || addr_code == PRE_INC
+	      || addr_code == PRE_DEC)
+	    {
+	      if (rtx_equal_p (reg, XEXP (XEXP (x, 0), 0)))
+		return x;
+	    }
+	  if (addr_code == POST_MODIFY
+	      || addr_code == PRE_MODIFY)
+	    {
+	      rtx modify = XEXP (x, 0);
+	      if (rtx_equal_p (reg, XEXP (modify, 0))
+		  && rtx_equal_p (reg, XEXP (XEXP (modify, 1), 0))
+		  && CONST_INT_P (XEXP (XEXP (modify, 1), 1)))
+		return x;
+	    }
+	}
+    }
+  return NULL_RTX;
+}
+
+/* Return rtx expression in INSN which calculate REG result.  */
+
+static rtx
+get_reg_calculate_expr (rtx_insn *insn, rtx reg)
+{
+  int i;
+  rtx set, pattern, expr;
+
+  pattern = PATTERN (insn);
+
+  /* For identifying ivs, we can actually ignore any other
+     SETs occurring in parallel, so look for one with the
+     correct SET_DEST.  */
+  if (GET_CODE (pattern) == PARALLEL)
+    {
+      for (i = XVECLEN (pattern, 0) - 1; i >= 0; i--)
+	if (GET_CODE (XVECEXP (pattern, 0, i)) == SET)
+	  {
+	    if (SET_DEST (XVECEXP (pattern, 0, i)) == reg)
+	      {
+		pattern = XVECEXP (pattern, 0, i);
+		return SET_SRC (pattern);
+	      }
+	  }
+    }
+
+  set = single_set (insn);
+
+  if (!set)
+    return NULL_RTX;
+
+  expr = find_reg_equal_equiv_note (insn);
+
+  if (expr)
+    expr = XEXP (expr, 0);
+  else
+    expr = SET_SRC (set);
+
+  return expr;
+}
+
 /* The recursive part of get_biv_step.  Gets the value of the single value
    defined by DEF wrto initial value of REG inside loop, in shape described
    at get_biv_step.  */
@@ -632,22 +709,20 @@ get_biv_step_1 (df_ref def, rtx reg,
 		enum iv_extend_code *extend, machine_mode outer_mode,
 		rtx *outer_step)
 {
-  rtx set, rhs, op0 = NULL_RTX, op1 = NULL_RTX;
+  rtx rhs, op0 = NULL_RTX, op1 = NULL_RTX;
   rtx next, nextr;
-  enum rtx_code code;
+  enum rtx_code code, addr_code;
   rtx_insn *insn = DF_REF_INSN (def);
   df_ref next_def;
   enum iv_grd_result res;
 
-  set = single_set (insn);
-  if (!set)
-    return false;
+  rhs = read_write_reg_mem (def, insn);
 
-  rhs = find_reg_equal_equiv_note (insn);
-  if (rhs)
-    rhs = XEXP (rhs, 0);
-  else
-    rhs = SET_SRC (set);
+  if (!rhs)
+    rhs = get_reg_calculate_expr (insn, reg);
+
+  if (!rhs)
+    return false;
 
   code = GET_CODE (rhs);
   switch (code)
@@ -700,6 +775,21 @@ get_biv_step_1 (df_ref def, rtx reg,
       next = op0;
       break;
 
+    /* Allow READ_WRITE memory reference register
+       identify as IV.  */
+    case MEM:
+      op0 = XEXP (rhs, 0);
+      addr_code = GET_CODE (op0);
+      if (addr_code != POST_INC
+	  && addr_code != POST_DEC
+	  && addr_code != PRE_INC
+	  && addr_code != PRE_DEC
+	  && addr_code != PRE_MODIFY
+	  && addr_code != POST_MODIFY)
+	return false;
+      next = XEXP (op0, 0);
+      break;
+
     default:
       return false;
     }
@@ -777,6 +867,26 @@ get_biv_step_1 (df_ref def, rtx reg,
       *extend = (code == SIGN_EXTEND) ? IV_SIGN_EXTEND : IV_ZERO_EXTEND;
       break;
 
+    /* Get inner_step by mode size for READ_WRITE
+       memory reference register.  */
+    case MEM:
+      gcc_assert (GET_CODE (op0) == POST_INC
+		  || GET_CODE (op0) == POST_DEC
+		  || GET_CODE (op0) == PRE_INC
+		  || GET_CODE (op0) == PRE_DEC
+		  || GET_CODE (op0) == PRE_MODIFY
+		  || GET_CODE (op0) == POST_MODIFY);
+
+      if (GET_CODE (op0) == POST_INC
+	  || GET_CODE (op0) == PRE_INC)
+	*inner_step = GEN_INT (GET_MODE_SIZE (GET_MODE (rhs)));
+      else if (GET_CODE (op0) == POST_DEC
+	       || GET_CODE (op0) == PRE_DEC)
+	*inner_step = GEN_INT (-GET_MODE_SIZE (GET_MODE (rhs)));
+      else
+	*inner_step = XEXP (XEXP (op0, 1), 1);
+      break;
+
     default:
       return false;
     }
@@ -936,14 +1046,13 @@ iv_analyze_expr (rtx_insn *insn, rtx rhs, machine_mode mode,
   rtx op0 = NULL_RTX, op1 = NULL_RTX;
   struct rtx_iv iv0, iv1;
   enum rtx_code code = GET_CODE (rhs);
+  enum rtx_code addr_code;
   machine_mode omode = mode;
 
   iv->mode = VOIDmode;
   iv->base = NULL_RTX;
   iv->step = NULL_RTX;
 
-  gcc_assert (GET_MODE (rhs) == mode || GET_MODE (rhs) == VOIDmode);
-
   if (CONSTANT_P (rhs)
       || REG_P (rhs)
       || code == SUBREG)
@@ -995,6 +1104,33 @@ iv_analyze_expr (rtx_insn *insn, rtx rhs, machine_mode mode,
 	return false;
       break;
 
+    case MEM:
+      op0 = XEXP (rhs, 0);
+      omode = GET_MODE (op0);
+      addr_code = GET_CODE (op0);
+
+      if (addr_code != POST_INC
+	  && addr_code != POST_DEC
+	  && addr_code != PRE_INC
+	  && addr_code != PRE_DEC
+	  && addr_code != PRE_MODIFY
+	  && addr_code != POST_MODIFY)
+	return false;
+      break;
+
+    case POST_INC:
+    case POST_DEC:
+    case PRE_INC:
+    case PRE_DEC:
+      op0 = XEXP (rhs, 0);
+      break;
+
+    case PRE_MODIFY:
+    case POST_MODIFY:
+      op0 = XEXP (rhs, 0);
+      op1 = XEXP (rhs, 1);
+      break;
+
     default:
       return false;
     }
@@ -1040,6 +1176,9 @@ iv_analyze_expr (rtx_insn *insn, rtx rhs, machine_mode mode,
 	return false;
       break;
 
+    case MEM:
+      break;
+
     default:
       break;
     }
@@ -1085,15 +1224,13 @@ iv_analyze_def (df_ref def, struct rtx_iv *iv)
   if (!set)
     return false;
 
-  if (!REG_P (SET_DEST (set)))
-    return false;
+  rhs = read_write_reg_mem (def, insn);
 
-  gcc_assert (SET_DEST (set) == reg);
-  rhs = find_reg_equal_equiv_note (insn);
-  if (rhs)
-    rhs = XEXP (rhs, 0);
-  else
-    rhs = SET_SRC (set);
+  if (!rhs)
+    rhs = get_reg_calculate_expr (insn, reg);
+
+  if (!rhs)
+    return false;
 
   iv_analyze_expr (insn, rhs, GET_MODE (reg), iv);
   record_iv (def, iv);
@@ -2314,6 +2451,7 @@ iv_number_of_iterations (struct loop *loop, rtx_insn *insn, rtx condition,
 			 struct niter_desc *desc)
 {
   rtx op0, op1, delta, step, bound, may_xform, tmp, tmp0, tmp1;
+  rtx op0_const = NULL_RTX;
   struct rtx_iv iv0, iv1;
   rtx assumption, may_not_xform;
   enum rtx_code cond;
@@ -2354,12 +2492,36 @@ iv_number_of_iterations (struct loop *loop, rtx_insn *insn, rtx condition,
     goto fail;
 
   op0 = XEXP (condition, 0);
+
+  /* We would use loop induction variable analysis
+     to get loop iteration count in SMS pass
+     which should work with/without doloop pass
+     active or not.
+
+     With doloop pass enabled, doloop pass would
+     generate pattern as (ne (REG - 1), 0).
+     we recognize it by following code
+     and setting op0 = REG, op1 = 1.  */
+  if (GET_CODE (op0) == PLUS
+      && CONST_INT_P (XEXP (op0, 1))
+      && REG_P (XEXP (op0, 0)))
+    {
+      op0_const = XEXP (op0, 1);
+      op0 = XEXP (op0, 0);
+    }
+
   if (!iv_analyze (insn, op0, &iv0))
     goto fail;
   if (iv0.extend_mode == VOIDmode)
     iv0.mode = iv0.extend_mode = mode;
 
   op1 = XEXP (condition, 1);
+
+  /* Transfer constant in (ne (REG - 1), 0) to (ne (REG), 1)
+     op1 = 0 - (-1) = 1.  */
+  if (CONST_INT_P (op1) && op0_const)
+    op1 = GEN_INT (INTVAL (op1) - INTVAL (op0_const));
+
   if (!iv_analyze (insn, op1, &iv1))
     goto fail;
   if (iv1.extend_mode == VOIDmode)
-- 
2.5.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2016-05-18  9:50 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-05-05  6:07 [PATCH 7/7] SMS remove dependence on doloop: To identify read/write register as loop induction variable Shiva Chen
2016-05-13 12:33 ` Bernd Schmidt
2016-05-18  9:50   ` Shiva Chen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).