This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: ipa for fortran question


Hi,

On Sun, 12 Aug 2007, Jan Hubicka wrote:

> > Recently I have tried to run Spec2000 fortran benchmarks with 
> > -fwhole-program and -combine flags. It looks like there was no effect 
> > of really combining files into one program, i.e. they are processed 
> > separately at ipa level.
> > 
> > I wonder what's the reason for this. Pointing to relevant docs will 
> > work for me.
> 
> --combine has no effect to fortran, but in general concatenating all the 
> sources to one big source with cat works just fine. Fortran however has 
> problems with the multiple declaration rule making IPA quite ineffective
> :(
> (each time something is re-declared in source new declaration is 
> produced and IPA thinks those are different objects)

I once hacked around this limitation with the below patch.  It's from two 
years ago, so probably doesn't apply at all anymore, much less work.  But 
perhaps it's of some use as starting point.  You'd still need to cat the 
.f* files together explicitely, but with that patch it more or less was 
forming a real call graph.  I think in its simplicity the patch got some 
fortran details wrong (in the sense of merging two decls which really are 
separate per fortran semantics), but I don't remember the details, except 
that spec2000 doesn't contain such cases.


Ciao,
Michael.
-- 
Index: fortran/f95-lang.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fortran/f95-lang.c,v
retrieving revision 1.39
diff -u -p -r1.39 f95-lang.c
--- fortran/f95-lang.c	21 Aug 2005 15:28:23 -0000	1.39
+++ fortran/f95-lang.c	13 Sep 2005 23:34:33 -0000
@@ -525,6 +525,22 @@ pushdecl_top_level (tree x)
   return t;
 }
 
+tree find_fndecl (tree name);
+tree
+find_fndecl (tree name)
+{
+  struct binding_level *b = current_binding_level;
+  while (b)
+    {
+      tree t;
+      for (t = b->names; t; t = TREE_CHAIN (t))
+        if (TREE_CODE (t) == FUNCTION_DECL
+	    && DECL_NAME (t) == name)
+	  return t;
+      b = b->level_chain;
+    }
+  return NULL_TREE;
+}
 
 /* Clear the binding stack.  */
 static void
Index: fortran/trans-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fortran/trans-decl.c,v
retrieving revision 1.69
diff -u -p -r1.69 trans-decl.c
--- fortran/trans-decl.c	9 Sep 2005 06:00:25 -0000	1.69
+++ fortran/trans-decl.c	13 Sep 2005 23:34:33 -0000
@@ -44,6 +44,7 @@ Software Foundation, 51 Franklin Street,
 
 #define MAX_LABEL_VALUE 99999
 
+extern tree find_fndecl (tree);
 
 /* Holds the result of the function if no result variable specified.  */
 
@@ -960,57 +961,61 @@ gfc_get_extern_function_decl (gfc_symbol
       mangled_name = gfc_sym_mangled_function_id (sym);
     }
 
-  type = gfc_get_function_type (sym);
-  fndecl = build_decl (FUNCTION_DECL, name, type);
+  fndecl = find_fndecl (name);
+  if (!fndecl || TREE_CODE (fndecl) != FUNCTION_DECL)
+    {
+      type = gfc_get_function_type (sym);
+      fndecl = build_decl (FUNCTION_DECL, name, type);
 
-  SET_DECL_ASSEMBLER_NAME (fndecl, mangled_name);
-  /* If the return type is a pointer, avoid alias issues by setting
-     DECL_IS_MALLOC to nonzero. This means that the function should be
-     treated as if it were a malloc, meaning it returns a pointer that
-     is not an alias.  */
-  if (POINTER_TYPE_P (type))
-    DECL_IS_MALLOC (fndecl) = 1;
+      SET_DECL_ASSEMBLER_NAME (fndecl, mangled_name);
+      /* If the return type is a pointer, avoid alias issues by setting
+	 DECL_IS_MALLOC to nonzero. This means that the function should be
+	 treated as if it were a malloc, meaning it returns a pointer that
+	 is not an alias.  */
+      if (POINTER_TYPE_P (type))
+	DECL_IS_MALLOC (fndecl) = 1;
 
-  /* Set the context of this decl.  */
-  if (0 && sym->ns && sym->ns->proc_name)
-    {
-      /* TODO: Add external decls to the appropriate scope.  */
-      DECL_CONTEXT (fndecl) = sym->ns->proc_name->backend_decl;
-    }
-  else
-    {
-      /* Global declaration, e.g. intrinsic subroutine.  */
-      DECL_CONTEXT (fndecl) = NULL_TREE;
-    }
+      /* Set the context of this decl.  */
+      if (0 && sym->ns && sym->ns->proc_name)
+	{
+	  /* TODO: Add external decls to the appropriate scope.  */
+	  DECL_CONTEXT (fndecl) = sym->ns->proc_name->backend_decl;
+	}
+      else
+	{
+	  /* Global declaration, e.g. intrinsic subroutine.  */
+	  DECL_CONTEXT (fndecl) = NULL_TREE;
+	}
 
-  DECL_EXTERNAL (fndecl) = 1;
+      DECL_EXTERNAL (fndecl) = 1;
 
-  /* This specifies if a function is globally addressable, i.e. it is
-     the opposite of declaring static in C.  */
-  TREE_PUBLIC (fndecl) = 1;
+      /* This specifies if a function is globally addressable, i.e. it is
+	 the opposite of declaring static in C.  */
+      TREE_PUBLIC (fndecl) = 1;
 
-  /* Set attributes for PURE functions. A call to PURE function in the
-     Fortran 95 sense is both pure and without side effects in the C
-     sense.  */
-  if (sym->attr.pure || sym->attr.elemental)
-    {
-      if (sym->attr.function)
-	DECL_IS_PURE (fndecl) = 1;
-      /* TODO: check if pure SUBROUTINEs don't have INTENT(OUT)
-	 parameters and don't use alternate returns (is this
-	 allowed?). In that case, calls to them are meaningless, and
-	 can be optimized away. See also in build_function_decl().  */
-      TREE_SIDE_EFFECTS (fndecl) = 0;
-    }
+      /* Set attributes for PURE functions. A call to PURE function in the
+	 Fortran 95 sense is both pure and without side effects in the C
+	 sense.  */
+      if (sym->attr.pure || sym->attr.elemental)
+	{
+	  if (sym->attr.function)
+	    DECL_IS_PURE (fndecl) = 1;
+	  /* TODO: check if pure SUBROUTINEs don't have INTENT(OUT)
+	     parameters and don't use alternate returns (is this
+	     allowed?). In that case, calls to them are meaningless, and
+	     can be optimized away. See also in build_function_decl().  */
+	  TREE_SIDE_EFFECTS (fndecl) = 0;
+	}
 
-  /* Mark non-returning functions.  */
-  if (sym->attr.noreturn)
-      TREE_THIS_VOLATILE(fndecl) = 1;
+      /* Mark non-returning functions.  */
+      if (sym->attr.noreturn)
+	  TREE_THIS_VOLATILE(fndecl) = 1;
 
-  sym->backend_decl = fndecl;
+      if (DECL_CONTEXT (fndecl) == NULL_TREE)
+	pushdecl_top_level (fndecl);
+    }
 
-  if (DECL_CONTEXT (fndecl) == NULL_TREE)
-    pushdecl_top_level (fndecl);
+  sym->backend_decl = fndecl;
 
   return fndecl;
 }
@@ -1026,6 +1031,7 @@ build_function_decl (gfc_symbol * sym)
   tree fndecl, type;
   symbol_attribute attr;
   tree result_decl;
+  tree name;
   gfc_formal_arglist *f;
 
   gcc_assert (!sym->backend_decl);
@@ -1039,8 +1045,24 @@ build_function_decl (gfc_symbol * sym)
   gcc_assert (current_function_decl == NULL_TREE
 	  || DECL_CONTEXT (current_function_decl) == NULL_TREE);
 
-  type = gfc_get_function_type (sym);
-  fndecl = build_decl (FUNCTION_DECL, gfc_sym_identifier (sym), type);
+  name = gfc_sym_identifier (sym);
+  fndecl = find_fndecl (name);
+  if (fndecl)
+    {
+      /* type = TREE_TYPE (fndecl); */
+      /* XXX hack to insert the correct type, which is known only
+         with the declaration, not with calls.  */
+      type = gfc_get_function_type (sym);
+      TREE_TYPE (fndecl) = type;
+    }
+  else
+    {
+      type = gfc_get_function_type (sym);
+      fndecl = build_decl (FUNCTION_DECL, gfc_sym_identifier (sym), type);
+      /* Layout the function declaration and put it in the binding level
+         of the current function.  */
+      pushdecl (fndecl);
+    }
 
   /* Perform name mangling if this is a top level or module procedure.  */
   if (current_function_decl == NULL_TREE)
@@ -1126,10 +1148,6 @@ build_function_decl (gfc_symbol * sym)
       TREE_SIDE_EFFECTS (fndecl) = 0;
     }
 
-  /* Layout the function declaration and put it in the binding level
-     of the current function.  */
-  pushdecl (fndecl);
-
   sym->backend_decl = fndecl;
 }
 
Index: fortran/trans.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fortran/trans.c,v
retrieving revision 1.28
diff -u -p -r1.28 trans.c
--- fortran/trans.c	11 Aug 2005 13:50:09 -0000	1.28
+++ fortran/trans.c	13 Sep 2005 23:34:33 -0000
@@ -662,6 +662,9 @@ gfc_generate_code (gfc_namespace * ns)
       gfc_symbol *main_program;
       symbol_attribute attr;
 
+      /* Let backend know that this is the main entry point to the program.  */
+      main_identifier_node = get_identifier ("MAIN__");
+
       /* Lots of things get upset if a subroutine doesn't have a symbol, so we
          make one now.  Hopefully we've set all the required fields.  */
       gfc_get_symbol ("MAIN__", ns, &main_program);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]