revamp alpha trap shadow handling

Richard Henderson rth@cygnus.com
Mon Oct 6 01:28:00 GMT 1997


The following patch reworks the trap shadow handling so that it uses
MACHINE_DEPENDENT_REORG and scans the function in one go rather than
instruction-by-instruction via FINAL_PRESCAN_INSN.

(1) It has _got_ to be faster.
(2) Using prescan and fprintf seems kludgy in the extreme.
(3) A solution I am working on for the EV5 split-issue scheduling 
    problem needs to know exact instruction alignments, and I can't
    have random trapb's throwing me off.

Nr 3 is also the reason alpha_reorg and alpha_handle_trap_shadows 
are not the same function.


r~



Mon Oct  6 01:09:49 1997  Richard Henderson  <rth@cygnus.com>

	* alpha.c (final_prescan_insn): Gut and transform to ...
	(alpha_handle_trap_shadows): ... a new function.  Handle the entire
	function in one go.  Emit RTL for trapb, instead of using printf.
	(alpha_reorg): New function.  Call alpha_handle_trap_shadows.
	(trap_pending): Kill global variable.
	(output_epilog): Don't call final_prescan_insn.
	(struct shadow_summary): Elide $31 and $f31; now it fits in one word.


Index: alpha.c
===================================================================
RCS file: /cvs/cvsfiles/egcs/gcc/config/alpha/alpha.c,v
retrieving revision 1.2
diff -u -p -d -r1.2 alpha.c
--- alpha.c	1997/09/15 22:28:34	1.2
+++ alpha.c	1997/10/06 08:11:28
@@ -75,10 +75,6 @@ char *alpha_function_name;
 
 static int inside_function = FALSE;
 
-/* Non-zero if an instruction that may cause a trap is pending.  */
-
-static int trap_pending = 0;
-
 /* Nonzero if the current function needs gp.  */
 
 int alpha_function_needs_gp;
@@ -2562,8 +2558,6 @@ output_epilog (file, size)
       int fp_offset = 0;
       int sa_reg;
 
-      final_prescan_insn (NULL_RTX, NULL_PTR, 0);
-
       /* If we have a frame pointer, restore SP from it.  */
       if (frame_pointer_needed)
 	fprintf (file, "\tbis $15,$15,$30\n");
@@ -2754,8 +2748,8 @@ alpha_output_lineno (stream, line)
 struct shadow_summary
 {
   struct {
-    unsigned long i     : 32;	/* Mask of int regs */
-    unsigned long fp    : 32;	/* Mask of fp regs */
+    unsigned long i     : 31;	/* Mask of int regs */
+    unsigned long fp    : 31;	/* Mask of fp regs */
     unsigned long mem   :  1;	/* mem == imem | fpmem */
   } used, defd;
 };
@@ -2879,18 +2873,8 @@ summarize_insn (x, sum, set)
     }
 }
 
-/* This function is executed just prior to the output of assembler code for
-   INSN to modify the extracted operands so they will be output differently.
-
-   OPVEC is the vector containing the operands extracted from INSN, and
-   NOPERANDS is the number of elements of the vector which contain meaningful
-   data for this insn.  The contents of this vector are what will be used to
-   convert the insn template into assembler code, so you can change the
-   assembler output by changing the contents of the vector.
-
-   We use this function to ensure a sufficient number of `trapb' instructions
-   are in the code when the user requests code with a trap precision of
-   functions or instructions.
+/* Ensure a sufficient number of `trapb' insns are in the code when the user
+   requests code with a trap precision of functions or instructions.
 
    In naive mode, when the user requests a trap-precision of "instruction", a
    trapb is needed after every instruction that may generate a trap (and after
@@ -2916,101 +2900,148 @@ summarize_insn (x, sum, set)
    (c) Within the trap shadow, no register may be used more than once as a
    destination register.  (This is to make life easier for the trap-handler.)
 
-   (d) The trap shadow may not include any branch instructions.
-
-     */
+   (d) The trap shadow may not include any branch instructions.  */
 
-void
-final_prescan_insn (insn, opvec, noperands)
-     rtx insn;
-     rtx *opvec;
-     int noperands;
+static void
+alpha_handle_trap_shadows (insns)
+     rtx insns;
 {
-  static struct shadow_summary shadow = {0, 0, 0, 0, 0};
-
-#define CLOSE_SHADOW				\
-  do						\
-    {						\
-      fputs ("\ttrapb\n", asm_out_file);	\
-      trap_pending = 0;				\
-      bzero ((char *) &shadow,  sizeof shadow);	\
-    }						\
-  while (0)
+  struct shadow_summary shadow;
+  int trap_pending, exception_nesting;
+  rtx i;
 
-  if (alpha_tp == ALPHA_TP_PROG)
+  if (alpha_tp == ALPHA_TP_PROG && !flag_exceptions)
     return;
 
-  if (trap_pending)
-    switch (alpha_tp)
-      {
-      case ALPHA_TP_FUNC:
-	/* Generate one trapb before epilogue (indicated by INSN==0) */
-	if (insn == 0)
-	  CLOSE_SHADOW;
-	break;
+  trap_pending = 0;
+  exception_nesting = 0;
+  shadow.used.i = 0;
+  shadow.used.fp = 0;
+  shadow.used.mem = 0;
+  shadow.defd = shadow.used;
+  
+  for (i = insns; i ; i = NEXT_INSN (i))
+    {
+      if (GET_CODE (i) == NOTE)
+	{
+	  switch (NOTE_LINE_NUMBER (i))
+	    {
+	    case NOTE_INSN_EH_REGION_BEG:
+	      exception_nesting++;
+	      if (trap_pending)
+		goto close_shadow;
+	      break;
 
-      case ALPHA_TP_INSN:
-	if (optimize && insn != 0)
-	  {
-	    struct shadow_summary sum = {0, 0, 0};
+	    case NOTE_INSN_EH_REGION_END:
+	      exception_nesting--;
+	      if (trap_pending)
+		goto close_shadow;
+	      break;
 
-	    switch (GET_CODE(insn))
-	      {
-	      case INSN:
-		summarize_insn (PATTERN (insn), &sum, 0);
+	    case NOTE_INSN_EPILOGUE_BEG:
+	      if (trap_pending && alpha_tp >= ALPHA_TP_FUNC)
+		goto close_shadow;
+	      break;
+	    }
+	}
+      else if (trap_pending)
+	{
+	  if (alpha_tp == ALPHA_TP_FUNC)
+	    {
+	      if (GET_CODE (i) == JUMP_INSN
+		  && GET_CODE (PATTERN (i)) == RETURN)
+		goto close_shadow;
+	    }
+	  else if (alpha_tp == ALPHA_TP_INSN)
+	    {
+	      if (optimize > 0)
+		{
+		  struct shadow_summary sum;
 
-		if ((sum.defd.i & shadow.defd.i)
-		    || (sum.defd.fp & shadow.defd.fp))
-		  {
-		    /* (c) would be violated */
-		    CLOSE_SHADOW;
-		    break;
-		  }
+		  sum.used.i = 0;
+		  sum.used.fp = 0;
+		  sum.used.mem = 0;
+		  sum.defd = shadow.used;
 
-		/* Combine shadow with summary of current insn: */
-		shadow.used.i     |= sum.used.i;
-		shadow.used.fp    |= sum.used.fp;
-		shadow.used.mem   |= sum.used.mem;
-		shadow.defd.i     |= sum.defd.i;
-		shadow.defd.fp    |= sum.defd.fp;
-		shadow.defd.mem   |= sum.defd.mem;
+		  switch (GET_CODE (i))
+		    {
+		    case INSN:
+		      /* Annoyingly, get_attr_trap will abort on USE.  */
+		      if (GET_CODE (PATTERN (i)) == USE)
+			break;
 
-		if ((sum.defd.i & shadow.used.i)
-		    || (sum.defd.fp & shadow.used.fp)
-		    || (sum.defd.mem & shadow.used.mem))
-		  {
-		    /* (a) would be violated (also takes care of (b)).  */
-		    if (get_attr_trap (insn) == TRAP_YES
-			&& ((sum.defd.i & sum.used.i)
-			    || (sum.defd.fp & sum.used.fp)))
-		      abort ();
+		      summarize_insn (PATTERN (i), &sum, 0);
 
-		    CLOSE_SHADOW;
-		    break;
-		  }
-		break;
+		      if ((sum.defd.i & shadow.defd.i)
+			  || (sum.defd.fp & shadow.defd.fp))
+			{
+			  /* (c) would be violated */
+			  goto close_shadow;
+			}
 
-	      case JUMP_INSN:
-	      case CALL_INSN:
-	      case CODE_LABEL:
-		CLOSE_SHADOW;
-		break;
+		      /* Combine shadow with summary of current insn: */
+		      shadow.used.i   |= sum.used.i;
+		      shadow.used.fp  |= sum.used.fp;
+		      shadow.used.mem |= sum.used.mem;
+		      shadow.defd.i   |= sum.defd.i;
+		      shadow.defd.fp  |= sum.defd.fp;
+		      shadow.defd.mem |= sum.defd.mem;
 
-	      default:
-		abort ();
-	      }
-	  }
-	else
-	  CLOSE_SHADOW;
-	break;
-      }
+		      if ((sum.defd.i & shadow.used.i)
+			  || (sum.defd.fp & shadow.used.fp)
+			  || (sum.defd.mem & shadow.used.mem))
+			{
+			  /* (a) would be violated (also takes care of (b))  */
+			  if (get_attr_trap (i) == TRAP_YES
+			      && ((sum.defd.i & sum.used.i)
+				  || (sum.defd.fp & sum.used.fp)))
+			    abort ();
 
-  if (insn != 0 && get_attr_trap (insn) == TRAP_YES)
-    {
-      if (optimize && !trap_pending && GET_CODE (insn) == INSN)
-	summarize_insn (PATTERN (insn), &shadow, 0);
-      trap_pending = 1;
+			  goto close_shadow;
+			}
+		      break;
+
+		    case JUMP_INSN:
+		    case CALL_INSN:
+		    case CODE_LABEL:
+		      goto close_shadow;
+
+		    default:
+		      abort ();
+		    }
+		}
+	      else
+		{
+		close_shadow:
+		  emit_insn_before (gen_trapb (), i);
+		  trap_pending = 0;
+		  shadow.used.i = 0;
+		  shadow.used.fp = 0;
+		  shadow.used.mem = 0;
+		  shadow.defd = shadow.used;
+		}
+	    }
+	}
+
+      if (exception_nesting > 0 || alpha_tp >= ALPHA_TP_FUNC)
+	if (GET_CODE (i) == INSN
+	    && GET_CODE (PATTERN (i)) != USE
+	    && get_attr_trap (i) == TRAP_YES)
+	  {
+	    if (optimize && !trap_pending)
+	      summarize_insn (PATTERN (i), &shadow, 0);
+	    trap_pending = 1;
+	  }
     }
+}
+
+/* Machine dependant reorg pass.  */
+
+void
+alpha_reorg (insns)
+     rtx insns;
+{
+  alpha_handle_trap_shadows (insns);
 }
 
 /* Check a floating-point value for validity for a particular machine mode.  */
Index: alpha.h
===================================================================
RCS file: /cvs/cvsfiles/egcs/gcc/config/alpha/alpha.h,v
retrieving revision 1.4
diff -u -p -d -r1.4 alpha.h
--- alpha.h	1997/09/29 06:18:28	1.4
+++ alpha.h	1997/10/06 08:11:28
@@ -1463,15 +1463,8 @@ __enable_execute_stack (addr)						\
 
 #define ADDRESS_COST(X)  0
 
-/* Define this if some processing needs to be done immediately before
-   emitting code for an insn.  */
-
-extern void final_prescan_insn ();
-#define FINAL_PRESCAN_INSN(INSN,OPERANDS,NOPERANDS) \
-  final_prescan_insn ((INSN), (OPERANDS), (NOPERANDS))
-
-/* Define this if FINAL_PRESCAN_INSN should be called for a CODE_LABEL.  */
-#define FINAL_PRESCAN_LABEL
+/* Machine-dependent reorg pass.   */
+#define MACHINE_DEPENDENT_REORG(X)	alpha_reorg(X)
 
 /* Specify the machine mode that this machine uses
    for the index in the tablejump instruction.  */
Index: alpha.md
===================================================================
RCS file: /cvs/cvsfiles/egcs/gcc/config/alpha/alpha.md,v
retrieving revision 1.5
diff -u -p -d -r1.5 alpha.md
--- alpha.md	1997/10/01 05:04:30	1.5
+++ alpha.md	1997/10/06 08:11:28
@@ -3279,18 +3279,6 @@
 	 (match_operand 1 "" ""))
    (clobber (reg:DI 27))
    (clobber (reg:DI 26))]
-  "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && alpha_tp == ALPHA_TP_INSN"
-  "@
-   jsr $26,($27),0\;trapb\;ldgp $29,4($26)
-   bsr $26,%0..ng\;trapb
-   jsr $26,%0\;trapb\;ldgp $29,4($26)"
-  [(set_attr "type" "jsr,jsr,ibr")])
-      
-(define_insn ""
-  [(call (mem:DI (match_operand:DI 0 "call_operand" "r,R,i"))
-	 (match_operand 1 "" ""))
-   (clobber (reg:DI 27))
-   (clobber (reg:DI 26))]
   "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS"
   "@
    jsr $26,($27),0\;ldgp $29,0($26)
@@ -3327,19 +3315,6 @@
 	      (match_operand 2 "" "")))
    (clobber (reg:DI 27))
    (clobber (reg:DI 26))]
-  "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS && alpha_tp == ALPHA_TP_INSN"
-  "@
-   jsr $26,($27),0\;trapb\;ldgp $29,4($26)
-   bsr $26,%1..ng\;trapb
-   jsr $26,%1\;trapb\;ldgp $29,4($26)"
-  [(set_attr "type" "jsr,jsr,ibr")])
-
-(define_insn ""
-  [(set (match_operand 0 "register_operand" "=rf,rf,rf")
-	(call (mem:DI (match_operand:DI 1 "call_operand" "r,R,i"))
-	      (match_operand 2 "" "")))
-   (clobber (reg:DI 27))
-   (clobber (reg:DI 26))]
   "! TARGET_WINDOWS_NT && ! TARGET_OPEN_VMS"
   "@
    jsr $26,($27),0\;ldgp $29,0($26)
@@ -4508,3 +4483,12 @@
    (clobber (reg:DI 0))]
   "TARGET_OPEN_VMS"
   "lda $0,ots$home_args\;ldq $0,8($0)\;jsr $0,ots$home_args")
+
+;; Close the trap shadow of preceeding instructions.  This is generated
+;; by alpha_reorg.
+
+(define_insn "trapb"
+  [(unspec_volatile [(const_int 0)] 3)]
+  ""
+  "trapb"
+  [(set_attr "type" "misc")])



More information about the Gcc mailing list