OSDN Git Service

* i386.c (ix86_expand_compare): Add bypass_test and second_test
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 14 Jan 2001 09:14:03 +0000 (09:14 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 14 Jan 2001 09:14:03 +0000 (09:14 +0000)
parameters.
(ix86_expand_branch): Update.
(ix86_expand_setcc): Update to handle multiple test conditions.
(expand_int_movcc): Likewise.
(expand_fp_movcc): Likewise.
* i386-protos.h (ix86_expand_compare): New.
* i386.md (andqi_?_slp, orqi_?_slp): New.
(conditional trap expander): Update call to ix86_expand_compare.

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

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

index a07f54b..7d82db9 100644 (file)
@@ -1,3 +1,15 @@
+Sun Jan 14 10:09:48 MET 2001  Jan hubicka  <jh@suse.cz>
+
+       * i386.c (ix86_expand_compare): Add bypass_test and second_test
+       parameters.
+       (ix86_expand_branch): Update.
+       (ix86_expand_setcc): Update to handle multiple test conditions.
+       (expand_int_movcc): Likewise.
+       (expand_fp_movcc): Likewise.
+       * i386-protos.h (ix86_expand_compare): New.
+       * i386.md (andqi_?_slp, orqi_?_slp): New.
+       (conditional trap expander): Update call to ix86_expand_compare.
+
 2001-01-14  Richard Henderson  <rth@redhat.com>
 
        * config/vax/vax.md: Use nonimmediate_operand instead of
index 3bf2ea8..cd44c4b 100644 (file)
@@ -101,7 +101,7 @@ extern void ix86_expand_unary_operator PARAMS ((enum rtx_code, enum machine_mode
 extern int ix86_unary_operator_ok PARAMS ((enum rtx_code, enum machine_mode,
                                         rtx[]));
 extern int ix86_match_ccmode PARAMS ((rtx, enum machine_mode));
-extern rtx ix86_expand_compare PARAMS ((enum rtx_code));
+extern rtx ix86_expand_compare PARAMS ((enum rtx_code, rtx *, rtx *));
 extern int ix86_use_fcomi_compare PARAMS ((enum rtx_code));
 extern void ix86_expand_branch PARAMS ((enum rtx_code, rtx));
 extern int ix86_expand_setcc PARAMS ((enum rtx_code, rtx));
index eb8a852..6508478 100644 (file)
@@ -5161,16 +5161,22 @@ ix86_expand_fp_compare (code, op0, op1, scratch, second_test, bypass_test)
 }
 
 rtx
-ix86_expand_compare (code)
+ix86_expand_compare (code, second_test, bypass_test)
      enum rtx_code code;
+     rtx *second_test, *bypass_test;
 {
   rtx op0, op1, ret;
   op0 = ix86_compare_op0;
   op1 = ix86_compare_op1;
 
+  if (second_test)
+    *second_test = NULL_RTX;
+  if (bypass_test)
+    *bypass_test = NULL_RTX;
+
   if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_FLOAT)
     ret = ix86_expand_fp_compare (code, op0, op1, gen_reg_rtx (HImode),
-                                 NULL, NULL);
+                                 second_test, bypass_test);
   else
     ret = ix86_expand_int_compare (code, op0, op1);
 
@@ -5189,7 +5195,7 @@ ix86_expand_branch (code, label)
     case QImode:
     case HImode:
     case SImode:
-      tmp = ix86_expand_compare (code);
+      tmp = ix86_expand_compare (code, NULL, NULL);
       tmp = gen_rtx_IF_THEN_ELSE (VOIDmode, tmp,
                                  gen_rtx_LABEL_REF (VOIDmode, label),
                                  pc_rtx);
@@ -5404,7 +5410,8 @@ ix86_expand_setcc (code, dest)
      enum rtx_code code;
      rtx dest;
 {
-  rtx ret, tmp;
+  rtx ret, tmp, tmpreg;
+  rtx second_test, bypass_test;
   int type;
 
   if (GET_MODE (ix86_compare_op0) == DImode)
@@ -5430,13 +5437,15 @@ ix86_expand_setcc (code, dest)
   if (type == 0)
     emit_move_insn (dest, const0_rtx);
 
-  ret = ix86_expand_compare (code);
+  ret = ix86_expand_compare (code, &second_test, &bypass_test);
   PUT_MODE (ret, QImode);
 
   tmp = dest;
+  tmpreg = dest;
   if (type == 0)
     {
       tmp = gen_lowpart (QImode, dest);
+      tmpreg = tmp;
       tmp = gen_rtx_STRICT_LOW_PART (VOIDmode, tmp);
     }
   else if (type == 1)
@@ -5445,9 +5454,31 @@ ix86_expand_setcc (code, dest)
        tmp = gen_reg_rtx (QImode);
       else
         tmp = gen_lowpart (QImode, dest);
+      tmpreg = tmp;
     }
 
   emit_insn (gen_rtx_SET (VOIDmode, tmp, ret));
+  if (bypass_test || second_test)
+    {
+      rtx test = second_test;
+      int bypass = 0;
+      rtx tmp2 = gen_reg_rtx (QImode);
+      if (bypass_test)
+       {
+         if (second_test)
+           abort();
+         test = bypass_test;
+         bypass = 1;
+         PUT_CODE (test, reverse_condition_maybe_unordered (GET_CODE (test)));
+       }
+      PUT_MODE (test, QImode);
+      emit_insn (gen_rtx_SET (VOIDmode, tmp2, test));
+
+      if (bypass)
+       emit_insn (gen_andqi3 (tmp, tmpreg, tmp2));
+      else
+       emit_insn (gen_iorqi3 (tmp, tmpreg, tmp2));
+    }
 
   if (type == 1)
     {
@@ -5469,6 +5500,7 @@ ix86_expand_int_movcc (operands)
 {
   enum rtx_code code = GET_CODE (operands[1]), compare_code;
   rtx compare_seq, compare_op;
+  rtx second_test, bypass_test;
 
   /* When the compare code is not LTU or GEU, we can not use sbbl case.
      In case comparsion is done with immediate, we can convert it to LTU or
@@ -5489,7 +5521,7 @@ ix86_expand_int_movcc (operands)
     }
 
   start_sequence ();
-  compare_op = ix86_expand_compare (code);
+  compare_op = ix86_expand_compare (code, &second_test, &bypass_test);
   compare_seq = gen_sequence ();
   end_sequence ();
 
@@ -5507,7 +5539,8 @@ ix86_expand_int_movcc (operands)
       HOST_WIDE_INT cf = INTVAL (operands[3]);
       HOST_WIDE_INT diff;
 
-      if (compare_code == LTU || compare_code == GEU)
+      if ((compare_code == LTU || compare_code == GEU)
+         && !second_test && !bypass_test)
        {
 
          /* Detect overlap between destination and compare sources.  */
@@ -5796,11 +5829,36 @@ ix86_expand_int_movcc (operands)
   if (! nonimmediate_operand (operands[3], GET_MODE (operands[0])))
     operands[3] = force_reg (GET_MODE (operands[0]), operands[3]);
 
+  if (bypass_test && reg_overlap_mentioned_p (operands[0], operands[3]))
+    {
+      rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
+      emit_move_insn (tmp, operands[3]);
+      operands[3] = tmp;
+    }
+  if (second_test && reg_overlap_mentioned_p (operands[0], operands[2]))
+    {
+      rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
+      emit_move_insn (tmp, operands[2]);
+      operands[2] = tmp;
+    }
+
   emit_insn (compare_seq);
   emit_insn (gen_rtx_SET (VOIDmode, operands[0],
                          gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
                                                compare_op, operands[2],
                                                operands[3])));
+  if (bypass_test)
+    emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+                           gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
+                                 bypass_test,
+                                 operands[3],
+                                 operands[0])));
+  if (second_test)
+    emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+                           gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
+                                 second_test,
+                                 operands[2],
+                                 operands[0])));
 
   return 1; /* DONE */
 }
@@ -5811,25 +5869,39 @@ ix86_expand_fp_movcc (operands)
 {
   enum rtx_code code;
   rtx tmp;
-  rtx compare_op;
+  rtx compare_op, second_test, bypass_test;
 
   /* The floating point conditional move instructions don't directly
      support conditions resulting from a signed integer comparison.  */
 
   code = GET_CODE (operands[1]);
-  compare_op = ix86_expand_compare (code);
+  compare_op = ix86_expand_compare (code, &second_test, &bypass_test);
 
   /* The floating point conditional move instructions don't directly
      support signed integer comparisons.  */
 
-  if (!fcmov_comparison_operator (compare_op, GET_MODE (XEXP (compare_op, 0))))
+  if (!fcmov_comparison_operator (compare_op, VOIDmode))
     {
+      if (second_test != NULL || bypass_test != NULL)
+       abort();
       tmp = gen_reg_rtx (QImode);
       ix86_expand_setcc (code, tmp);
       code = NE;
       ix86_compare_op0 = tmp;
       ix86_compare_op1 = const0_rtx;
-      compare_op = ix86_expand_compare (code);
+      compare_op = ix86_expand_compare (code,  &second_test, &bypass_test);
+    }
+  if (bypass_test && reg_overlap_mentioned_p (operands[0], operands[3]))
+    {
+      tmp = gen_reg_rtx (GET_MODE (operands[0]));
+      emit_move_insn (tmp, operands[3]);
+      operands[3] = tmp;
+    }
+  if (second_test && reg_overlap_mentioned_p (operands[0], operands[2]))
+    {
+      tmp = gen_reg_rtx (GET_MODE (operands[0]));
+      emit_move_insn (tmp, operands[2]);
+      operands[2] = tmp;
     }
 
   emit_insn (gen_rtx_SET (VOIDmode, operands[0],
@@ -5837,6 +5909,18 @@ ix86_expand_fp_movcc (operands)
                                compare_op,
                                operands[2],
                                operands[3])));
+  if (bypass_test)
+    emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+                           gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
+                                 bypass_test,
+                                 operands[3],
+                                 operands[0])));
+  if (second_test)
+    emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+                           gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
+                                 second_test,
+                                 operands[2],
+                                 operands[0])));
 
   return 1;
 }
index 12d7e39..5e53f14 100644 (file)
   [(set_attr "type" "alu")
    (set_attr "mode" "QI,QI,SI")])
 
+(define_insn "*andqi_1_slp"
+  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
+       (and:QI (match_dup 0)
+               (match_operand:QI 1 "general_operand" "qi,qmi")))
+   (clobber (reg:CC 17))]
+  ""
+  "and{b}\\t{%1, %0|%0, %1}"
+  [(set_attr "type" "alu1")
+   (set_attr "mode" "QI")])
+
 (define_insn "*andqi_2"
   [(set (reg 17)
        (compare (and:QI
   [(set_attr "type" "alu")
    (set_attr "mode" "QI,QI,SI")])
 
+(define_insn "*andqi_2_slp"
+  [(set (reg 17)
+       (compare (and:QI
+                  (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
+                  (match_operand:QI 1 "nonimmediate_operand" "qmi,qi"))
+                (const_int 0)))
+   (set (strict_low_part (match_dup 0))
+       (and:QI (match_dup 0) (match_dup 1)))]
+  "ix86_match_ccmode (insn, CCNOmode)"
+  "and{b}\\t{%1, %0|%0, %1}"
+  [(set_attr "type" "alu1")
+   (set_attr "mode" "QI")])
+
 ;; ??? A bug in recog prevents it from recognizing a const_int as an
 ;; operand to zero_extend in andqi_ext_1.  It was checking explicitly
 ;; for a QImode operand, which of course failed.
    or{b}\\t{%2, %0|%0, %2}
    or{l}\\t{%k2, %k0|%k0, %k2}"
   [(set_attr "type" "alu")
+   (set_attr "mode" "QI,QI,SI")])
+
+(define_insn "*iorqi_1_slp"
+  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+q,m"))
+       (ior:QI (match_dup 0)
+               (match_operand:QI 1 "general_operand" "qmi,qi")))
+   (clobber (reg:CC 17))]
+  ""
+  "or{b}\\t{%1, %0|%0, %1}"
+  [(set_attr "type" "alu1")
    (set_attr "mode" "QI")])
 
 (define_insn "*iorqi_2"
   [(set_attr "type" "alu")
    (set_attr "mode" "QI")])
 
+(define_insn "*iorqi_2_slp"
+  [(set (reg 17)
+       (compare (ior:QI (match_operand:QI 0 "nonimmediate_operand" "+q,qm")
+                        (match_operand:QI 1 "general_operand" "qim,qi"))
+                (const_int 0)))
+   (set (strict_low_part (match_dup 0))
+       (ior:QI (match_dup 0) (match_dup 1)))]
+  "ix86_match_ccmode (insn, CCNOmode)"
+  "or{b}\\t{%1, %0|%0, %1}"
+  [(set_attr "type" "alu1")
+   (set_attr "mode" "QI")])
+
 (define_insn "*iorqi_3"
   [(set (reg 17)
        (compare (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0")
   "
 {
   emit_insn (gen_rtx_TRAP_IF (VOIDmode,
-                             ix86_expand_compare (GET_CODE (operands[0])),
+                             ix86_expand_compare (GET_CODE (operands[0]),
+                                                  NULL_RTX, NULL_RTX),
                              operands[1]));
   DONE;
 }")