sparc.c: Include tree-pass.h.

* config/sparc/sparc.c: Include tree-pass.h.
	(TARGET_MACHINE_DEPENDENT_REORG): Do not redefine.
	(sparc_reorg): Rename to sparc_do_work_around_errata.  Move to
	head of file.  Change return type.  Split off gate function.
	(sparc_gate_work_around_errata): New function.
	(pass_work_around_errata): New pass definition.
	(insert_pass_work_around_errata) New pass insert definition to
	insert pass_work_around_errata just after delayed-branch scheduling.
	(sparc_option_override): Insert the pass.
	* config/sparc/t-sparc (sparc.o): Add TREE_PASS_H dependence.

From-SVN: r197681
This commit is contained in:
Steven Bosscher 2013-04-10 21:03:44 +00:00
parent 89deeb3b7e
commit 0ea8a6f9c7
3 changed files with 152 additions and 106 deletions

View File

@ -1,3 +1,16 @@
2013-04-10 Steven Bosscher <steven@gcc.gnu.org>
* config/sparc/sparc.c: Include tree-pass.h.
(TARGET_MACHINE_DEPENDENT_REORG): Do not redefine.
(sparc_reorg): Rename to sparc_do_work_around_errata. Move to
head of file. Change return type. Split off gate function.
(sparc_gate_work_around_errata): New function.
(pass_work_around_errata): New pass definition.
(insert_pass_work_around_errata) New pass insert definition to
insert pass_work_around_errata just after delayed-branch scheduling.
(sparc_option_override): Insert the pass.
* config/sparc/t-sparc (sparc.o): Add TREE_PASS_H dependence.
2013-04-10 David S. Miller <davem@davemloft.net>
* config/sparc/sparc.h (ASM_CPU_SPEC): Pass -Av8 if -mcpu=supersparc

View File

@ -52,6 +52,7 @@ along with GCC; see the file COPYING3. If not see
#include "params.h"
#include "df.h"
#include "opts.h"
#include "tree-pass.h"
/* Processor costs */
@ -538,7 +539,6 @@ static void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
HOST_WIDE_INT, tree);
static bool sparc_can_output_mi_thunk (const_tree, HOST_WIDE_INT,
HOST_WIDE_INT, const_tree);
static void sparc_reorg (void);
static struct machine_function * sparc_init_machine_status (void);
static bool sparc_cannot_force_const_mem (enum machine_mode, rtx);
static rtx sparc_tls_get_addr (void);
@ -681,9 +681,6 @@ char sparc_hard_reg_printed[8];
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK sparc_can_output_mi_thunk
#undef TARGET_MACHINE_DEPENDENT_REORG
#define TARGET_MACHINE_DEPENDENT_REORG sparc_reorg
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS sparc_rtx_costs
#undef TARGET_ADDRESS_COST
@ -808,6 +805,136 @@ char sparc_hard_reg_printed[8];
struct gcc_target targetm = TARGET_INITIALIZER;
/* We use a machine specific pass to enable workarounds for errata.
We need to have the (essentially) final form of the insn stream in order
to properly detect the various hazards. Therefore, this machine specific
pass runs as late as possible. The pass is inserted in the pass pipeline
at the end of sparc_options_override. */
static bool
sparc_gate_work_around_errata (void)
{
/* The only erratum we handle for now is that of the AT697F processor. */
return sparc_fix_at697f != 0;
}
static unsigned int
sparc_do_work_around_errata (void)
{
rtx insn, next;
/* Now look for specific patterns in the insn stream. */
for (insn = get_insns (); insn; insn = next)
{
bool insert_nop = false;
rtx set;
/* Look for a single-word load into an odd-numbered FP register. */
if (NONJUMP_INSN_P (insn)
&& (set = single_set (insn)) != NULL_RTX
&& GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4
&& MEM_P (SET_SRC (set))
&& REG_P (SET_DEST (set))
&& REGNO (SET_DEST (set)) > 31
&& REGNO (SET_DEST (set)) % 2 != 0)
{
/* The wrong dependency is on the enclosing double register. */
unsigned int x = REGNO (SET_DEST (set)) - 1;
unsigned int src1, src2, dest;
int code;
/* If the insn has a delay slot, then it cannot be problematic. */
next = next_active_insn (insn);
if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
code = -1;
else
{
extract_insn (next);
code = INSN_CODE (next);
}
switch (code)
{
case CODE_FOR_adddf3:
case CODE_FOR_subdf3:
case CODE_FOR_muldf3:
case CODE_FOR_divdf3:
dest = REGNO (recog_data.operand[0]);
src1 = REGNO (recog_data.operand[1]);
src2 = REGNO (recog_data.operand[2]);
if (src1 != src2)
{
/* Case [1-4]:
ld [address], %fx+1
FPOPd %f{x,y}, %f{y,x}, %f{x,y} */
if ((src1 == x || src2 == x)
&& (dest == src1 || dest == src2))
insert_nop = true;
}
else
{
/* Case 5:
ld [address], %fx+1
FPOPd %fx, %fx, %fx */
if (src1 == x
&& dest == src1
&& (code == CODE_FOR_adddf3 || code == CODE_FOR_muldf3))
insert_nop = true;
}
break;
case CODE_FOR_sqrtdf2:
dest = REGNO (recog_data.operand[0]);
src1 = REGNO (recog_data.operand[1]);
/* Case 6:
ld [address], %fx+1
fsqrtd %fx, %fx */
if (src1 == x && dest == src1)
insert_nop = true;
break;
default:
break;
}
}
else
next = NEXT_INSN (insn);
if (insert_nop)
emit_insn_after (gen_nop (), insn);
}
return 0;
}
struct rtl_opt_pass pass_work_around_errata =
{
{
RTL_PASS,
"errata", /* name */
OPTGROUP_NONE, /* optinfo_flags */
sparc_gate_work_around_errata, /* gate */
sparc_do_work_around_errata, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
TV_MACH_DEP, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_verify_rtl_sharing, /* todo_flags_finish */
}
};
struct register_pass_info insert_pass_work_around_errata =
{
&pass_work_around_errata.pass, /* pass */
"dbr", /* reference_pass_name */
1, /* ref_pass_instance_number */
PASS_POS_INSERT_AFTER /* po_op */
};
/* Helpers for TARGET_DEBUG_OPTIONS. */
static void
dump_target_flag_bits (const int flags)
{
@ -1245,6 +1372,13 @@ sparc_option_override (void)
pessimizes for double floating-point registers. */
if (!global_options_set.x_flag_ira_share_save_slots)
flag_ira_share_save_slots = 0;
/* We register a machine specific pass to work around errata, if any.
The pass mut be scheduled as late as possible so that we have the
(essentially) final form of the insn stream to work on.
Registering the pass must be done at start up. It's convenient to
do it here. */
register_pass (&insert_pass_work_around_errata);
}
/* Miscellaneous utilities. */
@ -10906,107 +11040,6 @@ sparc_can_output_mi_thunk (const_tree thunk_fndecl ATTRIBUTE_UNUSED,
return (vcall_offset >= -32768 || ! fixed_regs[5]);
}
/* We use the machine specific reorg pass to enable workarounds for errata. */
static void
sparc_reorg (void)
{
rtx insn, next;
/* The only erratum we handle for now is that of the AT697F processor. */
if (!sparc_fix_at697f)
return;
/* We need to have the (essentially) final form of the insn stream in order
to properly detect the various hazards. Run delay slot scheduling. */
if (optimize > 0 && flag_delayed_branch)
{
cleanup_barriers ();
dbr_schedule (get_insns ());
}
/* Now look for specific patterns in the insn stream. */
for (insn = get_insns (); insn; insn = next)
{
bool insert_nop = false;
rtx set;
/* Look for a single-word load into an odd-numbered FP register. */
if (NONJUMP_INSN_P (insn)
&& (set = single_set (insn)) != NULL_RTX
&& GET_MODE_SIZE (GET_MODE (SET_SRC (set))) == 4
&& MEM_P (SET_SRC (set))
&& REG_P (SET_DEST (set))
&& REGNO (SET_DEST (set)) > 31
&& REGNO (SET_DEST (set)) % 2 != 0)
{
/* The wrong dependency is on the enclosing double register. */
unsigned int x = REGNO (SET_DEST (set)) - 1;
unsigned int src1, src2, dest;
int code;
/* If the insn has a delay slot, then it cannot be problematic. */
next = next_active_insn (insn);
if (NONJUMP_INSN_P (next) && GET_CODE (PATTERN (next)) == SEQUENCE)
code = -1;
else
{
extract_insn (next);
code = INSN_CODE (next);
}
switch (code)
{
case CODE_FOR_adddf3:
case CODE_FOR_subdf3:
case CODE_FOR_muldf3:
case CODE_FOR_divdf3:
dest = REGNO (recog_data.operand[0]);
src1 = REGNO (recog_data.operand[1]);
src2 = REGNO (recog_data.operand[2]);
if (src1 != src2)
{
/* Case [1-4]:
ld [address], %fx+1
FPOPd %f{x,y}, %f{y,x}, %f{x,y} */
if ((src1 == x || src2 == x)
&& (dest == src1 || dest == src2))
insert_nop = true;
}
else
{
/* Case 5:
ld [address], %fx+1
FPOPd %fx, %fx, %fx */
if (src1 == x
&& dest == src1
&& (code == CODE_FOR_adddf3 || code == CODE_FOR_muldf3))
insert_nop = true;
}
break;
case CODE_FOR_sqrtdf2:
dest = REGNO (recog_data.operand[0]);
src1 = REGNO (recog_data.operand[1]);
/* Case 6:
ld [address], %fx+1
fsqrtd %fx, %fx */
if (src1 == x && dest == src1)
insert_nop = true;
break;
default:
break;
}
}
else
next = NEXT_INSN (insn);
if (insert_nop)
emit_insn_after (gen_nop (), insn);
}
}
/* How to allocate a 'struct machine_function'. */
static struct machine_function *

View File

@ -23,7 +23,7 @@ sparc.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
insn-codes.h conditions.h output.h $(INSN_ATTR_H) $(FLAGS_H) \
$(FUNCTION_H) $(EXCEPT_H) $(EXPR_H) $(OPTABS_H) $(RECOG_H) \
$(DIAGNOSTIC_CORE_H) $(GGC_H) $(TM_P_H) debug.h $(TARGET_H) \
$(TARGET_DEF_H) $(COMMON_TARGET_H) $(GIMPLE_H) \
$(TARGET_DEF_H) $(COMMON_TARGET_H) $(GIMPLE_H) $(TREE_PASS_H) \
langhooks.h reload.h $(PARAMS_H) $(DF_H) $(OPTS_H) \
gt-sparc.h