Starting with the 4.5.x series, we have pathological cases (Ada code generated 
by a code generator from a model) where FWPROP takes 80% of the compilation 
time at -O1 (for essentially no benefits).  There are very few basic blocks 
(typically 1) and tens of thousands of uses registered with DF, so processing 
them takes a while (top function in the profile: local_ref_killed_between_p).

The attached patch is an attempt (modelled on gcse.c) at disabling the pass for 
these pathological cases.  Thoughts?


        * Makefile.in (fwprop.o): Add intl.h.
        * fwprop.c: Include intl.h.
        (is_too_expensive): New function.
        (fwprop): Call it and return early if it returns true.
        (fwprop_addr): Likewise.


-- 
Eric Botcazou
Index: Makefile.in
===================================================================
--- Makefile.in	(revision 183423)
+++ Makefile.in	(working copy)
@@ -3023,9 +3023,10 @@ dse.o : dse.c $(CONFIG_H) $(SYSTEM_H) co
    $(TREE_PASS_H) alloc-pool.h $(ALIAS_H) dse.h $(OPTABS_H) $(TARGET_H) \
    $(BITMAP_H) $(PARAMS_H)
 fwprop.o : fwprop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
-   $(DIAGNOSTIC_CORE_H) insn-config.h $(RECOG_H) $(FLAGS_H) $(OBSTACK_H) $(BASIC_BLOCK_H) \
-   output.h $(DF_H) alloc-pool.h $(TIMEVAR_H) $(TREE_PASS_H) $(TARGET_H) \
-   $(TM_P_H) $(CFGLOOP_H) $(EMIT_RTL_H) domwalk.h sparseset.h
+   $(DIAGNOSTIC_CORE_H) insn-config.h $(RECOG_H) $(FLAGS_H) $(OBSTACK_H) \
+   intl.h $(BASIC_BLOCK_H) output.h $(DF_H) alloc-pool.h $(TIMEVAR_H) \
+   $(TREE_PASS_H) $(TARGET_H) $(TM_P_H) $(CFGLOOP_H) $(EMIT_RTL_H) \
+   domwalk.h sparseset.h
 web.o : web.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    hard-reg-set.h $(FLAGS_H) $(BASIC_BLOCK_H) $(FUNCTION_H) output.h $(DIAGNOSTIC_CORE_H) \
    insn-config.h $(RECOG_H) $(DF_H) $(OBSTACK_H) $(TIMEVAR_H) $(TREE_PASS_H)
Index: fwprop.c
===================================================================
--- fwprop.c	(revision 183423)
+++ fwprop.c	(working copy)
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.
 #include "insn-config.h"
 #include "recog.h"
 #include "flags.h"
+#include "intl.h"
 #include "obstack.h"
 #include "basic-block.h"
 #include "output.h"
@@ -1435,6 +1436,28 @@ fwprop_done (void)
 }
 
 
+/* Return true if the function is too expensive to optimize.  PASS is the
+   optimization about to be performed.  */
+
+static bool
+is_too_expensive (const char *pass)
+{
+  int ratio = DF_USES_TABLE_SIZE () / (n_basic_blocks - NUM_FIXED_BLOCKS);
+
+  /* Trying to propagate into uses in functions with gigantic basic blocks
+     will take a long time and is unlikely to be particularly useful.  */
+  if (ratio > 20000)
+    {
+      warning (OPT_Wdisabled_optimization,
+	       "%s: %d basic blocks and %d uses/basic block",
+	       pass, n_basic_blocks - NUM_FIXED_BLOCKS, ratio);
+
+      return true;
+    }
+
+  return false;
+}
+
 /* Main entry point.  */
 
 static bool
@@ -1451,6 +1474,12 @@ fwprop (void)
 
   fwprop_init ();
 
+  if (is_too_expensive (_("FWPROP1 disabled")))
+    {
+      fwprop_done ();
+      return 0;
+    }
+
   /* Go through all the uses.  df_uses_create will create new ones at the
      end, and we'll go through them as well.
 
@@ -1469,8 +1498,10 @@ fwprop (void)
     }
 
   fwprop_done ();
+
   if (need_cleanup)
     cleanup_cfg (0);
+
   return 0;
 }
 
@@ -1503,6 +1534,12 @@ fwprop_addr (void)
 
   fwprop_init ();
 
+  if (is_too_expensive (_("FWPROP2 disabled")))
+    {
+      fwprop_done ();
+      return 0;
+    }
+
   /* Go through all the uses.  df_uses_create will create new ones at the
      end, and we'll go through them as well.  */
   for (i = 0; i < DF_USES_TABLE_SIZE (); i++)
@@ -1520,6 +1557,7 @@ fwprop_addr (void)
 
   if (need_cleanup)
     cleanup_cfg (0);
+
   return 0;
 }
 

Reply via email to