predicates.md (word_offset_memref_op): Handle cmodel medium addresses.

* config/rs6000/predicates.md (word_offset_memref_op): Handle
	cmodel medium addresses.
	* config/rs6000/rs6000.c (rs6000_secondary_reload): Handle misaligned
	64-bit gpr loads and stores.
	(rs6000_secondary_reload_ppc64): New function.
	* config/rs6000/rs6000-protos.h: Declare it.
	* config/rs6000/rs6000.md (reload_di_store, reload_di_load): New.

From-SVN: r171542
This commit is contained in:
Alan Modra 2011-03-26 16:16:00 +10:30 committed by Alan Modra
parent 2fbb4d751b
commit f082c00037
5 changed files with 118 additions and 2 deletions

View File

@ -1,3 +1,13 @@
2011-03-26 Alan Modra <amodra@gmail.com>
* config/rs6000/predicates.md (word_offset_memref_op): Handle
cmodel medium addresses.
* config/rs6000/rs6000.c (rs6000_secondary_reload): Handle misaligned
64-bit gpr loads and stores.
(rs6000_secondary_reload_ppc64): New function.
* config/rs6000/rs6000-protos.h: Declare it.
* config/rs6000/rs6000.md (reload_di_store, reload_di_load): New.
2011-03-26 Alan Modra <amodra@gmail.com>
PR target/47487

View File

@ -435,9 +435,12 @@
op = XEXP (op, 0);
else if (GET_CODE (op) == PRE_MODIFY)
op = XEXP (op, 1);
else if (GET_CODE (op) == LO_SUM
&& GET_CODE (XEXP (op, 0)) == REG
&& GET_CODE (XEXP (op, 1)) == CONST)
op = XEXP (XEXP (op, 1), 0);
return (GET_CODE (op) != PLUS
|| ! REG_P (XEXP (op, 0))
|| GET_CODE (XEXP (op, 1)) != CONST_INT
|| INTVAL (XEXP (op, 1)) % 4 == 0);
})

View File

@ -79,6 +79,7 @@ extern bool (*rs6000_cannot_change_mode_class_ptr) (enum machine_mode,
enum machine_mode,
enum reg_class);
extern void rs6000_secondary_reload_inner (rtx, rtx, rtx, bool);
extern void rs6000_secondary_reload_ppc64 (rtx, rtx, rtx, bool);
extern int paired_emit_vector_cond_expr (rtx, rtx, rtx,
rtx, rtx, rtx);
extern void paired_expand_vector_move (rtx operands[]);

View File

@ -14816,7 +14816,10 @@ rs6000_reload_register_type (enum reg_class rclass)
needed for the immediate register.
For VSX and Altivec, we may need a register to convert sp+offset into
reg+sp. */
reg+sp.
For misaligned 64-bit gpr loads and stores we need a register to
convert an offset address to indirect. */
static reg_class_t
rs6000_secondary_reload (bool in_p,
@ -14919,6 +14922,34 @@ rs6000_secondary_reload (bool in_p,
else
default_p = true;
}
else if (TARGET_POWERPC64
&& rs6000_reload_register_type (rclass) == GPR_REGISTER_TYPE
&& MEM_P (x)
&& GET_MODE_SIZE (GET_MODE (x)) >= UNITS_PER_WORD)
{
rtx addr = XEXP (x, 0);
if (GET_CODE (addr) == PRE_MODIFY)
addr = XEXP (addr, 1);
else if (GET_CODE (addr) == LO_SUM
&& GET_CODE (XEXP (addr, 0)) == REG
&& GET_CODE (XEXP (addr, 1)) == CONST)
addr = XEXP (XEXP (addr, 1), 0);
if (GET_CODE (addr) == PLUS
&& GET_CODE (XEXP (addr, 1)) == CONST_INT
&& (INTVAL (XEXP (addr, 1)) & 3) != 0)
{
if (in_p)
sri->icode = CODE_FOR_reload_di_load;
else
sri->icode = CODE_FOR_reload_di_store;
sri->extra_cost = 2;
ret = NO_REGS;
}
else
default_p = true;
}
else
default_p = true;
@ -15207,6 +15238,56 @@ rs6000_secondary_reload_inner (rtx reg, rtx mem, rtx scratch, bool store_p)
return;
}
/* Convert reloads involving 64-bit gprs and misaligned offset
addressing to use indirect addressing. */
void
rs6000_secondary_reload_ppc64 (rtx reg, rtx mem, rtx scratch, bool store_p)
{
int regno = true_regnum (reg);
enum reg_class rclass;
rtx addr;
rtx scratch_or_premodify = scratch;
if (TARGET_DEBUG_ADDR)
{
fprintf (stderr, "\nrs6000_secondary_reload_ppc64, type = %s\n",
store_p ? "store" : "load");
fprintf (stderr, "reg:\n");
debug_rtx (reg);
fprintf (stderr, "mem:\n");
debug_rtx (mem);
fprintf (stderr, "scratch:\n");
debug_rtx (scratch);
}
gcc_assert (regno >= 0 && regno < FIRST_PSEUDO_REGISTER);
gcc_assert (GET_CODE (mem) == MEM);
rclass = REGNO_REG_CLASS (regno);
gcc_assert (rclass == GENERAL_REGS || rclass == BASE_REGS);
addr = XEXP (mem, 0);
if (GET_CODE (addr) == PRE_MODIFY)
{
scratch_or_premodify = XEXP (addr, 0);
gcc_assert (REG_P (scratch_or_premodify));
addr = XEXP (addr, 1);
}
gcc_assert (GET_CODE (addr) == PLUS || GET_CODE (addr) == LO_SUM);
rs6000_emit_move (scratch_or_premodify, addr, Pmode);
mem = replace_equiv_address_nv (mem, scratch_or_premodify);
/* Now create the move. */
if (store_p)
emit_insn (gen_rtx_SET (VOIDmode, mem, reg));
else
emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
return;
}
/* Target hook to return the cover classes for Integrated Register Allocator.
Cover classes is a set of non-intersected register classes covering all hard
registers used for register allocation purpose. Any move between two

View File

@ -9645,6 +9645,27 @@
[(set_attr "type" "two,load,store,*,*,*")
(set_attr "length" "8,8,8,8,12,16")])
;; Reload patterns to support gpr load/store with misaligned mem.
(define_expand "reload_di_store"
[(parallel [(match_operand 0 "memory_operand" "=m")
(match_operand 1 "gpc_reg_operand" "r")
(match_operand:DI 2 "register_operand" "=&b")])]
"TARGET_POWERPC64"
{
rs6000_secondary_reload_ppc64 (operands[1], operands[0], operands[2], true);
DONE;
})
(define_expand "reload_di_load"
[(parallel [(match_operand 0 "gpc_reg_operand" "=r")
(match_operand 1 "memory_operand" "m")
(match_operand:DI 2 "register_operand" "=b")])]
"TARGET_POWERPC64"
{
rs6000_secondary_reload_ppc64 (operands[0], operands[1], operands[2], false);
DONE;
})
; ld/std require word-aligned displacements -> 'Y' constraint.
; List Y->r and r->Y before r->r for reload.
(define_insn "*movdf_hardfloat64_mfpgpr"