aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIain Sandoe <iain@sandoe.co.uk>2019-10-29 20:20:23 +0000
committerIain Sandoe <iains@gcc.gnu.org>2019-10-29 20:20:23 +0000
commit9b6d95b967ca9dd7d9093c16c34881214af4db26 (patch)
tree3778d8bf8a0edefd428958f21fcd203477a6ba0d
parent2e58cf13995d40ab6160f669cbbf28e7297f4464 (diff)
downloadgcc-9b6d95b967ca9dd7d9093c16c34881214af4db26.zip
gcc-9b6d95b967ca9dd7d9093c16c34881214af4db26.tar.gz
gcc-9b6d95b967ca9dd7d9093c16c34881214af4db26.tar.bz2
[Darwin, PPC] Fix PR 65342.
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-29 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: r277590
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/config/rs6000/darwin.md32
-rw-r--r--gcc/config/rs6000/rs6000.c103
-rw-r--r--gcc/config/rs6000/rs6000.md8
4 files changed, 115 insertions, 41 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c0fd65a..8c1709b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,6 +1,19 @@
2019-10-29 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-29 Iain Sandoe <iain@sandoe.co.uk>
+
+ Backport from mainline
2019-10-12 Iain Sandoe <iain@sandoe.co.uk>
PR target/67183
diff --git a/gcc/config/rs6000/darwin.md b/gcc/config/rs6000/darwin.md
index fde67fd..f1fa9d4 100644
--- a/gcc/config/rs6000/darwin.md
+++ b/gcc/config/rs6000/darwin.md
@@ -139,38 +139,6 @@ You should have received a copy of the GNU General Public License
[(set_attr "type" "store")
(set_attr "length" "4")])
-;; 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")
- (set_attr "length" "4")])
-
-(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")
- (set_attr "length" "4")])
-
-(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")
- (set_attr "length" "4")])
-
;; Mach-O PIC trickery.
(define_expand "macho_high"
[(set (match_operand 0 "" "")
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index b6e62a2..dae2600 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -8582,6 +8582,101 @@ 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)
+{
+ 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 DFmode:
+ case DDmode:
+ case 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 TFmode:
+ case IFmode:
+ case KFmode:
+ case TDmode:
+ case TImode:
+ case 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.
@@ -8616,7 +8711,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;
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index aebb2d5..475f1f7 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -6746,14 +6746,6 @@
;; 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")
- (set_attr "length" "4")])
;; MR LA LWZ LFIWZX LXSIWZX
;; STW STFIWX STXSIWX LI LIS