gfc_se cont_se, array_se;
stmtblock_t if_block, else_block;
tree if_stmt, else_stmt;
+ mpz_t size;
+ bool size_set;
cont_var = gfc_create_var (boolean_type_node, "contiguous");
- /* cont_var = is_contiguous (expr); . */
- gfc_init_se (&cont_se, parmse);
- gfc_conv_is_contiguous_expr (&cont_se, expr);
- gfc_add_block_to_block (&se->pre, &(&cont_se)->pre);
- gfc_add_modify (&se->pre, cont_var, cont_se.expr);
- gfc_add_block_to_block (&se->pre, &(&cont_se)->post);
+ /* If the size is known to be one at compile-time, set
+ cont_var to true unconditionally. This may look
+ inelegant, but we're only doing this during
+ optimization, so the statements will be optimized away,
+ and this saves complexity here. */
+
+ size_set = gfc_array_size (expr, &size);
+ if (size_set && mpz_cmp_ui (size, 1) == 0)
+ {
+ gfc_add_modify (&se->pre, cont_var,
+ build_one_cst (boolean_type_node));
+ }
+ else
+ {
+ /* cont_var = is_contiguous (expr); . */
+ gfc_init_se (&cont_se, parmse);
+ gfc_conv_is_contiguous_expr (&cont_se, expr);
+ gfc_add_block_to_block (&se->pre, &(&cont_se)->pre);
+ gfc_add_modify (&se->pre, cont_var, cont_se.expr);
+ gfc_add_block_to_block (&se->pre, &(&cont_se)->post);
+ }
+
+ if (size_set)
+ mpz_clear (size);
/* arrayse->expr = descriptor of a. */
gfc_init_se (&array_se, se);
/* And put the above into an if statement. */
pre_stmts = fold_build3_loc (input_location, COND_EXPR, void_type_node,
- cont_var, if_stmt, else_stmt);
+ gfc_likely (cont_var,
+ PRED_FORTRAN_CONTIGUOUS),
+ if_stmt, else_stmt);
}
else
{
gfc_add_modify (&else_block, pointer, build_int_cst (type, 0));
else_stmt = gfc_finish_block (&else_block);
- tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, present_var,
+ tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
+ gfc_likely (present_var,
+ PRED_FORTRAN_ABSENT_DUMMY),
pre_stmts, else_stmt);
gfc_add_expr_to_block (&se->pre, tmp);
-
-
}
else
gfc_add_expr_to_block (&se->pre, pre_stmts);
tmp = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node,
cont_var,
build_zero_cst (boolean_type_node));
+ tmp = gfc_unlikely (tmp, PRED_FORTRAN_CONTIGUOUS);
+
if (pass_optional)
- post_cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
- boolean_type_node, present_var, tmp);
+ {
+ tree present_likely = gfc_likely (present_var,
+ PRED_FORTRAN_ABSENT_DUMMY);
+ post_cond = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
+ boolean_type_node, present_likely,
+ tmp);
+ }
else
post_cond = tmp;
}
--- /dev/null
+! { dg-do run }
+! { dg-additional-options "-O -fdump-tree-optimized" }
+module y
+ implicit none
+contains
+ subroutine foo(a,b,c,d,e,f)
+ real, dimension(1), intent(inout) :: a, b, c, d, e, f
+ if (any([a,b,c,d,e,f] /= [1,2,3,4,5,6])) stop 1
+ a = -a
+ b = -b
+ c = -c
+ d = -d
+ e = -e
+ f = -f
+ end subroutine foo
+end module y
+module x
+ use y
+ implicit none
+contains
+ subroutine bar(a)
+ real, dimension(:) :: a
+ integer :: n1, n3, n5
+ n1 = 1
+ n3 = 3
+ n5 = 5
+ call foo(a(n1:n1), a(n1+1:n1+1), a(n3:n3), a(n3+1:n3+1), a(n5:n5), a(n5+1:n5+1))
+ end subroutine bar
+end module x
+
+program main
+ use x
+ real, dimension(6) :: a,b
+ b = [1,2,3,4,5,6]
+ a = b
+ call bar(a)
+ if (any(a /= -b)) stop 2
+end program main
+! { dg-final { scan-tree-dump-not "contiguous" "optimized" } }