This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch] Optimize logical operations in the h8300 port. (revised)
- To: gcc-patches at gcc dot gnu dot org
- Subject: [patch] Optimize logical operations in the h8300 port. (revised)
- From: Kazu Hirata <kazu at hxi dot com>
- CC: law at redhat dot com
Hi,
Attached is a revised version of
http://gcc.gnu.org/ml/gcc-patches/2001-07/msg00897.html
I changed emit_logical_op to output_logical_op. Also, I revised a comment:
/* Take care of the lower byte. */
to
/* Take care of the upper byte. */
Bootstrapped. (I don't think the entire regression testing is
necessary this time because the above changes are minimal.) OK to
apply?
Kazu Hirata
2001-08-29 Kazu Hirata <kazu@hxi.com>
* config/h8300/h8300-protos.h: Add a prototype for
emit_logical_op.
* config/h8300/h8300.c (emit_logical_op): New.
* config/h8300/h8300.md (andhi3): Use emit_logical_op.
(andsi3): Likewise.
(iorhi3): Likewise.
(iorsi3): Likewise.
(xorhi3): Likewise.
(xorsi3): Likewise.
Index: h8300-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/h8300/h8300-protos.h,v
retrieving revision 1.10
diff -c -r1.10 h8300-protos.h
*** h8300-protos.h 2001/07/23 21:46:37 1.10
--- h8300-protos.h 2001/08/29 16:56:07
***************
*** 37,42 ****
--- 37,43 ----
extern void final_prescan_insn PARAMS ((rtx, rtx *, int));
extern int do_movsi PARAMS ((rtx[]));
extern void notice_update_cc PARAMS ((rtx, rtx));
+ extern const char *output_logical_op PARAMS ((enum machine_mode, int, rtx *));
extern int expand_a_shift PARAMS ((enum machine_mode, int, rtx[]));
extern int expand_a_rotate PARAMS ((int, rtx[]));
extern int fix_bit_operand PARAMS ((rtx *, int, enum rtx_code));
Index: h8300.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/h8300/h8300.c,v
retrieving revision 1.64
diff -c -r1.64 h8300.c
*** h8300.c 2001/08/17 02:33:32 1.64
--- h8300.c 2001/08/29 16:56:08
***************
*** 1601,1606 ****
--- 1601,1750 ----
|| code == IOR);
}
+ const char *
+ output_logical_op (mode, code, operands)
+ enum machine_mode mode;
+ int code;
+ rtx *operands;
+ {
+ /* Pretend that every byte is affected if both operands are registers. */
+ unsigned HOST_WIDE_INT intval =
+ (unsigned HOST_WIDE_INT) ((GET_CODE (operands[2]) == CONST_INT)
+ ? INTVAL (operands[2]) : 0x55555555);
+ /* The determinant of the algorithm. If we perform an AND, 0
+ affects a bit. Otherwise, 1 affects a bit. */
+ unsigned HOST_WIDE_INT det = (code != AND) ? intval : ~intval;
+ /* The name of an insn. */
+ const char *opname;
+ char insn_buf[100];
+
+ switch (code)
+ {
+ case AND:
+ opname = "and";
+ break;
+ case IOR:
+ opname = "or";
+ break;
+ case XOR:
+ opname = "xor";
+ break;
+ default:
+ abort ();
+ }
+
+ switch (mode)
+ {
+ case HImode:
+ /* First, see if we can finish with one insn. */
+ if ((TARGET_H8300H || TARGET_H8300S)
+ && ((det & 0x00ff) != 0)
+ && ((det & 0xff00) != 0))
+ {
+ sprintf (insn_buf, "%s.w\t%%T2,%%T0", opname);
+ output_asm_insn (insn_buf, operands);
+ }
+ else
+ {
+ /* Take care of the lower byte. */
+ if ((det & 0x00ff) != 0)
+ {
+ sprintf (insn_buf, "%s\t%%s2,%%s0", opname);
+ output_asm_insn (insn_buf, operands);
+ }
+ /* Take care of the upper byte. */
+ if ((det & 0xff00) != 0)
+ {
+ sprintf (insn_buf, "%s\t%%t2,%%t0", opname);
+ output_asm_insn (insn_buf, operands);
+ }
+ }
+ break;
+ case SImode:
+ /* First, see if we can finish with one insn.
+
+ If code is either AND or XOR, we exclude two special cases,
+ 0xffffff00 and 0xffff00ff, because insns like sub.w or neg.w
+ can do a better job. */
+ if ((TARGET_H8300H || TARGET_H8300S)
+ && ((det & 0x0000ffff) != 0)
+ && ((det & 0xffff0000) != 0)
+ && (code == IOR || det != 0xffffff00)
+ && (code == IOR || det != 0xffff00ff))
+ {
+ sprintf (insn_buf, "%s.l\t%%S2,%%S0", opname);
+ output_asm_insn (insn_buf, operands);
+ }
+ else
+ {
+ /* Take care of the lower and upper words individually. For
+ each word, we try different methods in the order of
+
+ 1) the special insn (in case of AND or XOR),
+ 2) the word-wise insn, and
+ 3) The byte-wise insn. */
+ if ((TARGET_H8300H || TARGET_H8300S)
+ && ((det & 0x0000ffff) == 0x0000ffff)
+ && code != IOR)
+ output_asm_insn ((code == AND)
+ ? "sub.w\t%f0,%f0" : "neg.w\t%f0",
+ operands);
+ else if ((TARGET_H8300H || TARGET_H8300S)
+ && ((det & 0x000000ff) != 0)
+ && ((det & 0x0000ff00) != 0))
+ {
+ sprintf (insn_buf, "%s.w\t%%f2,%%f0", opname);
+ output_asm_insn (insn_buf, operands);
+ }
+ else
+ {
+ if ((det & 0x000000ff) != 0)
+ {
+ sprintf (insn_buf, "%s\t%%w2,%%w0", opname);
+ output_asm_insn (insn_buf, operands);
+ }
+ if ((det & 0x0000ff00) != 0)
+ {
+ sprintf (insn_buf, "%s\t%%x2,%%x0", opname);
+ output_asm_insn (insn_buf, operands);
+ }
+ }
+
+ if ((TARGET_H8300H || TARGET_H8300S)
+ && ((det & 0xffff0000) == 0xffff0000)
+ && code != IOR)
+ output_asm_insn ((code == AND)
+ ? "sub.w\t%e0,%e0" : "neg.w\t%e0",
+ operands);
+ else if (TARGET_H8300H || TARGET_H8300S)
+ {
+ if ((det & 0xffff0000) != 0)
+ {
+ sprintf (insn_buf, "%s.w\t%%e2,%%e0", opname);
+ output_asm_insn (insn_buf, operands);
+ }
+ }
+ else
+ {
+ if ((det & 0x00ff0000) != 0)
+ {
+ sprintf (insn_buf, "%s\t%%y2,%%y0", opname);
+ output_asm_insn (insn_buf, operands);
+ }
+ if ((det & 0xff000000) != 0)
+ {
+ sprintf (insn_buf, "%s\t%%z2,%%z0", opname);
+ output_asm_insn (insn_buf, operands);
+ }
+ }
+ }
+ break;
+ default:
+ abort ();
+ }
+ return "";
+ }
+
/* Shifts.
We devote a fair bit of code to getting efficient shifts since we can only
Index: h8300.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/h8300/h8300.md,v
retrieving revision 1.34
diff -c -r1.34 h8300.md
*** h8300.md 2001/08/29 16:17:25 1.34
--- h8300.md 2001/08/29 16:56:08
***************
*** 988,1070 ****
DONE;
}")
! (define_insn "andhi3"
[(set (match_operand:HI 0 "register_operand" "=r")
(and:HI (match_operand:HI 1 "register_operand" "%0")
(match_operand:HI 2 "nonmemory_operand" "rn")))]
! ""
! "*
! {
! if (GET_CODE (operands[2]) == CONST_INT)
! {
! int i = INTVAL (operands[2]);
!
! if ((i & 0x00ff) != 0x00ff)
! output_asm_insn (\"and %s2,%s0\", operands);
! if ((i & 0xff00) != 0xff00)
! output_asm_insn (\"and %t2,%t0\", operands);
! return \"\";
! }
! if (TARGET_H8300H || TARGET_H8300S)
! return \"and.w %T2,%T0\";
! return \"and %s2,%s0\;and %t2,%t0;\";
! }"
[(set_attr "length" "4")
(set_attr "cc" "clobber")])
! (define_insn "andsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
(and:SI (match_operand:SI 1 "register_operand" "%0")
(match_operand:SI 2 "nonmemory_operand" "rn")))]
! ""
! "*
! {
! if (GET_CODE (operands[2]) == CONST_INT)
! {
! int i = INTVAL (operands[2]);
! int upper_cleared, lower_cleared;
!
! /* The h8300h can't do byte-wise operations on the
! upper 16bits of 32bit registers. However, if
! those bits aren't going to change, or they're
! going to be zero'd out, then we can work on the
! low-order bits. */
! if ((TARGET_H8300H || TARGET_H8300S)
! && ((i & 0xffff0000) != 0xffff0000
! || (i & 0xffff0000) == 0x00000000))
! return \"and.l %S2,%S0\";
!
! lower_cleared = 0;
! if ((i & 0x0000ffff) == 0x00000000)
! {
! output_asm_insn (\"sub.w %f0,%f0\", operands);
! lower_cleared = 1;
! }
!
! upper_cleared = 0;
! if ((i & 0xffff0000) == 0x00000000)
! {
! output_asm_insn (\"sub.w %e0,%e0\", operands);
! upper_cleared = 1;
! }
!
! if ((i & 0x000000ff) != 0x000000ff && !lower_cleared)
! output_asm_insn (\"and %w2,%w0\", operands);
! if ((i & 0x0000ff00) != 0x0000ff00 && !lower_cleared)
! output_asm_insn (\"and %x2,%x0\", operands);
! if ((i & 0x00ff0000) != 0x00ff0000 && !upper_cleared)
! output_asm_insn (\"and %y2,%y0\", operands);
! if ((i & 0xff000000) != 0xff000000 && !upper_cleared)
! output_asm_insn (\"and %z2,%z0\", operands);
! return \"\";
! }
! if (TARGET_H8300H || TARGET_H8300S)
! return \"and.l %S2,%S0\";
! return \"and %w2,%w0\;and %x2,%x0\;and %y2,%y0\;and %z2,%z0\";
! }"
[(set_attr "length" "8")
(set_attr "cc" "clobber")])
;; ----------------------------------------------------------------------
;; OR INSTRUCTIONS
--- 988,1042 ----
DONE;
}")
! (define_expand "andhi3"
! [(set (match_operand:HI 0 "register_operand" "")
! (and:HI (match_operand:HI 1 "register_operand" "")
! (match_operand:HI 2 "nonmemory_operand" "")))]
! ""
! "")
!
! (define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r")
(and:HI (match_operand:HI 1 "register_operand" "%0")
(match_operand:HI 2 "nonmemory_operand" "rn")))]
! "TARGET_H8300"
! "* return output_logical_op (HImode, AND, operands);"
[(set_attr "length" "4")
(set_attr "cc" "clobber")])
+
+ (define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=r,r")
+ (and:HI (match_operand:HI 1 "register_operand" "%0,0")
+ (match_operand:HI 2 "nonmemory_operand" "r,n")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "* return output_logical_op (HImode, AND, operands);"
+ [(set_attr "length" "2,4")
+ (set_attr "cc" "set_znv,clobber")])
+
+ (define_expand "andsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (and:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))]
+ ""
+ "")
! (define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(and:SI (match_operand:SI 1 "register_operand" "%0")
(match_operand:SI 2 "nonmemory_operand" "rn")))]
! "TARGET_H8300"
! "* return output_logical_op (SImode, AND, operands);"
[(set_attr "length" "8")
(set_attr "cc" "clobber")])
+ (define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (and:SI (match_operand:SI 1 "register_operand" "%0,0")
+ (match_operand:SI 2 "nonmemory_operand" "r,n")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "* return output_logical_op (SImode, AND, operands);"
+ [(set_attr "length" "4,6")
+ (set_attr "cc" "set_znv,clobber")])
;; ----------------------------------------------------------------------
;; OR INSTRUCTIONS
***************
*** 1093,1158 ****
DONE;
}")
! (define_insn "iorhi3"
[(set (match_operand:HI 0 "general_operand" "=r,r")
(ior:HI (match_operand:HI 1 "general_operand" "%0,0")
(match_operand:HI 2 "general_operand" "J,rn")))]
""
! "*
! {
! if (GET_CODE (operands[2]) == CONST_INT)
! {
! int i = INTVAL (operands[2]);
!
! if ((i & 0x00ff) != 0)
! output_asm_insn (\"or %s2,%s0\", operands);
! if ((i & 0xff00) != 0)
! output_asm_insn (\"or %t2,%t0\", operands);
! return \"\";
! }
! if (TARGET_H8300H || TARGET_H8300S)
! return \"or.w %T2,%T0\";
! return \"or %s2,%s0\;or %t2,%t0; %2 or2\";
! }"
[(set_attr "length" "2,4")
(set_attr "cc" "clobber,clobber")])
! (define_insn "iorsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(ior:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "J,rn")))]
! ""
! "*
! {
! if (GET_CODE (operands[2]) == CONST_INT)
! {
! int i = INTVAL (operands[2]);
!
! /* The h8300h can't do byte-wise operations on the
! upper 16bits of 32bit registers. However, if
! those bits aren't going to change, then we can
! work on the low-order bits. */
! if ((TARGET_H8300H || TARGET_H8300S)
! && (i & 0xffff0000) != 0x00000000)
! return \"or.l %S2,%S0\";
!
! if ((i & 0x000000ff) != 0)
! output_asm_insn (\"or %w2,%w0\", operands);
! if ((i & 0x0000ff00) != 0)
! output_asm_insn (\"or %x2,%x0\", operands);
! if ((i & 0x00ff0000) != 0)
! output_asm_insn (\"or %y2,%y0\", operands);
! if ((i & 0xff000000) != 0)
! output_asm_insn (\"or %z2,%z0\", operands);
! return \"\";
! }
! if (TARGET_H8300H || TARGET_H8300S)
! return \"or.l %S2,%S0\";
! return \"or %w2,%w0\;or %x2,%x0\;or %y2,%y0\;or %z2,%z0\";
! }"
[(set_attr "length" "2,8")
(set_attr "cc" "clobber,clobber")])
;; ----------------------------------------------------------------------
;; XOR INSTRUCTIONS
;; ----------------------------------------------------------------------
--- 1065,1120 ----
DONE;
}")
! (define_expand "iorhi3"
[(set (match_operand:HI 0 "general_operand" "=r,r")
(ior:HI (match_operand:HI 1 "general_operand" "%0,0")
(match_operand:HI 2 "general_operand" "J,rn")))]
""
! "")
!
! (define_insn ""
! [(set (match_operand:HI 0 "general_operand" "=r,r")
! (ior:HI (match_operand:HI 1 "general_operand" "%0,0")
! (match_operand:HI 2 "general_operand" "J,rn")))]
! "TARGET_H8300"
! "* return output_logical_op (HImode, IOR, operands);"
[(set_attr "length" "2,4")
(set_attr "cc" "clobber,clobber")])
! (define_insn ""
! [(set (match_operand:HI 0 "general_operand" "=r,r,r")
! (ior:HI (match_operand:HI 1 "general_operand" "%0,0,0")
! (match_operand:HI 2 "general_operand" "J,r,n")))]
! "TARGET_H8300H || TARGET_H8300S"
! "* return output_logical_op (HImode, IOR, operands);"
! [(set_attr "length" "2,2,4")
! (set_attr "cc" "clobber,set_znv,clobber")])
!
! (define_expand "iorsi3"
! [(set (match_operand:SI 0 "register_operand" "")
! (ior:SI (match_operand:SI 1 "register_operand" "")
! (match_operand:SI 2 "nonmemory_operand" "")))]
! ""
! "")
!
! (define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
(ior:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "J,rn")))]
! "TARGET_H8300"
! "* return output_logical_op (SImode, IOR, operands);"
[(set_attr "length" "2,8")
(set_attr "cc" "clobber,clobber")])
+ (define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+ (ior:SI (match_operand:SI 1 "register_operand" "%0,0,0")
+ (match_operand:SI 2 "nonmemory_operand" "J,r,n")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "* return output_logical_op (SImode, IOR, operands);"
+ [(set_attr "length" "2,4,6")
+ (set_attr "cc" "clobber,set_znv,clobber")])
+
;; ----------------------------------------------------------------------
;; XOR INSTRUCTIONS
;; ----------------------------------------------------------------------
***************
*** 1180,1244 ****
DONE;
}")
! (define_insn "xorhi3"
[(set (match_operand:HI 0 "register_operand" "=r,r")
(xor:HI (match_operand:HI 1 "general_operand" "%0,0")
(match_operand:HI 2 "nonmemory_operand" "J,rn")))]
! ""
! "*
! {
! if (GET_CODE (operands[2]) == CONST_INT)
! {
! int i = INTVAL (operands[2]);
!
! if ((i & 0x00ff) != 0)
! output_asm_insn (\"xor %s2,%s0\", operands);
! if ((i & 0xff00) != 0)
! output_asm_insn (\"xor %t2,%t0\", operands);
! return \"\";
! }
! if (TARGET_H8300H || TARGET_H8300S)
! return \"xor.w %T2,%T0\";
! return \"xor %s2,%s0\;xor %t2,%t0\";
! }"
[(set_attr "length" "2,4")
(set_attr "cc" "clobber,clobber")])
! (define_insn "xorsi3"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(xor:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "J,rn")))]
! ""
! "*
! {
! if (GET_CODE (operands[2]) == CONST_INT)
! {
! int i = INTVAL (operands[2]);
!
! /* The h8300h can't do byte-wise operations on the
! upper 16bits of 32bit registers. However, if
! those bits aren't going to change, then we can
! work on the low-order bits. */
! if ((TARGET_H8300H || TARGET_H8300S)
! && (i & 0xffff0000) != 0x00000000)
! return \"xor.l %S2,%S0\";
!
! if ((i & 0x000000ff) != 0)
! output_asm_insn (\"xor %w2,%w0\", operands);
! if ((i & 0x0000ff00) != 0)
! output_asm_insn (\"xor %x2,%x0\", operands);
! if ((i & 0x00ff0000) != 0)
! output_asm_insn (\"xor %y2,%y0\", operands);
! if ((i & 0xff000000) != 0)
! output_asm_insn (\"xor %z2,%z0\", operands);
! return \"\";
! }
! if (TARGET_H8300H || TARGET_H8300S)
! return \"xor.l %S2,%S0\";
! return \"xor %w2,%w0\;xor %x2,%x0\;xor %y2,%y0\;xor %z2,%z0\";
! }"
[(set_attr "length" "2,8")
(set_attr "cc" "clobber,clobber")])
;; ----------------------------------------------------------------------
;; NEGATION INSTRUCTIONS
--- 1142,1196 ----
DONE;
}")
! (define_expand "xorhi3"
! [(set (match_operand:HI 0 "register_operand" "")
! (xor:HI (match_operand:HI 1 "general_operand" "")
! (match_operand:HI 2 "nonmemory_operand" "")))]
! ""
! "")
!
! (define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r")
(xor:HI (match_operand:HI 1 "general_operand" "%0,0")
(match_operand:HI 2 "nonmemory_operand" "J,rn")))]
! "TARGET_H8300"
! "* return output_logical_op (HImode, XOR, operands);"
[(set_attr "length" "2,4")
(set_attr "cc" "clobber,clobber")])
+
+ (define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=r,r,r")
+ (xor:HI (match_operand:HI 1 "general_operand" "%0,0,0")
+ (match_operand:HI 2 "nonmemory_operand" "J,r,n")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "* return output_logical_op (HImode, XOR, operands);"
+ [(set_attr "length" "2,2,4")
+ (set_attr "cc" "clobber,set_znv,clobber")])
+
+ (define_expand "xorsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (xor:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "nonmemory_operand" "")))]
+ ""
+ "")
! (define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
(xor:SI (match_operand:SI 1 "register_operand" "%0,0")
(match_operand:SI 2 "nonmemory_operand" "J,rn")))]
! "TARGET_H8300"
! "* return output_logical_op (SImode, XOR, operands);"
[(set_attr "length" "2,8")
(set_attr "cc" "clobber,clobber")])
+
+ (define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+ (xor:SI (match_operand:SI 1 "register_operand" "%0,0,0")
+ (match_operand:SI 2 "nonmemory_operand" "J,r,n")))]
+ "TARGET_H8300H || TARGET_H8300S"
+ "* return output_logical_op (SImode, XOR, operands);"
+ [(set_attr "length" "2,4,6")
+ (set_attr "cc" "clobber,set_znv,clobber")])
;; ----------------------------------------------------------------------
;; NEGATION INSTRUCTIONS