Bug 46331 - Compilation time long with simple function in array constructor
Summary: Compilation time long with simple function in array constructor
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.6.0
: P3 normal
Target Milestone: ---
Assignee: Jerry DeLisle
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-11-06 15:30 UTC by Jerry DeLisle
Modified: 2010-11-10 05:25 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2010-11-08 02:19:56


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jerry DeLisle 2010-11-06 15:30:27 UTC
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.
Comment 1 Jerry DeLisle 2010-11-06 16:09:30 UTC
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
Comment 2 Jerry DeLisle 2010-11-07 14:32:47 UTC
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;
Comment 3 Jerry DeLisle 2010-11-08 02:19:56 UTC
I have a better patch and will submit it for approval.
Comment 4 Jerry DeLisle 2010-11-10 04:58:23 UTC
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
Comment 5 Jerry DeLisle 2010-11-10 05:25:59 UTC
Fixed on trunk.