From: Alan Modra Date: Sat, 26 Mar 2011 05:46:00 +0000 (+1030) Subject: predicates.md (word_offset_memref_op): Handle cmodel medium addresses. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f082c000379548ab460bd02f94e2986491b72c9e;p=gcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 69d92785ea8..a8fd3f9642b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2011-03-26 Alan Modra + + * 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 PR target/47487 diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index 046f8bca83b..e407eda86b3 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -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); }) diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index d79af36ce04..b7b60c0485f 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -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[]); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index abd09e16d62..b1efc0dc9d3 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -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 diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index dafc2d2a4f9..89836d7d632 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -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"