@@ -1289,7 +1289,7 @@ gcc_loop_to_lambda_loop (struct loop *lo
if (gimple_code (phi) != GIMPLE_PHI)
{
tree op = SINGLE_SSA_TREE_OPERAND (phi, SSA_OP_USE);
- if (!op)
+ if (!op || !is_gimple_assign (phi))
{
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1332,7 +1332,9 @@ gcc_loop_to_lambda_loop (struct loop *lo
return NULL;
}
- if (TREE_CODE (step) != INTEGER_CST)
+ if (!host_integerp (step, 0)
+ || (HOST_WIDE_INT) TREE_INT_CST_LOW (step)
+ != (int) TREE_INT_CST_LOW (step))
{
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1366,6 +1368,32 @@ gcc_loop_to_lambda_loop (struct loop *lo
return NULL;
}
+ if (SSA_NAME_DEF_STMT (inductionvar) != phi)
+ {
+ gimple stmt = SSA_NAME_DEF_STMT (inductionvar);
+ tree rhs2;
+ int stepintval = stepint;
+ switch (gimple_assign_rhs_code (stmt))
+ {
+ case MINUS_EXPR:
+ stepintval = -stepint;
+ /* FALLTHRU */
+ case PLUS_EXPR:
+ case POINTER_PLUS_EXPR:
+ rhs2 = gimple_assign_rhs2 (stmt);
+ if (TREE_CODE (rhs2) == INTEGER_CST
+ && (HOST_WIDE_INT) TREE_INT_CST_LOW (rhs2) == stepintval
+ && TREE_INT_CST_HIGH (rhs2) == (stepintval >= 0 ? 0 : -1))
+ break;
+ /* FALLTHRU */
+ default:
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "Unable to convert loop: Cannot find PHI node for induction variable\n");
+ return NULL;
+ }
+ }
+
if (flow_bb_inside_loop_p (loop, gimple_phi_arg_edge (phi, 0)->src))
{
lboundvar = PHI_ARG_DEF (phi, 1);
@@ -1417,14 +1445,24 @@ gcc_loop_to_lambda_loop (struct loop *lo
/* We might have some leftover. */
- if (gimple_cond_code (exit_cond) == LT_EXPR)
- extra = -1 * stepint;
- else if (gimple_cond_code (exit_cond) == NE_EXPR)
- extra = -1 * stepint;
- else if (gimple_cond_code (exit_cond) == GT_EXPR)
- extra = -1 * stepint;
- else if (gimple_cond_code (exit_cond) == EQ_EXPR)
- extra = 1 * stepint;
+ if (SSA_NAME_DEF_STMT (inductionvar) != phi)
+ {
+ if (gimple_cond_code (exit_cond) == LT_EXPR)
+ extra = -1 * stepint;
+ else if (gimple_cond_code (exit_cond) == NE_EXPR)
+ extra = -1 * stepint;
+ else if (gimple_cond_code (exit_cond) == GT_EXPR)
+ extra = -1 * stepint;
+ else if (gimple_cond_code (exit_cond) == EQ_EXPR)
+ extra = 1 * stepint;
+ }
+ else
+ {
+ if (gimple_cond_code (exit_cond) == LE_EXPR)
+ extra = 1 * stepint;
+ else if (gimple_cond_code (exit_cond) == GE_EXPR)
+ extra = 1 * stepint;
+ }
ubound = gcc_tree_to_linear_expression (depth, uboundvar,
outerinductionvars,
@@ -0,0 +1,27 @@
+/* PR tree-optimization/46970 */
+/* { dg-do run } */
+/* { dg-options "-Os -ftree-loop-linear" } */
+
+int
+foo (int n, int *a)
+{
+ int i, j;
+
+ for (i = 0; i < n; i++)
+ for (j = 0; j < n; j++)
+ a[j] = i + n;
+
+ for (j = 0; j < n; j++)
+ if (a[j] != i + n - 1)
+ __builtin_abort ();
+
+ return 0;
+}
+
+int
+main ()
+{
+ int a[16];
+ foo (16, a);
+ return 0;
+}
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -ftree-loop-linear" } */
+/* { dg-require-effective-target size32plus } */
+
+double u[1782225];
+
+__attribute__((noinline, noclone)) int
+foo (int N, int *res)
+{
+ unsigned int i, j;
+ double sum = 0;
+ for (i = 0; i < N; i++)
+ for (j = 0; j < N; j++)
+ sum = sum + u[i + 1335 * j];
+ *res = sum + N;
+}
+
+int
+main (void)
+{
+ int i;
+ for (i = 0; i < 1782225; i++)
+ u[i] = 1.0;
+ foo (64, &i);
+ if (i != 4160)
+ __builtin_abort ();
+ return 0;
+}