i386.md (floatdi?f): Avoid usinf of SSE instructions if TARGET_64BIT is false.
authorJan Hubicka <jh@suse.cz>
Wed, 6 Jun 2001 12:57:31 +0000 (14:57 +0200)
committerJan Hubicka <hubicka@gcc.gnu.org>
Wed, 6 Jun 2001 12:57:31 +0000 (12:57 +0000)
* i386.md (floatdi?f): Avoid usinf of SSE instructions
if TARGET_64BIT is false.
(floatdi?f_i386_only): New insn.
(floatdi?f_i386): Disable for !TARGET_64BIT.

* (min?f, max?f splitters): Handle case where
operands are cross-matched.

* i386.h (HI_REGISTER_NAMES): Remove redundant definition
(MMX_REGISTER_NAMES): Kill.
(PRINT_OPERAND): Fix comment.
(PRINT_REG): Likewise.
* i386.c (print_reg): Kill support for 'm' CODE; simplify.
(print_operand): Update comment; kill 'm'.

* i386.c (x86_branch_hints): New global variable
(print_operand): Support outputting of branch prediction hints.
* i386.md (conditional jump patterns): Add branch prediction hints
to the template.
* i386.h (x86_branch_hints): Declare
(TARGET_BRANCH_PREDICTION_HINTS): New macro.
(PRINT_OPERAND_FUNCT_VALID_P): New.
* final.c (final_forward_branch_p): New function.

From-SVN: r42945

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.h
gcc/config/i386/i386.md
gcc/final.c

index 7b7b76a3494df8d6bfafcc97dcf9f7cf12ca0755..e04cd659c635666fc21f71cd104cf32dc61c9a4e 100644 (file)
@@ -1,3 +1,29 @@
+Wed Jun  6 14:51:05 CEST 2001  Jan Hubicka  <jh@suse.cz>
+
+       * i386.md (floatdi?f): Avoid usinf of SSE instructions
+       if TARGET_64BIT is false.
+       (floatdi?f_i386_only): New insn.
+       (floatdi?f_i386): Disable for !TARGET_64BIT.
+
+       * (min?f, max?f splitters): Handle case where
+       operands are cross-matched.
+
+       * i386.h (HI_REGISTER_NAMES): Remove redundant definition
+       (MMX_REGISTER_NAMES): Kill.
+       (PRINT_OPERAND): Fix comment.
+       (PRINT_REG): Likewise.
+       * i386.c (print_reg): Kill support for 'm' CODE; simplify.
+       (print_operand): Update comment; kill 'm'.
+
+       * i386.c (x86_branch_hints): New global variable
+       (print_operand): Support outputting of branch prediction hints.
+       * i386.md (conditional jump patterns): Add branch prediction hints
+       to the template.
+       * i386.h (x86_branch_hints): Declare
+       (TARGET_BRANCH_PREDICTION_HINTS): New macro.
+       (PRINT_OPERAND_FUNCT_VALID_P): New.
+       * final.c (final_forward_branch_p): New function.
+
 2001-06-06  Richard Henderson  <rth@redhat.com>
 
        * flow.c (mark_used_reg): Clean up looping over multiple hard
index e352d073efddaf3c2c1615ff474bdf379a4845f1..275788e48d494fb2c0883979fe90386519ccbb1f 100644 (file)
@@ -290,6 +290,7 @@ const int x86_use_bit_test = m_386;
 const int x86_unroll_strlen = m_486 | m_PENT | m_PPRO | m_ATHLON | m_K6;
 const int x86_cmove = m_PPRO | m_ATHLON | m_PENT4;
 const int x86_deep_branch = m_PPRO | m_K6 | m_ATHLON | m_PENT4;
+const int x86_branch_hints = m_PENT4;
 const int x86_use_sahf = m_PPRO | m_K6 | m_PENT4;
 const int x86_partial_reg_stall = m_PPRO;
 const int x86_use_loop = m_K6;
@@ -3796,7 +3797,7 @@ print_reg (x, code, file)
   if (ASSEMBLER_DIALECT == 0 || USER_LABEL_PREFIX[0] == 0)
     putc ('%', file);
 
-  if (code == 'w')
+  if (code == 'w' || MMX_REG_P (x))
     code = 2;
   else if (code == 'b')
     code = 1;
@@ -3808,8 +3809,6 @@ print_reg (x, code, file)
     code = 3;
   else if (code == 'h')
     code = 0;
-  else if (code == 'm' || MMX_REG_P (x))
-    code = 5;
   else
     code = GET_MODE_SIZE (GET_MODE (x));
 
@@ -3821,7 +3820,7 @@ print_reg (x, code, file)
        abort ();
       switch (code)
        {
-         case 5:
+         case 0:
            error ("Extended registers have no high halves\n");
            break;
          case 1:
@@ -3844,9 +3843,6 @@ print_reg (x, code, file)
     }
   switch (code)
     {
-    case 5:
-      fputs (hi_reg_name[REGNO (x)], file);
-      break;
     case 3:
       if (STACK_TOP_P (x))
        {
@@ -3879,6 +3875,7 @@ print_reg (x, code, file)
    L,W,B,Q,S,T -- print the opcode suffix for specified size of operand.
    C -- print opcode suffix for set/cmov insn.
    c -- like C, but print reversed condition
+   F,f -- likewise, but for floating-point.
    R -- print the prefix for register names.
    z -- print the opcode suffix for the size of the current operand.
    * -- print a star (in certain assembler syntax)
@@ -3891,10 +3888,11 @@ print_reg (x, code, file)
    w --  likewise, print the HImode name of the register.
    k --  likewise, print the SImode name of the register.
    q --  likewise, print the DImode name of the register.
-   h --  print the QImode name for a "high" register, either ah, bh, ch or dh.
-   y --  print "st(0)" instead of "st" as a register.
-   m --  print "st(n)" as an mmx register.
+   h -- print the QImode name for a "high" register, either ah, bh, ch or dh.
+   y -- print "st(0)" instead of "st" as a register.
    D -- print condition for SSE cmp instruction.
+   P -- if PIC, print an @PLT suffix.
+   X -- don't print any sort of PIC '@' suffix for a symbol.
  */
 
 void
@@ -4017,7 +4015,6 @@ print_operand (file, x, code)
        case 'q':
        case 'h':
        case 'y':
-       case 'm':
        case 'X':
        case 'P':
          break;
@@ -4085,7 +4082,39 @@ print_operand (file, x, code)
        case 'f':
          put_condition_code (GET_CODE (x), GET_MODE (XEXP (x, 0)), 1, 1, file);
          return;
+       case '+':
+         {
+           rtx x;
 
+           if (!optimize || optimize_size || !TARGET_BRANCH_PREDICTION_HINTS)
+             return;
+           
+           x = find_reg_note (current_output_insn, REG_BR_PROB, 0);
+           if (x)
+             {
+               int pred_val = INTVAL (XEXP (x, 0));
+
+               if (pred_val < REG_BR_PROB_BASE * 45 / 100
+                   || pred_val > REG_BR_PROB_BASE * 55 / 100)
+                 {
+                   int taken = pred_val > REG_BR_PROB_BASE / 2;
+                   int cputaken = final_forward_branch_p (current_output_insn) == 0;
+
+                   /* Emit hints only in the case default branch prediction
+                      heruistics would fail.  */
+                   if (taken != cputaken)
+                     {
+                       /* We use 3e (DS) prefix for taken branches and
+                          2e (CS) prefix for not taken branches.  */
+                       if (taken)
+                         fputs ("ds ; ", file);
+                       else
+                         fputs ("cs ; ", file);
+                     }
+                 }
+             }
+           return;
+         }
        default:
          {
            char str[50];
index 9f47f5cac7219fd00a364a38a68847e63be03ca2..f1f8bef8d22d8d579d449df6af848c143337835b 100644 (file)
@@ -202,7 +202,7 @@ extern int target_flags;
 #define CPUMASK (1 << ix86_cpu)
 extern const int x86_use_leave, x86_push_memory, x86_zero_extend_with_and;
 extern const int x86_use_bit_test, x86_cmove, x86_deep_branch;
-extern const int x86_unroll_strlen;
+extern const int x86_branch_hints, x86_unroll_strlen;
 extern const int x86_double_with_add, x86_partial_reg_stall, x86_movx;
 extern const int x86_use_loop, x86_use_fiop, x86_use_mov0;
 extern const int x86_use_cltd, x86_read_modify_write;
@@ -222,6 +222,7 @@ extern const int x86_partial_reg_dependency, x86_memory_mismatch_stall;
    safe to enable all CMOVE instructions.  */
 #define TARGET_CMOVE ((x86_cmove & (1 << ix86_arch)) || TARGET_SSE)
 #define TARGET_DEEP_BRANCH_PREDICTION (x86_deep_branch & CPUMASK)
+#define TARGET_BRANCH_PREDICTION_HINTS (x86_branch_hints & CPUMASK)
 #define TARGET_DOUBLE_WITH_ADD (x86_double_with_add & CPUMASK)
 #define TARGET_USE_SAHF ((x86_use_sahf & CPUMASK) && !TARGET_64BIT)
 #define TARGET_MOVX (x86_movx & CPUMASK)
@@ -2755,11 +2756,6 @@ while (0)
    For float regs, the stack top is sometimes referred to as "%st(0)"
    instead of just "%st".  PRINT_REG handles this with the "y" code.  */
 
-#define HI_REGISTER_NAMES                                              \
-{"ax","dx","cx","bx","si","di","bp","sp",                              \
- "st","st(1)","st(2)","st(3)","st(4)","st(5)","st(6)","st(7)","",      \
- "flags","fpsr", "dirflag", "frame" }
-
 #undef  HI_REGISTER_NAMES                                              
 #define HI_REGISTER_NAMES                                              \
 {"ax","dx","cx","bx","si","di","bp","sp",                              \
@@ -2798,9 +2794,6 @@ number as al, and ax.
 #define QI_HIGH_REGISTER_NAMES \
 {"ah", "dh", "ch", "bh", }
 
-#define MMX_REGISTER_NAMES \
-{0,0,0,0,0,0,0,0,"mm0","mm1","mm2","mm3","mm4","mm5","mm6","mm7"}
-
 /* How to renumber registers for dbx and gdb.  */
 
 #define DBX_REGISTER_NUMBER(n) \
@@ -2970,33 +2963,19 @@ do { long l;                                            \
 \f
 /* Print operand X (an rtx) in assembler syntax to file FILE.
    CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
-   The CODE z takes the size of operand from the following digit, and
-   outputs b,w,or l respectively.
-
-   On the 80386, we use several such letters:
-   f -- float insn (print a CONST_DOUBLE as a float rather than in hex).
-   L,W,B,Q,S,T -- print the opcode suffix for specified size of operand.
-   R -- print the prefix for register names.
-   z -- print the opcode suffix for the size of the current operand.
-   * -- print a star (in certain assembler syntax)
-   A -- print an absolute memory reference.
-   P -- if PIC, print an @PLT suffix.
-   X -- don't print any sort of PIC '@' suffix for a symbol.
-   s -- ??? something to do with double shifts.  not actually used, afaik.
-   C -- print a conditional move suffix corresponding to the op code.
-   c -- likewise, but reverse the condition.
-   F,f -- likewise, but for floating-point.  */
+   Effect of various CODE letters is described in i386.c near
+   print_operand function.  */
 
 #define PRINT_OPERAND_PUNCT_VALID_P(CODE)                              \
-  ((CODE) == '*')
+  ((CODE) == '*' || (CODE) == '+')
 
 /* Print the name of a register based on its machine mode and number.
    If CODE is 'w', pretend the mode is HImode.
    If CODE is 'b', pretend the mode is QImode.
    If CODE is 'k', pretend the mode is SImode.
-   If CODE is 'd', pretend the mode is DImode.
+   If CODE is 'q', pretend the mode is DImode.
    If CODE is 'h', pretend the reg is the `high' byte register.
-   If CODE is 'y', print "st(0)" instead of "st", if the reg is stack op. */
+   If CODE is 'y', print "st(0)" instead of "st", if the reg is stack op.  */
 
 #define PRINT_REG(X, CODE, FILE)  \
   print_reg (X, CODE, FILE)
index dcd205bbd66119ddc8eafe40446ed9c00ee56a19..015bd83be634d6c55f301bdafe80b442c9cd248b 100644 (file)
   "TARGET_80387 || (TARGET_SSE2 && TARGET_64BIT)"
   "
 {
-  if (TARGET_SSE2)
+  if (TARGET_SSE2 && TARGET_64BIT)
    {
      rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DImode);
      emit_insn (gen_fix_truncdfdi_sse (out, operands[1]));
   "TARGET_80387 || (TARGET_SSE && TARGET_64BIT)"
   "
 {
-  if (TARGET_SSE2)
+  if (TARGET_SSE2 && TARGET_64BIT)
    {
      rtx out = REG_P (operands[0]) ? operands[0] : gen_reg_rtx (DImode);
      emit_insn (gen_fix_truncsfdi_sse (out, operands[1]));
   "(TARGET_SSE && TARGET_64BIT) || TARGET_80387"
   "")
 
+(define_insn "*floatdisf2_i387_only"
+  [(set (match_operand:SF 0 "register_operand" "=f,?f")
+       (float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r")))]
+  "TARGET_80387 && (!TARGET_SSE || !TARGET_64BIT || TARGET_MIX_SSE_I387)"
+  "@
+   fild%z1\\t%1
+   #"
+  [(set_attr "type" "fmov,multi")
+   (set_attr "mode" "SF")
+   (set_attr "fp_int_src" "true")])
+
 (define_insn "*floatdisf2_i387"
   [(set (match_operand:SF 0 "register_operand" "=f,?f,x")
        (float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r,mr")))]
-  "TARGET_80387 && (!TARGET_SSE || !TARGET_64BIT || TARGET_MIX_SSE_I387)"
+  "TARGET_80387 && TARGET_64BIT && (!TARGET_SSE || TARGET_MIX_SSE_I387)"
   "@
    fild%z1\\t%1
    #
   "TARGET_80387 || (TARGET_SSE2 && TARGET_64BIT)"
   "")
 
+(define_insn "*floatdidf2_i387_only"
+  [(set (match_operand:DF 0 "register_operand" "=f,?f")
+       (float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r")))]
+  "TARGET_80387 && (!TARGET_SSE2 || !TARGET_64BIT)"
+  "@
+   fild%z1\\t%1
+   #"
+  [(set_attr "type" "fmov,multi")
+   (set_attr "mode" "DF")
+   (set_attr "fp_int_src" "true")])
+
 (define_insn "*floatdidf2_i387"
   [(set (match_operand:DF 0 "register_operand" "=f,?f,Y")
        (float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r,mr")))]
-  "TARGET_80387 && (!TARGET_SSE2 || !TARGET_64BIT || TARGET_MIX_SSE_I387)"
+  "TARGET_80387 && TARGET_64BIT && (!TARGET_SSE2 || TARGET_MIX_SSE_I387)"
   "@
    fild%z1\\t%1
    #
       /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
         Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
       if (GET_CODE (operands[2]) == CONST_INT
+         /* Avoid overflows.  */
+         && ((INTVAL (operands[2]) & ((1 << 31) - 1)))
           && (INTVAL (operands[2]) == 128
              || (INTVAL (operands[2]) < 0
                  && INTVAL (operands[2]) != -128)))
       /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
         Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
       if (GET_CODE (operands[2]) == CONST_INT
+         /* Avoid overflows.  */
+         && ((INTVAL (operands[2]) & ((1 << 31) - 1)))
           && (INTVAL (operands[2]) == 128
              || (INTVAL (operands[2]) < 0
                  && INTVAL (operands[2]) != -128)))
       /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
         Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
       if (GET_CODE (operands[2]) == CONST_INT
+         /* Avoid overflows.  */
+         && ((INTVAL (operands[2]) & ((1 << 31) - 1)))
           && (INTVAL (operands[2]) == 128
              || (INTVAL (operands[2]) < 0
                  && INTVAL (operands[2]) != -128)))
         Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
       if ((INTVAL (operands[2]) == -128
           || (INTVAL (operands[2]) > 0
-              && INTVAL (operands[2]) != 128)))
+              && INTVAL (operands[2]) != 128))
+         /* Avoid overflows.  */
+         && ((INTVAL (operands[2]) & ((1 << 31) - 1))))
        return \"sub{q}\\t{%2, %0|%0, %2}\";
       operands[2] = GEN_INT (-INTVAL (operands[2]));
       return \"add{q}\\t{%2, %0|%0, %2}\";
       /* Make things pretty and `subl $4,%eax' rather than `addl $-4, %eax'.
         Exceptions: -128 encodes smaller than 128, so swap sign and op.  */
       if (GET_CODE (operands[2]) == CONST_INT
+         /* Avoid overflows.  */
+         && ((INTVAL (operands[2]) & ((1 << 31) - 1)))
           && (INTVAL (operands[2]) == 128
              || (INTVAL (operands[2]) < 0
                  && INTVAL (operands[2]) != -128)))
                      (label_ref (match_operand 0 "" ""))
                      (pc)))]
   ""
-  "j%C1\\t%l0"
+  "%+j%C1\\t%l0"
   [(set_attr "type" "ibr")
    (set (attr "prefix_0f")
           (if_then_else (and (ge (minus (match_dup 0) (pc))
                      (pc)
                      (label_ref (match_operand 0 "" ""))))]
   ""
-  "j%c1\\t%l0"
+  "%+j%c1\\t%l0"
   [(set_attr "type" "ibr")
    (set (attr "prefix_0f")
           (if_then_else (and (ge (minus (match_dup 0) (pc))
   if (which_alternative != 0)
     return \"#\";
   if (get_attr_length (insn) == 2)
-    return \"loop\\t%l0\";
+    return \"%+loop\\t%l0\";
   else
-    return \"dec{l}\\t%1\;jne\\t%l0\";
+    return \"dec{l}\\t%1\;%+jne\\t%l0\";
 }"
   [(set_attr "ppro_uops" "many")
    (set (attr "type")
   [(set (match_operand:SF 0 "register_operand" "")
        (if_then_else:SF (lt (match_operand:SF 1 "register_operand" "")
                             (match_operand:SF 2 "nonimmediate_operand" ""))
-                        (match_dup 1)
-                        (match_dup 2)))
+                        (match_operand:DF 3 "register_operand" "")
+                        (match_operand:DF 4 "nonimmediate_operand" "")))
    (clobber (reg:CC 17))]
-  "SSE_REG_P (operands[0]) && reload_completed"
+  "SSE_REG_P (operands[0]) && reload_completed
+   && ((operands_match_p (operands[1], operands[3])
+       && operands_match_p (operands[2], operands[4]))
+       || (operands_match_p (operands[1], operands[4])
+          && operands_match_p (operands[2], operands[3])))"
   [(set (match_dup 0)
        (if_then_else:SF (lt (match_dup 1)
                             (match_dup 2))
                         (match_dup 2)))])
 
 ;; We can't represent the LT test directly.  Do this by swapping the operands.
+
 (define_split
   [(set (match_operand:SF 0 "register_operand" "")
        (if_then_else:SF (lt (match_operand:SF 1 "register_operand" "")
                             (match_operand:SF 2 "register_operand" ""))
-                        (match_dup 1)
-                        (match_dup 2)))
-   (clobber (reg:CC 17))]
-  "FP_REG_P (operands[0]) && reload_completed"
+                        (match_operand:DF 3 "register_operand" "")
+                        (match_operand:DF 4 "register_operand" "")))
+   (clobber (reg:CC 17))]
+  "FP_REG_P (operands[0]) && reload_completed
+   && ((operands_match_p (operands[1], operands[3])
+       && operands_match_p (operands[2], operands[4]))
+       || (operands_match_p (operands[1], operands[4])
+          && operands_match_p (operands[2], operands[3])))"
   [(set (reg:CCFP 17)
        (compare:CCFP (match_dup 2)
                      (match_dup 1)))
   [(set (match_operand:DF 0 "register_operand" "")
        (if_then_else:DF (lt (match_operand:DF 1 "register_operand" "")
                             (match_operand:DF 2 "nonimmediate_operand" ""))
-                        (match_dup 1)
-                        (match_dup 2)))
+                        (match_operand:DF 3 "register_operand" "")
+                        (match_operand:DF 4 "nonimmediate_operand" "")))
    (clobber (reg:CC 17))]
-  "SSE_REG_P (operands[0]) && reload_completed"
+  "SSE_REG_P (operands[0]) && reload_completed
+   && ((operands_match_p (operands[1], operands[3])
+       && operands_match_p (operands[2], operands[4]))
+       || (operands_match_p (operands[1], operands[4])
+          && operands_match_p (operands[2], operands[3])))"
   [(set (match_dup 0)
        (if_then_else:DF (lt (match_dup 1)
                             (match_dup 2))
   [(set (match_operand:DF 0 "register_operand" "")
        (if_then_else:DF (lt (match_operand:DF 1 "register_operand" "")
                             (match_operand:DF 2 "register_operand" ""))
-                        (match_dup 1)
-                        (match_dup 2)))
-   (clobber (reg:CC 17))]
-  "FP_REG_P (operands[0]) && reload_completed"
+                        (match_operand:DF 3 "register_operand" "")
+                        (match_operand:DF 4 "register_operand" "")))
+   (clobber (reg:CC 17))]
+  "FP_REG_P (operands[0]) && reload_completed
+   && ((operands_match_p (operands[1], operands[3])
+       && operands_match_p (operands[2], operands[4]))
+       || (operands_match_p (operands[1], operands[4])
+          && operands_match_p (operands[2], operands[3])))"
   [(set (reg:CCFP 17)
        (compare:CCFP (match_dup 2)
                      (match_dup 2)))
   [(set (match_operand:SF 0 "register_operand" "")
        (if_then_else:SF (gt (match_operand:SF 1 "register_operand" "")
                             (match_operand:SF 2 "nonimmediate_operand" ""))
-                        (match_dup 1)
-                        (match_dup 2)))
+                        (match_operand:SF 3 "register_operand" "")
+                        (match_operand:SF 4 "nonimmediate_operand" "")))
    (clobber (reg:CC 17))]
-  "SSE_REG_P (operands[0]) && reload_completed"
+  "SSE_REG_P (operands[0]) && reload_completed
+   && ((operands_match_p (operands[1], operands[3])
+       && operands_match_p (operands[2], operands[4]))
+       || (operands_match_p (operands[1], operands[4])
+          && operands_match_p (operands[2], operands[3])))"
   [(set (match_dup 0)
        (if_then_else:SF (gt (match_dup 1)
                             (match_dup 2))
   [(set (match_operand:SF 0 "register_operand" "")
        (if_then_else:SF (gt (match_operand:SF 1 "register_operand" "")
                             (match_operand:SF 2 "register_operand" ""))
-                        (match_dup 1)
-                        (match_dup 2)))
-   (clobber (reg:CC 17))]
-  "FP_REG_P (operands[0]) && reload_completed"
+                        (match_operand:SF 3 "register_operand" "")
+                        (match_operand:SF 4 "register_operand" "")))
+   (clobber (reg:CC 17))]
+  "FP_REG_P (operands[0]) && reload_completed
+   && ((operands_match_p (operands[1], operands[3])
+       && operands_match_p (operands[2], operands[4]))
+       || (operands_match_p (operands[1], operands[4])
+          && operands_match_p (operands[2], operands[3])))"
   [(set (reg:CCFP 17)
        (compare:CCFP (match_dup 1)
                      (match_dup 2)))
   [(set (match_operand:DF 0 "register_operand" "")
        (if_then_else:DF (gt (match_operand:DF 1 "register_operand" "")
                             (match_operand:DF 2 "nonimmediate_operand" ""))
-                        (match_dup 1)
-                        (match_dup 2)))
+                        (match_operand:DF 3 "register_operand" "")
+                        (match_operand:DF 4 "nonimmediate_operand" "")))
    (clobber (reg:CC 17))]
-  "SSE_REG_P (operands[0]) && reload_completed"
+  "SSE_REG_P (operands[0]) && reload_completed
+   && ((operands_match_p (operands[1], operands[3])
+       && operands_match_p (operands[2], operands[4]))
+       || (operands_match_p (operands[1], operands[4])
+          && operands_match_p (operands[2], operands[3])))"
   [(set (match_dup 0)
        (if_then_else:DF (gt (match_dup 1)
                             (match_dup 2))
   [(set (match_operand:DF 0 "register_operand" "")
        (if_then_else:DF (gt (match_operand:DF 1 "register_operand" "")
                             (match_operand:DF 2 "register_operand" ""))
-                        (match_dup 1)
-                        (match_dup 2)))
-   (clobber (reg:CC 17))]
-  "FP_REG_P (operands[0]) && reload_completed"
+                        (match_operand:DF 3 "register_operand" "")
+                        (match_operand:DF 4 "register_operand" "")))
+   (clobber (reg:CC 17))]
+  "FP_REG_P (operands[0]) && reload_completed
+   && ((operands_match_p (operands[1], operands[3])
+       && operands_match_p (operands[2], operands[4]))
+       || (operands_match_p (operands[1], operands[4])
+          && operands_match_p (operands[2], operands[3])))"
   [(set (reg:CCFP 17)
        (compare:CCFP (match_dup 1)
                      (match_dup 2)))
index 64a4241b3786915127124b0c13ecf308cd6afddc..7b36b1b41020b44e577f775fca857c60035c1e70 100644 (file)
@@ -4086,6 +4086,25 @@ leaf_function_p ()
   return 1;
 }
 
+/* Return 1 if branch is an forward branch.
+   Uses insn_shuid array, so it works only in the final pass.  May be used by
+   output templates to customary add branch prediction hints.
+ */
+int
+final_forward_branch_p (insn)
+     rtx insn;
+{
+  int insn_id, label_id;
+  if (!uid_shuid)
+    abort ();
+  insn_id = INSN_SHUID (insn);
+  label_id = INSN_SHUID (JUMP_LABEL (insn));
+  /* We've hit some insns that does not have id information available.  */
+  if (!insn_id || !label_id)
+    abort ();
+  return insn_id < label_id;
+}
+
 /* On some machines, a function with no call insns
    can run faster if it doesn't create its own register window.
    When output, the leaf function should use only the "output"