]> gcc.gnu.org Git - gcc.git/commitdiff
h8300.c (h8300_adjust_insn_length): Adjust the cost of shifts by small constant values.
authorJeff Law <law@gcc.gnu.org>
Wed, 1 May 1996 22:41:55 +0000 (16:41 -0600)
committerJeff Law <law@gcc.gnu.org>
Wed, 1 May 1996 22:41:55 +0000 (16:41 -0600)
        * 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

gcc/config/h8300/h8300.c
gcc/config/h8300/h8300.md

index 87e45e48c91fbf47d8957ebcdcd686df7afc05ac..60203d19a78c42d98d50d6f27e21ac4282352a46 100644 (file)
@@ -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;
 }
index b4fba572d05f062c585263e4353677ad117ea0bc..be2fb158004e3ff7d7cb8af42dd5728e95b81c37 100644 (file)
 ;; 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
 ;; 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"
   [(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)
   [(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)
   [(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")])
 \f
 ;; ----------------------------------------------------------------------
 ;; ADD INSTRUCTIONS
   "@
    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"
   "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")])
 
 ;; 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")))]
    (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" "")))]
   ""
   "
 {
 }")
 
 (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")))]
   ""
   "*
 {
     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 \"\";
     }
     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")))]
 ;; 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")))]
   [(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"
 ;; 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")])
 
     }
 }")
 
-
-;; 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)))
     }
 }")
 
-;; 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)))
   ""
   "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
   ""
   "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
   ""
   "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")])
 \f
 ;; -----------------------------------------------------------------
This page took 0.086329 seconds and 5 git commands to generate.