This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: PATCH: PR middle-end/60013: [4.9 Regression] Build of 176.gcc from CPU2000 loops in cc1 starting with r207231
- From: Jan Hubicka <hubicka at ucw dot cz>
- To: "H.J. Lu" <hjl dot tools at gmail dot com>
- Cc: gcc-patches at gcc dot gnu dot org, hubicka at ucw dot cz
- Date: Sun, 2 Feb 2014 20:15:15 +0100
- Subject: Re: PATCH: PR middle-end/60013: [4.9 Regression] Build of 176.gcc from CPU2000 loops in cc1 starting with r207231
- Authentication-results: sourceware.org; auth=none
- References: <20140202182713 dot GA10390 at gmail dot com>
>
> 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