spec20000 eon fix

Jan Hubicka jh@suse.cz
Fri Aug 3 14:26:00 GMT 2001


> On Fri, Aug 03, 2001 at 10:34:38PM +0200, Jan Hubicka wrote:
> > OK, I can take a look for the edges - what flag they get?
> 
> EDGE_EH | EDGE_ABNORMAL
> 
> > How can I recognize instructions that throws?
> 
> can_throw_internal
I am just testing the attached patch. Does it look OK now?

Pá srp  3 21:12:55 CEST 2001  Jan Hubicka  <jh@suse.cz>
	* flow.c (verify_flow_info): Verify that abnormal call edge are
	going from calls.
	(fixup_abnormal_calls): New function.
	* rtl.h (fixup_abnormal_calls): Declare.
	* toplev.c (rest_of_compilation): Use it.

*** flow.c.older	Fri Aug  3 19:52:41 2001
--- flow.c	Fri Aug  3 19:57:46 2001
*** toplev.c1	Mon Jun 18 19:12:26 2001
--- toplev.c	Fri Aug  3 19:53:30 2001
*************** rest_of_compilation (decl)
*** 3482,3487 ****
--- 3423,3429 ----
        build_insn_chain (insns);
        failure = reload (insns, 0);
      }
+   fixup_abnormal_calls ();
  
    timevar_pop (TV_GLOBAL_ALLOC);
  
*** rtl.h.old	Fri Aug  3 21:12:23 2001
--- rtl.h	Fri Aug  3 21:12:41 2001
*************** extern void recompute_reg_usage		PARAMS 
*** 1844,1849 ****
--- 1844,1850 ----
  extern void print_rtl_with_bb		PARAMS ((FILE *, rtx));
  extern void dump_flow_info		PARAMS ((FILE *));
  #endif
+ extern void fixup_abnormal_calls	PARAMS ((void));
  
  /* In expmed.c */
  extern void init_expmed			PARAMS ((void));
*** flow.c.older	Fri Aug  3 19:52:41 2001
--- flow.c	Sat Aug  4 00:26:25 2001
*************** verify_flow_info ()
*** 8328,8333 ****
--- 8328,8339 ----
  	    }
  	  last_visited [e->dest->index + 2] = bb;
  
+ 	  if (e->flags & EDGE_ABNORMAL_CALL && GET_CODE (bb->end) != CALL_INSN)
+ 	    {
+ 	      error ("verify_flow_info: Abnormal call edge outgoing from BB %i not ending by CALL_INSN",
+ 		     bb->index);
+ 	      err = 1;
+ 	    }
  	  if (e->flags & EDGE_FALLTHRU)
  	    has_fallthru = 1;
  
*************** purge_all_dead_edges ()
*** 10220,10223 ****
--- 10226,10283 ----
    int i;
    for (i = 0; i < n_basic_blocks; i++)
      purge_dead_edges (BASIC_BLOCK (i));
+ }
+ 
+ /* This is used by reload pass, that does emit some instructions after
+    abnormal calls moving basic block end, but in fact it wants to emit
+    them on the edge.  Looks for abnormal call edges, find backward the
+    proper call and fix the damage.
+  
+    Similar handle instructions throwing exceptions internally.  */
+ void
+ fixup_abnormal_calls ()
+ {
+   int i;
+   bool inserted = false;
+ 
+   for (i = 0; i < n_basic_blocks; i++)
+     {
+       basic_block bb = BASIC_BLOCK (i);
+       edge e;
+ 
+       /* Look for cases we are interested in - an calls or instructions causing
+          exceptions.  */
+       for (e = bb->succ; e; e = e->succ_next)
+ 	{
+ 	  if (e->flags & EDGE_ABNORMAL_CALL)
+ 	    break;
+ 	  if ((e->flags & (EDGE_ABNORMAL | EDGE_EH))
+ 	      == (EDGE_ABNORMAL | EDGE_EH))
+ 	    break;
+ 	}
+       if (e && GET_CODE (bb->end) != CALL_INSN && !can_throw_internal (bb->end))
+ 	{
+ 	  rtx insn = bb->end;
+ 	  rtx next;
+ 	  for (e = bb->succ; e; e = e->succ_next)
+ 	    if (e->flags & EDGE_FALLTHRU)
+ 	      break;
+ 	  while (GET_CODE (insn) == INSN && !can_throw_internal (insn))
+ 	    insn = PREV_INSN (insn);
+ 	  if (GET_CODE (insn) != CALL_INSN && !can_throw_internal (insn))
+ 	    abort ();
+ 	  bb->end = insn;
+ 	  inserted = true;
+ 	  insn = NEXT_INSN (insn);
+ 	  while (insn && GET_CODE (insn) == INSN)
+ 	    {
+ 	      next = NEXT_INSN (insn);
+ 	      insert_insn_on_edge (PATTERN (insn), e);
+ 	      flow_delete_insn (insn);
+ 	      insn = next;
+ 	    }
+ 	}
+     }
+   if (inserted)
+     commit_edge_insertions ();
  }



More information about the Gcc-patches mailing list