2013-10-25 Vladimir Makarov <vmakarov@redhat.com>

* config/rs6000/rs6000-protos.h
	(rs6000_secondary_memory_needed_mode): New prototype.
	* config/rs6000/rs6000.c: Include ira.h.
	(TARGET_LRA_P): Redefine.
	(rs6000_legitimate_offset_address_p): Call
	legitimate_constant_pool_address_p in strict mode for LRA.
	(rs6000_legitimate_address_p): Ditto.
	(legitimate_lo_sum_address_p): Add code for LRA.
	Use lra_in_progress.
	(rs6000_emit_move): Add LRA version of code to generate load/store
	of SDmode values.
	(rs6000_secondary_memory_needed_mode): New.
	(rs6000_alloc_sdmode_stack_slot): Do nothing for LRA.
	(rs6000_secondary_reload_class): Return NO_REGS for LRA for
	constants, memory, and FP registers.
	(rs6000_lra_p): New.
	* config/rs6000/rs6000.h (SECONDARY_MEMORY_NEEDED_MODE): New
	macro.
	* config/rs6000/rs6000.opt (mlra): New option.
	* lra-spills.c (lra_final_code_change): Remove useless move insns.

From-SVN: r204079
This commit is contained in:
Vladimir Makarov 2013-10-25 21:06:38 +00:00 committed by Vladimir Makarov
parent 3ff4317f1c
commit 01b1efaa14
6 changed files with 159 additions and 7 deletions

View file

@ -1,3 +1,26 @@
2013-10-25 Vladimir Makarov <vmakarov@redhat.com>
* config/rs6000/rs6000-protos.h
(rs6000_secondary_memory_needed_mode): New prototype.
* config/rs6000/rs6000.c: Include ira.h.
(TARGET_LRA_P): Redefine.
(rs6000_legitimate_offset_address_p): Call
legitimate_constant_pool_address_p in strict mode for LRA.
(rs6000_legitimate_address_p): Ditto.
(legitimate_lo_sum_address_p): Add code for LRA.
Use lra_in_progress.
(rs6000_emit_move): Add LRA version of code to generate load/store
of SDmode values.
(rs6000_secondary_memory_needed_mode): New.
(rs6000_alloc_sdmode_stack_slot): Do nothing for LRA.
(rs6000_secondary_reload_class): Return NO_REGS for LRA for
constants, memory, and FP registers.
(rs6000_lra_p): New.
* config/rs6000/rs6000.h (SECONDARY_MEMORY_NEEDED_MODE): New
macro.
* config/rs6000/rs6000.opt (mlra): New option.
* lra-spills.c (lra_final_code_change): Remove useless move insns.
2013-10-25 Yufeng Zhang <yufeng.zhang@arm.com>
* tree-ssa-math-opts.c (convert_plusminus_to_widen): Call

View file

@ -126,6 +126,8 @@ extern void rs6000_split_multireg_move (rtx, rtx);
extern void rs6000_emit_le_vsx_move (rtx, rtx, enum machine_mode);
extern void rs6000_emit_move (rtx, rtx, enum machine_mode);
extern rtx rs6000_secondary_memory_needed_rtx (enum machine_mode);
extern enum machine_mode rs6000_secondary_memory_needed_mode (enum
machine_mode);
extern rtx (*rs6000_legitimize_reload_address_ptr) (rtx, enum machine_mode,
int, int, int, int *);
extern bool rs6000_legitimate_offset_address_p (enum machine_mode, rtx,

View file

@ -55,6 +55,7 @@
#include "intl.h"
#include "params.h"
#include "tm-constrs.h"
#include "ira.h"
#include "opts.h"
#include "tree-vectorizer.h"
#include "dumpfile.h"
@ -1554,6 +1555,9 @@ static const struct attribute_spec rs6000_attribute_table[] =
#undef TARGET_MODE_DEPENDENT_ADDRESS_P
#define TARGET_MODE_DEPENDENT_ADDRESS_P rs6000_mode_dependent_address_p
#undef TARGET_LRA_P
#define TARGET_LRA_P rs6000_lra_p
#undef TARGET_CAN_ELIMINATE
#define TARGET_CAN_ELIMINATE rs6000_can_eliminate
@ -6226,7 +6230,7 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x,
return false;
if (!reg_offset_addressing_ok_p (mode))
return virtual_stack_registers_memory_p (x);
if (legitimate_constant_pool_address_p (x, mode, strict))
if (legitimate_constant_pool_address_p (x, mode, strict || lra_in_progress))
return true;
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
return false;
@ -6366,19 +6370,31 @@ legitimate_lo_sum_address_p (enum machine_mode mode, rtx x, int strict)
if (TARGET_ELF || TARGET_MACHO)
{
bool large_toc_ok;
if (DEFAULT_ABI != ABI_AIX && DEFAULT_ABI != ABI_DARWIN && flag_pic)
return false;
if (TARGET_TOC)
/* LRA don't use LEGITIMIZE_RELOAD_ADDRESS as it usually calls
push_reload from reload pass code. LEGITIMIZE_RELOAD_ADDRESS
recognizes some LO_SUM addresses as valid although this
function says opposite. In most cases, LRA through different
transformations can generate correct code for address reloads.
It can not manage only some LO_SUM cases. So we need to add
code analogous to one in rs6000_legitimize_reload_address for
LOW_SUM here saying that some addresses are still valid. */
large_toc_ok = (lra_in_progress && TARGET_CMODEL != CMODEL_SMALL
&& small_toc_ref (x, VOIDmode));
if (TARGET_TOC && ! large_toc_ok)
return false;
if (GET_MODE_NUNITS (mode) != 1)
return false;
if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
if (! lra_in_progress && GET_MODE_SIZE (mode) > UNITS_PER_WORD
&& !(/* ??? Assume floating point reg based on mode? */
TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
&& (mode == DFmode || mode == DDmode)))
return false;
return CONSTANT_P (x);
return CONSTANT_P (x) || large_toc_ok;
}
return false;
@ -7368,7 +7384,8 @@ rs6000_legitimate_address_p (enum machine_mode mode, rtx x, bool reg_ok_strict)
if (reg_offset_p && legitimate_small_data_p (mode, x))
return 1;
if (reg_offset_p
&& legitimate_constant_pool_address_p (x, mode, reg_ok_strict))
&& legitimate_constant_pool_address_p (x, mode,
reg_ok_strict || lra_in_progress))
return 1;
/* For TImode, if we have load/store quad and TImode in VSX registers, only
allow register indirect addresses. This will allow the values to go in
@ -7654,6 +7671,7 @@ rs6000_conditional_register_usage (void)
fixed_regs[i] = call_used_regs[i] = call_really_used_regs[i] = 1;
}
}
/* Try to output insns to set TARGET equal to the constant C if it can
be done in less than N insns. Do all computations in MODE.
@ -8058,6 +8076,68 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
cfun->machine->sdmode_stack_slot =
eliminate_regs (cfun->machine->sdmode_stack_slot, VOIDmode, NULL_RTX);
if (lra_in_progress
&& mode == SDmode
&& REG_P (operands[0]) && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER
&& reg_preferred_class (REGNO (operands[0])) == NO_REGS
&& (REG_P (operands[1])
|| (GET_CODE (operands[1]) == SUBREG
&& REG_P (SUBREG_REG (operands[1])))))
{
int regno = REGNO (GET_CODE (operands[1]) == SUBREG
? SUBREG_REG (operands[1]) : operands[1]);
enum reg_class cl;
if (regno >= FIRST_PSEUDO_REGISTER)
{
cl = reg_preferred_class (regno);
gcc_assert (cl != NO_REGS);
regno = ira_class_hard_regs[cl][0];
}
if (FP_REGNO_P (regno))
{
if (GET_MODE (operands[0]) != DDmode)
operands[0] = gen_rtx_SUBREG (DDmode, operands[0], 0);
emit_insn (gen_movsd_store (operands[0], operands[1]));
}
else if (INT_REGNO_P (regno))
emit_insn (gen_movsd_hardfloat (operands[0], operands[1]));
else
gcc_unreachable();
return;
}
if (lra_in_progress
&& mode == SDmode
&& (REG_P (operands[0])
|| (GET_CODE (operands[0]) == SUBREG
&& REG_P (SUBREG_REG (operands[0]))))
&& REG_P (operands[1]) && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER
&& reg_preferred_class (REGNO (operands[1])) == NO_REGS)
{
int regno = REGNO (GET_CODE (operands[0]) == SUBREG
? SUBREG_REG (operands[0]) : operands[0]);
enum reg_class cl;
if (regno >= FIRST_PSEUDO_REGISTER)
{
cl = reg_preferred_class (regno);
gcc_assert (cl != NO_REGS);
regno = ira_class_hard_regs[cl][0];
}
if (FP_REGNO_P (regno))
{
if (GET_MODE (operands[1]) != DDmode)
operands[1] = gen_rtx_SUBREG (DDmode, operands[1], 0);
emit_insn (gen_movsd_load (operands[0], operands[1]));
}
else if (INT_REGNO_P (regno))
emit_insn (gen_movsd_hardfloat (operands[0], operands[1]));
else
gcc_unreachable();
return;
}
if (reload_in_progress
&& mode == SDmode
&& cfun->machine->sdmode_stack_slot != NULL_RTX
@ -14905,6 +14985,17 @@ rs6000_secondary_memory_needed_rtx (enum machine_mode mode)
return ret;
}
/* Return the mode to be used for memory when a secondary memory
location is needed. For SDmode values we need to use DDmode, in
all other cases we can use the same mode. */
enum machine_mode
rs6000_secondary_memory_needed_mode (enum machine_mode mode)
{
if (mode == SDmode)
return DDmode;
return mode;
}
static tree
rs6000_check_sdmode (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
{
@ -15798,6 +15889,10 @@ rs6000_alloc_sdmode_stack_slot (void)
gimple_stmt_iterator gsi;
gcc_assert (cfun->machine->sdmode_stack_slot == NULL_RTX);
/* We use a different approach for dealing with the secondary
memory in LRA. */
if (ira_use_lra_p)
return;
if (TARGET_NO_SDMODE_STACK)
return;
@ -16019,7 +16114,7 @@ rs6000_secondary_reload_class (enum reg_class rclass, enum machine_mode mode,
/* Constants, memory, and FP registers can go into FP registers. */
if ((regno == -1 || FP_REGNO_P (regno))
&& (rclass == FLOAT_REGS || rclass == NON_SPECIAL_REGS))
return (mode != SDmode) ? NO_REGS : GENERAL_REGS;
return (mode != SDmode || lra_in_progress) ? NO_REGS : GENERAL_REGS;
/* Memory, and FP/altivec registers can go into fp/altivec registers under
VSX. However, for scalar variables, use the traditional floating point
@ -29364,6 +29459,13 @@ rs6000_libcall_value (enum machine_mode mode)
}
/* Return true if we use LRA instead of reload pass. */
static bool
rs6000_lra_p (void)
{
return rs6000_lra_flag;
}
/* Given FROM and TO register numbers, say whether this elimination is allowed.
Frame pointer elimination is automatically handled.

View file

@ -1488,6 +1488,13 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX];
#define SECONDARY_MEMORY_NEEDED_RTX(MODE) \
rs6000_secondary_memory_needed_rtx (MODE)
/* Specify the mode to be used for memory when a secondary memory
location is needed. For cpus that cannot load/store SDmode values
from the 64-bit FP registers without using a full 64-bit
load/store, we need a wider mode. */
#define SECONDARY_MEMORY_NEEDED_MODE(MODE) \
rs6000_secondary_memory_needed_mode (MODE)
/* Return the maximum number of consecutive registers
needed to represent mode MODE in a register of class CLASS.

View file

@ -449,6 +449,10 @@ mlong-double-
Target RejectNegative Joined UInteger Var(rs6000_long_double_type_size) Save
-mlong-double-<n> Specify size of long double (64 or 128 bits)
mlra
Target Report Var(rs6000_lra_flag) Init(0) Save
Use LRA instead of reload
msched-costly-dep=
Target RejectNegative Joined Var(rs6000_sched_costly_dep_str)
Determine which dependences between insns are considered costly

View file

@ -625,7 +625,7 @@ lra_final_code_change (void)
{
int i, hard_regno;
basic_block bb;
rtx insn, curr;
rtx insn, curr, set;
int max_regno = max_reg_num ();
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
@ -661,5 +661,19 @@ lra_final_code_change (void)
}
if (insn_change_p)
lra_update_operator_dups (id);
if ((set = single_set (insn)) != NULL
&& REG_P (SET_SRC (set)) && REG_P (SET_DEST (set))
&& REGNO (SET_SRC (set)) == REGNO (SET_DEST (set)))
{
/* Remove an useless move insn. IRA can generate move
insns involving pseudos. It is better remove them
earlier to speed up compiler a bit. It is also
better to do it here as they might not pass final RTL
check in LRA, (e.g. insn moving a control register
into itself). */
lra_invalidate_insn_data (insn);
delete_insn (insn);
}
}
}