diff mbox

[AARCH64] Fix legitimate address checking for TImode and TFmode

Message ID 4FD6059A.9070100@arm.com
State New
Headers show

Commit Message

Marcus Shawcroft June 11, 2012, 2:50 p.m. UTC
This patch fixes the behaviour of legitimate address checking for TImode 
and TFmode values.

The current implementation does not correctly distinguish between the 
address modes available for ldp/stp X,X versus ldr/str Q.

/Marcus

ChangeLog:

	* config/aarch64/aarch64.c
	(aarch64_regno_ok_for_index_p): Handle NULL reg_renumber.
	(aarch64_regno_ok_for_base_p): Likewise.
	(offset_7bit_signed_scaled_p): New.
	(offset_9bit_signed_unscaled_p): New.
	(offset_12bit_unsigned_scaled_p): New.
	(aarch64_classify_address): Replace pair_p with allow_reg_index_p.
	Conservative test for valid TImode and TFmode addresses.  Use
	offset_7bit_signed_scaled_p offset_9bit_signed_unscaled_p and
	offset_12bit_unsigned_scaled_p.  Remove explicit TImode and TFmode
	tests.
	* config/aarch64/aarch64.md (movti_aarch64): Replace 'm' with 'Ump'.
	(movtf_aarch64): Replace 'm' with 'Ump', replace 'Utf' with 'm'.
	* config/aarch64/constraints.md (Utf): Remove.
	(Ump) Pass strict.
diff mbox

Patch

diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 34d04755900a75376c0afe5b9b4b8b3cd1ac84e2..b985d63c4fd591c7ae17d519a7b858c0264edec7 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -2441,6 +2441,10 @@  aarch64_regno_ok_for_index_p (int regno,
     {
       if (!strict_p)
 	return true;
+
+      if (!reg_renumber)
+	return false;
+
       regno = reg_renumber[regno];
     }
   return GP_REGNUM_P (regno);
@@ -2456,6 +2460,10 @@  aarch64_regno_ok_for_base_p (int regno,
     {
       if (!strict_p)
 	return true;
+
+      if (!reg_renumber)
+	return false;
+
       regno = reg_renumber[regno];
     }
 
@@ -2639,6 +2647,29 @@  aarch64_classify_index (struct aarch64_a
   return false;
 }
 
+static inline bool
+offset_7bit_signed_scaled_p (enum machine_mode mode, HOST_WIDE_INT offset)
+{
+  return (offset >= -64 * GET_MODE_SIZE (mode)
+	  && offset < 64 * GET_MODE_SIZE (mode)
+	  && offset % GET_MODE_SIZE (mode) == 0);
+}
+
+static inline bool
+offset_9bit_signed_unscaled_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+			       HOST_WIDE_INT offset)
+{
+  return offset >= -256 && offset < 256;
+}
+
+static inline bool
+offset_12bit_unsigned_scaled_p (enum machine_mode mode, HOST_WIDE_INT offset)
+{
+  return (offset >= 0
+	  && offset < 4096 * GET_MODE_SIZE (mode)
+	  && offset % GET_MODE_SIZE (mode) == 0);
+}
+
 /* Return true if X is a valid address for machine mode MODE.  If it is,
    fill in INFO appropriately.  STRICT_P is true if REG_OK_STRICT is in
    effect.  OUTER_CODE is PARALLEL for a load/store pair.  */
@@ -2650,7 +2681,8 @@  aarch64_classify_address (struct aarch64
 {
   enum rtx_code code = GET_CODE (x);
   rtx op0, op1;
-  bool pair_p = (outer_code == PARALLEL || mode == TImode);
+  bool allow_reg_index_p =
+    outer_code != PARALLEL && GET_MODE_SIZE(mode) != 16;
 
   /* Don't support anything other than POST_INC or REG addressing for
      AdvSIMD.  */
@@ -2679,25 +2711,27 @@  aarch64_classify_address (struct aarch64
 	  info->type = ADDRESS_REG_IMM;
 	  info->base = op0;
 	  info->offset = op1;
+
+	  /* TImode and TFmode values are allowed in both pairs of X
+	     registers and individual Q registers.  The available
+	     address modes are:
+	     X,X: 7-bit signed scaled offset
+	     Q:   9-bit signed offset
+	     We conservatively require an offset representable in either mode.
+	   */
+	  if (mode == TImode || mode == TFmode)
+	    return (offset_7bit_signed_scaled_p (mode, offset)
+		    && offset_9bit_signed_unscaled_p (mode, offset));
+
 	  if (outer_code == PARALLEL)
-	    /* load/store pair: 7-bit signed, scaled offset.  */
 	    return ((GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8)
-		    && offset >= -64 * GET_MODE_SIZE (mode)
-		    && offset < 64 * GET_MODE_SIZE (mode)
-		    && offset % GET_MODE_SIZE (mode) == 0);
-	  else if (mode == TImode)
-	    /* load/store pair of dwords: 7-bit signed, scaled offset.  */
-	    return offset >= -512 && offset < 512 && offset % 8 == 0;
+		    && offset_7bit_signed_scaled_p (mode, offset));
 	  else
-	    /* load/store single: 9-bit signed, unscaled offset.  */
-	    /* load/store single: 12-bit unsigned, scaled offset.  */
-	    return ((offset >= -256 && offset < 256)
-		    || (offset >= 0
-			&& offset < 4096 * GET_MODE_SIZE (mode)
-			&& offset % GET_MODE_SIZE (mode) == 0));
+	    return (offset_9bit_signed_unscaled_p (mode, offset)
+		    || offset_12bit_unsigned_scaled_p (mode, offset));
 	}
 
-      if (!pair_p)
+      if (allow_reg_index_p)
 	{
 	  /* Look for base + (scaled/extended) index register.  */
 	  if (aarch64_base_register_rtx_p (op0, strict_p)
@@ -2737,18 +2771,23 @@  aarch64_classify_address (struct aarch64
 	  HOST_WIDE_INT offset;
 	  info->offset = XEXP (XEXP (x, 1), 1);
 	  offset = INTVAL (info->offset);
+
+	  /* TImode and TFmode values are allowed in both pairs of X
+	     registers and individual Q registers.  The available
+	     address modes are:
+	     X,X: 7-bit signed scaled offset
+	     Q:   9-bit signed offset
+	     We conservatively require an offset representable in either mode.
+	   */
+	  if (mode == TImode || mode == TFmode)
+	    return (offset_7bit_signed_scaled_p (mode, offset)
+		    && offset_9bit_signed_unscaled_p (mode, offset));
+
 	  if (outer_code == PARALLEL)
-	    /* load/store pair: 7-bit signed, scaled offset.  */
 	    return ((GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8)
-		    && offset >= -64 * GET_MODE_SIZE (mode)
-		    && offset < 64 * GET_MODE_SIZE (mode)
-		    && offset % GET_MODE_SIZE (mode) == 0);
-	  else if (mode == TImode)
-	    /* load/store pair of dwords: 7-bit signed, scaled offset.  */
-	    return offset >= -512 && offset < 512 && offset % 8 == 0;
+		    && offset_7bit_signed_scaled_p (mode, offset));
 	  else
-	    /* load/store single: 9-bit signed, unscaled offset.  */
-	    return offset >= -256 && offset < 256;
+	    return offset_9bit_signed_unscaled_p (mode, offset);
 	}
       return false;
 
@@ -2759,10 +2798,10 @@  aarch64_classify_address (struct aarch64
       info->type = ADDRESS_SYMBOLIC;
       if (outer_code != PARALLEL
 	  && (GET_MODE_SIZE (mode) == 4
-	      || GET_MODE_SIZE (mode) == 8
-	      || mode == TFmode))
+	      || GET_MODE_SIZE (mode) == 8))
 	{
 	  rtx sym, addend;
+
 	  split_const (x, &sym, &addend);
 	  return (GET_CODE (sym) == LABEL_REF
 		  || (GET_CODE (sym) == SYMBOL_REF
@@ -2774,7 +2813,7 @@  aarch64_classify_address (struct aarch64
       info->type = ADDRESS_LO_SUM;
       info->base = XEXP (x, 0);
       info->offset = XEXP (x, 1);
-      if (!pair_p
+      if (allow_reg_index_p
 	  && aarch64_base_register_rtx_p (info->base, strict_p))
 	{
 	  rtx sym, offs;
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 456fab743ca301e596d147322266bbb10ed85507..3ce99941ecb4b0c89e02979c14df10c7080c1ff7 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -987,8 +987,10 @@  (define_expand "movti"
 )
 
 (define_insn "*movti_aarch64"
-  [(set (match_operand:TI 0 "nonimmediate_operand"  "=r, *w,r,*w,r,m,m,*w, m")
-	(match_operand:TI 1 "aarch64_movti_operand" " rn,r,*w,*w,m,r,Z, m,*w"))]
+  [(set (match_operand:TI 0
+	 "nonimmediate_operand"  "=r, *w,r ,*w,r  ,Ump,Ump,*w,m")
+	(match_operand:TI 1
+	 "aarch64_movti_operand" " rn,r ,*w,*w,Ump,r  ,Z  , m,*w"))]
   "(register_operand (operands[0], TImode)
     || aarch64_reg_or_zero (operands[1], TImode))"
   "@
@@ -1002,7 +1004,7 @@  (define_insn "*movti_aarch64"
    ldr\\t%q0, %1
    str\\t%q1, %0"
   [(set_attr "v8type" "move2,fmovi2f,fmovf2i,*, \
-	               load2,store2,store2,fpsimd_load,fpsimd_store")
+		       load2,store2,store2,fpsimd_load,fpsimd_store")
    (set_attr "simd_type" "*,*,*,simd_move,*,*,*,*,*")
    (set_attr "mode" "DI,DI,DI,TI,DI,DI,DI,TI,TI")
    (set_attr "length" "8,8,8,4,4,4,4,4,4")
@@ -1091,8 +1093,10 @@  (define_expand "movtf"
 )
 
 (define_insn "*movtf_aarch64"
-  [(set (match_operand:TF 0 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r ,Utf")
-	(match_operand:TF 1 "general_operand"      " w,?r,?r,w ,Y,Y ,m,w,Utf,?rY"))]
+  [(set (match_operand:TF 0
+	 "nonimmediate_operand" "=w,?&r,w ,?r,w,?w,w,m,?r ,Ump")
+	(match_operand:TF 1
+	 "general_operand"      " w,?r, ?r,w ,Y,Y ,m,w,Ump,?rY"))]
   "TARGET_FLOAT && (register_operand (operands[0], TFmode)
     || register_operand (operands[1], TFmode))"
   "@
diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md
index 47d638400c546051ba1a3db67231f07cf120870f..91eba09f02cc5f61cac18649b55f6f469b418eea 100644
--- a/gcc/config/aarch64/constraints.md
+++ b/gcc/config/aarch64/constraints.md
@@ -121,14 +121,7 @@  (define_memory_constraint "Ump"
   A memory address suitable for a load/store pair operation."
   (and (match_code "mem")
        (match_test "aarch64_legitimate_address_p (GET_MODE (op), XEXP (op, 0),
-						  PARALLEL, 0)")))
-
-(define_memory_constraint "Utf"
-  "@internal
-  A memory address suitable for a load/store pair operation."
-  (and (match_code "mem")
-       (match_test "aarch64_legitimate_address_p (TImode, XEXP (op, 0),
-						  UNKNOWN, 0)")))
+						  PARALLEL, 1)")))
 
 (define_constraint "Dn"
   "@internal