predicates.md (word_offset_memref_op): Handle cmodel medium addresses.
authorAlan Modra <amodra@gmail.com>
Sat, 26 Mar 2011 05:46:00 +0000 (16:16 +1030)
committerAlan Modra <amodra@gcc.gnu.org>
Sat, 26 Mar 2011 05:46:00 +0000 (16:16 +1030)
* 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

gcc/ChangeLog
gcc/config/rs6000/predicates.md
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md

index 69d92785ea84324f0bdca4915b9b81c6a75836cc..a8fd3f9642b073d2a6a897945bfe1cbb17e8602b 100644 (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
index 046f8bca83b4ac7180a5eae61052cff2f8f0dd61..e407eda86b3c30139b5806deed5d1b5d4fe0448a 100644 (file)
     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);
 })
index d79af36ce04d3dd1b024ee57532703622ea553a3..b7b60c0485f117272d0fde89d1f1bfcd88f94427 100644 (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[]);
index abd09e16d625f38eee3a0d9919bd8f67184696b1..b1efc0dc9d332d07f50b4c6382cf31aef464a3a9 100644 (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
index dafc2d2a4f9dfaa04923e6c96d48568058fc7bbe..89836d7d63213990a49562cff5066996a2d6d193 100644 (file)
   [(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"