]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[Darwin, PPC] Fix PR 65342.
authorIain Sandoe <iain@sandoe.co.uk>
Sun, 27 Oct 2019 21:25:57 +0000 (21:25 +0000)
committerIain Sandoe <iains@gcc.gnu.org>
Sun, 27 Oct 2019 21:25:57 +0000 (21:25 +0000)
The current Darwin load/store lo_sum patterns have neither predicate nor
constraint. This means that most parts of the backend, which rely on
recog() to validate the rtx, can produce invalid combinations/selections.

For 32bit cases this isn't a problem since we can load/store to unaligned
addresses using D-mode insns.

Conversely, for 64bit instructions that use DS mode, this can manifest as
assemble errors (for an assembler that checks the LO14 relocations), or as
crashes caused by wrong offsets (or worse, wrong content for the two LSBs).

What we want to check for Y on Darwin is:
- that the alignment of the Symbols' target is sufficient for DS mode
- that the offset is suitable for DS mode.
(while looking through the Mach-O PIC unspecs).

So, the patch removes the Darwin-specific lo_sum patterns (we begin using
the movdi_internal64 patterns). We also we need to extend the handling of the
mem_operand_gpr constraint to allow looking through Mach-O PIC UNSPECs in
the lo_sum cases.

2019-10-27  Iain Sandoe  <iain@sandoe.co.uk>

Backport from mainline
2019-10-17  Iain Sandoe  <iain@sandoe.co.uk>

PR target/65342
* config/rs6000/darwin.md (movdi_low, movsi_low_st): Delete.
(movdi_low_st): Delete.
* config/rs6000/rs6000.c
(darwin_rs6000_legitimate_lo_sum_const_p): New.
(mem_operand_gpr): Validate Mach-O LO_SUM cases separately.
* config/rs6000/rs6000.md (movsi_low): Delete.

From-SVN: r277495

gcc/ChangeLog
gcc/config/rs6000/darwin.md
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md

index 6af9d79970552efd382cc436a730f9c1f462cd46..6e41b1f651be7020ccda6e228cb19e3b157454b6 100644 (file)
@@ -1,3 +1,16 @@
+2019-10-27  Iain Sandoe  <iain@sandoe.co.uk>
+
+       Backport from mainline
+       2019-10-17  Iain Sandoe  <iain@sandoe.co.uk>
+
+       PR target/65342
+       * config/rs6000/darwin.md (movdi_low, movsi_low_st): Delete.
+       (movdi_low_st): Delete.
+       * config/rs6000/rs6000.c
+       (darwin_rs6000_legitimate_lo_sum_const_p): New.
+       (mem_operand_gpr): Validate Mach-O LO_SUM cases separately.
+       * config/rs6000/rs6000.md (movsi_low): Delete.
+
 2019-10-27  Iain Sandoe  <iain@sandoe.co.uk>
 
        Backport from mainline
index 471058dd417756acf44071cb56314355f1a65ebc..a1a46a9e7ea10b8623cd5a1125f9179fd4b0a1ae 100644 (file)
@@ -122,33 +122,6 @@ You should have received a copy of the GNU General Public License
   [(set_attr "type" "store")])
 
 ;; 64-bit MachO load/store support
-(define_insn "movdi_low"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,*!d")
-        (mem:DI (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b,b")
-                           (match_operand 2 "" ""))))]
-  "TARGET_MACHO && TARGET_64BIT"
-  "@
-   ld %0,lo16(%2)(%1)
-   lfd %0,lo16(%2)(%1)"
-  [(set_attr "type" "load")])
-
-(define_insn "movsi_low_st"
-  [(set (mem:SI (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
-                           (match_operand 2 "" "")))
-       (match_operand:SI 0 "gpc_reg_operand" "r"))]
-  "TARGET_MACHO && ! TARGET_64BIT"
-  "stw %0,lo16(%2)(%1)"
-  [(set_attr "type" "store")])
-
-(define_insn "movdi_low_st"
-  [(set (mem:DI (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b,b")
-                           (match_operand 2 "" "")))
-       (match_operand:DI 0 "gpc_reg_operand" "r,*!d"))]
-  "TARGET_MACHO && TARGET_64BIT"
-  "@
-   std %0,lo16(%2)(%1)
-   stfd %0,lo16(%2)(%1)"
-  [(set_attr "type" "store")])
 
 ;; Mach-O PIC trickery.
 (define_expand "macho_high"
index cb8d737976b24f52115b8fb316b74337e0100530..aa292a1c8bd3bef57003d3d6e3a2d1070586a9ea 100644 (file)
@@ -7671,6 +7671,104 @@ address_offset (rtx op)
   return NULL_RTX;
 }
 
+/* This tests that a lo_sum {constant, symbol, symbol+offset} is valid for
+   the mode.  If we can't find (or don't know) the alignment of the symbol
+   we assume (optimistically) that it's sufficiently aligned [??? maybe we
+   should be pessimistic].  Offsets are validated in the same way as for
+   reg + offset.  */
+static bool
+darwin_rs6000_legitimate_lo_sum_const_p (rtx x, machine_mode mode)
+{
+  /* We should not get here with this.  */
+  gcc_checking_assert (! mode_supports_dq_form (mode));
+
+  if (GET_CODE (x) == CONST)
+    x = XEXP (x, 0);
+
+  if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_MACHOPIC_OFFSET)
+    x =  XVECEXP (x, 0, 0);
+
+  rtx sym = NULL_RTX;
+  unsigned HOST_WIDE_INT offset = 0;
+
+  if (GET_CODE (x) == PLUS)
+    {
+      sym = XEXP (x, 0);
+      if (! SYMBOL_REF_P (sym))
+       return false;
+      if (!CONST_INT_P (XEXP (x, 1)))
+       return false;
+      offset = INTVAL (XEXP (x, 1));
+    }
+  else if (SYMBOL_REF_P (x))
+    sym = x;
+  else if (CONST_INT_P (x))
+    offset = INTVAL (x);
+  else if (GET_CODE (x) == LABEL_REF)
+    offset = 0; // We assume code labels are Pmode aligned
+  else
+    return false; // not sure what we have here.
+
+  /* If we don't know the alignment of the thing to which the symbol refers,
+     we assume optimistically it is "enough".
+     ??? maybe we should be pessimistic instead.  */
+  unsigned align = 0;
+
+  if (sym)
+    {
+      tree decl = SYMBOL_REF_DECL (sym);
+#if TARGET_MACHO
+      if (MACHO_SYMBOL_INDIRECTION_P (sym))
+      /* The decl in an indirection symbol is the original one, which might
+        be less aligned than the indirection.  Our indirections are always
+        pointer-aligned.  */
+       ;
+      else
+#endif
+      if (decl && DECL_ALIGN (decl))
+       align = DECL_ALIGN_UNIT (decl);
+   }
+
+  unsigned int extra = 0;
+  switch (mode)
+    {
+    case E_DFmode:
+    case E_DDmode:
+    case E_DImode:
+      /* If we are using VSX scalar loads, restrict ourselves to reg+reg
+        addressing.  */
+      if (VECTOR_MEM_VSX_P (mode))
+       return false;
+
+      if (!TARGET_POWERPC64)
+       extra = 4;
+      else if ((offset & 3) || (align & 3))
+       return false;
+      break;
+
+    case E_TFmode:
+    case E_IFmode:
+    case E_KFmode:
+    case E_TDmode:
+    case E_TImode:
+    case E_PTImode:
+      extra = 8;
+      if (!TARGET_POWERPC64)
+       extra = 12;
+      else if ((offset & 3) || (align & 3))
+       return false;
+      break;
+
+    default:
+      break;
+    }
+
+  /* We only care if the access(es) would cause a change to the high part.  */
+  offset = ((offset & 0xffff) ^ 0x8000) - 0x8000;
+  return IN_RANGE (offset, -(HOST_WIDE_INT_1 << 15),
+                            (HOST_WIDE_INT_1 << 15) - 1 - extra);
+}
+
 /* Return true if the MEM operand is a memory operand suitable for use
    with a (full width, possibly multiple) gpr load/store.  On
    powerpc64 this means the offset must be divisible by 4.
@@ -7705,7 +7803,13 @@ mem_operand_gpr (rtx op, machine_mode mode)
       && legitimate_indirect_address_p (XEXP (addr, 0), false))
     return true;
 
-  /* Don't allow non-offsettable addresses.  See PRs 83969 and 84279.  */
+  /* We need to look through Mach-O PIC unspecs to determine if a lo_sum is
+     really OK.  Doing this early avoids teaching all the other machinery
+     about them.  */
+  if (TARGET_MACHO && GET_CODE (addr) == LO_SUM)
+    return darwin_rs6000_legitimate_lo_sum_const_p (XEXP (addr, 1), mode);
+
+  /* Only allow offsettable addresses.  See PRs 83969 and 84279.  */
   if (!rs6000_offsettable_memref_p (op, mode, false))
     return false;
 
index 401cbfc3fd7101fabbb1599120df2723b56f80f4..b3469a17f2799e6ad6e954fdf3a808f0256c93b0 100644 (file)
 ;; do the load 16-bits at a time.  We could do this by loading from memory,
 ;; and this is even supposed to be faster, but it is simpler not to get
 ;; integers in the TOC.
-(define_insn "movsi_low"
-  [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
-        (mem:SI (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
-                           (match_operand 2 "" ""))))]
-  "TARGET_MACHO && ! TARGET_64BIT"
-  "lwz %0,lo16(%2)(%1)"
-  [(set_attr "type" "load")])
 
 ;;             MR           LA           LWZ          LFIWZX       LXSIWZX
 ;;             STW          STFIWX       STXSIWX      LI           LIS