alpha.c (alpha_return_addr_rtx): New variable.

* alpha.c (alpha_return_addr_rtx): New variable.
        (alpha_save_machine_status): New; save it.
        (alpha_restore_machine_status): New; restore it.
        (alpha_init_expanders): New; clear it.
        (alpha_return_addr): New; set it.
        (alpha_ra_ever_killed): New; if alpha_return_addr_rtx, regs_ever_live
        is overly conservative, so search the insns explicitly.
        (alpha_sa_mask [VMS]): Check alpha_ra_ever_killed.
        (alpha_sa_size [VMS && !VMS]): Likewise.
        * alpha.h (RETURN_ADDR_RTX): Call alpha_return_addr.
        (INIT_EXPANDERS): New definition.

        * alpha.c: Move REG_PV, REG_RA somewhere more visible in the file.
        (output_prolog [!VMS]): Use them.

        * alpha.c (output_prolog [!VMS]): Move gp detection to ...
        (alpha_does_function_need_gp): ... a new function.  Refine the
        CALL_INSN test to just TYPE_JSR.
        * alpha.md (most call insns): Fix some jsr/ibr type transpositions.

From-SVN: r15936
This commit is contained in:
Richard Henderson 1997-10-16 11:37:59 -07:00 committed by Richard Henderson
parent bda2ffefc8
commit 9ecc37f0e2
4 changed files with 187 additions and 54 deletions

View File

@ -1,3 +1,25 @@
Thu Oct 16 11:20:30 1997 Richard Henderson <rth@cygnus.com>
* alpha.c (alpha_return_addr_rtx): New variable.
(alpha_save_machine_status): New; save it.
(alpha_restore_machine_status): New; restore it.
(alpha_init_expanders): New; clear it.
(alpha_return_addr): New; set it.
(alpha_ra_ever_killed): New; if alpha_return_addr_rtx, regs_ever_live
is overly conservative, so search the insns explicitly.
(alpha_sa_mask [VMS]): Check alpha_ra_ever_killed.
(alpha_sa_size [VMS && !VMS]): Likewise.
* alpha.h (RETURN_ADDR_RTX): Call alpha_return_addr.
(INIT_EXPANDERS): New definition.
* alpha.c: Move REG_PV, REG_RA somewhere more visible in the file.
(output_prolog [!VMS]): Use them.
* alpha.c (output_prolog [!VMS]): Move gp detection to ...
(alpha_does_function_need_gp): ... a new function. Refine the
CALL_INSN test to just TYPE_JSR.
* alpha.md (most call insns): Fix some jsr/ibr type transpositions.
Thu Oct 16 09:36:47 1997 Jeffrey A Law (law@cygnus.com)
* version.c: Bump for snapshot.

View File

@ -37,8 +37,15 @@ Boston, MA 02111-1307, USA. */
#include "expr.h"
#include "obstack.h"
#include "tree.h"
#include "except.h"
#include "function.h"
/* External data. */
extern char *version_string;
extern int rtx_equal_function_value_matters;
/* Specify which cpu to schedule for. */
enum processor_type alpha_cpu;
/* Specify how accurate floating-point traps need to be. */
@ -54,6 +61,7 @@ enum alpha_fp_rounding_mode alpha_fprm;
enum alpha_fp_trap_mode alpha_fptm;
/* Strings decoded into the above options. */
char *alpha_cpu_string; /* -mcpu=ev[4|5] */
char *alpha_tp_string; /* -mtrap-precision=[p|s|i] */
char *alpha_fprm_string; /* -mfp-rounding-mode=[n|m|c|d] */
@ -79,8 +87,9 @@ static int inside_function = FALSE;
int alpha_function_needs_gp;
extern char *version_string;
extern int rtx_equal_function_value_matters;
/* If non-null, this rtx holds the return address for the function. */
static rtx alpha_return_addr_rtx;
/* Declarations of static functions. */
static void alpha_set_memflags_1 PROTO((rtx, int, int, int));
@ -91,10 +100,16 @@ static void add_long_const PROTO((FILE *, HOST_WIDE_INT, int, int, int));
/* Compute the size of the save area in the stack. */
static void alpha_sa_mask PROTO((unsigned long *imaskP,
unsigned long *fmaskP));
/* Strip type information. */
#define CURRENT_FUNCTION_ARGS_INFO \
(TARGET_OPEN_VMS ? current_function_args_info & 0xff \
: current_function_args_info)
/* Some helpful register info. */
#define REG_PV 27
#define REG_RA 26
/* Parse target option strings. */
@ -1269,6 +1284,87 @@ alpha_adjust_cost (insn, link, dep_insn, cost)
/* Otherwise, return the default cost. */
return cost;
}
/* Functions to save and restore alpha_return_addr_rtx. */
struct machine_function
{
rtx ra_rtx;
};
static void
alpha_save_machine_status (p)
struct function *p;
{
struct machine_function *machine =
(struct machine_function *) xmalloc (sizeof (struct machine_function));
p->machine = machine;
machine->ra_rtx = alpha_return_addr_rtx;
}
static void
alpha_restore_machine_status (p)
struct function *p;
{
struct machine_function *machine = p->machine;
alpha_return_addr_rtx = machine->ra_rtx;
free (machine);
p->machine = (struct machine_function *)0;
}
/* Do anything needed before RTL is emitted for each function. */
void
alpha_init_expanders ()
{
alpha_return_addr_rtx = NULL_RTX;
/* Arrange to save and restore machine status around nested functions. */
save_machine_status = alpha_save_machine_status;
restore_machine_status = alpha_restore_machine_status;
}
/* Start the ball rolling with RETURN_ADDR_RTX. */
rtx
alpha_return_addr (count, frame)
int count;
rtx frame;
{
rtx init, first;
if (count != 0)
return const0_rtx;
if (alpha_return_addr_rtx)
return alpha_return_addr_rtx;
/* No rtx yet. Invent one, and initialize it from $26 in the prologue. */
alpha_return_addr_rtx = gen_reg_rtx (Pmode);
init = gen_rtx (SET, Pmode, alpha_return_addr_rtx, gen_rtx (REG, Pmode, 26));
/* Emit the insn to the prologue with the other argument copies. */
push_topmost_sequence ();
emit_insn_after (init, get_insns ());
pop_topmost_sequence ();
return alpha_return_addr_rtx;
}
static int
alpha_ra_ever_killed ()
{
rtx i, ra;
if (!alpha_return_addr_rtx)
return regs_ever_live[REG_RA];
return reg_set_between_p (gen_rtx (REG, REG_RA), get_insns(), NULL_RTX);
}
/* Print an operand. Recognize special options, documented below. */
@ -1661,9 +1757,6 @@ alpha_builtin_saveregs (arglist)
#if OPEN_VMS
#define REG_PV 27
#define REG_RA 26
/* These variables are used for communication between the following functions.
They indicate various things about the current function being compiled
that are used to tell what kind of prologue, epilogue and procedure
@ -1700,13 +1793,16 @@ alpha_sa_mask (imaskP, fmaskP)
/* One for every register we have to save. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i])
if (! fixed_regs[i] && ! call_used_regs[i]
&& regs_ever_live[i] && i != REG_RA)
{
if (i < 32)
imask |= (1L << i);
else
fmask |= (1L << (i - 32));
}
if (alpha_ra_ever_killed ())
imask |= (1L << REG_RA);
*imaskP = imask;
*fmaskP = fmask;
@ -1724,13 +1820,14 @@ alpha_sa_size ()
/* One for every register we have to save. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i])
if (! fixed_regs[i] && ! call_used_regs[i]
&& regs_ever_live[i] && i != REG_RA)
sa_size++;
/* Start by assuming we can use a register procedure if we don't make any
calls (REG_RA not used) or need to save any registers and a stack
procedure if we do. */
is_stack_procedure = regs_ever_live[REG_RA] || sa_size != 0;
is_stack_procedure = sa_size != 0 || alpha_ra_ever_killed ();
/* Decide whether to refer to objects off our PV via FP or PV.
If we need need FP for something else or if we receive a nonlocal
@ -1788,12 +1885,13 @@ alpha_sa_size ()
int i;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i])
if (! fixed_regs[i] && ! call_used_regs[i]
&& regs_ever_live[i] && i != REG_RA)
size++;
/* If some registers were saved but not reg 26, reg 26 must also
be saved, so leave space for it. */
if (size != 0 && ! regs_ever_live[26])
if (size != 0 || alpha_ra_ever_killed ())
size++;
/* Our size must be even (multiple of 16 bytes). */
@ -2333,6 +2431,37 @@ output_epilog (file, size)
#else /* !OPEN_VMS */
static int
alpha_does_function_need_gp ()
{
rtx insn;
/* We never need a GP for Windows/NT. */
if (TARGET_WINDOWS_NT)
return 0;
#ifdef TARGET_PROFILING_NEEDS_GP
if (profile_flag)
return 1;
#endif
/* If we need a GP (we have a LDSYM insn or a CALL_INSN), load it first.
Even if we are a static function, we still need to do this in case
our address is taken and passed to something like qsort. */
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
&& GET_CODE (PATTERN (insn)) != USE
&& GET_CODE (PATTERN (insn)) != CLOBBER)
{
enum attr_type type = get_attr_type (insn);
if (type == TYPE_LDSYM || type == TYPE_JSR)
return 1;
}
return 0;
}
void
output_prolog (file, size)
FILE *file;
@ -2348,7 +2477,6 @@ output_prolog (file, size)
HOST_WIDE_INT start_reg_offset = reg_offset;
HOST_WIDE_INT actual_start_reg_offset = start_reg_offset;
int int_reg_save_area_size = 0;
rtx insn;
unsigned reg_mask = 0;
int i, sa_reg;
@ -2393,30 +2521,7 @@ output_prolog (file, size)
alpha_auto_offset = -frame_size + current_function_pretend_args_size;
alpha_arg_offset = -frame_size + 48;
/* If we need a GP (we have a LDSYM insn or a CALL_INSN), load it first.
Even if we are a static function, we still need to do this in case
our address is taken and passed to something like qsort.
We never need a GP for Windows/NT. */
alpha_function_needs_gp = 0;
#ifdef TARGET_PROFILING_NEEDS_GP
if (profile_flag)
alpha_function_needs_gp = 1;
#endif
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
if ((GET_CODE (insn) == CALL_INSN)
|| (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
&& GET_CODE (PATTERN (insn)) != USE
&& GET_CODE (PATTERN (insn)) != CLOBBER
&& (get_attr_type (insn) == TYPE_LDSYM
|| get_attr_type (insn) == TYPE_ISUBR)))
{
alpha_function_needs_gp = 1;
break;
}
alpha_function_needs_gp = alpha_does_function_need_gp ();
if (TARGET_WINDOWS_NT == 0)
{
@ -2515,10 +2620,10 @@ output_prolog (file, size)
sa_reg = 24;
}
/* Save register 26 if any other register needs to be saved. */
/* Save register RA if any other register needs to be saved. */
if (sa_size != 0)
{
reg_mask |= 1 << 26;
reg_mask |= 1 << REG_RA;
fprintf (file, "\tstq $26,%d($%d)\n", reg_offset, sa_reg);
reg_offset += 8;
int_reg_save_area_size += 8;
@ -2526,7 +2631,8 @@ output_prolog (file, size)
/* Now save any other used integer registers required to be saved. */
for (i = 0; i < 32; i++)
if (! fixed_regs[i] && ! call_used_regs[i] && regs_ever_live[i] && i != 26)
if (! fixed_regs[i] && ! call_used_regs[i]
&& regs_ever_live[i] && i != REG_RA)
{
reg_mask |= 1 << i;
fprintf (file, "\tstq $%d,%d($%d)\n", i, reg_offset, sa_reg);

View File

@ -1255,16 +1255,17 @@ __enable_execute_stack (addr) \
/* A C expression whose value is RTL representing the value of the return
address for the frame COUNT steps up from the current frame.
FRAMEADDR is the frame pointer of the COUNT frame, or the frame pointer of
the COUNT-1 frame if RETURN_ADDR_IN_PREVIOUS_FRAME} is defined.
the COUNT-1 frame if RETURN_ADDR_IN_PREVIOUS_FRAME} is defined. */
This definition for Alpha is broken, but is put in at the request of
Mike Stump. */
#define RETURN_ADDR_RTX alpha_return_addr
extern struct rtx_def *alpha_return_addr ();
/* Initialize data used by insn expanders. This is called from insn_emit,
once for every function before code is generated. */
#define INIT_EXPANDERS alpha_init_expanders ()
extern void alpha_init_expanders ();
#define RETURN_ADDR_RTX(COUNT, FRAME) \
((COUNT == 0 && alpha_sa_size () == 0 && 0 /* not right. */) \
? gen_rtx (REG, Pmode, 26) \
: gen_rtx (MEM, Pmode, \
memory_address (Pmode, FRAME)))
/* Addressing modes, and classification of registers for them. */

View File

@ -33,7 +33,7 @@
;; separately.
(define_attr "type"
"ld,st,ibr,fbr,jsr,iadd,ilog,shift,cmov,icmp,imull,imulq,imulh,fadd,fmul,fcpys,fdivs,fdivt,ldsym,isubr,misc"
"ld,st,ibr,fbr,jsr,iadd,ilog,shift,cmov,icmp,imull,imulq,imulh,fadd,fmul,fcpys,fdivs,fdivt,ldsym,misc"
(const_string "iadd"))
;; The TRAP_TYPE attribute marks instructions that may generate traps
@ -744,7 +744,7 @@
; (clobber (reg:DI 28))]
; "!TARGET_OPEN_VMS"
; "%E1 $24,$25,$27"
; [(set_attr "type" "isubr")])
; [(set_attr "type" "jsr")])
(define_insn ""
[(set (reg:DI 27)
@ -754,7 +754,7 @@
(clobber (reg:DI 28))]
"!TARGET_OPEN_VMS"
"%E1 $24,$25,$27"
[(set_attr "type" "isubr")])
[(set_attr "type" "jsr")])
;; Next are the basic logical operations. These only exist in DImode.
@ -3289,7 +3289,7 @@
jsr $26,($27),0\;ldgp $29,0($26)
bsr $26,%0..ng
jsr $26,%0\;ldgp $29,0($26)"
[(set_attr "type" "jsr,jsr,ibr")])
[(set_attr "type" "jsr,ibr,jsr")])
(define_insn ""
[(call (mem:DI (match_operand:DI 0 "call_operand" "r,i"))
@ -3299,7 +3299,7 @@
"@
jsr $26,(%0)
bsr $26,%0"
[(set_attr "type" "jsr")])
[(set_attr "type" "jsr,ibr")])
(define_insn ""
[(call (mem:DI (match_operand:DI 0 "call_operand" "r,i"))
@ -3325,7 +3325,7 @@
jsr $26,($27),0\;ldgp $29,0($26)
bsr $26,%1..ng
jsr $26,%1\;ldgp $29,0($26)"
[(set_attr "type" "jsr,jsr,ibr")])
[(set_attr "type" "jsr,ibr,jsr")])
(define_insn ""
[(set (match_operand 0 "register_operand" "=rf,rf")
@ -3336,7 +3336,7 @@
"@
jsr $26,(%1)
bsr $26,%1"
[(set_attr "type" "jsr")])
[(set_attr "type" "jsr,ibr")])
(define_insn ""
[(set (match_operand 0 "register_operand" "")
@ -3568,11 +3568,15 @@
;; Cache flush. Used by INITIALIZE_TRAMPOLINE. 0x86 is PAL_imb, but we don't
;; want to have to include pal.h in our .s file.
;;
;; Technically the type for call_pal is jsr, but we use that for determining
;; if we need a GP. Use ibr instead since it has the same scheduling
;; characteristics.
(define_insn ""
[(unspec_volatile [(const_int 0)] 0)]
""
"call_pal 0x86"
[(set_attr "type" "isubr")])
[(set_attr "type" "ibr")])
;; Finally, we have the basic data motion insns. The byte and word insns
;; are done via define_expand. Start with the floating-point insns, since