[tree-ssa] Insert on edge fix

Andrew MacLeod amacleod@redhat.com
Fri Jun 20 13:48:00 GMT 2003


On Fri, 2003-06-20 at 08:56, Jeff Sturm wrote:
> On Fri, 20 Jun 2003 law@redhat.com wrote:
> > I haven't looked into your problem, but it might be worth picking up
> > my fix to tree-cfg.c from earlier tonight and see if it fixes your
> > problem.  It was clearly doing the wrong thing in its handling of switch
> > statements.
>
Sorry, I was off yesterday and again today, so Im not on top of these
things.  My changes to handle_switch_split were suppose to make it
simpler rather than function changes. Clearly it needs a little more
examination, and I dont have time right now. Try reverting the changes
to just that function and see if that fixes your problem.

Patch attached.  Let me know. No testing on this yet, but it shouls be a
simple revert... :-)

Andrew


	* tree-cfg.c (handle_switch_split):  Revert last change.


Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.111
diff -c -p -r1.1.4.111 tree-cfg.c
*** tree-cfg.c	18 Jun 2003 16:50:24 -0000	1.1.4.111
--- tree-cfg.c	20 Jun 2003 13:14:58 -0000
*************** handle_switch_fallthru (tree sw_stmt, ba
*** 3676,3683 ****
    return tsi_container (tsi);
  }
  
  /* Arrange for a place to insert a stmt when we are splitting a block which is
!    targeted by a switch stmt.  Return the container which is used to build
     a TSI where the edge stmt should be inserted after. 
  
     Fallthrough code must be directed around the target label, and a target 
--- 3676,3684 ----
    return tsi_container (tsi);
  }
  
+ 
  /* Arrange for a place to insert a stmt when we are splitting a block which is
!    targetting by a switch stmt.  Return the container which is used to build
     a TSI where the edge stmt should be inserted after. 
  
     Fallthrough code must be directed around the target label, and a target 
*************** handle_switch_fallthru (tree sw_stmt, ba
*** 3692,3744 ****
     will be turned into:
  
       case X:
-        goto newlab;
    BB_b
       case Y:
         inserted_code;
    BB_a
       newlab:
         code;
    
     Note that upon entry to this function, src is *not* the switch stmt's block
     any more. bsi_insert_on_edge_immediate() has already split the edge from
     src->dest, so we have   original_src -> src -> dest. This new src block 
!    is currently empty.  */
     
  
  static tree *
  handle_switch_split (basic_block src, basic_block dest)
  {
    block_stmt_iterator bsi, tmp;
    tree_stmt_iterator tsi;
!   tree stmt, label, goto_stmt;
!   tree tmp_tree;
    basic_block new_bb;
!   edge e;
  
    label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-   DECL_CONTEXT (label) = current_function_decl;
    TREE_USED (label) = 1;
  
!   /* Insert a goto on all edges except the one from src to this label. */
      
!   for (e = dest->pred; e ; e = e->pred_next)
      {
!       if (e->src != src)
!         {
! 	  goto_stmt = build1 (GOTO_EXPR, void_type_node, label);
! 	  tmp_tree = PENDING_STMT (e);
! 	  SET_PENDING_STMT (e, NULL_TREE);
! 	  bsi_insert_on_edge_immediate (e, goto_stmt, NULL, &new_bb);   
! 	  SET_PENDING_STMT (e, tmp_tree);
! 
! 	  /* Splitting this edge should never result in a new block.  */
! 	  if (new_bb)
! 	    abort ();
  	}
      }
  
!   /* Find the last case label.  That will be where the code seperation
       between bb_c and bb_a will be formed.  Upon exit of the loop, bsi will
       point to the first stmt in BB_a.  */
  
--- 3693,3824 ----
     will be turned into:
  
       case X:
    BB_b
+        goto newlab;
+   BB_c
       case Y:
         inserted_code;
    BB_a
       newlab:
         code;
    
+    This will cause the creation of 2 new basic blocks, and require some 
+    edges to be redirected.  
+ 
     Note that upon entry to this function, src is *not* the switch stmt's block
     any more. bsi_insert_on_edge_immediate() has already split the edge from
     src->dest, so we have   original_src -> src -> dest. This new src block 
!    is currently empty. 
     
+    This routine will create BB_b. BB_c will be the SRC block passed in.
+    BB_a will remain the DEST block.  */
  
  static tree *
  handle_switch_split (basic_block src, basic_block dest)
  {
    block_stmt_iterator bsi, tmp;
    tree_stmt_iterator tsi;
!   tree stmt, label, parent;
!   tree phi;
    basic_block new_bb;
!   edge e, new_edge;
!   int num_elems, i;
!   bb_ann_t ann;
! 
! 
!   /* 1.  Insert the goto immediately preceeding the labels that are targeted. 
!      This should place the goto in the correct location in the tree.  */
! 
!   tsi = tsi_start (dest->head_tree_p);
!   parent = parent_stmt (tsi_stmt (tsi));
  
    label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
    TREE_USED (label) = 1;
+   stmt = build1 (GOTO_EXPR, void_type_node, label);
+ 
+   tsi_link_before (&tsi, stmt, TSI_NEW_STMT);
+   modify_stmt (stmt);
+ 
+   /* 2.  Make a new basic block of which this stmt is the sole member.  */
+ 
+   new_bb = create_bb ();
+   alloc_aux_for_block (new_bb, sizeof (struct bb_ann_d));
+   ann = bb_ann (new_bb);
+   ann->phi_nodes = NULL_TREE;
+   ann->ephi_nodes = NULL_TREE;
+   ann->dom_children = (bitmap) NULL;
+   append_stmt_to_bb (tsi_container (tsi), new_bb, parent);
+ 
+   /* Reset the head of dest since the container might be different now.  */
+   tsi_next (&tsi);
+   dest->head_tree_p = tsi_container (tsi);
  
!   /* 3. Redirect all the edges except the one from src to point to this
! 	block.  */
      
!   for (e = dest->pred; e ; )
      {
!       new_edge = e;
!       e = e->pred_next;
!       if (new_edge->src == src)
! 	continue;
!       redirect_edge_succ (new_edge, new_bb);
!     }
! 
!   /* 4. Now make dest the target of the new block.  Examine the PHI's and
! 	decide what to do.  */
! 
!   new_edge = make_edge (new_bb, dest, 0);
!   phi = phi_nodes (dest);
!   if (phi)
!     {
!       /* All PHI nodes should have the same number of elements.  */
!       num_elems = PHI_NUM_ARGS (phi);
! 
!       /* The easy case is if there are only 2 arguments. One edge has been 
! 	 updated already by the original edge split, so now update the 
! 	 other argument to come from this new edge.  */
!       if (num_elems == 2)
! 	{
! 	  for (; phi; phi = TREE_CHAIN (phi))
! 	    for (i = 0; i < num_elems; i++)
! 	      if (PHI_ARG_EDGE (phi, i)->src != src)
! 		PHI_ARG_EDGE (phi, i) = new_edge;
! 	}
!       else
! 	{
! 	  /* There is more than one edge coming into the new basic block,
! 	     so a new PHI node must be created for this block (BB_c), and 
! 	     then it must feed into another PHI node at the orginal 
! 	     block (BB_a).  This will require the creation of new PHI 
! 	     result variables for one of the 2 PHI nodes.  */
! 
! 	  for (; phi; phi = TREE_CHAIN (phi))
! 	    {
! 	      tree new_phi;
! 	      new_phi = create_phi_node (SSA_NAME_VAR (PHI_RESULT (phi)),
! 					 new_bb);
! 	      /* Add elements to the new PHI node.  */
! 	      for (i = 0; i < num_elems; i++)
! 	        {
! 		  e = PHI_ARG_EDGE (phi, i);
! 		  if (e->src != src)
! 		    add_phi_arg (new_phi, PHI_ARG_DEF (phi, i), e);
! 		}
! 
! 	      /* Remove the redirected edges from the old PHI node.  */
! 	      for (e = new_bb->pred; e ; e = e->pred_next)
! 		remove_phi_arg (phi, e->src);
! 	      
! 	      /* The original PHI node in BB_a should now contain only an
! 	         argument from src.  Add an argument from the new PHI node to
! 		 this PHI node.  */
! 	      add_phi_arg (phi, PHI_RESULT (new_phi), new_edge);
! 	    }
  	}
      }
  
!   /* 5. Find the last case label.  That will be where the code seperation
       between bb_c and bb_a will be formed.  Upon exit of the loop, bsi will
       point to the first stmt in BB_a.  */
  
*************** handle_switch_split (basic_block src, ba
*** 3748,3753 ****
--- 3828,3835 ----
        stmt = bsi_stmt (bsi);
        if (is_label_stmt (bsi_stmt (bsi)))
  	{
+ 	  /* FIXME.  This block may also be the target of a GOTO.  Hopefully 
+ 	     there are no case stmts after the label. ick.  */
  	  if (TREE_CODE (stmt) != CASE_LABEL_EXPR)
  	    break;
  	}
*************** handle_switch_split (basic_block src, ba
*** 3756,3766 ****
        tmp = bsi;
      }
  
!   /* Now the stmts delineating the new block are known. Change the basic
!      block for those stmts. It cannot be done in the above loop, for 
!      changing the basic block of a stmt pointed to by an iterator will cause
!      the iterator to think its reached the end of a block. (It is now 
!      pointing to BB_b, the next stmt is in BB_a, so it terminates.  */
  
    for (tsi = tsi_start (dest->head_tree_p); 
         !tsi_end_p (tsi) && (tsi_container (tsi) != bsi_container (bsi));
--- 3838,3848 ----
        tmp = bsi;
      }
  
!   /* 6. Now the stmts delinieating the new block are known. Change the basic
! 	block for those stmts. It cannot be done in the above loop, for 
! 	changing the basic block of a stmt pointed to by an iterator will cause
! 	the iterator to think its reached the end of a block. (It is now 
! 	pointing to BB_c, the next stmt is in BB_a, so it terminates.  */
  
    for (tsi = tsi_start (dest->head_tree_p); 
         !tsi_end_p (tsi) && (tsi_container (tsi) != bsi_container (bsi));
*************** handle_switch_split (basic_block src, ba
*** 3768,3775 ****
      append_stmt_to_bb (tsi_container (tsi), src, parent_stmt (tsi_stmt (tsi)));
  
  
!   /* Issue the label at the beginning of DEST, and update DEST's head
!      and end pointers.  */
  
    stmt = build1 (LABEL_EXPR, void_type_node, label);
    if (bsi_end_p (bsi))
--- 3850,3857 ----
      append_stmt_to_bb (tsi_container (tsi), src, parent_stmt (tsi_stmt (tsi)));
  
  
!   /* 7. Issue the label at the beginning of DEST, and update DEST's head
! 	and end pointers.  */
  
    stmt = build1 (LABEL_EXPR, void_type_node, label);
    if (bsi_end_p (bsi))
*************** handle_switch_split (basic_block src, ba
*** 3791,3799 ****
        bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
      }
  
!   bsi = bsi_last (src);
!   return bsi_container (bsi);
  }
  
  /* Given an edge between src and dest, return a TSI representing the location
     that any instructions on this edge should be inserted.  
--- 3873,3881 ----
        bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
      }
  
!   return bsi_container (tmp);
  }
+ 
  
  /* Given an edge between src and dest, return a TSI representing the location
     that any instructions on this edge should be inserted.  



More information about the Gcc-patches mailing list