[PATCH, ARM] PR47855 Compute attr "length" for some thumb2 insns, 2/3

Carrot Wei carrot@google.com
Fri Apr 8 09:57:00 GMT 2011


Hi

This is the second part of the fixing for

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47855

This patch contains the length computation for insn patterns "*arm_movqi_insn"
and "*arm_addsi3". Since the alternatives and encodings are much more complex,
the attribute length is computed in separate C functions.

The patch has been tested on qemu with both ARM and thumb mode.

thanks
Carrot

ChangeLog:
2011-04-08  Wei Guozhi  <carrot@google.com>

        PR target/47855
        * config/arm/arm-protos.h (arm_attr_length_movqi): New prototype.
        (arm_attr_length_addsi3): Likewise.
        * config/arm/arm.c (arm_attr_length_movqi): New function.
        (arm_attr_length_addsi3): Likewise.
        * config/arm/arm.md (*arm_movqi_insn): Compute attr "length".
        (*arm_addsi3): Change "length" computation by calling C function.


Index: arm.c
===================================================================
--- arm.c	(revision 172017)
+++ arm.c	(working copy)
@@ -23694,4 +23694,179 @@ arm_preferred_rename_class (reg_class_t
     return NO_REGS;
 }

+/* Compute the atrribute "length" of insn "*arm_movqi_insn".
+   So this function MUST be kept in sync with that insn pattern.  */
+int
+arm_attr_length_movqi (rtx dst, rtx src)
+{
+  enum rtx_code dst_code = GET_CODE (dst);
+  enum rtx_code src_code = GET_CODE (src);
+  rtx address, reg_op, base;
+
+  /* ARM mode.  */
+  if (TARGET_ARM)
+    return 4;
+
+  /* Thumb2 mode.  */
+  /* Register move.  */
+  if ((dst_code == REG) && (src_code == REG))
+    return 2;
+
+  /* Load an immediate.  */
+  if ((dst_code == REG) && (src_code == CONST_INT))
+    {
+      HOST_WIDE_INT i = INTVAL (src);
+      if ((arm_regno_class (REGNO (dst)) == LO_REGS) && (i >= 0) && (i <= 255))
+	return 2;
+      else
+	return 4;
+    }
+
+  /* Load/store a byte from/to memory.  */
+  if ((dst_code == REG) && (src_code == MEM))
+    {
+      reg_op = dst;
+      address = XEXP (src, 0);
+    }
+  else
+    {
+      gcc_assert ((dst_code == MEM) && (src_code == REG));
+      reg_op = src;
+      address = XEXP (dst, 0);
+    }
+
+  if (GET_CODE (address) == PLUS)
+    {
+      rtx op1 = XEXP (address, 1);
+      base = XEXP (address, 0);
+      if (GET_CODE (op1) == REG)
+	{
+	  if (arm_regno_class (REGNO (op1)) != LO_REGS)
+	    return 4;
+	}
+      else if ((GET_CODE (op1) != CONST_INT)
+	       || (INTVAL (op1) < 0) || (INTVAL (op1) > 31))
+	return 4;
+    }
+  else
+    base = address;
+
+  if (GET_CODE (base) != REG)
+    return 4;
+  if ((arm_regno_class (REGNO (base)) == LO_REGS)
+      && (arm_regno_class (REGNO (reg_op)) == LO_REGS))
+    return 2;
+
+  return 4;
+}
+
+/* Compute the atrribute "length" of insn "*arm_addsi3".
+   So this function MUST be kept in sync with that insn pattern.  */
+int
+arm_attr_length_addsi3 (rtx dst, rtx src1, rtx src2)
+{
+  HOST_WIDE_INT v;
+
+  /* The splite case.  */
+  if (which_alternative == 5)
+    return 16;
+
+  /* ARM mode.  */
+  if (TARGET_ARM)
+    return 4;
+
+  /* Thumb2 mode.  */
+  if (which_alternative == 4)
+    {
+      /* SUB (SP minus immediate).  */
+      v = -INTVAL (src2);
+      gcc_assert (v >= 0);
+      if (((v & 3) == 0) && (v < 512))
+	return 2;
+      return 4;
+    }
+  else if (which_alternative == 3)
+    {
+      /* SUB immediate.  */
+      HOST_WIDE_INT max_offset = 7;
+      v = -INTVAL (src2);
+      gcc_assert (v >= 0);
+      if (REGNO (dst) == REGNO (src1))
+	max_offset = 255;
+      if ((arm_regno_class (REGNO (dst)) == LO_REGS)
+	  && (arm_regno_class (REGNO (src1)) == LO_REGS)
+	  && (v <= max_offset))
+	return 2;
+      return 4;
+    }
+  else if (which_alternative == 1)
+    {
+      if (REG_P (src2))                    /* ADD SP,SP,<Rm>*/
+	return 2;
+      v = INTVAL (src2);
+      if (((v & 3) == 0) && (v < 1024))    /* ADD SP,SP,#<imm>  */
+	return 2;
+      return 4;
+    }
+  else
+    {
+      if (which_alternative == 2)
+	{
+	  rtx tmp = src1; src1 = src2; src2 = tmp;
+	}
+      /* Now we are in the most general case, (which_alternative == 0).  */
+      gcc_assert (REG_P (src1));
+      if (REGNO (src1) == SP_REGNUM)
+	{
+	  if (REG_P (src2))
+	    {
+	      /* ADD <Rdm>, SP, <Rdm>  */
+	      if (REGNO (src2) == REGNO (src1))
+		return 2;
+	      return 4;
+	    }
+	  else
+	    {
+	      gcc_assert (GET_CODE (src2) == CONST_INT);
+	      v = INTVAL (src2);
+	      /* ADD <Rd>, SP, #<imm>  */
+	      if ((arm_regno_class (REGNO (dst)) == LO_REGS)
+		  && ((v & 3) == 0) && (v < 1024))
+		return 2;
+	      return 4;
+	    }
+	}
+      else
+	{
+	  if (REG_P (src2))
+	    {
+	      /* ADD <Rdn>, <Rm>  */
+	      if ((REGNO (dst) == REGNO (src1))
+		  || (REGNO (dst) == REGNO (src2)))
+		return 2;
+	      /* ADDS <Rd>, <Rn>, <Rm>  */
+	      else if ((arm_regno_class (REGNO (dst)) == LO_REGS)
+		       && (arm_regno_class (REGNO (src1)) == LO_REGS)
+		       && (arm_regno_class (REGNO (src2)) == LO_REGS))
+		return 2;
+	      return 4;
+	    }
+	  else
+	    {
+	      /* ADD immediate.  */
+	      HOST_WIDE_INT max_offset = 7;
+	      gcc_assert (GET_CODE (src2) == CONST_INT);
+	      v = INTVAL (src2);
+	      if (REGNO (dst) == REGNO (src1))
+		max_offset = 255;
+	      if ((arm_regno_class (REGNO (dst)) == LO_REGS)
+		  && (arm_regno_class (REGNO (src1)) == LO_REGS)
+		  && (v <= max_offset))
+		return 2;
+	      return 4;
+	    }
+	}
+    }
+}
+
 #include "gt-arm.h"
Index: arm-protos.h
===================================================================
--- arm-protos.h	(revision 172017)
+++ arm-protos.h	(working copy)
@@ -152,6 +152,8 @@ extern void arm_expand_sync (enum machin
 extern const char *arm_output_memory_barrier (rtx *);
 extern const char *arm_output_sync_insn (rtx, rtx *);
 extern unsigned int arm_sync_loop_insns (rtx , rtx *);
+extern int arm_attr_length_movqi (rtx, rtx);
+extern int arm_attr_length_addsi3 (rtx, rtx, rtx);

 #if defined TREE_CODE
 extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
Index: arm.md
===================================================================
--- arm.md	(revision 172017)
+++ arm.md	(working copy)
@@ -730,8 +730,10 @@
 		      operands[1], 0);
   DONE;
   "
-  [(set_attr "length" "4,4,4,4,4,16")
-   (set_attr "predicable" "yes")]
+  [(set_attr "predicable" "yes")
+   (set (attr "length")
+	(symbol_ref
+	  "arm_attr_length_addsi3 (operands[0], operands[1], operands[2])"))]
 )

 (define_insn_and_split "*thumb1_addsi3"
@@ -5958,7 +5960,9 @@
    str%(b%)\\t%1, %0"
   [(set_attr "type" "*,*,load1,store1")
    (set_attr "insn" "mov,mvn,*,*")
-   (set_attr "predicable" "yes")]
+   (set_attr "predicable" "yes")
+   (set (attr "length")
+	(symbol_ref "arm_attr_length_movqi (operands[0], operands[1])"))]
 )

 (define_insn "*thumb1_movqi_insn"



More information about the Gcc-patches mailing list