This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
fix flow1.c ppc failure
- To: gcc-patches at gcc dot gnu dot org, rth at cygnus dot com
- Subject: fix flow1.c ppc failure
- From: Jan Hubicka <jh at suse dot cz>
- Date: Wed, 18 Jul 2001 21:06:05 +0200
Hi,
The flow1.c on ppc/-O2 -fPIC causes compiler crash (mainline+branch). Problem
is that ifcvt manages to create an fallthru edge over ADDR_VEC insn, that shows
as crash several passes later.
Nice way to fix this is to make ifcvt use the BB manipulation infrasturucture
I've made for cfg. It simplifies it, makes case_1 to match more often,
preserves the probability and counts.
Later I would like to provide infrastructure for inverting branches, as
dead_or_predictable, but I want to take my time on this. Updating of
probability infonformation is touchy task, as it can't be done at lowlevel
functions and needs to be distributed somehow and I would love to do that
in as robust was as possible.
For 3.0 branch we need different solution. What about importing can_fallthru
and replacing the index+1 == other_index test by it?
Regtested i586, bootstrap/regtesting of i686 in progress.
Honza
Wed Jul 18 19:39:00 CEST 2001 Jan Hubicka <jh@suse.cz>
* basic-block.h (redirect_edge_and_branch_force,
redirect_edge_and_branch, block_label, forwarder_block_p): Declare.
* flow.c (redirect_edge_and_branch_force,
redirect_edge_and_branch, block_label, forwarder_block_p): Make global.
(redirect_edge_and_branch_force): Fix copying of lifeness information.
(block_label): Handle EXIT_BLOCK_PTR by returning NULL.
* ifcvt.c (dead_or_predictable): Take BB as an new destionation
instead of label; update CFG after transformation.
(find_if_case_1): Update call, use redirect_edge_and_branch_force
for finishing the transformation; handle even case where ELSE
does not follow THEN.
(find_if_case_2): Update call of dead_or_predictable; simplify
CFG update.
Index: basic-block.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/basic-block.h,v
retrieving revision 1.102
diff -c -3 -p -r1.102 basic-block.h
*** basic-block.h 2001/07/16 20:54:42 1.102
--- basic-block.h 2001/07/18 19:00:50
*************** extern void debug_regset PARAMS ((regse
*** 597,602 ****
--- 597,607 ----
extern void allocate_reg_life_data PARAMS ((void));
extern void allocate_bb_life_data PARAMS ((void));
extern void find_unreachable_blocks PARAMS ((void));
+ extern basic_block redirect_edge_and_branch_force PARAMS ((edge, basic_block));
+ extern bool redirect_edge_and_branch PARAMS ((edge, basic_block));
+ extern rtx block_label PARAMS ((basic_block));
+ extern bool forwarder_block_p PARAMS ((basic_block));
+
/* This function is always defined so it can be called from the
debugger, and it is declared extern so we don't get warnings about
Index: flow.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/flow.c,v
retrieving revision 1.430
diff -c -3 -p -r1.430 flow.c
*** flow.c 2001/07/18 17:11:10 1.430
--- flow.c 2001/07/18 19:00:53
*************** static int merge_blocks_move_successor_n
*** 393,399 ****
static int merge_blocks PARAMS ((edge,basic_block,basic_block,
int));
static bool try_optimize_cfg PARAMS ((int));
- static bool forwarder_block_p PARAMS ((basic_block));
static bool can_fallthru PARAMS ((basic_block, basic_block));
static bool try_redirect_by_replacing_jump PARAMS ((edge, basic_block));
static bool try_simplify_condjump PARAMS ((basic_block));
--- 393,398 ----
*************** static void flow_loops_tree_build PARAMS
*** 485,493 ****
static int flow_loop_level_compute PARAMS ((struct loop *, int));
static int flow_loops_level_compute PARAMS ((struct loops *));
static void find_sub_basic_blocks PARAMS ((basic_block));
- static bool redirect_edge_and_branch PARAMS ((edge, basic_block));
- static basic_block redirect_edge_and_branch_force PARAMS ((edge, basic_block));
- static rtx block_label PARAMS ((basic_block));
/* Find basic blocks of the current function.
F is the first insn of the function and NREGS the number of register
--- 484,489 ----
*************** split_block (bb, insn)
*** 1598,1607 ****
}
/* Return label in the head of basic block. Create one if it doesn't exist. */
! static rtx
block_label (block)
basic_block block;
{
if (GET_CODE (block->head) != CODE_LABEL)
block->head = emit_label_before (gen_label_rtx (), block->head);
return block->head;
--- 1594,1605 ----
}
/* Return label in the head of basic block. Create one if it doesn't exist. */
! rtx
block_label (block)
basic_block block;
{
+ if (block == EXIT_BLOCK_PTR)
+ return NULL_RTX;
if (GET_CODE (block->head) != CODE_LABEL)
block->head = emit_label_before (gen_label_rtx (), block->head);
return block->head;
*************** block_label (block)
*** 1609,1615 ****
/* Return true if the block has no effect and only forwards control flow to
its single destination. */
! static bool
forwarder_block_p (bb)
basic_block bb;
{
--- 1607,1613 ----
/* Return true if the block has no effect and only forwards control flow to
its single destination. */
! bool
forwarder_block_p (bb)
basic_block bb;
{
*************** try_redirect_by_replacing_jump (e, targe
*** 1767,1773 ****
Return true if transformation suceeded. We still return flase in case
E already destinated TARGET and we didn't managed to simplify instruction
stream. */
! static bool
redirect_edge_and_branch (e, target)
edge e;
basic_block target;
--- 1765,1771 ----
Return true if transformation suceeded. We still return flase in case
E already destinated TARGET and we didn't managed to simplify instruction
stream. */
! bool
redirect_edge_and_branch (e, target)
edge e;
basic_block target;
*************** redirect_edge_and_branch (e, target)
*** 1875,1881 ****
/* Redirect edge even at the expense of creating new jump insn or
basic block. Return new basic block if created, NULL otherwise.
Abort if converison is impossible. */
! static basic_block
redirect_edge_and_branch_force (e, target)
edge e;
basic_block target;
--- 1873,1879 ----
/* Redirect edge even at the expense of creating new jump insn or
basic block. Return new basic block if created, NULL otherwise.
Abort if converison is impossible. */
! basic_block
redirect_edge_and_branch_force (e, target)
edge e;
basic_block target;
*************** redirect_edge_and_branch_force (e, targe
*** 1945,1951 ****
new_bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
new_bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
COPY_REG_SET (new_bb->global_live_at_start,
! e->dest->global_live_at_start);
COPY_REG_SET (new_bb->global_live_at_end, new_bb->global_live_at_start);
}
--- 1943,1949 ----
new_bb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
new_bb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
COPY_REG_SET (new_bb->global_live_at_start,
! target->global_live_at_start);
COPY_REG_SET (new_bb->global_live_at_end, new_bb->global_live_at_start);
}
Index: ifcvt.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/ifcvt.c,v
retrieving revision 1.55
diff -c -3 -p -r1.55 ifcvt.c
*** ifcvt.c 2001/07/15 00:00:56 1.55
--- ifcvt.c 2001/07/18 19:00:57
*************** static int find_if_case_2 PARAMS ((basi
*** 106,112 ****
static int find_cond_trap PARAMS ((basic_block, edge, edge));
static int find_memory PARAMS ((rtx *, void *));
static int dead_or_predicable PARAMS ((basic_block, basic_block,
! basic_block, rtx, int));
static void noce_emit_move_insn PARAMS ((rtx, rtx));
/* Abuse the basic_block AUX field to store the original block index,
--- 106,112 ----
static int find_cond_trap PARAMS ((basic_block, edge, edge));
static int find_memory PARAMS ((rtx *, void *));
static int dead_or_predicable PARAMS ((basic_block, basic_block,
! basic_block, basic_block, int));
static void noce_emit_move_insn PARAMS ((rtx, rtx));
/* Abuse the basic_block AUX field to store the original block index,
*************** find_if_case_1 (test_bb, then_edge, else
*** 2181,2189 ****
edge then_edge, else_edge;
{
basic_block then_bb = then_edge->dest;
! basic_block else_bb = else_edge->dest;
edge then_succ = then_bb->succ;
- rtx new_lab;
/* THEN has one successor. */
if (!then_succ || then_succ->succ_next != NULL)
--- 2181,2188 ----
edge then_edge, else_edge;
{
basic_block then_bb = then_edge->dest;
! basic_block else_bb = else_edge->dest, new_bb;
edge then_succ = then_bb->succ;
/* THEN has one successor. */
if (!then_succ || then_succ->succ_next != NULL)
*************** find_if_case_1 (test_bb, then_edge, else
*** 2197,2204 ****
if (then_bb->pred->pred_next != NULL)
return FALSE;
! /* ELSE follows THEN. (??? could be moved) */
! if (else_bb->index != then_bb->index + 1)
return FALSE;
num_possible_if_blocks++;
--- 2196,2203 ----
if (then_bb->pred->pred_next != NULL)
return FALSE;
! /* THEN must do something. */
! if (forwarder_block_p (then_bb))
return FALSE;
num_possible_if_blocks++;
*************** find_if_case_1 (test_bb, then_edge, else
*** 2211,2228 ****
if (count_bb_insns (then_bb) > BRANCH_COST)
return FALSE;
- /* Find the label for THEN's destination. */
- if (then_succ->dest == EXIT_BLOCK_PTR)
- new_lab = NULL_RTX;
- else
- {
- new_lab = JUMP_LABEL (then_bb->end);
- if (! new_lab)
- abort ();
- }
-
/* Registers set are dead, or are predicable. */
! if (! dead_or_predicable (test_bb, then_bb, else_bb, new_lab, 1))
return FALSE;
/* Conversion went ok, including moving the insns and fixing up the
--- 2210,2218 ----
if (count_bb_insns (then_bb) > BRANCH_COST)
return FALSE;
/* Registers set are dead, or are predicable. */
! if (! dead_or_predicable (test_bb, then_bb, else_bb,
! then_bb->succ->dest, 1))
return FALSE;
/* Conversion went ok, including moving the insns and fixing up the
*************** find_if_case_1 (test_bb, then_edge, else
*** 2233,2241 ****
else_bb->global_live_at_start,
then_bb->global_live_at_end, BITMAP_IOR);
! make_edge (NULL, test_bb, then_succ->dest, 0);
flow_delete_block (then_bb);
! tidy_fallthru_edge (else_edge, test_bb, else_bb);
num_removed_blocks++;
num_updated_if_blocks++;
--- 2223,2239 ----
else_bb->global_live_at_start,
then_bb->global_live_at_end, BITMAP_IOR);
! new_bb = redirect_edge_and_branch_force (FALLTHRU_EDGE (test_bb), else_bb);
! /* Make rest of code believe that the newly created block is the THEN_BB
! block we are going to remove. */
! if (new_bb)
! {
! new_bb->aux = then_bb;
! SET_UPDATE_LIFE (then_bb);
! }
flow_delete_block (then_bb);
! /* We've possibly created jump to next insn, cleanup_cfg will solve that
! later. */
num_removed_blocks++;
num_updated_if_blocks++;
*************** find_if_case_2 (test_bb, then_edge, else
*** 2253,2259 ****
basic_block then_bb = then_edge->dest;
basic_block else_bb = else_edge->dest;
edge else_succ = else_bb->succ;
! rtx new_lab, note;
/* ELSE has one successor. */
if (!else_succ || else_succ->succ_next != NULL)
--- 2251,2257 ----
basic_block then_bb = then_edge->dest;
basic_block else_bb = else_edge->dest;
edge else_succ = else_bb->succ;
! rtx note;
/* ELSE has one successor. */
if (!else_succ || else_succ->succ_next != NULL)
*************** find_if_case_2 (test_bb, then_edge, else
*** 2292,2318 ****
if (count_bb_insns (then_bb) > BRANCH_COST)
return FALSE;
- /* Find the label for ELSE's destination. */
- if (else_succ->dest == EXIT_BLOCK_PTR)
- new_lab = NULL_RTX;
- else
- {
- if (else_succ->flags & EDGE_FALLTHRU)
- {
- new_lab = else_succ->dest->head;
- if (GET_CODE (new_lab) != CODE_LABEL)
- abort ();
- }
- else
- {
- new_lab = JUMP_LABEL (else_bb->end);
- if (! new_lab)
- abort ();
- }
- }
-
/* Registers set are dead, or are predicable. */
! if (! dead_or_predicable (test_bb, else_bb, then_bb, new_lab, 0))
return FALSE;
/* Conversion went ok, including moving the insns and fixing up the
--- 2290,2297 ----
if (count_bb_insns (then_bb) > BRANCH_COST)
return FALSE;
/* Registers set are dead, or are predicable. */
! if (! dead_or_predicable (test_bb, else_bb, then_bb, else_succ->dest, 0))
return FALSE;
/* Conversion went ok, including moving the insns and fixing up the
*************** find_if_case_2 (test_bb, then_edge, else
*** 2323,2330 ****
then_bb->global_live_at_start,
else_bb->global_live_at_end, BITMAP_IOR);
- remove_edge (else_edge);
- make_edge (NULL, test_bb, else_succ->dest, 0);
flow_delete_block (else_bb);
num_removed_blocks++;
--- 2302,2307 ----
*************** find_memory (px, data)
*** 2358,2367 ****
static int
dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
basic_block test_bb, merge_bb, other_bb;
! rtx new_dest;
int reversep;
{
! rtx head, end, jump, earliest, old_dest;
jump = test_bb->end;
--- 2335,2344 ----
static int
dead_or_predicable (test_bb, merge_bb, other_bb, new_dest, reversep)
basic_block test_bb, merge_bb, other_bb;
! basic_block new_dest;
int reversep;
{
! rtx head, end, jump, earliest, old_dest, new_label;
jump = test_bb->end;
*************** dead_or_predicable (test_bb, merge_bb, o
*** 2546,2554 ****
change group management. */
old_dest = JUMP_LABEL (jump);
if (reversep
! ? ! invert_jump_1 (jump, new_dest)
! : ! redirect_jump_1 (jump, new_dest))
goto cancel;
if (! apply_change_group ())
--- 2523,2532 ----
change group management. */
old_dest = JUMP_LABEL (jump);
+ new_label = block_label (new_dest);
if (reversep
! ? ! invert_jump_1 (jump, new_label)
! : ! redirect_jump_1 (jump, new_label))
goto cancel;
if (! apply_change_group ())
*************** dead_or_predicable (test_bb, merge_bb, o
*** 2556,2567 ****
if (old_dest)
LABEL_NUSES (old_dest) -= 1;
! if (new_dest)
! LABEL_NUSES (new_dest) += 1;
! JUMP_LABEL (jump) = new_dest;
if (reversep)
invert_br_probabilities (jump);
/* Move the insns out of MERGE_BB to before the branch. */
if (head != NULL)
--- 2534,2557 ----
if (old_dest)
LABEL_NUSES (old_dest) -= 1;
! if (new_label)
! LABEL_NUSES (new_label) += 1;
! JUMP_LABEL (jump) = new_label;
if (reversep)
invert_br_probabilities (jump);
+
+ redirect_edge_succ (BRANCH_EDGE (test_bb), new_dest);
+ if (reversep)
+ {
+ gcov_type count, probability;
+ count = BRANCH_EDGE (test_bb)->count;
+ BRANCH_EDGE (test_bb)->count = FALLTHRU_EDGE (test_bb)->count;
+ FALLTHRU_EDGE (test_bb)->count = count;
+ probability = BRANCH_EDGE (test_bb)->probability;
+ BRANCH_EDGE (test_bb)->probability = FALLTHRU_EDGE (test_bb)->probability;
+ FALLTHRU_EDGE (test_bb)->probability = probability;
+ }
/* Move the insns out of MERGE_BB to before the branch. */
if (head != NULL)