This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: patch committed to dataflow branch
- From: Kenneth Zadeck <zadeck at naturalbridge dot com>
- To: Kenneth Zadeck <zadeck at naturalbridge dot com>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>, "Berlin, Daniel" <dberlin at dberlin dot org>
- Date: Sat, 15 Apr 2006 20:18:40 -0400
- Subject: Re: patch committed to dataflow branch
- References: <44418C5E.4060803@naturalbridge.com>
Kenneth Zadeck wrote:
> This patch converts the threading of the prologue and epilogue to use df.
>
> This code has been bootstrapped and regression tested on
>
> x86_64-unknown-linux-gnu
> powerpc64-unknown-linux-gnu
> i686-pc-linux-gnu
>
> Kenny
>
>
>
forgot again to attach the patch.
>
> 2006-04-15 Kenneth Zadeck <zadeck@naturalbridge.com>
> * tree-pass.h (pass_flow2): Renamed to
> pass_thread_prologue_and_epilogue.
> * passes.c (pass_flow2): Ditto.
> * final.c (rest_of_clean_state): Removed flow2_completed.
> * config/i386/i386.md: Ditto.
> * config/sh/sh.md: Ditto.
> * config/mips/mips.md: Ditto.
> * config/h8300/h8300.md: Ditto.
> * flow.c: Ditto.
> (rest_of_handle_flow2): Moved to function.c as
> rest_of_handle_thread_prologue_and_epilogue.
> * timevar.def (TV_FLOW2): Renamed to
> TV_THREAD_PROLOGUE_AND_EPILOGUE.
> * function.c (keep_stack_depressed): Added df parameter.
> (thread_prologue_and_epilogue_insns): Made local function and
> removed unused parameter. Added local instance of df.
> (rest_of_handle_thread_prologue_and_epilogue): New function
> renamed from flow.c.
> (pass_thread_prologue_and_epilogue): New pass.
> * rtl.h (flow2_completed, thread_prologue_and_epilogue_insns):
> Removed.
> * df-problems.c (df_ru_get_bb_info, df_rd_get_bb_info,
> df_lr_get_bb_info, df_ur_get_bb_info, df_urec_get_bb_info): Added
> check.
> * Makefile.in (function.o): Added timevar.h.
>
>
Index: tree-pass.h
===================================================================
--- tree-pass.h (revision 112921)
+++ tree-pass.h (working copy)
@@ -377,7 +377,7 @@ extern struct tree_opt_pass pass_postrel
extern struct tree_opt_pass pass_gcse2;
extern struct tree_opt_pass pass_split_after_reload;
extern struct tree_opt_pass pass_branch_target_load_optimize1;
-extern struct tree_opt_pass pass_flow2;
+extern struct tree_opt_pass pass_thread_prologue_and_epilogue;
extern struct tree_opt_pass pass_stack_adjustments;
extern struct tree_opt_pass pass_peephole2;
extern struct tree_opt_pass pass_if_after_reload;
Index: final.c
===================================================================
--- final.c (revision 112855)
+++ final.c (working copy)
@@ -4021,7 +4021,6 @@ rest_of_clean_state (void)
reload_completed = 0;
epilogue_completed = 0;
- flow2_completed = 0;
no_new_pseudos = 0;
#ifdef STACK_REGS
regstack_completed = 0;
Index: flow.c
===================================================================
--- flow.c (revision 112855)
+++ flow.c (working copy)
@@ -174,9 +174,6 @@ Software Foundation, 51 Franklin Street,
#endif
#endif
-/* Nonzero if the second flow pass has completed. */
-int flow2_completed;
-
/* Maximum register number used in this function, plus one. */
int max_regno;
@@ -4165,44 +4162,3 @@ struct tree_opt_pass pass_life =
'f' /* letter */
};
-static unsigned int
-rest_of_handle_flow2 (void)
-{
-#if 0
- int i;
-#endif
- if (optimize)
- cleanup_cfg (CLEANUP_EXPENSIVE);
-#if 0
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- fprintf (stderr, "regs_ever_live[%d]=%d before prologue\n", i,
- regs_ever_live[i]);
-#endif
- /* On some machines, the prologue and epilogue code, or parts thereof,
- can be represented as RTL. Doing so lets us schedule insns between
- it and the rest of the code and also allows delayed branch
- scheduling to operate in the epilogue. */
- thread_prologue_and_epilogue_insns (get_insns ());
- epilogue_completed = 1;
- flow2_completed = 1;
- return 0;
-}
-
-struct tree_opt_pass pass_flow2 =
-{
- "flow2", /* name */
- NULL, /* gate */
- rest_of_handle_flow2, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_FLOW2, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- TODO_verify_flow, /* todo_flags_start */
- TODO_dump_func |
- TODO_ggc_collect, /* todo_flags_finish */
- 'w' /* letter */
-};
-
Index: timevar.def
===================================================================
--- timevar.def (revision 112855)
+++ timevar.def (working copy)
@@ -156,7 +156,7 @@ DEFTIMEVAR (TV_GLOBAL_ALLOC , "
DEFTIMEVAR (TV_RELOAD_CSE_REGS , "reload CSE regs")
DEFTIMEVAR (TV_SEQABSTR , "sequence abstraction")
DEFTIMEVAR (TV_GCSE_AFTER_RELOAD , "load CSE after reload")
-DEFTIMEVAR (TV_FLOW2 , "flow 2")
+DEFTIMEVAR (TV_THREAD_PROLOGUE_AND_EPILOGUE, "thread prologue and epilogue")
DEFTIMEVAR (TV_IFCVT2 , "if-conversion 2")
DEFTIMEVAR (TV_PEEPHOLE2 , "peephole 2")
DEFTIMEVAR (TV_RENAME_REGISTERS , "rename registers")
Index: function.c
===================================================================
--- function.c (revision 112855)
+++ function.c (working copy)
@@ -64,6 +64,7 @@ Software Foundation, 51 Franklin Street,
#include "tree-pass.h"
#include "predict.h"
#include "df.h"
+#include "timevar.h"
#ifndef LOCAL_ALIGNMENT
#define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
@@ -210,7 +212,7 @@ static int contains (rtx, VEC(int,heap)
static void emit_return_into_block (basic_block, rtx);
#endif
#if defined(HAVE_epilogue) && defined(INCOMING_RETURN_ADDR_RTX)
-static rtx keep_stack_depressed (rtx);
+static rtx keep_stack_depressed (struct df *, rtx);
#endif
static void prepare_function_start (tree);
static void do_clobber_return_reg (rtx, void *);
@@ -4763,7 +4765,7 @@ static void emit_equiv_load (struct epi_
no modifications to the stack pointer. Return the new list of insns. */
static rtx
-keep_stack_depressed (rtx insns)
+keep_stack_depressed (struct df *df, rtx insns)
{
int j;
struct epi_info info;
@@ -4880,7 +4882,7 @@ keep_stack_depressed (rtx insns)
&& !fixed_regs[regno]
&& TEST_HARD_REG_BIT (regs_invalidated_by_call, regno)
&& !REGNO_REG_SET_P
- (DF_LIVE_IN (rtl_df, EXIT_BLOCK_PTR), regno)
+ (DF_UPWARD_LIVE_IN (df, EXIT_BLOCK_PTR), regno)
&& !refers_to_regno_p (regno,
regno + hard_regno_nregs[regno]
[Pmode],
@@ -5092,8 +5094,8 @@ emit_equiv_load (struct epi_info *p)
this into place with notes indicating where the prologue ends and where
the epilogue begins. Update the basic block information when possible. */
-void
-thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED)
+static void
+thread_prologue_and_epilogue_insns (void)
{
int inserted = 0;
edge e;
@@ -5107,6 +5109,20 @@ thread_prologue_and_epilogue_insns (rtx
rtx epilogue_end = NULL_RTX;
#endif
edge_iterator ei;
+ struct df * df = df_init (DF_HARD_REGS);
+
+ /* Do not even think about running dce here!!!! All life, as we
+ know it will cease!!! There is dead code created by the previous
+ call to split_all_insns that is resurrected by the prologue and
+ epilogue. This does not appear to be a bug in dce. On the
+ x86-64 this shows up as failues in g++ excepion handling and is
+ extremely difficult to debug because the problem is with the way
+ that that the g++ library is compiled and this library was not
+ designed for modular testing. All of the test cases that when
+ dce is added here fail in the gcc library, not in the test
+ case. */
+ df_lr_add_problem (df, 0);
+ df_analyze (df);
#ifdef HAVE_prologue
if (HAVE_prologue)
@@ -5275,7 +5291,7 @@ thread_prologue_and_epilogue_insns (rtx
it, massage the epilogue to actually do that. */
if (TREE_CODE (TREE_TYPE (current_function_decl)) == FUNCTION_TYPE
&& TYPE_RETURNS_STACK_DEPRESSED (TREE_TYPE (current_function_decl)))
- seq = keep_stack_depressed (seq);
+ seq = keep_stack_depressed (df, seq);
#endif
emit_jump_insn (seq);
@@ -5422,6 +5438,7 @@ epilogue_done:
}
}
#endif
+ df_finish (df);
}
/* Reposition the prologue-end and epilogue-begin notes after instruction
@@ -5607,5 +5624,38 @@ struct tree_opt_pass pass_leaf_regs =
0 /* letter */
};
+static unsigned int
+rest_of_handle_thread_prologue_and_epilogue (void)
+{
+ if (optimize)
+ cleanup_cfg (CLEANUP_EXPENSIVE);
+ /* On some machines, the prologue and epilogue code, or parts thereof,
+ can be represented as RTL. Doing so lets us schedule insns between
+ it and the rest of the code and also allows delayed branch
+ scheduling to operate in the epilogue. */
+
+ thread_prologue_and_epilogue_insns ();
+ epilogue_completed = 1;
+ return 0;
+}
+
+struct tree_opt_pass pass_thread_prologue_and_epilogue =
+{
+ "pro_and_epilogue", /* name */
+ NULL, /* gate */
+ rest_of_handle_thread_prologue_and_epilogue, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_THREAD_PROLOGUE_AND_EPILOGUE, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ TODO_verify_flow, /* todo_flags_start */
+ TODO_dump_func |
+ TODO_ggc_collect, /* todo_flags_finish */
+ 'w' /* letter */
+};
+
#include "gt-function.h"
Index: rtl.h
===================================================================
--- rtl.h (revision 112855)
+++ rtl.h (working copy)
@@ -1962,10 +1962,6 @@ extern rtx gen_rtx_MEM (enum machine_mod
extern rtx output_constant_def (tree, int);
extern rtx lookup_constant_def (tree);
-/* Nonzero after the second flow pass has completed.
- Set to 1 or 0 by toplev.c */
-extern int flow2_completed;
-
/* Nonzero after end of reload pass.
Set to 1 or 0 by reload1.c. */
@@ -1979,7 +1975,6 @@ extern int epilogue_completed;
extern int reload_in_progress;
-
#ifdef STACK_REGS
/* Nonzero after end of regstack pass.
Set to 1 or 0 by reg-stack.c. */
@@ -2124,7 +2119,6 @@ extern void init_loop (void);
/* In function.c */
extern void reposition_prologue_and_epilogue_notes (void);
-extern void thread_prologue_and_epilogue_insns (rtx);
extern int prologue_epilogue_contains (rtx);
extern int sibcall_epilogue_contains (rtx);
extern void mark_temp_addr_taken (rtx);
Index: df-problems.c
===================================================================
--- df-problems.c (revision 112855)
+++ df-problems.c (working copy)
@@ -301,6 +301,7 @@ struct df_ru_problem_data
struct df_ru_bb_info *
df_ru_get_bb_info (struct dataflow *dflow, unsigned int index)
{
+ gcc_assert (dflow);
return (struct df_ru_bb_info *) dflow->block_info[index];
}
@@ -833,6 +834,7 @@ struct df_rd_problem_data
struct df_rd_bb_info *
df_rd_get_bb_info (struct dataflow *dflow, unsigned int index)
{
+ gcc_assert (dflow);
return (struct df_rd_bb_info *) dflow->block_info[index];
}
@@ -1334,6 +1336,7 @@ df_rd_add_problem (struct df *df, int fl
struct df_lr_bb_info *
df_lr_get_bb_info (struct dataflow *dflow, unsigned int index)
{
+ gcc_assert (dflow);
return (struct df_lr_bb_info *) dflow->block_info[index];
}
@@ -1855,6 +1858,7 @@ df_lr_add_problem (struct df *df, int fl
struct df_ur_bb_info *
df_ur_get_bb_info (struct dataflow *dflow, unsigned int index)
{
+ gcc_assert (dflow);
return (struct df_ur_bb_info *) dflow->block_info[index];
}
@@ -2221,6 +2225,7 @@ struct df_urec_problem_data
struct df_urec_bb_info *
df_urec_get_bb_info (struct dataflow *dflow, unsigned int index)
{
+ gcc_assert (dflow);
return (struct df_urec_bb_info *) dflow->block_info[index];
}
Index: Makefile.in
===================================================================
--- Makefile.in (revision 112855)
+++ Makefile.in (working copy)
@@ -2166,7 +2166,7 @@ function.o : function.c $(CONFIG_H) $(SY
$(OPTABS_H) libfuncs.h $(REGS_H) hard-reg-set.h insn-config.h $(RECOG_H) \
output.h toplev.h except.h $(HASHTAB_H) $(GGC_H) $(TM_P_H) langhooks.h \
gt-function.h $(TARGET_H) $(BASIC_BLOCK_H) $(INTEGRATE_H) $(PREDICT_H) \
- tree-pass.h $(DF_H)
+ tree-pass.h $(DF_H) timevar.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 $(RECOG_H) toplev.h output.h $(GGC_H) $(TM_P_H) \
Index: passes.c
===================================================================
--- passes.c (revision 112921)
+++ passes.c (working copy)
@@ -675,7 +675,7 @@ init_optimization_passes (void)
NEXT_PASS (pass_rtl_dse);
NEXT_PASS (pass_split_after_reload);
NEXT_PASS (pass_branch_target_load_optimize1);
- NEXT_PASS (pass_flow2);
+ NEXT_PASS (pass_thread_prologue_and_epilogue);
NEXT_PASS (pass_clear_df);
NEXT_PASS (pass_rtl_seqabstr);
NEXT_PASS (pass_stack_adjustments);
Index: config/i386/i386.md
===================================================================
--- config/i386/i386.md (revision 112855)
+++ config/i386/i386.md (working copy)
@@ -1867,7 +1867,7 @@ (define_split
[(set (match_operand:DI 0 "push_operand" "")
(match_operand:DI 1 "immediate_operand" ""))]
"TARGET_64BIT && ((optimize > 0 && flag_peephole2)
- ? flow2_completed : reload_completed)
+ ? epilogue_completed : reload_completed)
&& !symbolic_operand (operands[1], DImode)
&& !x86_64_immediate_operand (operands[1], DImode)"
[(set (match_dup 0) (match_dup 1))
@@ -2097,7 +2097,7 @@ (define_split
[(set (match_operand:DI 0 "memory_operand" "")
(match_operand:DI 1 "immediate_operand" ""))]
"TARGET_64BIT && ((optimize > 0 && flag_peephole2)
- ? flow2_completed : reload_completed)
+ ? epilogue_completed : reload_completed)
&& !symbolic_operand (operands[1], DImode)
&& !x86_64_immediate_operand (operands[1], DImode)"
[(set (match_dup 2) (match_dup 3))
@@ -10453,7 +10453,7 @@ (define_split
(match_operand:QI 2 "nonmemory_operand" "")))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && ((optimize > 0 && flag_peephole2)
- ? flow2_completed : reload_completed)"
+ ? epilogue_completed : reload_completed)"
[(const_int 0)]
"ix86_split_ashl (operands, NULL_RTX, DImode); DONE;")
@@ -11208,7 +11208,7 @@ (define_split
(match_operand:QI 2 "nonmemory_operand" "")))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && ((optimize > 0 && flag_peephole2)
- ? flow2_completed : reload_completed)"
+ ? epilogue_completed : reload_completed)"
[(const_int 0)]
"ix86_split_ashr (operands, NULL_RTX, DImode); DONE;")
@@ -11743,7 +11743,7 @@ (define_split
(match_operand:QI 2 "nonmemory_operand" "")))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && ((optimize > 0 && flag_peephole2)
- ? flow2_completed : reload_completed)"
+ ? epilogue_completed : reload_completed)"
[(const_int 0)]
"ix86_split_lshr (operands, NULL_RTX, DImode); DONE;")
Index: config/sh/sh.md
===================================================================
--- config/sh/sh.md (revision 112855)
+++ config/sh/sh.md (working copy)
@@ -9897,7 +9897,7 @@ (define_split
[(set (reg:PSI FPSCR_REG)
(mem:PSI (match_operand:SI 0 "register_operand" "")))]
"(TARGET_SH4 || TARGET_SH2A_DOUBLE)
- && (flag_peephole2 ? flow2_completed : reload_completed)"
+ && (flag_peephole2 ? epilogue_completed : reload_completed)"
[(const_int 0)]
{
rtx fpscr, mem, new_insn;
Index: config/mips/mips.md
===================================================================
--- config/mips/mips.md (revision 112855)
+++ config/mips/mips.md (working copy)
@@ -3026,7 +3026,7 @@ (define_insn_and_split "*lea_high64"
(high:DI (match_operand:DI 1 "general_symbolic_operand" "")))]
"TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS"
"#"
- "&& flow2_completed"
+ "&& epilogue_completed"
[(set (match_dup 0) (high:DI (match_dup 2)))
(set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 2)))
(set (match_dup 0) (ashift:DI (match_dup 0) (const_int 16)))
Index: config/h8300/h8300.md
===================================================================
--- config/h8300/h8300.md (revision 112855)
+++ config/h8300/h8300.md (working copy)
@@ -1210,7 +1210,7 @@ (define_split
[(set (match_operand:HI 0 "stack_pointer_operand" "")
(plus:HI (match_dup 0)
(match_operand 1 "const_int_gt_2_operand" "")))]
- "TARGET_H8300 && flow2_completed"
+ "TARGET_H8300 && epilogue_completed"
[(const_int 0)]
"split_adds_subs (HImode, operands); DONE;")
@@ -3017,7 +3017,7 @@ (define_split
[(match_dup 0)
(match_operand:QI 1 "register_operand" "")]))
(clobber (match_operand:QI 3 "register_operand" ""))]
- "flow2_completed
+ "epilogue_completed
&& find_regno_note (insn, REG_DEAD, REGNO (operands[1]))"
[(set (cc0)
(match_dup 1))
@@ -3048,7 +3048,7 @@ (define_split
[(match_dup 0)
(match_operand:QI 1 "register_operand" "")]))
(clobber (match_operand:QI 3 "register_operand" ""))]
- "flow2_completed
+ "epilogue_completed
&& !find_regno_note (insn, REG_DEAD, REGNO (operands[1]))"
[(set (match_dup 3)
(match_dup 1))
@@ -4183,7 +4183,7 @@ (define_split
(match_dup 0)))
(clobber (match_operand:SI 2 "register_operand" ""))]
"(TARGET_H8300H || TARGET_H8300S)
- && flow2_completed
+ && epilogue_completed
&& find_regno_note (insn, REG_DEAD, REGNO (operands[1]))
&& REGNO (operands[0]) != REGNO (operands[1])"
[(parallel [(set (match_dup 3)
@@ -4203,7 +4203,7 @@ (define_split
(match_dup 0)))
(clobber (match_operand:SI 2 "register_operand" ""))]
"(TARGET_H8300H || TARGET_H8300S)
- && flow2_completed
+ && epilogue_completed
&& !(find_regno_note (insn, REG_DEAD, REGNO (operands[1]))
&& REGNO (operands[0]) != REGNO (operands[1]))"
[(set (match_dup 2)
@@ -4286,7 +4286,7 @@ (define_split
(match_dup 0)))
(clobber (match_operand:SI 2 "register_operand" ""))]
"(TARGET_H8300H || TARGET_H8300S)
- && flow2_completed
+ && epilogue_completed
&& find_regno_note (insn, REG_DEAD, REGNO (operands[1]))
&& REGNO (operands[0]) != REGNO (operands[1])"
[(parallel [(set (match_dup 3)
@@ -4306,7 +4306,7 @@ (define_split
(match_dup 0)))
(clobber (match_operand:SI 2 "register_operand" ""))]
"(TARGET_H8300H || TARGET_H8300S)
- && flow2_completed
+ && epilogue_completed
&& !(find_regno_note (insn, REG_DEAD, REGNO (operands[1]))
&& REGNO (operands[0]) != REGNO (operands[1]))"
[(set (match_dup 2)