This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Cleanup some switch expanding code and leftovers from RTL EH
- From: Steven Bosscher <stevenb at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Cc: java-patches at gcc dot gnu dot org
- Date: Sun, 11 Jul 2004 18:25:03 +0200
- Subject: Cleanup some switch expanding code and leftovers from RTL EH
- Organization: SUSE Labs
Hi,
While cleaning up a few more switch expanding related functions,
I noted some other garbage, mostly in stmt.c and emit-rtl.c, that
should go away. Some of them are leftovers from rth removing RTL
exception handling, and the others because we already lower switch
statements in gimplify.c.
Bootstrapped&tested on x86_64-unknown-linux-gnu, OK?
Gr.
Steven
* 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.
cp/
* cp-tree.h (struct lang_type): Don't have three GTY options on a
single bit GTY desc.
java/
* parse.y (java_complete_expand_methods, java_expand_classes): Don't
abuse restore_line_number_status.
Index: emit-rtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/emit-rtl.c,v
retrieving revision 1.402
diff -c -3 -p -r1.402 emit-rtl.c
*** emit-rtl.c 9 Jul 2004 03:29:27 -0000 1.402
--- emit-rtl.c 11 Jul 2004 15:22:27 -0000
*************** init_emit_once (int line_numbers)
*** 5444,5470 ****
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. */
--- 5444,5449 ----
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.679
diff -c -3 -p -r1.679 expr.c
*** expr.c 11 Jul 2004 11:11:36 -0000 1.679
--- expr.c 11 Jul 2004 15:22:27 -0000
*************** expand_expr_real_1 (tree exp, rtx target
*** 8824,8829 ****
--- 8824,8830 ----
case WITH_CLEANUP_EXPR:
case CLEANUP_POINT_EXPR:
case TARGET_EXPR:
+ case CASE_LABEL_EXPR:
/* Lowered by gimplify.c. */
abort ();
*************** expand_expr_real_1 (tree exp, rtx target
*** 8842,8851 ****
abort ();
case SWITCH_EXPR:
! expand_start_case (0, SWITCH_COND (exp), integer_type_node,
! "switch");
if (SWITCH_BODY (exp))
! expand_expr_stmt (SWITCH_BODY (exp));
if (SWITCH_LABELS (exp))
{
tree duplicate = 0;
--- 8843,8853 ----
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 duplicate = 0;
*************** expand_expr_real_1 (tree exp, rtx target
*** 8904,8910 ****
}
}
! add_case_node (case_low, case_high, CASE_LABEL (elt), &duplicate, true);
if (duplicate)
abort ();
}
--- 8906,8912 ----
}
}
! add_case_node (case_low, case_high, CASE_LABEL (elt), &duplicate);
if (duplicate)
abort ();
}
*************** expand_expr_real_1 (tree exp, rtx target
*** 8916,8931 ****
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;
--- 8918,8923 ----
Index: rtl.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtl.h,v
retrieving revision 1.489
diff -c -3 -p -r1.489 rtl.h
*** rtl.h 9 Jul 2004 03:29:34 -0000 1.489
--- rtl.h 11 Jul 2004 15:22:28 -0000
*************** extern void remove_insn (rtx);
*** 2199,2209 ****
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);
--- 2199,2204 ----
Index: stmt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stmt.c,v
retrieving revision 1.375
diff -c -3 -p -r1.375 stmt.c
*** stmt.c 10 Jul 2004 08:04:57 -0000 1.375
--- stmt.c 11 Jul 2004 15:22:28 -0000
*************** struct nesting GTY(())
*** 174,189 ****
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
--- 174,179 ----
*************** struct nesting GTY(())
*** 199,212 ****
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;
};
--- 189,194 ----
*************** do { struct nesting *target = STACK; \
*** 234,265 ****
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(())
{
--- 216,221 ----
*************** struct stmt_status GTY(())
*** 287,294 ****
/* 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)
--- 243,248 ----
*************** struct stmt_status GTY(())
*** 298,307 ****
#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);
--- 252,257 ----
*************** static void expand_value_return (rtx);
*** 316,341 ****
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));
--- 266,282 ----
*************** expand_start_bindings_and_block (int fla
*** 2224,2231 ****
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
--- 2165,2170 ----
*************** expand_anon_union_decl (tree decl, tree
*** 2779,2786 ****
but instead we take short cuts. */
void
! expand_start_case (int exit_flag, tree expr, tree type,
! const char *printname)
{
struct nesting *thiscase = ALLOC_NESTING ();
--- 2718,2724 ----
but instead we take short cuts. */
void
! expand_start_case (tree index_expr)
{
struct nesting *thiscase = ALLOC_NESTING ();
*************** expand_start_case (int exit_flag, tree e
*** 2790,2802 ****
thiscase->next = case_stack;
thiscase->all = nesting_stack;
thiscase->depth = ++nesting_depth;
! thiscase->exit_label = exit_flag ? gen_label_rtx () : 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.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;
--- 2728,2737 ----
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;
*************** expand_start_case (int exit_flag, tree e
*** 2811,2929 ****
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
slowdown for large switch statements. */
int
! add_case_node (tree low, tree high, tree label, tree *duplicate,
! bool dont_expand_label)
{
struct case_node *p, **q, *r;
--- 2746,2757 ----
thiscase->data.case_stmt.start = get_last_insn ();
}
! /* 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)
{
struct case_node *p, **q, *r;
*************** add_case_node (tree low, tree high, tree
*** 2942,2949 ****
return 2;
}
case_stack->data.case_stmt.default_label = label;
- if (!dont_expand_label)
- expand_label (label);
return 0;
}
--- 2770,2775 ----
*************** add_case_node (tree low, tree high, tree
*** 2982,2989 ****
r->high = high;
r->code_label = label;
- if (!dont_expand_label)
- expand_label (label);
*q = r;
r->parent = p;
--- 2808,2813 ----
*************** expand_end_case_type (tree orig_index, t
*** 3377,3387 ****
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. */
--- 3201,3206 ----
*************** expand_end_case_type (tree orig_index, t
*** 3559,3565 ****
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);
}
}
else
--- 3378,3384 ----
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 (default_label);
}
}
else
*************** expand_end_case_type (tree orig_index, t
*** 3568,3574 ****
if (! try_casesi (index_type, index_expr, minval, range,
table_label, default_label))
{
! index_type = thiscase->data.case_stmt.nominal_type;
/* Index jumptables from zero for suitable values of
minval to avoid a subtraction. */
--- 3387,3393 ----
if (! try_casesi (index_type, index_expr, minval, range,
table_label, default_label))
{
! index_type = integer_type_node;
/* Index jumptables from zero for suitable values of
minval to avoid a subtraction. */
*************** estimate_case_costs (case_node_ptr node)
*** 3770,3869 ****
return 1;
}
! /* Determine whether two case labels branch to the same target. */
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
--- 3589,3604 ----
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
*************** node_is_bounded (case_node_ptr node, tre
*** 4086,4100 ****
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
--- 3821,3826 ----
*************** emit_case_nodes (rtx index, case_node_pt
*** 4240,4246 ****
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);
/* Code branches here for the right-hand subtree. */
expand_label (test_label);
--- 3966,3972 ----
emit_case_nodes (index, node->left, default_label, index_type);
/* If left-hand subtree does nothing,
go to default. */
! emit_jump (default_label);
/* Code branches here for the right-hand subtree. */
expand_label (test_label);
*************** emit_case_nodes (rtx index, case_node_pt
*** 4381,4387 ****
{
/* If the left-hand subtree fell through,
don't let it fall into the right-hand subtree. */
! emit_jump_if_reachable (default_label);
expand_label (test_label);
emit_case_nodes (index, node->right, default_label, index_type);
--- 4107,4113 ----
{
/* If the left-hand subtree fell through,
don't let it fall into the right-hand subtree. */
! emit_jump (default_label);
expand_label (test_label);
emit_case_nodes (index, node->right, default_label, index_type);
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-cfg.c,v
retrieving revision 2.29
diff -c -3 -p -r2.29 tree-cfg.c
*** tree-cfg.c 9 Jul 2004 22:42:37 -0000 2.29
--- tree-cfg.c 11 Jul 2004 15:22:28 -0000
*************** static void tree_cfg2vcg (FILE *);
*** 99,106 ****
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);
--- 99,104 ----
*************** update_eh_label (struct eh_region *regio
*** 769,775 ****
tree old_label = get_eh_region_tree_label (region);
if (old_label)
{
! tree new_label = label_for_bb[label_to_block (old_label)->index];
set_eh_region_tree_label (region, new_label);
}
}
--- 767,782 ----
tree old_label = get_eh_region_tree_label (region);
if (old_label)
{
! 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);
}
}
*************** main_block_label (tree label)
*** 791,797 ****
2) Redirect all references to labels to the leading labels.
3) Cleanup all useless labels. */
! static void
cleanup_dead_labels (void)
{
basic_block bb;
--- 798,804 ----
2) Redirect all references to labels to the leading labels.
3) Cleanup all useless labels. */
! void
cleanup_dead_labels (void)
{
basic_block bb;
*************** cleanup_dead_labels (void)
*** 924,930 ****
same label.
Eg. three separate entries 1: 2: 3: become one entry 1..3: */
! static void
group_case_labels (void)
{
basic_block bb;
--- 931,937 ----
same label.
Eg. three separate entries 1: 2: 3: become one entry 1..3: */
! void
group_case_labels (void)
{
basic_block bb;
Index: tree-eh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-eh.c,v
retrieving revision 2.10
diff -c -3 -p -r2.10 tree-eh.c
*** tree-eh.c 10 Jul 2004 04:57:54 -0000 2.10
--- tree-eh.c 11 Jul 2004 15:22:28 -0000
*************** Boston, MA 02111-1307, USA. */
*** 37,44 ****
#include "langhooks.h"
#include "ggc.h"
! /* HACK */
! extern int using_eh_for_cleanups_p;
/* Misc functions used in this file. */
--- 37,51 ----
#include "langhooks.h"
#include "ggc.h"
!
! /* 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. */
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-flow.h,v
retrieving revision 2.23
diff -c -3 -p -r2.23 tree-flow.h
*** tree-flow.h 10 Jul 2004 04:57:54 -0000 2.23
--- tree-flow.h 11 Jul 2004 15:22:28 -0000
*************** extern void dump_cfg_stats (FILE *);
*** 486,491 ****
--- 486,493 ----
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);
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 2.28
diff -c -3 -p -r2.28 tree-optimize.c
*** tree-optimize.c 10 Jul 2004 04:57:54 -0000 2.28
--- tree-optimize.c 11 Jul 2004 15:22:28 -0000
*************** static struct tree_opt_pass pass_all_opt
*** 101,106 ****
--- 101,135 ----
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
+ 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. */
*************** init_tree_optimization_passes (void)
*** 324,329 ****
--- 353,359 ----
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;
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.554
diff -c -3 -p -r1.554 tree.h
*** tree.h 11 Jul 2004 10:04:57 -0000 1.554
--- tree.h 11 Jul 2004 15:22:29 -0000
*************** extern void warn_about_unused_variables
*** 3352,3363 ****
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_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 void using_eh_for_cleanups (void);
/* In fold-const.c */
--- 3352,3363 ----
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 int add_case_node (tree, tree, tree, tree *);
!
! /* In tree-eh.c */
extern void using_eh_for_cleanups (void);
/* In fold-const.c */
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1000
diff -c -3 -p -r1.1000 cp-tree.h
*** cp/cp-tree.h 11 Jul 2004 09:53:02 -0000 1.1000
--- cp/cp-tree.h 11 Jul 2004 15:22:33 -0000
*************** struct lang_type GTY(())
*** 1049,1055 ****
{
union lang_type_u
{
! struct lang_type_header GTY((tag ("2"))) 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;
--- 1049,1055 ----
{
union lang_type_u
{
! 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;
Index: java/parse.y
===================================================================
RCS file: /cvs/gcc/gcc/gcc/java/parse.y,v
retrieving revision 1.491
diff -c -3 -p -r1.491 parse.y
*** java/parse.y 10 Jul 2004 05:38:15 -0000 1.491
--- java/parse.y 11 Jul 2004 15:22:35 -0000
*************** java_complete_expand_methods (tree class
*** 7746,7766 ****
/* 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. */
--- 7746,7754 ----
*************** java_expand_classes (void)
*** 9036,9044 ****
{
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. */
}
}
--- 9024,9030 ----
*************** java_expand_classes (void)
*** 9060,9070 ****
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);
! }
}
}
}
--- 9046,9052 ----
for (d = TYPE_METHODS (current_class); d; d = TREE_CHAIN (d))
{
if (DECL_RESULT (d) == NULL_TREE)
! java_complete_expand_method (d);
}
}
}
*************** java_expand_classes (void)
*** 9093,9101 ****
if (DECL_RESULT (d) == NULL_TREE)
{
something_changed = 1;
- restore_line_number_status (1);
java_complete_expand_method (d);
- restore_line_number_status (0);
}
}
}
--- 9075,9081 ----