program foo implicit none Integer :: i Integer, Parameter :: N = 10**4 Real, Dimension(N) :: xs ! Random points xs = (/ (rand(0), i=1,N) /) print *, xs end program The time spent in the FE is not bad, but the resulting translation is horrible and it wreaks havoc with the middle end and down the road. I think we should not expand this constructor at all, especially since 'i' is not used in the function expression. However, rand(0) needs to be called once for each element. That means it needs to be translated into: do i-1,N xs = rand(0) end do In otherwords, I think another special case in gfc_trans_assignment. There are other special cases already there.
I should add that if rand is the only function that acts like this, then this is not of much value. While just playing around, this translates as expected. (Nice short -fdump-tree-original file.) program foo implicit none Integer :: i Integer, Parameter :: N = 10**4 Real, Dimension(N) :: xs ! Random points !xs = (/ (rand(0), i=1,N) /) xs = (/ (myfunction(0), i=1,N) /) !xs = myfunction (0.0) print *, xs contains function myfunction(somenumber) integer :: somenumber real :: myfunction myfunction = 1234.567 if (somenumber .eq. 42) return myfunction = somenumber + rand(0) end function end program
Patch: The part removed too agressively decides if an expression is constant. In the case of rand(), the result obviously does not reduce to a constant but the array constructor was expanded. Returning zero here means the function is not constant and therefore the array is not expanded at compile time. Regression tested OK on x86-64. Index: expr.c =================================================================== --- expr.c (revision 166382) +++ expr.c (working copy) @@ -900,7 +900,6 @@ int gfc_is_constant_expr (gfc_expr *e) { gfc_constructor *c; - gfc_actual_arglist *arg; if (e == NULL) return 1; @@ -921,19 +920,8 @@ gfc_is_constant_expr (gfc_expr *e) /* Specification functions are constant. */ if (check_specification_function (e) == MATCH_YES) return 1; + return 0; - /* Call to intrinsic with at least one argument. */ - if (e->value.function.isym && e->value.function.actual) - { - for (arg = e->value.function.actual; arg; arg = arg->next) - if (!gfc_is_constant_expr (arg->expr)) - return 0; - - return 1; - } - else - return 0; - case EXPR_CONSTANT: case EXPR_NULL: return 1;
I have a better patch and will submit it for approval.
Author: jvdelisle Date: Wed Nov 10 04:58:16 2010 New Revision: 166520 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=166520 Log: 2010-11-09 Jerry DeLisle <jvdelisle@gcc.gnu.org> Mikael Morin <mikael@gcc.gnu.org> PR fortran/46331 * intrinsic.c: Correctly set the pure attributes for intrinsic functions. * expr.c (check_specification_function): Remove this function and move its code into gfc_is_constant_expr. (gfc_is_constant_expr): Change the order of checks by checking for non-constant arguments first. Then, check for initialization functions, followed by intrinsics. Modified: trunk/gcc/fortran/ChangeLog trunk/gcc/fortran/expr.c trunk/gcc/fortran/intrinsic.c
Fixed on trunk.