alpha.c (final_prescan_insn): Gut, remove and transform to ...

* alpha.c (final_prescan_insn): Gut, remove and transform to ...
        (alpha_handle_trap_shadows): ... a new function.  Handle the entire
        function in one go.  Emit RTL for trapb, instead of printf directly.
        (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 a word.
        * alpha.h (FINAL_PRESCAN_INSN): Remove.
        (MACHINE_DEPENENT_REORG): Define.
        * alpha.md (jsr patterns with trapb): Stupid and useless.  Kill.
        (trapb): New insn.

From-SVN: r15917
This commit is contained in:
Richard Henderson 1997-10-15 18:23:23 -07:00 committed by Richard Henderson
parent 74835ed802
commit 2ea844d394
4 changed files with 165 additions and 142 deletions

View File

@ -1,3 +1,17 @@
Wed Oct 15 18:21:46 1997 Richard Henderson <rth@cygnus.com>
* alpha.c (final_prescan_insn): Gut, remove and transform to ...
(alpha_handle_trap_shadows): ... a new function. Handle the entire
function in one go. Emit RTL for trapb, instead of printf directly.
(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 a word.
* alpha.h (FINAL_PRESCAN_INSN): Remove.
(MACHINE_DEPENENT_REORG): Define.
* alpha.md (jsr patterns with trapb): Stupid and useless. Kill.
(trapb): New insn.
Wed Oct 15 18:16:05 1997 Richard Henderson <rth@cygnus.com>
Tune Haifa scheduler for Alpha:

View File

@ -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;
@ -2599,8 +2595,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");
@ -2791,8 +2785,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;
};
@ -2915,19 +2909,9 @@ 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
@ -2953,103 +2937,151 @@ 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};
struct shadow_summary shadow;
int trap_pending, exception_nesting;
rtx i;
#define CLOSE_SHADOW \
do \
{ \
fputs ("\ttrapb\n", asm_out_file); \
trap_pending = 0; \
bzero ((char *) &shadow, sizeof shadow); \
} \
while (0)
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;
case ALPHA_TP_INSN:
if (optimize && insn != 0)
{
struct shadow_summary sum = {0, 0, 0};
switch (GET_CODE(insn))
{
case INSN:
summarize_insn (PATTERN (insn), &sum, 0);
if ((sum.defd.i & shadow.defd.i)
|| (sum.defd.fp & shadow.defd.fp))
{
/* (c) would be violated */
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;
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 ();
CLOSE_SHADOW;
break;
}
break;
case JUMP_INSN:
case CALL_INSN:
case CODE_LABEL:
CLOSE_SHADOW;
break;
default:
abort ();
}
}
else
CLOSE_SHADOW;
break;
}
if (insn != 0 && get_attr_trap (insn) == TRAP_YES)
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 (optimize && !trap_pending && GET_CODE (insn) == INSN)
summarize_insn (PATTERN (insn), &shadow, 0);
trap_pending = 1;
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 NOTE_INSN_EH_REGION_END:
exception_nesting--;
if (trap_pending)
goto close_shadow;
break;
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;
sum.used.i = 0;
sum.used.fp = 0;
sum.used.mem = 0;
sum.defd = shadow.used;
switch (GET_CODE (i))
{
case INSN:
/* Annoyingly, get_attr_trap will abort on USE. */
if (GET_CODE (PATTERN (i)) == USE)
break;
summarize_insn (PATTERN (i), &sum, 0);
if ((sum.defd.i & shadow.defd.i)
|| (sum.defd.fp & shadow.defd.fp))
{
/* (c) would be violated */
goto close_shadow;
}
/* 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;
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 ();
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. */
static char *float_strings[] =

View File

@ -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. */

View File

@ -3279,18 +3279,6 @@
}
}")
(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 && 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 "" ""))
@ -3326,19 +3314,6 @@
ldq $27,%2\;jsr $26,%0\;ldq $27,0($29)"
[(set_attr "type" "jsr")])
(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 && 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"))
@ -4513,3 +4488,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")])