OSDN Git Service

Support procedures for testing profile-directed optimizations.
[pf3gnuchains/gcc-fork.git] / gcc / reg-stack.c
index 558735f..a72f622 100644 (file)
@@ -1775,6 +1775,12 @@ subst_stack_regs_pat (insn, regstack, pat)
          case IF_THEN_ELSE:
            /* This insn requires the top of stack to be the destination.  */
 
+           src1 = get_true_reg (&XEXP (pat_src, 1));
+           src2 = get_true_reg (&XEXP (pat_src, 2));
+
+           src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
+           src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));
+
            /* If the comparison operator is an FP comparison operator,
               it is handled correctly by compare_for_stack_reg () who
               will move the destination to the top of stack. But if the
@@ -1782,13 +1788,33 @@ subst_stack_regs_pat (insn, regstack, pat)
               have to handle it here.  */
            if (get_hard_regnum (regstack, *dest) >= FIRST_STACK_REG
                && REGNO (*dest) != regstack->reg[regstack->top])
-             emit_swap_insn (insn, regstack, *dest);   
-
-           src1 = get_true_reg (&XEXP (pat_src, 1));
-           src2 = get_true_reg (&XEXP (pat_src, 2));
-
-           src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
-           src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));
+             {
+               /* In case one of operands is the top of stack and the operands
+                  dies, it is safe to make it the destination operand by reversing
+                  the direction of cmove and avoid fxch.  */
+               if ((REGNO (*src1) == regstack->reg[regstack->top]
+                    && src1_note)
+                   || (REGNO (*src2) == regstack->reg[regstack->top]
+                       && src2_note))
+                 {
+                   int idx1 = (get_hard_regnum (regstack, *src1)
+                               - FIRST_STACK_REG);
+                   int idx2 = (get_hard_regnum (regstack, *src2)
+                               - FIRST_STACK_REG);
+
+                   /* Make reg-stack believe that the operands are already
+                      swapped on the stack */
+                   regstack->reg[regstack->top - idx1] = REGNO (*src2);
+                   regstack->reg[regstack->top - idx2] = REGNO (*src1);
+
+                   /* Reverse condition to compensate the operand swap.
+                      i386 do have comparison always reversible.  */
+                   PUT_CODE (XEXP (pat_src, 0),
+                             reversed_comparison_code (XEXP (pat_src, 0), insn));
+                 }
+               else
+                 emit_swap_insn (insn, regstack, *dest);       
+             }
 
            {
              rtx src_note [3];
@@ -1817,11 +1843,9 @@ subst_stack_regs_pat (insn, regstack, pat)
                                       EMIT_AFTER);
                      }
                    else
-                     {
-                       CLEAR_HARD_REG_BIT (regstack->reg_set, regno);
-                       replace_reg (&XEXP (src_note[i], 0), FIRST_STACK_REG);
-                       regstack->top--;
-                     }
+                     /* Top of stack never dies, as it is the
+                        destination.  */
+                     abort ();
                  }
            }