Commit c47decad by Jeff Law

pa.h (enum processor_type): New enumeration describing the processor to schedule…

pa.h (enum processor_type): New enumeration describing the processor to schedule for (700, 7100, 7100LC).

	* pa.h (enum processor_type): New enumeration describing the
	processor to schedule for (700, 7100, 7100LC).
	(pa_cpu_attr, TARGET_OPTIONS, OVERRIDE_OPTIONS): Define.
	(pa_cpu_string, pa_cpu): Provide extern decls.
	* pa.c (pa_cpu, pa_cpu_string): Provide definitions.
	(override_options): New function.
	(pa_adjust_cost): Handle PROCESSOR_7100 and PROCESSOR_7100LC
	scheduling.  Handle anti-dependendy cases involving fp division
	and sqrt.  Handle output dependencies correctly.  Break TYPE_FPMUL
	into TYPE_FPMULSGL and TYPE_FPMULDBL.
	* pa.md (cpu attribute): New attribute.
	Clean up comments for PROCESSOR_700 scheduling info.  Slightly
	simplify.  Make conditional on PROCESSOR_700.
	Add comments and scheduling information for PROCESSOR_7100 and
	PROCESSOR_7100LC.  Set types for instructions which use the shifter
	to "shift".  Explicitly set lengths and types for all instructions.
	Break type "fpmul" into "fmulsgl" and "fpmuldbl".

From-SVN: r8723
parent c1fe41cb
...@@ -41,6 +41,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ...@@ -41,6 +41,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
rtx hppa_compare_op0, hppa_compare_op1; rtx hppa_compare_op0, hppa_compare_op1;
enum cmp_type hppa_branch_type; enum cmp_type hppa_branch_type;
/* Which cpu we are scheduling for. */
enum processor_type pa_cpu;
/* String to hold which cpu we are scheduling for. */
char *pa_cpu_string;
rtx hppa_save_pic_table_rtx; rtx hppa_save_pic_table_rtx;
/* Set by the FUNCTION_PROFILER macro. */ /* Set by the FUNCTION_PROFILER macro. */
...@@ -57,6 +63,34 @@ static rtx find_addr_reg (); ...@@ -57,6 +63,34 @@ static rtx find_addr_reg ();
unsigned int total_code_bytes; unsigned int total_code_bytes;
void
override_options ()
{
/* Default to 700 scheduling which is reasonable for older 800 processors
correct for the 700s, and not too bad for the 7100s and 7100LCs. */
if (pa_cpu_string == NULL
|| ! strcmp (pa_cpu_string, "700"))
{
pa_cpu_string = "700";
pa_cpu = PROCESSOR_700;
}
else if (! strcmp (pa_cpu_string, "7100"))
{
pa_cpu_string = "7100";
pa_cpu = PROCESSOR_7100;
}
else if (! strncmp (pa_cpu_string, "7100LC"))
{
pa_cpu_string = "7100LC";
pa_cpu = PROCESSOR_7100LC;
}
else
{
warning ("Unknown -mschedule= option (%s).\nValid options are 700, 7100 and 7100LC\n", pa_cpu_string);
}
}
/* Return non-zero only if OP is a register of mode MODE, /* Return non-zero only if OP is a register of mode MODE,
or CONST0_RTX. */ or CONST0_RTX. */
int int
...@@ -2498,18 +2532,20 @@ pa_adjust_cost (insn, link, dep_insn, cost) ...@@ -2498,18 +2532,20 @@ pa_adjust_cost (insn, link, dep_insn, cost)
switch (get_attr_type (dep_insn)) switch (get_attr_type (dep_insn))
{ {
case TYPE_FPLOAD: case TYPE_FPLOAD:
/* This cost 3 cycles, not 2 as the md says. */ /* This cost 3 cycles, not 2 as the md says for the
return cost + 1; 700 and 7100. Note scaling of cost for 7100. */
return cost + (pa_cpu_attr == PROCESSOR_700) ? 1 : 2;
case TYPE_FPALU: case TYPE_FPALU:
case TYPE_FPMUL: case TYPE_FPMULSGL:
case TYPE_FPMULDBL:
case TYPE_FPDIVSGL: case TYPE_FPDIVSGL:
case TYPE_FPDIVDBL: case TYPE_FPDIVDBL:
case TYPE_FPSQRTSGL: case TYPE_FPSQRTSGL:
case TYPE_FPSQRTDBL: case TYPE_FPSQRTDBL:
/* In these important cases, we save one cycle compared to /* In these important cases, we save one cycle compared to
when flop instruction feed each other. */ when flop instruction feed each other. */
return cost - 1; return cost - (pa_cpu_attr == PROCESSOR_700) ? 1 : 2;
default: default:
return cost; return cost;
...@@ -2547,16 +2583,52 @@ pa_adjust_cost (insn, link, dep_insn, cost) ...@@ -2547,16 +2583,52 @@ pa_adjust_cost (insn, link, dep_insn, cost)
switch (get_attr_type (dep_insn)) switch (get_attr_type (dep_insn))
{ {
case TYPE_FPALU: case TYPE_FPALU:
case TYPE_FPMUL: case TYPE_FPMULSGL:
case TYPE_FPMULDBL:
case TYPE_FPDIVSGL: case TYPE_FPDIVSGL:
case TYPE_FPDIVDBL: case TYPE_FPDIVDBL:
case TYPE_FPSQRTSGL: case TYPE_FPSQRTSGL:
case TYPE_FPSQRTDBL: case TYPE_FPSQRTDBL:
/* A fpload can't be issued until one cycle before a /* A fpload can't be issued until one cycle before a
preceeding arithmetic operation has finished, if preceeding arithmetic operation has finished if
the target of the fpload is any of the sources the target of the fpload is any of the sources
(or destination) of the arithmetic operation. */ (or destination) of the arithmetic operation. */
return cost - 1; return cost - (pa_cpu_attr == PROCESSOR_700) ? 1 : 2;
default:
return 0;
}
}
}
else if (get_attr_type (insn) == TYPE_FPALU)
{
rtx pat = PATTERN (insn);
rtx dep_pat = PATTERN (dep_insn);
if (GET_CODE (pat) == PARALLEL)
{
/* This happens for the fldXs,mb patterns. */
pat = XVECEXP (pat, 0, 0);
}
if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
/* If this happens, we have to extend this to schedule
optimally. Return 0 for now. */
return 0;
if (reg_mentioned_p (SET_DEST (pat), SET_SRC (dep_pat)))
{
if (! recog_memoized (dep_insn))
return 0;
switch (get_attr_type (dep_insn))
{
case TYPE_FPDIVSGL:
case TYPE_FPDIVDBL:
case TYPE_FPSQRTSGL:
case TYPE_FPSQRTDBL:
/* An ALU flop can't be issued until two cycles before a
preceeding divide or sqrt operation has finished if
the target of the ALU flop is any of the sources
(or destination) of the divide or sqrt operation. */
return cost - (pa_cpu_attr == PROCESSOR_700) ? 2 : 4;
default: default:
return 0; return 0;
...@@ -2567,9 +2639,89 @@ pa_adjust_cost (insn, link, dep_insn, cost) ...@@ -2567,9 +2639,89 @@ pa_adjust_cost (insn, link, dep_insn, cost)
/* For other anti dependencies, the cost is 0. */ /* For other anti dependencies, the cost is 0. */
return 0; return 0;
} }
else if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT)
{
/* Output dependency; DEP_INSN writes a register that INSN writes some
cycles later. */
if (get_attr_type (insn) == TYPE_FPLOAD)
{
rtx pat = PATTERN (insn);
rtx dep_pat = PATTERN (dep_insn);
if (GET_CODE (pat) == PARALLEL)
{
/* This happens for the fldXs,mb patterns. */
pat = XVECEXP (pat, 0, 0);
}
if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
/* If this happens, we have to extend this to schedule
optimally. Return 0 for now. */
return 0;
if (reg_mentioned_p (SET_DEST (pat), SET_DEST (dep_pat)))
{
if (! recog_memoized (dep_insn))
return 0;
switch (get_attr_type (dep_insn))
{
case TYPE_FPALU:
case TYPE_FPMULSGL:
case TYPE_FPMULDBL:
case TYPE_FPDIVSGL:
case TYPE_FPDIVDBL:
case TYPE_FPSQRTSGL:
case TYPE_FPSQRTDBL:
/* A fpload can't be issued until one cycle before a
preceeding arithmetic operation has finished if
the target of the fpload is the destination of the
arithmetic operation. */
return cost - (pa_cpu_attr == PROCESSOR_700) ? 1 : 2;
/* For output dependencies, the cost is often one too high. */ default:
return cost - 1; return 0;
}
}
}
else if (get_attr_type (insn) == TYPE_FPALU)
{
rtx pat = PATTERN (insn);
rtx dep_pat = PATTERN (dep_insn);
if (GET_CODE (pat) == PARALLEL)
{
/* This happens for the fldXs,mb patterns. */
pat = XVECEXP (pat, 0, 0);
}
if (GET_CODE (pat) != SET || GET_CODE (dep_pat) != SET)
/* If this happens, we have to extend this to schedule
optimally. Return 0 for now. */
return 0;
if (reg_mentioned_p (SET_DEST (pat), SET_DEST (dep_pat)))
{
if (! recog_memoized (dep_insn))
return 0;
switch (get_attr_type (dep_insn))
{
case TYPE_FPDIVSGL:
case TYPE_FPDIVDBL:
case TYPE_FPSQRTSGL:
case TYPE_FPSQRTDBL:
/* An ALU flop can't be issued until two cycles before a
preceeding divide or sqrt operation has finished if
the target of the ALU flop is also the target of
of the divide or sqrt operation. */
return cost - (pa_cpu_attr == PROCESSOR_700) ? 2 : 4;
default:
return 0;
}
}
}
/* For other output dependencies, the cost is 0. */
return 0;
}
else
abort ();
} }
/* Return any length adjustment needed by INSN which already has its length /* Return any length adjustment needed by INSN which already has its length
......
...@@ -31,6 +31,21 @@ enum cmp_type /* comparison type */ ...@@ -31,6 +31,21 @@ enum cmp_type /* comparison type */
/* For long call handling. */ /* For long call handling. */
extern unsigned int total_code_bytes; extern unsigned int total_code_bytes;
/* Which processor to schedule for. */
enum processor_type
{
PROCESSOR_700,
PROCESSOR_7100,
PROCESSOR_7100LC,
};
#define pa_cpu_attr ((enum attr_cpu)pa_cpu)
/* For -mschedule= option. */
extern char *pa_cpu_string;
extern enum processor_type pa_cpu;
/* Print subsidiary information on the compiler version in use. */ /* Print subsidiary information on the compiler version in use. */
#define TARGET_VERSION fprintf (stderr, " (hppa)"); #define TARGET_VERSION fprintf (stderr, " (hppa)");
...@@ -123,6 +138,13 @@ extern int target_flags; ...@@ -123,6 +138,13 @@ extern int target_flags;
#define TARGET_DEFAULT 0x88 /* TARGET_GAS + TARGET_JUMP_IN_DELAY */ #define TARGET_DEFAULT 0x88 /* TARGET_GAS + TARGET_JUMP_IN_DELAY */
#endif #endif
#define TARGET_OPTIONS \
{ \
{ "schedule=", &pa_cpu_string }\
}
#define OVERRIDE_OPTIONS override_options ()
#define DBX_DEBUGGING_INFO #define DBX_DEBUGGING_INFO
#define DEFAULT_GDB_EXTENSIONS 1 #define DEFAULT_GDB_EXTENSIONS 1
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment