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]
Other format: [Raw text]

[patch] for PR 28888


Hello,

if conversion leaves edges after non-control statements marked with
EDGE_TRUE/FALSE_VALUE, which confuses simplify_using_initial_conditions
and causes this ICE.  The code in combine_blocks that is responsible for
the cfg manipulations during if conversion turned out to be a bit
strange  (checking for things like loop latch having an exit, which
cannot happen since we require that loop latch has only one successor;
and possibly generating wrong cfg in some cases); hence, I have
rewritten it almost completely in the progress of fixing the bug.

Bootstrapped & regtested on x86_64.

Zdenek

	PR tree-optimization/28888
	* tree-if-conv.c (combine_blocks): Rewritten.
	* tree-cfg.c (tree_verify_flow_info): Check that edges with
	EDGE_TRUE/FALSE_VALUE follow COND_EXPR.

Index: tree-if-conv.c
===================================================================
*** tree-if-conv.c	(revision 116570)
--- tree-if-conv.c	(working copy)
*************** combine_blocks (struct loop *loop)
*** 863,933 ****
    basic_block bb, exit_bb, merge_target_bb;
    unsigned int orig_loop_num_nodes = loop->num_nodes;
    unsigned int i;
!   unsigned int n_exits;
!   edge *exits;
  
-   exits = get_loop_exit_edges (loop, &n_exits);
-   free (exits);
    /* Process phi nodes to prepare blocks for merge.  */
    process_phi_nodes (loop);
  
    exit_bb = NULL;
  
-   /* Merge basic blocks */
-   merge_target_bb = loop->header;
    for (i = 1; i < orig_loop_num_nodes; i++)
      {
-       edge e;
-       block_stmt_iterator bsi;
-       tree_stmt_iterator last;
- 
        bb = ifc_bbs[i];
  
!       if (!exit_bb && bb_with_exit_edge_p (loop, bb))
! 	  exit_bb = bb;
! 
!       if (bb == exit_bb)
  	{
! 	  edge_iterator ei;
  
  	  /* Connect this node with loop header.  */
! 	  make_edge (ifc_bbs[0], bb, EDGE_FALLTHRU);
! 	  set_immediate_dominator (CDI_DOMINATORS, bb, ifc_bbs[0]);
  
! 	  if (exit_bb != loop->latch)
! 	    {
! 	      /* Redirect non-exit edge to loop->latch.  */
! 	      FOR_EACH_EDGE (e, ei, bb->succs)
! 		{
! 		  if (!loop_exit_edge_p (loop, e))
! 		    {
! 		      redirect_edge_and_branch (e, loop->latch);
! 		      set_immediate_dominator (CDI_DOMINATORS, loop->latch, bb);
! 		    }
! 		}
! 	    }
! 	  continue;
  	}
  
!       if (bb == loop->latch && empty_block_p (bb))
! 	continue;
  
!       /* It is time to remove this basic block.	 First remove edges.  */
!       while (EDGE_COUNT (bb->preds) > 0)
! 	remove_edge (EDGE_PRED (bb, 0));
! 
!       /* This is loop latch and loop does not have exit then do not
!  	 delete this basic block. Just remove its PREDS and reconnect 
!  	 loop->header and loop->latch blocks.  */
!       if (bb == loop->latch && n_exits == 0)
!  	{
!  	  make_edge (loop->header, loop->latch, EDGE_FALLTHRU);
!  	  set_immediate_dominator (CDI_DOMINATORS, loop->latch, loop->header);
! 	  continue;
!  	}
  
!       while (EDGE_COUNT (bb->succs) > 0)
! 	remove_edge (EDGE_SUCC (bb, 0));
  
        /* Remove labels and make stmts member of loop->header.  */
        for (bsi = bsi_start (bb); !bsi_end_p (bsi); )
--- 863,935 ----
    basic_block bb, exit_bb, merge_target_bb;
    unsigned int orig_loop_num_nodes = loop->num_nodes;
    unsigned int i;
!   edge e;
!   edge_iterator ei;
  
    /* Process phi nodes to prepare blocks for merge.  */
    process_phi_nodes (loop);
  
+   /* Merge basic blocks.  First remove all the edges in the loop, except
+      for those from the exit block.  */
    exit_bb = NULL;
+   for (i = 0; i < orig_loop_num_nodes; i++)
+     {
+       bb = ifc_bbs[i];
+       if (bb_with_exit_edge_p (loop, bb))
+ 	{
+ 	  exit_bb = bb;
+ 	  break;
+ 	}
+     }
+   gcc_assert (exit_bb != loop->latch);
  
    for (i = 1; i < orig_loop_num_nodes; i++)
      {
        bb = ifc_bbs[i];
  
!       for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei));)
  	{
! 	  if (e->src == exit_bb)
! 	    ei_next (&ei);
! 	  else
! 	    remove_edge (e);
! 	}
!     }
  
+   if (exit_bb != NULL)
+     {
+       if (exit_bb != loop->header)
+ 	{
  	  /* Connect this node with loop header.  */
! 	  make_edge (loop->header, exit_bb, EDGE_FALLTHRU);
! 	  set_immediate_dominator (CDI_DOMINATORS, exit_bb, loop->header);
! 	}
  
!       /* Redirect non-exit edges to loop->latch.  */
!       FOR_EACH_EDGE (e, ei, exit_bb->succs)
! 	{
! 	  if (!loop_exit_edge_p (loop, e))
! 	    redirect_edge_and_branch (e, loop->latch);
  	}
+       set_immediate_dominator (CDI_DOMINATORS, loop->latch, exit_bb);
+     }
+   else
+     {
+       /* If the loop does not have exit then reconnect header and latch.  */
+       make_edge (loop->header, loop->latch, EDGE_FALLTHRU);
+       set_immediate_dominator (CDI_DOMINATORS, loop->latch, loop->header);
+     }
  
!   merge_target_bb = loop->header;
!   for (i = 1; i < orig_loop_num_nodes; i++)
!     {
!       block_stmt_iterator bsi;
!       tree_stmt_iterator last;
  
!       bb = ifc_bbs[i];
  
!       if (bb == exit_bb || bb == loop->latch)
! 	continue;
  
        /* Remove labels and make stmts member of loop->header.  */
        for (bsi = bsi_start (bb); !bsi_end_p (bsi); )
*************** combine_blocks (struct loop *loop)
*** 953,960 ****
  	delete_from_dominance_info (CDI_POST_DOMINATORS, bb);
  
        /* Remove basic block.  */
-       if (bb == loop->latch)
- 	loop->latch = merge_target_bb;
        remove_bb_from_loops (bb);
        expunge_block (bb);
      }
--- 955,960 ----
*************** combine_blocks (struct loop *loop)
*** 963,977 ****
       This reduces number of basic blocks to 2. Auto vectorizer addresses
       loops with two nodes only.  FIXME: Use cleanup_tree_cfg().  */
    if (exit_bb
!       && loop->header != loop->latch
!       && exit_bb != loop->latch 
!       && empty_block_p (loop->latch))
      {
!       if (can_merge_blocks_p (loop->header, exit_bb))
! 	{
! 	  remove_bb_from_loops (exit_bb);
! 	  merge_blocks (loop->header, exit_bb);
! 	}
      }
  }
  
--- 963,973 ----
       This reduces number of basic blocks to 2. Auto vectorizer addresses
       loops with two nodes only.  FIXME: Use cleanup_tree_cfg().  */
    if (exit_bb
!       && exit_bb != loop->header
!       && can_merge_blocks_p (loop->header, exit_bb))
      {
!       remove_bb_from_loops (exit_bb);
!       merge_blocks (loop->header, exit_bb);
      }
  }
  
Index: tree-cfg.c
===================================================================
*** tree-cfg.c	(revision 116570)
--- tree-cfg.c	(working copy)
*************** tree_verify_flow_info (void)
*** 3757,3762 ****
--- 3757,3775 ----
  	      }
  	}
  
+       if (TREE_CODE (stmt) != COND_EXPR)
+ 	{
+ 	  /* Verify that there are no edges with EDGE_TRUE/FALSE_FLAG set
+ 	     after anything else but if statement.  */
+ 	  FOR_EACH_EDGE (e, ei, bb->succs)
+ 	    if (e->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE))
+ 	      {
+ 		error ("true/false edge after a non-COND_EXPR in bb %d",
+ 		       bb->index);
+ 		err = 1;
+ 	      }
+ 	}
+ 
        switch (TREE_CODE (stmt))
  	{
  	case COND_EXPR:


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