i386.c (output_fp_conditional_move): New function to output floating point conditiona...
authorH.J. Lu <hjl@gnu.org>
Fri, 5 Jun 1998 00:13:57 +0000 (00:13 +0000)
committerJeff Law <law@gcc.gnu.org>
Fri, 5 Jun 1998 00:13:57 +0000 (18:13 -0600)
        * i386/i386.c (output_fp_conditional_move): New function
        to output floating point conditional move.
        (output_int_conditional_move): New function to output integer
        conditional move.
        * i386/i386.md (movsicci+5, movhicc+5, movdicc+5): Call
        output_int_conditional_move () to output int conditional move.
        (movsfcc+5, movdfcc+5, movxfcc+5): Call
        output_fp_conditional_move () to output floating point
        conditional move.
        * i386/i386.c (put_condition_code): In INT mode, check
        cc_prev_status.flags & CC_NO_OVERFLOW for GE and LT.

From-SVN: r20233

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

index f5b124103b7b856b79b59ce61623d1e077ea7370..4a9e3a27d147447ff4fe219f339e234d09e5f794 100644 (file)
@@ -1,3 +1,19 @@
+Fri Jun  5 01:12:15 1998  H.J. Lu  (hjl@gnu.org)
+
+       * i386/i386.c (output_fp_conditional_move): New function
+       to output floating point conditional move.
+       (output_int_conditional_move): New function to output integer
+       conditional move.
+
+       * i386/i386.md (movsicci+5, movhicc+5, movdicc+5): Call
+       output_int_conditional_move () to output int conditional move.
+       (movsfcc+5, movdfcc+5, movxfcc+5): Call
+       output_fp_conditional_move () to output floating point
+       conditional move.
+
+       * i386/i386.c (put_condition_code): In INT mode, check
+       cc_prev_status.flags & CC_NO_OVERFLOW for GE and LT.
+
 Thu Jun  4 16:09:51 1998  Dave Brolley  <brolley@cygnus.com>
 
        * dbxout.c (dbxout_type): Output arrays of bits as if
index da08da1ff8af765e03370c98602fd91e1e29f6ef..73d89dc8cddae03e77394df866228e973c88a87b 100644 (file)
@@ -3097,7 +3097,10 @@ put_condition_code (code, reverse_cc, mode, file)
        return;
 
       case GE:
-       fputs ("ge", file);
+       if (cc_prev_status.flags & CC_NO_OVERFLOW)
+         fputs ("ns", file);
+       else
+         fputs ("ge", file);
        return;
 
       case GT:
@@ -3109,7 +3112,10 @@ put_condition_code (code, reverse_cc, mode, file)
        return;
 
       case LT:
-       fputs ("l", file);
+       if (cc_prev_status.flags & CC_NO_OVERFLOW)
+         fputs ("s", file);
+       else
+         fputs ("l", file);
        return;
 
       case GEU:
@@ -5132,3 +5138,124 @@ output_strlen_unroll (operands)
 
   return "";
 }
+
+char *
+output_fp_conditional_move (which_alternative, operands)
+     int which_alternative;
+     rtx operands[];
+{
+  int code = GET_CODE (operands[1]);
+
+  /* This is very tricky. We have to do it right. For a code segement
+     like:
+
+       int foo;
+       double bar;
+       ....
+       foo = foo - x;
+       if (foo >= 0)
+         bar = y;
+
+     final_scan_insn () may delete the insn which sets CC. We have to
+     tell final_scan_insn () if it should be reinserted. When CODE is
+     GT or LE, we have to check the CC_NO_OVERFLOW bit and return
+     NULL_PTR to tell final to reinsert the test insn because the
+     conditional move cannot be handled properly without it. */
+  if ((code == GT || code == LE)
+      && (cc_prev_status.flags & CC_NO_OVERFLOW))
+    return NULL_PTR;
+
+  switch (which_alternative)
+    {
+    case 0:
+      /* r <- cond ? arg : r */
+      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
+      break;
+  
+    case 1:
+      /* r <- cond ? r : arg */
+      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
+      break;
+
+    case 2:
+      /* r <- cond ? r : arg */
+      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
+      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
+      break;
+
+    default:
+      abort ();
+    }
+
+  return "";
+}
+
+char *
+output_int_conditional_move (which_alternative, operands)
+     int which_alternative;
+     rtx operands[];
+{
+  int code = GET_CODE (operands[1]);
+  enum machine_mode mode;
+  rtx xops[4];
+
+  /* This is very tricky. We have to do it right. For a code segement
+     like:
+
+       int foo, bar;
+       ....
+       foo = foo - x;
+       if (foo >= 0)
+         bar = y;
+
+     final_scan_insn () may delete the insn which sets CC. We have to
+     tell final_scan_insn () if it should be reinserted. When CODE is
+     GT or LE, we have to check the CC_NO_OVERFLOW bit and return
+     NULL_PTR to tell final to reinsert the test insn because the
+     conditional move cannot be handled properly without it. */
+  if ((code == GT || code == LE)
+      && (cc_prev_status.flags & CC_NO_OVERFLOW))
+    return NULL_PTR;
+
+  mode = GET_MODE (operands [0]);
+  if (mode == DImode)
+    {
+      xops [0] = gen_rtx_SUBREG (SImode, operands [0], 1);
+      xops [1] = operands [1];
+      xops [2] = gen_rtx_SUBREG (SImode, operands [2], 1);
+      xops [3] = gen_rtx_SUBREG (SImode, operands [3], 1);
+    }
+
+  switch (which_alternative)
+    {
+    case 0:
+      /* r <- cond ? arg : r */
+      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
+      if (mode == DImode)
+       output_asm_insn (AS2 (cmov%C1,%2,%0), xops);
+      break;
+
+    case 1:
+      /* r <- cond ? r : arg */
+      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
+      if (mode == DImode)
+       output_asm_insn (AS2 (cmov%c1,%3,%0), xops);
+      break;
+
+    case 2:
+      /* rm <- cond ? arg1 : arg2 */
+      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
+      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
+      if (mode == DImode)
+       {
+         output_asm_insn (AS2 (cmov%C1,%2,%0), xops);
+         output_asm_insn (AS2 (cmov%c1,%3,%0), xops);
+       }
+      break;
+
+    default:
+      abort ();
+    }
+
+  return "";
+}
index f060c05aee143f9ac905b12906212708d0761a2e..b2ee298ca19256ddabc8eb6cc844c434ad90f8fe 100644 (file)
@@ -7307,35 +7307,7 @@ byte_xor_operation:
                      (match_operand:SI 2 "nonimmediate_operand" "rm,0,rm")
                      (match_operand:SI 3 "nonimmediate_operand" "0,rm,rm")))]
   "TARGET_CMOVE && reload_completed"
-  "*
-{
-
-  switch (which_alternative)
-    {
-    case 0:
-      /* r <- cond ? arg : r */
-      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
-      break;
-
-    case 1:
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
-      break;
-
-    case 2:
-      /* r <- cond ? arg1 : arg2 */
-      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
-      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
-      break;
-
-    default:
-      abort();
-    /* NOTREACHED */
-      break;
-    }
-
-  RET;
-}")
+  "* return output_int_conditional_move (which_alternative, operands);")
 
 (define_expand "movhicc"
   [(set (match_operand:HI 0 "register_operand" "")
@@ -7410,35 +7382,7 @@ byte_xor_operation:
                      (match_operand:HI 2 "nonimmediate_operand" "rm,0,rm")
                      (match_operand:HI 3 "nonimmediate_operand" "0,rm,rm")))]
   "TARGET_CMOVE && reload_completed"
-  "*
-{
-
-  switch (which_alternative)
-    {
-    case 0:
-      /* r <- cond ? arg : r */
-      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
-      break;
-
-    case 1:
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
-      break;
-
-    case 2:
-      /* r <- cond ? arg1 : arg2 */
-      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
-      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
-      break;
-
-    default:
-      abort();
-    /* NOTREACHED */
-      break;
-    }
-
-  RET;
-}")
+  "* return output_int_conditional_move (which_alternative, operands);")
 
 (define_expand "movsfcc"
   [(set (match_operand:SF 0 "register_operand" "")
@@ -7512,35 +7456,7 @@ byte_xor_operation:
                      (match_operand:SF 2 "register_operand" "f,0,f")
                      (match_operand:SF 3 "register_operand" "0,f,f")))]
   "TARGET_CMOVE && reload_completed"
-  "*
-{
-
-  switch (which_alternative)
-    {
-    case 0:
-      /* r <- cond ? arg : r */
-      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
-      break;
-
-    case 1:
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
-      break;
-
-    case 2:
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
-      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
-      break;
-
-    default:
-      abort();
-    /* NOTREACHED */
-      break;
-    }
-
-  RET;
-}")
+  "* return output_fp_conditional_move (which_alternative, operands);")
 
 (define_expand "movdfcc"
   [(set (match_operand:DF 0 "register_operand" "")
@@ -7614,35 +7530,7 @@ byte_xor_operation:
                      (match_operand:DF 2 "register_operand" "f,0,f")
                      (match_operand:DF 3 "register_operand" "0,f,f")))]
   "TARGET_CMOVE && reload_completed"
-  "*
-{
-
-  switch (which_alternative)
-    {
-    case 0:
-      /* r <- cond ? arg : r */
-      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
-      break;
-
-    case 1:
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
-      break;
-
-    case 2:
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
-      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
-      break;
-
-    default:
-      abort();
-    /* NOTREACHED */
-      break;
-    }
-
-  RET;
-}")
+  "* return output_fp_conditional_move (which_alternative, operands);")
 
 (define_expand "movxfcc"
   [(set (match_operand:XF 0 "register_operand" "")
@@ -7716,35 +7604,7 @@ byte_xor_operation:
                      (match_operand:XF 2 "register_operand" "f,0,f")
                      (match_operand:XF 3 "register_operand" "0,f,f")))]
   "TARGET_CMOVE && reload_completed"
-  "*
-{
-
-  switch (which_alternative)
-    {
-    case 0:
-      /* r <- cond ? arg : r */
-      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
-      break;
-
-    case 1:
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
-      break;
-
-    case 2:
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
-      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
-      break;
-
-    default:
-      abort();
-    /* NOTREACHED */
-      break;
-    }
-
-  RET;
-}")
+  "* return output_fp_conditional_move (which_alternative, operands);")
 
 (define_expand "movdicc"
   [(set (match_operand:DI 0 "register_operand" "")
@@ -7818,49 +7678,7 @@ byte_xor_operation:
                      (match_operand:DI 2 "nonimmediate_operand" "ro,0,ro")
                      (match_operand:DI 3 "nonimmediate_operand" "0,ro,ro")))]
   "TARGET_CMOVE && reload_completed"
-  "*
-{
-  rtx xops[4];
-
-  xops[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
-  xops[1] = operands[1];
-  xops[2] = REG_P (operands[2])
-               ? gen_rtx_REG (SImode, REGNO (operands[2]) + 1)
-               : adj_offsettable_operand (operands[2], 4);
-  xops[3] = REG_P (operands[3])
-               ? gen_rtx_REG (SImode, REGNO (operands[3]) + 1)
-               : adj_offsettable_operand (operands[3], 4);
-
-  switch (which_alternative)
-    {
-    case 0:
-      /* r <- cond ? arg : r */
-      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
-      output_asm_insn (AS2 (cmov%C1,%2,%0), xops);
-      break;
-
-    case 1:
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
-      output_asm_insn (AS2 (cmov%c1,%3,%0), xops);
-      break;
-
-    case 2:
-      /* r <- cond ? arg1 : arg2 */
-      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
-      output_asm_insn (AS2 (cmov%C1,%2,%0), xops);
-      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
-      output_asm_insn (AS2 (cmov%c1,%3,%0), xops);
-      break;
-
-    default:
-      abort();
-    /* NOTREACHED */
-      break;
-    }
-
-  RET;
-}")
+  "* return output_int_conditional_move (which_alternative, operands);")
 
 (define_insn "strlensi_unroll"
   [(set (match_operand:SI 0 "register_operand" "=&r,&r")