OSDN Git Service

* i386.md (floatdi?f): Avoid usinf of SSE instructions
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 6 Jun 2001 12:57:31 +0000 (12:57 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 6 Jun 2001 12:57:31 +0000 (12:57 +0000)
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.

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

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

index 7b7b76a..e04cd65 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 e352d07..275788e 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 9f47f5c..f1f8bef 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 dcd205b..015bd83 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 64a4241..7b36b1b 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"