]> gcc.gnu.org Git - gcc.git/commitdiff
i386.c (ix86_carry_flag_operator): New predicate.
authorJan Hubicka <jh@suse.cz>
Tue, 28 Jan 2003 11:16:32 +0000 (12:16 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Tue, 28 Jan 2003 11:16:32 +0000 (11:16 +0000)
  * i386.c (ix86_carry_flag_operator):  New predicate.
  (fcmov_operator): Fix whitespace.
  (ix86_expand_carry_flag_compare):  Deal with floating point.
  (ix86_expand_int_movcc): Deal with fp; update insn expansion
  (ix86_expand_int_addcc): Likewise.
  (ix86_expand_strlensi_unroll_1): likewsie.
  * i386.h (PREDICATE_CODES): Add ix86_carry_flag_operator.
  * i386.md (add?i_carry_rex64): Use new predicate.
  (sub?i3_carry_rex64): Likewise.
  (x86_mov?icc_0_m1*): Likewise.

From-SVN: r61963

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

index b79a48622247e3c53b4b9e5682ec803c7f2d7ca4..24d5cd1bfffbe35d20507ce9cd6af97ccf036c36 100644 (file)
@@ -1,3 +1,16 @@
+Tue Jan 28 12:15:13 CET 2003  Jan Hubicka  <jh@suse.cz>
+
+       * i386.c (ix86_carry_flag_operator):  New predicate.
+       (fcmov_operator): Fix whitespace.
+       (ix86_expand_carry_flag_compare):  Deal with floating point.
+       (ix86_expand_int_movcc): Deal with fp; update insn expansion
+       (ix86_expand_int_addcc): Likewise.
+       (ix86_expand_strlensi_unroll_1): likewsie.
+       * i386.h (PREDICATE_CODES): Add ix86_carry_flag_operator.
+       * i386.md (add?i_carry_rex64): Use new predicate.
+       (sub?i3_carry_rex64): Likewise.
+       (x86_mov?icc_0_m1*): Likewise.
+
 2003-01-28  Andreas Schwab  <schwab@suse.de>
 
        * cfgloopmanip.c (create_preheader): Initialize src to avoid
index 0f0a3a76282de7824eef830027dbfbf35216cab0..bb8091dfcb4b2ddeaa3bfb196491ba0c8ad3b01c 100644 (file)
@@ -3797,6 +3797,40 @@ ix86_comparison_operator (op, mode)
     }
 }
 
+/* Return 1 if OP is a valid comparison operator testing carry flag
+   to be set.  */
+int
+ix86_carry_flag_operator (op, mode)
+     register rtx op;
+     enum machine_mode mode;
+{
+  enum machine_mode inmode;
+  enum rtx_code code = GET_CODE (op);
+
+  if (mode != VOIDmode && GET_MODE (op) != mode)
+    return 0;
+  if (GET_RTX_CLASS (code) != '<')
+    return 0;
+  inmode = GET_MODE (XEXP (op, 0));
+  if (GET_CODE (XEXP (op, 0)) != REG
+      || REGNO (XEXP (op, 0)) != 17
+      || XEXP (op, 1) != const0_rtx)
+    return 0;
+
+  if (inmode == CCFPmode || inmode == CCFPUmode)
+    {
+      enum rtx_code second_code, bypass_code;
+
+      ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
+      if (bypass_code != NIL || second_code != NIL)
+       return 0;
+      code = ix86_fp_compare_code_to_integer (code);
+    }
+  else if (inmode != CCmode)
+    return 0;
+  return code == LTU;
+}
+
 /* Return 1 if OP is a comparison operator that can be issued by fcmov.  */
 
 int
@@ -3806,6 +3840,7 @@ fcmov_comparison_operator (op, mode)
 {
   enum machine_mode inmode;
   enum rtx_code code = GET_CODE (op);
+
   if (mode != VOIDmode && GET_MODE (op) != mode)
     return 0;
   if (GET_RTX_CLASS (code) != '<')
@@ -3814,6 +3849,7 @@ fcmov_comparison_operator (op, mode)
   if (inmode == CCFPmode || inmode == CCFPUmode)
     {
       enum rtx_code second_code, bypass_code;
+
       ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
       if (bypass_code != NIL || second_code != NIL)
        return 0;
@@ -9316,7 +9352,51 @@ ix86_expand_carry_flag_compare (code, op0, op1, pop)
 
   /* Do not handle DImode compares that go trought special path.  Also we can't
      deal with FP compares yet.  This is possible to add.   */
-  if ((mode == DImode && !TARGET_64BIT) || !INTEGRAL_MODE_P (mode))
+  if ((mode == DImode && !TARGET_64BIT))
+    return false;
+  if (FLOAT_MODE_P (mode))
+    {
+      rtx second_test = NULL, bypass_test = NULL;
+      rtx compare_op, compare_seq;
+
+      /* Shortcut:  following common codes never translate into carry flag compares.  */
+      if (code == EQ || code == NE || code == UNEQ || code == LTGT
+         || code == ORDERED || code == UNORDERED)
+       return false;
+
+      /* These comparisons require zero flag; swap operands so they won't.  */
+      if ((code == GT || code == UNLE || code == LE || code == UNGT)
+         && !TARGET_IEEE_FP)
+       {
+         rtx tmp = op0;
+         op0 = op1;
+         op1 = tmp;
+         code = swap_condition (code);
+       }
+
+      /* Try to expand the comparsion and verify that we end up with carry flag
+        based comparsion.  This is fails to be true only when we decide to expand
+        comparsion using arithmetic that is not too common scenario.  */
+      start_sequence ();
+      compare_op = ix86_expand_fp_compare (code, op0, op1, NULL_RTX,
+                                          &second_test, &bypass_test);
+      compare_seq = get_insns ();
+      end_sequence ();
+
+      if (second_test || bypass_test)
+       return false;
+      if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode
+         || GET_MODE (XEXP (compare_op, 0)) == CCFPUmode)
+        code = ix86_fp_compare_code_to_integer (GET_CODE (compare_op));
+      else
+       code = GET_CODE (compare_op);
+      if (code != LTU && code != GEU)
+       return false;
+      emit_insn (compare_seq);
+      *pop = compare_op;
+      return true;
+    }
+  if (!INTEGRAL_MODE_P (mode))
     return false;
   switch (code)
     {
@@ -9428,8 +9508,17 @@ ix86_expand_int_movcc (operands)
 
           if (!sign_bit_compare_p)
            {
+             bool fpcmp = false;
+
              compare_code = GET_CODE (compare_op);
 
+             if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode
+                 || GET_MODE (XEXP (compare_op, 0)) == CCFPUmode)
+               {
+                 fpcmp = true;
+                 compare_code = ix86_fp_compare_code_to_integer (compare_code);
+               }
+
              /* To simplify rest of code, restrict to the GEU case.  */
              if (compare_code == LTU)
                {
@@ -9439,6 +9528,15 @@ ix86_expand_int_movcc (operands)
                  compare_code = reverse_condition (compare_code);
                  code = reverse_condition (code);
                }
+             else
+               {
+                 if (fpcmp)
+                   PUT_CODE (compare_op,
+                             reverse_condition_maybe_unordered
+                               (GET_CODE (compare_op)));
+                 else
+                   PUT_CODE (compare_op, reverse_condition (GET_CODE (compare_op)));
+               }
              diff = ct - cf;
 
              if (reg_overlap_mentioned_p (out, ix86_compare_op0)
@@ -9446,9 +9544,9 @@ ix86_expand_int_movcc (operands)
                tmp = gen_reg_rtx (mode);
 
              if (mode == DImode)
-               emit_insn (gen_x86_movdicc_0_m1_rex64 (tmp));
+               emit_insn (gen_x86_movdicc_0_m1_rex64 (tmp, compare_op));
              else
-               emit_insn (gen_x86_movsicc_0_m1 (gen_lowpart (SImode, tmp)));
+               emit_insn (gen_x86_movsicc_0_m1 (gen_lowpart (SImode, tmp), compare_op));
            }
          else
            {
@@ -10051,6 +10149,9 @@ ix86_expand_int_addcc (operands)
   enum rtx_code code = GET_CODE (operands[1]);
   rtx compare_op;
   rtx val = const0_rtx;
+  bool fpcmp = false;
+  rtx pat, clob;
+  enum machine_mode mode = GET_MODE (operands[0]);
 
   if (operands[3] != const1_rtx
       && operands[3] != constm1_rtx)
@@ -10058,23 +10159,43 @@ ix86_expand_int_addcc (operands)
   if (!ix86_expand_carry_flag_compare (code, ix86_compare_op0,
                                       ix86_compare_op1, &compare_op))
      return 0;
-  if (GET_CODE (compare_op) != LTU)
-    val = constm1_rtx;
-  if ((GET_CODE (compare_op) == LTU) == (operands[3] == constm1_rtx))
+  code = GET_CODE (compare_op);
+
+  if (GET_MODE (XEXP (compare_op, 0)) == CCFPmode
+      || GET_MODE (XEXP (compare_op, 0)) == CCFPUmode)
+    {
+      fpcmp = true;
+      code = ix86_fp_compare_code_to_integer (code);
+    }
+
+  if (code != LTU)
+    {
+      val = constm1_rtx;
+      if (fpcmp)
+       PUT_CODE (compare_op,
+                 reverse_condition_maybe_unordered
+                   (GET_CODE (compare_op)));
+      else
+       PUT_CODE (compare_op, reverse_condition (GET_CODE (compare_op)));
+    }
+  PUT_MODE (compare_op, mode);
+
+  /* Construct either adc or sbb insn.  */
+  if ((code == LTU) == (operands[3] == constm1_rtx))
     {
       switch (GET_MODE (operands[0]))
        {
          case QImode:
-            emit_insn (gen_subqi3_carry (operands[0], operands[2], val));
+            emit_insn (gen_subqi3_carry (operands[0], operands[2], val, compare_op));
            break;
          case HImode:
-            emit_insn (gen_subhi3_carry (operands[0], operands[2], val));
+            emit_insn (gen_subhi3_carry (operands[0], operands[2], val, compare_op));
            break;
          case SImode:
-            emit_insn (gen_subsi3_carry (operands[0], operands[2], val));
+            emit_insn (gen_subsi3_carry (operands[0], operands[2], val, compare_op));
            break;
          case DImode:
-            emit_insn (gen_subdi3_carry_rex64 (operands[0], operands[2], val));
+            emit_insn (gen_subdi3_carry_rex64 (operands[0], operands[2], val, compare_op));
            break;
          default:
            abort ();
@@ -10085,16 +10206,16 @@ ix86_expand_int_addcc (operands)
       switch (GET_MODE (operands[0]))
        {
          case QImode:
-            emit_insn (gen_addqi3_carry (operands[0], operands[2], val));
+            emit_insn (gen_addqi3_carry (operands[0], operands[2], val, compare_op));
            break;
          case HImode:
-            emit_insn (gen_addhi3_carry (operands[0], operands[2], val));
+            emit_insn (gen_addhi3_carry (operands[0], operands[2], val, compare_op));
            break;
          case SImode:
-            emit_insn (gen_addsi3_carry (operands[0], operands[2], val));
+            emit_insn (gen_addsi3_carry (operands[0], operands[2], val, compare_op));
            break;
          case DImode:
-            emit_insn (gen_adddi3_carry_rex64 (operands[0], operands[2], val));
+            emit_insn (gen_adddi3_carry_rex64 (operands[0], operands[2], val, compare_op));
            break;
          default:
            abort ();
@@ -11181,6 +11302,7 @@ ix86_expand_strlensi_unroll_1 (out, align_rtx)
   rtx mem;
   rtx tmpreg = gen_reg_rtx (SImode);
   rtx scratch = gen_reg_rtx (SImode);
+  rtx cmp;
 
   align = 0;
   if (GET_CODE (align_rtx) == CONST_INT)
@@ -11339,10 +11461,11 @@ ix86_expand_strlensi_unroll_1 (out, align_rtx)
   /* Avoid branch in fixing the byte.  */
   tmpreg = gen_lowpart (QImode, tmpreg);
   emit_insn (gen_addqi3_cc (tmpreg, tmpreg, tmpreg));
+  cmp = gen_rtx_LTU (Pmode, gen_rtx_REG (CCmode, 17), const0_rtx);
   if (TARGET_64BIT)
-    emit_insn (gen_subdi3_carry_rex64 (out, out, GEN_INT (3)));
+    emit_insn (gen_subdi3_carry_rex64 (out, out, GEN_INT (3), cmp));
   else
-    emit_insn (gen_subsi3_carry (out, out, GEN_INT (3)));
+    emit_insn (gen_subsi3_carry (out, out, GEN_INT (3), cmp));
 
   emit_label (end_0_label);
 }
index 32eb8ad6f6fcec27604293c4af0b1d7a0cb8b1da..6543ab018a49e76a880b922603739b42984e673b 100644 (file)
@@ -3048,6 +3048,8 @@ do {                                              \
   {"ix86_comparison_operator", {EQ, NE, LE, LT, GE, GT, LEU, LTU, GEU, \
                               GTU, UNORDERED, ORDERED, UNLE, UNLT,     \
                               UNGE, UNGT, LTGT, UNEQ }},               \
+  {"ix86_carry_flag_operator", {LTU, LT, UNLT, GT, UNGT, LE, UNLE,     \
+                                GE, UNGE, LTGT, UNEQ}},                \
   {"cmp_fp_expander_operand", {CONST_DOUBLE, SUBREG, REG, MEM}},       \
   {"ext_register_operand", {SUBREG, REG}},                             \
   {"binary_fp_operator", {PLUS, MINUS, MULT, DIV}},                    \
index b17579fbf8a9e9080e5897eb8b54395d8df95904..e58f3e07d342b037af5d6085c75e63902a85d093 100644 (file)
 
 (define_insn "adddi3_carry_rex64"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
-         (plus:DI (plus:DI (ltu:DI (reg:CC 17) (const_int 0))
+         (plus:DI (plus:DI (match_operand:DI 3 "ix86_carry_flag_operator" "")
                            (match_operand:DI 1 "nonimmediate_operand" "%0,0"))
                   (match_operand:DI 2 "x86_64_general_operand" "re,rm")))
    (clobber (reg:CC 17))]
 
 (define_insn "addqi3_carry"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=rm,r")
-         (plus:QI (plus:QI (ltu:QI (reg:CC 17) (const_int 0))
+         (plus:QI (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "")
                            (match_operand:QI 1 "nonimmediate_operand" "%0,0"))
                   (match_operand:QI 2 "general_operand" "ri,rm")))
    (clobber (reg:CC 17))]
 
 (define_insn "addhi3_carry"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
-         (plus:HI (plus:HI (ltu:HI (reg:CC 17) (const_int 0))
+         (plus:HI (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "")
                            (match_operand:HI 1 "nonimmediate_operand" "%0,0"))
                   (match_operand:HI 2 "general_operand" "ri,rm")))
    (clobber (reg:CC 17))]
 
 (define_insn "addsi3_carry"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
-         (plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
+         (plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
                            (match_operand:SI 1 "nonimmediate_operand" "%0,0"))
                   (match_operand:SI 2 "general_operand" "ri,rm")))
    (clobber (reg:CC 17))]
 (define_insn "*addsi3_carry_zext"
   [(set (match_operand:DI 0 "register_operand" "=r")
          (zero_extend:DI 
-           (plus:SI (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
+           (plus:SI (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
                              (match_operand:SI 1 "nonimmediate_operand" "%0"))
                     (match_operand:SI 2 "general_operand" "rim"))))
    (clobber (reg:CC 17))]
 (define_insn "subdi3_carry_rex64"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=rm,r")
          (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
-           (plus:DI (ltu:DI (reg:CC 17) (const_int 0))
+           (plus:DI (match_operand:SI 3 "ix86_carry_flag_operator" "")
               (match_operand:DI 2 "x86_64_general_operand" "re,rm"))))
    (clobber (reg:CC 17))]
   "TARGET_64BIT && ix86_binary_operator_ok (MINUS, DImode, operands)"
 (define_insn "subqi3_carry"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=rm,r")
          (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
-           (plus:QI (ltu:QI (reg:CC 17) (const_int 0))
+           (plus:QI (match_operand:QI 3 "ix86_carry_flag_operator" "")
               (match_operand:QI 2 "general_operand" "ri,rm"))))
    (clobber (reg:CC 17))]
   "ix86_binary_operator_ok (MINUS, QImode, operands)"
 (define_insn "subhi3_carry"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
          (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
-           (plus:HI (ltu:HI (reg:CC 17) (const_int 0))
+           (plus:HI (match_operand:HI 3 "ix86_carry_flag_operator" "")
               (match_operand:HI 2 "general_operand" "ri,rm"))))
    (clobber (reg:CC 17))]
   "ix86_binary_operator_ok (MINUS, HImode, operands)"
 (define_insn "subsi3_carry"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
          (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
-           (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
+           (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
               (match_operand:SI 2 "general_operand" "ri,rm"))))
    (clobber (reg:CC 17))]
   "ix86_binary_operator_ok (MINUS, SImode, operands)"
   [(set (match_operand:DI 0 "register_operand" "=rm,r")
          (zero_extend:DI
            (minus:SI (match_operand:SI 1 "register_operand" "0,0")
-             (plus:SI (ltu:SI (reg:CC 17) (const_int 0))
+             (plus:SI (match_operand:SI 3 "ix86_carry_flag_operator" "")
                 (match_operand:SI 2 "general_operand" "ri,rm")))))
    (clobber (reg:CC 17))]
   "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)"
 
 (define_insn "x86_movdicc_0_m1_rex64"
   [(set (match_operand:DI 0 "register_operand" "=r")
-       (if_then_else:DI (ltu (reg:CC 17) (const_int 0))
+       (if_then_else:DI (match_operand 1 "ix86_carry_flag_operator" "")
          (const_int -1)
          (const_int 0)))
    (clobber (reg:CC 17))]
    (set_attr "mode" "DI")
    (set_attr "length_immediate" "0")])
 
-(define_insn "*movdicc_c_rex64"
+(define_insn "movdicc_c_rex64"
   [(set (match_operand:DI 0 "register_operand" "=r,r")
        (if_then_else:DI (match_operator 1 "ix86_comparison_operator" 
                                [(reg 17) (const_int 0)])
 
 (define_insn "x86_movsicc_0_m1"
   [(set (match_operand:SI 0 "register_operand" "=r")
-       (if_then_else:SI (ltu (reg:CC 17) (const_int 0))
+       (if_then_else:SI (match_operand 1 "ix86_carry_flag_operator" "")
          (const_int -1)
          (const_int 0)))
    (clobber (reg:CC 17))]
This page took 0.111544 seconds and 5 git commands to generate.