(attribute "type"): Add new type, "branch".
authorRichard Kenner <kenner@gcc.gnu.org>
Thu, 12 Aug 1993 23:02:25 +0000 (19:02 -0400)
committerRichard Kenner <kenner@gcc.gnu.org>
Thu, 12 Aug 1993 23:02:25 +0000 (19:02 -0400)
(attribute "length"): New attribute; put on all insns that don't have default
length.
(branch patterns): If conditional branch won't reach, take conditional branch
around an unconditional branch.

(plus): Split (plus (COMPARISON FOO ...) ...) at FOO.

From-SVN: r5148

gcc/config/rs6000/rs6000.md

index d04b249ad87f6929bc5cb46a9c7d043b35dd104a..5de6f206eb6e37c4701cb19160bf0fe0248d83be 100644 (file)
 \f
 ;; Define an insn type attribute.  This is used in function unit delay
 ;; computations.
-(define_attr "type" "load,integer,fp,compare,delayed_compare,fpcompare,mtlr"
+(define_attr "type" "load,integer,fp,compare,delayed_compare,fpcompare,mtlr,branch"
   (const_string "integer"))
 
+;; Length (in bytes).
+(define_attr "length" ""
+  (if_then_else (eq_attr "type" "branch")
+               (if_then_else (and (ge (minus (pc) (match_dup 0))
+                                      (const_int -32768))
+                                  (lt (minus (pc) (match_dup 0))
+                                      (const_int 32767)))
+                             (const_int 8)
+                             (const_int 12))
+               (const_int 4)))
+
 ;; Memory delivers its result in two cycles.
 (define_function_unit "memory" 1 0 (eq_attr "type" "load") 2 0)
 
   [(set (match_operand:SI 0 "register_operand" "=&r")
        (ffs:SI (match_operand:SI 1 "register_operand" "r")))]
   ""
-  "neg %0,%1\;and %0,%0,%1\;cntlz %0,%0\;sfi %0,%0,32")
+  "neg %0,%1\;and %0,%0,%1\;cntlz %0,%0\;sfi %0,%0,32"
+  [(set_attr "length" "16")])
 
 (define_insn "mulsi3"
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
        (div:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                (match_operand:SI 2 "const_int_operand" "N")))]
   "exact_log2 (INTVAL (operands[2])) >= 0"
-  "srai %0,%1,%p2\;aze %0,%0")
+  "srai %0,%1,%p2\;aze %0,%0"
+  [(set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
    (clobber (match_scratch:SI 3 "=r"))]
   "exact_log2 (INTVAL (operands[2])) >= 0"
   "srai %3,%1,%p2\;aze. %3,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (div:SI (match_dup 1) (match_dup 2)))]
   "exact_log2 (INTVAL (operands[2])) >= 0"
   "srai %0,%1,%p2\;aze. %0,%0"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
    andil. %0,%1,%b2
    andiu. %0,%1,%u2
    rlinm. %0,%1,0,%m2,%M2"
-  [(set_attr "type" "compare,compare,compare,delayed_compare")]) 
+  [(set_attr "type" "compare,compare,compare,delayed_compare")])
 
 ;; Take a AND with a constant that cannot be done in a single insn and try to
 ;; split it into two insns.  This does not verify that the insns are valid
   ""
   "@
    sle %0,%1,%2
-   sli %0,%1,%h2")
+   sli %0,%1,%h2"
+  [(set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x")
   ""
   "@
    a %L0,%L1,%L2\;ae %0,%1,%2
-   ai %L0,%L1,%2\;a%G2e %0,%1")
+   ai %L0,%L1,%2\;a%G2e %0,%1"
+  [(set_attr "length" "8")])
 
 (define_insn "subdi3"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
   ""
   "@
    sf %L0,%L2,%L1\;sfe %0,%2,%1
-   sfi %L0,%L2,%1\;sf%G1e %0,%2")
+   sfi %L0,%L2,%1\;sf%G1e %0,%2"
+  [(set_attr "length" "8")])
 
 (define_insn "negdi2"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
        (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
   ""
-  "sfi %L0,%L1,0\;sfze %0,%1")
+  "sfi %L0,%L1,0\;sfze %0,%1"
+  [(set_attr "length" "8")])
 
 (define_insn "mulsidi3"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
                 (sign_extend:DI (match_operand:SI 2 "gpc_reg_operand" "r"))))
    (clobber (match_scratch:SI 3 "=q"))]
   ""
-  "mul %0,%1,%2\;mfmq %L0")
+  "mul %0,%1,%2\;mfmq %L0"
+  [(set_attr "length" "8")])
 
 ;; If operands 0 and 2 are in the same register, we have a problem.  But
 ;; operands 0 and 1 (the usual case) can be in the same register.  That's
    sli %0,%L1,%h2\;cal %L0,0(0)
    sl%I2q %L0,%L1,%h2\;sll%I2q %0,%1,%h2
    sl%I2q %L0,%L1,%h2\;sll%I2q %0,%1,%h2
-   sl%I2q %L0,%L1,%h2\;sll%I2q %0,%1,%h2")
+   sl%I2q %L0,%L1,%h2\;sll%I2q %0,%1,%h2"
+  [(set_attr "length" "8")])
 
 (define_insn "lshrdi3"
   [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r,r,&r")
    cal %0,0(0)\;s%A2i %L0,%1,%h2
    sr%I2q %0,%1,%h2\;srl%I2q %L0,%L1,%h2
    sr%I2q %0,%1,%h2\;srl%I2q %L0,%L1,%h2
-   sr%I2q %0,%1,%h2\;srl%I2q %L0,%L1,%h2")
+   sr%I2q %0,%1,%h2\;srl%I2q %L0,%L1,%h2"
+  [(set_attr "length" "8")])
 
 ;; Shift by a variable amount is too complex to be worth open-coding.  We
 ;; just handle shifts by constants.
   ""
   "@
    srai %0,%1,31\;srai %L0,%1,%h2
-   sraiq %0,%1,%h2\;srliq %L0,%L1,%h2")
+   sraiq %0,%1,%h2\;srliq %L0,%L1,%h2"
+  [(set_attr "length" "8")])
 \f
 ;; Now define ways of moving data around.
 ;;
    ai %0,%1,0
    l%U1%X1 %0,%1
    st%U0%U1 %1,%0"
-  [(set_attr "type" "*,*,*,compare,*,*,load,*")])
+  [(set_attr "type" "*,*,*,compare,*,*,load,*")
+   (set_attr "length" "*,*,12,*,8,*,*,*")])
 \f
 ;; For floating-point, we normally deal with the floating-point registers.
 ;; The sole exception is that parameter passing can produce floating-point
    fmr %0,%1
    lfs%U1%X1 %0,%1
    frsp %1,%1\;stfs%U0%X0 %1,%0"
-  [(set_attr "type" "fp,load,*")])
+  [(set_attr "type" "fp,load,*")
+   (set_attr "length" "*,*,8")])
 \f
 (define_expand "movdf"
   [(set (match_operand:DF 0 "nonimmediate_operand" "")
   "@
    #
    l %0,%1\;l %L0,%L1"
-  [(set_attr "type" "*,load")])
+  [(set_attr "type" "*,load")
+   (set_attr "length" "*,8")])
 
 (define_split
   [(set (match_operand:DF 0 "gpc_reg_operand" "")
       return \"st%U0 %1,%0\;st %L1,%L0\";
     }
 }"
-  [(set_attr "type" "*,load,*")])
+  [(set_attr "type" "*,load,*")
+   (set_attr "length" "8")])
 \f
 ;; TImode is similar, except that we usually want to compute the address into
 ;; a register and use lsi/stsi (the exception is during reload).  MQ is also
        return \"l%U1 %0,%1\;l %L0,%L1\;l %Y0,%Y1\;l %Z0,%Z1\";
     }
 }"
-  [(set_attr "type" "*,load,load,*,*")])
+  [(set_attr "type" "*,load,load,*,*")
+   (set_attr "length" "*,16,16,*,16")])
 \f
 (define_expand "load_multiple"
   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
   /* We have to handle the case where the pseudo used to contain the address
      is assigned to one of the output registers.  In that case, do the
      lsi, but then load the correct value.  This is a bit of a mess, but is
-     the best we can do.  */
+     the best we can do.
+     We set the length attribute to the maximum possible size (8 bytes).  */
   static char result[100];
   char newload[40];
   int i;
 
   return result;
 }"
-  [(set_attr "type" "load")])
+  [(set_attr "type" "load")
+   (set_attr "length" "8")])
 \f
+
 (define_expand "store_multiple"
   [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
                          (match_operand:SI 1 "" ""))
   ""
   "@
    brl\;l 2,20(1)
-   bl %z0\;cror %.,%.,%.")
+   bl %z0\;cror %.,%.,%."
+  [(set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand 0 "" "=fg")
   ""
   "@
    brl\;l 2,20(1)
-   bl %z1\;cror %.,%.,%.")
+   bl %z1\;cror %.,%.,%."
+  [(set_attr "length" "8")])
 
 ;; Call subroutine returning any type.
 
                           [(match_operand 2 "cc_reg_operand" "y")
                            (const_int 0)]))]
   ""
-  "%D1mfcr %0\;rlinm %0,%0,%J1,31,31")
+  "%D1mfcr %0\;rlinm %0,%0,%J1,31,31"
+  [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
        (match_op_dup 1 [(match_dup 2) (const_int 0)]))]
   ""
   "%D1mfcr %3\;rlinm. %3,%3,%J1,30,31"
-  [(set_attr "type" "delayed_compare")])
+  [(set_attr "type" "delayed_compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
   operands[5] = gen_rtx (CONST_INT, VOIDmode, put_bit);
 
   return \"%D1mfcr %0\;rlinm %0,%0,%4,%5,%5\";
-}")
+}"
+ [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
 
   return \"%D1mfcr %4\;rlinm. %4,%4,%5,%6,%6\";
 }"
-  [(set_attr "type" "delayed_compare")])
+  [(set_attr "type" "delayed_compare")
+   (set_attr "length" "12")])
 
 ;; If we are comparing the result of two comparisons, this can be done
 ;; using creqv or crxor.
     return \"%C1%C3crxor %E0,%j1,%j3\";
   else
     return \"%C1%C3creqv %E0,%j1,%j3\";
-}")
+}"
+  [(set_attr "length" "12")])
 
 ;; There is a 3 cycle delay between consecutive mfcr instructions
 ;; so it is useful to combine 2 scc instructions to use only one mfcr.
                           [(match_operand 5 "cc_reg_operand" "y")
                            (const_int 0)]))]
    "REGNO (operands[2]) != REGNO (operands[5])"
-   "%D1%D4mfcr %3\;rlinm %0,%3,%J1,31,31\;rlinm %3,%3,%J4,31,31")
+   "%D1%D4mfcr %3\;rlinm %0,%3,%J1,31,31\;rlinm %3,%3,%J4,31,31"
+   [(set_attr "length" "20")])
 
 ;; There are some scc insns that can be done directly, without a compare.
 ;; These are faster because they don't involve the communications between
    sfi %3,%1,0\;ae %0,%3,%1
    xoril %0,%1,%b2\;sfi %3,%0,0\;ae %0,%3,%0
    xoriu %0,%1,%u2\;sfi %3,%0,0\;ae %0,%3,%0
-   sfi %0,%1,%2\;sfi %3,%0,0\;ae %0,%3,%0")
+   sfi %0,%1,%2\;sfi %3,%0,0\;ae %0,%3,%0"
+  [(set_attr "length" "12,8,12,12,12")])
 
 (define_insn ""
   [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,x,x,x")
    xoril %0,%1,%b2\;sfi %3,%0,0\;ae. %0,%3,%0
    xoriu %0,%1,%u2\;sfi %3,%0,0\;ae. %0,%3,%0
    sfi %0,%1,%2\;sfi %3,%0,0\;ae. %0,%3,%0"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12,8,12,12,12")])
+
+;; We have insns of the form shown by the first define_insn below.  If
+;; there is something inside the comparison operation, we must split it.
+(define_split
+  [(set (match_operand:SI 0 "gpc_reg_operand" "")
+       (plus:SI (match_operator 1 "comparison_operator"
+                                [(match_operand:SI 2 "" "")
+                                 (match_operand:SI 3
+                                                   "reg_or_cint_operand" "")])
+                (match_operand:SI 4 "gpc_reg_operand" "")))
+   (clobber (match_operand:SI 5 "register_operand" ""))]
+  "! gpc_reg_operand (operands[2], SImode)"
+  [(set (match_dup 5) (match_dup 2))
+   (set (match_dup 2) (plus:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
+                              (match_dup 4)))])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r")
    sfi %4,%1,0\;aze %0,%3
    xoril %4,%1,%b2\;sfi %4,%4,0\;aze %0,%3
    xoriu %4,%1,%u2\;sfi %4,%4,0\;aze %0,%3
-   sfi %4,%1,%2\;sfi %4,%4,0\;aze %0,%3")
+   sfi %4,%1,%2\;sfi %4,%4,0\;aze %0,%3"
+  [(set_attr "length" "12,8,12,12,12")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,x")
    xoril %4,%1,%b2\;sfi %4,%4,0\;aze. %4,%3
    xoriu %4,%1,%u2\;sfi %4,%4,0\;aze. %4,%3
    sfi %4,%1,%2\;sfi %4,%4,0\;aze. %4,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12,8,12,12,12")])
 
 (define_insn ""
   [(set (match_operand:CC 5 "cc_reg_operand" "=x,x,x,x,x")
    xoril %4,%1,%b2\;sfi %4,%4,0\;aze. %0,%3
    xoriu %4,%1,%u2\;sfi %4,%4,0\;aze. %0,%3
    sfi %4,%1,%2\;sfi %4,%4,0\;aze. %0,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12,8,12,12,12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r")
    ai %0,%1,-1\;sfe %0,%0,%0
    xoril %0,%1,%b2\;ai %0,%0,-1\;sfe %0,%0,%0
    xoriu %0,%1,%u2\;ai %0,%0,-1\;sfe %0,%0,%0
-   sfi %0,%1,%2\;ai %0,%0,-1\;sfe %0,%0,%0")
+   sfi %0,%1,%2\;ai %0,%0,-1\;sfe %0,%0,%0"
+   [(set_attr "length" "12,8,12,12,12")])
 
 ;; This is what (plus (ne X (const_int 0)) Y) looks like.
 (define_insn ""
                 (match_operand:SI 2 "gpc_reg_operand" "r")))
    (clobber (match_scratch:SI 3 "=&r"))]
   ""
-  "ai %3,%1,-1\;aze %0,%2")
+  "ai %3,%1,-1\;aze %0,%2"
+  [(set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
    (clobber (match_scratch:SI 3 "=&r"))]
   ""
   "ai %3,%1,-1\;aze. %3,%2"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:CC 4 "cc_reg_operand" "=x")
    (clobber (match_scratch:SI 3 "=&r"))]
   ""
   "ai %3,%1,-1\;aze. %0,%2"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
   ""
   "@
    doz %3,%2,%1\;sfi %0,%3,0\;ae %0,%0,%3
-   ai %0,%1,-1\;aze %0,%0\;sri %0,%0,31")
+   ai %0,%1,-1\;aze %0,%0\;sri %0,%0,31"
+  [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 4 "cc_reg_operand" "=x,x")
   "@
    doz %3,%2,%1\;sfi %0,%3,0\;ae. %0,%0,%3
    ai %0,%1,-1\;aze %0,%0\;sri. %0,%0,31"
-  [(set_attr "type" "delayed_compare,compare")])
+  [(set_attr "type" "delayed_compare,compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
   ""
   "@
    doz %4,%2,%1\;sfi %4,%4,0\;aze %0,%3
-   srai %4,%1,31\;sf %4,%1,%4\;aze %0,%3")
+   srai %4,%1,31\;sf %4,%1,%4\;aze %0,%3"
+  [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x")
   "@
    doz %4,%2,%1\;sfi %4,%4,0\;aze. %4,%3
    srai %4,%1,31\;sf %4,%1,%4\;aze. %4,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 5 "cc_reg_operand" "=x,x")
   "@
    doz %4,%2,%1\;sfi %4,%4,0\;aze. %0,%3
    srai %4,%1,31\;sf %4,%1,%4\;aze. %0,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
   ""
   "@
    doz %0,%2,%1\;ai %0,%0,-1\;sfe %0,%0,%0
-   ai %0,%1,-1\;aze %0,%0\;srai %0,%0,31")
+   ai %0,%1,-1\;aze %0,%0\;srai %0,%0,31"
+  [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (leu:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                (match_operand:SI 2 "reg_or_short_operand" "rI")))]
   ""
-  "sf%I2 %0,%1,%2\;cal %0,0(0)\;ae %0,%0,%0")
+  "sf%I2 %0,%1,%2\;cal %0,0(0)\;ae %0,%0,%0"
+  [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (leu:SI (match_dup 1) (match_dup 2)))]
    ""
   "sf%I2 %0,%1,%2\;cal %0,0(0)\;ae. %0,%0,%0"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
                 (match_operand:SI 3 "gpc_reg_operand" "r")))
    (clobber (match_scratch:SI 4 "=&r"))]
   ""
-  "sf%I2 %4,%1,%2\;aze %0,%3")
+  "sf%I2 %4,%1,%2\;aze %0,%3"
+  [(set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
    (clobber (match_scratch:SI 4 "=&r"))]
   ""
   "sf%I2 %4,%1,%2\;aze. %4,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:CC 5 "cc_reg_operand" "=x")
    (clobber (match_scratch:SI 4 "=&r"))]
   ""
   "sf%I2 %4,%1,%2\;aze. %0,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (neg:SI (leu:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                        (match_operand:SI 2 "reg_or_short_operand" "rI"))))]
   ""
-  "sf%I2 %0,%1,%2\;sfe %0,%0,%0\;nand %0,%0,%0")
+  "sf%I2 %0,%1,%2\;sfe %0,%0,%0\;nand %0,%0,%0"
+   [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
                (match_operand:SI 3 "gpc_reg_operand" "r")))
    (clobber (match_scratch:SI 4 "=&r"))]
   ""
-  "sf%I2 %4,%1,%2\;sfe %4,%4,%4\;andc %0,%3,%4")
+  "sf%I2 %4,%1,%2\;sfe %4,%4,%4\;andc %0,%3,%4"
+  [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
    (clobber (match_scratch:SI 4 "=&r"))]
   ""
   "sf%I2 %4,%1,%2\;sfe %4,%4,%4\;andc. %4,%3,%4"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 5 "cc_reg_operand" "=x")
    (clobber (match_scratch:SI 4 "=&r"))]
   ""
   "sf%I2 %4,%1,%2\;sfe %4,%4,%4\;andc. %0,%3,%4"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (lt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
               (match_operand:SI 2 "reg_or_short_operand" "rI")))]
   ""
-  "doz%I2 %0,%1,%2\;nabs %0,%0\;sri %0,%0,31")
+  "doz%I2 %0,%1,%2\;nabs %0,%0\;sri %0,%0,31"
+   [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 3 "cc_reg_operand" "=x")
        (lt:SI (match_dup 1) (match_dup 2)))]
   ""
   "doz%I2 %0,%1,%2\;nabs %0,%0\;sri. %0,%0,31"
-  [(set_attr "type" "delayed_compare")])
+  [(set_attr "type" "delayed_compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
                 (match_operand:SI 3 "gpc_reg_operand" "r")))
    (clobber (match_scratch:SI 4 "=&r"))]
   ""
-  "doz%I2 %4,%1,%2\;ai %4,%4,-1\;aze %0,%3")
+  "doz%I2 %4,%1,%2\;ai %4,%4,-1\;aze %0,%3"
+  [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "cc_reg_operand" "=x")
    (clobber (match_scratch:SI 4 "=&r"))]
   ""
   "doz%I2 %4,%1,%2\;ai %4,%4,-1\;aze. %4,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 5 "cc_reg_operand" "=x")
    (clobber (match_scratch:SI 4 "=&r"))]
   ""
   "doz%I2 %4,%1,%2\;ai %4,%4,-1\;aze. %0,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (neg:SI (lt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                       (match_operand:SI 2 "reg_or_short_operand" "rI"))))]
   ""
-  "doz%I2 %0,%1,%2\;nabs %0,%0\;srai %0,%0,31")
+  "doz%I2 %0,%1,%2\;nabs %0,%0\;srai %0,%0,31"
+  [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
   ""
   "@
    sf %0,%2,%1\;sfe %0,%0,%0\;neg %0,%0
-   ai %0,%1,%n2\;sfe %0,%0,%0\;neg %0,%0")
+   ai %0,%1,%n2\;sfe %0,%0,%0\;neg %0,%0"
+  [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,x")
   "@
    sf %0,%2,%1\;sfe %0,%0,%0\;neg. %0,%0
    ai %0,%1,%n2\;sfe %0,%0,%0\;neg. %0,%0"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
   sf %4,%2,%1\;sfe %4,%4,%4\;sf%I3 %0,%4,%3
   sf %4,%2,%1\;sfe %4,%4,%4\;sf%I3 %0,%4,%3
   ai %4,%1,%n2\;sfe %4,%4,%4\;sf%I3 %0,%4,%3
-  ai %4,%1,%n2\;sfe %4,%4,%4\;sf%I3 %0,%4,%3")
+  ai %4,%1,%n2\;sfe %4,%4,%4\;sf%I3 %0,%4,%3"
+ [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x")
    sf %4,%2,%1\;sfe %4,%4,%4\;sf%I3. %4,%4,%3
    ai %4,%1,%n2\;sfe %4,%4,%4\;sf%I3. %4,%4,%3
    ai %4,%1,%n2\;sfe %4,%4,%4\;sf%I3. %4,%4,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 5 "cc_reg_operand" "=x,x,x,x")
    sf %4,%2,%1\;sfe %4,%4,%4\;sf%I3. %0,%4,%3
    ai %4,%1,%n2\;sfe %4,%4,%4\;sf%I3. %0,%4,%3
    ai %4,%1,%n2\;sfe %4,%4,%4\;sf%I3. %0,%4,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
   ""
   "@
    sf %0,%2,%1\;sfe %0,%0,%0
-   ai %0,%1,%n2\;sfe %0,%0,%0")
+   ai %0,%1,%n2\;sfe %0,%0,%0"
+  [(set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
               (match_operand:SI 2 "reg_or_short_operand" "rI")))
    (clobber (match_scratch:SI 3 "=r"))]
   ""
-  "doz%I2 %3,%1,%2\;sfi %0,%3,0\;ae %0,%0,%3")
+  "doz%I2 %3,%1,%2\;sfi %0,%3,0\;ae %0,%0,%3"
+   [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 4 "cc_reg_operand" "=x")
    (clobber (match_scratch:SI 3 "=r"))]
   ""
   "doz%I2 %3,%1,%2\;sfi %0,%3,0\;ae. %0,%0,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
                 (match_operand:SI 3 "gpc_reg_operand" "r")))
    (clobber (match_scratch:SI 4 "=&r"))]
   ""
-  "doz%I2 %4,%1,%2\;sfi %4,%4,0\;aze %0,%3")
+  "doz%I2 %4,%1,%2\;sfi %4,%4,0\;aze %0,%3"
+  [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
    (clobber (match_scratch:SI 4 "=&r"))]
   ""
   "doz%I2 %4,%1,%2\;sfi %4,%4,0\;aze. %4,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 5 "cc_reg_operand" "=x")
    (clobber (match_scratch:SI 4 "=&r"))]
   ""
   "doz%I2 %4,%1,%2\;sfi %4,%4,0\;aze. %0,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (neg:SI (ge:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                       (match_operand:SI 2 "reg_or_short_operand" "rI"))))]
   ""
-  "doz%I2 %0,%1,%2\;ai %0,%0,-1\;sfe %0,%0,%0")
+  "doz%I2 %0,%1,%2\;ai %0,%0,-1\;sfe %0,%0,%0"
+  [(set_attr "length" "12")])
 
 ;; This is (and (neg (ge X (const_int 0))) Y).
 (define_insn ""
                (match_operand:SI 2 "gpc_reg_operand" "r")))
    (clobber (match_scratch:SI 3 "=&r"))]
   ""
-  "srai %3,%1,31\;andc %0,%2,%3")
+  "srai %3,%1,31\;andc %0,%2,%3"
+  [(set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
    (clobber (match_scratch:SI 3 "=&r"))]
   ""
   "srai %3,%1,31\;andc. %3,%2,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:CC 4 "cc_reg_operand" "=x")
    (clobber (match_scratch:SI 3 "=&r"))]
   ""
   "srai %3,%1,31\;andc. %0,%2,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
   ""
   "@
    sf %0,%2,%1\;cal %0,0(0)\;ae %0,%0,%0
-   ai %0,%1,%n2\;cal %0,0(0)\;ae %0,%0,%0")
+   ai %0,%1,%n2\;cal %0,0(0)\;ae %0,%0,%0"
+  [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 3 "cc_reg_operand" "=x,x")
   "@
    sf %0,%2,%1\;cal %0,0(0)\;ae. %0,%0,%0
    ai %0,%1,%n2\;cal %0,0(0)\;ae. %0,%0,%0"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
   ""
   "@
    sf %4,%2,%1\;aze %0,%3
-   ai %4,%1,%n2\;aze %0,%3")
+   ai %4,%1,%n2\;aze %0,%3"
+  [(set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x")
   "@
    sf %4,%2,%1\;aze. %4,%3
    ai %4,%1,%n2\;aze. %4,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:CC 5 "cc_reg_operand" "=x,x")
   "@
    sf %4,%2,%1\;aze. %0,%3
    ai %4,%1,%n2\;aze. %4,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "8")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
   ""
   "@
    sf %0,%2,%1\;sfe %0,%0,%0\;nand %0,%0,%0
-   sfi %0,%1,-1\;a%I2 %0,%0,%2\;sfe %0,%0,%0")
+   sfi %0,%1,-1\;a%I2 %0,%0,%2\;sfe %0,%0,%0"
+  [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
   ""
   "@
    sf %4,%2,%1\;sfe %4,%4,%4\;andc %0,%3,%4
-   ai %4,%1,%n2\;sfe %4,%4,%4\;andc %0,%3,%4")
+   ai %4,%1,%n2\;sfe %4,%4,%4\;andc %0,%3,%4"
+  [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x")
   "@
    sf %4,%2,%1\;sfe %4,%4,%4\;andc. %4,%3,%4
    ai %4,%1,%n2\;sfe %4,%4,%4\;andc. %4,%3,%4"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 5 "cc_reg_operand" "=x,x")
   "@
    sf %4,%2,%1\;sfe %4,%4,%4\;andc. %0,%3,%4
    ai %4,%1,%n2\;sfe %4,%4,%4\;andc. %0,%3,%4"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (gt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
               (const_int 0)))]
   ""
-  "sfi %0,%1,0\;ame %0,%0\;sri %0,%0,31")
+  "sfi %0,%1,0\;ame %0,%0\;sri %0,%0,31"
+  [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 2 "cc_reg_operand" "=x")
        (gt:SI (match_dup 1) (const_int 0)))]
   ""
   "sfi %0,%1,0\;ame %0,%0\;sri. %0,%0,31"
-  [(set_attr "type" "delayed_compare")])
+  [(set_attr "type" "delayed_compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (gt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
               (match_operand:SI 2 "reg_or_short_operand" "r")))]
   ""
-  "doz %0,%2,%1\;nabs %0,%0\;sri %0,%0,31")
+  "doz %0,%2,%1\;nabs %0,%0\;sri %0,%0,31"
+  [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (gt:SI (match_dup 1) (match_dup 2)))]
   ""
   "doz %0,%2,%1\;nabs %0,%0\;sri. %0,%0,31"
-  [(set_attr "type" "delayed_compare")])
+  [(set_attr "type" "delayed_compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
                 (match_operand:SI 2 "gpc_reg_operand" "r")))
    (clobber (match_scratch:SI 3 "=&r"))]
   ""
-  "a %3,%1,%1\;sfe %3,%1,%3\;aze %0,%2")
+  "a %3,%1,%1\;sfe %3,%1,%3\;aze %0,%2"
+  [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
    (clobber (match_scratch:SI 3 "=&r"))]
   ""
   "a %3,%1,%1\;sfe %3,%1,%3\;aze. %0,%2"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 4 "cc_reg_operand" "=x")
    (clobber (match_scratch:SI 3 "=&r"))]
   ""
   "a %3,%1,%1\;sfe %3,%1,%3\;aze. %3,%2"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
                 (match_operand:SI 3 "gpc_reg_operand" "r")))
    (clobber (match_scratch:SI 4 "=&r"))]
   ""
-  "doz %4,%2,%1\;ai %4,%4,-1\;aze %0,%3")
+  "doz %4,%2,%1\;ai %4,%4,-1\;aze %0,%3"
+  [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x")
    (clobber (match_scratch:SI 4 "=&r"))]
   ""
   "doz %4,%2,%1\;ai %4,%4,-1\;aze. %4,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 5 "cc_reg_operand" "=x")
    (clobber (match_scratch:SI 4 "=&r"))]
   ""
   "doz %4,%2,%1\;ai %4,%4,-1\;aze. %0,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (neg:SI (gt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                       (const_int 0))))]
   ""
-  "sfi %0,%1,0\;ame %0,%0\;srai %0,%0,31")
+  "sfi %0,%1,0\;ame %0,%0\;srai %0,%0,31"
+  [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (neg:SI (gt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                       (match_operand:SI 2 "reg_or_short_operand" "r"))))]
   ""
-  "doz %0,%2,%1\;nabs %0,%0\;srai %0,%0,31")
+  "doz %0,%2,%1\;nabs %0,%0\;srai %0,%0,31"
+  [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                (match_operand:SI 2 "reg_or_short_operand" "rI")))]
   ""
-  "sf%I2 %0,%1,%2\;sfe %0,%0,%0\;neg %0,%0")
+  "sf%I2 %0,%1,%2\;sfe %0,%0,%0\;neg %0,%0"
+  [(set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:CC 3 "cc_reg_operand" "=x")
        (gtu:SI (match_dup 1) (match_dup 2)))]
   ""
   "sf%I2 %0,%1,%2\;sfe %0,%0,%0\;neg. %0,%0"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r")
   "@
    ai %4,%1,%k2\;aze %0,%3
    sf%I2 %4,%1,%2\;sfe %4,%4,%4\;sf%I3 %0,%4,%3
-   sf%I2 %4,%1,%2\;sfe %4,%4,%4\;sf%I3 %0,%4,%3")
+   sf%I2 %4,%1,%2\;sfe %4,%4,%4\;sf%I3 %0,%4,%3"
+  [(set_attr "length" "8,12,12")])
 
 (define_insn ""
   [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x")
    ai %4,%1,%k2\;aze. %0,%3
    sf%I2 %4,%1,%2\;sfe %4,%4,%4\;sf%I3. %0,%4,%3
    sf%I2 %4,%1,%2\;sfe %4,%4,%4\;sf%I3. %0,%4,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "8,12,12")])
 
 (define_insn ""
   [(set (match_operand:CC 5 "cc_reg_operand" "=x,x,x")
    ai %4,%1,%k2\;aze. %0,%3
    sf%I2 %4,%1,%2\;sfe %4,%4,%4\;sf%I3. %0,%4,%3
    sf%I2 %4,%1,%2\;sfe %4,%4,%4\;sf%I3. %0,%4,%3"
-  [(set_attr "type" "compare")])
+  [(set_attr "type" "compare")
+   (set_attr "length" "8,12,12")])
 
 (define_insn ""
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
        (neg:SI (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                        (match_operand:SI 2 "reg_or_short_operand" "rI"))))]
   ""
-  "sf%I2 %0,%1,%2\;sfe %0,%0,%0")
+  "sf%I2 %0,%1,%2\;sfe %0,%0,%0"
+  [(set_attr "length" "8")])
 \f
 ;; Define both directions of branch and return.  If we need a reload
 ;; register, we'd rather use CR0 since it is much easier to copy a
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "%C1bc %t1,%j1,%0")
+  "*
+{
+  if (get_attr_length (insn) == 8)
+    return \"%C1bc %t1,%j1,%l0\";
+  else
+    return \"%C1bc %T1,%j1,$+8\;b %l0\";
+}"
+  [(set_attr "type" "branch")])
+
 
 (define_insn ""
   [(set (pc)
                      (return)
                      (pc)))]
   "direct_return ()"
-  "%C0bcr %t0,%j0")
+  "%C0bcr %t0,%j0"
+  [(set_attr "length" "8")])
 
 (define_insn ""
   [(set (pc)
                      (pc)
                      (label_ref (match_operand 0 "" ""))))]
   ""
-  "%C1bc %T1,%j1,%0")
+  "*
+{
+  if (get_attr_length (insn) == 8)
+    return \"%C1bc %T1,%j1,%l0\";
+  else
+    return \"%C1bc %t1,%j1,$+8\;b %l0\";
+}"
+  [(set_attr "type" "branch")])
 
 (define_insn ""
   [(set (pc)
                      (pc)
                      (return)))]
   "direct_return ()"
-  "%C0bcr %T0,%j0")
+  "%C0bcr %T0,%j0"
+  [(set_attr "length" "8")])
 
 ;; Unconditional branch and return.
 
    (clobber (match_scratch:CC 3 "=X,&x,&x"))
    (clobber (match_scratch:SI 4 "=X,X,r"))]
   ""
-  "@
-   bdn %l2
-   #
-   #")
+  "*
+{
+  if (which_alternative == 1)
+    return \"#\";
+  else if (get_attr_length (insn) == 8)
+    return \"bdn %l2\";
+  else
+    return \"bdz $+8\;b %l2\";
+}"
+  [(set_attr "type" "branch")])
                               
 ;; Similar, but we can use GE since we have a REG_NONNEG.
 (define_insn ""
    (clobber (match_scratch:CC 3 "=X,&x,&X"))
    (clobber (match_scratch:SI 4 "=X,X,r"))]
   "find_reg_note (insn, REG_NONNEG, 0)"
-  "@
-   bdn %l2
-   #
-   #")
+  "*
+{
+  if (which_alternative == 1)
+    return \"#\";
+  else if (get_attr_length (insn) == 8)
+    return \"bdn %l2\";
+  else
+    return \"bdz $+8\;b %l2\";
+}"
+  [(set_attr "type" "branch")])
                               
 (define_insn ""
   [(set (pc)
    (clobber (match_scratch:CC 3 "=X,&x,&x"))
    (clobber (match_scratch:SI 4 "=X,X,r"))]
   ""
-  "@
-   bdz %l2
-   #
-   #")
+  "*
+{
+  if (which_alternative == 1)
+    return \"#\";
+  else if (get_attr_length (insn) == 8)
+    return \"bdz %l2\";
+  else
+    return \"bdn $+8\;b %l2\";
+}"
+  [(set_attr "type" "branch")])
 
 (define_split
   [(set (pc)