diff mbox

PATCH: PR middle-end/60013: [4.9 Regression] Build of 176.gcc from CPU2000 loops in cc1 starting with r207231

Message ID 20140202182713.GA10390@gmail.com
State New
Headers show

Commit Message

H.J. Lu Feb. 2, 2014, 6:27 p.m. UTC
Hi,

Before r207231, we generate:

;;   basic block 12, loop depth 0
;;   Invalid sum of incoming frequencies 8210, should be 4809
;;    pred:       4
;;                13
;;                5
;;                6
;;                7
;;                10
;;                11
  _33 = _setjmp (&float_error);
  if (_33 != 0)
    goto <bb 13>;
  else
    goto <bb 9>;
;;    succ:       13
;;                9

;;   basic block 13, loop depth 0
;;    pred:       12
  copy_node (arg1_7(D));
  goto <bb 9>;
;;    succ:       12
;;                9

;;   basic block 14, loop depth 0
;;    pred:       5
;;                11
;;                7
;;                9
;;                3
;;                6
;;                4
  # _2 = PHI <t_26(5), arg2_11(D)(11), t_28(7), 0B(9), t_15(D)(3), _19(6), t_23(4)>
<L21>:
  return _2;
;;    succ:       EXIT

}

After r207231, we have

;;   basic block 12, loop depth 0
;;    pred:       11
;;                13
  _34 = _setjmp (&float_error);
  if (_34 != 0)
    goto <bb 14>;
  else
    goto <bb 9>;
;;    succ:       14
;;                9

;;   basic block 13, loop depth 0
;;    pred:       4
;;                14
;;                5
;;                6
;;                7
;;                10
  ABNORMAL_DISPATCHER (0);
;;    succ:       12

;;   basic block 14, loop depth 0
;;    pred:       12
  copy_node (arg1_8(D));
  goto <bb 9>;
;;    succ:       9
;;                13

;;   basic block 15, loop depth 0
;;    pred:       5
;;                11
;;                7
;;                9
;;                3
;;                6
;;                4
  # _2 = PHI <t_27(5), arg2_12(D)(11), t_29(7), 0B(9), t_16(D)(3), _20(6), t_24(4)>
<L21>:
  return _2;
;;    succ:       EXIT

}

basic block 13 only contains

  ABNORMAL_DISPATCHER (0);

which is an internal function and will be expanded to empty block:

;; Generating RTL for gimple basic block 13

;; ABNORMAL_DISPATCHER (0); 

(nil)

compute_bb_predicates goes into an infinite loop due to

;;   basic block 13, loop depth 0
;;    pred:       4
;;                14
;;                5
;;                6
;;                7
;;                10
  ABNORMAL_DISPATCHER (0);
;;    succ:       12

This patch changes compute_bb_predicates to skip basic blocks containing
IFN_ABNORMAL_DISPATCHER and updates estimate_function_body_sizes to use
Use false predicate if aux is NULL.

Tested on Linux/x86-64 with:

--enable-languages=c,c++,fortran,java,lto,objc,ada,obj-c++,go

and make check RUNTESTFLAGS="--target_board='unix{-m32,}'".  OK for
trunk?

Thanks.

H.J.
--
gcc/

2014-02-02  H.J. Lu  <hongjiu.lu@intel.com>

	PR middle-end/60013
	* basic-block.h (bb_has_abnormal_dispatcher): New prototype.
	* ipa-inline-analysis.c (compute_bb_predicates): Skip basic block
	containing IFN_ABNORMAL_DISPATCHER when computing predicate.
	(estimate_function_body_sizes): Use false predicate if aux is
	NULL.
	* tree-cfg.c (bb_has_abnormal_dispatcher): New functiom.

gcc/testsuite/

2014-02-02  H.J. Lu  <hongjiu.lu@intel.com>

	PR middle-end/60013
	* gcc.dg/torture/pr60013.c: New test.

Comments

Jan Hubicka Feb. 2, 2014, 7:15 p.m. UTC | #1
> 
> basic block 13 only contains
> 
>   ABNORMAL_DISPATCHER (0);
> 
> which is an internal function and will be expanded to empty block:
> 
> ;; Generating RTL for gimple basic block 13
> 
> ;; ABNORMAL_DISPATCHER (0); 
> 
> (nil)
> 
> compute_bb_predicates goes into an infinite loop due to

OK, how does it make compute_bb_predicates to go into an infinite loop?

I do not see why we would need to specifically ignore BBs with the dispatcher
here, bug it looks like some big in the termination of dataflow perhaps related
to internal function?

I will try to check.
Honza
> 
> ;;   basic block 13, loop depth 0
> ;;    pred:       4
> ;;                14
> ;;                5
> ;;                6
> ;;                7
> ;;                10
>   ABNORMAL_DISPATCHER (0);
> ;;    succ:       12
> 
> This patch changes compute_bb_predicates to skip basic blocks containing
> IFN_ABNORMAL_DISPATCHER and updates estimate_function_body_sizes to use
> Use false predicate if aux is NULL.
> 
> Tested on Linux/x86-64 with:
> 
> --enable-languages=c,c++,fortran,java,lto,objc,ada,obj-c++,go
> 
> and make check RUNTESTFLAGS="--target_board='unix{-m32,}'".  OK for
> trunk?
> 
> Thanks.
> 
> H.J.
> --
> gcc/
> 
> 2014-02-02  H.J. Lu  <hongjiu.lu@intel.com>
> 
> 	PR middle-end/60013
> 	* basic-block.h (bb_has_abnormal_dispatcher): New prototype.
> 	* ipa-inline-analysis.c (compute_bb_predicates): Skip basic block
> 	containing IFN_ABNORMAL_DISPATCHER when computing predicate.
> 	(estimate_function_body_sizes): Use false predicate if aux is
> 	NULL.
> 	* tree-cfg.c (bb_has_abnormal_dispatcher): New functiom.
> 
> gcc/testsuite/
> 
> 2014-02-02  H.J. Lu  <hongjiu.lu@intel.com>
> 
> 	PR middle-end/60013
> 	* gcc.dg/torture/pr60013.c: New test.
> 
> diff --git a/gcc/basic-block.h b/gcc/basic-block.h
> index 82729b4..4cb0238 100644
> --- a/gcc/basic-block.h
> +++ b/gcc/basic-block.h
> @@ -942,6 +942,9 @@ extern void default_rtl_profile (void);
>  typedef struct gcov_working_set_info gcov_working_set_t;
>  extern gcov_working_set_t *find_working_set (unsigned pct_times_10);
>  
> +/* In tree-cfg.c.  */
> +extern bool bb_has_abnormal_dispatcher (basic_block bb);
> +
>  /* Check tha probability is sane.  */
>  
>  static inline void
> diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
> index ffb8264..dc3ebe1 100644
> --- a/gcc/ipa-inline-analysis.c
> +++ b/gcc/ipa-inline-analysis.c
> @@ -1860,21 +1860,24 @@ compute_bb_predicates (struct cgraph_node *node,
>  	  struct predicate p = false_predicate ();
>  	  edge e;
>  	  edge_iterator ei;
> -	  FOR_EACH_EDGE (e, ei, bb->preds)
> -	    {
> -	      if (e->src->aux)
> -		{
> -		  struct predicate this_bb_predicate
> -		    = *(struct predicate *) e->src->aux;
> -		  if (e->aux)
> -		    this_bb_predicate
> -		      = and_predicates (summary->conds, &this_bb_predicate,
> -					(struct predicate *) e->aux);
> -		  p = or_predicates (summary->conds, &p, &this_bb_predicate);
> -		  if (true_predicate_p (&p))
> -		    break;
> -		}
> -	    }
> +	  if (!bb_has_abnormal_dispatcher (bb))
> +	    FOR_EACH_EDGE (e, ei, bb->preds)
> +	      {
> +		if (e->src->aux)
> +		  {
> +		    struct predicate this_bb_predicate
> +		      = *(struct predicate *) e->src->aux;
> +		    if (e->aux)
> +		      this_bb_predicate
> +			= and_predicates (summary->conds,
> +					  &this_bb_predicate,
> +					  (struct predicate *) e->aux);
> +		    p = or_predicates (summary->conds, &p,
> +				       &this_bb_predicate);
> +		    if (true_predicate_p (&p))
> +		      break;
> +		  }
> +	      }
>  	  if (false_predicate_p (&p))
>  	    gcc_assert (!bb->aux);
>  	  else
> @@ -2703,7 +2706,10 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early)
>  	  for (i = 0; i < loop->num_nodes; i++)
>  	    {
>  	      gimple_stmt_iterator gsi;
> -	      bb_predicate = *(struct predicate *) body[i]->aux;
> +	      if (body[i]->aux)
> +		bb_predicate = *(struct predicate *) body[i]->aux;
> +	      else
> +		bb_predicate = false_predicate ();
>  	      for (gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi);
>  		   gsi_next (&gsi))
>  		{
> diff --git a/gcc/testsuite/gcc.dg/torture/pr60013.c b/gcc/testsuite/gcc.dg/torture/pr60013.c
> new file mode 100644
> index 0000000..e9d7c4e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/pr60013.c
> @@ -0,0 +1,102 @@
> +/* { dg-do compile } */
> +
> +#include <setjmp.h>
> +
> +enum tree_code {
> +  INTEGER_CST,
> +  REAL_CST,
> +  CEIL_MOD_EXPR,
> +  FLOOR_MOD_EXPR,
> +  EXACT_DIV_EXPR,
> +  CEIL_DIV_EXPR,
> +  FLOOR_DIV_EXPR,
> +  PLUS_EXPR,
> +  BIT_IOR_EXPR
> +};
> +typedef union tree_node *tree;
> +struct tree_common
> +{
> +  unsigned int code : 8;
> +  unsigned unsigned_flag : 1;
> +};
> +struct tree_int_cst
> +{
> +  char common[sizeof (struct tree_common)];
> +  int int_cst_low;
> +  int int_cst_high;
> +};
> +struct tree_real_cst
> +{
> +  char common[sizeof (struct tree_common)];
> +  double real_cst;
> +};
> +union tree_node
> +{
> +  struct tree_common common;
> +  struct tree_int_cst int_cst;
> +  struct tree_real_cst real_cst;
> +};
> +extern tree build_int_2_wide (int, int);
> +extern tree size_int (unsigned int);
> +extern tree copy_node (tree);
> +extern int target_isnan (double);
> +static jmp_buf float_error;
> +int
> +add_double (l1, h1, l2, h2, lv, hv)
> +	int l1, h1, l2, h2;
> +	int *lv, *hv;
> +{
> +  int l, h;
> +  l = l1 + l2;
> +  h = h1 + h2 + ((unsigned int) l < l1);
> +  *lv = l;
> +  *hv = h;
> +  return ((~((h1) ^ (h2)) & ((h1) ^ (h))) < 0);
> +}
> +tree
> +const_binop (code, arg1, arg2, notrunc)
> +	enum tree_code code;
> +	register tree arg1, arg2;
> +	int notrunc;
> +{
> +  if (((enum tree_code) (arg1)->common.code) == INTEGER_CST)
> +    {
> +      register int int1l = ((arg1)->int_cst.int_cst_low);
> +      register int int1h = ((arg1)->int_cst.int_cst_high);
> +      int int2l = ((arg2)->int_cst.int_cst_low);
> +      int int2h = ((arg2)->int_cst.int_cst_high);
> +      int low, hi;
> +      register tree t;
> +      int overflow = 0;
> +      switch (code)
> +	{
> +	case BIT_IOR_EXPR:
> +	  t = build_int_2_wide ((int) (int1l | int2l), (int) (int1h | int2h));
> +	  break;
> +	case PLUS_EXPR:
> +	  overflow = add_double (int1l, int1h, int2l, int2h, &low, &hi);
> +	  t = build_int_2_wide ((int) (low), (int) (hi));
> +	  break;
> +	case FLOOR_DIV_EXPR: case CEIL_DIV_EXPR:
> +	case EXACT_DIV_EXPR:
> +	  return size_int (int1l / int2l);
> +	case FLOOR_MOD_EXPR: case CEIL_MOD_EXPR:
> +	  t = build_int_2_wide ((int) (low), (int) (hi));
> +	  break;
> +	default:
> +	  break;
> +	}
> +      return t;
> +    }
> +  if (((enum tree_code) (arg1)->common.code) == REAL_CST)
> +    {
> +      tree t;
> +      double d2;
> +      d2 = ((arg2)->real_cst.real_cst);
> +      if ((target_isnan (d2)))
> +	return arg2;
> +      else if (_setjmp (float_error))
> +	t = copy_node (arg1);
> +    }
> +  return 0;
> +}
> diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
> index dfc9b7b..f1075fd 100644
> --- a/gcc/tree-cfg.c
> +++ b/gcc/tree-cfg.c
> @@ -599,6 +599,25 @@ get_abnormal_succ_dispatcher (basic_block bb)
>    return NULL;
>  }
>  
> +/* Return TRUE if basic block BB contains IFN_ABNORMAL_DISPATCHER
> +   internal call, otherwise return FALSE.  */
> +
> +bool
> +bb_has_abnormal_dispatcher (basic_block bb)
> +{
> +  gimple_stmt_iterator gsi;
> +  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
> +    {
> +      gimple g = gsi_stmt (gsi);
> +      if (g
> +	  && is_gimple_call (g)
> +	  && gimple_call_internal_p (g)
> +	  && gimple_call_internal_fn (g) == IFN_ABNORMAL_DISPATCHER)
> +	return true;
> +    }
> +  return false;
> +}
> +
>  /* Helper function for make_edges.  Create a basic block with
>     with ABNORMAL_DISPATCHER internal call in it if needed, and
>     create abnormal edges from BBS to it and from it to FOR_BB
diff mbox

Patch

diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index 82729b4..4cb0238 100644
--- a/gcc/basic-block.h
+++ b/gcc/basic-block.h
@@ -942,6 +942,9 @@  extern void default_rtl_profile (void);
 typedef struct gcov_working_set_info gcov_working_set_t;
 extern gcov_working_set_t *find_working_set (unsigned pct_times_10);
 
+/* In tree-cfg.c.  */
+extern bool bb_has_abnormal_dispatcher (basic_block bb);
+
 /* Check tha probability is sane.  */
 
 static inline void
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index ffb8264..dc3ebe1 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -1860,21 +1860,24 @@  compute_bb_predicates (struct cgraph_node *node,
 	  struct predicate p = false_predicate ();
 	  edge e;
 	  edge_iterator ei;
-	  FOR_EACH_EDGE (e, ei, bb->preds)
-	    {
-	      if (e->src->aux)
-		{
-		  struct predicate this_bb_predicate
-		    = *(struct predicate *) e->src->aux;
-		  if (e->aux)
-		    this_bb_predicate
-		      = and_predicates (summary->conds, &this_bb_predicate,
-					(struct predicate *) e->aux);
-		  p = or_predicates (summary->conds, &p, &this_bb_predicate);
-		  if (true_predicate_p (&p))
-		    break;
-		}
-	    }
+	  if (!bb_has_abnormal_dispatcher (bb))
+	    FOR_EACH_EDGE (e, ei, bb->preds)
+	      {
+		if (e->src->aux)
+		  {
+		    struct predicate this_bb_predicate
+		      = *(struct predicate *) e->src->aux;
+		    if (e->aux)
+		      this_bb_predicate
+			= and_predicates (summary->conds,
+					  &this_bb_predicate,
+					  (struct predicate *) e->aux);
+		    p = or_predicates (summary->conds, &p,
+				       &this_bb_predicate);
+		    if (true_predicate_p (&p))
+		      break;
+		  }
+	      }
 	  if (false_predicate_p (&p))
 	    gcc_assert (!bb->aux);
 	  else
@@ -2703,7 +2706,10 @@  estimate_function_body_sizes (struct cgraph_node *node, bool early)
 	  for (i = 0; i < loop->num_nodes; i++)
 	    {
 	      gimple_stmt_iterator gsi;
-	      bb_predicate = *(struct predicate *) body[i]->aux;
+	      if (body[i]->aux)
+		bb_predicate = *(struct predicate *) body[i]->aux;
+	      else
+		bb_predicate = false_predicate ();
 	      for (gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi);
 		   gsi_next (&gsi))
 		{
diff --git a/gcc/testsuite/gcc.dg/torture/pr60013.c b/gcc/testsuite/gcc.dg/torture/pr60013.c
new file mode 100644
index 0000000..e9d7c4e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr60013.c
@@ -0,0 +1,102 @@ 
+/* { dg-do compile } */
+
+#include <setjmp.h>
+
+enum tree_code {
+  INTEGER_CST,
+  REAL_CST,
+  CEIL_MOD_EXPR,
+  FLOOR_MOD_EXPR,
+  EXACT_DIV_EXPR,
+  CEIL_DIV_EXPR,
+  FLOOR_DIV_EXPR,
+  PLUS_EXPR,
+  BIT_IOR_EXPR
+};
+typedef union tree_node *tree;
+struct tree_common
+{
+  unsigned int code : 8;
+  unsigned unsigned_flag : 1;
+};
+struct tree_int_cst
+{
+  char common[sizeof (struct tree_common)];
+  int int_cst_low;
+  int int_cst_high;
+};
+struct tree_real_cst
+{
+  char common[sizeof (struct tree_common)];
+  double real_cst;
+};
+union tree_node
+{
+  struct tree_common common;
+  struct tree_int_cst int_cst;
+  struct tree_real_cst real_cst;
+};
+extern tree build_int_2_wide (int, int);
+extern tree size_int (unsigned int);
+extern tree copy_node (tree);
+extern int target_isnan (double);
+static jmp_buf float_error;
+int
+add_double (l1, h1, l2, h2, lv, hv)
+	int l1, h1, l2, h2;
+	int *lv, *hv;
+{
+  int l, h;
+  l = l1 + l2;
+  h = h1 + h2 + ((unsigned int) l < l1);
+  *lv = l;
+  *hv = h;
+  return ((~((h1) ^ (h2)) & ((h1) ^ (h))) < 0);
+}
+tree
+const_binop (code, arg1, arg2, notrunc)
+	enum tree_code code;
+	register tree arg1, arg2;
+	int notrunc;
+{
+  if (((enum tree_code) (arg1)->common.code) == INTEGER_CST)
+    {
+      register int int1l = ((arg1)->int_cst.int_cst_low);
+      register int int1h = ((arg1)->int_cst.int_cst_high);
+      int int2l = ((arg2)->int_cst.int_cst_low);
+      int int2h = ((arg2)->int_cst.int_cst_high);
+      int low, hi;
+      register tree t;
+      int overflow = 0;
+      switch (code)
+	{
+	case BIT_IOR_EXPR:
+	  t = build_int_2_wide ((int) (int1l | int2l), (int) (int1h | int2h));
+	  break;
+	case PLUS_EXPR:
+	  overflow = add_double (int1l, int1h, int2l, int2h, &low, &hi);
+	  t = build_int_2_wide ((int) (low), (int) (hi));
+	  break;
+	case FLOOR_DIV_EXPR: case CEIL_DIV_EXPR:
+	case EXACT_DIV_EXPR:
+	  return size_int (int1l / int2l);
+	case FLOOR_MOD_EXPR: case CEIL_MOD_EXPR:
+	  t = build_int_2_wide ((int) (low), (int) (hi));
+	  break;
+	default:
+	  break;
+	}
+      return t;
+    }
+  if (((enum tree_code) (arg1)->common.code) == REAL_CST)
+    {
+      tree t;
+      double d2;
+      d2 = ((arg2)->real_cst.real_cst);
+      if ((target_isnan (d2)))
+	return arg2;
+      else if (_setjmp (float_error))
+	t = copy_node (arg1);
+    }
+  return 0;
+}
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index dfc9b7b..f1075fd 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -599,6 +599,25 @@  get_abnormal_succ_dispatcher (basic_block bb)
   return NULL;
 }
 
+/* Return TRUE if basic block BB contains IFN_ABNORMAL_DISPATCHER
+   internal call, otherwise return FALSE.  */
+
+bool
+bb_has_abnormal_dispatcher (basic_block bb)
+{
+  gimple_stmt_iterator gsi;
+  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+    {
+      gimple g = gsi_stmt (gsi);
+      if (g
+	  && is_gimple_call (g)
+	  && gimple_call_internal_p (g)
+	  && gimple_call_internal_fn (g) == IFN_ABNORMAL_DISPATCHER)
+	return true;
+    }
+  return false;
+}
+
 /* Helper function for make_edges.  Create a basic block with
    with ABNORMAL_DISPATCHER internal call in it if needed, and
    create abnormal edges from BBS to it and from it to FOR_BB