This patch adds support for 12-bit immediate values for Thumb-2 in ADD and
SUB instructions.  We added two new alternatives for *arm_addsi3 which
make use of two new constraints for 12-bit values.  Also we modified
costs of PLUS rtx expression.
This patch reduces size of libevas by 1788 bytes (from 464916 to
463128), and sqlite by 54 bytes (from 266156 to 266052).
Regtested with Cortex-A8 QEMU.

Ok for trunk?

gcc/config/arm/

2011-05-19  Dmitry Plotnikov  <dplotni...@ispras.ru>

	* arm-protos.h (const_ok_for_thumb2_12bit): New prototype.

	* arm.c (const_ok_for_thumb2_12bit): New function.
	(arm_rtx_costs_1): Modified costs for PLUS rtx.

	* arm.md (*arm_addsi3): New variants.
	
	* constraints.md (Pn): New constraint.
	(Pq): New constraint.

gcc/testsuite/

2010-05-19  Dmitry Plotnikov  <dplotni...@ispras.ru>

	* gcc.target/arm/thumb2-addw.c: New testcase.
	* gcc.target/arm/thumb2-subw.c: New testcase.

diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index 190fec0..aaebdba 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -46,6 +46,7 @@ extern bool arm_vector_mode_supported_p (enum machine_mode);
 extern bool arm_small_register_classes_for_mode_p (enum machine_mode);
 extern int arm_hard_regno_mode_ok (unsigned int, enum machine_mode);
 extern int const_ok_for_arm (HOST_WIDE_INT);
+extern int const_ok_for_thumb2_12bit (HOST_WIDE_INT);
 extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx,
 			       HOST_WIDE_INT, rtx, rtx, int);
 extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, rtx *, rtx *);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 5f964d6..db2e5f2 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -2298,6 +2298,21 @@ const_ok_for_arm (HOST_WIDE_INT i)
   return FALSE;
 }
 
+/* Return TRUE if int I is a valid immediate THUMB-2 constant in add/sub 
+ *  instructions in 12 bit encoding variants.  */
+
+int
+const_ok_for_thumb2_12bit (HOST_WIDE_INT i) 
+{
+   /* According to Thumb-2 instruction set manual such constants should be 
+   *  in range 0-4095.  */
+  if ((i & ~(unsigned HOST_WIDE_INT) 0xfff) == 0)
+    return TRUE;
+
+  return FALSE;
+}
+
+
 /* Return true if I is a valid constant for the operation CODE.  */
 static int
 const_ok_for_op (HOST_WIDE_INT i, enum rtx_code code)
@@ -7164,7 +7179,10 @@ arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
 
     case CONST_INT:
       if (const_ok_for_arm (INTVAL (x))
-	  || const_ok_for_arm (~INTVAL (x)))
+	  || const_ok_for_arm (~INTVAL (x))
+	  || (TARGET_THUMB2 && (outer == PLUS) 
+	      && (const_ok_for_thumb2_12bit (INTVAL (x))
+	          || const_ok_for_thumb2_12bit (~INTVAL (x)))))
 	*total = COSTS_N_INSNS (1);
       else
 	*total = COSTS_N_INSNS (arm_gen_constant (SET, mode, NULL_RTX,
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 9e23d9b..0a92b0a 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -707,21 +707,26 @@
 ;;  (plus (reg rN) (reg sp)) into (reg rN).  In this case reload will
 ;; put the duplicated register first, and not try the commutative version.
 (define_insn_and_split "*arm_addsi3"
-  [(set (match_operand:SI          0 "s_register_operand" "=r, k,r,r, k,r")
-	(plus:SI (match_operand:SI 1 "s_register_operand" "%rk,k,r,rk,k,rk")
-		 (match_operand:SI 2 "reg_or_int_operand" "rI,rI,k,L, L,?n")))]
+  [(set (match_operand:SI          0 "s_register_operand" "=r ,k, r,r, r, r, k,r")
+	(plus:SI (match_operand:SI 1 "s_register_operand" "%rk,k, r,rk, rk, rk,k,rk")
+		 (match_operand:SI 2 "reg_or_int_operand" "rI ,rI,k,Pq,Pn,L, L,?n")))]
   "TARGET_32BIT"
   "@
    add%?\\t%0, %1, %2
    add%?\\t%0, %1, %2
    add%?\\t%0, %2, %1
+   add%?\\t%0, %1, %2
+   sub%?\\t%0, %1, #%n2
    sub%?\\t%0, %1, #%n2
    sub%?\\t%0, %1, #%n2
    #"
   "TARGET_32BIT
    && GET_CODE (operands[2]) == CONST_INT
    && !(const_ok_for_arm (INTVAL (operands[2]))
-        || const_ok_for_arm (-INTVAL (operands[2])))
+        || const_ok_for_arm (-INTVAL (operands[2]))
+        || (TARGET_THUMB2 
+            && (const_ok_for_thumb2_12bit (INTVAL (operands[2]))
+                || const_ok_for_thumb2_12bit (-INTVAL (operands[2])))))
    && (reload_completed || !arm_eliminable_register (operands[1]))"
   [(clobber (const_int 0))]
   "
@@ -730,7 +735,7 @@
 		      operands[1], 0);
   DONE;
   "
-  [(set_attr "length" "4,4,4,4,4,16")
+  [(set_attr "length" "4,4,4,4,4,4,4,16")
    (set_attr "predicable" "yes")]
 )
 
diff --git a/gcc/config/arm/constraints.md b/gcc/config/arm/constraints.md
index f5b8521..71b7130 100644
--- a/gcc/config/arm/constraints.md
+++ b/gcc/config/arm/constraints.md
@@ -160,6 +160,16 @@
   (and (match_code "const_int")
        (match_test "TARGET_THUMB1 && ival >= 0 && ival <= 7")))
 
+(define_constraint "Pn"
+  "@internal In Thumb-2 state a constant in the range -4095 to 0"
+  (and (match_code "const_int")
+       (match_test "TARGET_THUMB2 && ival >= -4094 && ival <= 0")))
+
+(define_constraint "Pq"
+  "@internal In Thumb-2 state a constant in the range 0 to 4095"
+  (and (match_code "const_int")
+       (match_test "TARGET_THUMB2 && ival >= 0 && ival <= 4095")))
+
 (define_constraint "Ps"
   "@internal In Thumb-2 state a constant in the range -255 to +255"
   (and (match_code "const_int")
diff --git a/gcc/testsuite/gcc.target/arm/thumb2-addw.c b/gcc/testsuite/gcc.target/arm/thumb2-addw.c
new file mode 100644
index 0000000..e84dc69
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/thumb2-addw.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_thumb2_ok} */
+/* { dg-options "-O2 -mthumb" } */
+/* { dg-final { scan-assembler "add.*#3565" } } */
+
+/* Verify that 12-bit immediate is used.  */
+int f1(int n) {
+       return n + 0xded;
+}
+
diff --git a/gcc/testsuite/gcc.target/arm/thumb2-subw.c b/gcc/testsuite/gcc.target/arm/thumb2-subw.c
new file mode 100644
index 0000000..78f5b09
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/thumb2-subw.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_thumb2_ok} */
+/* { dg-options "-O2 -mthumb" } */
+/* { dg-final { scan-assembler "sub.*#3565" } } */
+
+/* Verify that 12-bit immediate is used.  */
+int f1(int n) {
+       return n - 0xded;
+}
+

Reply via email to