OSDN Git Service

* recog.c (recog_memoized): Rename to recog_memoized_1.
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 29 Sep 2000 11:24:13 +0000 (11:24 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 29 Sep 2000 11:24:13 +0000 (11:24 +0000)
* recog.h (recog_memoized): Rename to recog_memoized_1.
(recog_memoized): New macro.
* rtl.h (single_set): Rename to single_set_1
(single_set): New macro.
* rtlanal.c (single_set): Rename to single_set_1;  expect clobbers
to be last.

* i386.md (strmovsi_1, strmovhi_1 strmovqi_1):
Do not use match_dup of input operands at outputs.
Use register_operand for memory expression.
(rep_movsi): Put use last, canonicalize.
Use register_operand for memory expression.
(rep_movqi): Put use last.
Use register_operand for memory expression.
(strsetsi_1, strset_hi_1, strsetqi_1): Do not use match_dup
of input operands at outputs.  Use register_operand for memory
expression.
(rep_stossi): Put use last; canonicalize; fix match_dup in
the address expression
(rep_stosqi): Likewise.
(memcmp expander): Update calls.
(cmpstrsi_nz_1, cmpstrsi_1, strlensi_1): Avoid match_dups in
the clobbers.

* i386.md (fp_jcc_3, fp_jcc_4, jp_fcc_5): if_then_else operand is
VOIDmode.
(fp_jcc_4, fp_jcc_3): Refuse unordered comparisons.

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

gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.md
gcc/recog.c
gcc/rtl.h
gcc/rtlanal.c

index 263f526..fef5c52 100644 (file)
@@ -125,6 +125,7 @@ extern int ix86_adjust_cost PARAMS ((rtx, rtx, rtx, int));
 extern void ix86_sched_init PARAMS ((FILE *, int));
 extern int ix86_sched_reorder PARAMS ((FILE *, int, rtx *, int, int));
 extern int ix86_variable_issue PARAMS ((FILE *, int, rtx, int));
+extern enum machine_mode ix86_fp_compare_mode PARAMS ((enum rtx_code));
 
 #ifdef TREE_CODE
 extern void init_cumulative_args PARAMS ((CUMULATIVE_ARGS *, tree, rtx));
index efc0eaa..5521ea2 100644 (file)
@@ -388,7 +388,6 @@ static void put_condition_code PARAMS ((enum rtx_code, enum machine_mode,
                                       int, int, FILE *));
 static enum rtx_code unsigned_comparison PARAMS ((enum rtx_code code));
 static rtx ix86_expand_int_compare PARAMS ((enum rtx_code, rtx, rtx));
-static enum machine_mode ix86_fp_compare_mode PARAMS ((enum rtx_code));
 static enum rtx_code ix86_prepare_fp_compare_args PARAMS ((enum rtx_code,
                                                           rtx *, rtx *));
 static rtx gen_push PARAMS ((rtx));
@@ -4635,7 +4634,7 @@ ix86_expand_int_compare (code, op0, op1)
 /* Figure out whether to use ordered or unordered fp comparisons.
    Return the appropriate mode to use.  */
 
-static enum machine_mode
+enum machine_mode
 ix86_fp_compare_mode (code)
      enum rtx_code code;
 {
index a855508..db8be56 100644 (file)
 
 (define_insn "*fp_jcc_3"
   [(set (pc)
-       (if_then_else (match_operator:CCFP 0 "comparison_operator"
+       (if_then_else (match_operator 0 "comparison_operator"
                        [(match_operand 1 "register_operand" "f")
                         (match_operand 2 "nonimmediate_operand" "fm")])
          (label_ref (match_operand 3 "" ""))
   "TARGET_80387
    && (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
    && GET_MODE (operands[1]) == GET_MODE (operands[2])
-   && !ix86_use_fcomi_compare (GET_CODE (operands[0]))"
+   && !ix86_use_fcomi_compare (GET_CODE (operands[0]))
+   && SELECT_CC_MODE (GET_CODE (operands[0]),
+                     operands[1], operands[2]) == CCFPmode"
   "#")
 
 (define_insn "*fp_jcc_4"
   [(set (pc)
-       (if_then_else (match_operator:CCFP 0 "comparison_operator"
+       (if_then_else (match_operator 0 "comparison_operator"
                        [(match_operand 1 "register_operand" "f")
                         (match_operand 2 "nonimmediate_operand" "fm")])
          (pc)
   "TARGET_80387
    && (GET_MODE (operands[1]) == SFmode || GET_MODE (operands[1]) == DFmode)
    && GET_MODE (operands[1]) == GET_MODE (operands[2])
-   && !ix86_use_fcomi_compare (GET_CODE (operands[0]))"
+   && !ix86_use_fcomi_compare (GET_CODE (operands[0]))
+   && SELECT_CC_MODE (GET_CODE (operands[0]),
+                     operands[1], operands[2]) == CCFPmode"
   "#")
 
 (define_insn "*fp_jcc_5"
   [(set (mem:SI (match_operand:SI 2 "register_operand" "0"))
        (mem:SI (match_operand:SI 3 "register_operand" "1")))
    (set (match_operand:SI 0 "register_operand" "=D")
-       (plus:SI (match_dup 0)
+       (plus:SI (match_dup 2)
                 (const_int 4)))
    (set (match_operand:SI 1 "register_operand" "=S")
-       (plus:SI (match_dup 1)
+       (plus:SI (match_dup 3)
                 (const_int 4)))
    (use (reg:SI 19))]
   "TARGET_SINGLE_STRINGOP || optimize_size"
   [(set (mem:HI (match_operand:SI 2 "register_operand" "0"))
        (mem:HI (match_operand:SI 3 "register_operand" "1")))
    (set (match_operand:SI 0 "register_operand" "=D")
-       (plus:SI (match_dup 0)
+       (plus:SI (match_dup 2)
                 (const_int 2)))
    (set (match_operand:SI 1 "register_operand" "=S")
-       (plus:SI (match_dup 1)
+       (plus:SI (match_dup 3)
                 (const_int 2)))
    (use (reg:SI 19))]
   "TARGET_SINGLE_STRINGOP || optimize_size"
   [(set (mem:QI (match_operand:SI 2 "register_operand" "0"))
        (mem:QI (match_operand:SI 3 "register_operand" "1")))
    (set (match_operand:SI 0 "register_operand" "=D")
-       (plus:SI (match_dup 0)
+       (plus:SI (match_dup 2)
                 (const_int 1)))
    (set (match_operand:SI 1 "register_operand" "=S")
-       (plus:SI (match_dup 1)
+       (plus:SI (match_dup 3)
                 (const_int 1)))
    (use (reg:SI 19))]
   "TARGET_SINGLE_STRINGOP || optimize_size"
    (set_attr "memory" "both")
    (set_attr "mode" "QI")])
 
-;; It might seem that operands 3 & 4 could use predicate register_operand.
-;; But strength reduction might offset the MEM expression.  So we let
-;; reload put the address into %edi & %esi.
-
 (define_insn "rep_movsi"
   [(set (match_operand:SI 2 "register_operand" "=c") (const_int 0))
-   (use (match_operand:SI 5 "register_operand" "2"))
    (set (match_operand:SI 0 "register_operand" "=D") 
-        (plus:SI (match_operand:SI 3 "address_operand" "0")
-                (ashift:SI (match_dup 5) (const_int 2))))
+        (plus:SI (ashift:SI (match_operand:SI 5 "register_operand" "2")
+                           (const_int 2))
+                (match_operand:SI 3 "register_operand" "0")))
    (set (match_operand:SI 1 "register_operand" "=S") 
-        (plus:SI (match_operand:SI 4 "address_operand" "1")
-                (ashift:SI (match_dup 5) (const_int 2))))
+        (plus:SI (ashift:SI (match_dup 5) (const_int 2))
+                (match_operand:SI 4 "register_operand" "1")))
    (set (mem:BLK (match_dup 3))
        (mem:BLK (match_dup 4)))
+   (use (match_dup 5))
    (use (reg:SI 19))]
   ""
   "rep\;movsl|rep movsd"
 
 (define_insn "rep_movqi"
   [(set (match_operand:SI 2 "register_operand" "=c") (const_int 0))
-   (use (match_operand:SI 5 "register_operand" "2"))
    (set (match_operand:SI 0 "register_operand" "=D") 
-        (plus:SI (match_operand:SI 3 "address_operand" "0") (match_dup 5)))
+        (plus:SI (match_operand:SI 3 "register_operand" "0")
+                (match_operand:SI 5 "register_operand" "2")))
    (set (match_operand:SI 1 "register_operand" "=S") 
-        (plus:SI (match_operand:SI 4 "address_operand" "1") (match_dup 5)))
+        (plus:SI (match_operand:SI 4 "register_operand" "1") (match_dup 5)))
    (set (mem:BLK (match_dup 3))
        (mem:BLK (match_dup 4)))
+   (use (match_dup 5))
    (use (reg:SI 19))]
   ""
   "rep\;movsb|rep movsb"
   [(set (mem:SI (match_operand:SI 1 "register_operand" "0"))
        (match_operand:SI 2 "register_operand" "a"))
    (set (match_operand:SI 0 "register_operand" "=D")
-       (plus:SI (match_dup 0)
+       (plus:SI (match_dup 1)
                 (const_int 4)))
    (use (reg:SI 19))]
   "TARGET_SINGLE_STRINGOP || optimize_size"
   [(set (mem:HI (match_operand:SI 1 "register_operand" "0"))
        (match_operand:HI 2 "register_operand" "a"))
    (set (match_operand:SI 0 "register_operand" "=D")
-       (plus:SI (match_dup 0)
+       (plus:SI (match_dup 1)
                 (const_int 2)))
    (use (reg:SI 19))]
   "TARGET_SINGLE_STRINGOP || optimize_size"
   [(set (mem:QI (match_operand:SI 1 "register_operand" "0"))
        (match_operand:QI 2 "register_operand" "a"))
    (set (match_operand:SI 0 "register_operand" "=D")
-       (plus:SI (match_dup 0)
+       (plus:SI (match_dup 1)
                 (const_int 1)))
    (use (reg:SI 19))]
   "TARGET_SINGLE_STRINGOP || optimize_size"
    (set_attr "memory" "store")
    (set_attr "mode" "QI")])
 
-;; It might seem that operand 0 could use predicate register_operand.
-;; But strength reduction might offset the MEM expression.  So we let
-;; reload put the address into %edi.
-
 (define_insn "rep_stossi"
   [(set (match_operand:SI 1 "register_operand" "=c") (const_int 0))
-   (use (match_operand:SI 2 "register_operand" "a"))
-   (use (match_operand:SI 4 "register_operand" "1"))
    (set (match_operand:SI 0 "register_operand" "=D") 
-        (plus:SI (match_operand:SI 3 "address_operand" "0")
-                (ashift:SI (match_dup 3) (const_int 2))))
+        (plus:SI (ashift:SI (match_operand:SI 4 "register_operand" "1")
+                           (const_int 2))
+                (match_operand:SI 3 "register_operand" "0")))
    (set (mem:BLK (match_dup 3))
        (const_int 0))
+   (use (match_operand:SI 2 "register_operand" "a"))
+   (use (match_dup 4))
    (use (reg:SI 19))]
   ""
   "rep\;stosl|rep stosd"
 
 (define_insn "rep_stosqi"
   [(set (match_operand:SI 1 "register_operand" "=c") (const_int 0))
-   (use (match_operand:QI 2 "register_operand" "a"))
-   (use (match_operand:SI 4 "register_operand" "1"))
    (set (match_operand:SI 0 "register_operand" "=D") 
-        (plus:SI (match_operand:SI 3 "address_operand" "0") (match_dup 3)))
+        (plus:SI (match_operand:SI 3 "register_operand" "0")
+                (match_operand:SI 4 "register_operand" "1")))
    (set (mem:BLK (match_dup 3))
        (const_int 0))
+   (use (match_operand:QI 2 "register_operand" "a"))
+   (use (match_dup 4))
    (use (reg:SI 19))]
   ""
   "rep\;stosb|rep stosb"
          emit_move_insn (operands[0], const0_rtx);
          DONE;
        }
-      emit_insn (gen_cmpstrsi_nz_1 (addr1, addr2, countreg, align));
+      emit_insn (gen_cmpstrsi_nz_1 (addr1, addr2, countreg, align,
+                                   addr1, addr2, countreg));
     }
   else
     {
       emit_insn (gen_cmpsi_1 (countreg, countreg));
-      emit_insn (gen_cmpstrsi_1 (addr1, addr2, countreg, align));
+      emit_insn (gen_cmpstrsi_1 (addr1, addr2, countreg, align,
+                                addr1, addr2, countreg));
     }
 
   outlow = gen_lowpart (QImode, out);
 
 ;; memcmp recognizers.  The `cmpsb' opcode does nothing if the count is
 ;; zero.  Emit extra code to make sure that a zero-length compare is EQ.
-;;
-;; It might seem that operands 0 & 1 could use predicate register_operand.
-;; But strength reduction might offset the MEM expression.  So we let
-;; reload put the address into %edi & %esi.
 
 (define_insn "cmpstrsi_nz_1"
   [(set (reg:CC 17)
-       (compare:CC (mem:BLK (match_operand:SI 0 "address_operand" "S"))
-                   (mem:BLK (match_operand:SI 1 "address_operand" "D"))))
-   (use (match_operand:SI 2 "register_operand" "c"))
+       (compare:CC (mem:BLK (match_operand:SI 4 "register_operand" "0"))
+                   (mem:BLK (match_operand:SI 5 "register_operand" "1"))))
+   (use (match_operand:SI 6 "register_operand" "2"))
    (use (match_operand:SI 3 "immediate_operand" "i"))
    (use (reg:SI 19))
-   (clobber (match_dup 0))
-   (clobber (match_dup 1))
-   (clobber (match_dup 2))]
+   (clobber (match_operand:SI 0 "register_operand" "=S"))
+   (clobber (match_operand:SI 1 "register_operand" "=D"))
+   (clobber (match_operand:SI 2 "register_operand" "=c"))]
   ""
   "repz{\;| }cmpsb"
   [(set_attr "type" "str")
 
 (define_insn "cmpstrsi_1"
   [(set (reg:CC 17)
-       (if_then_else:CC (ne (match_operand:SI 2 "register_operand" "c")
+       (if_then_else:CC (ne (match_operand:SI 6 "register_operand" "2")
                             (const_int 0))
-         (compare:SI (mem:BLK (match_operand:SI 0 "address_operand" "S"))
-                     (mem:BLK (match_operand:SI 1 "address_operand" "D")))
+         (compare:SI (mem:BLK (match_operand:SI 4 "register_operand" "0"))
+                     (mem:BLK (match_operand:SI 5 "register_operand" "1")))
          (const_int 0)))
    (use (match_operand:SI 3 "immediate_operand" "i"))
    (use (reg:CC 17))
    (use (reg:SI 19))
-   (clobber (match_dup 0))
-   (clobber (match_dup 1))
-   (clobber (match_dup 2))]
+   (clobber (match_operand:SI 0 "register_operand" "=S"))
+   (clobber (match_operand:SI 1 "register_operand" "=D"))
+   (clobber (match_operand:SI 2 "register_operand" "=c"))]
   ""
   "repz{\;| }cmpsb"
   [(set_attr "type" "str")
 
       emit_insn (gen_cld ());
       emit_insn (gen_strlensi_1 (scratch1, scratch3, eoschar,
-                                align, constm1_rtx));
+                                align, constm1_rtx, scratch3));
       emit_insn (gen_one_cmplsi2 (scratch2, scratch1));
       emit_insn (gen_addsi3 (out, scratch2, constm1_rtx));
     }
   DONE;
 }")
 
-;; It might seem that operands 0 & 1 could use predicate register_operand.
-;; But strength reduction might offset the MEM expression.  So we let
-;; reload put the address into %edi.
-
 (define_insn "strlensi_1"
   [(set (match_operand:SI 0 "register_operand" "=&c")
-       (unspec:SI [(mem:BLK (match_operand:SI 1 "address_operand" "D"))
+       (unspec:SI [(mem:BLK (match_operand:SI 5 "register_operand" "1"))
                    (match_operand:QI 2 "general_operand" "a")
                    (match_operand:SI 3 "immediate_operand" "i")
                    (match_operand:SI 4 "immediate_operand" "0")] 0))
    (use (reg:SI 19))
-   (clobber (match_dup 1))
+   (clobber (match_operand:SI 1 "register_operand" "=D"))
    (clobber (reg:CC 17))]
   ""
   "repnz{\;| }scasb"
index f1d5dee..248f8d8 100644 (file)
@@ -112,7 +112,7 @@ init_recog ()
    through this one.  (The only exception is in combine.c.)  */
 
 int
-recog_memoized (insn)
+recog_memoized_1 (insn)
      rtx insn;
 {
   if (INSN_CODE (insn) < 0)
index 190e971..825f097 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1329,6 +1329,12 @@ extern void set_unique_reg_note         PARAMS ((rtx, enum reg_note, rtx));
 
 /* Functions in rtlanal.c */
 
+/* Single set is implemented as macro for performance reasons.  */
+#define single_set(I) (INSN_P (I) \
+                      ? (GET_CODE (PATTERN (I)) == SET \
+                         ? PATTERN (I) : single_set_1 (I)) \
+                      : NULL_RTX)
+
 extern int rtx_unstable_p              PARAMS ((rtx));
 extern int rtx_varies_p                        PARAMS ((rtx));
 extern int rtx_addr_varies_p           PARAMS ((rtx));
@@ -1347,7 +1353,7 @@ extern int no_jumps_between_p             PARAMS ((rtx, rtx));
 extern int modified_in_p               PARAMS ((rtx, rtx));
 extern int insn_dependent_p            PARAMS ((rtx, rtx));
 extern int reg_set_p                   PARAMS ((rtx, rtx));
-extern rtx single_set                  PARAMS ((rtx));
+extern rtx single_set_1                        PARAMS ((rtx));
 extern int multiple_sets               PARAMS ((rtx));
 extern rtx find_last_value             PARAMS ((rtx, rtx *, rtx, int));
 extern int refers_to_regno_p           PARAMS ((unsigned int, unsigned int,
index c19b3f5..0d922c6 100644 (file)
@@ -842,46 +842,91 @@ insn_dependent_p_1 (x, pat, data)
    will not be used, which we ignore.  */
 
 rtx
-single_set (insn)
+single_set_1 (insn)
      rtx insn;
 {
   rtx set;
+  rtx pat = PATTERN (insn);
   int i;
   
-  if (! INSN_P (insn))
-    return 0;
-
-  if (GET_CODE (PATTERN (insn)) == SET)
-    return PATTERN (insn);
-  
-  else if (GET_CODE (PATTERN (insn)) == PARALLEL)
+  if (GET_CODE (pat) == PARALLEL)
     {
-      for (i = 0, set = 0; i < XVECLEN (PATTERN (insn), 0); i++)
+      rtx x, sub;
+      /* This part is is performance critical for targets that use a lot of
+        parallels, such as i386.  We want to accept as single set
+        instructions even an instructions with multiple sets where only
+        one has live result, but we attempt to delay this tests only for
+        multiple set instructions to reduce amount of calls to
+        find_reg_note and side_effects_p.
+       
+        We expect the "common" instruction to be parallel with first SET
+        followed by the clobbers.  So first we get the set, then look
+        if it is followed by USE or CLOBBER. If so, we just return expect
+        no SETs after these.  When SET is followed by another SET, we
+        continue by the clomplex loop trought all members of PARALLEL.
+       */
+#ifdef ENABLE_CHECKING
+      if (XVECLEN (pat, 0) < 2)
+       abort ();
+#endif
+      set = XVECEXP (pat, 0, 0);
+      switch (GET_CODE (set))
        {
-         rtx sub = XVECEXP (PATTERN (insn), 0, i);
-
-         switch (GET_CODE (sub))
+#ifdef ENABLE_CHECKING
+         case USE:
+         case CLOBBER:
+           /* Instruction should not consist only from USEs and CLOBBERS,
+              since then gcc is allowed to remove it entirely.  In case
+              something else is present, it should be first in the pattern.  */
+           abort();
+#endif
+         case SET:
+           break;
+         default:
+           return NULL_RTX;
+       }
+      x = XVECEXP (pat, 0, 1);
+      switch (GET_CODE (x))
+       {
+       case USE:
+       case CLOBBER:
+#ifdef ENABLE_CHECKING
+         /* The USEs and CLOBBERs should always come last in the pattern.  */
+         for (i = XVECLEN (pat, 0) - 1; i > 1; i--)
+           if (GET_CODE (XVECEXP (pat, 0, i)) != USE
+               && GET_CODE (XVECEXP (pat, 0, i)) != CLOBBER)
+             abort();
+#endif
+           return set;
+       case SET:
+         /* Multiple set insns - we are off the critical path now.  */
+         for (i = XVECLEN (pat, 0) - 1; i > 0; i--)
            {
-           case USE:
-           case CLOBBER:
-             break;
-
-           case SET:
-             if (! find_reg_note (insn, REG_UNUSED, SET_DEST (sub))
-                 || side_effects_p (sub))
+             sub = XVECEXP (pat, 0, i);
+             switch GET_CODE (sub)
                {
-                 if (set)
-                   return 0;
-                 else
+               case USE:
+               case CLOBBER:
+                 break;
+
+               case SET:
+                 if (!set
+                     || (find_reg_note (insn, REG_UNUSED, SET_DEST (set))
+                         && side_effects_p (set)))
                    set = sub;
-               }
-             break;
+                 else if (! find_reg_note (insn, REG_UNUSED, SET_DEST (sub))
+                          || side_effects_p (sub))
+                   return NULL_RTX;
+                 break;
 
-           default:
-             return 0;
+               default:
+                 return NULL_RTX;
+               }
            }
+         return set;
+       default:
+         return NULL_RTX;
        }
-      return set;
     }
   
   return 0;