re PR rtl-optimization/32283 (Missed induction variable optimization)
authorZdenek Dvorak <ook@ucw.cz>
Thu, 20 Nov 2008 08:05:12 +0000 (09:05 +0100)
committerZdenek Dvorak <rakdver@gcc.gnu.org>
Thu, 20 Nov 2008 08:05:12 +0000 (08:05 +0000)
PR rtl-optimization/32283
* tree-ssa-loop-niter.c (scev_probably_wraps_p): Use type of the base
of the induction variable to decide whether it may wrap.
* tree-ssa-loop-ivopts.c (rewrite_use_compare): Emit the initialization
of the bound before the loop.
* simplify-rtx.c (simplify_binary_operation_1): Add two simplifications
regarding AND.
(simplify_plus_minus): Only fail if no simplification is possible.
* loop-iv.c (simple_rhs_p): Consider reg + reg and reg << cst simple.

From-SVN: r142035

gcc/ChangeLog
gcc/loop-iv.c
gcc/simplify-rtx.c
gcc/tree-ssa-loop-ivopts.c
gcc/tree-ssa-loop-niter.c

index 48757a5..8731154 100644 (file)
@@ -1,3 +1,15 @@
+2008-11-19  Zdenek Dvorak  <ook@ucw.cz>
+
+       PR rtl-optimization/32283
+       * tree-ssa-loop-niter.c (scev_probably_wraps_p): Use type of the base
+       of the induction variable to decide whether it may wrap.
+       * tree-ssa-loop-ivopts.c (rewrite_use_compare): Emit the initialization
+       of the bound before the loop.
+       * simplify-rtx.c (simplify_binary_operation_1): Add two simplifications
+       regarding AND.
+       (simplify_plus_minus): Only fail if no simplification is possible.
+       * loop-iv.c (simple_rhs_p): Consider reg + reg and reg << cst simple.
+
 2008-11-20  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/36631
index 2523963..3723dbd 100644 (file)
@@ -1337,13 +1337,26 @@ simple_rhs_p (rtx rhs)
     case MINUS:
       op0 = XEXP (rhs, 0);
       op1 = XEXP (rhs, 1);
-      /* Allow reg + const sets only.  */
-      if (REG_P (op0) && !HARD_REGISTER_P (op0) && CONSTANT_P (op1))
-       return true;
-      if (REG_P (op1) && !HARD_REGISTER_P (op1) && CONSTANT_P (op0))
-       return true;
+      /* Allow reg + const and reg + reg.  */
+      if (!(REG_P (op0) && !HARD_REGISTER_P (op0))
+         && !CONSTANT_P (op0))
+       return false;
+      if (!(REG_P (op1) && !HARD_REGISTER_P (op1))
+         && !CONSTANT_P (op1))
+       return false;
 
-      return false;
+      return true;
+
+    case ASHIFT:
+      op0 = XEXP (rhs, 0);
+      op1 = XEXP (rhs, 1);
+      /* Allow reg << const.  */
+      if (!(REG_P (op0) && !HARD_REGISTER_P (op0)))
+       return false;
+      if (!CONSTANT_P (op1))
+       return false;
+
+      return true;
 
     default:
       return false;
index dd91e12..16d0d48 100644 (file)
@@ -2304,12 +2304,19 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
     case AND:
       if (trueop1 == CONST0_RTX (mode) && ! side_effects_p (op0))
        return trueop1;
-      /* If we are turning off bits already known off in OP0, we need
-        not do an AND.  */
       if (GET_CODE (trueop1) == CONST_INT
-         && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
-         && (nonzero_bits (trueop0, mode) & ~INTVAL (trueop1)) == 0)
-       return op0;
+         && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
+       {
+         HOST_WIDE_INT nzop0 = nonzero_bits (trueop0, mode);
+         HOST_WIDE_INT val1 = INTVAL (trueop1);
+         /* If we are turning off bits already known off in OP0, we need
+            not do an AND.  */
+         if ((nzop0 & ~val1) == 0)
+           return op0;
+         /* If we are clearing all the nonzero bits, the result is zero.  */
+         if ((val1 & nzop0) == 0 && !side_effects_p (op0))
+           return CONST0_RTX (mode);
+       }
       if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0)
          && GET_MODE_CLASS (mode) != MODE_CC)
        return op0;
@@ -2391,7 +2398,9 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
         ((A & N) + B) & M -> (A + B) & M
         Similarly if (N & M) == 0,
         ((A | N) + B) & M -> (A + B) & M
-        and for - instead of + and/or ^ instead of |.  */
+        and for - instead of + and/or ^ instead of |.
+         Also, if (N & M) == 0, then
+        (A +- N) & M -> A & M.  */
       if (GET_CODE (trueop1) == CONST_INT
          && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
          && ~INTVAL (trueop1)
@@ -2404,6 +2413,10 @@ simplify_binary_operation_1 (enum rtx_code code, enum machine_mode mode,
          pmop[0] = XEXP (op0, 0);
          pmop[1] = XEXP (op0, 1);
 
+         if (GET_CODE (pmop[1]) == CONST_INT
+             && (INTVAL (pmop[1]) & INTVAL (trueop1)) == 0)
+           return simplify_gen_binary (AND, mode, pmop[0], op1);
+
          for (which = 0; which < 2; which++)
            {
              tem = pmop[which];
@@ -3591,10 +3604,6 @@ simplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0,
           ops[j + 1] = save;
         }
 
-      /* This is only useful the first time through.  */
-      if (!canonicalized)
-        return NULL_RTX;
-
       changed = 0;
       for (i = n_ops - 1; i > 0; i--)
        for (j = i - 1; j >= 0; j--)
@@ -3650,10 +3659,15 @@ simplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0,
                    ops[i].neg = lneg;
                    ops[j].op = NULL_RTX;
                    changed = 1;
+                   canonicalized = 1;
                  }
              }
          }
 
+      /* If nothing changed, fail.  */
+      if (!canonicalized)
+        return NULL_RTX;
+
       /* Pack all the operands to the lower-numbered entries.  */
       for (i = 0, j = 0; j < n_ops; j++)
         if (ops[j].op)
index 92d9c75..aa0472e 100644 (file)
@@ -5323,11 +5323,15 @@ rewrite_use_compare (struct ivopts_data *data,
     {
       tree var = var_at_stmt (data->current_loop, cand, use->stmt);
       tree var_type = TREE_TYPE (var);
+      gimple_seq stmts;
 
       compare = iv_elimination_compare (data, use);
       bound = unshare_expr (fold_convert (var_type, bound));
-      op = force_gimple_operand_gsi (&bsi, bound, true, NULL_TREE,
-                                    true, GSI_SAME_STMT);
+      op = force_gimple_operand (bound, &stmts, true, NULL_TREE);
+      if (stmts)
+       gsi_insert_seq_on_edge_immediate (
+               loop_preheader_edge (data->current_loop),
+               stmts);
 
       gimple_cond_set_lhs (use->stmt, var);
       gimple_cond_set_code (use->stmt, compare);
index 33aacae..13b10c9 100644 (file)
@@ -3053,7 +3053,7 @@ scev_probably_wraps_p (tree base, tree step,
 
   /* If we can use the fact that signed and pointer arithmetics does not
      wrap, we are done.  */
-  if (use_overflow_semantics && nowrap_type_p (type))
+  if (use_overflow_semantics && nowrap_type_p (TREE_TYPE (base)))
     return false;
 
   /* To be able to use estimates on number of iterations of the loop,