This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] h8300: Use inc/dec.


Hi,

Attached is a patch to use inc/dec instead of adds/subs in certain
cases.

Currently, a decrement followed by a conditional branch based on
inequality test looks like

  subs   #1,er4
  mov.w  r4,r4
  bne    .L2028

The test instruction in the middle can be removed if the decrement is
done by dec because it sets cc0.

  dec.w  #1,r4
  bne    .L2028

This kind of optimization is valid only for (in)equality tests.  The
patch implements the above transformation using a peephole and an
unspec insn representing inc/dec.

Tested on h8300 port.  Committed.

Kazu Hirata

2002-12-20  Kazu Hirata  <kazu@cs.umass.edu>

	* config/h8300/h8300-protos.h: Add prototypes for
	incdec_operand and eqne_operator.
	* config/h8300/h8300.c (incdec_operand): New.
	(eqne_operator): Likewise.
	* config/h8300/h8300.h (CONST_OK_FOR_M): Likewise.
	(CONST_OK_FOR_O): Likewise.
	(CONST_OK_FOR_LETTER_P): Use CONST_OK_FOR_M and
	CONST_OK_FOR_O.
	* config/h8300/h8300.md (UNSPEC_INCDEC): New.
	(addhi3_incdec): New.
	(addsi3_incdec): Likewise.
	(two peepholes): Likewise.

Index: h8300-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/h8300/h8300-protos.h,v
retrieving revision 1.34
diff -u -r1.34 h8300-protos.h
--- h8300-protos.h	28 Nov 2002 14:08:34 -0000	1.34
+++ h8300-protos.h	20 Dec 2002 20:42:34 -0000
@@ -59,8 +59,10 @@
 extern int jump_address_operand PARAMS ((rtx, enum machine_mode));
 extern int bit_operand PARAMS ((rtx, enum machine_mode));
 extern int bit_memory_operand PARAMS ((rtx, enum machine_mode));
+extern int incdec_operand PARAMS ((rtx, enum machine_mode));
 extern int bit_operator PARAMS ((rtx, enum machine_mode));
 extern int nshift_operator PARAMS ((rtx, enum machine_mode));
+extern int eqne_operator PARAMS ((rtx, enum machine_mode));
 
 extern int h8300_eightbit_constant_address_p PARAMS ((rtx));
 extern int h8300_tiny_constant_address_p PARAMS ((rtx));
Index: h8300.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/h8300/h8300.c,v
retrieving revision 1.178
diff -u -r1.178 h8300.c
--- h8300.c	20 Dec 2002 20:40:57 -0000	1.178
+++ h8300.c	20 Dec 2002 20:42:35 -0000
@@ -1806,6 +1806,30 @@
     }
 }
 
+/* Return nonzero if X is a constant suitable for inc/dec.  */
+
+int
+incdec_operand (x, mode)
+     rtx x;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+  return (GET_CODE (x) == CONST_INT
+	  && (CONST_OK_FOR_M (INTVAL (x))
+	      || CONST_OK_FOR_O (INTVAL (x))));
+}
+
+/* Return nonzero if X is either EQ or NE.  */
+
+int
+eqne_operator (x, mode)
+     rtx x;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
+{
+  enum rtx_code code = GET_CODE (x);
+
+  return (code == EQ || code == NE);
+}
+
 /* Recognize valid operators for bit instructions.  */
 
 int
Index: h8300.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/h8300/h8300.h,v
retrieving revision 1.124
diff -u -r1.124 h8300.h
--- h8300.h	16 Dec 2002 18:21:14 -0000	1.124
+++ h8300.h	20 Dec 2002 20:42:36 -0000
@@ -466,16 +466,22 @@
   (TARGET_H8300H || TARGET_H8300S			\
    ? (VALUE) == 1 || (VALUE) == 2 || (VALUE) == 4	\
    : (VALUE) == 1 || (VALUE) == 2)
+#define CONST_OK_FOR_M(VALUE)				\
+  ((VALUE) == 1 || (VALUE) == 2)
 #define CONST_OK_FOR_N(VALUE)				\
   (TARGET_H8300H || TARGET_H8300S			\
    ? (VALUE) == -1 || (VALUE) == -2 || (VALUE) == -4	\
    : (VALUE) == -1 || (VALUE) == -2)
+#define CONST_OK_FOR_O(VALUE)				\
+  ((VALUE) == -1 || (VALUE) == -2)
 
 #define CONST_OK_FOR_LETTER_P(VALUE, C)		\
   ((C) == 'I' ? CONST_OK_FOR_I (VALUE) :	\
    (C) == 'J' ? CONST_OK_FOR_J (VALUE) :	\
    (C) == 'L' ? CONST_OK_FOR_L (VALUE) :	\
+   (C) == 'M' ? CONST_OK_FOR_M (VALUE) :	\
    (C) == 'N' ? CONST_OK_FOR_N (VALUE) :	\
+   (C) == 'O' ? CONST_OK_FOR_O (VALUE) :	\
    0)
 
 /* Similar, but for floating constants, and defining letters G and H.
Index: h8300.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/h8300/h8300.md,v
retrieving revision 1.125
diff -u -r1.125 h8300.md
--- h8300.md	20 Dec 2002 00:08:06 -0000	1.125
+++ h8300.md	20 Dec 2002 20:42:36 -0000
@@ -51,6 +51,9 @@
 ;; ----------------------------------------------------------------------
 
 (define_constants
+  [(UNSPEC_INCDEC	0)])
+
+(define_constants
   [(SC_REG	 3)
    (FP_REG	 6)
    (SP_REG	 7)
@@ -794,6 +797,18 @@
   [(set_attr "length" "2,2,2,4,2")
    (set_attr "cc" "none_0hit,none_0hit,clobber,set_zn,set_zn")])
 
+(define_insn "addhi3_incdec"
+  [(set (match_operand:HI 0 "register_operand" "=r,r")
+	(unspec:HI [(match_operand:HI 1 "register_operand" "0,0")
+		    (match_operand:HI 2 "incdec_operand" "M,O")]
+		   UNSPEC_INCDEC))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "@
+   inc.w	%2,%T0
+   dec.w	%G2,%T0"
+  [(set_attr "length" "2,2")
+   (set_attr "cc" "set_zn,set_zn")])
+
 (define_split
   [(set (match_operand:HI 0 "register_operand" "")
 	(plus:HI (match_dup 0)
@@ -834,6 +849,18 @@
   [(set_attr "length" "2,2,6,2")
    (set_attr "cc" "none_0hit,none_0hit,set_zn,set_zn")])
 
+(define_insn "addsi3_incdec"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+	(unspec:SI [(match_operand:SI 1 "register_operand" "0,0")
+		    (match_operand:SI 2 "incdec_operand" "M,O")]
+		   UNSPEC_INCDEC))]
+  "TARGET_H8300H || TARGET_H8300S"
+  "@
+   inc.l	%2,%S0
+   dec.l	%G2,%S0"
+  [(set_attr "length" "2,2")
+   (set_attr "cc" "set_zn,set_zn")])
+
 (define_split
   [(set (match_operand:SI 0 "register_operand" "")
 	(plus:SI (match_dup 0)
@@ -2783,4 +2810,65 @@
    (set (match_dup 0)
 	(plus:SI (match_dup 0)
 		 (match_dup 1)))]
+  "")
+
+;; Turn
+;;
+;;   subs   #1,er4
+;;   mov.w  r4,r4
+;;   bne    .L2028
+;;
+;; into
+;;
+;;   dec.w  #1,r4
+;;   bne    .L2028
+
+(define_peephole2
+  [(set (match_operand:HI 0 "register_operand" "")
+	(plus:HI (match_dup 0)
+		 (match_operand 1 "incdec_operand" "")))
+   (set (cc0)
+	(match_dup 0))
+   (set (pc)
+	(if_then_else (match_operator 3 "eqne_operator"
+			[(cc0) (const_int 0)])
+		      (label_ref (match_operand 2 "" ""))
+		      (pc)))]
+  "TARGET_H8300H || TARGET_H8300S"
+  [(set (match_operand:HI 0 "register_operand" "")
+	(unspec:HI [(match_dup 0)
+		    (match_dup 1)]
+		   UNSPEC_INCDEC))
+   (set (cc0)
+	(match_dup 0))
+   (set (pc)
+	(if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+		      (label_ref (match_dup 2))
+		      (pc)))]
+  "")
+
+;; The SImode version of the previous pattern.
+
+(define_peephole2
+  [(set (match_operand:SI 0 "register_operand" "")
+	(plus:SI (match_dup 0)
+		 (match_operand 1 "incdec_operand" "")))
+   (set (cc0)
+	(match_dup 0))
+   (set (pc)
+	(if_then_else (match_operator 3 "eqne_operator"
+			[(cc0) (const_int 0)])
+		      (label_ref (match_operand 2 "" ""))
+		      (pc)))]
+  "TARGET_H8300H || TARGET_H8300S"
+  [(set (match_operand:SI 0 "register_operand" "")
+	(unspec:SI [(match_dup 0)
+		    (match_dup 1)]
+		   UNSPEC_INCDEC))
+   (set (cc0)
+	(match_dup 0))
+   (set (pc)
+	(if_then_else (match_op_dup 3 [(cc0) (const_int 0)])
+		      (label_ref (match_dup 2))
+		      (pc)))]
   "")


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]