> > 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...@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...@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