diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 316ad25a1f226f477dfff7db09c6680cff3ae4f7..c023f37e5158b44cfd0bddc6f971243e9307ec7c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -7,6 +7,23 @@
 	* tree-ssa.c (ssa_remove_edge): Call remove_phi_args instead
 	of remove_phi_arg.
 
+	* cfg.c (unchecked_make_edge): Call execute_on_growing_pred
+	after making an edge.
+	(remove_edge): Call execute_on_shrinking_pred before removing
+	an edge.
+	(redirect_edge_succ): Call execute_on_growing_pred and
+	execute_on_shrinking_pred.
+	* cfghooks.c (execute_on_growing_pred): New.
+	(execute_on_shrinking_pred): Likewise.
+	* cfghooks.h (cfg_hooks): Add execute_on_growing_pred and
+	execute_on_shrinking_pred.
+	Add prototypes for execute_on_growing_pred and
+	execute_on_shrinking_pred.
+	* cfgrtl.c (rtl_cfg_hooks): Add NULL hooks to
+	execute_on_growing_pred and execute_on_shrinking_pred.
+	(cfg_layout_rtl_cfg_hook): Likewise.
+	* tree-cfg.c (tree_cfg_hooks): Likewise.
+
 2004-11-23  Ben Elliston  <bje@au.ibm.com>
 
 	* doc/cfg.texi (Maintaining the CFG): Use @ftable instead of
diff --git a/gcc/cfg.c b/gcc/cfg.c
index f7e5a79e0aede8e7fc7707052213da07d32b09ac..563f5e2a6aa1cb5714ecb361d171c6373c78f607 100644
--- a/gcc/cfg.c
+++ b/gcc/cfg.c
@@ -277,6 +277,8 @@ unchecked_make_edge (basic_block src, basic_block dst, int flags)
   e->flags = flags;
   e->dest_idx = EDGE_COUNT (dst->preds) - 1;
 
+  execute_on_growing_pred (e);
+
   return e;
 }
 
@@ -358,6 +360,8 @@ remove_edge (edge e)
   bool found = false;
   edge_iterator ei;
 
+  execute_on_shrinking_pred (e);
+
   src = e->src;
   dest = e->dest;
   dest_idx = e->dest_idx;
@@ -394,6 +398,8 @@ redirect_edge_succ (edge e, basic_block new_succ)
   basic_block dest = e->dest;
   unsigned int dest_idx = e->dest_idx;
 
+  execute_on_shrinking_pred (e);
+
   VEC_unordered_remove (edge, dest->preds, dest_idx);
 
   /* If we removed an edge in the middle of the edge vector, we need
@@ -405,6 +411,7 @@ redirect_edge_succ (edge e, basic_block new_succ)
   VEC_safe_push (edge, new_succ->preds, e);
   e->dest = new_succ;
   e->dest_idx = EDGE_COUNT (new_succ->preds) - 1;
+  execute_on_growing_pred (e);
 }
 
 /* Like previous but avoid possible duplicate edge.  */
diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c
index 841e468bfbb8e97adabc31399a93c4e6355ca556..0f0c230fb805b764c70d469be1560e7218cd4dff 100644
--- a/gcc/cfghooks.c
+++ b/gcc/cfghooks.c
@@ -804,3 +804,23 @@ flow_call_edges_add (sbitmap blocks)
 
   return (cfg_hooks->flow_call_edges_add) (blocks);
 }
+
+/* This function is called immediately after edge E is added to the
+   edge vector E->dest->preds.  */
+
+void
+execute_on_growing_pred (edge e)
+{
+  if (cfg_hooks->execute_on_growing_pred)
+    cfg_hooks->execute_on_growing_pred (e);
+}
+
+/* This function is called immediately before edge E is removed from
+   the edge vector E->dest->preds.  */
+
+void
+execute_on_shrinking_pred (edge e)
+{
+  if (cfg_hooks->execute_on_shrinking_pred)
+    cfg_hooks->execute_on_shrinking_pred (e);
+}
diff --git a/gcc/cfghooks.h b/gcc/cfghooks.h
index 7cbe700df3678b84d291511a0bc15b7d5feed224..92a458ed4aa73e6f572c925d61e25efb5d2fcc80 100644
--- a/gcc/cfghooks.h
+++ b/gcc/cfghooks.h
@@ -100,6 +100,14 @@ struct cfg_hooks
      The goal is to expose cases in which entering a basic block does not imply
      that all subsequent instructions must be executed.  */
   int (*flow_call_edges_add) (sbitmap);
+
+  /* This function is called immediately after edge E is added to the
+     edge vector E->dest->preds.  */
+  void (*execute_on_growing_pred) (edge);
+
+  /* This function is called immediately before edge E is removed from
+     the edge vector E->dest->preds.  */
+  void (*execute_on_shrinking_pred) (edge);
 };
 
 extern void verify_flow_info (void);
@@ -126,6 +134,8 @@ extern basic_block duplicate_block (basic_block, edge);
 extern bool block_ends_with_call_p (basic_block bb);
 extern bool block_ends_with_condjump_p (basic_block bb);
 extern int flow_call_edges_add (sbitmap);
+extern void execute_on_growing_pred (edge);
+extern void execute_on_shrinking_pred (edge);
 
 /* Hooks containers.  */
 extern struct cfg_hooks tree_cfg_hooks;
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 69970518de4454bde4348fcfb0daa18a682adf7a..0bb181aee9c43a91ed0c450bd5d9452a73489641 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -3071,7 +3071,9 @@ struct cfg_hooks rtl_cfg_hooks = {
   rtl_tidy_fallthru_edge,
   rtl_block_ends_with_call_p,
   rtl_block_ends_with_condjump_p,
-  rtl_flow_call_edges_add
+  rtl_flow_call_edges_add,
+  NULL, /* execute_on_growing_pred */
+  NULL /* execute_on_shrinking_pred */
 };
 
 /* Implementation of CFG manipulation for cfg layout RTL, where
@@ -3107,6 +3109,8 @@ struct cfg_hooks cfg_layout_rtl_cfg_hooks = {
   NULL,
   rtl_block_ends_with_call_p,
   rtl_block_ends_with_condjump_p,
-  rtl_flow_call_edges_add
+  rtl_flow_call_edges_add,
+  NULL, /* execute_on_growing_pred */
+  NULL /* execute_on_shrinking_pred */
 };
 
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index fea09d88bfe1e4ff7c0d29aebe26cd1dd144c3ce..f00084aed30808c71ae93d8f1c4af9a8b35e661b 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -5360,7 +5360,9 @@ struct cfg_hooks tree_cfg_hooks = {
   NULL,				/* tidy_fallthru_edge  */
   tree_block_ends_with_call_p,	/* block_ends_with_call_p */
   tree_block_ends_with_condjump_p, /* block_ends_with_condjump_p */
-  tree_flow_call_edges_add      /* flow_call_edges_add */
+  tree_flow_call_edges_add,     /* flow_call_edges_add */
+  NULL,	/* execute_on_growing_pred */
+  NULL, /* execute_on_shrinking_pred */
 };