This is the mail archive of the gcc-patches@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]

Fix PR rtl-optimization/33737


This is a regression present on the mainline.  The attached testcase triggers 
a CFG verification failure at -O2, because of a negative edge probability.

The negative probably is computed in try_crossjump_to_edge

      if (!redirect_to->frequency && !src1->frequency)
	s->probability = (s->probability + s2->probability) / 2;
      else
	s->probability
	  = ((s->probability * redirect_to->frequency +
	      s2->probability * src1->frequency)
	     / (redirect_to->frequency + src1->frequency));

from the overflow of the numerator.  redirect_to->frequency happens to be huge 
because try_crossjump_to_edge is invoked many times on the same edge and the 
frequencies add up for cross-jumping:

  redirect_to->count += src1->count;
  redirect_to->frequency += src1->frequency;


Frequencies are supposed to be in the range 0..BB_FREQ_MAX and maintained by 
means of local updates (see update_bb_profile_for_threading).  But conflicts 
can arise when jumps are threaded if frequencies have been set artificially 
low e.g. by __builtin_expect.  This is acknowledged:

/* An edge originally destinating BB of FREQUENCY and COUNT has been proved to
  leave the block by TAKEN_EDGE.  Update profile of BB such that edge E can be
  redirected to destination of TAKEN_EDGE.

   This function may leave the profile inconsistent in the case TAKEN_EDGE
   frequency or count is believed to be lower than FREQUENCY or COUNT
   respectively.  */
void
update_bb_profile_for_threading (basic_block bb, int edge_frequency,
				 gcov_type count, edge taken_edge)


For the testcase at hand, the profile is already inconsistent after the jump 
threading at the end of the first VRP pass.  A global update would be needed 
in order to recover from this inconsistent state.

The patch simply caps the frequencies in try_crossjump_to_edge.  It also fixes 
a couple of related defects:

1. In try_crossjump_to_edge, the frequencies were added before the weighted
mean for the edge probabilities was computed, thus skewing the weights.

2. In redirect_edges when all incoming edges of a basic block were redirected, 
the orphaned basic block was reused for the split of one of its predecessors.
Its count and frequency had been zeroed by update_bb_profile_for_threading and 
they weren't updated.

Bootstrapped/regtested on x86_64-suse-linux, applied on the mainline, as 
obvious for the tree-ssa-threadupdate.c part.


2007-11-07  Eric Botcazou  <ebotcazou@libertysurf.fr>

	PR rtl-optimization/33737
	* cfgcleanup.c (try_crossjump_to_edge): Add count and frequency of
	target block after computing the probabilities of outgoing edges.
	Cap the frequency to BB_FREQ_MAX.
	* tree-ssa-threadupdate.c (redirect_edges): Also adjust count and
	frequency of the basic block if it has been reused.


2007-11-07  Eric Botcazou  <ebotcazou@libertysurf.fr>

	* gcc.c-torture/compile/20071107-1.c: New test.


-- 
Eric Botcazou
Index: cfgcleanup.c
===================================================================
--- cfgcleanup.c	(revision 129844)
+++ cfgcleanup.c	(working copy)
@@ -1699,8 +1699,6 @@ try_crossjump_to_edge (int mode, edge e1
 	     "Cross jumping from bb %i to bb %i; %i common insns\n",
 	     src1->index, src2->index, nmatch);
 
-  redirect_to->count += src1->count;
-  redirect_to->frequency += src1->frequency;
   /* We may have some registers visible through the block.  */
   df_set_bb_dirty (redirect_to);
 
@@ -1757,6 +1755,14 @@ try_crossjump_to_edge (int mode, edge e1
 	     / (redirect_to->frequency + src1->frequency));
     }
 
+  /* Adjust count and frequency for the block.  An earlier jump
+     threading pass may have left the profile in an inconsistent
+     state (see update_bb_profile_for_threading) so we must be
+     prepared for overflows.  */
+  redirect_to->count += src1->count;
+  redirect_to->frequency += src1->frequency;
+  if (redirect_to->frequency > BB_FREQ_MAX)
+    redirect_to->frequency = BB_FREQ_MAX;
   update_br_prob_note (redirect_to);
 
   /* Edit SRC1 to go to REDIRECT_TO at NEWPOS1.  */
Index: tree-ssa-threadupdate.c
===================================================================
--- tree-ssa-threadupdate.c	(revision 129844)
+++ tree-ssa-threadupdate.c	(working copy)
@@ -442,10 +442,14 @@ redirect_edges (void **slot, void *data)
 	  remove_ctrl_stmt_and_useless_edges (local_info->bb,
 					      rd->outgoing_edge->dest);
 
-	  /* And fixup the flags on the single remaining edge.  */
+	  /* Fixup the flags on the single remaining edge.  */
 	  single_succ_edge (local_info->bb)->flags
 	    &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE | EDGE_ABNORMAL);
 	  single_succ_edge (local_info->bb)->flags |= EDGE_FALLTHRU;
+
+	  /* And adjust count and frequency on BB.  */
+	  local_info->bb->count = e->count;
+	  local_info->bb->frequency = EDGE_FREQUENCY (e);
 	}
     }
 
/* PR rtl-optimization/33737 */
/* Testcase by Richard Guenther <rguenth@gcc.gnu.org> */

enum { PROP_0, PROP_DOUBLE_CLICK_TIME, PROP_DOUBLE_CLICK_DISTANCE, PROP_CURSOR_BLINK, PROP_CURSOR_BLINK_TIME, PROP_CURSOR_BLINK_TIMEOUT, PROP_SPLIT_CURSOR, PROP_THEME_NAME, PROP_ICON_THEME_NAME, PROP_FALLBACK_ICON_THEME, PROP_KEY_THEME_NAME, PROP_MENU_BAR_ACCEL, PROP_DND_DRAG_THRESHOLD, PROP_FONT_NAME, PROP_ICON_SIZES, PROP_MODULES, PROP_XFT_ANTIALIAS, PROP_XFT_HINTING, PROP_XFT_HINTSTYLE, PROP_XFT_RGBA, PROP_XFT_DPI, PROP_CURSOR_THEME_NAME, PROP_CURSOR_THEME_SIZE, PROP_ALTERNATIVE_BUTTON_ORDER, PROP_ALTERNATIVE_SORT_ARROWS, PROP_SHOW_INPUT_METHOD_MENU, PROP_SHOW_UNICODE_MENU, PROP_TIMEOUT_INITIAL, PROP_TIMEOUT_REPEAT, PROP_TIMEOUT_EXPAND, PROP_COLOR_SCHEME, PROP_ENABLE_ANIMATIONS, PROP_TOUCHSCREEN_MODE, PROP_TOOLTIP_TIMEOUT, PROP_TOOLTIP_BROWSE_TIMEOUT, PROP_TOOLTIP_BROWSE_MODE_TIMEOUT, PROP_KEYNAV_CURSOR_ONLY, PROP_KEYNAV_WRAP_AROUND, PROP_ERROR_BELL, PROP_COLOR_HASH, PROP_FILE_CHOOSER_BACKEND, PROP_PRINT_BACKENDS, PROP_PRINT_PREVIEW_COMMAND, PROP_ENABLE_MNEMONICS, PROP_ENABLE_ACCELS, PROP_RECENT_FILES_LIMIT };
void g_assert_warning (void) __attribute__((__noreturn__));
void gtk_settings_class_init (void)
{
    unsigned int result;
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_DOUBLE_CLICK_TIME) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_DOUBLE_CLICK_DISTANCE) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_CURSOR_BLINK) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_CURSOR_BLINK_TIME) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_CURSOR_BLINK_TIMEOUT) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_SPLIT_CURSOR) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_THEME_NAME) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_ICON_THEME_NAME) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_FALLBACK_ICON_THEME) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_KEY_THEME_NAME) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_MENU_BAR_ACCEL) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_DND_DRAG_THRESHOLD) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_FONT_NAME) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_ICON_SIZES) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_MODULES) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_XFT_ANTIALIAS) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_XFT_HINTING) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_XFT_HINTSTYLE) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_XFT_RGBA) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_XFT_DPI) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_CURSOR_THEME_NAME) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_CURSOR_THEME_SIZE) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_ALTERNATIVE_BUTTON_ORDER) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_ALTERNATIVE_SORT_ARROWS) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_SHOW_INPUT_METHOD_MENU) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_SHOW_UNICODE_MENU) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_TOOLTIP_BROWSE_TIMEOUT) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_TOOLTIP_BROWSE_MODE_TIMEOUT) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_KEYNAV_CURSOR_ONLY) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_KEYNAV_WRAP_AROUND) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_ERROR_BELL) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_FILE_CHOOSER_BACKEND) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_PRINT_PREVIEW_COMMAND) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_ENABLE_MNEMONICS) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
    result = settings_install_property_parser();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_ENABLE_ACCELS) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
     if (__builtin_expect (__extension__ ({
       int _g_boolean_var_;
       if (result == PROP_RECENT_FILES_LIMIT) _g_boolean_var_ = 1;
       else _g_boolean_var_ = 0;
       _g_boolean_var_;
   }), 1)) {
     }
     else g_assert_warning();
}

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