Re: [PATCH][ARM] Add support for ADDW and SUBW instructions

2011-06-15 Thread Richard Earnshaw
On 06/06/11 15:31, Andrew Stubbs wrote:
 On 06/06/11 15:26, Dmitry Plotnikov wrote:
 On 06/06/2011 05:33 PM, Andrew Stubbs wrote:
 On 06/06/11 14:26, Dmitry Plotnikov wrote:
 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_op (INTVAL (x), outer

 Sorry, I should have noticed before ...

 This whole condition should be covered by a single call to
 const_ok_for_op. It already calls const_ok_for_arm internally.

 This condition is not covered by const_ok_for_op, because outer can be
 equal to other rtx codes, which are not covered in const_ok_for_op like
 IF_THEN_ELSE or MULT (I have several ICEs with these codes). I don't
 know how to fix this correctly - should I add all codes to
 const_ok_for_op or maybe just replace default alternative from
 gcc_unreachable() to return 0; ?
 
 That sounds reasonable to me - I mean, the constant is indeed not ok for 
 those operations.
 
 ... but I'm not a maintainer 
 
 Andrew
 
 


const_ok_for_op has grown beyond it's original intended use.  A quick
look at it shows that a change along the way you describe would first
require fixing the assumption that if the constant matches
const_ok_for_arm in an unmodified form that it is OK universally.  That
might be a good idea anyway, I'm not entirely sure that that's correct
for all possible use cases these days.

It's also likely that it needs extending to handle some of these cases
you describe.  Having an outer of IF_THEN_ELSE most likely means this is
used in the case

(set reg if_then_else(cond) (op_or_const) (const))

for which the rules would be the same as if const were used directly in
a SET.

But it's also equally likely that we don't calculate the costs of
IF_THEN_ELSE very accurately anyway.

R.

R.




Re: [PATCH][ARM] Add support for ADDW and SUBW instructions

2011-06-06 Thread Dmitry Plotnikov
This is follow-up patch that fixes rtx costs for CONST_INT in PLUS 
pattern.  Original discussion is here: 
http://gcc.gnu.org/ml/gcc-patches/2011-05/msg01427.html
2011-06-06  Dmitry PLotnikov  dplotni...@ispras.ru

	gcc/
	* config/arm/arm.c (arm_rtx_costs_1): Fixed costs for CONST_INT
	in PLUS pattern.

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 22ddcd2..9ef6f6d 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -7050,7 +7056,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_op (INTVAL (x), outer)
+	  || const_ok_for_op (~INTVAL (x), outer
 	*total = COSTS_N_INSNS (1);
   else
 	*total = COSTS_N_INSNS (arm_gen_constant (SET, mode, NULL_RTX,


Re: [PATCH][ARM] Add support for ADDW and SUBW instructions

2011-06-06 Thread Dmitry Plotnikov

On 06/06/2011 04:41 PM, Andrew Stubbs wrote:

On 06/06/11 13:15, Dmitry Plotnikov wrote:

+   (const_ok_for_op (INTVAL (x), outer)
+  || const_ok_for_op (~INTVAL (x), outer


The second call is redundant. const_ok_for_op should already do that.


Fixed patch is attached.  Ok?
2011-06-06  Dmitry PLotnikov  dplotni...@ispras.ru

	gcc/
	* config/arm/arm.c (arm_rtx_costs_1): Fixed costs for CONST_INT
	in PLUS pattern.

diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 22ddcd2..9ef6f6d 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -7050,7 +7056,9 @@ 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_op (INTVAL (x), outer
 	*total = COSTS_N_INSNS (1);
   else
 	*total = COSTS_N_INSNS (arm_gen_constant (SET, mode, NULL_RTX,


Re: [PATCH][ARM] Add support for ADDW and SUBW instructions

2011-06-06 Thread Andrew Stubbs

On 06/06/11 14:26, Dmitry Plotnikov wrote:

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_op (INTVAL (x), outer


Sorry, I should have noticed before ...

This whole condition should be covered by a single call to 
const_ok_for_op. It already calls const_ok_for_arm internally.


Andrew


Re: [PATCH][ARM] Add support for ADDW and SUBW instructions

2011-06-06 Thread Dmitry Plotnikov

On 06/06/2011 05:33 PM, Andrew Stubbs wrote:

On 06/06/11 14:26, Dmitry Plotnikov wrote:

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_op (INTVAL (x), outer


Sorry, I should have noticed before ...

This whole condition should be covered by a single call to 
const_ok_for_op. It already calls const_ok_for_arm internally.


This condition is not covered by const_ok_for_op, because outer can be 
equal to other rtx codes, which are not covered in const_ok_for_op like 
IF_THEN_ELSE or MULT (I have several ICEs with these codes).  I don't 
know how to fix this correctly - should I add all codes to 
const_ok_for_op or maybe just replace default alternative from 
gcc_unreachable() to return 0; ?


Re: [PATCH][ARM] Add support for ADDW and SUBW instructions

2011-06-06 Thread Andrew Stubbs

On 06/06/11 15:26, Dmitry Plotnikov wrote:

On 06/06/2011 05:33 PM, Andrew Stubbs wrote:

On 06/06/11 14:26, Dmitry Plotnikov wrote:

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_op (INTVAL (x), outer


Sorry, I should have noticed before ...

This whole condition should be covered by a single call to
const_ok_for_op. It already calls const_ok_for_arm internally.


This condition is not covered by const_ok_for_op, because outer can be
equal to other rtx codes, which are not covered in const_ok_for_op like
IF_THEN_ELSE or MULT (I have several ICEs with these codes). I don't
know how to fix this correctly - should I add all codes to
const_ok_for_op or maybe just replace default alternative from
gcc_unreachable() to return 0; ?


That sounds reasonable to me - I mean, the constant is indeed not ok for 
those operations.


... but I'm not a maintainer 

Andrew


Re: [PATCH][ARM] Add support for ADDW and SUBW instructions

2011-06-02 Thread Andrew Stubbs

Ping 2.

On 20/04/11 16:27, Andrew Stubbs wrote:

This patch adds basic support for the Thumb ADDW and SUBW instructions.

The patch permits the compiler to use the new instructions for constants
that can be loaded with a single instruction (i.e. 16-bit unshifted),
but does not support use of addw with split-constants; I have a patch
for that coming soon.

This patch requires that my previously posted patch for MOVW is applied
first.

OK?

Andrew




Re: [PATCH][ARM] Add support for ADDW and SUBW instructions

2011-06-02 Thread Ramana Radhakrishnan
 OK?


This is largely OK modulo the following.

Please remove the alternatives in the subsi3 pattern since that is just
unnecessary. Please make the constraints internal only.


cheers
Ramana


 Andrew


Re: [PATCH][ARM] Add support for ADDW and SUBW instructions

2011-06-02 Thread Andrew Stubbs

On 02/06/11 09:23, Ramana Radhakrishnan wrote:

Please remove the alternatives in the subsi3 pattern since that is just
unnecessary. Please make the constraints internal only.


Is this better?

Andrew
2011-06-02  Andrew Stubbs  a...@codesourcery.com

	gcc/
	* config/arm/arm-protos.h (const_ok_for_op): Add prototype.
	* config/arm/arm.c (const_ok_for_op): Add support for addw/subw.
	Remove prototype. Remove static function type.
	* config/arm/arm.md (*arm_addsi3): Add addw/subw support.
	Add arch attribute.
	* config/arm/constraints.md (Pj, PJ): New constraints.

--- 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_op (HOST_WIDE_INT, enum rtx_code);
 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 *);
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -82,7 +82,6 @@ inline static int thumb1_index_register_rtx_p (rtx, int);
 static bool arm_legitimate_address_p (enum machine_mode, rtx, bool);
 static int thumb_far_jump_used_p (void);
 static bool thumb_force_lr_save (void);
-static int const_ok_for_op (HOST_WIDE_INT, enum rtx_code);
 static rtx emit_sfm (int, int);
 static unsigned arm_size_return_regs (void);
 static bool arm_assemble_integer (rtx, unsigned int, int);
@@ -2149,7 +2148,7 @@ const_ok_for_arm (HOST_WIDE_INT i)
 }
 
 /* Return true if I is a valid constant for the operation CODE.  */
-static int
+int
 const_ok_for_op (HOST_WIDE_INT i, enum rtx_code code)
 {
   if (const_ok_for_arm (i))
@@ -2165,6 +2164,13 @@ const_ok_for_op (HOST_WIDE_INT i, enum rtx_code code)
 	return 0;
 
 case PLUS:
+  /* See if we can use addw or subw.  */
+  if (TARGET_THUMB2
+	   ((i  0xf000) == 0
+	  || ((-i)  0xf000) == 0))
+	return 1;
+  /* else fall through.  */
+
 case COMPARE:
 case EQ:
 case NE:
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -707,21 +707,24 @@
 ;;  (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, k, r, k,r, k, r)
+	(plus:SI (match_operand:SI 1 s_register_operand %rk,k,r,rk,k, rk,k,rk,k, rk)
+		 (match_operand:SI 2 reg_or_int_operand rI,rI,k,Pj,Pj,L, L,PJ,PJ,?n)))]
   TARGET_32BIT
   @
add%?\\t%0, %1, %2
add%?\\t%0, %1, %2
add%?\\t%0, %2, %1
+   addw%?\\t%0, %1, %2
+   addw%?\\t%0, %1, %2
sub%?\\t%0, %1, #%n2
sub%?\\t%0, %1, #%n2
+   subw%?\\t%0, %1, #%n2
+   subw%?\\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_op (INTVAL (operands[2]), PLUS)
 (reload_completed || !arm_eliminable_register (operands[1]))
   [(clobber (const_int 0))]
   
@@ -730,8 +733,9 @@
 		  operands[1], 0);
   DONE;
   
-  [(set_attr length 4,4,4,4,4,16)
-   (set_attr predicable yes)]
+  [(set_attr length 4,4,4,4,4,4,4,4,4,16)
+   (set_attr predicable yes)
+   (set_attr arch *,*,*,t2,t2,*,*,t2,t2,*)]
 )
 
 (define_insn_and_split *thumb1_addsi3
--- a/gcc/config/arm/constraints.md
+++ b/gcc/config/arm/constraints.md
@@ -31,7 +31,7 @@
 ;; The following multi-letter normal constraints have been used:
 ;; in ARM/Thumb-2 state: Da, Db, Dc, Dn, Dl, DL, Dv, Dy, Di, Dz
 ;; in Thumb-1 state: Pa, Pb, Pc, Pd
-;; in Thumb-2 state: Ps, Pt, Pu, Pv, Pw, Px, Py
+;; in Thumb-2 state: Pj, PJ, Ps, Pt, Pu, Pv, Pw, Px, Py
 
 ;; The following memory constraints have been used:
 ;; in ARM/Thumb-2 state: Q, Ut, Uv, Uy, Un, Um, Us
@@ -75,6 +75,18 @@
 	   (and (match_code const_int)
 (match_test (ival  0x) == 0)
 
+(define_constraint Pj
+ @internal A 12-bit constant suitable for an ADDW or SUBW instruction. (Thumb-2)
+ (and (match_code const_int)
+  (and (match_test TARGET_THUMB2)
+	   (match_test (ival  0xf000) == 0
+
+(define_constraint PJ
+ @internal A constant that satisfies the Pj constrant if negated.
+ (and (match_code const_int)
+  (and (match_test TARGET_THUMB2)
+	   (match_test ((-ival)  0xf000) == 0
+
 (define_register_constraint k STACK_REG
  @internal The stack register.)
 


Re: [PATCH][ARM] Add support for ADDW and SUBW instructions

2011-06-02 Thread Ramana Radhakrishnan
On 2 June 2011 10:03, Andrew Stubbs a...@codesourcery.com wrote:
 On 02/06/11 09:23, Ramana Radhakrishnan wrote:

 Please remove the alternatives in the subsi3 pattern since that is just
 unnecessary. Please make the constraints internal only.

 Is this better?


OK.

Ramana

 Andrew



Re: [PATCH][ARM] Add support for ADDW and SUBW instructions

2011-05-18 Thread Andrew Stubbs

Ping.

On 20/04/11 16:27, Andrew Stubbs wrote:

This patch adds basic support for the Thumb ADDW and SUBW instructions.

The patch permits the compiler to use the new instructions for constants
that can be loaded with a single instruction (i.e. 16-bit unshifted),
but does not support use of addw with split-constants; I have a patch
for that coming soon.

This patch requires that my previously posted patch for MOVW is applied
first.

OK?

Andrew




[PATCH][ARM] Add support for ADDW and SUBW instructions

2011-04-20 Thread Andrew Stubbs

This patch adds basic support for the Thumb ADDW and SUBW instructions.

The patch permits the compiler to use the new instructions for constants 
that can be loaded with a single instruction (i.e. 16-bit unshifted), 
but does not support use of addw with split-constants; I have a patch 
for that coming soon.


This patch requires that my previously posted patch for MOVW is applied 
first.


OK?

Andrew
2011-04-20  Andrew Stubbs  a...@codesourcery.com

	gcc/
	* config/arm/arm-protos.h (const_ok_for_op): Add prototype.
	* config/arm/arm.c (const_ok_for_op): Add support for addw/subw.
	Remove prototype. Remove static function type.
	* config/arm/arm.md (*arm_addsi3): Add addw/subw support.
	Add arch attribute.
	(*arm_subsi3_insn): Add subw support.
	Add arch attribute.
	* config/arm/constraints.md (Pj, PJ): New constraints.

--- 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_op (HOST_WIDE_INT, enum rtx_code);
 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 *);
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -82,7 +82,6 @@ inline static int thumb1_index_register_rtx_p (rtx, int);
 static bool arm_legitimate_address_p (enum machine_mode, rtx, bool);
 static int thumb_far_jump_used_p (void);
 static bool thumb_force_lr_save (void);
-static int const_ok_for_op (HOST_WIDE_INT, enum rtx_code);
 static rtx emit_sfm (int, int);
 static unsigned arm_size_return_regs (void);
 static bool arm_assemble_integer (rtx, unsigned int, int);
@@ -2453,7 +2452,7 @@ const_ok_for_arm (HOST_WIDE_INT i)
 }
 
 /* Return true if I is a valid constant for the operation CODE.  */
-static int
+int
 const_ok_for_op (HOST_WIDE_INT i, enum rtx_code code)
 {
   if (const_ok_for_arm (i))
@@ -2469,6 +2468,13 @@ const_ok_for_op (HOST_WIDE_INT i, enum rtx_code code)
 	return 0;
 
 case PLUS:
+  /* See if we can use addw or subw.  */
+  if (TARGET_THUMB2
+	   ((i  0xf000) == 0
+	  || ((-i)  0xf000) == 0))
+	return 1;
+  /* else fall through.  */
+
 case COMPARE:
 case EQ:
 case NE:
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -707,21 +707,24 @@
 ;;  (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, k, r, k,r, k, r)
+	(plus:SI (match_operand:SI 1 s_register_operand %rk,k,r,rk,k, rk,k,rk,k, rk)
+		 (match_operand:SI 2 reg_or_int_operand rI,rI,k,Pj,Pj,L, L,PJ,PJ,?n)))]
   TARGET_32BIT
   @
add%?\\t%0, %1, %2
add%?\\t%0, %1, %2
add%?\\t%0, %2, %1
+   addw%?\\t%0, %1, %2
+   addw%?\\t%0, %1, %2
sub%?\\t%0, %1, #%n2
sub%?\\t%0, %1, #%n2
+   subw%?\\t%0, %1, #%n2
+   subw%?\\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_op (INTVAL (operands[2]), PLUS)
 (reload_completed || !arm_eliminable_register (operands[1]))
   [(clobber (const_int 0))]
   
@@ -730,8 +733,9 @@
 		  operands[1], 0);
   DONE;
   
-  [(set_attr length 4,4,4,4,4,16)
-   (set_attr predicable yes)]
+  [(set_attr length 4,4,4,4,4,4,4,4,4,16)
+   (set_attr predicable yes)
+   (set_attr arch *,*,*,t2,t2,*,*,t2,t2,*)]
 )
 
 (define_insn_and_split *thumb1_addsi3
@@ -1184,28 +1188,33 @@
 
 ; ??? Check Thumb-2 split length
 (define_insn_and_split *arm_subsi3_insn
-  [(set (match_operand:SI   0 s_register_operand =r,r,rk,r,r)
-	(minus:SI (match_operand:SI 1 reg_or_int_operand rI,r,k,?n,r)
-		  (match_operand:SI 2 reg_or_int_operand r,rI,r, r,?n)))]
+  [(set (match_operand:SI   0 s_register_operand =r,r,rk,r, k, r,r)
+	(minus:SI (match_operand:SI 1 reg_or_int_operand rI,r,k, rk,k, ?n,r)
+		  (match_operand:SI 2 reg_or_int_operand r,rI,r, Pj,Pj,r,?n)))]
   TARGET_32BIT
   @
rsb%?\\t%0, %2, %1
sub%?\\t%0, %1, %2
sub%?\\t%0, %1, %2
+   subw%?\\t%0, %1, %2
+   subw%?\\t%0, %1, %2
#
#
((GET_CODE (operands[1]) == CONST_INT
-   	 !const_ok_for_arm (INTVAL (operands[1])))
+   	 !(const_ok_for_arm (INTVAL (operands[1]))
+	 || satisfies_constraint_Pj (operands[2])))
|| (GET_CODE (operands[2]) == CONST_INT
-	!const_ok_for_arm (INTVAL (operands[2]
+	!(const_ok_for_arm (INTVAL 

Re: [PATCH][ARM] Add support for ADDW and SUBW instructions

2011-04-20 Thread Andrew Stubbs

On 20/04/11 16:27, Andrew Stubbs wrote:

(*arm_subsi3_insn): Add subw support.


Oh, I should probably say that I've added subw support to arm_subsi3 
even though it's not obvious that anything will ever use this.


The existing implementation of arm_subsi3 (sans 'w') supports 
immediates, so I added subw to match.


If there are any objections, I expect I can remove that hunk of the patch.

Andrew