re PR target/53513 ([SH] Add support for fpchg insn and improve fenv support)

gcc/
	PR target/53513
	* config/sh/sh-protos.h (emit_sf_insn, emit_df_insn, expand_sf_unop,
	expand_sf_binop, expand_df_unop, expand_df_binop): Remove.

	* config/sh/sh.c (sh_emit_set_t_insn): Adjust generated insn pattern
	to match fp insn patterns.
	(calc_live_regs): Add FPSCR_MODES_REG and FPSCR_STAT_REG to the ignore
	list.
	(emit_sf_insn, emit_df_insn, expand_sf_unop, expand_sf_binop,
	expand_df_unop, expand_df_binop): Remove.
	(sh_conditional_register_usage): Mark FPSCR_MODES_REG and
	FPSCR_STAT_REG as not call clobbered.
	(sh_emit_mode_set): Emit fpscr store-modify-load sequence instead of
	invoking fpscr_set_from_mem.

	* config/sh/sh.h (MAX_REGISTER_NAME_LENGTH): Increase to 6.
	(SH_REGISTER_NAMES_INITIALIZER): Add names for FPSCR_MODES_REG and
	FPSCR_STAT_REG.
	(REGISTER_NAMES): Adjust.
	(SPECIAL_REGISTER_P): Add FPSCR_MODES_REG and FPSCR_STAT_REG.
	(FIRST_PSEUDO_REGISTER): Increase to 156.
	(DWARF_FRAME_REGISTERS): Define as 153 to keep the original value.
	(FIXED_REGISTERS, CALL_USED_REGISTERS): Add FPSCR_MODES_REG and
	FPSCR_STAT_REG.
	(REG_CLASS_CONTENTS): Adjust ALL_REGS bit mask to include
	FPSCR_MODES_REG and FPSCR_STAT_REG.
	(REG_ALLOC_ORDER): Add FPSCR_MODES_REG and FPSCR_STAT_REG.

	* config/sh/sh.md (FPSCR_MODES_REG, FPSCR_STAT_REG, FPSCR_PR,
	FPSCR_SZ): Add new constants.
	(UNSPECV_FPSCR_MODES, UNSPECV_FPSCR_STAT): Add new unspecv constants.

	(movpsi): Use TARGET_FPU_ANY condition, invoke gen_fpu_switch.
	(fpu_switch): Add use and set of FPSCR_STAT_REG and FPSCR_MODES_REG.
	Use TARGET_FPU_ANY condition.
	(fpu_switch peephole2): Remove.
	(fpu_switch split): Use simple_mem_operand to capture the mem and
	adjust split implementation.
	(extend_psi_si, truncate_si_psi): New insns.
	(toggle_sz, toggle_pr): Use FPSCR_SZ, FPSCR_PR constants.  Add
	set of FPSCR_MODES_REG.

	(push_e, push_4, pop_e, pop_4, movdf_i4, reload_indf__frn, movsf_ie,
	reload_insf__frn, force_mode_for_call, calli, calli_tbr_rel,
	calli_pcrel, call_pcrel, call_compact, call_compact_rettramp,
	call_valuei, call_valuei_tbr_rel, call_valuei_pcrel, call_value_pcrel,
	call_value_compact, call_value_compact_rettramp, call,
	call_pop_compact, call_pop_compact_rettramp, call_value, sibcalli,
	sibcalli_pcrel, sibcalli_thunk, sibcall_pcrel, sibcall_compact,
	sibcall, sibcall_valuei, sibcall_valuei_pcrel, sibcall_value_pcrel,
	sibcall_value_compact, sibcall_value, call_value_pop_compact,
	call_value_pop_compact_rettramp, various unnamed splits):
	Replace use of FPSCR_REG with use of FPSCR_MODES_REG.  Adjust gen_*
	function uses.

	(floatsisf2_i4, *floatsisf2_ie): Merge into floatsisf2_i4.
	(fix_truncsfsi2_i4, *fixsfsi): Merge into fix_truncsfsi2_i4.
	(cmpgtsf_t, cmpgtsf_t_i4): Merge into cmpgtsf_t.
	(cmpeqsf_t, cmpeqsf_t_i4): Merge into cmpeqsf_t.
	(ieee_ccmpeqsf_t, *ieee_ccmpeqsf_t_4): Merge into ieee_ccmpeqsf_t.

	(udivsi3_i4, divsi3_i4, addsf3_i, subsf3_i, mulsf3_i, fmasf4_i,
	*fmasf4, divsf3_i, floatsisf2_i4, fix_truncsfsi2_i4, cmpgtsf_t,
	cmpeqsf_t, ieee_ccmpeqsf_t, sqrtsf2_i, rsqrtsf2, fsca, adddf3_i,
	subdf3_i, muldf3_i, divdf3_i, floatsidf2_i, fix_truncdfsi2_i,
	cmpgtdf_t, cmpeqdf_t, *ieee_ccmpeqdf_t, sqrtdf2_i, extendsfdf2_i4,
	truncdfsf2_i4): Replace use of FPSCR_REG with clobber of FPSCR_STAT_REG
	and use of FPSCR_MODES_REG.  Adjust gen_* function uses.

gcc/testsuite/
	PR target/53513
	* gcc.target/sh/pr54680.c: Adjust matching of lds insn.

From-SVN: r216307
This commit is contained in:
Oleg Endo 2014-10-16 10:58:36 +00:00
parent c74459ea75
commit 3a2317d15b
7 changed files with 374 additions and 345 deletions

View File

@ -1,3 +1,74 @@
2014-10-16 Oleg Endo <olegendo@gcc.gnu.org>
PR target/53513
* config/sh/sh-protos.h (emit_sf_insn, emit_df_insn, expand_sf_unop,
expand_sf_binop, expand_df_unop, expand_df_binop): Remove.
* config/sh/sh.c (sh_emit_set_t_insn): Adjust generated insn pattern
to match fp insn patterns.
(calc_live_regs): Add FPSCR_MODES_REG and FPSCR_STAT_REG to the ignore
list.
(emit_sf_insn, emit_df_insn, expand_sf_unop, expand_sf_binop,
expand_df_unop, expand_df_binop): Remove.
(sh_conditional_register_usage): Mark FPSCR_MODES_REG and
FPSCR_STAT_REG as not call clobbered.
(sh_emit_mode_set): Emit fpscr store-modify-load sequence instead of
invoking fpscr_set_from_mem.
* config/sh/sh.h (MAX_REGISTER_NAME_LENGTH): Increase to 6.
(SH_REGISTER_NAMES_INITIALIZER): Add names for FPSCR_MODES_REG and
FPSCR_STAT_REG.
(REGISTER_NAMES): Adjust.
(SPECIAL_REGISTER_P): Add FPSCR_MODES_REG and FPSCR_STAT_REG.
(FIRST_PSEUDO_REGISTER): Increase to 156.
(DWARF_FRAME_REGISTERS): Define as 153 to keep the original value.
(FIXED_REGISTERS, CALL_USED_REGISTERS): Add FPSCR_MODES_REG and
FPSCR_STAT_REG.
(REG_CLASS_CONTENTS): Adjust ALL_REGS bit mask to include
FPSCR_MODES_REG and FPSCR_STAT_REG.
(REG_ALLOC_ORDER): Add FPSCR_MODES_REG and FPSCR_STAT_REG.
* config/sh/sh.md (FPSCR_MODES_REG, FPSCR_STAT_REG, FPSCR_PR,
FPSCR_SZ): Add new constants.
(UNSPECV_FPSCR_MODES, UNSPECV_FPSCR_STAT): Add new unspecv constants.
(movpsi): Use TARGET_FPU_ANY condition, invoke gen_fpu_switch.
(fpu_switch): Add use and set of FPSCR_STAT_REG and FPSCR_MODES_REG.
Use TARGET_FPU_ANY condition.
(fpu_switch peephole2): Remove.
(fpu_switch split): Use simple_mem_operand to capture the mem and
adjust split implementation.
(extend_psi_si, truncate_si_psi): New insns.
(toggle_sz, toggle_pr): Use FPSCR_SZ, FPSCR_PR constants. Add
set of FPSCR_MODES_REG.
(push_e, push_4, pop_e, pop_4, movdf_i4, reload_indf__frn, movsf_ie,
reload_insf__frn, force_mode_for_call, calli, calli_tbr_rel,
calli_pcrel, call_pcrel, call_compact, call_compact_rettramp,
call_valuei, call_valuei_tbr_rel, call_valuei_pcrel, call_value_pcrel,
call_value_compact, call_value_compact_rettramp, call,
call_pop_compact, call_pop_compact_rettramp, call_value, sibcalli,
sibcalli_pcrel, sibcalli_thunk, sibcall_pcrel, sibcall_compact,
sibcall, sibcall_valuei, sibcall_valuei_pcrel, sibcall_value_pcrel,
sibcall_value_compact, sibcall_value, call_value_pop_compact,
call_value_pop_compact_rettramp, various unnamed splits):
Replace use of FPSCR_REG with use of FPSCR_MODES_REG. Adjust gen_*
function uses.
(floatsisf2_i4, *floatsisf2_ie): Merge into floatsisf2_i4.
(fix_truncsfsi2_i4, *fixsfsi): Merge into fix_truncsfsi2_i4.
(cmpgtsf_t, cmpgtsf_t_i4): Merge into cmpgtsf_t.
(cmpeqsf_t, cmpeqsf_t_i4): Merge into cmpeqsf_t.
(ieee_ccmpeqsf_t, *ieee_ccmpeqsf_t_4): Merge into ieee_ccmpeqsf_t.
(udivsi3_i4, divsi3_i4, addsf3_i, subsf3_i, mulsf3_i, fmasf4_i,
*fmasf4, divsf3_i, floatsisf2_i4, fix_truncsfsi2_i4, cmpgtsf_t,
cmpeqsf_t, ieee_ccmpeqsf_t, sqrtsf2_i, rsqrtsf2, fsca, adddf3_i,
subdf3_i, muldf3_i, divdf3_i, floatsidf2_i, fix_truncdfsi2_i,
cmpgtdf_t, cmpeqdf_t, *ieee_ccmpeqdf_t, sqrtdf2_i, extendsfdf2_i4,
truncdfsf2_i4): Replace use of FPSCR_REG with clobber of FPSCR_STAT_REG
and use of FPSCR_MODES_REG. Adjust gen_* function uses.
2014-10-16 Martin Liska <mliska@suse.cz>
Jan Hubicka <hubicka@ucw.cz>

View File

@ -112,8 +112,6 @@ extern bool sh_legitimate_index_p (enum machine_mode, rtx, bool, bool);
extern bool sh_legitimize_reload_address (rtx *, enum machine_mode, int, int);
extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
extern bool nonpic_symbol_mentioned_p (rtx);
extern void emit_sf_insn (rtx);
extern void emit_df_insn (rtx);
extern void output_pic_addr_const (FILE *, rtx);
extern bool expand_block_move (rtx *);
extern void prepare_move_operands (rtx[], enum machine_mode mode);
@ -150,10 +148,6 @@ extern void final_prescan_insn (rtx_insn *, rtx *, int);
extern enum tls_model tls_symbolic_operand (rtx, enum machine_mode);
extern bool system_reg_operand (rtx, enum machine_mode);
extern bool reg_unused_after (rtx, rtx_insn *);
extern void expand_sf_unop (rtx (*)(rtx, rtx, rtx), rtx *);
extern void expand_sf_binop (rtx (*)(rtx, rtx, rtx, rtx), rtx *);
extern void expand_df_unop (rtx (*)(rtx, rtx, rtx), rtx *);
extern void expand_df_binop (rtx (*)(rtx, rtx, rtx, rtx), rtx *);
extern int sh_insn_length_adjustment (rtx_insn *);
extern bool sh_can_redirect_branch (rtx_insn *, rtx_insn *);
extern void sh_expand_unop_v2sf (enum rtx_code, rtx, rtx);

View File

@ -2281,20 +2281,20 @@ sh_eval_treg_value (rtx op)
return t ^ (cmpval == cmpop);
}
/* Emit INSN, possibly in a PARALLEL with an USE of fpscr for SH4. */
/* Emit INSN, possibly in a PARALLEL with an USE/CLOBBER of FPSCR bits in case
of floating-point comparisons. */
static void
sh_emit_set_t_insn (rtx insn, enum machine_mode mode)
{
if ((TARGET_SH4 || TARGET_SH2A) && GET_MODE_CLASS (mode) == MODE_FLOAT)
if (TARGET_FPU_ANY && GET_MODE_CLASS (mode) == MODE_FLOAT
&& GET_CODE (insn) != PARALLEL)
{
insn = gen_rtx_PARALLEL (VOIDmode,
gen_rtvec (2, insn,
gen_rtx_USE (VOIDmode, get_fpscr_rtx ())));
(mode == SFmode ? emit_sf_insn : emit_df_insn) (insn);
gen_rtvec (3, insn,
gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, FPSCR_STAT_REG)),
gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, FPSCR_MODES_REG))));
}
else
emit_insn (insn);
emit_insn (insn);
}
/* Prepare the operands for an scc instruction; make sure that the
@ -7250,6 +7250,7 @@ calc_live_regs (HARD_REG_SET *live_regs_mask)
&& reg != STACK_POINTER_REGNUM && reg != ARG_POINTER_REGNUM
&& reg != RETURN_ADDRESS_POINTER_REGNUM
&& reg != T_REG && reg != GBR_REG
&& reg != FPSCR_MODES_REG && reg != FPSCR_STAT_REG
/* Push fpscr only on targets which have FPU */
&& (reg != FPSCR_REG || TARGET_FPU_ANY))
: (/* Only push those regs which are used and need to be saved. */
@ -10070,44 +10071,6 @@ emit_fpu_switch (rtx scratch, int index)
dst = get_fpscr_rtx ();
emit_move_insn (dst, src);
}
void
emit_sf_insn (rtx pat)
{
emit_insn (pat);
}
void
emit_df_insn (rtx pat)
{
emit_insn (pat);
}
void
expand_sf_unop (rtx (*fun) (rtx, rtx, rtx), rtx *operands)
{
emit_sf_insn ((*fun) (operands[0], operands[1], get_fpscr_rtx ()));
}
void
expand_sf_binop (rtx (*fun) (rtx, rtx, rtx, rtx), rtx *operands)
{
emit_sf_insn ((*fun) (operands[0], operands[1], operands[2],
get_fpscr_rtx ()));
}
void
expand_df_unop (rtx (*fun) (rtx, rtx, rtx), rtx *operands)
{
emit_df_insn ((*fun) (operands[0], operands[1], get_fpscr_rtx ()));
}
void
expand_df_binop (rtx (*fun) (rtx, rtx, rtx, rtx), rtx *operands)
{
emit_df_insn ((*fun) (operands[0], operands[1], operands[2],
get_fpscr_rtx ()));
}
static rtx get_free_reg (HARD_REG_SET);
@ -13308,6 +13271,9 @@ sh_conditional_register_usage (void)
for (regno = FIRST_GENERAL_REG; regno <= LAST_GENERAL_REG; regno++)
if (! fixed_regs[regno] && call_really_used_regs[regno])
SET_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], regno);
call_really_used_regs[FPSCR_MODES_REG] = 0;
call_really_used_regs[FPSCR_STAT_REG] = 0;
}
/* Implement TARGET_LEGITIMATE_CONSTANT_P
@ -13659,7 +13625,7 @@ sh_try_omit_signzero_extend (rtx extended_op, rtx insn)
static void
sh_emit_mode_set (int entity ATTRIBUTE_UNUSED, int mode,
int prev_mode, HARD_REG_SET regs_live)
int prev_mode, HARD_REG_SET regs_live ATTRIBUTE_UNUSED)
{
if ((TARGET_SH4A_FP || TARGET_SH4_300)
&& prev_mode != FP_MODE_NONE && prev_mode != mode)
@ -13668,8 +13634,36 @@ sh_emit_mode_set (int entity ATTRIBUTE_UNUSED, int mode,
if (TARGET_FMOVD)
emit_insn (gen_toggle_sz ());
}
else
fpscr_set_from_mem (mode, regs_live);
else if (mode != FP_MODE_NONE)
{
rtx tmp0 = gen_reg_rtx (PSImode);
rtx tmp1 = gen_reg_rtx (SImode);
emit_move_insn (tmp0, get_fpscr_rtx ());
emit_insn (gen_extend_psi_si (tmp1, tmp0));
rtx i = NULL;
const unsigned HOST_WIDE_INT fpbits =
TARGET_FMOVD ? (FPSCR_PR | FPSCR_SZ) : FPSCR_PR;
if (prev_mode != FP_MODE_NONE && prev_mode != mode)
i = gen_xorsi3 (tmp1, tmp1,
force_reg (SImode, GEN_INT (fpbits)));
else if (mode == FP_MODE_SINGLE)
i = gen_andsi3 (tmp1, tmp1,
force_reg (SImode, GEN_INT (~fpbits)));
else if (mode == FP_MODE_DOUBLE)
i = gen_iorsi3 (tmp1, tmp1,
force_reg (SImode, GEN_INT (fpbits)));
else
gcc_unreachable ();
emit_insn (i);
emit_insn (gen_truncate_si_psi (tmp0, tmp1));
emit_move_insn (get_fpscr_rtx (), tmp0);
}
}
static int

View File

@ -574,7 +574,7 @@ extern enum sh_divide_strategy_e sh_div_strategy;
fr4..fr11 fp args in
fr12..fr15 call saved floating point registers */
#define MAX_REGISTER_NAME_LENGTH 5
#define MAX_REGISTER_NAME_LENGTH 6
extern char sh_register_names[][MAX_REGISTER_NAME_LENGTH + 1];
#define SH_REGISTER_NAMES_INITIALIZER \
@ -598,7 +598,7 @@ extern char sh_register_names[][MAX_REGISTER_NAME_LENGTH + 1];
"tr0", "tr1", "tr2", "tr3", "tr4", "tr5", "tr6", "tr7", \
"xd0", "xd2", "xd4", "xd6", "xd8", "xd10", "xd12", "xd14", \
"gbr", "ap", "pr", "t", "mach", "macl", "fpul", "fpscr", \
"rap", "sfp" \
"rap", "sfp", "fpscr0", "fpscr1" \
}
#define REGNAMES_ARR_INDEX_1(index) \
@ -623,7 +623,7 @@ extern char sh_register_names[][MAX_REGISTER_NAME_LENGTH + 1];
REGNAMES_ARR_INDEX_8 (128), \
REGNAMES_ARR_INDEX_8 (136), \
REGNAMES_ARR_INDEX_8 (144), \
REGNAMES_ARR_INDEX_2 (152) \
REGNAMES_ARR_INDEX_4 (152) \
}
#define ADDREGNAMES_SIZE 32
@ -711,7 +711,8 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
#define SPECIAL_REGISTER_P(REGNO) \
((REGNO) == GBR_REG || (REGNO) == T_REG \
|| (REGNO) == MACH_REG || (REGNO) == MACL_REG)
|| (REGNO) == MACH_REG || (REGNO) == MACL_REG \
|| (REGNO) == FPSCR_MODES_REG || (REGNO) == FPSCR_STAT_REG)
#define TARGET_REGISTER_P(REGNO) \
((int) (REGNO) >= FIRST_TARGET_REG && (int) (REGNO) <= LAST_TARGET_REG)
@ -738,10 +739,10 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
? DImode \
: SImode)
#define FIRST_PSEUDO_REGISTER 154
#define FIRST_PSEUDO_REGISTER 156
/* Don't count soft frame pointer. */
#define DWARF_FRAME_REGISTERS (FIRST_PSEUDO_REGISTER - 1)
#define DWARF_FRAME_REGISTERS (153)
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator.
@ -777,8 +778,8 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
0, 0, 0, 0, 0, 0, 0, 0, \
/*"gbr", "ap", "pr", "t", "mach", "macl", "fpul", "fpscr", */ \
1, 1, 1, 1, 1, 1, 0, 1, \
/*"rap", "sfp" */ \
1, 1, \
/*"rap", "sfp","fpscr0","fpscr1" */ \
1, 1, 1, 1, \
}
/* 1 for registers not available across function calls.
@ -816,8 +817,8 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
1, 1, 1, 1, 1, 1, 0, 0, \
/*"gbr", "ap", "pr", "t", "mach", "macl", "fpul", "fpscr", */ \
1, 1, 1, 1, 1, 1, 1, 1, \
/*"rap", "sfp" */ \
1, 1, \
/*"rap", "sfp","fpscr0","fpscr1" */ \
1, 1, 1, 1, \
}
/* TARGET_CONDITIONAL_REGISTER_USAGE might want to make a register
@ -1072,7 +1073,7 @@ enum reg_class
/* TARGET_REGS: */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000ff }, \
/* ALL_REGS: */ \
{ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x03ffffff }, \
{ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0fffffff }, \
}
/* The same information, inverted:
@ -1122,7 +1123,7 @@ extern enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER];
128,129,130,131,132,133,134,135, \
/* Fixed registers */ \
15, 16, 24, 25, 26, 27, 63,144, \
145,146,147,148,149,152,153 }
145,146,147,148,149,152,153,154,155 }
/* The class value for index registers, and the one for base regs. */
#define INDEX_REG_CLASS \

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,8 @@
2014-10-16 Oleg Endo <olegendo@gcc.gnu.org>
PR target/53513
* gcc.target/sh/pr54680.c: Adjust matching of lds insn.
2014-10-16 Martin Liska <mliska@suse.cz>
Jan Hubicka <hubicka@ucw.cz>
@ -45,7 +50,7 @@
* gcc.target/i386/bmi-2.c: Likewise.
* gcc.target/i386/pr56564-2.c: Likewise.
2014-10-16 Richard Biener <rguenther@suse.de>i
2014-10-16 Richard Biener <rguenther@suse.de>
PR tree-optimization/63168
* gcc.dg/tree-ssa/loop-40.c: New testcase.

View File

@ -6,7 +6,7 @@
/* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2*" "-m3*" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */
/* { dg-final { scan-assembler-times "fsca" 7 } } */
/* { dg-final { scan-assembler-times "shad" 1 } } */
/* { dg-final { scan-assembler-times "lds\t" 6 } } */
/* { dg-final { scan-assembler-times "lds\tr\[0-9\],fpul" 6 } } */
/* { dg-final { scan-assembler-times "fmul" 2 } } */
/* { dg-final { scan-assembler-times "ftrc" 1 } } */