aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>2003-10-05 19:25:45 +0000
committerZdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>2003-10-05 19:25:45 +0000
commit5d257a9fb0630280c9641ba8d7483bd14abee86b (patch)
treeebc3b32c994e64c1e08654a14590a1c5f591767e
parent0ba2d01f63f0cb3a15f5cc2e7e32b948ba3f8b2d (diff)
* gimple-low.c: New.
* Makefile.in (gimple-low.o): Add. * cfglayout.c (insn_locators_initialize): Use new scoping info. * expr.c (expand_expr): Record scope changes. * function.c (blocks_nreverse): Export. (uninitialized_vars_warning): Use DECL_RTL_SET_P instead of DECL_RTL. (reset_block_changes, record_block_change, record_block_change, check_block_change, free_block_changes): New. * function.h (struct function): New fields dont_emit_block_notes and ib_boundaries_block. (blocks_nreverse, reset_block_changes, record_block_change, finalize_block_changes, check_block_change, free_block_changes): Declare. * sibcall.c (optimize_sibling_and_tail_recursive_call): Don't call reorder_blocks if cfun->dont_emit_block_notes. * stmt.c (expand_start_bindings_and_block, expand_end_bindings): Don't emit block notes if cfun->dont_emit_block_notes. * toplev.c (rest_of_compilation): Don't call reorder_blocks if cfun->dont_emit_block_notes. * tree-flow.h (lower_function_body): Declare. * tree-optimize.c (optimize_function_tree): Call lower_function_body. * tree.c (build1): Initialize TREE_BLOCK. * tree.h (TREE_BLOCK): New macro. (struct tree_exp): Add block field. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/tree-ssa-cfg-branch@72117 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog.tree-ssa-cfg27
-rw-r--r--gcc/Makefile.in6
-rw-r--r--gcc/cfglayout.c10
-rw-r--r--gcc/expr.c10
-rw-r--r--gcc/function.c59
-rw-r--r--gcc/function.h14
-rw-r--r--gcc/gimple-low.c182
-rw-r--r--gcc/sibcall.c3
-rw-r--r--gcc/stmt.c4
-rw-r--r--gcc/toplev.c26
-rw-r--r--gcc/tree-flow.h2
-rw-r--r--gcc/tree-optimize.c5
-rw-r--r--gcc/tree.c1
-rw-r--r--gcc/tree.h3
14 files changed, 333 insertions, 19 deletions
diff --git a/gcc/ChangeLog.tree-ssa-cfg b/gcc/ChangeLog.tree-ssa-cfg
index 595926ff52c..70a227bb3a6 100644
--- a/gcc/ChangeLog.tree-ssa-cfg
+++ b/gcc/ChangeLog.tree-ssa-cfg
@@ -1,3 +1,30 @@
+2003-10-05 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
+
+ * gimple-low.c: New.
+ * Makefile.in (gimple-low.o): Add.
+ * cfglayout.c (insn_locators_initialize): Use new scoping info.
+ * expr.c (expand_expr): Record scope changes.
+ * function.c (blocks_nreverse): Export.
+ (uninitialized_vars_warning): Use DECL_RTL_SET_P instead of DECL_RTL.
+ (reset_block_changes, record_block_change, record_block_change,
+ check_block_change, free_block_changes): New.
+ * function.h (struct function): New fields dont_emit_block_notes
+ and ib_boundaries_block.
+ (blocks_nreverse, reset_block_changes, record_block_change,
+ finalize_block_changes, check_block_change, free_block_changes):
+ Declare.
+ * sibcall.c (optimize_sibling_and_tail_recursive_call): Don't call
+ reorder_blocks if cfun->dont_emit_block_notes.
+ * stmt.c (expand_start_bindings_and_block, expand_end_bindings): Don't
+ emit block notes if cfun->dont_emit_block_notes.
+ * toplev.c (rest_of_compilation): Don't call reorder_blocks if
+ cfun->dont_emit_block_notes.
+ * tree-flow.h (lower_function_body): Declare.
+ * tree-optimize.c (optimize_function_tree): Call lower_function_body.
+ * tree.c (build1): Initialize TREE_BLOCK.
+ * tree.h (TREE_BLOCK): New macro.
+ (struct tree_exp): Add block field.
+
2003-10-03 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
* tree-ssa.c (degrees): Removed.
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index b4d3fa24967..ecd5f075204 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -865,7 +865,7 @@ OBJS-common = \
tree-alias-type.o gimplify.o tree-nomudflap.o tree-pretty-print.o \
tree-alias-common.o tree-ssa-ccp.o tree-browser.o @ANDER@ tree-ssa-dce.o \
tree-ssa-pre.o tree-ssa-copyprop.o tree-ssa-live.o tree-must-alias.o \
- tree-ssa-dom.o \
+ tree-ssa-dom.o gimple-low.o \
alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o \
cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o \
cfgloopanal.o cfgloopmanip.o loop-init.o loop-unswitch.o loop-unroll.o \
@@ -1570,6 +1570,10 @@ gimplify.o : gimplify.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) errors.h \
diagnostic.h $(TREE_SIMPLE_H) tree-inline.h varray.h langhooks.h \
langhooks-def.h $(TREE_FLOW_H) $(TIMEVAR_H) $(TM_H) coretypes.h except.h \
flags.h $(RTL_H)
+gimple-low.o : gimple-low.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) errors.h \
+ diagnostic.h $(TREE_SIMPLE_H) tree-inline.h varray.h langhooks.h \
+ langhooks-def.h $(TREE_FLOW_H) $(TIMEVAR_H) $(TM_H) coretypes.h except.h \
+ flags.h $(RTL_H) function.h
tree-browser.o : tree-browser.c tree-browser.def $(CONFIG_H) $(SYSTEM_H) \
$(TREE_H) errors.h tree-inline.h diagnostic.h $(HASHTAB_H) \
$(TM_H) coretypes.h
diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c
index 7121a3e5db4..a3199a27d34 100644
--- a/gcc/cfglayout.c
+++ b/gcc/cfglayout.c
@@ -310,10 +310,14 @@ insn_locators_initialize (void)
switch (NOTE_LINE_NUMBER (insn))
{
case NOTE_INSN_BLOCK_BEG:
+ if (cfun->dont_emit_block_notes)
+ abort ();
block = NOTE_BLOCK (insn);
delete_insn (insn);
break;
case NOTE_INSN_BLOCK_END:
+ if (cfun->dont_emit_block_notes)
+ abort ();
block = BLOCK_SUPERCONTEXT (block);
if (block && TREE_CODE (block) == FUNCTION_DECL)
block = 0;
@@ -328,11 +332,17 @@ insn_locators_initialize (void)
break;
}
}
+
+ if (cfun->dont_emit_block_notes)
+ check_block_change (insn, &block);
}
/* Tag the blocks with a depth number so that change_scope can find
the common parent easily. */
set_block_levels (DECL_INITIAL (cfun->decl), 0);
+
+ if (cfun->dont_emit_block_notes)
+ free_block_changes ();
}
/* For each lexical block, set BLOCK_NUMBER to the depth at which it is
diff --git a/gcc/expr.c b/gcc/expr.c
index 37c4d437eb9..554547ae89f 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -6762,6 +6762,10 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode,
input_line = EXPR_LINENO (exp);
emit_line_note (input_location);
+ /* Record where the insns produced belong. */
+ if (cfun->dont_emit_block_notes)
+ record_block_change (TREE_BLOCK (exp));
+
/* This is a gross hack. Temporarily remove the locus information
and re-call expand_expr.
@@ -8818,7 +8822,11 @@ expand_expr (tree exp, rtx target, enum machine_mode tmode,
{
expand_start_else ();
if (EXPR_LOCUS (exp))
- emit_line_note (*(EXPR_LOCUS (exp)));
+ {
+ emit_line_note (*(EXPR_LOCUS (exp)));
+ if (cfun->dont_emit_block_notes)
+ record_block_change (TREE_BLOCK (exp));
+ }
expand_elseif (TREE_OPERAND (exp, 0));
expand_expr (TREE_OPERAND (exp, 1), const0_rtx, VOIDmode, 0);
}
diff --git a/gcc/function.c b/gcc/function.c
index baec4ab3048..8d230455485 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -265,7 +265,6 @@ static tree *identify_blocks_1 (rtx, tree *, tree *, tree *);
static void reorder_blocks_0 (tree);
static void reorder_blocks_1 (rtx, tree, varray_type *);
static void reorder_fix_fragments (tree);
-static tree blocks_nreverse (tree);
static int all_blocks (tree, tree *);
static tree *get_block_vector (tree, int *);
extern tree debug_find_var_in_block_tree (tree, tree);
@@ -5598,7 +5597,7 @@ uninitialized_vars_warning (tree block)
flow.c that the entire aggregate was initialized.
Unions are troublesome because members may be shorter. */
&& ! AGGREGATE_TYPE_P (TREE_TYPE (decl))
- && DECL_RTL (decl) != 0
+ && DECL_RTL_SET_P (decl)
&& GET_CODE (DECL_RTL (decl)) == REG
/* Global optimizations can make it difficult to determine if a
particular variable has been initialized. However, a VAR_DECL
@@ -5613,7 +5612,7 @@ uninitialized_vars_warning (tree block)
decl, decl);
if (extra_warnings
&& TREE_CODE (decl) == VAR_DECL
- && DECL_RTL (decl) != 0
+ && DECL_RTL_SET_P (decl)
&& GET_CODE (DECL_RTL (decl)) == REG
&& regno_clobbered_at_setjmp (REGNO (DECL_RTL (decl))))
warning ("%Jvariable '%D' might be clobbered by `longjmp' or `vfork'",
@@ -6177,7 +6176,7 @@ reorder_fix_fragments (tree block)
/* Reverse the order of elements in the chain T of blocks,
and return the new head of the chain (old last element). */
-static tree
+tree
blocks_nreverse (tree t)
{
tree prev = 0, decl, next;
@@ -7939,4 +7938,56 @@ init_function_once (void)
VARRAY_INT_INIT (sibcall_epilogue, 0, "sibcall_epilogue");
}
+/* Resets insn_block_boundaries array. */
+
+void
+reset_block_changes ()
+{
+ VARRAY_TREE_INIT (cfun->ib_boundaries_block, 100, "ib_boundaries_block");
+ VARRAY_PUSH_TREE (cfun->ib_boundaries_block, NULL_TREE);
+}
+
+/* Record the boundary for BLOCK. */
+void
+record_block_change (tree block)
+{
+ int i, n;
+ tree last_block;
+
+ if (!block)
+ return;
+
+ last_block = VARRAY_TOP_TREE (cfun->ib_boundaries_block);
+ VARRAY_POP (cfun->ib_boundaries_block);
+ n = get_max_uid ();
+ for (i = VARRAY_ACTIVE_SIZE (cfun->ib_boundaries_block); i < n; i++)
+ VARRAY_PUSH_TREE (cfun->ib_boundaries_block, last_block);
+
+ VARRAY_PUSH_TREE (cfun->ib_boundaries_block, block);
+}
+
+/* Finishes record of boundaries. */
+void finalize_block_changes ()
+{
+ record_block_change (DECL_INITIAL (current_function_decl));
+}
+
+/* For INSN return the BLOCK it belongs to. */
+void
+check_block_change (rtx insn, tree *block)
+{
+ unsigned uid = INSN_UID (insn);
+
+ if (uid >= VARRAY_ACTIVE_SIZE (cfun->ib_boundaries_block))
+ return;
+
+ *block = VARRAY_TREE (cfun->ib_boundaries_block, uid);
+}
+
+/* Releases the ib_boundaries_block records. */
+void
+free_block_changes ()
+{
+ cfun->ib_boundaries_block = NULL;
+}
#include "gt-function.h"
diff --git a/gcc/function.h b/gcc/function.h
index 37d6e2e9a2e..5307782e6fe 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -389,6 +389,10 @@ struct function GTY(())
delay list for them is recorded here. */
rtx epilogue_delay_list;
+ /* Nonzero if NOTE_INSN_BLOCK_BEG / NOTE_INSN_BLOCK_END notes should not
+ be emitted. */
+ unsigned int dont_emit_block_notes : 1;
+
/* How commonly executed the function is. Initialized during branch
probabilities pass. */
enum function_frequency {
@@ -409,6 +413,9 @@ struct function GTY(())
/* Line number of the end of the function. */
location_t function_end_locus;
+ /* Array mapping insn uids to blocks. */
+ struct varray_head_tag *ib_boundaries_block;
+
/* Collected bit flags. */
/* Nonzero if function being compiled needs to be given an address
@@ -601,6 +608,13 @@ extern void reorder_blocks (void);
/* Set BLOCK_NUMBER for all the blocks in FN. */
extern void number_blocks (tree);
+extern tree blocks_nreverse (tree);
+extern void reset_block_changes (void);
+extern void record_block_change (tree);
+extern void finalize_block_changes (void);
+extern void check_block_change (rtx, tree *);
+extern void free_block_changes (void);
+
/* Return size needed for stack frame based on slots so far allocated.
This size counts from zero. It is not rounded to STACK_BOUNDARY;
the caller may have to do that. */
diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c
new file mode 100644
index 00000000000..d7edd33beb2
--- /dev/null
+++ b/gcc/gimple-low.c
@@ -0,0 +1,182 @@
+/* Tree lowering pass. Lowers GIMPLE into unstructured form.
+
+ Copyright (C) 2003 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "rtl.h"
+#include "errors.h"
+#include "varray.h"
+#include "tree-simple.h"
+#include "tree-inline.h"
+#include "diagnostic.h"
+#include "langhooks.h"
+#include "langhooks-def.h"
+#include "tree-flow.h"
+#include "timevar.h"
+#include "except.h"
+#include "hashtab.h"
+#include "flags.h"
+#include "function.h"
+
+struct lower_data
+{
+ /* Block the current statement belongs to. */
+ tree block;
+};
+
+static void lower_stmt_body (tree *, struct lower_data *);
+static void lower_stmt (tree_stmt_iterator *, struct lower_data *);
+static void lower_bind_expr (tree_stmt_iterator *, struct lower_data *);
+static void lower_cond_expr (tree_stmt_iterator *, struct lower_data *);
+static void lower_switch_expr (tree_stmt_iterator *, struct lower_data *);
+
+/* Lowers the BODY. */
+void
+lower_function_body (tree *body)
+{
+ struct lower_data data;
+
+ if (TREE_CODE (*body) != BIND_EXPR)
+ abort ();
+
+ data.block = DECL_INITIAL (current_function_decl);
+ BLOCK_SUBBLOCKS (data.block) = NULL_TREE;
+ BLOCK_CHAIN (data.block) = NULL_TREE;
+
+ lower_stmt_body (&BIND_EXPR_BODY (*body), &data);
+
+ if (data.block != DECL_INITIAL (current_function_decl))
+ abort ();
+ BLOCK_SUBBLOCKS (data.block) =
+ blocks_nreverse (BLOCK_SUBBLOCKS (data.block));
+}
+
+/* Lowers the EXPR. Unlike gimplification the statements are not relowered
+ when they are changed -- if this has to be done, the lowering routine must
+ do it explicitly. DATA is passed through the recursion. */
+
+static void
+lower_stmt_body (tree *expr, struct lower_data *data)
+{
+ tree_stmt_iterator tsi;
+
+ for (tsi = tsi_start (expr); !tsi_end_p (tsi); tsi_next (&tsi))
+ lower_stmt (&tsi, data);
+}
+
+/* Lowers statement TSI. DATA is passed through the recursion. */
+static void
+lower_stmt (tree_stmt_iterator *tsi, struct lower_data *data)
+{
+ tree stmt = tsi_stmt (*tsi);
+
+ if (EXPR_LOCUS (stmt))
+ TREE_BLOCK (stmt) = data->block;
+
+ switch (TREE_CODE (stmt))
+ {
+ case BIND_EXPR:
+ lower_bind_expr (tsi, data);
+ break;
+
+ case COMPOUND_EXPR:
+ abort ();
+
+ case NOP_EXPR:
+ case ASM_EXPR:
+ case RETURN_EXPR:
+ case MODIFY_EXPR:
+ case CALL_EXPR:
+ case GOTO_EXPR:
+ case LABEL_EXPR:
+ case CASE_LABEL_EXPR:
+ case VA_ARG_EXPR:
+ case RESX_EXPR:
+ break;
+
+ case COND_EXPR:
+ lower_cond_expr (tsi, data);
+ break;
+
+ case SWITCH_EXPR:
+ lower_switch_expr (tsi, data);
+ break;
+
+ default:
+ print_node_brief (stderr, "", tsi_stmt (*tsi), 0);
+ abort ();
+ }
+}
+
+/* Lowers a bind_expr TSI. DATA is passed through the recursion. */
+
+static void
+lower_bind_expr (tree_stmt_iterator *tsi, struct lower_data *data)
+{
+ tree old_block = data->block;
+ tree stmt = tsi_stmt (*tsi);
+
+ if (BIND_EXPR_BLOCK (stmt))
+ {
+ data->block = BIND_EXPR_BLOCK (stmt);
+
+ /* Block tree may get clobbered by inlining. Normally this would be
+ fixed in rest_of_decl_compilation using block notes, but since we
+ are not going to emit them, it is up to us. */
+ BLOCK_CHAIN (data->block) = BLOCK_SUBBLOCKS (old_block);
+ BLOCK_SUBBLOCKS (old_block) = data->block;
+ BLOCK_SUBBLOCKS (data->block) = NULL_TREE;
+ BLOCK_SUPERCONTEXT (data->block) = old_block;
+ }
+ lower_stmt_body (&BIND_EXPR_BODY (stmt), data);
+
+ if (BIND_EXPR_BLOCK (stmt))
+ {
+ if (data->block != BIND_EXPR_BLOCK (stmt))
+ abort ();
+
+ BLOCK_SUBBLOCKS (data->block) =
+ blocks_nreverse (BLOCK_SUBBLOCKS (data->block));
+ data->block = old_block;
+ }
+}
+
+/* Lowers a cond_expr TSI. DATA is passed through the recursion. */
+
+static void
+lower_cond_expr (tree_stmt_iterator *tsi, struct lower_data *data)
+{
+ tree stmt = tsi_stmt (*tsi);
+
+ lower_stmt_body (&COND_EXPR_THEN (stmt), data);
+ lower_stmt_body (&COND_EXPR_ELSE (stmt), data);
+}
+
+/* Lowers a switch_expr TSI. DATA is passed through the recursion. */
+
+static void
+lower_switch_expr (tree_stmt_iterator *tsi, struct lower_data *data)
+{
+ lower_stmt_body (&SWITCH_BODY (tsi_stmt (*tsi)), data);
+}
diff --git a/gcc/sibcall.c b/gcc/sibcall.c
index ec85cb23786..bc210f9e66b 100644
--- a/gcc/sibcall.c
+++ b/gcc/sibcall.c
@@ -748,7 +748,8 @@ optimize_sibling_and_tail_recursive_calls (void)
/* There may have been NOTE_INSN_BLOCK_{BEGIN,END} notes in the
CALL_PLACEHOLDER alternatives that we didn't emit. Rebuild the
lexical block tree to correspond to the notes that still exist. */
- if (replaced_call_placeholder)
+ if (replaced_call_placeholder
+ && !cfun->dont_emit_block_notes)
reorder_blocks ();
/* This information will be invalid after inline expansion. Kill it now. */
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 2e0cd523d22..403a13ad64b 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -3402,7 +3402,7 @@ expand_start_bindings_and_block (int flags, tree block)
abort ();
/* Create a note to mark the beginning of the block. */
- if (block_flag)
+ if (block_flag && !cfun->dont_emit_block_notes)
{
note = emit_note (NOTE_INSN_BLOCK_BEG);
NOTE_BLOCK (note) = block;
@@ -3822,7 +3822,7 @@ expand_end_bindings (tree vars, int mark_ends, int dont_jump_in)
We do this now, after running cleanups on the variables
just going out of scope, so they are in scope for their cleanups. */
- if (mark_ends)
+ if (mark_ends && !cfun->dont_emit_block_notes)
{
rtx note = emit_note (NOTE_INSN_BLOCK_END);
NOTE_BLOCK (note) = NOTE_BLOCK (thisblock->data.block.first_insn);
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 4293ac345b0..69d7026b3f4 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -3139,15 +3139,20 @@ rest_of_compilation (tree decl)
have been run to re-initialize it. */
cse_not_expected = ! optimize;
- /* First, make sure that NOTE_BLOCK is set correctly for each
- NOTE_INSN_BLOCK_BEG/NOTE_INSN_BLOCK_END note. */
- if (!cfun->x_whole_function_mode_p)
- identify_blocks ();
-
- /* In function-at-a-time mode, we do not attempt to keep the BLOCK
- tree in sensible shape. So, we just recalculate it here. */
- if (cfun->x_whole_function_mode_p)
- reorder_blocks ();
+ if (!cfun->dont_emit_block_notes)
+ {
+ /* First, make sure that NOTE_BLOCK is set correctly for each
+ NOTE_INSN_BLOCK_BEG/NOTE_INSN_BLOCK_END note. */
+ if (!cfun->x_whole_function_mode_p)
+ identify_blocks ();
+
+ /* In function-at-a-time mode, we do not attempt to keep the BLOCK
+ tree in sensible shape. So, we just recalculate it here. */
+ if (cfun->x_whole_function_mode_p)
+ reorder_blocks ();
+ }
+ else
+ finalize_block_changes ();
init_flow ();
@@ -3175,7 +3180,8 @@ rest_of_compilation (tree decl)
over the instruction sequence faster, and allow the garbage
collector to reclaim the memory used by the notes. */
remove_unnecessary_notes ();
- reorder_blocks ();
+ if (!cfun->dont_emit_block_notes)
+ reorder_blocks ();
ggc_collect ();
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index 8d51c2dc88b..8f84e890e8e 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -513,6 +513,8 @@ extern void add_referenced_tmp_var (tree var);
#define TDFA_USE_OPS 1 << 0
#define TDFA_USE_VOPS 1 << 1
+/* In gimple-low.c */
+void lower_function_body (tree *);
/* In tree-ssa.c */
extern void init_tree_ssa (void);
diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c
index 65954234a5a..e0a49fc4319 100644
--- a/gcc/tree-optimize.c
+++ b/gcc/tree-optimize.c
@@ -61,8 +61,13 @@ optimize_function_tree (tree fndecl)
if (errorcount || sorrycount)
return;
+ lower_function_body (&DECL_SAVED_TREE (fndecl));
fnbody = DECL_SAVED_TREE (fndecl);
+ /* Avoid producing notes for blocks. */
+ cfun->dont_emit_block_notes = 1;
+ reset_block_changes ();
+
/* Flatten the trees. */
head.prev = head.next = NULL;
last = &head;
diff --git a/gcc/tree.c b/gcc/tree.c
index 2fe85234030..9d735c286a1 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -2431,6 +2431,7 @@ build1 (enum tree_code code, tree type, tree node)
TREE_TYPE (t) = type;
/* FIXME maybe give expr a locus here? */
SET_EXPR_LOCUS (t, NULL);
+ TREE_BLOCK (t) = NULL;
TREE_COMPLEXITY (t) = 0;
TREE_OPERAND (t, 0) = node;
if (node && first_rtl_op (code) != 0)
diff --git a/gcc/tree.h b/gcc/tree.h
index 2624fe19219..b1cab8607e8 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -426,6 +426,8 @@ extern void tree_operand_check_failed (int, enum tree_code,
#endif
+#define TREE_BLOCK(NODE) ((NODE)->exp.block)
+
#include "tree-check.h"
#define TYPE_CHECK(T) TREE_CLASS_CHECK (T, 't')
@@ -982,6 +984,7 @@ struct tree_exp GTY(())
struct tree_common common;
location_t *locus;
int complexity;
+ tree block;
tree GTY ((special ("tree_exp"),
desc ("TREE_CODE ((tree) &%0)")))
operands[1];