]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
s390.h (SECONDARY_OUTPUT_RELOAD_CLASS): Define.
authorUlrich Weigand <uweigand@de.ibm.com>
Fri, 27 Jun 2003 21:10:17 +0000 (21:10 +0000)
committerUlrich Weigand <uweigand@gcc.gnu.org>
Fri, 27 Jun 2003 21:10:17 +0000 (21:10 +0000)
gcc/ChangeLog:

* config/s390/s390.h (SECONDARY_OUTPUT_RELOAD_CLASS): Define.
* config/s390/s390.c (s390_secondary_output_reload_class): New function.
* config/s390/s390-protos.h (s390_secondary_output_reload_class):
Declare it.
* config/s390/s390.md ("reload_outti", "reload_outdi",
"reload_outdf"): New expanders.

* config/s390/s390.md ("movti" + splitters): Handle non-offsettable
memory operands as source.
("movdi" + splitters): Likewise.
("movdf" + splitters): Likewise.
* config/s390/s390.c (s390_split_ok_p): New function.
* config/s390/s390-protos.h (s390_split_ok_p): Declare it.

gcc/testsuite/ChangeLog:

* gcc.dg/20030627-1.c: New test.

From-SVN: r68607

gcc/ChangeLog
gcc/config/s390/s390-protos.h
gcc/config/s390/s390.c
gcc/config/s390/s390.h
gcc/config/s390/s390.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/20030627-1.c [new file with mode: 0644]

index 240105dcba1887d177bb154c776780185f392a61..8a6872fc14e23a94fbc2673d8259b0b60daa5353 100644 (file)
@@ -1,3 +1,19 @@
+2003-06-27  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * config/s390/s390.h (SECONDARY_OUTPUT_RELOAD_CLASS): Define.
+       * config/s390/s390.c (s390_secondary_output_reload_class): New function.
+       * config/s390/s390-protos.h (s390_secondary_output_reload_class): 
+       Declare it.
+       * config/s390/s390.md ("reload_outti", "reload_outdi", 
+       "reload_outdf"): New expanders.
+
+       * config/s390/s390.md ("movti" + splitters): Handle non-offsettable
+       memory operands as source.
+       ("movdi" + splitters): Likewise.
+       ("movdf" + splitters): Likewise.
+       * config/s390/s390.c (s390_split_ok_p): New function.
+       * config/s390/s390-protos.h (s390_split_ok_p): Declare it.
+
 2003-06-27  Kazu Hirata  <kazu@cs.umass.edu>
 
        * combine.c (force_to_mode): Replace the equality comparison
index e241f282e52dfb12e5922c375649faf8bed12d3a..c33018f3a3119d8e54abe0e41169a875077fa1c1 100644 (file)
@@ -42,6 +42,7 @@ extern int s390_single_hi PARAMS ((rtx, enum machine_mode, int));
 extern int s390_extract_hi PARAMS ((rtx, enum machine_mode, int));
 extern int s390_single_qi PARAMS ((rtx, enum machine_mode, int));
 extern int s390_extract_qi PARAMS ((rtx, enum machine_mode, int));
+extern bool s390_split_ok_p PARAMS ((rtx, rtx, enum machine_mode, int));
 extern int tls_symbolic_operand PARAMS ((rtx));
 
 extern int s390_match_ccmode PARAMS ((rtx, enum machine_mode));
@@ -60,6 +61,7 @@ extern rtx legitimize_pic_address PARAMS ((rtx, rtx));
 extern rtx legitimize_address PARAMS ((rtx, rtx, enum machine_mode));
 extern enum reg_class s390_preferred_reload_class PARAMS ((rtx, enum reg_class));
 extern enum reg_class s390_secondary_input_reload_class PARAMS ((enum reg_class, enum machine_mode, rtx));
+extern enum reg_class s390_secondary_output_reload_class PARAMS ((enum reg_class, enum machine_mode, rtx));
 extern int s390_plus_operand PARAMS ((rtx, enum machine_mode));
 extern void s390_expand_plus_operand PARAMS ((rtx, rtx, rtx));
 extern void emit_symbolic_move PARAMS ((rtx *));
index 4f0dd02542c6111af65808ac588c75aed66ffca0..dc02d229153318cdb114ca7d280e5822de353e89 100644 (file)
@@ -863,6 +863,42 @@ s390_extract_qi (op, mode, part)
   abort ();
 }
 
+/* Check whether we can (and want to) split a double-word 
+   move in mode MODE from SRC to DST into two single-word 
+   moves, moving the subword FIRST_SUBWORD first.  */
+
+bool
+s390_split_ok_p (dst, src, mode, first_subword)
+     rtx dst;
+     rtx src;
+     enum machine_mode mode;
+     int first_subword;
+{
+  /* Floating point registers cannot be split.  */
+  if (FP_REG_P (src) || FP_REG_P (dst))
+    return false;
+
+  /* We don't need to split if operands are directly accessable.  */
+  if (s_operand (src, mode) || s_operand (dst, mode))
+    return false;
+
+  /* Non-offsettable memory references cannot be split.  */
+  if ((GET_CODE (src) == MEM && !offsettable_memref_p (src))
+      || (GET_CODE (dst) == MEM && !offsettable_memref_p (dst)))
+    return false;
+
+  /* Moving the first subword must not clobber a register
+     needed to move the second subword.  */
+  if (register_operand (dst, mode))
+    {
+      rtx subreg = operand_subword (dst, first_subword, 0, mode);
+      if (reg_overlap_mentioned_p (subreg, src))
+        return false;
+    }
+
+  return true;
+}
+
 
 /* Change optimizations to be performed, depending on the 
    optimization level.
@@ -1715,6 +1751,29 @@ s390_secondary_input_reload_class (class, mode, in)
   return NO_REGS;
 }
 
+/* Return the register class of a scratch register needed to
+   store a register of class CLASS in MODE into OUT:
+
+   We need a temporary when storing a double-word to a 
+   non-offsettable memory address.  */
+
+enum reg_class
+s390_secondary_output_reload_class (class, mode, out)
+     enum reg_class class;
+     enum machine_mode mode;
+     rtx out;
+{
+  if ((TARGET_64BIT ? mode == TImode
+                    : (mode == DImode || mode == DFmode))
+      && reg_classes_intersect_p (GENERAL_REGS, class)
+      && GET_CODE (out) == MEM
+      && !offsettable_memref_p (out)
+      && !s_operand (out, VOIDmode))
+    return ADDR_REGS;
+
+  return NO_REGS;
+}
+
 /* Return true if OP is a PLUS that is not a legitimate
    operand for the LA instruction. 
    OP is the current operation.
index e0e5901a1ce755ed1b32e301a9b23ae64e22d6ee..7848d7d971f5ac483eda820ba790be31bb8951c7 100644 (file)
@@ -460,6 +460,11 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
 #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, IN)  \
   s390_secondary_input_reload_class ((CLASS), (MODE), (IN))
 
+/* We need a secondary reload when storing a double-word
+   to a non-offsettable memory address.  */
+#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, OUT)        \
+  s390_secondary_output_reload_class ((CLASS), (MODE), (OUT))
+
 /* We need secondary memory to move data between GPRs and FPRs.  */
 #define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
  ((CLASS1) != (CLASS2) && ((CLASS1) == FP_REGS || (CLASS2) == FP_REGS))
index 244fbc3292346efb8ae6281f6b1dc1eb4ac8d4a4..b5a222be1269da678521f8694f78fba2327979be 100644 (file)
 
 (define_insn "movti"
   [(set (match_operand:TI 0 "nonimmediate_operand" "=d,Q,d,o,Q")
-        (match_operand:TI 1 "general_operand" "Q,d,dKo,d,Q"))]
+        (match_operand:TI 1 "general_operand" "Q,d,dKm,d,Q"))]
   "TARGET_64BIT"
   "@
    lmg\\t%0,%N0,%1
   [(set (match_operand:TI 0 "nonimmediate_operand" "")
         (match_operand:TI 1 "general_operand" ""))]
   "TARGET_64BIT && reload_completed
-   && !s_operand (operands[0], VOIDmode)
-   && !s_operand (operands[1], VOIDmode)
-   && (register_operand (operands[0], VOIDmode)
-       || register_operand (operands[1], VOIDmode))
-   && (!register_operand (operands[0], VOIDmode)
-       || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, TImode),
-                                    operands[1])
-       || !reg_overlap_mentioned_p (operand_subword (operands[0], 1, 0, TImode),
-                                    operands[1]))"
+   && s390_split_ok_p (operands[0], operands[1], TImode, 0)"
   [(set (match_dup 2) (match_dup 4))
    (set (match_dup 3) (match_dup 5))]
-  "
 {
-  if (!register_operand (operands[0], VOIDmode)
-      || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, TImode),
-                                   operands[1]))
-    {
-      operands[2] = operand_subword (operands[0], 0, 0, TImode);
-      operands[3] = operand_subword (operands[0], 1, 0, TImode);
-      operands[4] = operand_subword (operands[1], 0, 0, TImode);
-      operands[5] = operand_subword (operands[1], 1, 0, TImode);
-    }
-  else
-    {
-      operands[2] = operand_subword (operands[0], 1, 0, TImode);
-      operands[3] = operand_subword (operands[0], 0, 0, TImode);
-      operands[4] = operand_subword (operands[1], 1, 0, TImode);
-      operands[5] = operand_subword (operands[1], 0, 0, TImode);
-    }
-}")
+  operands[2] = operand_subword (operands[0], 0, 0, TImode);
+  operands[3] = operand_subword (operands[0], 1, 0, TImode);
+  operands[4] = operand_subword (operands[1], 0, 0, TImode);
+  operands[5] = operand_subword (operands[1], 1, 0, TImode);
+})
+
+(define_split
+  [(set (match_operand:TI 0 "nonimmediate_operand" "")
+        (match_operand:TI 1 "general_operand" ""))]
+  "TARGET_64BIT && reload_completed
+   && s390_split_ok_p (operands[0], operands[1], TImode, 1)"
+  [(set (match_dup 2) (match_dup 4))
+   (set (match_dup 3) (match_dup 5))]
+{
+  operands[2] = operand_subword (operands[0], 1, 0, TImode);
+  operands[3] = operand_subword (operands[0], 0, 0, TImode);
+  operands[4] = operand_subword (operands[1], 1, 0, TImode);
+  operands[5] = operand_subword (operands[1], 0, 0, TImode);
+})
 
 (define_split
   [(set (match_operand:TI 0 "register_operand" "")
   "TARGET_64BIT && reload_completed
    && !s_operand (operands[1], VOIDmode)"
   [(set (match_dup 0) (match_dup 1))]
-  "
 {
   rtx addr = operand_subword (operands[0], 1, 0, TImode);
   s390_load_address (addr, XEXP (operands[1], 0));
   operands[1] = replace_equiv_address (operands[1], addr);
-}")
+})
+
+(define_expand "reload_outti"
+  [(parallel [(match_operand:TI 0 "memory_operand" "")
+              (match_operand:TI 1 "register_operand" "d")
+              (match_operand:DI 2 "register_operand" "=&a")])]
+  "TARGET_64BIT"
+{
+  s390_load_address (operands[2], XEXP (operands[0], 0));
+  operands[0] = replace_equiv_address (operands[0], operands[2]);
+  emit_move_insn (operands[0], operands[1]);
+  DONE;
+})
 
 ;
 ; movdi instruction pattern(s).
 
 (define_insn "*movdi_31"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=d,Q,d,o,!*f,!*f,!m,Q")
-        (match_operand:DI 1 "general_operand" "Q,d,dKo,d,*f,m,*f,Q"))]
+        (match_operand:DI 1 "general_operand" "Q,d,dKm,d,*f,m,*f,Q"))]
   "!TARGET_64BIT"
   "@
    lm\\t%0,%N0,%1
   [(set (match_operand:DI 0 "nonimmediate_operand" "")
         (match_operand:DI 1 "general_operand" ""))]
   "!TARGET_64BIT && reload_completed
-   && !FP_REG_P (operands[0])
-   && !FP_REG_P (operands[1])
-   && !s_operand (operands[0], VOIDmode)
-   && !s_operand (operands[1], VOIDmode)
-   && (register_operand (operands[0], VOIDmode)
-       || register_operand (operands[1], VOIDmode))
-   && (!register_operand (operands[0], VOIDmode)
-       || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DImode),
-                                    operands[1])
-       || !reg_overlap_mentioned_p (operand_subword (operands[0], 1, 0, DImode),
-                                    operands[1]))"
+   && s390_split_ok_p (operands[0], operands[1], DImode, 0)"
   [(set (match_dup 2) (match_dup 4))
    (set (match_dup 3) (match_dup 5))]
-  "
 {
-  if (!register_operand (operands[0], VOIDmode)
-      || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DImode),
-                                   operands[1]))
-    {
-      operands[2] = operand_subword (operands[0], 0, 0, DImode);
-      operands[3] = operand_subword (operands[0], 1, 0, DImode);
-      operands[4] = operand_subword (operands[1], 0, 0, DImode);
-      operands[5] = operand_subword (operands[1], 1, 0, DImode);
-    }
-  else
-    {
-      operands[2] = operand_subword (operands[0], 1, 0, DImode);
-      operands[3] = operand_subword (operands[0], 0, 0, DImode);
-      operands[4] = operand_subword (operands[1], 1, 0, DImode);
-      operands[5] = operand_subword (operands[1], 0, 0, DImode);
-    }
-}")
+  operands[2] = operand_subword (operands[0], 0, 0, DImode);
+  operands[3] = operand_subword (operands[0], 1, 0, DImode);
+  operands[4] = operand_subword (operands[1], 0, 0, DImode);
+  operands[5] = operand_subword (operands[1], 1, 0, DImode);
+})
+
+(define_split
+  [(set (match_operand:DI 0 "nonimmediate_operand" "")
+        (match_operand:DI 1 "general_operand" ""))]
+  "!TARGET_64BIT && reload_completed
+   && s390_split_ok_p (operands[0], operands[1], DImode, 1)"
+  [(set (match_dup 2) (match_dup 4))
+   (set (match_dup 3) (match_dup 5))]
+{
+  operands[2] = operand_subword (operands[0], 1, 0, DImode);
+  operands[3] = operand_subword (operands[0], 0, 0, DImode);
+  operands[4] = operand_subword (operands[1], 1, 0, DImode);
+  operands[5] = operand_subword (operands[1], 0, 0, DImode);
+})
 
 (define_split
   [(set (match_operand:DI 0 "register_operand" "")
         (match_operand:DI 1 "memory_operand" ""))]
   "!TARGET_64BIT && reload_completed
    && !FP_REG_P (operands[0])
-   && !FP_REG_P (operands[1])
    && !s_operand (operands[1], VOIDmode)"
   [(set (match_dup 0) (match_dup 1))]
-  "
 {
   rtx addr = operand_subword (operands[0], 1, 0, DImode);
   s390_load_address (addr, XEXP (operands[1], 0));
   operands[1] = replace_equiv_address (operands[1], addr);
-}")
+})
+
+(define_expand "reload_outdi"
+  [(parallel [(match_operand:DI 0 "memory_operand" "")
+              (match_operand:DI 1 "register_operand" "d")
+              (match_operand:SI 2 "register_operand" "=&a")])]
+  "!TARGET_64BIT"
+{
+  s390_load_address (operands[2], XEXP (operands[0], 0));
+  operands[0] = replace_equiv_address (operands[0], operands[2]);
+  emit_move_insn (operands[0], operands[1]);
+  DONE;
+})
 
 (define_peephole2
   [(set (match_operand:DI 0 "register_operand" "")
 
 (define_insn "*movdf_31"
   [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,m,d,Q,d,o,Q")
-        (match_operand:DF 1 "general_operand" "f,m,f,Q,d,dKo,d,Q"))]
+        (match_operand:DF 1 "general_operand" "f,m,f,Q,d,dKm,d,Q"))]
   "!TARGET_64BIT"
   "@
    ldr\\t%0,%1
   [(set (match_operand:DF 0 "nonimmediate_operand" "")
         (match_operand:DF 1 "general_operand" ""))]
   "!TARGET_64BIT && reload_completed
-   && !FP_REG_P (operands[0])
-   && !FP_REG_P (operands[1])
-   && !s_operand (operands[0], VOIDmode)
-   && !s_operand (operands[1], VOIDmode)
-   && (register_operand (operands[0], VOIDmode)
-       || register_operand (operands[1], VOIDmode))
-   && (!register_operand (operands[0], VOIDmode)
-       || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DFmode),
-                                    operands[1])
-       || !reg_overlap_mentioned_p (operand_subword (operands[0], 1, 0, DFmode),
-                                    operands[1]))"
+   && s390_split_ok_p (operands[0], operands[1], DFmode, 0)"
   [(set (match_dup 2) (match_dup 4))
    (set (match_dup 3) (match_dup 5))]
-  "
 {
-  if (!register_operand (operands[0], VOIDmode)
-      || !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DFmode),
-                                   operands[1]))
-    {
-      operands[2] = operand_subword (operands[0], 0, 0, DFmode);
-      operands[3] = operand_subword (operands[0], 1, 0, DFmode);
-      operands[4] = operand_subword (operands[1], 0, 0, DFmode);
-      operands[5] = operand_subword (operands[1], 1, 0, DFmode);
-    }
-  else
-    {
-      operands[2] = operand_subword (operands[0], 1, 0, DFmode);
-      operands[3] = operand_subword (operands[0], 0, 0, DFmode);
-      operands[4] = operand_subword (operands[1], 1, 0, DFmode);
-      operands[5] = operand_subword (operands[1], 0, 0, DFmode);
-    }
-}")
+  operands[2] = operand_subword (operands[0], 0, 0, DFmode);
+  operands[3] = operand_subword (operands[0], 1, 0, DFmode);
+  operands[4] = operand_subword (operands[1], 0, 0, DFmode);
+  operands[5] = operand_subword (operands[1], 1, 0, DFmode);
+})
+
+(define_split
+  [(set (match_operand:DF 0 "nonimmediate_operand" "")
+        (match_operand:DF 1 "general_operand" ""))]
+  "!TARGET_64BIT && reload_completed
+   && s390_split_ok_p (operands[0], operands[1], DFmode, 1)"
+  [(set (match_dup 2) (match_dup 4))
+   (set (match_dup 3) (match_dup 5))]
+{
+  operands[2] = operand_subword (operands[0], 1, 0, DFmode);
+  operands[3] = operand_subword (operands[0], 0, 0, DFmode);
+  operands[4] = operand_subword (operands[1], 1, 0, DFmode);
+  operands[5] = operand_subword (operands[1], 0, 0, DFmode);
+})
 
 (define_split
   [(set (match_operand:DF 0 "register_operand" "")
         (match_operand:DF 1 "memory_operand" ""))]
   "!TARGET_64BIT && reload_completed
    && !FP_REG_P (operands[0])
-   && !FP_REG_P (operands[1])
    && !s_operand (operands[1], VOIDmode)"
   [(set (match_dup 0) (match_dup 1))]
-  "
 {
   rtx addr = operand_subword (operands[0], 1, 0, DFmode);
   s390_load_address (addr, XEXP (operands[1], 0));
   operands[1] = replace_equiv_address (operands[1], addr);
-}")
+})
+
+(define_expand "reload_outdf"
+  [(parallel [(match_operand:DF 0 "memory_operand" "")
+              (match_operand:DF 1 "register_operand" "d")
+              (match_operand:SI 2 "register_operand" "=&a")])]
+  "!TARGET_64BIT"
+{
+  s390_load_address (operands[2], XEXP (operands[0], 0));
+  operands[0] = replace_equiv_address (operands[0], operands[2]);
+  emit_move_insn (operands[0], operands[1]);
+  DONE;
+})
 
 ;
 ; movsf instruction pattern(s).
index 190e0ef20763371467158d7493032df0e1a9e151..930031bf95a0460d9d4cef2c74884b67eb093cd1 100644 (file)
@@ -1,3 +1,7 @@
+2003-06-27  Ulrich Weigand  <uweigand@de.ibm.com>
+
+       * gcc.dg/20030627-1.c: New test.
+
 2003-06-26  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/11332
diff --git a/gcc/testsuite/gcc.dg/20030627-1.c b/gcc/testsuite/gcc.dg/20030627-1.c
new file mode 100644 (file)
index 0000000..4135f71
--- /dev/null
@@ -0,0 +1,20 @@
+/* This tests whether non-offsettable memory operands are reloaded 
+   correctly in certain corner cases on s390 targets.  */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu89" } */
+
+void test_inout (char *bd, int xd, char *bs, int xs)
+{
+  *(long long *)(bd + xd + 4093) = *(long long *)(bs + xs + 4093);
+}
+
+void test_in (char *bd, int xd, char *bs, int xs)
+{
+  *(long long *)(bd + xd) = *(long long *)(bs + xs + 4093);
+}
+
+void test_out (char *bd, int xd, char *bs, int xs)
+{
+  *(long long *)(bd + xd + 4093) = *(long long *)(bs + xs);
+}
+