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