aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Law <law@gcc.gnu.org>1996-05-01 16:41:55 -0600
committerJeff Law <law@gcc.gnu.org>1996-05-01 16:41:55 -0600
commitdd4fd0a0fdeed482a3159b5579564b227041f87e (patch)
tree8edf7a26211bf37aa69cb7eae40f8e507b2dd71c
parent17d6fedc573f97792a04b363e59a030584de2459 (diff)
downloadgcc-dd4fd0a0fdeed482a3159b5579564b227041f87e.zip
gcc-dd4fd0a0fdeed482a3159b5579564b227041f87e.tar.gz
gcc-dd4fd0a0fdeed482a3159b5579564b227041f87e.tar.bz2
h8300.c (h8300_adjust_insn_length): Adjust the cost of shifts by small constant values.
* h8300/h8300.c (h8300_adjust_insn_length): Adjust the cost of shifts by small constant values. * h8300/h8300.md: Refine comments. Remove names from many patterns which don't need them. (compare insns): Don't underestimate lengths. (andqi3 expander): Remove constrains. (andhi3): Don't underestimate length. (andsi3): Don't underestimate length. Improve code when upper or lower half of destination is being cleared. (indirect_jump_h8300, indirect_jump_h8300h): Simplify. (shift insns): Remove useless "I" constraint. From-SVN: r11912
-rw-r--r--gcc/config/h8300/h8300.c41
-rw-r--r--gcc/config/h8300/h8300.md169
2 files changed, 128 insertions, 82 deletions
diff --git a/gcc/config/h8300/h8300.c b/gcc/config/h8300/h8300.c
index 87e45e4..60203d1 100644
--- a/gcc/config/h8300/h8300.c
+++ b/gcc/config/h8300/h8300.c
@@ -2342,5 +2342,46 @@ h8300_adjust_insn_length (insn, length)
}
}
+ /* Shifts need various adjustments. */
+ if (GET_CODE (pat) == PARALLEL
+ && GET_CODE (XVECEXP (pat, 0, 0)) == SET
+ && (GET_CODE (SET_SRC (XVECEXP (pat, 0, 0))) == ASHIFTRT
+ || GET_CODE (SET_SRC (XVECEXP (pat, 0, 0))) == LSHIFTRT
+ || GET_CODE (SET_SRC (XVECEXP (pat, 0, 0))) == ASHIFT))
+ {
+ rtx src = SET_SRC (XVECEXP (pat, 0, 0));
+ enum machine_mode mode = GET_MODE (src);
+
+ if (GET_CODE (XEXP (src, 1)) != CONST_INT)
+ return 0;
+
+ /* QImode shifts by small constants take one insn
+ per shift. So the adjustment is 20 (md length) -
+ # shifts * 2. */
+ if (mode == QImode && INTVAL (XEXP (src, 1)) <= 4)
+ return -(20 - INTVAL (XEXP (src, 1)) * 2);
+
+ /* Similarly for HImode and SImode shifts by
+ small constants on the H8/300H. */
+ if (TARGET_H8300H
+ && (mode == HImode || mode == SImode)
+ && INTVAL (XEXP (src, 1)) <= 4)
+ return -(20 - INTVAL (XEXP (src, 1)) * 2);
+
+ /* HImode shifts by small constants for the H8/300. */
+ if (mode == HImode
+ && INTVAL (XEXP (src, 1)) <= 4)
+ return -(20 - (INTVAL (XEXP (src, 1))
+ * (GET_CODE (src) == ASHIFT ? 2 : 4)));
+
+ /* SImode shifts by small constants for the H8/300. */
+ if (mode == SImode
+ && INTVAL (XEXP (src, 1)) <= 2)
+ return -(20 - (INTVAL (XEXP (src, 1))
+ * (GET_CODE (src) == ASHIFT ? 6 : 8)));
+
+ /* XXX ??? Could check for more shift/rotate cases here. */
+ }
+
return 0;
}
diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md
index b4fba57..be2fb15 100644
--- a/gcc/config/h8300/h8300.md
+++ b/gcc/config/h8300/h8300.md
@@ -32,7 +32,16 @@
;; Many logical operations should have "bit" variants if only one
;; bit is going to be operated on.
-;; Should be HI & SImode tstXX insns which test one bit using btst.
+;; (and (logical op) (const_int X))
+;; If const_int only specifies a few bits (like a single byte in a 4 byte
+;; operation, then it's more efficient to only apply the and and logical_op
+;; to the bits we care about.
+
+;; Some of the extend instructions accept a general_operand_src, which
+;; allows all the normal memory addressing modes. The length computations
+;; don't take this into account. The lengths in the MD file should be
+;; "worst case" and then be adjusted to their correct values by
+;; h8300_adjust_insn_length.
;; On the h8300h, adds/subs operate on the 32bit "er" registers. Right
;; now GCC doesn't expose the "e" half to the compiler, so using add/subs
@@ -43,6 +52,12 @@
;; There's currently no way to have a insv/extzv expander for the h8/300h
;; because word_mode is different for the h8/300 and h8/300h.
+;; Shifts/rotates by small constants should be handled by special
+;; patterns so we get the length and cc status correct.
+
+;; Bitfield operations no longer accept memory operands. We need
+;; to add variants which operate on memory back to the MD.
+
;; ??? Implement remaining bit ops available on the h8300
(define_attr "type" "branch,arith"
@@ -100,7 +115,7 @@
[(set (attr "length") (if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4)))
(set_attr "cc" "set")])
-(define_insn "movqi_internal"
+(define_insn ""
[(set (match_operand:QI 0 "general_operand_dst" "=r,r,<,r,o")
(match_operand:QI 1 "general_operand_src" "I,r>,r,io,r"))]
"register_operand (operands[0],QImode)
@@ -162,7 +177,7 @@
[(set (attr "length") (if_then_else (eq_attr "cpu" "h8300") (const_int 2) (const_int 4)))
(set_attr "cc" "set")])
-(define_insn "movhi_internal"
+(define_insn ""
[(set (match_operand:HI 0 "general_operand_dst" "=r,r,<,r,o")
(match_operand:HI 1 "general_operand_src" "I,r>,r,io,r"))]
"register_operand (operands[0],HImode)
@@ -511,28 +526,28 @@
[(set (cc0)
(compare:HI (match_operand:HI 0 "register_operand" "r")
(match_operand:HI 1 "register_operand" "r")))]
- "!TARGET_H8300H"
+ "TARGET_H8300"
"cmp.w %T1,%T0"
[(set_attr "length" "2")
(set_attr "cc" "compare")])
(define_insn ""
[(set (cc0)
- (compare:HI (match_operand:HI 0 "register_operand" "r")
- (match_operand:HI 1 "nonmemory_operand" "ri")))]
+ (compare:HI (match_operand:HI 0 "register_operand" "r,r")
+ (match_operand:HI 1 "nonmemory_operand" "r,i")))]
"TARGET_H8300H"
"cmp.w %T1,%T0"
- [(set_attr "length" "2")
- (set_attr "cc" "compare")])
+ [(set_attr "length" "2,4")
+ (set_attr "cc" "compare,compare")])
(define_insn "cmpsi"
[(set (cc0)
- (compare:SI (match_operand:SI 0 "register_operand" "r")
- (match_operand:SI 1 "nonmemory_operand" "ri")))]
+ (compare:SI (match_operand:SI 0 "register_operand" "r,r")
+ (match_operand:SI 1 "nonmemory_operand" "r,i")))]
"TARGET_H8300H"
"cmp.l %S1,%S0"
- [(set_attr "length" "2")
- (set_attr "cc" "compare")])
+ [(set_attr "length" "2,6")
+ (set_attr "cc" "compare,compare")])
;; ----------------------------------------------------------------------
;; ADD INSTRUCTIONS
@@ -622,8 +637,8 @@
"@
add %w2,%w0\;addx %x2,%x0\;addx %y2,%y0\;addx %z2,%z0
add.w %f2,%f0\;addx %y2,%y0\;addx %z2,%z0
- mov %f1,%f0\;mov %e1,%e0\;add.w %f2,%f0\;addx %y2,%y0\;addx %z2,%z0"
- [(set_attr "length" "8,6,20")
+ mov.w %f1,%f0\;mov.w %e1,%e0\;add.w %f2,%f0\;addx %y2,%y0\;addx %z2,%z0"
+ [(set_attr "length" "8,6,10")
(set_attr "cc" "clobber")])
(define_insn "addsi_h8300h"
@@ -686,7 +701,7 @@
"TARGET_H8300"
"@
sub.w %T2,%T0
- add.b %E2,%s0\;addx %F2,%t0 ; -%0"
+ add.b %E2,%s0\;addx %F2,%t0"
[(set_attr "length" "2,4")
(set_attr "cc" "set_zn_c0,clobber")])
@@ -876,7 +891,7 @@
;; AND INSTRUCTIONS
;; ----------------------------------------------------------------------
-(define_insn "andqi3_internal"
+(define_insn ""
[(set (match_operand:QI 0 "bit_operand" "=r,U")
(and:QI (match_operand:QI 1 "bit_operand" "%0,0")
(match_operand:QI 2 "nonmemory_operand" "rn,O")))]
@@ -888,9 +903,9 @@
(set_attr "cc" "set,none_0hit")])
(define_expand "andqi3"
- [(set (match_operand:QI 0 "bit_operand" "=r,U")
- (and:QI (match_operand:QI 1 "bit_operand" "%0,0")
- (match_operand:QI 2 "nonmemory_operand" "rn,O")))]
+ [(set (match_operand:QI 0 "bit_operand" "")
+ (and:QI (match_operand:QI 1 "bit_operand" "")
+ (match_operand:QI 2 "nonmemory_operand" "")))]
""
"
{
@@ -899,9 +914,9 @@
}")
(define_insn "andhi3"
- [(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" "J,rn")))]
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (and:HI (match_operand:HI 1 "register_operand" "%0")
+ (match_operand:HI 2 "nonmemory_operand" "rn")))]
""
"*
{
@@ -919,38 +934,52 @@
return \"and.w %T2,%T0\";
return \"and %s2,%s0\;and %t2,%t0;\";
}"
- [(set_attr "length" "2,4")
- (set_attr "cc" "clobber,clobber")])
+ [(set_attr "length" "4")
+ (set_attr "cc" "clobber")])
(define_insn "andsi3"
- [(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" "J,rn")))]
+ [(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]);
-
- /* ??? If we used e0..e7, then we could sub.w eX,eX to
- clear the high word if (i & 0xffff0000) == 0. */
+ 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, then we can
- work on the low-order bits. */
+ 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
- && (i & 0xffff0000) != 0xffff0000)
+ && ((i & 0xffff0000) != 0xffff0000
+ || (i & 0xffff0000) == 0x00000000))
return \"and.l %S2,%S0\";
- if ((i & 0x000000ff) != 0x000000ff)
+ 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)
+ if ((i & 0x0000ff00) != 0x0000ff00 && !lower_cleared)
output_asm_insn (\"and %x2,%x0\", operands);
- if ((i & 0x00ff0000) != 0x00ff0000)
+ if ((i & 0x00ff0000) != 0x00ff0000 && !upper_cleared)
output_asm_insn (\"and %y2,%y0\", operands);
- if ((i & 0xff000000) != 0xff000000)
+ if ((i & 0xff000000) != 0xff000000 && !upper_cleared)
output_asm_insn (\"and %z2,%z0\", operands);
return \"\";
}
@@ -958,14 +987,15 @@
return \"and.l %S2,%S0\";
return \"and %w2,%w0\;and %x2,%x0\;and %y2,%y0\;and %z2,%z0\;\";
}"
- [(set_attr "length" "2,8")
- (set_attr "cc" "clobber,clobber")])
+ [(set_attr "length" "8")
+ (set_attr "cc" "clobber")])
+
;; ----------------------------------------------------------------------
;; OR INSTRUCTIONS
;; ----------------------------------------------------------------------
-(define_insn "iorqi3_internal"
+(define_insn ""
[(set (match_operand:QI 0 "bit_operand" "=r,U")
(ior:QI (match_operand:QI 1 "bit_operand" "%0,0")
(match_operand:QI 2 "nonmemory_operand" "rn,P")))]
@@ -1051,7 +1081,7 @@
;; XOR INSTRUCTIONS
;; ----------------------------------------------------------------------
-(define_insn "xorqi3_internal"
+(define_insn ""
[(set (match_operand:QI 0 "bit_operand" "=r,U")
(xor:QI (match_operand:QI 1 "bit_operand" "%0,0")
(match_operand:QI 2 "nonmemory_operand" "rn,P")))]
@@ -1231,7 +1261,7 @@
[(set_attr "cc" "clobber")
(set (attr "length")
(if_then_else (eq (symbol_ref "TARGET_H8300H") (const_int 0))
- (const_int 8)
+ (const_int 4)
(const_int 2)))])
(define_insn "one_cmplsi2"
@@ -1441,25 +1471,21 @@
;; This is a define expand, because pointers may be either 16 or 32 bits.
(define_expand "indirect_jump"
- [(set (pc) (match_operand 0 "jump_address_operand" "Vr"))]
+ [(set (pc) (match_operand 0 "jump_address_operand" ""))]
""
"")
(define_insn "indirect_jump_h8300"
- [(set (pc) (match_operand:HI 0 "jump_address_operand" "V,r"))]
+ [(set (pc) (match_operand:HI 0 "jump_address_operand" "Vr"))]
"TARGET_H8300"
- "@
- jmp @%0
- jmp @%0"
+ "jmp @%0"
[(set_attr "cc" "none")
(set_attr "length" "2")])
(define_insn "indirect_jump_h8300h"
- [(set (pc) (match_operand:SI 0 "jump_address_operand" "V,r"))]
+ [(set (pc) (match_operand:SI 0 "jump_address_operand" "Vr"))]
"TARGET_H8300H"
- "@
- jmp @%0
- jmp @%0"
+ "jmp @%0"
[(set_attr "cc" "none")
(set_attr "length" "2")])
@@ -1559,10 +1585,8 @@
}
}")
-
-;; I don't know why, but if I try to simplify extendhisi2 in the
-;; natural way, I get about a 2X code bloat on the h8300 without
-;; optimization, and a small bloat with optimization. Weird.
+;; This is used when not optimizing. It avoids severe code explosion
+;; due to poor register allocation.
(define_expand "zero_extendhisi2_h8300"
[(set (reg:HI 1) (match_operand:HI 1 "general_operand" ""))
(set (reg:SI 0) (zero_extend:SI (reg:HI 1)))
@@ -1644,9 +1668,8 @@
}
}")
-;; I don't know why, but if I try to simplify extendhisi2 in the
-;; natural way, I get about a 2X code bloat on the h8300 without
-;; optimization, and a small bloat with optimization. Weird.
+;; This is used when not optimizing. It avoids severe code explosion
+;; due to poor register allocation.
(define_expand "extendhisi2_h8300"
[(set (reg:HI 1) (match_operand:HI 1 "general_operand" ""))
(set (reg:SI 0) (sign_extend:SI (reg:HI 1)))
@@ -1716,21 +1739,15 @@
""
"if (expand_a_shift (QImode, LSHIFTRT, operands)) DONE;else FAIL;")
-;; WARNING: The constraints on the scratch register say one is not needed
-;; for constant shifts of 1,2,3,4. Emit_a_shift() must know this.
-
-(define_insn "shiftbyn_QI"
+(define_insn ""
[(set (match_operand:QI 0 "register_operand" "=r,r")
(match_operator:QI 3 "nshift_operator"
[ (match_operand:QI 1 "register_operand" "0,0")
- (match_operand:QI 2 "nonmemory_operand" "IKM,rn")]))
+ (match_operand:QI 2 "nonmemory_operand" "KM,rn")]))
(clobber (match_scratch:QI 4 "=X,&r"))]
""
"* return emit_a_shift (insn, operands);"
[(set_attr "length" "20")
-;; ??? We'd like to indicate that cc is set here, and it is for simple shifts.
-;; However, for cases that loop or are done in pieces, cc does not contain
-;; what we want. Emit_a_shift is free to tweak cc_status as desired.
(set_attr "cc" "clobber")])
;; HI BIT SHIFTS
@@ -1756,21 +1773,15 @@
""
"if (expand_a_shift (HImode, ASHIFTRT, operands)) DONE;else FAIL;")
-;; WARNING: The constraints on the scratch register say one is not needed
-;; for constant shifts of 1,2,3,4. Emit_a_shift() must know this.
-
-(define_insn "shiftbyn_HI"
+(define_insn ""
[(set (match_operand:HI 0 "register_operand" "=r,r")
(match_operator:HI 3 "nshift_operator"
[ (match_operand:HI 1 "register_operand" "0,0")
- (match_operand:QI 2 "nonmemory_operand" "IKM,rn")]))
+ (match_operand:QI 2 "nonmemory_operand" "KM,rn")]))
(clobber (match_scratch:QI 4 "=X,&r"))]
""
"* return emit_a_shift (insn, operands);"
[(set_attr "length" "20")
-;; ??? We'd like to indicate that cc is set here, and it is for simple shifts.
-;; However, for cases that loop or are done in pieces, cc does not contain
-;; what we want. Emit_a_shift is free to tweak cc_status as desired.
(set_attr "cc" "clobber")])
;; SI BIT SHIFTS
@@ -1799,21 +1810,15 @@
""
"if (expand_a_shift (SImode, ASHIFTRT, operands)) DONE;else FAIL;")
-;; WARNING: The constraints on the scratch register say one is not needed
-;; for constant shifts of 1,2. Emit_a_shift() must know this.
-
-(define_insn "shiftbyn_SI"
+(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r,r")
(match_operator:SI 3 "nshift_operator"
[ (match_operand:SI 1 "register_operand" "0,0")
- (match_operand:QI 2 "nonmemory_operand" "IK,rn")]))
+ (match_operand:QI 2 "nonmemory_operand" "K,rn")]))
(clobber (match_scratch:QI 4 "=X,&r"))]
""
"* return emit_a_shift (insn, operands);"
[(set_attr "length" "20")
-;; ??? We'd like to indicate that cc is set here, and it is for simple shifts.
-;; However, for cases that loop or are done in pieces, cc does not contain
-;; what we want. Emit_a_shift is free to tweak cc_status as desired.
(set_attr "cc" "clobber")])
;; -----------------------------------------------------------------