diff options
-rw-r--r-- | gcc/ChangeLog | 50 | ||||
-rw-r--r-- | gcc/cfgcleanup.c | 22 | ||||
-rw-r--r-- | gcc/combine.c | 6 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/emit-rtl.c | 21 | ||||
-rw-r--r-- | gcc/expr.c | 20 | ||||
-rw-r--r-- | gcc/final.c | 13 | ||||
-rw-r--r-- | gcc/gimplify.c | 2 | ||||
-rw-r--r-- | gcc/java/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/java/parse.y | 22 | ||||
-rw-r--r-- | gcc/rtl.c | 3 | ||||
-rw-r--r-- | gcc/rtl.h | 11 | ||||
-rw-r--r-- | gcc/stmt.c | 300 | ||||
-rw-r--r-- | gcc/toplev.c | 3 | ||||
-rw-r--r-- | gcc/tree-cfg.c | 17 | ||||
-rw-r--r-- | gcc/tree-eh.c | 11 | ||||
-rw-r--r-- | gcc/tree-flow.h | 2 | ||||
-rw-r--r-- | gcc/tree-optimize.c | 30 | ||||
-rw-r--r-- | gcc/tree.h | 8 |
20 files changed, 142 insertions, 411 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f72d122..48b3e20 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,53 @@ +2004-07-17 Steven Bosscher <stevenb@suse.de> + + * cfgcleanup.c (try_simplify_condjump): Don't remove line + notes to avoid unreachable code warnings. + * toplev.c (backend_init): Don't emit line notes for + unreachable code warnings. + + * combine.c (distribute_notes): Don't distribute a + REG_VTABLE_REF note. + * final.c (final_scan_insn): Don't handle it. + * rtl.c (reg_note_name): Remove it. + * rtl.h (enum reg_node): Dito. + + * emit-rtl.c (force_line_numbers, restore_line_number_status): + Remove. + * rtl.h (force_line_numbers, restore_line_number_status): + Remove prototypes. + + * stmt.c (using_eh_for_cleanups_p, using_eh_for_cleanups): Move... + * tree-eh.c (using_eh_for_cleanups_p): ...here. Make static. + (using_eh_for_cleanups): Also moved here. + + * expr.c (expand_expr_real_1) <CASE_LABEL_EXPR>: Die if we see one. + <SWITCH_EXPR>: Die if we have a non-NULL SWITCH_BODY. Update calls + to expand_start_case and add_case_node. + * stmt.c (struct nesting): Cleanup unused fields condition_code, + last_unconditional_cleanup, nominal_type, printname, and + line_number_status. + (struct fixup_goto): Remove. + (struct stmt_status): Remove x_goto_fixup_chain field. + (goto_fixup_chain): Remove. + (strip_default_case_nodes, group_case_nodes, emit_jump_if_reachable, + pushcase, pushcase_range): Remove. + (expand_start_bindings_and_block): Don't set unused fields in + the nesting stack. + (expand_start_case, add_case_node): Cleanup unused formal arguments. + (expand_end_case_type): Don't simplify the case-list. Use emit_jump + instead of emit_jump_if_reachable. + (emit_case_nodes): Likewise. + * tree-cfg.c (group_case_labels, cleanup_dead_labels): No longer + static. + (update_eh_label): Work around left-over exception handing regions. + * tree-flow.h (group_case_labels, cleanup_dead_labels): Add protos. + * tree-optimize.c (execute_cleanup_cfg_post_optimizing): New function. + (pass_cleanup_cfg_post_optimizing): New pass. + (init_tree_optimization_passes): Run the new pass after all + optimizations. + * tree.h (pushcase, pushcase_range): Remove prototypes. + (expand_start_case, add_case_node): Update prototypes. + 2004-07-16 Krister Walfridsson <cato@df.lth.se> * tree-inline.c (estimate_num_insns_1): Correct increase of count. diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index f167800..f704d31 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -122,8 +122,6 @@ try_simplify_condjump (basic_block cbranch_block) basic_block jump_block, jump_dest_block, cbranch_dest_block; edge cbranch_jump_edge, cbranch_fallthru_edge; rtx cbranch_insn; - rtx insn, next; - rtx end; /* Verify that there are exactly two successors. */ if (!cbranch_block->succ @@ -186,26 +184,6 @@ try_simplify_condjump (basic_block cbranch_block) cbranch_fallthru_edge->flags &= ~EDGE_FALLTHRU; update_br_prob_note (cbranch_block); - end = BB_END (jump_block); - /* Deleting a block may produce unreachable code warning even when we are - not deleting anything live. Suppress it by moving all the line number - notes out of the block. */ - for (insn = BB_HEAD (jump_block); insn != NEXT_INSN (BB_END (jump_block)); - insn = next) - { - next = NEXT_INSN (insn); - if (NOTE_P (insn) && NOTE_LINE_NUMBER (insn) > 0) - { - if (insn == BB_END (jump_block)) - { - BB_END (jump_block) = PREV_INSN (insn); - if (insn == end) - break; - } - reorder_insns_nobb (insn, insn, end); - end = insn; - } - } /* Delete the block with the unconditional jump, and clean up the mess. */ delete_basic_block (jump_block); tidy_fallthru_edge (cbranch_jump_edge); diff --git a/gcc/combine.c b/gcc/combine.c index 0b4b4ca..e6002d6 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -11698,12 +11698,6 @@ distribute_notes (rtx notes, rtx from_insn, rtx i3, rtx i2) /* Just get rid of this note, as it is unused later anyway. */ break; - case REG_VTABLE_REF: - /* ??? Should remain with *a particular* memory load. Given the - nature of vtable data, the last insn seems relatively safe. */ - place = i3; - break; - case REG_NON_LOCAL_GOTO: if (JUMP_P (i3)) place = i3; diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3945ebf..472b101 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2004-07-16 Steven Bosscher <stevenb@suse.de> + + * cp-tree.h (struct lang_type): Don't have three GTY options on a + single bit GTY desc. + 2004-07-16 Richard Henderson <rth@redhat.com> * cp-lang.c (LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING): Die. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index f61dc39..e7069ba 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -1033,7 +1033,7 @@ struct lang_type GTY(()) { union lang_type_u { - struct lang_type_header GTY((tag ("2"))) h; + struct lang_type_header GTY((skip (""))) h; struct lang_type_class GTY((tag ("1"))) c; struct lang_type_ptrmem GTY((tag ("0"))) ptrmem; } GTY((desc ("%h.h.is_lang_type_class"))) u; diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index cca6f63..0f32005 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -5438,27 +5438,6 @@ init_emit_once (int line_numbers) pic_offset_table_rtx = gen_raw_REG (Pmode, PIC_OFFSET_TABLE_REGNUM); } -/* Query and clear/ restore no_line_numbers. This is used by the - switch / case handling in stmt.c to give proper line numbers in - warnings about unreachable code. */ - -int -force_line_numbers (void) -{ - int old = no_line_numbers; - - no_line_numbers = 0; - if (old) - force_next_line_note (); - return old; -} - -void -restore_line_number_status (int old_value) -{ - no_line_numbers = old_value; -} - /* Produce exact duplicate of insn INSN after AFTER. Care updating of libcall regions if present. */ @@ -8541,6 +8541,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, case WITH_CLEANUP_EXPR: case CLEANUP_POINT_EXPR: case TARGET_EXPR: + case CASE_LABEL_EXPR: case VA_ARG_EXPR: /* Lowered by gimplify.c. */ abort (); @@ -8561,10 +8562,11 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, abort (); case SWITCH_EXPR: - expand_start_case (0, SWITCH_COND (exp), integer_type_node, - "switch"); + expand_start_case (SWITCH_COND (exp)); + /* The switch body is lowered in gimplify.c, we should never have + switches with a non-NULL SWITCH_BODY here. */ if (SWITCH_BODY (exp)) - expand_expr_stmt (SWITCH_BODY (exp)); + abort (); if (SWITCH_LABELS (exp)) { tree duplicate = 0; @@ -8623,7 +8625,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, } } - add_case_node (case_low, case_high, CASE_LABEL (elt), &duplicate, true); + add_case_node (case_low, case_high, CASE_LABEL (elt), &duplicate); if (duplicate) abort (); } @@ -8635,16 +8637,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, expand_label (TREE_OPERAND (exp, 0)); return const0_rtx; - case CASE_LABEL_EXPR: - { - tree duplicate = 0; - add_case_node (CASE_LOW (exp), CASE_HIGH (exp), CASE_LABEL (exp), - &duplicate, false); - if (duplicate) - abort (); - return const0_rtx; - } - case ASM_EXPR: expand_asm_expr (exp); return const0_rtx; diff --git a/gcc/final.c b/gcc/final.c index fccb846..ea75e54 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -1999,7 +1999,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, rtx body = PATTERN (insn); int insn_code_number; const char *template; - rtx note; /* An INSN, JUMP_INSN or CALL_INSN. First check for special kinds that recog doesn't recognize. */ @@ -2549,18 +2548,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, dwarf2out_frame_debug (insn); #endif -#if 0 - /* It's not at all clear why we did this and doing so used to - interfere with tests that used REG_WAS_0 notes, which are - now gone, so let's try with this out. */ - - /* Mark this insn as having been output. */ - INSN_DELETED_P (insn) = 1; -#endif - - /* Emit information for vtable gc. */ - note = find_reg_note (insn, REG_VTABLE_REF, NULL_RTX); - current_output_insn = debug_insn = 0; } } diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 34f1b3e..e2e8585 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1066,7 +1066,7 @@ compare_case_labels (const void *p1, const void *p2) return tree_int_cst_compare (CASE_LOW (case1), CASE_LOW (case2)); } -/* Sort the case labels in LABEL_VEC in ascending order. */ +/* Sort the case labels in LABEL_VEC in place in ascending order. */ void sort_case_labels (tree label_vec) diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 76bef66..5cd390e 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,8 @@ +2004-07-16 Steven Bosscher <stevenb@suse.de> + + * parse.y (java_complete_expand_methods, java_expand_classes): Don't + abuse restore_line_number_status. + 2004-07-15 Frank Ch. Eigler <fche@redhat.com> g++/15861 diff --git a/gcc/java/parse.y b/gcc/java/parse.y index 283176f..2ca09a2 100644 --- a/gcc/java/parse.y +++ b/gcc/java/parse.y @@ -7742,21 +7742,9 @@ java_complete_expand_methods (tree class_decl) /* Now do the constructors */ for (decl = first_decl ; !java_error_count && decl; decl = TREE_CHAIN (decl)) { - int no_body; - if (!DECL_CONSTRUCTOR_P (decl)) continue; - - no_body = !DECL_FUNCTION_BODY (decl); - /* Don't generate debug info on line zero when expanding a - generated constructor. */ - if (no_body) - restore_line_number_status (1); - java_complete_expand_method (decl); - - if (no_body) - restore_line_number_status (0); } /* First, do the ordinary methods. */ @@ -9032,9 +9020,7 @@ java_expand_classes (void) { if (DECL_CONSTRUCTOR_P (d)) { - restore_line_number_status (1); java_complete_expand_method (d); - restore_line_number_status (0); break; /* There is only one constructor. */ } } @@ -9056,11 +9042,7 @@ java_expand_classes (void) for (d = TYPE_METHODS (current_class); d; d = TREE_CHAIN (d)) { if (DECL_RESULT (d) == NULL_TREE) - { - restore_line_number_status (1); - java_complete_expand_method (d); - restore_line_number_status (0); - } + java_complete_expand_method (d); } } } @@ -9089,9 +9071,7 @@ java_expand_classes (void) if (DECL_RESULT (d) == NULL_TREE) { something_changed = 1; - restore_line_number_status (1); java_complete_expand_method (d); - restore_line_number_status (0); } } } @@ -136,8 +136,7 @@ const char * const reg_note_name[] = "REG_VALUE_PROFILE", "REG_NOALIAS", "REG_SAVE_AREA", "REG_BR_PRED", "REG_FRAME_RELATED_EXPR", "REG_EH_CONTEXT", "REG_EH_REGION", "REG_SAVE_NOTE", "REG_MAYBE_DEAD", "REG_NORETURN", - "REG_NON_LOCAL_GOTO", "REG_CROSSING_JUMP", "REG_SETJMP", "REG_ALWAYS_RETURN", - "REG_VTABLE_REF" + "REG_NON_LOCAL_GOTO", "REG_CROSSING_JUMP", "REG_SETJMP", "REG_ALWAYS_RETURN" }; @@ -865,11 +865,7 @@ enum reg_note REG_SETJMP, /* Indicate calls that always returns. */ - REG_ALWAYS_RETURN, - - /* Indicate that the memory load references a vtable. The expression - is of the form (plus (symbol_ref vtable_sym) (const_int offset)). */ - REG_VTABLE_REF + REG_ALWAYS_RETURN }; /* The base value for branch probability notes. */ @@ -2200,11 +2196,6 @@ extern void remove_insn (rtx); extern void emit_insn_after_with_line_notes (rtx, rtx, rtx); extern enum rtx_code classify_insn (rtx); extern rtx emit (rtx); -/* Query and clear/ restore no_line_numbers. This is used by the - switch / case handling in stmt.c to give proper line numbers in - warnings about unreachable code. */ -int force_line_numbers (void); -void restore_line_number_status (int old_value); extern void renumber_insns (FILE *); extern void remove_unnecessary_notes (void); extern rtx delete_insn (rtx); @@ -174,16 +174,6 @@ struct nesting GTY(()) reverts to the saved target_temp_slot_level at the very end of the block. */ int block_target_temp_slot_level; - /* True if we are currently emitting insns in an area of - output code that is controlled by a conditional - expression. This is used by the cleanup handling code to - generate conditional cleanup actions. */ - int conditional_code; - /* A place to move the start of the exception region for any - of the conditional cleanups, must be at the end or after - the start of the last unconditional cleanup, and before any - conditional branch points. */ - rtx last_unconditional_cleanup; } GTY ((tag ("BLOCK_NESTING"))) block; /* For switch (C) or case (Pascal) statements. */ struct nesting_case @@ -199,14 +189,6 @@ struct nesting GTY(()) tree default_label; /* The expression to be dispatched on. */ tree index_expr; - /* Type that INDEX_EXPR should be converted to. */ - tree nominal_type; - /* Name of this kind of statement, for warnings. */ - const char *printname; - /* Used to save no_line_numbers till we see the first case label. - We set this to -1 when we see the first case label in this - case statement. */ - int line_number_status; } GTY ((tag ("CASE_NESTING"))) case_stmt; } GTY ((desc ("%1.desc"))) data; }; @@ -234,32 +216,6 @@ do { struct nesting *target = STACK; \ nesting_stack = this->all; } \ while (this != target); } while (0) -/* In some cases it is impossible to generate code for a forward goto - until the label definition is seen. This happens when it may be necessary - for the goto to reset the stack pointer: we don't yet know how to do that. - So expand_goto puts an entry on this fixup list. - Each time a binding contour that resets the stack is exited, - we check each fixup. - If the target label has now been defined, we can insert the proper code. */ - -struct goto_fixup GTY(()) -{ - /* Points to following fixup. */ - struct goto_fixup *next; - /* Points to the insn before the jump insn. - If more code must be inserted, it goes after this insn. */ - rtx before_jump; - /* The LABEL_DECL that this jump is jumping to, or 0 - for break, continue or return. */ - tree target; - /* The BLOCK for the place where this goto was found. */ - tree context; - /* The CODE_LABEL rtx that this is jumping to. */ - rtx target_rtl; - /* Number of binding contours started in current function - before the label reference. */ - int block_start_count; -}; struct stmt_status GTY(()) { @@ -287,8 +243,6 @@ struct stmt_status GTY(()) /* Location of last line-number note, whether we actually emitted it or not. */ location_t x_emit_locus; - - struct goto_fixup *x_goto_fixup_chain; }; #define block_stack (cfun->stmt->x_block_stack) @@ -298,10 +252,6 @@ struct stmt_status GTY(()) #define nesting_depth (cfun->stmt->x_nesting_depth) #define current_block_start_count (cfun->stmt->x_block_start_count) #define emit_locus (cfun->stmt->x_emit_locus) -#define goto_fixup_chain (cfun->stmt->x_goto_fixup_chain) - -/* Nonzero if we are using EH to handle cleanups. */ -int using_eh_for_cleanups_p = 0; static int n_occurrences (int, const char *); static bool decl_conflicts_with_clobbers_p (tree, const HARD_REG_SET); @@ -316,26 +266,17 @@ static void expand_value_return (rtx); static void do_jump_if_equal (rtx, rtx, rtx, int); static int estimate_case_costs (case_node_ptr); static bool same_case_target_p (rtx, rtx); -static void strip_default_case_nodes (case_node_ptr *, rtx); static bool lshift_cheap_p (void); static int case_bit_test_cmp (const void *, const void *); static void emit_case_bit_tests (tree, tree, tree, tree, case_node_ptr, rtx); -static void group_case_nodes (case_node_ptr); static void balance_case_nodes (case_node_ptr *, case_node_ptr); static int node_has_low_bound (case_node_ptr, tree); static int node_has_high_bound (case_node_ptr, tree); static int node_is_bounded (case_node_ptr, tree); -static void emit_jump_if_reachable (rtx); static void emit_case_nodes (rtx, case_node_ptr, rtx, tree); static struct case_node *case_tree2list (case_node *, case_node *); void -using_eh_for_cleanups (void) -{ - using_eh_for_cleanups_p = 1; -} - -void init_stmt_for_function (void) { cfun->stmt = ggc_alloc_cleared (sizeof (struct stmt_status)); @@ -2207,8 +2148,6 @@ expand_start_bindings_and_block (int flags, tree block) thisblock->depth = ++nesting_depth; thisblock->data.block.block_target_temp_slot_level = target_temp_slot_level; - thisblock->data.block.conditional_code = 0; - thisblock->data.block.last_unconditional_cleanup = note; /* When we insert instructions after the last unconditional cleanup, we don't adjust last_insn. That means that a later add_insn will clobber the instructions we've just added. The easiest way to @@ -2760,8 +2699,7 @@ expand_anon_union_decl (tree decl, tree cleanup ATTRIBUTE_UNUSED, but instead we take short cuts. */ void -expand_start_case (int exit_flag, tree expr, tree type, - const char *printname) +expand_start_case (tree index_expr) { struct nesting *thiscase = ALLOC_NESTING (); @@ -2771,13 +2709,10 @@ expand_start_case (int exit_flag, tree expr, tree type, thiscase->next = case_stack; thiscase->all = nesting_stack; thiscase->depth = ++nesting_depth; - thiscase->exit_label = exit_flag ? gen_label_rtx () : 0; + thiscase->exit_label = 0; thiscase->data.case_stmt.case_list = 0; - thiscase->data.case_stmt.index_expr = expr; - thiscase->data.case_stmt.nominal_type = type; + thiscase->data.case_stmt.index_expr = index_expr; thiscase->data.case_stmt.default_label = 0; - thiscase->data.case_stmt.printname = printname; - thiscase->data.case_stmt.line_number_status = force_line_numbers (); case_stack = thiscase; nesting_stack = thiscase; @@ -2791,119 +2726,12 @@ expand_start_case (int exit_flag, tree expr, tree type, thiscase->data.case_stmt.start = get_last_insn (); } -/* Accumulate one case or default label inside a case or switch statement. - VALUE is the value of the case (a null pointer, for a default label). - The function CONVERTER, when applied to arguments T and V, - converts the value V to the type T. - - If not currently inside a case or switch statement, return 1 and do - nothing. The caller will print a language-specific error message. - If VALUE is a duplicate or overlaps, return 2 and do nothing - except store the (first) duplicate node in *DUPLICATE. - If VALUE is out of range, return 3 and do nothing. - Return 0 on success. - - Extended to handle range statements. */ - -int -pushcase (tree value, tree (*converter) (tree, tree), tree label, - tree *duplicate) -{ - tree index_type; - tree nominal_type; - - /* Fail if not inside a real case statement. */ - if (! (case_stack && case_stack->data.case_stmt.start)) - return 1; - - index_type = TREE_TYPE (case_stack->data.case_stmt.index_expr); - nominal_type = case_stack->data.case_stmt.nominal_type; - - /* If the index is erroneous, avoid more problems: pretend to succeed. */ - if (index_type == error_mark_node) - return 0; - - /* Convert VALUE to the type in which the comparisons are nominally done. */ - if (value != 0) - value = (*converter) (nominal_type, value); - - /* Fail if this value is out of range for the actual type of the index - (which may be narrower than NOMINAL_TYPE). */ - if (value != 0 - && (TREE_CONSTANT_OVERFLOW (value) - || ! int_fits_type_p (value, index_type))) - return 3; - - return add_case_node (value, value, label, duplicate, false); -} - -/* Like pushcase but this case applies to all values between VALUE1 and - VALUE2 (inclusive). If VALUE1 is NULL, the range starts at the lowest - value of the index type and ends at VALUE2. If VALUE2 is NULL, the range - starts at VALUE1 and ends at the highest value of the index type. - If both are NULL, this case applies to all values. - - The return value is the same as that of pushcase but there is one - additional error code: 4 means the specified range was empty. */ - -int -pushcase_range (tree value1, tree value2, tree (*converter) (tree, tree), - tree label, tree *duplicate) -{ - tree index_type; - tree nominal_type; - - /* Fail if not inside a real case statement. */ - if (! (case_stack && case_stack->data.case_stmt.start)) - return 1; - - index_type = TREE_TYPE (case_stack->data.case_stmt.index_expr); - nominal_type = case_stack->data.case_stmt.nominal_type; - - /* If the index is erroneous, avoid more problems: pretend to succeed. */ - if (index_type == error_mark_node) - return 0; - - /* Convert VALUEs to type in which the comparisons are nominally done - and replace any unspecified value with the corresponding bound. */ - if (value1 == 0) - value1 = TYPE_MIN_VALUE (index_type); - if (value2 == 0) - value2 = TYPE_MAX_VALUE (index_type); - - /* Fail if the range is empty. Do this before any conversion since - we want to allow out-of-range empty ranges. */ - if (value2 != 0 && tree_int_cst_lt (value2, value1)) - return 4; - - /* If the max was unbounded, use the max of the nominal_type we are - converting to. Do this after the < check above to suppress false - positives. */ - if (value2 == 0) - value2 = TYPE_MAX_VALUE (nominal_type); - - value1 = (*converter) (nominal_type, value1); - value2 = (*converter) (nominal_type, value2); - - /* Fail if these values are out of range. */ - if (TREE_CONSTANT_OVERFLOW (value1) - || ! int_fits_type_p (value1, index_type)) - return 3; - - if (TREE_CONSTANT_OVERFLOW (value2) - || ! int_fits_type_p (value2, index_type)) - return 3; - - return add_case_node (value1, value2, label, duplicate, false); -} - -/* Do the actual insertion of a case label for pushcase and pushcase_range - into case_stack->data.case_stmt.case_list. Use an AVL tree to avoid +/* Do the insertion of a case label into + case_stack->data.case_stmt.case_list. Use an AVL tree to avoid slowdown for large switch statements. */ int -add_case_node (tree low, tree high, tree label, tree *duplicate, - bool dont_expand_label) +add_case_node (tree low, tree high, tree label, tree *duplicate) { struct case_node *p, **q, *r; @@ -2922,8 +2750,6 @@ add_case_node (tree low, tree high, tree label, tree *duplicate, return 2; } case_stack->data.case_stmt.default_label = label; - if (!dont_expand_label) - expand_label (label); return 0; } @@ -2962,8 +2788,6 @@ add_case_node (tree low, tree high, tree label, tree *duplicate, r->high = high; r->code_label = label; - if (!dont_expand_label) - expand_label (label); *q = r; r->parent = p; @@ -3355,11 +3179,6 @@ expand_end_case_type (tree orig_index, tree orig_type) thiscase->data.case_stmt.case_list = case_tree2list (thiscase->data.case_stmt.case_list, 0); - /* Simplify the case-list before we count it. */ - group_case_nodes (thiscase->data.case_stmt.case_list); - strip_default_case_nodes (&thiscase->data.case_stmt.case_list, - default_label); - /* Get upper and lower bounds of case values. Also convert all the case values to the index expr's data type. */ @@ -3534,7 +3353,7 @@ expand_end_case_type (tree orig_index, tree orig_type) balance_case_nodes (&thiscase->data.case_stmt.case_list, NULL); emit_case_nodes (index, thiscase->data.case_stmt.case_list, default_label, index_type); - emit_jump_if_reachable (default_label); + emit_jump (default_label); } } else @@ -3543,7 +3362,7 @@ expand_end_case_type (tree orig_index, tree orig_type) if (! try_casesi (index_type, index_expr, minval, range, table_label, default_label)) { - index_type = thiscase->data.case_stmt.nominal_type; + index_type = integer_type_node; /* Index jumptables from zero for suitable values of minval to avoid a subtraction. */ @@ -3745,100 +3564,16 @@ estimate_case_costs (case_node_ptr node) return 1; } -/* Determine whether two case labels branch to the same target. */ +/* Determine whether two case labels branch to the same target. + Since we now do tree optimizations, just comparing labels is + good enough. */ static bool same_case_target_p (rtx l1, rtx l2) { -#if 0 - rtx i1, i2; - - if (l1 == l2) - return true; - - i1 = next_real_insn (l1); - i2 = next_real_insn (l2); - if (i1 == i2) - return true; - - if (i1 && simplejump_p (i1)) - { - l1 = XEXP (SET_SRC (PATTERN (i1)), 0); - } - - if (i2 && simplejump_p (i2)) - { - l2 = XEXP (SET_SRC (PATTERN (i2)), 0); - } -#endif - /* When coming from gimple, we usually won't have emitted either - the labels or the body of the switch statement. The job being - done here should be done via jump threading at the tree level. - Cases that go the same place should have the same label. */ return l1 == l2; } -/* Delete nodes that branch to the default label from a list of - case nodes. Eg. case 5: default: becomes just default: */ - -static void -strip_default_case_nodes (case_node_ptr *prev, rtx deflab) -{ - case_node_ptr ptr; - - while (*prev) - { - ptr = *prev; - if (same_case_target_p (label_rtx (ptr->code_label), deflab)) - *prev = ptr->right; - else - prev = &ptr->right; - } -} - -/* Scan an ordered list of case nodes - combining those with consecutive values or ranges. - - Eg. three separate entries 1: 2: 3: become one entry 1..3: */ - -static void -group_case_nodes (case_node_ptr head) -{ - case_node_ptr node = head; - - while (node) - { - rtx lab; - case_node_ptr np = node; - - lab = label_rtx (node->code_label); - - /* Try to group the successors of NODE with NODE. */ - while (((np = np->right) != 0) - /* Do they jump to the same place? */ - && same_case_target_p (label_rtx (np->code_label), lab) - /* Are their ranges consecutive? */ - && tree_int_cst_equal (np->low, - fold (build (PLUS_EXPR, - TREE_TYPE (node->high), - node->high, - integer_one_node))) - /* An overflow is not consecutive. */ - && tree_int_cst_lt (node->high, - fold (build (PLUS_EXPR, - TREE_TYPE (node->high), - node->high, - integer_one_node)))) - { - node->high = np->high; - } - /* NP is the first node after NODE which can't be grouped with it. - Delete the nodes in between, and move on to that node. */ - node->right = np; - node = np; - } -} - /* Take an ordered list of case nodes and transform them into a near optimal binary tree, on the assumption that any target code selection value is as @@ -4061,15 +3796,6 @@ node_is_bounded (case_node_ptr node, tree index_type) return (node_has_low_bound (node, index_type) && node_has_high_bound (node, index_type)); } - -/* Emit an unconditional jump to LABEL unless it would be dead code. */ - -static void -emit_jump_if_reachable (rtx label) -{ - if (!BARRIER_P (get_last_insn ())) - emit_jump (label); -} /* Emit step-by-step code to select a case for the value of INDEX. The thus generated decision tree follows the form of the @@ -4215,7 +3941,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label, emit_case_nodes (index, node->left, default_label, index_type); /* If left-hand subtree does nothing, go to default. */ - emit_jump_if_reachable (default_label); + emit_jump (default_label); /* Code branches here for the right-hand subtree. */ expand_label (test_label); @@ -4356,7 +4082,7 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label, { /* If the left-hand subtree fell through, don't let it fall into the right-hand subtree. */ - emit_jump_if_reachable (default_label); + emit_jump (default_label); expand_label (test_label); emit_case_nodes (index, node->right, default_label, index_type); diff --git a/gcc/toplev.c b/gcc/toplev.c index e318ac3..f0c18cb 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -1926,8 +1926,7 @@ backend_init (void) /* Enable line number info for traceback. */ || debug_info_level > DINFO_LEVEL_NONE #endif - || flag_test_coverage - || warn_notreached); + || flag_test_coverage); init_regs (); init_fake_stack_mems (); diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index f3df4e2..ac2d5da 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -99,8 +99,6 @@ static void tree_cfg2vcg (FILE *); static void tree_merge_blocks (basic_block, basic_block); static bool tree_can_merge_blocks_p (basic_block, basic_block); static void remove_bb (basic_block); -static void group_case_labels (void); -static void cleanup_dead_labels (void); static bool cleanup_control_flow (void); static bool cleanup_control_expr_graph (basic_block, block_stmt_iterator); static edge find_taken_edge_cond_expr (basic_block, tree); @@ -769,7 +767,16 @@ update_eh_label (struct eh_region *region) tree old_label = get_eh_region_tree_label (region); if (old_label) { - tree new_label = label_for_bb[label_to_block (old_label)->index]; + tree new_label; + basic_block bb = label_to_block (old_label); + + /* ??? After optimizing, there may be EH regions with labels + that have already been removed from the function body, so + there is no basic block for them. */ + if (! bb) + return; + + new_label = label_for_bb[bb->index]; set_eh_region_tree_label (region, new_label); } } @@ -791,7 +798,7 @@ main_block_label (tree label) 2) Redirect all references to labels to the leading labels. 3) Cleanup all useless labels. */ -static void +void cleanup_dead_labels (void) { basic_block bb; @@ -924,7 +931,7 @@ cleanup_dead_labels (void) same label. Eg. three separate entries 1: 2: 3: become one entry 1..3: */ -static void +void group_case_labels (void) { basic_block bb; diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index b7fe64d..42834e4 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -37,8 +37,15 @@ Boston, MA 02111-1307, USA. */ #include "langhooks.h" #include "ggc.h" -/* HACK */ -extern int using_eh_for_cleanups_p; + +/* Nonzero if we are using EH to handle cleanups. */ +static int using_eh_for_cleanups_p = 0; + +void +using_eh_for_cleanups (void) +{ + using_eh_for_cleanups_p = 1; +} /* Misc functions used in this file. */ diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index 5bd9f94..2f32734 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -473,6 +473,8 @@ extern void dump_cfg_stats (FILE *); extern void debug_cfg_stats (void); extern void debug_loop_ir (void); extern void print_loop_ir (FILE *); +extern void cleanup_dead_labels (void); +extern void group_case_labels (void); extern void cleanup_tree_cfg (void); extern tree first_stmt (basic_block); extern tree last_stmt (basic_block); diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c index d66c1b9..bd4bb0d 100644 --- a/gcc/tree-optimize.c +++ b/gcc/tree-optimize.c @@ -101,6 +101,35 @@ static struct tree_opt_pass pass_all_optimizations = 0 /* todo_flags_finish */ }; +/* Pass: cleanup the CFG just before expanding trees to RTL. + This is just a round of label cleanups and case node grouping + because after the tree optimizers have run such cleanups may + be necessary. */ + +static void +execute_cleanup_cfg_post_optimizing (void) +{ + cleanup_tree_cfg (); + cleanup_dead_labels (); + group_case_labels (); +} + +static struct tree_opt_pass pass_cleanup_cfg_post_optimizing = +{ + NULL, /* name */ + NULL, /* gate */ + execute_cleanup_cfg_post_optimizing, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + 0, /* tv_id */ + PROP_cfg, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0 /* todo_flags_finish */ +}; + /* Pass: do the actions required to finish with tree-ssa optimization passes. */ @@ -324,6 +353,7 @@ init_tree_optimization_passes (void) NEXT_PASS (pass_del_ssa); NEXT_PASS (pass_nrv); NEXT_PASS (pass_remove_useless_vars); + NEXT_PASS (pass_cleanup_cfg_post_optimizing); *p = NULL; p = &pass_loop.sub; @@ -3352,12 +3352,12 @@ extern void warn_about_unused_variables (tree); extern int is_body_block (tree); extern struct nesting * current_nesting_level (void); -extern void expand_start_case (int, tree, tree, const char *); +extern void expand_start_case (tree); extern void expand_end_case_type (tree, tree); #define expand_end_case(cond) expand_end_case_type (cond, NULL) -extern int add_case_node (tree, tree, tree, tree *, bool); -extern int pushcase (tree, tree (*) (tree, tree), tree, tree *); -extern int pushcase_range (tree, tree, tree (*) (tree, tree), tree, tree *); +extern int add_case_node (tree, tree, tree, tree *); + +/* In tree-eh.c */ extern void using_eh_for_cleanups (void); /* In fold-const.c */ |