+
+ for (i = 0; i < fd->collapse; i++)
+ {
+ if (fd->collapse == 1)
+ loop = &fd->loop;
+ else if (loops != NULL)
+ loop = loops + i;
+ else
+ loop = &dummy_loop;
+
+
+ loop->v = gimple_omp_for_index (for_stmt, i);
+ gcc_assert (SSA_VAR_P (loop->v));
+ gcc_assert (TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
+ || TREE_CODE (TREE_TYPE (loop->v)) == POINTER_TYPE);
+ var = TREE_CODE (loop->v) == SSA_NAME ? SSA_NAME_VAR (loop->v) : loop->v;
+ loop->n1 = gimple_omp_for_initial (for_stmt, i);
+
+ loop->cond_code = gimple_omp_for_cond (for_stmt, i);
+ loop->n2 = gimple_omp_for_final (for_stmt, i);
+ switch (loop->cond_code)
+ {
+ case LT_EXPR:
+ case GT_EXPR:
+ break;
+ case LE_EXPR:
+ if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
+ loop->n2 = fold_build2_loc (loc,
+ POINTER_PLUS_EXPR, TREE_TYPE (loop->n2),
+ loop->n2, size_one_node);
+ else
+ loop->n2 = fold_build2_loc (loc,
+ PLUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
+ build_int_cst (TREE_TYPE (loop->n2), 1));
+ loop->cond_code = LT_EXPR;
+ break;
+ case GE_EXPR:
+ if (POINTER_TYPE_P (TREE_TYPE (loop->n2)))
+ loop->n2 = fold_build2_loc (loc,
+ POINTER_PLUS_EXPR, TREE_TYPE (loop->n2),
+ loop->n2, size_int (-1));
+ else
+ loop->n2 = fold_build2_loc (loc,
+ MINUS_EXPR, TREE_TYPE (loop->n2), loop->n2,
+ build_int_cst (TREE_TYPE (loop->n2), 1));
+ loop->cond_code = GT_EXPR;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ t = gimple_omp_for_incr (for_stmt, i);
+ gcc_assert (TREE_OPERAND (t, 0) == var);
+ switch (TREE_CODE (t))
+ {
+ case PLUS_EXPR:
+ case POINTER_PLUS_EXPR:
+ loop->step = TREE_OPERAND (t, 1);
+ break;
+ case MINUS_EXPR:
+ loop->step = TREE_OPERAND (t, 1);
+ loop->step = fold_build1_loc (loc,
+ NEGATE_EXPR, TREE_TYPE (loop->step),
+ loop->step);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ if (iter_type != long_long_unsigned_type_node)
+ {
+ if (POINTER_TYPE_P (TREE_TYPE (loop->v)))
+ iter_type = long_long_unsigned_type_node;
+ else if (TYPE_UNSIGNED (TREE_TYPE (loop->v))
+ && TYPE_PRECISION (TREE_TYPE (loop->v))
+ >= TYPE_PRECISION (iter_type))
+ {
+ tree n;
+
+ if (loop->cond_code == LT_EXPR)
+ n = fold_build2_loc (loc,
+ PLUS_EXPR, TREE_TYPE (loop->v),
+ loop->n2, loop->step);
+ else
+ n = loop->n1;
+ if (TREE_CODE (n) != INTEGER_CST
+ || tree_int_cst_lt (TYPE_MAX_VALUE (iter_type), n))
+ iter_type = long_long_unsigned_type_node;
+ }
+ else if (TYPE_PRECISION (TREE_TYPE (loop->v))
+ > TYPE_PRECISION (iter_type))
+ {
+ tree n1, n2;
+
+ if (loop->cond_code == LT_EXPR)
+ {
+ n1 = loop->n1;
+ n2 = fold_build2_loc (loc,
+ PLUS_EXPR, TREE_TYPE (loop->v),
+ loop->n2, loop->step);
+ }
+ else
+ {
+ n1 = fold_build2_loc (loc,
+ MINUS_EXPR, TREE_TYPE (loop->v),
+ loop->n2, loop->step);
+ n2 = loop->n1;
+ }
+ if (TREE_CODE (n1) != INTEGER_CST
+ || TREE_CODE (n2) != INTEGER_CST
+ || !tree_int_cst_lt (TYPE_MIN_VALUE (iter_type), n1)
+ || !tree_int_cst_lt (n2, TYPE_MAX_VALUE (iter_type)))
+ iter_type = long_long_unsigned_type_node;
+ }
+ }
+
+ if (collapse_count && *collapse_count == NULL)
+ {
+ if ((i == 0 || count != NULL_TREE)
+ && TREE_CODE (TREE_TYPE (loop->v)) == INTEGER_TYPE
+ && TREE_CONSTANT (loop->n1)
+ && TREE_CONSTANT (loop->n2)
+ && TREE_CODE (loop->step) == INTEGER_CST)
+ {
+ tree itype = TREE_TYPE (loop->v);
+
+ if (POINTER_TYPE_P (itype))
+ itype
+ = lang_hooks.types.type_for_size (TYPE_PRECISION (itype), 0);
+ t = build_int_cst (itype, (loop->cond_code == LT_EXPR ? -1 : 1));
+ t = fold_build2_loc (loc,
+ PLUS_EXPR, itype,
+ fold_convert_loc (loc, itype, loop->step), t);
+ t = fold_build2_loc (loc, PLUS_EXPR, itype, t,
+ fold_convert_loc (loc, itype, loop->n2));
+ t = fold_build2_loc (loc, MINUS_EXPR, itype, t,
+ fold_convert_loc (loc, itype, loop->n1));
+ if (TYPE_UNSIGNED (itype) && loop->cond_code == GT_EXPR)
+ t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype,
+ fold_build1_loc (loc, NEGATE_EXPR, itype, t),
+ fold_build1_loc (loc, NEGATE_EXPR, itype,
+ fold_convert_loc (loc, itype,
+ loop->step)));
+ else
+ t = fold_build2_loc (loc, TRUNC_DIV_EXPR, itype, t,
+ fold_convert_loc (loc, itype, loop->step));
+ t = fold_convert_loc (loc, long_long_unsigned_type_node, t);
+ if (count != NULL_TREE)
+ count = fold_build2_loc (loc,
+ MULT_EXPR, long_long_unsigned_type_node,
+ count, t);
+ else
+ count = t;
+ if (TREE_CODE (count) != INTEGER_CST)
+ count = NULL_TREE;
+ }
+ else
+ count = NULL_TREE;
+ }
+ }
+
+ if (count)
+ {
+ if (!tree_int_cst_lt (count, TYPE_MAX_VALUE (long_integer_type_node)))
+ iter_type = long_long_unsigned_type_node;
+ else
+ iter_type = long_integer_type_node;
+ }
+ else if (collapse_iter && *collapse_iter != NULL)
+ iter_type = TREE_TYPE (*collapse_iter);
+ fd->iter_type = iter_type;
+ if (collapse_iter && *collapse_iter == NULL)
+ *collapse_iter = create_tmp_var (iter_type, ".iter");
+ if (collapse_count && *collapse_count == NULL)
+ {
+ if (count)
+ *collapse_count = fold_convert_loc (loc, iter_type, count);
+ else
+ *collapse_count = create_tmp_var (iter_type, ".count");
+ }
+
+ if (fd->collapse > 1)
+ {
+ fd->loop.v = *collapse_iter;
+ fd->loop.n1 = build_int_cst (TREE_TYPE (fd->loop.v), 0);
+ fd->loop.n2 = *collapse_count;
+ fd->loop.step = build_int_cst (TREE_TYPE (fd->loop.v), 1);
+ fd->loop.cond_code = LT_EXPR;
+ }