* config/mips/mips-protos.h (mips_output_conditional_branch): Change
authorrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Mar 2006 21:03:17 +0000 (21:03 +0000)
committerrsandifo <rsandifo@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 9 Mar 2006 21:03:17 +0000 (21:03 +0000)
interface.
(mips_output_order_conditional_branch): Declare.
* config/mips/mips.h (MIPS_BRANCH): New macro.
* config/mips/mips.c (gen_conditional_branch): Use VOIDmode
for the comparison.  Use gen_condjump.
(mips_output_conditional_branch): Rework interface to take the
asm templates for a direct branch and the inverse of a direct branch.
(mips_output_order_conditional_branch): New function.
(mips_builtin_branch_and_move): New function.
(mips_expand_builtin_compare): Use it.  Use VOIDmode for the
branch condition.  Use gen_single_cc as the condition for
__builtin_mips_upper_* or __builtin_mips_lower_*.
(mips_expand_builtin_bposge): Use mips_builtin_branch_and_move.
Use VOIDmode for the branch condition.
* config/mips/predicates.md (order_operator): New predicate.
* config/mips/mips.md (UNSPEC_SINGLE_CC): New constant.
(branch_fp): Rename to...
(*branch_fp): ...this.  Remove mode from comparison operator.
Use new mips_output_conditional_branch interface.
(branch_fp_inverted): Rename to...
(*branch_fp_inverted): ...this and update as for *branch_fp.
(*branch_zero<mode>): Rename to...
(*branch_order<mode>): ...this.  Remove mode from comparison operator.
Use mips_output_order_conditional_branch.  Only accept ordered
comparisons.
(*branch_zero<mode>_inverted): Rename to...
(*branch_order<mode>_inverted): ...this and update as for
*branch_order<mode>.
(*branch_equality<mode>): Accept zero as the second operand to
the equality operator.  Use the new mips_output_conditional_branch
interface.
(*branch_equality<mode>_inverted): Likewise.
(condjump): New expander.
* config/mips/mips-dsp.md (mips_bposge): Remove mode from comparison
operator.
* config/mips/mips-ps-3d.md (bc1any4t, bc1any4f): Likewise.
(bc1any2t, bc1any2f): Likewise.
(single_cc): New expander.
(*branch_upper_lower, *branch_upper_lower_inverted): New patterns.

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

gcc/ChangeLog
gcc/config/mips/mips-dsp.md
gcc/config/mips/mips-protos.h
gcc/config/mips/mips-ps-3d.md
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.md
gcc/config/mips/predicates.md

index 9b1fb91..32155a4 100644 (file)
@@ -1,5 +1,48 @@
 2006-03-09  Richard Sandiford  <richard@codesourcery.com>
 
+       * config/mips/mips-protos.h (mips_output_conditional_branch): Change
+       interface.
+       (mips_output_order_conditional_branch): Declare.
+       * config/mips/mips.h (MIPS_BRANCH): New macro.
+       * config/mips/mips.c (gen_conditional_branch): Use VOIDmode
+       for the comparison.  Use gen_condjump.
+       (mips_output_conditional_branch): Rework interface to take the
+       asm templates for a direct branch and the inverse of a direct branch.
+       (mips_output_order_conditional_branch): New function.
+       (mips_builtin_branch_and_move): New function.
+       (mips_expand_builtin_compare): Use it.  Use VOIDmode for the
+       branch condition.  Use gen_single_cc as the condition for
+       __builtin_mips_upper_* or __builtin_mips_lower_*.
+       (mips_expand_builtin_bposge): Use mips_builtin_branch_and_move.
+       Use VOIDmode for the branch condition.
+       * config/mips/predicates.md (order_operator): New predicate.
+       * config/mips/mips.md (UNSPEC_SINGLE_CC): New constant.
+       (branch_fp): Rename to...
+       (*branch_fp): ...this.  Remove mode from comparison operator.
+       Use new mips_output_conditional_branch interface.
+       (branch_fp_inverted): Rename to...
+       (*branch_fp_inverted): ...this and update as for *branch_fp.
+       (*branch_zero<mode>): Rename to...
+       (*branch_order<mode>): ...this.  Remove mode from comparison operator.
+       Use mips_output_order_conditional_branch.  Only accept ordered
+       comparisons.  
+       (*branch_zero<mode>_inverted): Rename to...
+       (*branch_order<mode>_inverted): ...this and update as for
+       *branch_order<mode>.
+       (*branch_equality<mode>): Accept zero as the second operand to
+       the equality operator.  Use the new mips_output_conditional_branch
+       interface.
+       (*branch_equality<mode>_inverted): Likewise.
+       (condjump): New expander.
+       * config/mips/mips-dsp.md (mips_bposge): Remove mode from comparison
+       operator.
+       * config/mips/mips-ps-3d.md (bc1any4t, bc1any4f): Likewise.
+       (bc1any2t, bc1any2f): Likewise.
+       (single_cc): New expander.
+       (*branch_upper_lower, *branch_upper_lower_inverted): New patterns.
+
+2006-03-09  Richard Sandiford  <richard@codesourcery.com>
+
        * doc/md.texi: Update documentation of MIPS constraints.
        * config/mips/constraints.md: New file.
        * config/mips/mips.md: Include it.
index a61b23f..3fdcc59 100644 (file)
 ;; BPOSGE32
 (define_insn "mips_bposge"
   [(set (pc)
-       (if_then_else
-          (ge:CCDSP (reg:CCDSP CCDSP_PO_REGNUM)
-                    (match_operand:SI 0 "immediate_operand" "I"))
-          (label_ref (match_operand 1 "" ""))
-          (pc)))]
+       (if_then_else (ge (reg:CCDSP CCDSP_PO_REGNUM)
+                         (match_operand:SI 0 "immediate_operand" "I"))
+                     (label_ref (match_operand 1 "" ""))
+                     (pc)))]
   "TARGET_DSP"
   "%*bposge%0\t%1%/"
   [(set_attr "type"    "branch")
index 9481b08..1dc31f5 100644 (file)
@@ -212,8 +212,9 @@ extern int mips_register_move_cost (enum machine_mode, enum reg_class,
 
 extern int mips_adjust_insn_length (rtx, int);
 extern const char *mips_output_load_label (void);
-extern const char *mips_output_conditional_branch (rtx, rtx *, int, int,
-                                                  int, int);
+extern const char *mips_output_conditional_branch (rtx, rtx *, const char *,
+                                                  const char *);
+extern const char *mips_output_order_conditional_branch (rtx, rtx *, bool);
 extern const char *mips_output_division (const char *, rtx *);
 extern unsigned int mips_hard_regno_nregs (int, enum machine_mode);
 extern bool mips_linked_madd_p (rtx, rtx);
index 17dd038..6a4c2b9 100644 (file)
 ; Branch on Any of Four Floating Point Condition Codes True
 (define_insn "bc1any4t"
   [(set (pc)
-       (if_then_else (ne:CCV4 (match_operand:CCV4 0 "register_operand" "z")
-                              (const_int 0))
+       (if_then_else (ne (match_operand:CCV4 0 "register_operand" "z")
+                         (const_int 0))
                      (label_ref (match_operand 1 "" ""))
                      (pc)))]
   "TARGET_MIPS3D"
 ; Branch on Any of Four Floating Point Condition Codes False
 (define_insn "bc1any4f"
   [(set (pc)
-       (if_then_else (ne:CCV4 (match_operand:CCV4 0 "register_operand" "z")
-                              (const_int -1))
+       (if_then_else (ne (match_operand:CCV4 0 "register_operand" "z")
+                         (const_int -1))
                      (label_ref (match_operand 1 "" ""))
                      (pc)))]
   "TARGET_MIPS3D"
 ; Branch on Any of Two Floating Point Condition Codes True
 (define_insn "bc1any2t"
   [(set (pc)
-       (if_then_else (ne:CCV2 (match_operand:CCV2 0 "register_operand" "z")
-                              (const_int 0))
+       (if_then_else (ne (match_operand:CCV2 0 "register_operand" "z")
+                         (const_int 0))
                      (label_ref (match_operand 1 "" ""))
                      (pc)))]
   "TARGET_MIPS3D"
 ; Branch on Any of Two Floating Point Condition Codes False
 (define_insn "bc1any2f"
   [(set (pc)
-       (if_then_else (ne:CCV2 (match_operand:CCV2 0 "register_operand" "z")
-                              (const_int -1))
+       (if_then_else (ne (match_operand:CCV2 0 "register_operand" "z")
+                         (const_int -1))
                      (label_ref (match_operand 1 "" ""))
                      (pc)))]
   "TARGET_MIPS3D"
   [(set_attr "type" "branch")
    (set_attr "mode" "none")])
 
+; Used to access one register in a CCV2 pair.  Operand 0 is the register
+; pair and operand 1 is the index of the register we want (a CONST_INT).
+(define_expand "single_cc"
+  [(ne (unspec:CC [(match_operand 0) (match_operand 1)] UNSPEC_SINGLE_CC)
+       (const_int 0))])
+
+; This is a normal floating-point branch pattern, but rather than check
+; a single CCmode register, it checks one register in a CCV2 pair.
+; Operand 2 is the register pair and operand 3 is the index of the
+; register we want.
+(define_insn "*branch_upper_lower"
+  [(set (pc)
+        (if_then_else
+        (match_operator 0 "equality_operator"
+           [(unspec:CC [(match_operand:CCV2 2 "register_operand" "z")
+                        (match_operand 3 "const_int_operand")]
+                       UNSPEC_SINGLE_CC)
+            (const_int 0)])
+        (label_ref (match_operand 1 "" ""))
+        (pc)))]
+  "TARGET_HARD_FLOAT"
+{
+  operands[2]
+    = gen_rtx_REG (CCmode, REGNO (operands[2]) + INTVAL (operands[3]));
+  return mips_output_conditional_branch (insn, operands,
+                                        MIPS_BRANCH ("b%F0", "%2,%1"),
+                                        MIPS_BRANCH ("b%W0", "%2,%1"));
+}
+  [(set_attr "type" "branch")
+   (set_attr "mode" "none")])
+
+; As above, but with the sense of the condition reversed.
+(define_insn "*branch_upper_lower_inverted"
+  [(set (pc)
+        (if_then_else
+        (match_operator 0 "equality_operator"
+           [(unspec:CC [(match_operand:CCV2 2 "register_operand" "z")
+                        (match_operand 3 "const_int_operand")]
+                       UNSPEC_SINGLE_CC)
+            (const_int 0)])
+        (pc)
+        (label_ref (match_operand 1 "" ""))))]
+  "TARGET_HARD_FLOAT"
+{
+  operands[2]
+    = gen_rtx_REG (CCmode, REGNO (operands[2]) + INTVAL (operands[3]));
+  return mips_output_conditional_branch (insn, operands,
+                                        MIPS_BRANCH ("b%W0", "%2,%1"),
+                                        MIPS_BRANCH ("b%F0", "%2,%1"));
+}
+  [(set_attr "type" "branch")
+   (set_attr "mode" "none")])
+
 ;----------------------------------------------------------------------------
 ; Floating Point Reduced Precision Reciprocal Square Root Instructions.
 ;----------------------------------------------------------------------------
index aed07e5..daa7488 100644 (file)
@@ -3186,15 +3186,11 @@ mips_emit_scc (enum rtx_code code, rtx target)
 void
 gen_conditional_branch (rtx *operands, enum rtx_code code)
 {
-  rtx op0, op1, target;
+  rtx op0, op1, condition;
 
   mips_emit_compare (&code, &op0, &op1, TARGET_MIPS16);
-  target = gen_rtx_IF_THEN_ELSE (VOIDmode,
-                                gen_rtx_fmt_ee (code, GET_MODE (op0),
-                                                op0, op1),
-                                gen_rtx_LABEL_REF (VOIDmode, operands[0]),
-                                pc_rtx);
-  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, target));
+  condition = gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
+  emit_jump_insn (gen_condjump (condition, operands[0]));
 }
 
 /* Emit the common code for conditional moves.  OPERANDS is the array
@@ -9127,217 +9123,126 @@ mips_output_load_label (void)
     }
 }
 
+/* Return the assembly code for INSN, which has the operands given by
+   OPERANDS, and which branches to OPERANDS[1] if some condition is true.
+   BRANCH_IF_TRUE is the asm template that should be used if OPERANDS[1]
+   is in range of a direct branch.  BRANCH_IF_FALSE is an inverted
+   version of BRANCH_IF_TRUE.  */
 
-/* Output assembly instructions to peform a conditional branch.
-
-   INSN is the branch instruction.  OPERANDS[0] is the condition.
-   OPERANDS[1] is the target of the branch.  OPERANDS[2] is the target
-   of the first operand to the condition.  If TWO_OPERANDS_P is
-   nonzero the comparison takes two operands; OPERANDS[3] will be the
-   second operand.
-
-   If INVERTED_P is nonzero we are to branch if the condition does
-   not hold.  If FLOAT_P is nonzero this is a floating-point comparison.
-
-   LENGTH is the length (in bytes) of the sequence we are to generate.
-   That tells us whether to generate a simple conditional branch, or a
-   reversed conditional branch around a `jr' instruction.  */
 const char *
-mips_output_conditional_branch (rtx insn, rtx *operands, int two_operands_p,
-                               int float_p, int inverted_p, int length)
-{
-  static char buffer[200];
-  /* The kind of comparison we are doing.  */
-  enum rtx_code code = GET_CODE (operands[0]);
-  /* Nonzero if the opcode for the comparison needs a `z' indicating
-     that it is a comparison against zero.  */
-  int need_z_p;
-  /* A string to use in the assembly output to represent the first
-     operand.  */
-  const char *op1 = "%z2";
-  /* A string to use in the assembly output to represent the second
-     operand.  Use the hard-wired zero register if there's no second
-     operand.  */
-  const char *op2 = (two_operands_p ? ",%z3" : ",%.");
-  /* The operand-printing string for the comparison.  */
-  const char *const comp = (float_p ? "%F0" : "%C0");
-  /* The operand-printing string for the inverted comparison.  */
-  const char *const inverted_comp = (float_p ? "%W0" : "%N0");
-
-  /* The MIPS processors (for levels of the ISA at least two), have
-     "likely" variants of each branch instruction.  These instructions
-     annul the instruction in the delay slot if the branch is not
-     taken.  */
-  mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
-
-  if (!two_operands_p)
-    {
-      /* To compute whether than A > B, for example, we normally
-        subtract B from A and then look at the sign bit.  But, if we
-        are doing an unsigned comparison, and B is zero, we don't
-        have to do the subtraction.  Instead, we can just check to
-        see if A is nonzero.  Thus, we change the CODE here to
-        reflect the simpler comparison operation.  */
-      switch (code)
-       {
-       case GTU:
-         code = NE;
-         break;
+mips_output_conditional_branch (rtx insn, rtx *operands,
+                               const char *branch_if_true,
+                               const char *branch_if_false)
+{
+  unsigned int length;
+  rtx taken, not_taken;
 
-       case LEU:
-         code = EQ;
-         break;
+  length = get_attr_length (insn);
+  if (length <= 8)
+    {
+      /* Just a simple conditional branch.  */
+      mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
+      return branch_if_true;
+    }
 
-       case GEU:
-         /* A condition which will always be true.  */
-         code = EQ;
-         op1 = "%.";
-         break;
+  /* Generate a reversed branch around a direct jump.  This fallback does
+     not use branch-likely instructions.  */
+  mips_branch_likely = false;
+  not_taken = gen_label_rtx ();
+  taken = operands[1];
 
-       case LTU:
-         /* A condition which will always be false.  */
-         code = NE;
-         op1 = "%.";
-         break;
+  /* Generate the reversed branch to NOT_TAKEN.  */
+  operands[1] = not_taken;
+  output_asm_insn (branch_if_false, operands);
 
-       default:
-         /* Not a special case.  */
-         break;
+  /* If INSN has a delay slot, we must provide delay slots for both the
+     branch to NOT_TAKEN and the conditional jump.  We must also ensure
+     that INSN's delay slot is executed in the appropriate cases.  */
+  if (final_sequence)
+    {
+      /* This first delay slot will always be executed, so use INSN's
+        delay slot if is not annulled.  */
+      if (!INSN_ANNULLED_BRANCH_P (insn))
+       {
+         final_scan_insn (XVECEXP (final_sequence, 0, 1),
+                          asm_out_file, optimize, 1, NULL);
+         INSN_DELETED_P (XVECEXP (final_sequence, 0, 1)) = 1;
        }
+      else
+       output_asm_insn ("nop", 0);
+      fprintf (asm_out_file, "\n");
     }
 
-  /* Relative comparisons are always done against zero.  But
-     equality comparisons are done between two operands, and therefore
-     do not require a `z' in the assembly language output.  */
-  need_z_p = (!float_p && code != EQ && code != NE);
-  /* For comparisons against zero, the zero is not provided
-     explicitly.  */
-  if (need_z_p)
-    op2 = "";
-
-  /* Begin by terminating the buffer.  That way we can always use
-     strcat to add to it.  */
-  buffer[0] = '\0';
+  /* Output the unconditional branch to TAKEN.  */
+  if (length <= 16)
+    output_asm_insn ("j\t%0%/", &taken);
+  else
+    {
+      output_asm_insn (mips_output_load_label (), &taken);
+      output_asm_insn ("jr\t%@%]%/", 0);
+    }
 
-  switch (length)
+  /* Now deal with its delay slot; see above.  */
+  if (final_sequence)
     {
-    case 4:
-    case 8:
-      /* Just a simple conditional branch.  */
-      if (float_p)
-       sprintf (buffer, "%%*b%s%%?\t%%Z2%%1%%/",
-                inverted_p ? inverted_comp : comp);
+      /* This delay slot will only be executed if the branch is taken.
+        Use INSN's delay slot if is annulled.  */
+      if (INSN_ANNULLED_BRANCH_P (insn))
+       {
+         final_scan_insn (XVECEXP (final_sequence, 0, 1),
+                          asm_out_file, optimize, 1, NULL);
+         INSN_DELETED_P (XVECEXP (final_sequence, 0, 1)) = 1;
+       }
       else
-       sprintf (buffer, "%%*b%s%s%%?\t%s%s,%%1%%/",
-                inverted_p ? inverted_comp : comp,
-                need_z_p ? "z" : "",
-                op1,
-                op2);
-      return buffer;
-
-    case 12:
-    case 16:
-    case 24:
-    case 28:
-      {
-       /* Generate a reversed conditional branch around ` j'
-          instruction:
-
-               .set noreorder
-               .set nomacro
-               bc    l
-               delay_slot or #nop
-               j     target
-               #nop
-            l:
-               .set macro
-               .set reorder
-
-          If the original branch was a likely branch, the delay slot
-          must be executed only if the branch is taken, so generate:
-
-               .set noreorder
-               .set nomacro
-               bc    l
-               #nop
-               j     target
-               delay slot or #nop
-            l:
-               .set macro
-               .set reorder
-
-          When generating PIC, instead of:
-
-               j     target
-
-          we emit:
-
-               .set noat
-               la    $at, target
-               jr    $at
-               .set at
-       */
-
-        rtx orig_target;
-       rtx target = gen_label_rtx ();
-
-        orig_target = operands[1];
-        operands[1] = target;
-       /* Generate the reversed comparison.  This takes four
-          bytes.  */
-       if (float_p)
-         sprintf (buffer, "%%*b%s\t%%Z2%%1",
-                  inverted_p ? comp : inverted_comp);
-       else
-         sprintf (buffer, "%%*b%s%s\t%s%s,%%1",
-                  inverted_p ? comp : inverted_comp,
-                  need_z_p ? "z" : "",
-                  op1,
-                  op2);
-        output_asm_insn (buffer, operands);
-
-        if (length != 16 && length != 28 && ! mips_branch_likely)
-          {
-            /* Output delay slot instruction.  */
-            rtx insn = final_sequence;
-            final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file,
-                             optimize, 1, NULL);
-            INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1;
-          }
-       else
-         output_asm_insn ("%#", 0);
+       output_asm_insn ("nop", 0);
+      fprintf (asm_out_file, "\n");
+    }
 
-       if (length <= 16)
-         output_asm_insn ("j\t%0", &orig_target);
-       else
-         {
-           output_asm_insn (mips_output_load_label (), &orig_target);
-           output_asm_insn ("jr\t%@%]", 0);
-         }
+  /* Output NOT_TAKEN.  */
+  (*targetm.asm_out.internal_label) (asm_out_file, "L",
+                                    CODE_LABEL_NUMBER (not_taken));
+  return "";
+}
 
-        if (length != 16 && length != 28 && mips_branch_likely)
-          {
-            /* Output delay slot instruction.  */
-            rtx insn = final_sequence;
-            final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file,
-                             optimize, 1, NULL);
-            INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1;
-          }
-       else
-         output_asm_insn ("%#", 0);
+/* Return the assembly code for INSN, which branches to OPERANDS[1]
+   if some ordered condition is true.  The condition is given by
+   OPERANDS[0] if !INVERTED_P, otherwise it is the inverse of
+   OPERANDS[0].  OPERANDS[2] is the comparison's first operand;
+   its second is always zero.  */
 
-        (*targetm.asm_out.internal_label) (asm_out_file, "L",
-                                   CODE_LABEL_NUMBER (target));
+const char *
+mips_output_order_conditional_branch (rtx insn, rtx *operands, bool inverted_p)
+{
+  const char *branch[2];
 
-        return "";
-      }
+  /* Make BRANCH[1] branch to OPERANDS[1] when the condition is true.
+     Make BRANCH[0] branch on the inverse condition.  */
+  switch (GET_CODE (operands[0]))
+    {
+      /* These cases are equivalent to comparisons against zero.  */
+    case LEU:
+      inverted_p = !inverted_p;
+      /* Fall through.  */
+    case GTU:
+      branch[!inverted_p] = MIPS_BRANCH ("bne", "%2,%.,%1");
+      branch[inverted_p] = MIPS_BRANCH ("beq", "%2,%.,%1");
+      break;
+
+      /* These cases are always true or always false.  */
+    case LTU:
+      inverted_p = !inverted_p;
+      /* Fall through.  */
+    case GEU:
+      branch[!inverted_p] = MIPS_BRANCH ("beq", "%.,%.,%1");
+      branch[inverted_p] = MIPS_BRANCH ("bne", "%.,%.,%1");
+      break;
 
     default:
-      gcc_unreachable ();
+      branch[!inverted_p] = MIPS_BRANCH ("b%C0z", "%2,%1");
+      branch[inverted_p] = MIPS_BRANCH ("b%N0z", "%2,%1");
+      break;
     }
-
-  /* NOTREACHED */
-  return 0;
+  return mips_output_conditional_branch (insn, operands, branch[1], branch[0]);
 }
 \f
 /* Used to output div or ddiv instruction DIVISION, which has the operands
@@ -10591,6 +10496,34 @@ mips_expand_builtin_movtf (enum mips_builtin_type type,
   return target;
 }
 
+/* Move VALUE_IF_TRUE into TARGET if CONDITION is true; move VALUE_IF_FALSE
+   into TARGET otherwise.  Return TARGET.  */
+
+static rtx
+mips_builtin_branch_and_move (rtx condition, rtx target,
+                             rtx value_if_true, rtx value_if_false)
+{
+  rtx true_label, done_label;
+
+  true_label = gen_label_rtx ();
+  done_label = gen_label_rtx ();
+
+  /* First assume that CONDITION is false.  */
+  emit_move_insn (target, value_if_false);
+
+  /* Branch to TRUE_LABEL if CONDITION is true and DONE_LABEL otherwise.  */
+  emit_jump_insn (gen_condjump (condition, true_label));
+  emit_jump_insn (gen_jump (done_label));
+  emit_barrier ();
+
+  /* Fix TARGET if CONDITION is true.  */
+  emit_label (true_label);
+  emit_move_insn (target, value_if_true);
+
+  emit_label (done_label);
+  return target;
+}
+
 /* Expand a comparison builtin of type BUILTIN_TYPE.  ICODE is the code
    of the comparison instruction and COND is the condition it should test.
    ARGLIST is the list of function arguments and TARGET, if nonnull,
@@ -10601,10 +10534,8 @@ mips_expand_builtin_compare (enum mips_builtin_type builtin_type,
                             enum insn_code icode, enum mips_fp_condition cond,
                             rtx target, tree arglist)
 {
-  rtx label1, label2, if_then_else;
-  rtx pat, cmp_result, ops[MAX_RECOG_OPERANDS];
-  rtx target_if_equal, target_if_unequal;
-  int cmp_value, i;
+  rtx offset, condition, cmp_result, ops[MAX_RECOG_OPERANDS];
+  int i;
 
   if (target == 0 || GET_MODE (target) != SImode)
     target = gen_reg_rtx (SImode);
@@ -10617,12 +10548,12 @@ mips_expand_builtin_compare (enum mips_builtin_type builtin_type,
   switch (insn_data[icode].n_operands)
     {
     case 4:
-      pat = GEN_FCN (icode) (cmp_result, ops[1], ops[2], GEN_INT (cond));
+      emit_insn (GEN_FCN (icode) (cmp_result, ops[1], ops[2], GEN_INT (cond)));
       break;
 
     case 6:
-      pat = GEN_FCN (icode) (cmp_result, ops[1], ops[2],
-                            ops[3], ops[4], GEN_INT (cond));
+      emit_insn (GEN_FCN (icode) (cmp_result, ops[1], ops[2],
+                                 ops[3], ops[4], GEN_INT (cond)));
       break;
 
     default:
@@ -10631,71 +10562,35 @@ mips_expand_builtin_compare (enum mips_builtin_type builtin_type,
 
   /* If the comparison sets more than one register, we define the result
      to be 0 if all registers are false and -1 if all registers are true.
-     The value of the complete result is indeterminate otherwise.  It is
-     possible to test individual registers using SUBREGs.
-
-     Set up CMP_RESULT, CMP_VALUE, TARGET_IF_EQUAL and TARGET_IF_UNEQUAL so
-     that the result should be TARGET_IF_EQUAL if (EQ CMP_RESULT CMP_VALUE)
-     and TARGET_IF_UNEQUAL otherwise.  */
-  if (builtin_type == MIPS_BUILTIN_CMP_ALL)
-    {
-      cmp_value = -1;
-      target_if_equal = const1_rtx;
-      target_if_unequal = const0_rtx;
-    }
-  else
+     The value of the complete result is indeterminate otherwise.  */
+  switch (builtin_type)
     {
-      cmp_value = 0;
-      target_if_equal = const0_rtx;
-      target_if_unequal = const1_rtx;
-      if (builtin_type == MIPS_BUILTIN_CMP_UPPER)
-       cmp_result = simplify_gen_subreg (CCmode, cmp_result, CCV2mode, 4);
-      else if (builtin_type == MIPS_BUILTIN_CMP_LOWER)
-       cmp_result = simplify_gen_subreg (CCmode, cmp_result, CCV2mode, 0);
-    }
-
-  /* First assume that CMP_RESULT == CMP_VALUE.  */
-  emit_move_insn (target, target_if_equal);
-
-  /* Branch to LABEL1 if CMP_RESULT != CMP_VALUE.  */
-  emit_insn (pat);
-  label1 = gen_label_rtx ();
-  label2 = gen_label_rtx ();
-  if_then_else
-    = gen_rtx_IF_THEN_ELSE (VOIDmode,
-                           gen_rtx_fmt_ee (NE, GET_MODE (cmp_result),
-                                           cmp_result, GEN_INT (cmp_value)),
-                           gen_rtx_LABEL_REF (VOIDmode, label1), pc_rtx);
-  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_then_else));
-  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
-                              gen_rtx_LABEL_REF (VOIDmode, label2)));
-  emit_barrier ();
-  emit_label (label1);
+    case MIPS_BUILTIN_CMP_ALL:
+      condition = gen_rtx_NE (VOIDmode, cmp_result, constm1_rtx);
+      return mips_builtin_branch_and_move (condition, target,
+                                          const0_rtx, const1_rtx);
 
-  /* Fix TARGET for CMP_RESULT != CMP_VALUE.  */
-  emit_move_insn (target, target_if_unequal);
-  emit_label (label2);
+    case MIPS_BUILTIN_CMP_UPPER:
+    case MIPS_BUILTIN_CMP_LOWER:
+      offset = GEN_INT (builtin_type == MIPS_BUILTIN_CMP_UPPER);
+      condition = gen_single_cc (cmp_result, offset);
+      return mips_builtin_branch_and_move (condition, target,
+                                          const1_rtx, const0_rtx);
 
-  return target;
+    default:
+      condition = gen_rtx_NE (VOIDmode, cmp_result, const0_rtx);
+      return mips_builtin_branch_and_move (condition, target,
+                                          const1_rtx, const0_rtx);
+    }
 }
 
 /* Expand a bposge builtin of type BUILTIN_TYPE.  TARGET, if nonnull,
-   suggests a good place to put the boolean result.
-
-   The sequence we want is
-
-       li      target, 0
-       bposge* label1
-       j       label2
-   label1:
-       li      target, 1
-   label2:  */
+   suggests a good place to put the boolean result.  */
 
 static rtx
 mips_expand_builtin_bposge (enum mips_builtin_type builtin_type, rtx target)
 {
-  rtx label1, label2, if_then_else;
-  rtx cmp_result;
+  rtx condition, cmp_result;
   int cmp_value;
 
   if (target == 0 || GET_MODE (target) != SImode)
@@ -10708,29 +10603,9 @@ mips_expand_builtin_bposge (enum mips_builtin_type builtin_type, rtx target)
   else
     gcc_assert (0);
 
-  /* Move 0 to target */
-  emit_move_insn (target, const0_rtx);
-
-  /* Generate two labels */
-  label1 = gen_label_rtx ();
-  label2 = gen_label_rtx ();
-
-  /* Generate if_then_else */
-  if_then_else
-    = gen_rtx_IF_THEN_ELSE (VOIDmode,
-                           gen_rtx_fmt_ee (GE, CCDSPmode,
-                                           cmp_result, GEN_INT (cmp_value)),
-                           gen_rtx_LABEL_REF (VOIDmode, label1), pc_rtx);
-
-  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_then_else));
-  emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
-                               gen_rtx_LABEL_REF (VOIDmode, label2)));
-  emit_barrier ();
-  emit_label (label1);
-  emit_move_insn (target, const1_rtx);
-  emit_label (label2);
-
-  return target;
+  condition = gen_rtx_GE (VOIDmode, cmp_result, GEN_INT (cmp_value));
+  return mips_builtin_branch_and_move (condition, target,
+                                      const1_rtx, const0_rtx);
 }
 \f
 /* Set SYMBOL_REF_FLAGS for the SYMBOL_REF inside RTL, which belongs to DECL.
index 8a993e0..b0ae120 100644 (file)
@@ -2272,6 +2272,12 @@ typedef struct mips_args {
    be updated with the correct length of the insn.  */
 #define ADJUST_INSN_LENGTH(INSN, LENGTH) \
   ((LENGTH) = mips_adjust_insn_length ((INSN), (LENGTH)))
+
+/* Return the asm template for a non-MIPS16 conditional branch instruction.
+   OPCODE is the opcode's mnemonic and OPERANDS is the asm template for
+   its operands.  */
+#define MIPS_BRANCH(OPCODE, OPERANDS) \
+  "%*" OPCODE "%?\t" OPERANDS "%/"
 \f
 /* Control the assembler format that we output.  */
 
index 23677f0..01653d6 100644 (file)
@@ -72,6 +72,7 @@
    (UNSPEC_RSQRT2              209)
    (UNSPEC_RECIP1              210)
    (UNSPEC_RECIP2              211)
+   (UNSPEC_SINGLE_CC           212)
 
    ;; MIPS DSP ASE Revision 0.98 3/24/2005
    (UNSPEC_ADDQ                        300)
 
 ;; Conditional branches on floating-point equality tests.
 
-(define_insn "branch_fp"
+(define_insn "*branch_fp"
   [(set (pc)
         (if_then_else
-         (match_operator:CC 0 "comparison_operator"
-                            [(match_operand:CC 2 "register_operand" "z")
-                            (const_int 0)])
+         (match_operator 0 "equality_operator"
+                         [(match_operand:CC 2 "register_operand" "z")
+                         (const_int 0)])
          (label_ref (match_operand 1 "" ""))
          (pc)))]
   "TARGET_HARD_FLOAT"
 {
-  return mips_output_conditional_branch (insn,
-                                        operands,
-                                        /*two_operands_p=*/0,
-                                        /*float_p=*/1,
-                                        /*inverted_p=*/0,
-                                        get_attr_length (insn));
+  return mips_output_conditional_branch (insn, operands,
+                                        MIPS_BRANCH ("b%F0", "%2,%1"),
+                                        MIPS_BRANCH ("b%W0", "%2,%1"));
 }
-  [(set_attr "type"    "branch")
-   (set_attr "mode"    "none")])
+  [(set_attr "type" "branch")
+   (set_attr "mode" "none")])
 
-(define_insn "branch_fp_inverted"
+(define_insn "*branch_fp_inverted"
   [(set (pc)
         (if_then_else
-         (match_operator:CC 0 "comparison_operator"
-                            [(match_operand:CC 2 "register_operand" "z")
-                            (const_int 0)])
+         (match_operator 0 "equality_operator"
+                         [(match_operand:CC 2 "register_operand" "z")
+                         (const_int 0)])
          (pc)
          (label_ref (match_operand 1 "" ""))))]
   "TARGET_HARD_FLOAT"
 {
-  return mips_output_conditional_branch (insn,
-                                        operands,
-                                        /*two_operands_p=*/0,
-                                        /*float_p=*/1,
-                                        /*inverted_p=*/1,
-                                        get_attr_length (insn));
+  return mips_output_conditional_branch (insn, operands,
+                                        MIPS_BRANCH ("b%W0", "%2,%1"),
+                                        MIPS_BRANCH ("b%F0", "%2,%1"));
 }
-  [(set_attr "type"    "branch")
-   (set_attr "mode"    "none")])
+  [(set_attr "type" "branch")
+   (set_attr "mode" "none")])
 
-;; Conditional branches on comparisons with zero.
+;; Conditional branches on ordered comparisons with zero.
 
-(define_insn "*branch_zero<mode>"
+(define_insn "*branch_order<mode>"
   [(set (pc)
        (if_then_else
-        (match_operator 0 "comparison_operator"
+        (match_operator 0 "order_operator"
                         [(match_operand:GPR 2 "register_operand" "d")
                          (const_int 0)])
         (label_ref (match_operand 1 "" ""))
         (pc)))]
   "!TARGET_MIPS16"
-{
-  return mips_output_conditional_branch (insn,
-                                        operands,
-                                        /*two_operands_p=*/0,
-                                        /*float_p=*/0,
-                                        /*inverted_p=*/0,
-                                        get_attr_length (insn));
-}
+  { return mips_output_order_conditional_branch (insn, operands, false); }
   [(set_attr "type" "branch")
    (set_attr "mode" "none")])
 
-(define_insn "*branch_zero<mode>_inverted"
+(define_insn "*branch_order<mode>_inverted"
   [(set (pc)
        (if_then_else
-        (match_operator 0 "comparison_operator"
+        (match_operator 0 "order_operator"
                         [(match_operand:GPR 2 "register_operand" "d")
                          (const_int 0)])
         (pc)
         (label_ref (match_operand 1 "" ""))))]
   "!TARGET_MIPS16"
-{
-  return mips_output_conditional_branch (insn,
-                                        operands,
-                                        /*two_operands_p=*/0,
-                                        /*float_p=*/0,
-                                        /*inverted_p=*/1,
-                                        get_attr_length (insn));
-}
+  { return mips_output_order_conditional_branch (insn, operands, true); }
   [(set_attr "type" "branch")
    (set_attr "mode" "none")])
 
        (if_then_else
         (match_operator 0 "equality_operator"
                         [(match_operand:GPR 2 "register_operand" "d")
-                         (match_operand:GPR 3 "register_operand" "d")])
+                         (match_operand:GPR 3 "reg_or_0_operand" "dJ")])
         (label_ref (match_operand 1 "" ""))
         (pc)))]
   "!TARGET_MIPS16"
 {
-  return mips_output_conditional_branch (insn,
-                                        operands,
-                                        /*two_operands_p=*/1,
-                                        /*float_p=*/0,
-                                        /*inverted_p=*/0,
-                                        get_attr_length (insn));
+  return mips_output_conditional_branch (insn, operands,
+                                        MIPS_BRANCH ("b%C0", "%2,%z3,%1"),
+                                        MIPS_BRANCH ("b%N0", "%2,%z3,%1"));
 }
   [(set_attr "type" "branch")
    (set_attr "mode" "none")])
        (if_then_else
         (match_operator 0 "equality_operator"
                         [(match_operand:GPR 2 "register_operand" "d")
-                         (match_operand:GPR 3 "register_operand" "d")])
+                         (match_operand:GPR 3 "reg_or_0_operand" "dJ")])
         (pc)
         (label_ref (match_operand 1 "" ""))))]
   "!TARGET_MIPS16"
 {
-  return mips_output_conditional_branch (insn,
-                                        operands,
-                                        /*two_operands_p=*/1,
-                                        /*float_p=*/0,
-                                        /*inverted_p=*/1,
-                                        get_attr_length (insn));
+  return mips_output_conditional_branch (insn, operands,
+                                        MIPS_BRANCH ("b%N0", "%2,%z3,%1"),
+                                        MIPS_BRANCH ("b%C0", "%2,%z3,%1"));
 }
   [(set_attr "type" "branch")
    (set_attr "mode" "none")])
   gen_conditional_branch (operands, <CODE>);
   DONE;
 })
+
+;; Used to implement built-in functions.
+(define_expand "condjump"
+  [(set (pc)
+       (if_then_else (match_operand 0)
+                     (label_ref (match_operand 1))
+                     (pc)))])
 \f
 ;;
 ;;  ....................
index a96e017..d93621d 100644 (file)
 (define_predicate "trap_comparison_operator"
   (match_code "eq,ne,lt,ltu,ge,geu"))
 
+(define_predicate "order_operator"
+  (match_code "lt,ltu,le,leu,ge,geu,gt,gtu"))
+
 
 (define_predicate "small_data_pattern"
   (and (match_code "set,parallel,unspec,unspec_volatile,prefetch")