From: Paolo Bonzini Date: Mon, 9 Aug 2004 07:14:17 +0000 (+0000) Subject: Makefile.in (GTFILES): Remove stmt.c X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7efcb746dac871864e4f193ea3abda75ab2b7f5c;p=gcc.git Makefile.in (GTFILES): Remove stmt.c 2004-08-09 Paolo Bonzini * Makefile.in (GTFILES): Remove stmt.c (stmt.o): Do not depend on gt-stmt.h. * emit-rtl.c (emit_line_note): Do not call set_file_and_line_for_stmt. * expr.c (expand_expr_real_1) : Let expand_case do everything. * function.c (free_after_parsing): Do not free STMT field. (allocate_struct_function): Do not call init_stmt_for_function. (assign_stack_temp_for_type): Do not accept values of keep other than 0 or 1. (init_temp_slots): Do not initialize removed variables. * function.h (struct function): Remove STMT, X_TARGET_TEMP_SLOT_LEVEL and X_VAR_TEMP_SLOT_LEVEL fields. * rtl.h (set_file_and_line_for_stmt): Remove. * stmt.c (struct nesting, ALLOC_NESTING, POPSTACK, struct stmt_status, cond_stack, case_stack, nesting_stack, nesting_depth, emit_locus, set_file_and_line_for_stmt, same_case_target_p, init_stmt_for_function, emit_nop, expand_start_cond, expand_start_elseif, expand_start_else, expand_elseif, expand_end_cond): Remove. (preserve_subexpressions_p): Remove references to CFUN->STMT. (expand_start_case, expand_end_case_type): Remove, merge into... (expand_case): ... this one, including other bits from expand_expr_real_1. Inline same_case_target_p. Turn members of CASE_STACK into local variables. (emit_case_bit_tests): Inline same_case_target_p. (add_case_node): Add HEAD argument, return new head of the list, do not handle default label here. * tree.h (expand_start_cond, expand_end_cond, expand_start_else, expand_start_elseif, current_nesting_level, expand_start_case, expand_end_case_type, expand_end_case, add_case_node, init_stmt_for_function, expand_elseif): Remove prototypes. (expand_case): Add prototype. From-SVN: r85712 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5d69b904676..06dfe4fb0a5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,39 @@ +2004-08-09 Paolo Bonzini + + * Makefile.in (GTFILES): Remove stmt.c + (stmt.o): Do not depend on gt-stmt.h. + * emit-rtl.c (emit_line_note): Do not call + set_file_and_line_for_stmt. + * expr.c (expand_expr_real_1) : Let expand_case + do everything. + * function.c (free_after_parsing): Do not free STMT field. + (allocate_struct_function): Do not call init_stmt_for_function. + (assign_stack_temp_for_type): Do not accept values of keep + other than 0 or 1. + (init_temp_slots): Do not initialize removed variables. + * function.h (struct function): Remove STMT, X_TARGET_TEMP_SLOT_LEVEL + and X_VAR_TEMP_SLOT_LEVEL fields. + * rtl.h (set_file_and_line_for_stmt): Remove. + * stmt.c (struct nesting, ALLOC_NESTING, POPSTACK, + struct stmt_status, cond_stack, case_stack, nesting_stack, + nesting_depth, emit_locus, set_file_and_line_for_stmt, + same_case_target_p, init_stmt_for_function, emit_nop, + expand_start_cond, expand_start_elseif, expand_start_else, + expand_elseif, expand_end_cond): Remove. + (preserve_subexpressions_p): Remove references to CFUN->STMT. + (expand_start_case, expand_end_case_type): Remove, merge into... + (expand_case): ... this one, including other bits from + expand_expr_real_1. Inline same_case_target_p. Turn members + of CASE_STACK into local variables. + (emit_case_bit_tests): Inline same_case_target_p. + (add_case_node): Add HEAD argument, return new head of the list, + do not handle default label here. + * tree.h (expand_start_cond, expand_end_cond, expand_start_else, + expand_start_elseif, current_nesting_level, expand_start_case, + expand_end_case_type, expand_end_case, add_case_node, + init_stmt_for_function, expand_elseif): Remove prototypes. + (expand_case): Add prototype. + 2004-08-09 Paolo Bonzini * expr.c (expand_expr_real_1): Use optab_for_tree_code. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 7215087fb1f..2bcfee4f13a 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1809,7 +1809,7 @@ function.o : function.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ stmt.o : stmt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) $(FLAGS_H) \ function.h insn-config.h hard-reg-set.h $(EXPR_H) libfuncs.h except.h \ $(LOOP_H) $(RECOG_H) toplev.h output.h varray.h $(GGC_H) $(TM_P_H) \ - langhooks.h $(PREDICT_H) gt-stmt.h $(OPTABS_H) $(TARGET_H) + langhooks.h $(PREDICT_H) $(OPTABS_H) $(TARGET_H) except.o : except.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ $(TREE_H) $(FLAGS_H) except.h function.h $(EXPR_H) libfuncs.h $(INTEGRATE_H) \ langhooks.h insn-config.h hard-reg-set.h $(BASIC_BLOCK_H) output.h \ @@ -2358,7 +2358,7 @@ GTFILES = $(srcdir)/input.h $(srcdir)/coretypes.h \ $(srcdir)/gcse.c $(srcdir)/integrate.c $(srcdir)/lists.c $(srcdir)/optabs.c \ $(srcdir)/profile.c $(srcdir)/ra-build.c $(srcdir)/regclass.c \ $(srcdir)/reg-stack.c $(srcdir)/cfglayout.c \ - $(srcdir)/sdbout.c $(srcdir)/stmt.c $(srcdir)/stor-layout.c \ + $(srcdir)/sdbout.c $(srcdir)/stor-layout.c \ $(srcdir)/stringpool.c $(srcdir)/tree.c $(srcdir)/varasm.c \ $(srcdir)/tree-mudflap.c $(srcdir)/tree-flow.h \ $(srcdir)/c-objc-common.c $(srcdir)/c-common.c $(srcdir)/c-parse.in \ diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 717bb4bfdca..b49ccb2f530 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -4626,8 +4626,6 @@ emit_line_note (location_t location) { rtx note; - set_file_and_line_for_stmt (location); - #ifdef USE_MAPPED_LOCATION if (location == last_location) return NULL_RTX; diff --git a/gcc/expr.c b/gcc/expr.c index 211bac8f10b..7334c59ca39 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -7697,7 +7697,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, goto binop; case TRUTH_OR_EXPR: - code = BIT_OR_EXPR; + code = BIT_IOR_EXPR; case BIT_IOR_EXPR: goto binop; @@ -8144,27 +8144,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, abort (); case SWITCH_EXPR: - 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)) - abort (); - if (SWITCH_LABELS (exp)) - { - tree vec = SWITCH_LABELS (exp); - size_t i = TREE_VEC_LENGTH (vec); - - do - { - tree elt = TREE_VEC_ELT (vec, --i); - add_case_node (CASE_LOW (elt), CASE_HIGH (elt), - CASE_LABEL (elt)); - } - while (i); - } - else - abort (); - expand_end_case_type (SWITCH_COND (exp), TREE_TYPE (exp)); + expand_case (exp); return const0_rtx; case LABEL_EXPR: diff --git a/gcc/function.c b/gcc/function.c index 4de748aceb8..ed7821b4f7b 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -315,7 +315,6 @@ free_after_parsing (struct function *f) /* f->eh->eh_return_stub_label is used by code generation. */ lang_hooks.function.final (f); - f->stmt = NULL; } /* Clear out all parts of the state in F that can safely be discarded @@ -589,10 +588,9 @@ make_slot_available (struct temp_slot *temp) KEEP is 1 if this slot is to be retained after a call to free_temp_slots. Automatic variables for a block are allocated - with this flag. KEEP is 2 if we allocate a longer term temporary, - whose lifetime is controlled by CLEANUP_POINT_EXPRs. KEEP is 3 - if we are to allocate something at an inner level to be treated as - a variable in the block (e.g., a SAVE_EXPR). + with this flag. KEEP values of 2 or 3 were needed respectively + for variables whose lifetime is controlled by CLEANUP_POINT_EXPRs + or for SAVE_EXPRs, but they are now unused and will abort. TYPE is the type that will be used for the stack slot. */ @@ -609,6 +607,10 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size, int keep if (size == -1) abort (); + /* These are now unused. */ + if (keep > 1) + abort (); + if (mode == BLKmode) align = BIGGEST_ALIGNMENT; else @@ -733,22 +735,8 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size, int keep p->in_use = 1; p->addr_taken = 0; p->type = type; - - if (keep == 2) - { - p->level = target_temp_slot_level; - p->keep = 1; - } - else if (keep == 3) - { - p->level = var_temp_slot_level; - p->keep = 0; - } - else - { - p->level = temp_slot_level; - p->keep = keep; - } + p->level = temp_slot_level; + p->keep = keep; pp = temp_slots_at_level (p->level); insert_slot_to_list (p, pp); @@ -1190,8 +1178,6 @@ init_temp_slots (void) avail_temp_slots = 0; used_temp_slots = 0; temp_slot_level = 0; - var_temp_slot_level = 0; - target_temp_slot_level = 0; } /* These routines are responsible for converting virtual register references @@ -3784,7 +3770,6 @@ allocate_struct_function (tree fndecl) cfun->function_frequency = FUNCTION_FREQUENCY_NORMAL; - init_stmt_for_function (); init_eh_for_function (); lang_hooks.function.init (cfun); diff --git a/gcc/function.h b/gcc/function.h index b3e750fd6b0..0c1ca1aba5f 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -162,7 +162,6 @@ struct expr_status GTY(()) struct function GTY(()) { struct eh_status *eh; - struct stmt_status *stmt; struct expr_status *expr; struct emit_status *emit; struct varasm_status *varasm; @@ -276,15 +275,6 @@ struct function GTY(()) /* Current nesting level for temporaries. */ int x_temp_slot_level; - /* Current nesting level for variables in a block. */ - int x_var_temp_slot_level; - - /* When temporaries are created by TARGET_EXPRs, they are created at - this level of temp_slot_level, so that they can remain allocated - until no longer needed. CLEANUP_POINT_EXPRs define the lifetime - of TARGET_EXPRs. */ - int x_target_temp_slot_level; - /* This slot is initialized as 0 and is added to during the nested function. */ struct var_refs_queue *fixup_var_refs_queue; @@ -492,8 +482,6 @@ extern int trampolines_created; #define used_temp_slots (cfun->x_used_temp_slots) #define avail_temp_slots (cfun->x_avail_temp_slots) #define temp_slot_level (cfun->x_temp_slot_level) -#define target_temp_slot_level (cfun->x_target_temp_slot_level) -#define var_temp_slot_level (cfun->x_var_temp_slot_level) #define nonlocal_labels (cfun->x_nonlocal_labels) #define nonlocal_goto_handler_labels (cfun->x_nonlocal_goto_handler_labels) diff --git a/gcc/rtl.h b/gcc/rtl.h index 8174b6e3c4a..fdff2f65b36 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -2236,7 +2236,6 @@ extern void mark_temp_addr_taken (rtx); extern void update_temp_slot_address (rtx, rtx); /* In stmt.c */ -extern void set_file_and_line_for_stmt (location_t); extern void expand_null_return (void); extern void expand_naked_return (void); extern void emit_jump (rtx); diff --git a/gcc/stmt.c b/gcc/stmt.c index a09d83d5751..8164c2d269f 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -21,17 +21,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA /* This file handles the generation of rtl code from tree structure above the level of expressions, using subroutines in exp*.c and emit-rtl.c. - It also creates the rtl expressions for parameters and auto variables - and has full responsibility for allocating stack slots. - The functions whose names start with `expand_' are called by the - parser to generate RTL instructions for various kinds of constructs. - - Some control and binding constructs require calling several such - functions at different times. For example, a simple if-then - is expanded by calling `expand_start_cond' (with the condition-expression - as argument) before parsing the then-clause and calling `expand_end_cond' - after parsing the then-clause. */ + expander to generate RTL instructions for various kinds of constructs. */ #include "config.h" #include "system.h" @@ -113,123 +104,6 @@ static int cost_table_initialized; is unsigned. */ #define COST_TABLE(I) cost_table_[(unsigned HOST_WIDE_INT) ((I) + 1)] -/* Stack of control and binding constructs we are currently inside. - - These constructs begin when you call `expand_start_WHATEVER' - and end when you call `expand_end_WHATEVER'. This stack records - info about how the construct began that tells the end-function - what to do. It also may provide information about the construct - to alter the behavior of other constructs within the body. - For example, they may affect the behavior of C `break' and `continue'. - - Each construct gets one `struct nesting' object. - All of these objects are chained through the `all' field. - `nesting_stack' points to the first object (innermost construct). - The position of an entry on `nesting_stack' is in its `depth' field. - - Each type of construct has its own individual stack. - For example, loops have `cond_stack'. Each object points to the - next object of the same type through the `next' field. - - Some constructs are visible to `break' exit-statements and others - are not. Which constructs are visible depends on the language. - Therefore, the data structure allows each construct to be visible - or not, according to the args given when the construct is started. - The construct is visible if the `exit_label' field is non-null. - In that case, the value should be a CODE_LABEL rtx. */ - -struct nesting GTY(()) -{ - struct nesting *all; - struct nesting *next; - int depth; - rtx exit_label; - enum nesting_desc { - COND_NESTING, - BLOCK_NESTING, - CASE_NESTING - } desc; - union nesting_u - { - /* For conds (if-then and if-then-else statements). */ - struct nesting_cond - { - /* Label for the end of the if construct. - There is none if EXITFLAG was not set - and no `else' has been seen yet. */ - rtx endif_label; - /* Label for the end of this alternative. - This may be the end of the if or the next else/elseif. */ - rtx next_label; - } GTY ((tag ("COND_NESTING"))) cond; - /* For switch (C) or case (Pascal) statements. */ - struct nesting_case - { - /* The insn after which the case dispatch should finally - be emitted. Zero for a dummy. */ - rtx start; - /* A list of case labels; it is first built as an AVL tree. - During expand_end_case, this is converted to a list, and may be - rearranged into a nearly balanced binary tree. */ - struct case_node *case_list; - /* Label to jump to if no case matches. */ - tree default_label; - /* The expression to be dispatched on. */ - tree index_expr; - } GTY ((tag ("CASE_NESTING"))) case_stmt; - } GTY ((desc ("%1.desc"))) data; -}; - -/* Allocate and return a new `struct nesting'. */ - -#define ALLOC_NESTING() ggc_alloc (sizeof (struct nesting)) - -/* Pop the nesting stack element by element until we pop off - the element which is at the top of STACK. - Update all the other stacks, popping off elements from them - as we pop them from nesting_stack. */ - -#define POPSTACK(STACK) \ -do { struct nesting *target = STACK; \ - struct nesting *this; \ - do { this = nesting_stack; \ - if (cond_stack == this) \ - cond_stack = cond_stack->next; \ - if (case_stack == this) \ - case_stack = case_stack->next; \ - nesting_depth = nesting_stack->depth - 1; \ - nesting_stack = this->all; } \ - while (this != target); } while (0) - - -struct stmt_status GTY(()) -{ - /* If any new stacks are added here, add them to POPSTACKS too. */ - - /* Chain of all pending conditional statements. */ - struct nesting * x_cond_stack; - - /* Chain of all pending case or switch statements. */ - struct nesting * x_case_stack; - - /* Separate chain including all of the above, - chained through the `all' field. */ - struct nesting * x_nesting_stack; - - /* Number of entries on nesting_stack now. */ - int x_nesting_depth; - - /* Location of last line-number note, whether we actually - emitted it or not. */ - location_t x_emit_locus; -}; - -#define cond_stack (cfun->stmt->x_cond_stack) -#define case_stack (cfun->stmt->x_case_stack) -#define nesting_stack (cfun->stmt->x_nesting_stack) -#define nesting_depth (cfun->stmt->x_nesting_depth) -#define emit_locus (cfun->stmt->x_emit_locus) - static int n_occurrences (int, const char *); static bool decl_conflicts_with_clobbers_p (tree, const HARD_REG_SET); static void expand_nl_goto_receiver (void); @@ -241,7 +115,6 @@ static rtx shift_return_value (rtx); 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 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); @@ -250,39 +123,8 @@ 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_case_nodes (rtx, case_node_ptr, rtx, tree); - -void -init_stmt_for_function (void) -{ - cfun->stmt = ggc_alloc_cleared (sizeof (struct stmt_status)); -} - -/* Record the current file and line. Called from emit_line_note. */ +static struct case_node *add_case_node (struct case_node *, tree, tree, tree); -void -set_file_and_line_for_stmt (location_t location) -{ - /* If we're outputting an inline function, and we add a line note, - there may be no CFUN->STMT information. So, there's no need to - update it. */ - if (cfun->stmt) - emit_locus = location; -} - -/* Emit a no-op instruction. */ - -void -emit_nop (void) -{ - rtx last_insn; - - last_insn = get_last_insn (); - if (!optimize - && (LABEL_P (last_insn) - || (NOTE_P (last_insn) - && prev_real_insn (last_insn) == 0))) - emit_insn (gen_nop ()); -} /* Return the rtx-label that corresponds to a LABEL_DECL, creating it if necessary. */ @@ -1650,90 +1492,6 @@ warn_if_unused_value (tree exp, location_t locus) } } -/* Generate RTL for the start of an if-then. COND is the expression - whose truth should be tested. - - If EXITFLAG is nonzero, this conditional is visible to - `exit_something'. */ - -void -expand_start_cond (tree cond, int exitflag) -{ - struct nesting *thiscond = ALLOC_NESTING (); - - /* Make an entry on cond_stack for the cond we are entering. */ - - thiscond->desc = COND_NESTING; - thiscond->next = cond_stack; - thiscond->all = nesting_stack; - thiscond->depth = ++nesting_depth; - thiscond->data.cond.next_label = gen_label_rtx (); - /* Before we encounter an `else', we don't need a separate exit label - unless there are supposed to be exit statements - to exit this conditional. */ - thiscond->exit_label = exitflag ? gen_label_rtx () : 0; - thiscond->data.cond.endif_label = thiscond->exit_label; - cond_stack = thiscond; - nesting_stack = thiscond; - - do_jump (cond, thiscond->data.cond.next_label, NULL_RTX); -} - -/* Generate RTL between then-clause and the elseif-clause - of an if-then-elseif-.... */ - -void -expand_start_elseif (tree cond) -{ - if (cond_stack->data.cond.endif_label == 0) - cond_stack->data.cond.endif_label = gen_label_rtx (); - emit_jump (cond_stack->data.cond.endif_label); - emit_label (cond_stack->data.cond.next_label); - cond_stack->data.cond.next_label = gen_label_rtx (); - do_jump (cond, cond_stack->data.cond.next_label, NULL_RTX); -} - -/* Generate RTL between the then-clause and the else-clause - of an if-then-else. */ - -void -expand_start_else (void) -{ - if (cond_stack->data.cond.endif_label == 0) - cond_stack->data.cond.endif_label = gen_label_rtx (); - - emit_jump (cond_stack->data.cond.endif_label); - emit_label (cond_stack->data.cond.next_label); - cond_stack->data.cond.next_label = 0; /* No more _else or _elseif calls. */ -} - -/* After calling expand_start_else, turn this "else" into an "else if" - by providing another condition. */ - -void -expand_elseif (tree cond) -{ - cond_stack->data.cond.next_label = gen_label_rtx (); - do_jump (cond, cond_stack->data.cond.next_label, NULL_RTX); -} - -/* Generate RTL for the end of an if-then. - Pop the record for it off of cond_stack. */ - -void -expand_end_cond (void) -{ - struct nesting *thiscond = cond_stack; - - do_pending_stack_adjust (); - if (thiscond->data.cond.next_label) - emit_label (thiscond->data.cond.next_label); - if (thiscond->data.cond.endif_label) - emit_label (thiscond->data.cond.endif_label); - - POPSTACK (cond_stack); -} - /* Return nonzero if we should preserve sub-expressions as separate pseudos. We never do so if we aren't optimizing. We always do so if -fexpensive-optimizations. */ @@ -1741,13 +1499,7 @@ expand_end_cond (void) int preserve_subexpressions_p (void) { - if (flag_expensive_optimizations) - return 1; - - if (optimize == 0 || cfun == 0 || cfun->stmt == 0) - return 0; - - return 1; + return optimize && (cfun || flag_expensive_optimizations); } @@ -2451,54 +2203,13 @@ expand_anon_union_decl (tree decl, tree cleanup ATTRIBUTE_UNUSED, } } -/* Enter a case (Pascal) or switch (C) statement. - Push a block onto case_stack and nesting_stack - to accumulate the case-labels that are seen - and to record the labels generated for the statement. - - EXIT_FLAG is nonzero if `exit_something' should exit this case stmt. - Otherwise, this construct is transparent for `exit_something'. - - EXPR is the index-expression to be dispatched on. - TYPE is its nominal type. We could simply convert EXPR to this type, - but instead we take short cuts. */ - -void -expand_start_case (tree index_expr) -{ - struct nesting *thiscase = ALLOC_NESTING (); - - /* Make an entry on case_stack for the case we are entering. */ - - thiscase->desc = CASE_NESTING; - thiscase->next = case_stack; - thiscase->all = nesting_stack; - thiscase->depth = ++nesting_depth; - thiscase->exit_label = 0; - thiscase->data.case_stmt.case_list = 0; - thiscase->data.case_stmt.index_expr = index_expr; - thiscase->data.case_stmt.default_label = 0; - case_stack = thiscase; - nesting_stack = thiscase; - - do_pending_stack_adjust (); - - /* Make sure case_stmt.start points to something that won't - need any transformation before expand_end_case. */ - if (!NOTE_P (get_last_insn ())) - emit_note (NOTE_INSN_DELETED); - - thiscase->data.case_stmt.start = get_last_insn (); -} - -/* Do the insertion of a case label into - case_stack->data.case_stmt.case_list. The labels are fed to us - in descending order from the sorted vector of case labels used +/* Do the insertion of a case label into case_list. The labels are + fed to us in descending order from the sorted vector of case labels used in the tree part of the middle end. So the list we construct is sorted in ascending order. */ -void -add_case_node (tree low, tree high, tree label) +struct case_node * +add_case_node (struct case_node *head, tree low, tree high, tree label) { struct case_node *r; @@ -2509,25 +2220,14 @@ add_case_node (tree low, tree high, tree label) if (!high || tree_int_cst_equal (low, high)) high = low; - /* Handle default labels specially. */ - if (!high && !low) - { -#ifdef ENABLE_CHECKING - if (case_stack->data.case_stmt.default_label != 0) - abort (); -#endif - case_stack->data.case_stmt.default_label = label; - return; - } - /* Add this label to the chain. */ r = ggc_alloc (sizeof (struct case_node)); r->low = low; r->high = high; r->code_label = label; r->parent = r->left = NULL; - r->right = case_stack->data.case_stmt.case_list; - case_stack->data.case_stmt.case_list = r; + r->right = head; + return r; } /* Maximum number of case bit tests. */ @@ -2618,7 +2318,7 @@ emit_case_bit_tests (tree index_type, tree index_expr, tree minval, { label = label_rtx (n->code_label); for (i = 0; i < count; i++) - if (same_case_target_p (label, test[i].label)) + if (label == test[i].label) break; if (i == count) @@ -2689,7 +2389,7 @@ emit_case_bit_tests (tree index_type, tree index_expr, tree minval, Generate the code to test it and jump to the right place. */ void -expand_end_case_type (tree orig_index, tree orig_type) +expand_case (tree exp) { tree minval = NULL_TREE, maxval = NULL_TREE, range = NULL_TREE; rtx default_label = 0; @@ -2701,42 +2401,68 @@ expand_end_case_type (tree orig_index, tree orig_type) rtx *labelvec; int i; rtx before_case, end, lab; - struct nesting *thiscase = case_stack; - tree index_expr, index_type; - bool exit_done = false; - int unsignedp; - /* Don't crash due to previous errors. */ - if (thiscase == NULL) - return; + tree vec = SWITCH_LABELS (exp); + tree orig_type = TREE_TYPE (exp); + tree index_expr = SWITCH_COND (exp); + tree index_type = TREE_TYPE (index_expr); + int unsignedp = TYPE_UNSIGNED (index_type); + + /* The insn after which the case dispatch should finally + be emitted. Zero for a dummy. */ + rtx start; + + /* A list of case labels; it is first built as a list and it may then + be rearranged into a nearly balanced binary tree. */ + struct case_node *case_list = 0; + + /* Label to jump to if no case matches. */ + tree default_label_decl = 0; + + /* The switch body is lowered in gimplify.c, we should never have + switches with a non-NULL SWITCH_BODY here. */ + if (SWITCH_BODY (exp) || !SWITCH_LABELS (exp)) + abort (); - index_expr = thiscase->data.case_stmt.index_expr; - index_type = TREE_TYPE (index_expr); - unsignedp = TYPE_UNSIGNED (index_type); - if (orig_type == NULL) - orig_type = TREE_TYPE (orig_index); + for (i = TREE_VEC_LENGTH (vec); --i >= 0; ) + { + tree elt = TREE_VEC_ELT (vec, i); + + /* Handle default labels specially. */ + if (!CASE_HIGH (elt) && !CASE_LOW (elt)) + { +#ifdef ENABLE_CHECKING + if (default_label_decl != 0) + abort (); +#endif + default_label_decl = CASE_LABEL (elt); + } + else + case_list = add_case_node (case_list, CASE_LOW (elt), CASE_HIGH (elt), + CASE_LABEL (elt)); + } do_pending_stack_adjust (); + /* Make sure start points to something that won't need any transformation + before the end of this function. */ + if (!NOTE_P (get_last_insn ())) + emit_note (NOTE_INSN_DELETED); + + start = get_last_insn (); + /* An ERROR_MARK occurs for various reasons including invalid data type. */ if (index_type != error_mark_node) { /* If we don't have a default-label, create one here, after the body of the switch. */ - if (thiscase->data.case_stmt.default_label == 0) + if (default_label_decl == 0) { - thiscase->data.case_stmt.default_label + default_label_decl = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE); - /* Share the exit label if possible. */ - if (thiscase->exit_label) - { - SET_DECL_RTL (thiscase->data.case_stmt.default_label, - thiscase->exit_label); - exit_done = true; - } - expand_label (thiscase->data.case_stmt.default_label); + expand_label (default_label_decl); } - default_label = label_rtx (thiscase->data.case_stmt.default_label); + default_label = label_rtx (default_label_decl); before_case = get_last_insn (); @@ -2745,7 +2471,7 @@ expand_end_case_type (tree orig_index, tree orig_type) uniq = 0; count = 0; - for (n = thiscase->data.case_stmt.case_list; n; n = n->right) + for (n = case_list; n; n = n->right) { /* Check low and high label values are integers. */ if (TREE_CODE (n->low) != INTEGER_CST) @@ -2777,8 +2503,8 @@ expand_end_case_type (tree orig_index, tree orig_type) /* Count the number of unique case node targets. */ uniq++; lab = label_rtx (n->code_label); - for (m = thiscase->data.case_stmt.case_list; m != n; m = m->right) - if (same_case_target_p (label_rtx (m->code_label), lab)) + for (m = case_list; m != n; m = m->right) + if (label_rtx (m->code_label) == lab) { uniq--; break; @@ -2817,8 +2543,7 @@ expand_end_case_type (tree orig_index, tree orig_type) range = maxval; } emit_case_bit_tests (index_type, index_expr, minval, range, - thiscase->data.case_stmt.case_list, - default_label); + case_list, default_label); } /* If range of values is much bigger than number of values, @@ -2882,7 +2607,7 @@ expand_end_case_type (tree orig_index, tree orig_type) target code. The job of removing any unreachable code is left to the optimization phase if the "-O" option is specified. */ - for (n = thiscase->data.case_stmt.case_list; n; n = n->right) + for (n = case_list; n; n = n->right) if (! tree_int_cst_lt (index_expr, n->low) && ! tree_int_cst_lt (n->high, index_expr)) break; @@ -2910,10 +2635,9 @@ expand_end_case_type (tree orig_index, tree orig_type) use_cost_table = (TREE_CODE (orig_type) != ENUMERAL_TYPE - && estimate_case_costs (thiscase->data.case_stmt.case_list)); - balance_case_nodes (&thiscase->data.case_stmt.case_list, NULL); - emit_case_nodes (index, thiscase->data.case_stmt.case_list, - default_label, index_type); + && estimate_case_costs (case_list)); + balance_case_nodes (&case_list, NULL); + emit_case_nodes (index, case_list, default_label, index_type); emit_jump (default_label); } } @@ -2946,7 +2670,7 @@ expand_end_case_type (tree orig_index, tree orig_type) labelvec = alloca (ncases * sizeof (rtx)); memset (labelvec, 0, ncases * sizeof (rtx)); - for (n = thiscase->data.case_stmt.case_list; n; n = n->right) + for (n = case_list; n; n = n->right) { /* Compute the low and high bounds relative to the minimum value since that should fit in a HOST_WIDE_INT while the @@ -2995,15 +2719,9 @@ expand_end_case_type (tree orig_index, tree orig_type) end = get_last_insn (); if (squeeze_notes (&before_case, &end)) abort (); - reorder_insns (before_case, end, - thiscase->data.case_stmt.start); + reorder_insns (before_case, end, start); } - if (thiscase->exit_label && !exit_done) - emit_label (thiscase->exit_label); - - POPSTACK (case_stack); - free_temp_slots (); } @@ -3103,16 +2821,6 @@ estimate_case_costs (case_node_ptr node) return 1; } -/* 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) -{ - return l1 == l2; -} - /* 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 @@ -3745,5 +3453,3 @@ emit_case_nodes (rtx index, case_node_ptr node, rtx default_label, } } } - -#include "gt-stmt.h" diff --git a/gcc/tree.h b/gcc/tree.h index 8bd1219240b..2b71b393065 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -3352,10 +3352,6 @@ extern void expand_decl_init (tree); extern void expand_label (tree); extern void expand_goto (tree); extern void expand_asm (tree, int); -extern void expand_start_cond (tree, int); -extern void expand_end_cond (void); -extern void expand_start_else (void); -extern void expand_start_elseif (tree); extern void expand_stack_alloc (tree, tree); extern rtx expand_stack_save (void); @@ -3363,12 +3359,6 @@ extern void expand_stack_restore (tree); extern void expand_return (tree); extern int is_body_block (tree); -extern struct nesting * current_nesting_level (void); -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 void add_case_node (tree, tree, tree); - /* In tree-eh.c */ extern void using_eh_for_cleanups (void); @@ -3619,7 +3609,6 @@ extern void notice_global_symbol (tree); extern void set_user_assembler_name (tree, const char *); /* In stmt.c */ -extern void emit_nop (void); extern void expand_computed_goto (tree); extern bool parse_output_constraint (const char **, int, int, int, bool *, bool *, bool *); @@ -3629,8 +3618,7 @@ extern void expand_asm_operands (tree, tree, tree, tree, int, location_t); extern void expand_asm_expr (tree); extern bool asm_op_is_mem_input (tree, tree); extern tree resolve_asm_operand_names (tree, tree, tree); -extern void init_stmt_for_function (void); -extern void expand_elseif (tree); +extern void expand_case (tree); extern void expand_decl (tree); extern void expand_anon_union_decl (tree, tree, tree);