]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
backport: [multiple changes]
authorBill Schmidt <wschmidt@linux.vnet.ibm.com>
Fri, 4 Apr 2014 13:57:48 +0000 (13:57 +0000)
committerWilliam Schmidt <wschmidt@gcc.gnu.org>
Fri, 4 Apr 2014 13:57:48 +0000 (13:57 +0000)
2014-04-04  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>

Backport from mainline r205123:

2013-11-20  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>

* config/rs6000/rs6000.c (rs6000_cannot_change_mode_class): Do not
allow subregs of TDmode in FPRs of smaller size in little-endian.
(rs6000_split_multireg_move): When splitting an access to TDmode
in FPRs, do not use simplify_gen_subreg.

Backport from mainline r204927:

2013-11-17  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>

* config/rs6000/rs6000.c (rs6000_emit_move): Use low word of
sdmode_stack_slot also in little-endian mode.

From-SVN: r209093

gcc/ChangeLog
gcc/config/rs6000/rs6000.c

index 0e939a4c6b1908437accb763c09ce220c09ef89c..bf76e38c602acfded318f33875c5e4f26bfe6f39 100644 (file)
@@ -1,3 +1,21 @@
+2014-04-04  Bill Schmidt  <wschmidt@linux.vnet.ibm.com>
+
+       Backport from mainline r205123:
+
+       2013-11-20  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
+
+       * config/rs6000/rs6000.c (rs6000_cannot_change_mode_class): Do not
+       allow subregs of TDmode in FPRs of smaller size in little-endian.
+       (rs6000_split_multireg_move): When splitting an access to TDmode
+       in FPRs, do not use simplify_gen_subreg.
+
+       Backport from mainline r204927:
+
+       2013-11-17  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
+
+       * config/rs6000/rs6000.c (rs6000_emit_move): Use low word of
+       sdmode_stack_slot also in little-endian mode.
+
 2014-04-04  Bill Schmidt <wschmidt@linux.vnet.ibm.com>
 
        Power8 HTM Support
index 8d1f1981a38165ecee0667a7ab39285bc36f8a74..27137a325f953a1f883e59008786520b94916561 100644 (file)
@@ -7963,7 +7963,9 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
        }
       else if (INT_REGNO_P (REGNO (operands[1])))
        {
-         rtx mem = adjust_address_nv (operands[0], mode, 4);
+         rtx mem = operands[0];
+         if (BYTES_BIG_ENDIAN)
+           mem = adjust_address_nv (mem, mode, 4);
          mem = eliminate_regs (mem, VOIDmode, NULL_RTX);
          emit_insn (gen_movsd_hardfloat (mem, operands[1]));
        }
@@ -7986,7 +7988,9 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
        }
       else if (INT_REGNO_P (REGNO (operands[0])))
        {
-         rtx mem = adjust_address_nv (operands[1], mode, 4);
+         rtx mem = operands[1];
+         if (BYTES_BIG_ENDIAN)
+           mem = adjust_address_nv (mem, mode, 4);
          mem = eliminate_regs (mem, VOIDmode, NULL_RTX);
          emit_insn (gen_movsd_hardfloat (operands[0], mem));
        }
@@ -16082,6 +16086,13 @@ rs6000_cannot_change_mode_class (enum machine_mode from,
          if (TARGET_IEEEQUAD && (to == TFmode || from == TFmode))
            return true;
 
+         /* TDmode in floating-mode registers must always go into a register
+            pair with the most significant word in the even-numbered register
+            to match ISA requirements.  In little-endian mode, this does not
+            match subreg numbering, so we cannot allow subregs.  */
+         if (!BYTES_BIG_ENDIAN && (to == TDmode || from == TDmode))
+           return true;
+
          if (from_size < 8 || to_size < 8)
            return true;
 
@@ -19028,6 +19039,39 @@ rs6000_split_multireg_move (rtx dst, rtx src)
 
   gcc_assert (reg_mode_size * nregs == GET_MODE_SIZE (mode));
 
+  /* TDmode residing in FP registers is special, since the ISA requires that
+     the lower-numbered word of a register pair is always the most significant
+     word, even in little-endian mode.  This does not match the usual subreg
+     semantics, so we cannnot use simplify_gen_subreg in those cases.  Access
+     the appropriate constituent registers "by hand" in little-endian mode.
+
+     Note we do not need to check for destructive overlap here since TDmode
+     can only reside in even/odd register pairs.  */
+  if (FP_REGNO_P (reg) && DECIMAL_FLOAT_MODE_P (mode) && !BYTES_BIG_ENDIAN)
+    {
+      rtx p_src, p_dst;
+      int i;
+
+      for (i = 0; i < nregs; i++)
+       {
+         if (REG_P (src) && FP_REGNO_P (REGNO (src)))
+           p_src = gen_rtx_REG (reg_mode, REGNO (src) + nregs - 1 - i);
+         else
+           p_src = simplify_gen_subreg (reg_mode, src, mode,
+                                        i * reg_mode_size);
+
+         if (REG_P (dst) && FP_REGNO_P (REGNO (dst)))
+           p_dst = gen_rtx_REG (reg_mode, REGNO (dst) + nregs - 1 - i);
+         else
+           p_dst = simplify_gen_subreg (reg_mode, dst, mode,
+                                        i * reg_mode_size);
+
+         emit_insn (gen_rtx_SET (VOIDmode, p_dst, p_src));
+       }
+
+      return;
+    }
+
   if (REG_P (src) && REG_P (dst) && (REGNO (src) < REGNO (dst)))
     {
       /* Move register range backwards, if we might have destructive