X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fifcvt.c;h=66a65a4a7ab34b817150271ac6ea20b016eb0d2d;hb=bf3e1520c00cff0abcd998aac1c85f084f162d3e;hp=dd7764b921f0ba4ebdce7659e8bb3b31da532307;hpb=deb2741b38fe5c3702de0139b72df56eb72ebe35;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index dd7764b921f..66a65a4a7ab 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -6,7 +6,7 @@ GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) + the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT @@ -15,9 +15,8 @@ License for more details. You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING. If not, write to the Free - Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA - 02110-1301, USA. */ + along with GCC; see the file COPYING3. If not see + . */ #include "config.h" #include "system.h" @@ -46,6 +45,7 @@ #include "df.h" #include "vec.h" #include "vecprim.h" +#include "dbgcnt.h" #ifndef HAVE_conditional_execution #define HAVE_conditional_execution 0 @@ -67,7 +67,9 @@ #endif #ifndef MAX_CONDITIONAL_EXECUTE -#define MAX_CONDITIONAL_EXECUTE (BRANCH_COST + 1) +#define MAX_CONDITIONAL_EXECUTE \ + (BRANCH_COST (optimize_function_for_speed_p (cfun), false) \ + + 1) #endif #define IFCVT_MULTIPLE_DUMPS 1 @@ -88,15 +90,15 @@ static int num_true_changes; static int cond_exec_changed_p; /* Forward references. */ -static int count_bb_insns (basic_block); -static bool cheap_bb_rtx_cost_p (basic_block, int); +static int count_bb_insns (const_basic_block); +static bool cheap_bb_rtx_cost_p (const_basic_block, int); static rtx first_active_insn (basic_block); static rtx last_active_insn (basic_block, int); static basic_block block_fallthru (basic_block); static int cond_exec_process_insns (ce_if_block_t *, rtx, rtx, rtx, rtx, int); static rtx cond_exec_get_condition (rtx); static rtx noce_get_condition (rtx, rtx *, bool); -static int noce_operand_ok (rtx); +static int noce_operand_ok (const_rtx); static void merge_if_block (ce_if_block_t *); static int find_cond_trap (basic_block, edge, edge); static basic_block find_if_header (basic_block, int); @@ -114,7 +116,7 @@ static rtx block_has_only_trap (basic_block); /* Count the number of non-jump active insns in BB. */ static int -count_bb_insns (basic_block bb) +count_bb_insns (const_basic_block bb) { int count = 0; rtx insn = BB_HEAD (bb); @@ -137,16 +139,17 @@ count_bb_insns (basic_block bb) false if the cost of any instruction could not be estimated. */ static bool -cheap_bb_rtx_cost_p (basic_block bb, int max_cost) +cheap_bb_rtx_cost_p (const_basic_block bb, int max_cost) { int count = 0; rtx insn = BB_HEAD (bb); + bool speed = optimize_bb_for_speed_p (bb); while (1) { if (NONJUMP_INSN_P (insn)) { - int cost = insn_rtx_cost (PATTERN (insn)); + int cost = insn_rtx_cost (PATTERN (insn), speed); if (cost == 0) return false; @@ -626,6 +629,9 @@ struct noce_if_info from TEST_BB. For the noce transformations, we allow the symmetric form as well. */ bool then_else_reversed; + + /* Estimated cost of the particular branch instruction. */ + int branch_cost; }; static rtx noce_emit_store_flag (struct noce_if_info *, rtx, int, int); @@ -963,20 +969,20 @@ noce_try_store_flag_constants (struct noce_if_info *if_info) normalize = 0; else if (ifalse == 0 && exact_log2 (itrue) >= 0 && (STORE_FLAG_VALUE == 1 - || BRANCH_COST >= 2)) + || if_info->branch_cost >= 2)) normalize = 1; else if (itrue == 0 && exact_log2 (ifalse) >= 0 && can_reverse - && (STORE_FLAG_VALUE == 1 || BRANCH_COST >= 2)) + && (STORE_FLAG_VALUE == 1 || if_info->branch_cost >= 2)) normalize = 1, reversep = 1; else if (itrue == -1 && (STORE_FLAG_VALUE == -1 - || BRANCH_COST >= 2)) + || if_info->branch_cost >= 2)) normalize = -1; else if (ifalse == -1 && can_reverse - && (STORE_FLAG_VALUE == -1 || BRANCH_COST >= 2)) + && (STORE_FLAG_VALUE == -1 || if_info->branch_cost >= 2)) normalize = -1, reversep = 1; - else if ((BRANCH_COST >= 2 && STORE_FLAG_VALUE == -1) - || BRANCH_COST >= 3) + else if ((if_info->branch_cost >= 2 && STORE_FLAG_VALUE == -1) + || if_info->branch_cost >= 3) normalize = -1; else return FALSE; @@ -1107,7 +1113,7 @@ noce_try_addcc (struct noce_if_info *if_info) /* If that fails, construct conditional increment or decrement using setcc. */ - if (BRANCH_COST >= 2 + if (if_info->branch_cost >= 2 && (XEXP (if_info->a, 1) == const1_rtx || XEXP (if_info->a, 1) == constm1_rtx)) { @@ -1158,7 +1164,7 @@ noce_try_store_flag_mask (struct noce_if_info *if_info) int reversep; reversep = 0; - if ((BRANCH_COST >= 2 + if ((if_info->branch_cost >= 2 || STORE_FLAG_VALUE == -1) && ((if_info->a == const0_rtx && rtx_equal_p (if_info->b, if_info->x)) @@ -1317,7 +1323,7 @@ noce_try_cmove_arith (struct noce_if_info *if_info) /* ??? FIXME: Magic number 5. */ if (cse_not_expected && MEM_P (a) && MEM_P (b) - && BRANCH_COST >= 5) + && if_info->branch_cost >= 5) { a = XEXP (a, 0); b = XEXP (b, 0); @@ -1346,8 +1352,9 @@ noce_try_cmove_arith (struct noce_if_info *if_info) if insn_rtx_cost can't be estimated. */ if (insn_a) { - insn_cost = insn_rtx_cost (PATTERN (insn_a)); - if (insn_cost == 0 || insn_cost > COSTS_N_INSNS (BRANCH_COST)) + insn_cost = insn_rtx_cost (PATTERN (insn_a), + optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn_a))); + if (insn_cost == 0 || insn_cost > COSTS_N_INSNS (if_info->branch_cost)) return FALSE; } else @@ -1355,8 +1362,9 @@ noce_try_cmove_arith (struct noce_if_info *if_info) if (insn_b) { - insn_cost += insn_rtx_cost (PATTERN (insn_b)); - if (insn_cost == 0 || insn_cost > COSTS_N_INSNS (BRANCH_COST)) + insn_cost += insn_rtx_cost (PATTERN (insn_b), + optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn_b))); + if (insn_cost == 0 || insn_cost > COSTS_N_INSNS (if_info->branch_cost)) return FALSE; } @@ -1535,6 +1543,7 @@ noce_get_alt_condition (struct noce_if_info *if_info, rtx target, /* First, look to see if we put a constant in a register. */ prev_insn = prev_nonnote_insn (if_info->cond_earliest); if (prev_insn + && BLOCK_NUM (prev_insn) == BLOCK_NUM (if_info->cond_earliest) && INSN_P (prev_insn) && GET_CODE (PATTERN (prev_insn)) == SET) { @@ -1737,6 +1746,10 @@ noce_try_abs (struct noce_if_info *if_info) rtx cond, earliest, target, seq, a, b, c; int negate; + /* Reject modes with signed zeros. */ + if (HONOR_SIGNED_ZEROS (GET_MODE (if_info->x))) + return FALSE; + /* Recognize A and B as constituting an ABS or NABS. The canonical form is a branch around the negation, taken when the object is the first operand of a comparison against 0 that evaluates to true. */ @@ -1773,6 +1786,7 @@ noce_try_abs (struct noce_if_info *if_info) { rtx set, insn = prev_nonnote_insn (earliest); if (insn + && BLOCK_NUM (insn) == BLOCK_NUM (earliest) && (set = single_set (insn)) && rtx_equal_p (SET_DEST (set), c)) { @@ -1890,7 +1904,8 @@ noce_try_sign_mask (struct noce_if_info *if_info) INSN_B which can happen for e.g. conditional stores to memory. */ b_unconditional = (if_info->insn_b == NULL_RTX || BLOCK_FOR_INSN (if_info->insn_b) == if_info->test_bb); - if (rtx_cost (t, SET) >= COSTS_N_INSNS (2) + if (rtx_cost (t, SET, optimize_bb_for_speed_p (BLOCK_FOR_INSN (if_info->insn_b))) + >= COSTS_N_INSNS (2) && (!b_unconditional || t != if_info->b)) return FALSE; @@ -2072,7 +2087,7 @@ noce_get_condition (rtx jump, rtx *earliest, bool then_else_reversed) /* Return true if OP is ok for if-then-else processing. */ static int -noce_operand_ok (rtx op) +noce_operand_ok (const_rtx op) { /* We special-case memories, so handle any of them with no address side effects. */ @@ -2088,7 +2103,7 @@ noce_operand_ok (rtx op) /* Return true if a write into MEM may trap or fault. */ static bool -noce_mem_write_may_trap_or_fault_p (rtx mem) +noce_mem_write_may_trap_or_fault_p (const_rtx mem) { rtx addr; @@ -2138,6 +2153,44 @@ noce_mem_write_may_trap_or_fault_p (rtx mem) return false; } +/* Return whether we can use store speculation for MEM. TOP_BB is the + basic block above the conditional block where we are considering + doing the speculative store. We look for whether MEM is set + unconditionally later in the function. */ + +static bool +noce_can_store_speculate_p (basic_block top_bb, const_rtx mem) +{ + basic_block dominator; + + for (dominator = get_immediate_dominator (CDI_POST_DOMINATORS, top_bb); + dominator != NULL; + dominator = get_immediate_dominator (CDI_POST_DOMINATORS, dominator)) + { + rtx insn; + + FOR_BB_INSNS (dominator, insn) + { + /* If we see something that might be a memory barrier, we + have to stop looking. Even if the MEM is set later in + the function, we still don't want to set it + unconditionally before the barrier. */ + if (INSN_P (insn) + && (volatile_insn_p (PATTERN (insn)) + || (CALL_P (insn) && (!RTL_CONST_CALL_P (insn))))) + return false; + + if (memory_modified_in_insn_p (mem, insn)) + return true; + if (modified_in_p (XEXP (mem, 0), insn)) + return false; + + } + } + + return false; +} + /* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to convert it without using conditional execution. Return TRUE if we were successful at converting the block. */ @@ -2199,9 +2252,11 @@ noce_process_if_block (struct noce_if_info *if_info) COND_EARLIEST to JUMP. Make sure the relevant data is still intact. */ if (! insn_b + || BLOCK_NUM (insn_b) != BLOCK_NUM (if_info->cond_earliest) || !NONJUMP_INSN_P (insn_b) || (set_b = single_set (insn_b)) == NULL_RTX || ! rtx_equal_p (x, SET_DEST (set_b)) + || ! noce_operand_ok (SET_SRC (set_b)) || reg_overlap_mentioned_p (x, SET_SRC (set_b)) || modified_between_p (SET_SRC (set_b), PREV_INSN (if_info->cond_earliest), jump) @@ -2234,7 +2289,7 @@ noce_process_if_block (struct noce_if_info *if_info) if (GET_MODE (x) == BLKmode) return FALSE; - if (GET_MODE (x) == ZERO_EXTRACT + if (GET_CODE (x) == ZERO_EXTRACT && (GET_CODE (XEXP (x, 1)) != CONST_INT || GET_CODE (XEXP (x, 2)) != CONST_INT)) return FALSE; @@ -2247,6 +2302,7 @@ noce_process_if_block (struct noce_if_info *if_info) if (! noce_operand_ok (a) || ! noce_operand_ok (b)) return FALSE; + retry: /* Set up the info block for our subroutines. */ if_info->insn_a = insn_a; if_info->insn_b = insn_b; @@ -2290,17 +2346,31 @@ noce_process_if_block (struct noce_if_info *if_info) goto success; } - /* Disallow the "if (...) x = a;" form (with an implicit "else x = x;") - for optimizations if writing to x may trap or fault, i.e. it's a memory - other than a static var or a stack slot, is misaligned on strict - aligned machines or is read-only. - If x is a read-only memory, then the program is valid only if we - avoid the store into it. If there are stores on both the THEN and - ELSE arms, then we can go ahead with the conversion; either the - program is broken, or the condition is always false such that the - other memory is selected. */ - if (!set_b && MEM_P (orig_x) && noce_mem_write_may_trap_or_fault_p (orig_x)) - return FALSE; + if (!set_b && MEM_P (orig_x)) + { + /* Disallow the "if (...) x = a;" form (implicit "else x = x;") + for optimizations if writing to x may trap or fault, + i.e. it's a memory other than a static var or a stack slot, + is misaligned on strict aligned machines or is read-only. If + x is a read-only memory, then the program is valid only if we + avoid the store into it. If there are stores on both the + THEN and ELSE arms, then we can go ahead with the conversion; + either the program is broken, or the condition is always + false such that the other memory is selected. */ + if (noce_mem_write_may_trap_or_fault_p (orig_x)) + return FALSE; + + /* Avoid store speculation: given "if (...) x = a" where x is a + MEM, we only want to do the store if x is always set + somewhere in the function. This avoids cases like + if (pthread_mutex_trylock(mutex)) + ++global_variable; + where we only want global_variable to be changed if the mutex + is held. FIXME: This should ideally be expressed directly in + RTL somehow. */ + if (!noce_can_store_speculate_p (test_bb, orig_x)) + return FALSE; + } if (noce_try_move (if_info)) goto success; @@ -2330,6 +2400,13 @@ noce_process_if_block (struct noce_if_info *if_info) goto success; } + if (!else_bb && set_b) + { + insn_b = set_b = NULL_RTX; + b = orig_x; + goto retry; + } + return FALSE; success: @@ -2382,7 +2459,7 @@ noce_process_if_block (struct noce_if_info *if_info) REGS. COND is the condition we will test. */ static int -check_cond_move_block (basic_block bb, rtx *vals, VEC (int, heap) *regs, rtx cond) +check_cond_move_block (basic_block bb, rtx *vals, VEC (int, heap) **regs, rtx cond) { rtx insn; @@ -2443,7 +2520,7 @@ check_cond_move_block (basic_block bb, rtx *vals, VEC (int, heap) *regs, rtx con vals[REGNO (dest)] = src; - VEC_safe_push (int, heap, regs, REGNO (dest)); + VEC_safe_push (int, heap, *regs, REGNO (dest)); } return TRUE; @@ -2544,9 +2621,13 @@ cond_move_process_if_block (struct noce_if_info *if_info) memset (else_vals, 0, size); /* Make sure the blocks are suitable. */ - if (!check_cond_move_block (then_bb, then_vals, then_regs, cond) - || (else_bb && !check_cond_move_block (else_bb, else_vals, else_regs, cond))) - return FALSE; + if (!check_cond_move_block (then_bb, then_vals, &then_regs, cond) + || (else_bb && !check_cond_move_block (else_bb, else_vals, &else_regs, cond))) + { + VEC_free (int, heap, then_regs); + VEC_free (int, heap, else_regs); + return FALSE; + } /* Make sure the blocks can be used together. If the same register is set in both blocks, and is not set to a constant in both @@ -2567,7 +2648,11 @@ cond_move_process_if_block (struct noce_if_info *if_info) if (!CONSTANT_P (then_vals[reg]) && !CONSTANT_P (else_vals[reg]) && !rtx_equal_p (then_vals[reg], else_vals[reg])) - return FALSE; + { + VEC_free (int, heap, then_regs); + VEC_free (int, heap, else_regs); + return FALSE; + } } } @@ -2581,7 +2666,11 @@ cond_move_process_if_block (struct noce_if_info *if_info) branches, since if we convert we are going to always execute them. */ if (c > MAX_CONDITIONAL_EXECUTE) - return FALSE; + { + VEC_free (int, heap, then_regs); + VEC_free (int, heap, else_regs); + return FALSE; + } /* Try to emit the conditional moves. First do the then block, then do anything left in the else blocks. */ @@ -2593,11 +2682,17 @@ cond_move_process_if_block (struct noce_if_info *if_info) then_vals, else_vals, true))) { end_sequence (); + VEC_free (int, heap, then_regs); + VEC_free (int, heap, else_regs); return FALSE; } seq = end_ifcvt_sequence (if_info); if (!seq) - return FALSE; + { + VEC_free (int, heap, then_regs); + VEC_free (int, heap, else_regs); + return FALSE; + } loc_insn = first_active_insn (then_bb); if (!loc_insn) @@ -2630,7 +2725,6 @@ cond_move_process_if_block (struct noce_if_info *if_info) VEC_free (int, heap, then_regs); VEC_free (int, heap, else_regs); - return TRUE; } @@ -2651,6 +2745,7 @@ noce_find_if_block (basic_block test_bb, basic_block then_bb, else_bb, join_bb; bool then_else_reversed = false; rtx jump, cond; + rtx cond_earliest; struct noce_if_info if_info; /* We only ever should get here before reload. */ @@ -2726,7 +2821,7 @@ noce_find_if_block (basic_block test_bb, /* If this is not a standard conditional jump, we can't parse it. */ cond = noce_get_condition (jump, - &if_info.cond_earliest, + &cond_earliest, then_else_reversed); if (!cond) return FALSE; @@ -2742,8 +2837,11 @@ noce_find_if_block (basic_block test_bb, if_info.else_bb = else_bb; if_info.join_bb = join_bb; if_info.cond = cond; + if_info.cond_earliest = cond_earliest; if_info.jump = jump; if_info.then_else_reversed = then_else_reversed; + if_info.branch_cost = BRANCH_COST (optimize_bb_for_speed_p (test_bb), + predictable_edge_p (then_edge)); /* Do the real work. */ @@ -3311,8 +3409,8 @@ find_cond_trap (basic_block test_bb, edge then_edge, edge else_edge) } /* Attempt to generate the conditional trap. */ - seq = gen_cond_trap (code, XEXP (cond, 0), - XEXP (cond, 1), + seq = gen_cond_trap (code, copy_rtx (XEXP (cond, 0)), + copy_rtx (XEXP (cond, 1)), TRAP_CODE (PATTERN (trap))); if (seq == NULL) return FALSE; @@ -3510,7 +3608,9 @@ find_if_case_1 (basic_block test_bb, edge then_edge, edge else_edge) test_bb->index, then_bb->index); /* THEN is small. */ - if (! cheap_bb_rtx_cost_p (then_bb, COSTS_N_INSNS (BRANCH_COST))) + if (! cheap_bb_rtx_cost_p (then_bb, + COSTS_N_INSNS (BRANCH_COST (optimize_bb_for_speed_p (then_edge->src), + predictable_edge_p (then_edge))))) return FALSE; /* Registers set are dead, or are predicable. */ @@ -3624,7 +3724,9 @@ find_if_case_2 (basic_block test_bb, edge then_edge, edge else_edge) test_bb->index, else_bb->index); /* ELSE is small. */ - if (! cheap_bb_rtx_cost_p (else_bb, COSTS_N_INSNS (BRANCH_COST))) + if (! cheap_bb_rtx_cost_p (else_bb, + COSTS_N_INSNS (BRANCH_COST (optimize_bb_for_speed_p (else_edge->src), + predictable_edge_p (else_edge))))) return FALSE; /* Registers set are dead, or are predicable. */ @@ -3843,7 +3945,7 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb, if (INSN_P (insn)) { df_simulate_find_defs (insn, test_set); - df_simulate_one_insn_backwards (test_bb, insn, test_live); + df_simulate_one_insn (test_bb, insn, test_live); } prev = PREV_INSN (insn); if (insn == earliest) @@ -3953,7 +4055,7 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb, /* Main entry point for all if-conversion. */ static void -if_convert (bool recompute_dominance) +if_convert (void) { basic_block bb; int pass; @@ -3968,18 +4070,13 @@ if_convert (bool recompute_dominance) num_updated_if_blocks = 0; num_true_changes = 0; - /* Some transformations in this pass can create new pseudos, - if the pass runs before reload. Make sure we can do so. */ - gcc_assert (! no_new_pseudos || reload_completed); - loop_optimizer_init (AVOID_CFG_MODIFICATIONS); mark_loop_exit_edges (); loop_optimizer_finalize (); free_dominance_info (CDI_DOMINATORS); - /* Compute postdominators if we think we'll use them. */ - if (HAVE_conditional_execution || recompute_dominance) - calculate_dominance_info (CDI_POST_DOMINATORS); + /* Compute postdominators. */ + calculate_dominance_info (CDI_POST_DOMINATORS); df_set_flags (DF_LR_RUN_DCE); @@ -4056,7 +4153,8 @@ if_convert (bool recompute_dominance) static bool gate_handle_if_conversion (void) { - return (optimize > 0); + return (optimize > 0) + && dbg_cnt (if_conversion); } /* If-conversion and CFG cleanup. */ @@ -4068,15 +4166,17 @@ rest_of_handle_if_conversion (void) if (dump_file) dump_flow_info (dump_file, dump_flags); cleanup_cfg (CLEANUP_EXPENSIVE); - if_convert (false); + if_convert (); } cleanup_cfg (0); return 0; } -struct tree_opt_pass pass_rtl_ifcvt = +struct rtl_opt_pass pass_rtl_ifcvt = { + { + RTL_PASS, "ce1", /* name */ gate_handle_if_conversion, /* gate */ rest_of_handle_if_conversion, /* execute */ @@ -4088,15 +4188,16 @@ struct tree_opt_pass pass_rtl_ifcvt = 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - TODO_df_finish | - TODO_dump_func, /* todo_flags_finish */ - 'C' /* letter */ + TODO_df_finish | TODO_verify_rtl_sharing | + TODO_dump_func /* todo_flags_finish */ + } }; static bool gate_handle_if_after_combine (void) { - return (optimize > 0 && flag_if_conversion); + return optimize > 0 && flag_if_conversion + && dbg_cnt (if_after_combine); } @@ -4105,14 +4206,14 @@ gate_handle_if_after_combine (void) static unsigned int rest_of_handle_if_after_combine (void) { - no_new_pseudos = 0; - if_convert (true); - no_new_pseudos = 1; + if_convert (); return 0; } -struct tree_opt_pass pass_if_after_combine = +struct rtl_opt_pass pass_if_after_combine = { + { + RTL_PASS, "ce2", /* name */ gate_handle_if_after_combine, /* gate */ rest_of_handle_if_after_combine, /* execute */ @@ -4124,29 +4225,32 @@ struct tree_opt_pass pass_if_after_combine = 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - TODO_df_finish | + TODO_df_finish | TODO_verify_rtl_sharing | TODO_dump_func | - TODO_ggc_collect, /* todo_flags_finish */ - 'C' /* letter */ + TODO_ggc_collect /* todo_flags_finish */ + } }; static bool gate_handle_if_after_reload (void) { - return (optimize > 0 && flag_if_conversion2); + return optimize > 0 && flag_if_conversion2 + && dbg_cnt (if_after_reload); } static unsigned int rest_of_handle_if_after_reload (void) { - if_convert (true); + if_convert (); return 0; } -struct tree_opt_pass pass_if_after_reload = +struct rtl_opt_pass pass_if_after_reload = { + { + RTL_PASS, "ce3", /* name */ gate_handle_if_after_reload, /* gate */ rest_of_handle_if_after_reload, /* execute */ @@ -4158,8 +4262,8 @@ struct tree_opt_pass pass_if_after_reload = 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - TODO_df_finish | + TODO_df_finish | TODO_verify_rtl_sharing | TODO_dump_func | - TODO_ggc_collect, /* todo_flags_finish */ - 'E' /* letter */ + TODO_ggc_collect /* todo_flags_finish */ + } };