diff options
author | Jeff Law <law@gcc.gnu.org> | 1996-05-01 16:41:55 -0600 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 1996-05-01 16:41:55 -0600 |
commit | dd4fd0a0fdeed482a3159b5579564b227041f87e (patch) | |
tree | 8edf7a26211bf37aa69cb7eae40f8e507b2dd71c | |
parent | 17d6fedc573f97792a04b363e59a030584de2459 (diff) | |
download | gcc-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.c | 41 | ||||
-rw-r--r-- | gcc/config/h8300/h8300.md | 169 |
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")]) ;; ----------------------------------------------------------------- |