[RS6000] PR72802 part 1, fix constraints for lxssp/stxssp
authorAlan Modra <amodra@gmail.com>
Mon, 8 Aug 2016 09:05:16 +0000 (18:35 +0930)
committerAlan Modra <amodra@gcc.gnu.org>
Mon, 8 Aug 2016 09:05:16 +0000 (18:35 +0930)
We can't use "o" constraint for lsxxp/stxssp since those insns have a
DS-form offset field, ie. the bottom two bits of the offset must be 0.
So use "wY" instead, but that leads to finding another problem.

mem_operand_gpr is only suitable for gpr loads/stores since it does
not enforce multiple-of-4 offsets when -m32.  So "wY" can't use
mem_operand_gpr, and the vsx tests in mem_operand_gpr are bogus.

I've deleted offsettable_mem_14bit_operand because it wasn't used
anywhere but in the wY constraint.  Note also that the new wY
constraint doesn't use memory_operand because that is redundant in a
constraint, having already been tested in the predicate.

PR target/72802
* config/rs6000/rs6000.c (mem_operand_gpr): Remove vsx dform test.
(mem_operand_ds_form): New predicate.
* config/rs6000/rs6000-protos.h (mem_operand_ds_form): Declare.
* config/rs6000/constraints.md (wY): Use mem_operand_df_form.
* config/rs6000/predicates.md (offsettable_mem_14bit_operand): Delete.
* config/rs6000/rs6000.md (f32_lm2, f32_sm2): Use wY for SF.
(extendsfdf2_fpr): Replace o constraint with wY.

From-SVN: r239233

gcc/ChangeLog
gcc/config/rs6000/constraints.md
gcc/config/rs6000/predicates.md
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md

index 9f1caad8c02f1e4dce38c38824f14d0c7a4bc97c..ef0de804196fbecd29dbca7737f9108bde6531c3 100644 (file)
@@ -1,3 +1,14 @@
+2016-08-08  Alan Modra  <amodra@gmail.com>
+
+       PR target/72802
+       * config/rs6000/rs6000.c (mem_operand_gpr): Remove vsx dform test.
+       (mem_operand_ds_form): New predicate.
+       * config/rs6000/rs6000-protos.h (mem_operand_ds_form): Declare.
+       * config/rs6000/constraints.md (wY): Use mem_operand_df_form.
+       * config/rs6000/predicates.md (offsettable_mem_14bit_operand): Delete.
+       * config/rs6000/rs6000.md (f32_lm2, f32_sm2): Use wY for SF.
+       (extendsfdf2_fpr): Replace o constraint with wY.
+
 2016-08-07  Jan Hubicka  <hubicka@ucw.cz>
 
        * tree-ssa-threadbackward.c: Include tree-inline.h
index 18713256b9be7e7b052bb10138902d4bee2a5a5e..7535c35155f203c98930d1cd3a03403ccc34cb7a 100644 (file)
   "Vector constant that can be loaded with XXSPLTIB & sign extension."
   (match_test "xxspltib_constant_split (op, mode)"))
 
-;; ISA 3.0 D-form instruction that has the bottom 2 bits 0 (LXSD or STXSD).
+;; ISA 3.0 DS-form instruction that has the bottom 2 bits 0 and no update form.
+;; Used by LXSD/STXSD/LXSSP/STXSSP.  In contrast to "Y", the multiple-of-four
+;; offset is enforced for 32-bit too.
 (define_memory_constraint "wY"
   "Offsettable memory operand, with bottom 2 bits 0"
-  (match_operand 0 "offsettable_mem_14bit_operand"))
+  (and (match_code "mem")
+       (not (match_test "update_address_mem (op, mode)"))
+       (match_test "mem_operand_ds_form (op, mode)")))
 
 ;; Altivec style load/store that ignores the bottom bits of the address
 (define_memory_constraint "wZ"
index 0d10e9ab5c19865f81d1f72725909aae4dd414d0..6436d5eb3a1ef536c78b76adf1028dfc8eef204c 100644 (file)
   (and (match_operand 0 "memory_operand")
        (match_test "offsettable_nonstrict_memref_p (op)")))
 
-;; Return 1 if the operand is an offsettable memory operand for ISA 3.0
-;; scalar LXSD/STXSD that must have the bottom 2 bits 0 and no update
-;; form
-(define_predicate "offsettable_mem_14bit_operand"
-  (and (match_operand 0 "memory_operand")
-       (match_test "offsettable_nonstrict_memref_p (op)")
-       (match_test "mem_operand_gpr (op, mode)")
-       (not (match_test "update_address_mem  (op, mode)"))))
-
 ;; Return 1 if the operand is suitable for load/store quad memory.
 ;; This predicate only checks for non-atomic loads/stores (not lqarx/stqcx).
 (define_predicate "quad_memory_operand"
index 8a307a85e6f270069eb95532eecead55551f9678..c7e338a8927cba001d28b982daff019087521445 100644 (file)
@@ -39,6 +39,7 @@ extern int num_insns_constant (rtx, machine_mode);
 extern int num_insns_constant_wide (HOST_WIDE_INT);
 extern int small_data_operand (rtx, machine_mode);
 extern bool mem_operand_gpr (rtx, machine_mode);
+extern bool mem_operand_ds_form (rtx, machine_mode);
 extern bool toc_relative_expr_p (const_rtx, bool);
 extern bool invalid_e500_subreg (rtx, machine_mode);
 extern void validate_condition_mode (enum rtx_code, machine_mode);
index 779ba1fb002520b11a8a2cdb0a1b0d13b89f71d6..c59d07ac899636898eac511df3b72d3f0145a5d6 100644 (file)
@@ -7717,8 +7717,34 @@ mem_operand_gpr (rtx op, machine_mode mode)
   if (TARGET_POWERPC64 && (offset & 3) != 0)
     return false;
 
-  if (mode_supports_vsx_dform_quad (mode)
-      && !quad_address_offset_p (offset))
+  extra = GET_MODE_SIZE (mode) - UNITS_PER_WORD;
+  if (extra < 0)
+    extra = 0;
+
+  if (GET_CODE (addr) == LO_SUM)
+    /* For lo_sum addresses, we must allow any offset except one that
+       causes a wrap, so test only the low 16 bits.  */
+    offset = ((offset & 0xffff) ^ 0x8000) - 0x8000;
+
+  return offset + 0x8000 < 0x10000u - extra;
+}
+
+/* As above, but for DS-FORM VSX insns.  Unlike mem_operand_gpr,
+   enforce an offset divisible by 4 even for 32-bit.  */
+
+bool
+mem_operand_ds_form (rtx op, machine_mode mode)
+{
+  unsigned HOST_WIDE_INT offset;
+  int extra;
+  rtx addr = XEXP (op, 0);
+
+  op = address_offset (addr);
+  if (op == NULL_RTX)
+    return true;
+
+  offset = INTVAL (op);
+  if ((offset & 3) != 0)
     return false;
 
   extra = GET_MODE_SIZE (mode) - UNITS_PER_WORD;
index bc01dc7d2f0af02c8271763cfd58e91d9418707f..1430799a04e896722554ab5cd52c5dde1f54f254 100644 (file)
 (define_mode_attr f32_lr  [(SF "f")              (SD "wz")])
 (define_mode_attr f32_lr2 [(SF "wb")             (SD "wn")])
 (define_mode_attr f32_lm  [(SF "m")              (SD "Z")])
-(define_mode_attr f32_lm2 [(SF "o")              (SD "wn")])
+(define_mode_attr f32_lm2 [(SF "wY")             (SD "wn")])
 (define_mode_attr f32_li  [(SF "lfs%U1%X1 %0,%1") (SD "lfiwzx %0,%y1")])
 (define_mode_attr f32_li2 [(SF "lxssp %0,%1")     (SD "lfiwzx %0,%y1")])
 (define_mode_attr f32_lv  [(SF "lxsspx %x0,%y1")  (SD "lxsiwzx %x0,%y1")])
 (define_mode_attr f32_sr  [(SF "f")               (SD "wx")])
 (define_mode_attr f32_sr2 [(SF "wb")              (SD "wn")])
 (define_mode_attr f32_sm  [(SF "m")               (SD "Z")])
-(define_mode_attr f32_sm2 [(SF "o")               (SD "wn")])
+(define_mode_attr f32_sm2 [(SF "wY")              (SD "wn")])
 (define_mode_attr f32_si  [(SF "stfs%U0%X0 %1,%0") (SD "stfiwx %1,%y0")])
 (define_mode_attr f32_si2 [(SF "stxssp %1,%0")     (SD "stfiwx %1,%y0")])
 (define_mode_attr f32_sv  [(SF "stxsspx %x1,%y0")  (SD "stxsiwzx %x1,%y0")])
 
 (define_insn_and_split "*extendsfdf2_fpr"
   [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d,d,ws,?ws,wu,wb")
-       (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m,0,wy,Z,o")))]
+       (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m,0,wy,Z,wY")))]
   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
   "@
    #