On 27/11/12 13:41, Richard Biener wrote: > On Mon, Nov 19, 2012 at 3:33 AM, Tom de Vries <tom_devr...@mentor.com> wrote: >> Richard, >> >> Consider the PR55124 example test.c: >> ... >> int a, b; >> long c; >> >> static void inline >> f2 (void) >> { >> unsigned long k = 1; >> >> foo (b ? k = 0 : 0); >> >> b = (((c = b) >> ? (k ?: (c = 0)) >> : a) >> * c); >> } >> >> void >> f1 (void) >> { >> f2 (); >> a = b | c; >> } >> ... >> >> when compiling with -O2, we're running into the following assertion in pre: >> ... >> test.c:18:1: internal compiler error: in find_or_generate_expression, at >> tree-ssa-pre.c:2802 >> f1 (void) >> ^ >> 0xcf41d3 find_or_generate_expression >> gcc/tree-ssa-pre.c:2802 >> 0xcf42f6 create_expression_by_pieces >> gcc/tree-ssa-pre.c:2861 >> 0xcf4193 find_or_generate_expression >> gcc/tree-ssa-pre.c:2799 >> 0xcf42f6 create_expression_by_pieces >> gcc/tree-ssa-pre.c:2861 >> 0xcf4e28 insert_into_preds_of_block >> gcc/tree-ssa-pre.c:3096 >> 0xcf5c7d do_regular_insertion >> gcc/tree-ssa-pre.c:3386 >> ... >> >> We're hitting the assert at the end of find_or_generate_expression: >> ... >> static tree >> find_or_generate_expression (basic_block block, tree op, gimple_seq *stmts) >> { >> pre_expr expr = get_or_alloc_expr_for (op); >> unsigned int lookfor = get_expr_value_id (expr); >> pre_expr leader = bitmap_find_leader (AVAIL_OUT (block), lookfor); >> if (leader) >> { >> if (leader->kind == NAME) >> return PRE_EXPR_NAME (leader); >> else if (leader->kind == CONSTANT) >> return PRE_EXPR_CONSTANT (leader); >> } >> >> /* It must be a complex expression, so generate it recursively. */ >> bitmap exprset = VEC_index (bitmap, value_expressions, lookfor); >> bitmap_iterator bi; >> unsigned int i; >> EXECUTE_IF_SET_IN_BITMAP (exprset, 0, i, bi) >> { >> pre_expr temp = expression_for_id (i); >> if (temp->kind != NAME) >> return create_expression_by_pieces (block, temp, stmts, >> get_expr_type (expr)); >> } >> >> gcc_unreachable (); >> } >> ... >> >> The state in which we're asserting is the following: >> ... >> #5 0x0000000000cf41d4 in find_or_generate_expression (block=0x7ffff6210f08, >> op=0x7ffff62384c8, stmts=0x7fffffffdb78) at gcc/tree-ssa-pre.c:2802 >> 2802 gcc_unreachable (); >> (gdb) p block.index >> $13 = 4 >> (gdb) call debug_generic_expr (op) >> b.4_3 >> (gdb) call debug_pre_expr (expr) >> b.4_3 >> (gdb) p lookfor >> $11 = 7 >> (gdb) call debug_bitmap_set (((bb_value_sets_t) ((block)->aux))->avail_out) >> debug[0] := { b.4_8 (0012), a.10_13 (0013), _14 (0014), iftmp.5_15 (0015) } >> (gdb) p leader >> $12 = (pre_expr) 0x0 >> (gdb) call debug_bitmap ( exprset ) >> first = 0x21fb058 current = 0x21fb058 indx = 0 >> 0x21fb058 next = (nil) prev = (nil) indx = 0 >> bits = { 22 25 } >> (gdb) call debug_pre_expr (expression_for_id (22)) >> b.4_3 >> (gdb) call debug_pre_expr (expression_for_id (25)) >> b.4_31 >> ... >> We're trying to find or generate an expr with value-id 0007 in block 4. We >> can't >> find it (there's no leader) and we can't generate it because there are no >> exprs >> with that value that are not names. >> >> Higher up in the call stack and skipping create_expression_by_pieces, the >> state >> is as follows: >> ... >> #7 0x0000000000cf4194 in find_or_generate_expression (block=0x7ffff6210f08, >> op=0x7ffff6238558, stmts=0x7fffffffdb78) at gcc/tree-ssa-pre.c:2799 >> 2799 get_expr_type (expr)); >> (gdb) call debug_generic_expr (op) >> c.6_5 >> (gdb) call debug_pre_expr (expr) >> c.6_5 >> (gdb) p lookfor >> $14 = 9 >> (gdb) p leader >> $15 = (pre_expr) 0x0 >> (gdb) call debug_bitmap ( exprset ) >> first = 0x21fb0f8 current = 0x21fb0f8 indx = 0 >> 0x21fb0f8 next = (nil) prev = (nil) indx = 0 >> bits = { 23 24 26 27 } >> (gdb) call debug_pre_expr (temp) >> {nop_expr,b.4_3} >> (gdb) call debug_pre_expr (expression_for_id (23)) >> c.6_5 >> (gdb) call debug_pre_expr (expression_for_id (24)) >> {nop_expr,b.4_3} >> (gdb) call debug_pre_expr (expression_for_id (26)) >> c.6_32 >> (gdb) call debug_pre_expr (expression_for_id (27)) >> {mem_ref<0B>,addr_expr<&c>}@.MEM_28 >> ... >> We're trying to find or generate an expr with value-id 0009 (in block 4). We >> can't find it. We're trying to generate it using {nop_expr,b.4_3}, but as >> we've >> seen above that won't work. The generation using expr 27 would work though. >> >> Again higher up in the call stack and skipping create_expression_by_pieces, >> the >> state is as follows: >> ... >> (gdb) up >> #9 0x0000000000cf4e29 in insert_into_preds_of_block (block=0x7ffff6210f70, >> exprnum=19, avail=0x22102e0) at gcc/tree-ssa-pre.c:3096 >> 3096 &stmts, type); >> (gdb) l >> 3091 eprime = VEC_index (pre_expr, avail, pred->dest_idx); >> 3092 >> 3093 if (eprime->kind != NAME && eprime->kind != CONSTANT) >> 3094 { >> 3095 builtexpr = create_expression_by_pieces (bprime, eprime, >> 3096 &stmts, type); >> (gdb) p block.index >> $17 = 5 >> (gdb) call debug_pre_expr (expr) >> {convert_expr,c.7_16} >> (gdb) p val >> $18 = 8 >> (gdb) call debug_pre_expr (eprime) >> {convert_expr,c.6_5} >> (gdb) call get_expr_value_id (eprime) >> $16 = 26 >> ... >> So we're trying to insert expr {convert_expr,c.6_5} with value-id 0026 into >> block 4. The expr is the phi-translation of expr {convert_expr,c.7_16} with >> value-id 0008 in block 5. >> >> One of the reasons why we're inserting the phi-translation of expr >> {convert_expr,c.7_16} in block 4 is because it's a member of ANTIC_IN[5]: >> ... >> ANTIC_IN[5] := { iftmp.5_18 (0018), {mem_ref<0B>,addr_expr<&c>}@.MEM_23 >> (0016), >> {nop_expr,c.7_16} (0017), {mult_expr,_17,iftmp.5_18} (0019), >> {nop_expr,_19} (0020), {convert_expr,c.7_16} (0008), >> {bit_ior_expr,_4,b.11_20} (0010) } >> ... >> A requirement for an expr to be in ANTIC_IN is that that it's either 'a live >> temporary or a non-simple expression whose operands are represented in the >> anti-leader set'. The operand is c.7_16, which has value id 0016, as we can >> see >> here: >> ... >> tmp_gen[5] := { c.7_16 (0016), _17 (0017), _19 (0019), b.11_20 (0020), _4 >> (0008), a.2_6 (0010) } >> ... >> And it has this representation in ANTIC_IN[5] in expr >> {mem_ref<0B>,addr_expr<&c>}@.MEM_23. So that looks ok. >> >> The order in which we traverse ANTIC_IN[5] in do_regular_insertion is this: >> ... >> (gdb) call debug_pre_expr ( exprs.vec_[0] ) >> {convert_expr,c.7_16} >> (gdb) call debug_pre_expr ( exprs.vec_[1] ) >> {bit_ior_expr,_4,b.11_20} >> (gdb) call debug_pre_expr ( exprs.vec_[2] ) >> {mem_ref<0B>,addr_expr<&c>}@.MEM_23 >> (gdb) call debug_pre_expr ( exprs.vec_[3] ) >> {nop_expr,c.7_16} >> (gdb) call debug_pre_expr ( exprs.vec_[4] ) >> iftmp.5_18 >> (gdb) call debug_pre_expr ( exprs.vec_[5] ) >> {mult_expr,_17,iftmp.5_18} >> (gdb) call debug_pre_expr ( exprs.vec_[6] ) >> {nop_expr,_19} >> ... >> >> The order is indeed in increasing value-id order: >> ... >> (gdb) call get_expr_value_id ( exprs.vec_[0] ) >> $11 = 8 >> (gdb) call get_expr_value_id ( exprs.vec_[1] ) >> $12 = 10 >> (gdb) call get_expr_value_id ( exprs.vec_[2] ) >> $13 = 16 >> (gdb) call get_expr_value_id ( exprs.vec_[3] ) >> $14 = 17 >> (gdb) call get_expr_value_id ( exprs.vec_[4] ) >> $15 = 18 >> (gdb) call get_expr_value_id ( exprs.vec_[5] ) >> $16 = 19 >> (gdb) call get_expr_value_id ( exprs.vec_[6] ) >> $17 = 20 >> ... >> >> But the operand of the first expr {convert_expr,c.7_16} has value-id 0016, >> which >> corresponds to the 3rd expr {mem_ref<0B>,addr_expr<&c>}@.MEM_23. So if I >> understand the intended topological sort correctly, this is in the wrong >> order, >> we should be processing the 3rd element before the first element. I'm not >> quite >> sure this is the root cause of the problem though. >> >> Assuming for the moment that the order is correct, I've written a tentative >> patch that fixes the assert, simply by predicting whether >> create_expression_by_pieces will succeed or not, and to skip those calls that >> will fail in find_or_generate_expression. The patch has only been tested >> with a >> tree-ssa.exp testrun, but no issues found there. >> >> Do you think this patch is the way to fix this ICE, or is it the order of >> generation that needs fixing, or is the problem yet something else? > > This looks like an ordering issue. But rather in what value-numbers were > assigned to the expressions, not the sorting itself.
The sorting done by sorted_array_from_bitmap_set assumes that value_id order is in topological order: ... FOR_EACH_VALUE_ID_IN_SET (set, i, bi) { /* The number of expressions having a given value is usually relatively small. Thus, rather than making a vector of all the expressions and sorting it by value-id, we walk the values and check in the reverse mapping that tells us what expressions have a given value, to filter those in our set. As a result, the expressions are inserted in value-id order, which means topological order. If this is somehow a significant lose for some cases, we can choose which set to walk based on the set size. */ bitmap exprset = VEC_index (bitmap, value_expressions, i); EXECUTE_IF_SET_IN_BITMAP (exprset, 0, j, bj) { if (bitmap_bit_p (&set->expressions, j)) VEC_safe_push (pre_expr, heap, result, expression_for_id (j)); } } ... The relevant ssa-names are _4 and _16: ... # VUSE <.MEM_23> c.7_16 = cD.1716; _4 = (intD.6) c.7_16; ... which have the following value ids, which means that they're not in topological order: ... _4 = _4 value_id 8 c.7_16 = c.7_16 value_id 16 ... If I revert patch r189321, the compiler doesn't assert anymore. But if I look at the relevant ssa-names, the value numbers are still not in topological order: ... _4 = _4 value_id 5 c.7_16 = c.7_16 value_id 13 ... Assigning these value_ids is done in run_scc_vn. I don't find any evidence there that an effort is done to number values in topological order, so my conclusion is that the premise in sorted_array_from_bitmap_set about value-id order meaning topological order is invalid. I suspect that value_ids introduced after value numbering, by pre itself, are in topological order though. > I suppose it may > result from your vitrual operand numbering changes and compute_avail > doing > > case VN_REFERENCE: > { > vn_reference_t ref; > vn_reference_lookup (gimple_assign_rhs1 (stmt), > gimple_vuse (stmt), > VN_WALK, &ref); > > which valueizes the VUSE here? > The value numbers are out of order, with and without the patch, so I don't see the connection with the patch or with virtual operand numbering changes. I can think of a few ways to fix this: - add assignment of value_id during value numbering rather than after value numbering - try to add a topo_id <-> value_id mapping during building up the pre_exprs, and use that in sorted_array_from_bitmap_set - do actual topological sorting in sorted_array_from_bitmap_set (FWIW, patch attached, passes tree-ssa.exp) In what way do you think should this be fixed? Thanks, - Tom
Index: gcc/bitmap.c =================================================================== --- gcc/bitmap.c (revision 192023) +++ gcc/bitmap.c (working copy) @@ -539,6 +539,15 @@ to_ptr = to_elt; } } + +void +bitmap_swap (bitmap a, bitmap b) +{ + bitmap_head tmp = *a; + *a = *b; + *b = tmp; +} + /* Find a bitmap element that would hold a bitmap's bit. Update the `current' field even if we can't find an element that Index: gcc/bitmap.h =================================================================== --- gcc/bitmap.h (revision 192023) +++ gcc/bitmap.h (working copy) @@ -200,6 +200,9 @@ /* Copy a bitmap to another bitmap. */ extern void bitmap_copy (bitmap, const_bitmap); +/* Swap 2 bitmaps. */ +extern void bitmap_swap (bitmap, bitmap); + /* True if two bitmaps are identical. */ extern bool bitmap_equal_p (const_bitmap, const_bitmap); Index: gcc/tree-ssa-pre.c =================================================================== --- gcc/tree-ssa-pre.c (revision 192023) +++ gcc/tree-ssa-pre.c (working copy) @@ -715,30 +715,183 @@ unsigned int i, j; bitmap_iterator bi, bj; VEC(pre_expr, heap) *result; + bitmap todo = BITMAP_ALLOC (NULL); + bitmap values_done = BITMAP_ALLOC (NULL); + bitmap values_new = BITMAP_ALLOC (NULL); + bitmap_head *waiting = NULL; + unsigned int waiting_size = get_max_value_id () + 1; + int *nr_waiting = NULL; + unsigned int nr_waiting_size = next_expression_id; /* Pre-allocate roughly enough space for the array. */ result = VEC_alloc (pre_expr, heap, bitmap_count_bits (&set->values)); + /* Handle expressions without dependencies, put expressions with dependencies + in todo. */ + EXECUTE_IF_SET_IN_BITMAP (&set->expressions, 0, i, bi) + { + pre_expr expr = expression_for_id (i); + switch (expr->kind) + { + case NAME: + case CONSTANT: + break; + + default: + bitmap_set_bit (todo, i); + continue; + } + + VEC_safe_push (pre_expr, heap, result, expr); + bitmap_set_bit (values_done, get_expr_value_id (expr)); + } + + /* Handle expressions with dependencies. Put expressions with unready + dependencies in waiting. Do this in value-id order, so that if the + value-id order is already a topological order, we won't use the waiting + arrays. */ FOR_EACH_VALUE_ID_IN_SET (set, i, bi) { - /* The number of expressions having a given value is usually - relatively small. Thus, rather than making a vector of all - the expressions and sorting it by value-id, we walk the values - and check in the reverse mapping that tells us what expressions - have a given value, to filter those in our set. As a result, - the expressions are inserted in value-id order, which means - topological order. - - If this is somehow a significant lose for some cases, we can - choose which set to walk based on the set size. */ bitmap exprset = VEC_index (bitmap, value_expressions, i); - EXECUTE_IF_SET_IN_BITMAP (exprset, 0, j, bj) + EXECUTE_IF_AND_IN_BITMAP (exprset, todo, 0, j, bj) { - if (bitmap_bit_p (&set->expressions, j)) - VEC_safe_push (pre_expr, heap, result, expression_for_id (j)); - } + pre_expr expr = expression_for_id (j); + bool wait = false; + switch (expr->kind) + { + case NARY: + { + vn_nary_op_t nary = PRE_EXPR_NARY (expr); + unsigned int k; + for (k = 0; k < nary->length; k++) + { + tree op = nary->op[k]; + if (TREE_CODE (op) != SSA_NAME) + continue; + unsigned int v = VN_INFO (op)->value_id; + if (!bitmap_bit_p (values_done, v) + && bitmap_bit_p (&set->values, v)) + { + if (waiting == NULL) + { + waiting = XCNEWVEC (bitmap_head, waiting_size); + nr_waiting = XCNEWVEC (int, nr_waiting_size); + } + if (waiting[v].obstack == NULL) + bitmap_initialize (&waiting[v], + &bitmap_default_obstack); + if (!bitmap_bit_p (&waiting[v], j)) + { + bitmap_set_bit (&waiting[v], j); + nr_waiting[j]++; + } + wait = true; + } + } + } + break; + + case REFERENCE: + { + vn_reference_t ref = PRE_EXPR_REFERENCE (expr); + vn_reference_op_t vro; + + unsigned int k; + FOR_EACH_VEC_ELT (vn_reference_op_s, ref->operands, k, vro) + { + tree ops[3] = { vro->op0, vro->op1, vro->op2}; + unsigned int l; + for (l = 0; l < 3; l++) + { + tree op = ops[l]; + if (op == NULL_TREE + || TREE_CODE (op) != SSA_NAME) + continue; + unsigned int v = VN_INFO (op)->value_id; + if (!bitmap_bit_p (values_done, v) + && bitmap_bit_p (&set->values, v)) + { + if (waiting == NULL) + { + waiting = XCNEWVEC (bitmap_head, waiting_size); + nr_waiting = XCNEWVEC (int, nr_waiting_size); + } + if (waiting[v].obstack == NULL) + bitmap_initialize (&waiting[v], + &bitmap_default_obstack); + if (!bitmap_bit_p (&waiting[v], j)) + { + bitmap_set_bit (&waiting[v], j); + nr_waiting[j]++; + } + wait = true; + } + } + } + } + break; + + default: + gcc_unreachable (); + } + + /* The dependencies are not ready, so wait. */ + if (wait) + continue; + + /* The dependencies are ready so add the expr. */ + VEC_safe_push (pre_expr, heap, result, expr); + unsigned int value_id = get_expr_value_id (expr); + if (!bitmap_bit_p (values_done, value_id)) + { + bitmap_set_bit (values_new, value_id); + bitmap_set_bit (values_done, value_id); + } + } } + /* Handle newly produced values, decrease wait count for appropriate + expressions and handle ready expressions. Iterate until done. */ + while (!bitmap_empty_p (values_new) + && waiting != NULL) + { + bitmap_clear (todo); + bitmap_swap (todo, values_new); + + EXECUTE_IF_SET_IN_BITMAP (todo, 0, i, bi) + { + if (waiting[i].obstack == NULL) + continue; + + EXECUTE_IF_SET_IN_BITMAP (&waiting[i], 0, j, bj) + { + nr_waiting[j]--; + gcc_assert (nr_waiting[j] >= 0); + if (nr_waiting[j] == 0) + { + pre_expr expr = expression_for_id (j); + + VEC_safe_push (pre_expr, heap, result, expr); + unsigned int value_id = get_expr_value_id (expr); + if (!bitmap_bit_p (values_done, value_id)) + { + bitmap_set_bit (values_done, value_id); + bitmap_set_bit (values_new, value_id); + } + } + } + bitmap_clear (&waiting[i]); + } + } + + gcc_assert (bitmap_count_bits (&set->expressions) + == VEC_length (pre_expr, result)); + BITMAP_FREE (todo); + BITMAP_FREE (values_done); + BITMAP_FREE (values_new); + XDELETE (waiting); + XDELETE (nr_waiting); + return result; }