OSDN Git Service

* pa.md (smin, umin, smax, umax): New patterns.
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 28 Mar 1993 23:56:26 +0000 (23:56 +0000)
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 28 Mar 1993 23:56:26 +0000 (23:56 +0000)
* pa.md (cbranch define_delay): Enable nullification of
conditional branch delay slots (based upon branch direction).
(conditional branch patterns): Call output_cbranch to get the
correct output template.  Long conditional branches with an
annulled delay slot have a length of 3.
(branch on bit patterns): Call output_bb to get the correct
output template.  Long branches with an annulled delay slot have
a length of 3.
(decrement and branch pattern): Handle nullification of long

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@3906 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/config/pa/pa.md

index 97a82f3..1c4b9b5 100644 (file)
                (const_string "true")
                (const_string "false")))
 
+;; Disallow instructions which use the FPU since they will tie up the FPU
+;; even if the instruction is nullified.
+(define_attr "in_nullified_branch_delay" "false,true"
+  (if_then_else (and (eq_attr "type" "!branch,cbranch,fbranch,call,dyncall,multi,milli,fpcc,fpalu,fpmul,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl")
+                    (eq_attr "length" "1"))
+               (const_string "true")
+               (const_string "false")))
+
 ;; Unconditional branch, call, and millicode call delay slot description.
 (define_delay (eq_attr "type" "branch,call,milli")
   [(eq_attr "in_branch_delay" "true") (nil) (nil)])
 
-;; Floating point conditional branch delay slot description.
+;; Floating point conditional branch delay slot description and
 (define_delay (eq_attr "type" "fbranch")
   [(eq_attr "in_branch_delay" "true")
-   (eq_attr "in_branch_delay" "true")
+   (eq_attr "in_nullified_branch_delay" "true")
    (nil)])
 
 ;; Integer conditional branch delay slot description.
+;; Nullification of conditional branches on the PA is dependent on the
+;; direction of the branch.  Forward branches nullify true (direction > 0),
+;; and backward branches nullify false (direction < 0).
+;; If direction == 0, then the direction is unknown and we do not allow
+;; any nullification.
 (define_delay (eq_attr "type" "cbranch")
-  [(eq_attr "in_branch_delay" "true") (nil) (nil)])
+  [(eq_attr "in_branch_delay" "true") 
+   (and (eq_attr "in_nullified_branch_delay" "true") 
+       (attr_flag "forward"))
+   (and (eq_attr "in_nullified_branch_delay" "true")
+       (attr_flag "backward"))])
 
 ;; Function units of the HPPA. The following data is for the "Snake"
 ;; (Mustang CPU + Timex FPU) because that's what I have the docs for.
   [(set_attr "type" "binary,binary")
    (set_attr "length" "2,3")])
 
+;; Signed/Unsigned minimum and maximum patterns.
+(define_insn "sminsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+       (smin:SI (match_operand:SI 1 "register_operand" "%r,0,0")
+                (match_operand:SI 2 "arith11_operand" "M,r,I")))]
+  ""
+  "@
+  comclr,> %1,%2,%0\;copy %1,%0
+  comclr,> %2,%0,0\;copy %2,%0
+  comiclr,> %2,%0,0\;ldi %2,%0"
+[(set_attr "type" "multi,multi,multi")
+ (set_attr "length" "2,2,2")])
+
+(define_insn "uminsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (umin:SI (match_operand:SI 1 "register_operand" "%0,0")
+                (match_operand:SI 2 "arith11_operand" "r,I")))]
+  ""
+  "@
+  comclr,>> %2,%0,0\;copy %2,%0
+  comiclr,>> %2,%0,0\;ldi %2,%0"
+[(set_attr "type" "multi,multi")
+ (set_attr "length" "2,2")])
+
+(define_insn "smaxsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r,r")
+       (smax:SI (match_operand:SI 1 "register_operand" "%r,0,0")
+                (match_operand:SI 2 "arith11_operand" "M,r,I")))]
+  ""
+  "@
+  comclr,< %1,%2,%0\;copy %1,%0
+  comclr,< %2,%0,0\;copy %2,%0
+  comiclr,< %2,%0,0\;ldi %2,%0"
+[(set_attr "type" "multi,multi,multi")
+ (set_attr "length" "2,2,2")])
+
+(define_insn "umaxsi3"
+  [(set (match_operand:SI 0 "register_operand" "=r,r")
+       (umax:SI (match_operand:SI 1 "register_operand" "%0,0")
+                (match_operand:SI 2 "arith11_operand" "r,I")))]
+  ""
+  "@
+  comclr,<< %2,%0,0\;copy %2,%0
+  comiclr,<< %2,%0,0\;ldi %2,%0"
+[(set_attr "type" "multi,multi")
+ (set_attr "length" "2,2")])
 ;;; Experimental conditional move patterns
 
 ; We need the first constraint alternative in order to avoid
 
 ;; Match the branch patterns.
 
+
+;; Note a long backward conditional branch with an annulled delay slot
+;; has a length of 3.  
 (define_insn ""
   [(set (pc)
        (if_then_else
   ""
   "*
 {
-  return (get_attr_length (insn) == 1
-         ? \"com%I2b,%S3 %2,%1,%0%#\" : \"com%I2clr,%B3 %2,%1,0\;bl %0,0%#\");
+  return output_cbranch (operands, INSN_ANNULLED_BRANCH_P (insn), 
+                        get_attr_length (insn), 0, insn);
 }"
-  [(set_attr "type" "cbranch")
-   (set (attr "length") (if_then_else (lt (abs (minus (match_dup 0)
-                                                     (plus (pc) (const_int 2))))
-                                         (const_int 1023))
-                                     (const_int 1)
-                                     (const_int 2)))])
+[(set_attr "type" "cbranch")
+ (set (attr "length") 
+    (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 2))))
+                     (const_int 1023))
+           (const_int 1)
+          (and (lt (match_dup 0) (pc))
+               (eq (symbol_ref "INSN_ANNULLED_BRANCH_P (insn)")
+                   (const_int 1)))
+          (const_int 3)]
+         (const_int 2)))])
 
 ;; Match the negated branch.
 
   ""
   "*
 {
-  return (get_attr_length (insn) == 1
-         ? \"com%I2b,%B3 %2,%1,%0%#\" : \"com%I2clr,%S3 %2,%1,0%#\;bl %0,0%#\");
+  return output_cbranch (operands, INSN_ANNULLED_BRANCH_P (insn), 
+                        get_attr_length (insn), 1, insn);
 }"
-  [(set_attr "type" "cbranch")
-   (set (attr "length") (if_then_else (lt (abs (minus (match_dup 0)
-                                                     (plus (pc) (const_int 2))))
-                                         (const_int 1023))
-                                     (const_int 1)
-                                     (const_int 2)))])
-
-;; Branch on bit patterns
-
+[(set_attr "type" "cbranch")
+ (set (attr "length") 
+    (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 2))))
+                     (const_int 1023))
+           (const_int 1)
+          (and (lt (match_dup 0) (pc))
+               (eq (symbol_ref "INSN_ANNULLED_BRANCH_P (insn)")
+                   (const_int 1)))
+          (const_int 3)]
+         (const_int 2)))])
+
+;; Branch on Bit patterns.
 (define_insn ""
   [(set (pc)
        (if_then_else
   ""
   "*
 {
-  if (operands[3] == pc_rtx)
-    return (get_attr_length (insn) == 1
-           ? \"bb,< %0,%1,%2%#\" : \"extrs,>= %0,%1,1,0\;bl %2,0%#\");
-  else
-    return (get_attr_length (insn) == 1
-           ? \"bb,>= %0,%1,%3%#\" : \"extrs,< %0,%1,1,0\;bl %3,0%#\");
+  return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn), 
+                        get_attr_length (insn), 
+                        (operands[3] != pc_rtx),
+                        insn, 0);
 }"
-  [(set_attr "type" "cbranch")
-   (set (attr "length") (if_then_else (lt (abs (minus (match_dup 0)
-                                                     (plus (pc) (const_int 2))))
-                                         (const_int 1023))
-                                     (const_int 1)
-                                     (const_int 2)))])
+[(set_attr "type" "cbranch")
+ (set (attr "length") 
+    (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 2))))
+                     (const_int 1023))
+           (const_int 1)
+          (and (lt (match_dup 0) (pc))
+               (eq (symbol_ref "INSN_ANNULLED_BRANCH_P (insn)")
+                   (const_int 1)))
+          (const_int 3)]
+         (const_int 2)))])
 
 (define_insn ""
   [(set (pc)
   ""
   "*
 {
-  if (operands[3] == pc_rtx)
-    return (get_attr_length (insn) == 1
-           ? \"bb,>= %0,%1,%2%#\" : \"extrs,< %0,%1,1,0\;bl %2,0%#\");
-  else
-    return (get_attr_length (insn) == 1
-           ? \"bb,< %0,%1,%3%#\" : \"extrs,>= %0,%1,1,0\;bl %3,0%#\");
+  return output_bb (operands, INSN_ANNULLED_BRANCH_P (insn), 
+                        get_attr_length (insn), 
+                        (operands[3] != pc_rtx),
+                        insn, 1);
 }"
-  [(set_attr "type" "cbranch")
-   (set (attr "length") (if_then_else (lt (abs (minus (match_dup 0)
-                                                     (plus (pc) (const_int 2))))
-                                         (const_int 1023))
-                                     (const_int 1)
-                                     (const_int 2)))])
+[(set_attr "type" "cbranch")
+ (set (attr "length") 
+    (cond [(lt (abs (minus (match_dup 0) (plus (pc) (const_int 2))))
+                     (const_int 1023))
+           (const_int 1)
+          (and (lt (match_dup 0) (pc))
+               (eq (symbol_ref "INSN_ANNULLED_BRANCH_P (insn)")
+                   (const_int 1)))
+          (const_int 3)]
+         (const_int 2)))])
+
 ;; Floating point branches
 
 (define_insn ""
   return \"depi %3,%2+%1-1,%1,%0\";
 }")
 
+;; The dbra pattern from hell.  
 ;; This insn is used for some loop tests, typically loops reversed when
 ;; strength reduction is used.  It is actually created when the instruction
 ;; combination phase combines the special loop test.  Since this insn
 ;; is both a jump insn and has an output, it must deal with it's own
 ;; reloads, hence the `m' constraints.  The `!' constraints direct reload
 ;; to not choose the register alternatives in the event a reload is needed.
-
 (define_insn "decrement_and_branch_until_zero"
   [(set (pc)
        (if_then_else
   "find_reg_note (insn, REG_NONNEG, 0)"
 "*
 {
-  if (which_alternative == 0)
-    if (get_attr_length (insn) == 1)
-      return \"addib,>= -1,%0,%1%#\";
-    else
-      return \"addi,< -1,%0,%0\;bl %1,0%#\";
+  if (INSN_ANNULLED_BRANCH_P (insn))
+    {
+      /* Loop counter is in a register.  */
+      if (which_alternative == 0)
+       /* Short branch.  Normal handling of nullification.  */
+        if (get_attr_length (insn) == 1)
+          return \"addib,>=,n -1,%0,%1\";
+       /* Long Conditional branch forward with delay slot nullified if
+          branch is taken.  */
+        else if (get_attr_length (insn) == 2)
+          return \"addi,< -1,%0,%0\;bl,n %1,0\";
+       /* Long Conditional branch backwards with delay slot nullified
+          if branch is not taken.  */
+        else
+          return \"addib,< -1,%0,.+16\;nop\;bl %1,0\";
+      else
+        {
+         /* Must reload loop counter from memory.  Ugly.  */
+          output_asm_insn (\"ldw %0,%2\;ldo -1(%2),%2\;stw %2,%0\", operands);
+         /* Short branch.  Normal handling of nullification.  */
+          if (get_attr_length (insn) == 4)
+           return \"comb,>,n 0,%2,%1\";
+         /* Long Conditional branch forward with delay slot nullified if
+            branch is taken.  */
+          else if (get_attr_length (insn) == 5)
+           return \"comclr,<= 0,%2,0\;bl,n %1,0\";
+         else 
+         /* Long Conditional branch backwards with delay slot nullified
+            if branch is not taken.  */
+           return \"comb,<= 0,%2,.+16\;nop\;bl %1,0\";
+        }
+    }
   else
     {
-      output_asm_insn (\"ldw %0,%2\;ldo -1(%2),%2\;stw %2,%0\", operands);
-      if (get_attr_length (insn) == 4)
-       return \"comb,> 0,%2,%1%#\";
+      /* We are not nullifying the delay slot.  Much simpler.  */
+      if (which_alternative == 0)
+        if (get_attr_length (insn) == 1)
+         /* Short form.  */
+          return \"addib,>= -1,%0,%1%#\";
+        else
+         /* Long form.  */
+          return \"addi,< -1,%0,%0\;bl%* %1,0\";
       else
-       return \"comclr,<= 0,%2,0\;bl %1,0%#\";
+        {
+         /* Reload loop counter from memory.  */
+          output_asm_insn (\"ldw %0,%2\;ldo -1(%2),%2\;stw %2,%0\", operands);
+         /* Short form.  */
+          if (get_attr_length (insn) == 4)
+           return \"comb,> 0,%2,%1%#\";
+         /* Long form.  */
+          else
+           return \"comclr,<= 0,%2,0\;bl%* %1,0\";
+        }
     }
 }"
+;; Do not expect to understand this the first time through.  
 [(set_attr "type" "cbranch")
  (set (attr "length")
-      (if_then_else (eq (symbol_ref "which_alternative") (const_int 0))
-                   (if_then_else (lt (abs (minus (match_dup 1)
-                                                 (plus (pc) (const_int 2))))
-                                     (const_int 1023))
-                                 (const_int 1)
-                                 (const_int 2))
-                   (if_then_else (lt (match_dup 1)
-                                     (pc))
-                                 (if_then_else
-                                  (lt (abs (minus (match_dup 1)
-                                                  (plus (pc)
-                                                        (const_int 5))))
-                                      (const_int 1023))
-                                  (const_int 4)
-                                  (const_int 5))
-                                 (if_then_else
-                                  (lt (abs (minus (match_dup 1)
-                                                  (plus (pc)
-                                                        (const_int 2))))
-                                      (const_int 1023))
-                                  (const_int 4)
-                                  (const_int 5)))))])
+      (if_then_else 
+       (eq_attr "alternative" "0")
+;; Loop counter in register case.
+       (cond [(lt (abs (minus (match_dup 1) (plus (pc) (const_int 2))))
+                  (const_int 1023))
+;; Short branch has a length of 1.
+              (const_int 1)
+;; Long backward branch with nullified delay slot has length of 3.
+              (and (lt (match_dup 1) (pc))
+                   (eq (symbol_ref "INSN_ANNULLED_BRANCH_P (insn)")
+                       (const_int 1)))
+              (const_int 3)]
+;; Default others to 2.
+;; Long branches with unfilled delay slots  --or--
+;; Long forward with nullified delay slot.
+             (const_int 2))
+;; Loop counter in memory case.   Similar to above except we pay
+;; 3 extra insns in each case for reloading the counter into a register.
+       (if_then_else (lt (match_dup 1) (pc))
+         (cond [(lt (abs (minus (match_dup 1) (plus (pc) (const_int 5))))
+                    (const_int 1023))
+;; Short branch has length of 4 (the reloading costs 3 insns)
+                (const_int 4)
+                (and (lt (match_dup 1) (pc))
+                     (eq (symbol_ref "INSN_ANNULLED_BRANCH_P (insn)")
+                         (const_int 1)))
+;; Long backward branch with nullified delay slot has length of 6.
+                (const_int 6)]
+;; Default others to 5.
+;; Long branches with unfilled delay slots  --or--
+;; Long forward with nullified delay slot.
+               (const_int 5))
+         (if_then_else (lt (abs (minus (match_dup 1) 
+                                       (plus (pc) (const_int 2))))
+                           (const_int 1023))
+                       (const_int 4)
+                       (const_int 5)))))])
 
 
 ;; The next four peepholes take advantage of the new 5 operand