This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

fix flow1.c ppc failure


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)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]