diff --git a/gcc/fold-mem-offsets.cc b/gcc/fold-mem-offsets.cc
index a816006e2078219383a87d857a31bc2774a3649d..c1c94472a071711536fd585d4edbd2a94237c762 100644
--- a/gcc/fold-mem-offsets.cc
+++ b/gcc/fold-mem-offsets.cc
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "df.h"
 #include "tree-pass.h"
 #include "cfgrtl.h"
+#include "diagnostic-core.h"
 
 /* This pass tries to optimize memory offset calculations by moving constants
    from add instructions to the memory instructions (loads / stores).
@@ -841,6 +842,23 @@ do_commit_insn (rtx_insn *insn)
 unsigned int
 pass_fold_mem_offsets::execute (function *fn)
 {
+  /* Computing UD/DU chains for flow graphs which have a high connectivity
+     will take a long time and is unlikely to be particularly useful.
+
+     In normal circumstances a cfg should have about twice as many
+     edges as blocks.  But we do not want to punish small functions
+     which have a couple switch statements.  Rather than simply
+     threshold the number of blocks, uses something with a more
+     graceful degradation.  */
+  if (n_edges_for_fn (fn) > 20000 + n_basic_blocks_for_fn (fn) * 4)
+    {
+      warning (OPT_Wdisabled_optimization,
+	       "fold-mem-offsets: %d basic blocks and %d edges/basic block",
+	       n_basic_blocks_for_fn (cfun),
+	       n_edges_for_fn (cfun) / n_basic_blocks_for_fn (cfun));
+      return 0;
+    }
+
   df_set_flags (DF_EQ_NOTES + DF_RD_PRUNE_DEAD_DEFS + DF_DEFER_INSN_RESCAN);
   df_chain_add_problem (DF_UD_CHAIN + DF_DU_CHAIN);
   df_analyze ();