]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR target/42427 (invalid assembly code for 301.apsi for -fnon-call-exceptions)
authorPeter Bergner <bergner@vnet.ibm.com>
Thu, 18 Mar 2010 03:10:04 +0000 (22:10 -0500)
committerPeter Bergner <bergner@gcc.gnu.org>
Thu, 18 Mar 2010 03:10:04 +0000 (22:10 -0500)
gcc/
PR target/42427
* config/rs6000/rs6000.c (rs6000_split_multireg_move): Add support for
non-offsettable and pre_modify update addressing.
* config/rs6000/dfp.md (*movdd_hardfloat32): Make the "0", "1"
and "2" alternatives "#".
(*movdd_softfloat32): Make all alternatives "#";
* config/rs6000/rs6000.md (DIFD): New define_mode_iterator.
(*movdf_hardfloat32): Make the "0", "1" and "2" alternatives "#".
(*movdf_softfloat32): Make all alternatives "#";
(movdi): Use the new DIFD mode iterator to create a common splitter
for movdi, movdf and movdd patterns.

gcc/testsuite/
PR target/42427
* gcc.dg/pr42427.c: New test.

From-SVN: r157530

gcc/ChangeLog
gcc/config/rs6000/dfp.md
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr42427.c [new file with mode: 0644]

index f6f62b9583b3e31316a1d4cc86679662edc89fc9..69edc12851c76fd4316ab3425a5e68258103001a 100644 (file)
@@ -1,3 +1,17 @@
+2010-03-17  Peter Bergner  <bergner@vnet.ibm.com>
+
+       PR target/42427
+       * config/rs6000/rs6000.c (rs6000_split_multireg_move): Add support for
+       non-offsettable and pre_modify update addressing.
+       * config/rs6000/dfp.md (*movdd_hardfloat32): Make the "0", "1"
+       and "2" alternatives "#".
+       (*movdd_softfloat32): Make all alternatives "#";
+       * config/rs6000/rs6000.md (DIFD): New define_mode_iterator.
+       (*movdf_hardfloat32): Make the "0", "1" and "2" alternatives "#".
+       (*movdf_softfloat32): Make all alternatives "#";
+       (movdi): Use the new DIFD mode iterator to create a common splitter
+       for movdi, movdf and movdd patterns.
+
 2010-03-18  Shujing Zhao  <pearly.zhao@oracle.com>
 
        * common.opt (dumpdir): Remove redundant tab.
index 96da57c319c3dad3e1bcd7cb0a5eff78e0f92c8a..8326d6be0a618a1a5257f4cbf38d796912a84f57 100644 (file)
     default:
       gcc_unreachable ();
     case 0:
-      /* We normally copy the low-numbered register first.  However, if
-        the first register operand 0 is the same as the second register
-        of operand 1, we must copy in the opposite order.  */
-      if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
-       return \"mr %L0,%L1\;mr %0,%1\";
-      else
-       return \"mr %0,%1\;mr %L0,%L1\";
     case 1:
-      if (rs6000_offsettable_memref_p (operands[1])
-         || (GET_CODE (operands[1]) == MEM
-             && (GET_CODE (XEXP (operands[1], 0)) == LO_SUM
-                 || GET_CODE (XEXP (operands[1], 0)) == PRE_INC
-                 || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC)))
-       {
-         /* If the low-address word is used in the address, we must load
-            it last.  Otherwise, load it first.  Note that we cannot have
-            auto-increment in that case since the address register is
-            known to be dead.  */
-         if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
-                                operands[1], 0))
-           return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
-         else
-           return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
-       }
-      else
-       {
-         rtx addreg;
-
-         addreg = find_addr_reg (XEXP (operands[1], 0));
-         if (refers_to_regno_p (REGNO (operands[0]),
-                                REGNO (operands[0]) + 1,
-                                operands[1], 0))
-           {
-             output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
-             output_asm_insn (\"{lx|lwzx} %L0,%1\", operands);
-             output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
-             return \"{lx|lwzx} %0,%1\";
-           }
-         else
-           {
-             output_asm_insn (\"{lx|lwzx} %0,%1\", operands);
-             output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
-             output_asm_insn (\"{lx|lwzx} %L0,%1\", operands);
-             output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
-             return \"\";
-           }
-       }
     case 2:
-      if (rs6000_offsettable_memref_p (operands[0])
-         || (GET_CODE (operands[0]) == MEM
-             && (GET_CODE (XEXP (operands[0], 0)) == LO_SUM
-                 || GET_CODE (XEXP (operands[0], 0)) == PRE_INC
-                 || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)))
-       return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
-      else
-       {
-         rtx addreg;
-
-         addreg = find_addr_reg (XEXP (operands[0], 0));
-         output_asm_insn (\"{stx|stwx} %1,%0\", operands);
-         output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
-         output_asm_insn (\"{stx|stwx} %L1,%0\", operands);
-         output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
-         return \"\";
-       }
+      return \"#\";
     case 3:
       return \"fmr %0,%1\";
     case 4:
   "! TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS)
    && (gpc_reg_operand (operands[0], DDmode)
        || gpc_reg_operand (operands[1], DDmode))"
-  "*
-{
-  switch (which_alternative)
-    {
-    default:
-      gcc_unreachable ();
-    case 0:
-      /* We normally copy the low-numbered register first.  However, if
-        the first register operand 0 is the same as the second register of
-        operand 1, we must copy in the opposite order.  */
-      if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
-       return \"mr %L0,%L1\;mr %0,%1\";
-      else
-       return \"mr %0,%1\;mr %L0,%L1\";
-    case 1:
-      /* If the low-address word is used in the address, we must load
-        it last.  Otherwise, load it first.  Note that we cannot have
-        auto-increment in that case since the address register is
-        known to be dead.  */
-      if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
-                            operands[1], 0))
-       return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
-      else
-       return \"{l%U1|lwz%U1} %0,%1\;{l|lwz} %L0,%L1\";
-    case 2:
-      return \"{st%U0|stw%U0} %1,%0\;{st|stw} %L1,%L0\";
-    case 3:
-    case 4:
-    case 5:
-      return \"#\";
-    }
-}"
+  "#"
   [(set_attr "type" "two,load,store,*,*,*")
    (set_attr "length" "8,8,8,8,12,16")])
 
index 4754502b34ef2ff8124d0917edb3f3d620c6150c..dea0271b91a65df56769d363b4b9a48fd867561f 100644 (file)
@@ -16724,6 +16724,7 @@ rs6000_split_multireg_move (rtx dst, rtx src)
       int i;
       int j = -1;
       bool used_update = false;
+      rtx restore_basereg = NULL_RTX;
 
       if (MEM_P (src) && INT_REGNO_P (reg))
        {
@@ -16742,10 +16743,27 @@ rs6000_split_multireg_move (rtx dst, rtx src)
            }
          else if (! rs6000_offsettable_memref_p (src))
            {
-             rtx basereg;
-             basereg = gen_rtx_REG (Pmode, reg);
-             emit_insn (gen_rtx_SET (VOIDmode, basereg, XEXP (src, 0)));
-             src = replace_equiv_address (src, basereg);
+             if (GET_CODE (XEXP (src, 0)) == PRE_MODIFY)
+               {
+                 rtx basereg = XEXP (XEXP (src, 0), 0);
+                 if (TARGET_UPDATE)
+                   {
+                     rtx ndst = simplify_gen_subreg (reg_mode, dst, mode, 0);
+                     emit_insn (gen_rtx_SET (VOIDmode, ndst,
+                                gen_rtx_MEM (reg_mode, XEXP (src, 0))));
+                     used_update = true;
+                   }
+                 else
+                   emit_insn (gen_rtx_SET (VOIDmode, basereg,
+                              XEXP (XEXP (src, 0), 1)));
+                 src = replace_equiv_address (src, basereg);
+               }
+             else
+               {
+                 rtx basereg = gen_rtx_REG (Pmode, reg);
+                 emit_insn (gen_rtx_SET (VOIDmode, basereg, XEXP (src, 0)));
+                 src = replace_equiv_address (src, basereg);
+               }
            }
 
          breg = XEXP (src, 0);
@@ -16759,8 +16777,7 @@ rs6000_split_multireg_move (rtx dst, rtx src)
              && REGNO (breg) < REGNO (dst) + nregs)
            j = REGNO (breg) - REGNO (dst);
        }
-
-      if (GET_CODE (dst) == MEM && INT_REGNO_P (reg))
+      else if (MEM_P (dst) && INT_REGNO_P (reg))
        {
          rtx breg;
 
@@ -16790,7 +16807,34 @@ rs6000_split_multireg_move (rtx dst, rtx src)
                emit_insn (gen_add3_insn (breg, breg, delta_rtx));
              dst = replace_equiv_address (dst, breg);
            }
-         else
+         else if (!rs6000_offsettable_memref_p (dst)
+                  && GET_CODE (XEXP (dst, 0)) != LO_SUM)
+           {
+             if (GET_CODE (XEXP (dst, 0)) == PRE_MODIFY)
+               {
+                 rtx basereg = XEXP (XEXP (dst, 0), 0);
+                 if (TARGET_UPDATE)
+                   {
+                     rtx nsrc = simplify_gen_subreg (reg_mode, src, mode, 0);
+                     emit_insn (gen_rtx_SET (VOIDmode,
+                                gen_rtx_MEM (reg_mode, XEXP (dst, 0)), nsrc));
+                     used_update = true;
+                   }
+                 else
+                   emit_insn (gen_rtx_SET (VOIDmode, basereg,
+                              XEXP (XEXP (dst, 0), 1)));
+                 dst = replace_equiv_address (dst, basereg);
+               }
+             else
+               {
+                 rtx basereg = XEXP (XEXP (dst, 0), 0);
+                 rtx offsetreg = XEXP (XEXP (dst, 0), 1);
+                 emit_insn (gen_add3_insn (basereg, basereg, offsetreg));
+                 restore_basereg = gen_sub3_insn (basereg, basereg, offsetreg);
+                 dst = replace_equiv_address (dst, basereg);
+               }
+           }
+         else if (GET_CODE (XEXP (dst, 0)) != LO_SUM)
            gcc_assert (rs6000_offsettable_memref_p (dst));
        }
 
@@ -16812,6 +16856,8 @@ rs6000_split_multireg_move (rtx dst, rtx src)
                                  simplify_gen_subreg (reg_mode, src, mode,
                                                       j * reg_mode_size)));
        }
+      if (restore_basereg != NULL_RTX)
+       emit_insn (restore_basereg);
     }
 }
 
index 08475b65e545d7e8154a3ef7ffab39f5e4f3e8f5..50c4d618053c137b4f49cda49769b3e28e08c1a1 100644 (file)
   (DD "TARGET_DFP")
   (TD "TARGET_DFP")])
 
+; These modes do not fit in integer registers in 32-bit mode.
+(define_mode_iterator DIFD [DI DF DD])
+
 ; Various instructions that come in SI and DI forms.
 ; A generic w/d attribute, for things like cmpw/cmpd.
 (define_mode_attr wd [(QI "b") (HI "h") (SI "w") (DI "d")])
     default:
       gcc_unreachable ();
     case 0:
-      /* We normally copy the low-numbered register first.  However, if
-        the first register operand 0 is the same as the second register
-        of operand 1, we must copy in the opposite order.  */
-      if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
-       return \"mr %L0,%L1\;mr %0,%1\";
-      else
-       return \"mr %0,%1\;mr %L0,%L1\";
     case 1:
-      if (rs6000_offsettable_memref_p (operands[1])
-         || (GET_CODE (operands[1]) == MEM
-             && (GET_CODE (XEXP (operands[1], 0)) == LO_SUM
-                 || GET_CODE (XEXP (operands[1], 0)) == PRE_INC
-                 || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC
-                 || GET_CODE (XEXP (operands[1], 0)) == PRE_MODIFY)))
-       {
-         /* If the low-address word is used in the address, we must load
-            it last.  Otherwise, load it first.  Note that we cannot have
-            auto-increment in that case since the address register is
-            known to be dead.  */
-         if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
-                                operands[1], 0))
-           return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
-         else
-           return \"{l%U1%X1|lwz%U1%X1} %0,%1\;{l|lwz} %L0,%L1\";
-       }
-      else
-       {
-         rtx addreg;
-
-         addreg = find_addr_reg (XEXP (operands[1], 0));
-         if (refers_to_regno_p (REGNO (operands[0]),
-                                REGNO (operands[0]) + 1,
-                                operands[1], 0))
-           {
-             output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
-             output_asm_insn (\"{l%X1|lwz%X1} %L0,%1\", operands);
-             output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
-             return \"{l%X1|lwz%X1} %0,%1\";
-           }
-         else
-           {
-             output_asm_insn (\"{l%X1|lwz%X1} %0,%1\", operands);
-             output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
-             output_asm_insn (\"{l%X1|lwz%X1} %L0,%1\", operands);
-             output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
-             return \"\";
-           }
-       }
     case 2:
-      if (rs6000_offsettable_memref_p (operands[0])
-         || (GET_CODE (operands[0]) == MEM
-             && (GET_CODE (XEXP (operands[0], 0)) == LO_SUM
-                 || GET_CODE (XEXP (operands[0], 0)) == PRE_INC
-                 || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
-                 || GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)))
-       return \"{st%U0%X0|stw%U0%X0} %1,%0\;{st|stw} %L1,%L0\";
-      else
-       {
-         rtx addreg;
-
-         addreg = find_addr_reg (XEXP (operands[0], 0));
-         output_asm_insn (\"{st%X0|stw%X0} %1,%0\", operands);
-         output_asm_insn (\"{cal|la} %0,4(%0)\", &addreg);
-         output_asm_insn (\"{st%X0|stw%X0} %L1,%0\", operands);
-         output_asm_insn (\"{cal|la} %0,-4(%0)\", &addreg);
-         return \"\";
-       }
+      return \"#\";
     case 3:
     case 4:
       return \"xxlor %x0,%x1,%x1\";
        || TARGET_SOFT_FLOAT || TARGET_E500_SINGLE)
    && (gpc_reg_operand (operands[0], DFmode)
        || gpc_reg_operand (operands[1], DFmode))"
-  "*
-{
-  switch (which_alternative)
-    {
-    default:
-      gcc_unreachable ();
-    case 0:
-      /* We normally copy the low-numbered register first.  However, if
-        the first register operand 0 is the same as the second register of
-        operand 1, we must copy in the opposite order.  */
-      if (REGNO (operands[0]) == REGNO (operands[1]) + 1)
-       return \"mr %L0,%L1\;mr %0,%1\";
-      else
-       return \"mr %0,%1\;mr %L0,%L1\";
-    case 1:
-      /* If the low-address word is used in the address, we must load
-        it last.  Otherwise, load it first.  Note that we cannot have
-        auto-increment in that case since the address register is
-        known to be dead.  */
-      if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
-                            operands[1], 0))
-       return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
-      else
-       return \"{l%U1%X1|lwz%U1%X1} %0,%1\;{l|lwz} %L0,%L1\";
-    case 2:
-      return \"{st%U0%X0|stw%U0%X0} %1,%0\;{st|stw} %L1,%L0\";
-    case 3:
-    case 4:
-    case 5:
-      return \"#\";
-    }
-}"
+  "#"
   [(set_attr "type" "two,load,store,*,*,*")
    (set_attr "length" "8,8,8,8,12,16")])
 
 }")
 
 (define_split
-  [(set (match_operand:DI 0 "rs6000_nonimmediate_operand" "")
-        (match_operand:DI 1 "input_operand" ""))]
+  [(set (match_operand:DIFD 0 "rs6000_nonimmediate_operand" "")
+        (match_operand:DIFD 1 "input_operand" ""))]
   "reload_completed && !TARGET_POWERPC64
    && gpr_or_gpr_p (operands[0], operands[1])"
   [(pc)]
index da5166f9f2d0568d3795f5d9223edf23b886a6cf..5797626bc56a120ff3ec82eb8f507c1161a38092 100644 (file)
@@ -1,3 +1,8 @@
+2010-03-17  Peter Bergner  <bergner@vnet.ibm.com>
+
+       PR target/42427
+       * gcc.dg/pr42427.c: New test.
+
 2010-03-17  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
        PR libfortran/43265
diff --git a/gcc/testsuite/gcc.dg/pr42427.c b/gcc/testsuite/gcc.dg/pr42427.c
new file mode 100644 (file)
index 0000000..1961313
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do assemble } */
+/* { dg-options "-O2 -fexceptions -fnon-call-exceptions -fpeel-loops" } */
+/* { dg-require-effective-target ilp32 } */
+
+#include <complex.h>
+
+extern double myabs (complex double);
+
+void
+test (double *help, complex double *wm, long nz)
+{
+  long k;
+  double znew;
+  double zold;
+  for (k = 0; k < nz; k++)
+    {
+      znew = myabs (wm[k]);
+      zold = help[k];
+      help[k] = znew;
+    }
+}