PR gcc/1532
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 23 Jan 2004 21:05:21 +0000 (21:05 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 23 Jan 2004 21:05:21 +0000 (21:05 +0000)
* cse.c (cse_change_cc_mode): New static function.
(cse_change_cc_mode_insns, cse_cc_succs): Likewise.
(cse_condition_code_reg): New function.
* rtl.h (cse_condition_code_reg): Declare.
* toplev.c (rest_of_handle_cse2): Call cse_condition_code_reg.
* target.h (struct gcc_target): Add fixed_condition_code_regs and
cc_modes_compatible.
* target-def.h (TARGET_FIXED_CONDITION_CODE_REGS): Define.
(TARGET_CC_MODES_COMPATIBLE): Define.
(TARGET_INITIALIZER): Add new initializers.
* targhooks.c (default_cc_modes_compatible): New function.
* targhooks.c (default_cc_modes_compatible): Declare.
* hooks.c (hook_bool_intp_intp_false): New function.
* hooks.h (hook_bool_intp_intp_false): Declare.
* config/i386/i386.c (TARGET_FIXED_CONDITION_CODE_REGS): Define.
(TARGET_CC_MODES_COMPATIBLE): Define.
(ix86_fixed_condition_code_regs): New static function.
(ix86_cc_modes_compatible): Likewise.
* doc/tm.texi (Condition Code): Document new hooks.

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

12 files changed:
gcc/ChangeLog
gcc/config/i386/i386.c
gcc/cse.c
gcc/doc/tm.texi
gcc/hooks.c
gcc/hooks.h
gcc/rtl.h
gcc/target-def.h
gcc/target.h
gcc/targhooks.c
gcc/targhooks.h
gcc/toplev.c

index 1e4f176..48a9f84 100644 (file)
@@ -1,3 +1,26 @@
+2004-01-23  Ian Lance Taylor  <ian@wasabisystems.com>
+
+       PR gcc/1532
+       * cse.c (cse_change_cc_mode): New static function.
+       (cse_change_cc_mode_insns, cse_cc_succs): Likewise.
+       (cse_condition_code_reg): New function.
+       * rtl.h (cse_condition_code_reg): Declare.
+       * toplev.c (rest_of_handle_cse2): Call cse_condition_code_reg.
+       * target.h (struct gcc_target): Add fixed_condition_code_regs and
+       cc_modes_compatible.
+       * target-def.h (TARGET_FIXED_CONDITION_CODE_REGS): Define.
+       (TARGET_CC_MODES_COMPATIBLE): Define.
+       (TARGET_INITIALIZER): Add new initializers.
+       * targhooks.c (default_cc_modes_compatible): New function.
+       * targhooks.c (default_cc_modes_compatible): Declare.
+       * hooks.c (hook_bool_intp_intp_false): New function.
+       * hooks.h (hook_bool_intp_intp_false): Declare.
+       * config/i386/i386.c (TARGET_FIXED_CONDITION_CODE_REGS): Define.
+       (TARGET_CC_MODES_COMPATIBLE): Define.
+       (ix86_fixed_condition_code_regs): New static function.
+       (ix86_cc_modes_compatible): Likewise.
+       * doc/tm.texi (Condition Code): Document new hooks.
+
 2004-01-23  Rainer Orth  <ro@TechFak.Uni-Bielefeld.DE>
 
        * fixinc/inclhack.def (bad_lval): Renamed to ...
index 0cad3f1..79102cf 100644 (file)
@@ -1,6 +1,6 @@
 /* Subroutines used for code generation on IA-32.
    Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003 Free Software Foundation, Inc.
+   2002, 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -793,6 +793,9 @@ static rtx maybe_get_pool_constant (rtx);
 static rtx ix86_expand_int_compare (enum rtx_code, rtx, rtx);
 static enum rtx_code ix86_prepare_fp_compare_args (enum rtx_code, rtx *,
                                                   rtx *);
+static bool ix86_fixed_condition_code_regs (unsigned int *, unsigned int *);
+static enum machine_mode ix86_cc_modes_compatible (enum machine_mode,
+                                                  enum machine_mode);
 static rtx get_thread_pointer (int);
 static rtx legitimize_tls_address (rtx, enum tls_model, int);
 static void get_pc_thunk_name (char [32], unsigned int);
@@ -1010,6 +1013,11 @@ static void init_ext_80387_constants (void);
 #undef TARGET_ADDRESS_COST
 #define TARGET_ADDRESS_COST ix86_address_cost
 
+#undef TARGET_FIXED_CONDITION_CODE_REGS
+#define TARGET_FIXED_CONDITION_CODE_REGS ix86_fixed_condition_code_regs
+#undef TARGET_CC_MODES_COMPATIBLE
+#define TARGET_CC_MODES_COMPATIBLE ix86_cc_modes_compatible
+
 #undef TARGET_MACHINE_DEPENDENT_REORG
 #define TARGET_MACHINE_DEPENDENT_REORG ix86_reorg
 
@@ -8723,6 +8731,64 @@ ix86_cc_mode (enum rtx_code code, rtx op0, rtx op1)
     }
 }
 
+/* Return the fixed registers used for condition codes.  */
+
+static bool
+ix86_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
+{
+  *p1 = FLAGS_REG;
+  *p2 = FPSR_REG;
+  return true;
+}
+
+/* If two condition code modes are compatible, return a condition code
+   mode which is compatible with both.  Otherwise, return
+   VOIDmode.  */
+
+static enum machine_mode
+ix86_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
+{
+  if (m1 == m2)
+    return m1;
+
+  if (GET_MODE_CLASS (m1) != MODE_CC || GET_MODE_CLASS (m2) != MODE_CC)
+    return VOIDmode;
+
+  if ((m1 == CCGCmode && m2 == CCGOCmode)
+      || (m1 == CCGOCmode && m2 == CCGCmode))
+    return CCGCmode;
+
+  switch (m1)
+    {
+    default:
+      abort ();
+
+    case CCmode:
+    case CCGCmode:
+    case CCGOCmode:
+    case CCNOmode:
+    case CCZmode:
+      switch (m2)
+       {
+       default:
+         return VOIDmode;
+
+       case CCmode:
+       case CCGCmode:
+       case CCGOCmode:
+       case CCNOmode:
+       case CCZmode:
+         return CCmode;
+       }
+
+    case CCFPmode:
+    case CCFPUmode:
+      /* These are only compatible with themselves, which we already
+        checked above.  */
+      return VOIDmode;
+    }
+}
+
 /* Return true if we should use an FCOMI instruction for this fp comparison.  */
 
 int
index d5a37fd..1ec01f9 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -658,6 +658,9 @@ static void flush_hash_table (void);
 static bool insn_live_p (rtx, int *);
 static bool set_live_p (rtx, rtx, int *);
 static bool dead_libcall_p (rtx, int *);
+static int cse_change_cc_mode (rtx *, void *);
+static void cse_change_cc_mode_insns (rtx, rtx, rtx);
+static enum machine_mode cse_cc_succs (basic_block, rtx, rtx, bool);
 \f
 /* Nonzero if X has the form (PLUS frame-pointer integer).  We check for
    virtual regs here because the simplify_*_operation routines are called
@@ -7665,3 +7668,316 @@ delete_trivially_dead_insns (rtx insns, int nreg)
   timevar_pop (TV_DELETE_TRIVIALLY_DEAD);
   return ndead;
 }
+
+/* This function is called via for_each_rtx.  The argument, NEWREG, is
+   a condition code register with the desired mode.  If we are looking
+   at the same register in a different mode, replace it with
+   NEWREG.  */
+
+static int
+cse_change_cc_mode (rtx *loc, void *data)
+{
+  rtx newreg = (rtx) data;
+
+  if (*loc
+      && GET_CODE (*loc) == REG
+      && REGNO (*loc) == REGNO (newreg)
+      && GET_MODE (*loc) != GET_MODE (newreg))
+    {
+      *loc = newreg;
+      return -1;
+    }
+  return 0;
+}
+
+/* Change the mode of any reference to the register REGNO (NEWREG) to
+   GET_MODE (NEWREG), starting at START.  Stop before END.  Stop at
+   any instruction after START which modifies NEWREG.  */
+
+static void
+cse_change_cc_mode_insns (rtx start, rtx end, rtx newreg)
+{
+  rtx insn;
+
+  for (insn = start; insn != end; insn = NEXT_INSN (insn))
+    {
+      if (! INSN_P (insn))
+       continue;
+
+      if (insn != start && reg_set_p (newreg, insn))
+       return;
+
+      for_each_rtx (&PATTERN (insn), cse_change_cc_mode, newreg);
+      for_each_rtx (&REG_NOTES (insn), cse_change_cc_mode, newreg);
+    }
+}
+
+/* BB is a basic block which finishes with CC_REG as a condition code
+   register which is set to CC_SRC.  Look through the successors of BB
+   to find blocks which have a single predecessor (i.e., this one),
+   and look through those blocks for an assignment to CC_REG which is
+   equivalent to CC_SRC.  CAN_CHANGE_MODE indicates whether we are
+   permitted to change the mode of CC_SRC to a compatible mode.  This
+   returns VOIDmode if no equivalent assignments were found.
+   Otherwise it returns the mode which CC_SRC should wind up with.
+
+   The main complexity in this function is handling the mode issues.
+   We may have more than one duplicate which we can eliminate, and we
+   try to find a mode which will work for multiple duplicates.  */
+
+static enum machine_mode
+cse_cc_succs (basic_block bb, rtx cc_reg, rtx cc_src, bool can_change_mode)
+{
+  bool found_equiv;
+  enum machine_mode mode;
+  unsigned int insn_count;
+  edge e;
+  rtx insns[2];
+  enum machine_mode modes[2];
+  rtx last_insns[2];
+  unsigned int i;
+  rtx newreg;
+
+  /* We expect to have two successors.  Look at both before picking
+     the final mode for the comparison.  If we have more successors
+     (i.e., some sort of table jump, although that seems unlikely),
+     then we require all beyond the first two to use the same
+     mode.  */
+
+  found_equiv = false;
+  mode = GET_MODE (cc_src);
+  insn_count = 0;
+  for (e = bb->succ; e; e = e->succ_next)
+    {
+      rtx insn;
+      rtx end;
+
+      if (e->flags & EDGE_COMPLEX)
+       continue;
+
+      if (! e->dest->pred
+         || e->dest->pred->pred_next
+         || e->dest == EXIT_BLOCK_PTR)
+       continue;
+
+      end = NEXT_INSN (BB_END (e->dest));
+      for (insn = BB_HEAD (e->dest); insn != end; insn = NEXT_INSN (insn))
+       {
+         rtx set;
+
+         if (! INSN_P (insn))
+           continue;
+
+         /* If CC_SRC is modified, we have to stop looking for
+            something which uses it.  */
+         if (modified_in_p (cc_src, insn))
+           break;
+
+         /* Check whether INSN sets CC_REG to CC_SRC.  */
+         set = single_set (insn);
+         if (set
+             && GET_CODE (SET_DEST (set)) == REG
+             && REGNO (SET_DEST (set)) == REGNO (cc_reg))
+           {
+             bool found;
+             enum machine_mode set_mode;
+             enum machine_mode comp_mode;
+
+             found = false;
+             set_mode = GET_MODE (SET_SRC (set));
+             comp_mode = set_mode;
+             if (rtx_equal_p (cc_src, SET_SRC (set)))
+               found = true;
+             else if (GET_CODE (cc_src) == COMPARE
+                      && GET_CODE (SET_SRC (set)) == COMPARE
+                      && GET_MODE (cc_src) != set_mode
+                      && rtx_equal_p (XEXP (cc_src, 0),
+                                      XEXP (SET_SRC (set), 0))
+                      && rtx_equal_p (XEXP (cc_src, 1),
+                                      XEXP (SET_SRC (set), 1)))
+                          
+               {
+                 comp_mode = (*targetm.cc_modes_compatible) (mode, set_mode);
+                 if (comp_mode != VOIDmode
+                     && (can_change_mode || comp_mode == mode))
+                   found = true;
+               }
+
+             if (found)
+               {
+                 found_equiv = true;
+                 if (insn_count < sizeof insns / sizeof insn[0])
+                   {
+                     insns[insn_count] = insn;
+                     modes[insn_count] = set_mode;
+                     last_insns[insn_count] = end;
+                     ++insn_count;
+
+                     /* Sanity check.  */
+                     if (! can_change_mode && mode != comp_mode)
+                       abort ();
+
+                     mode = comp_mode;
+                   }
+                 else
+                   {
+                     if (set_mode != mode)
+                       break;
+                     /* INSN sets CC_REG to a value equal to CC_SRC
+                        with the right mode.  We can simply delete
+                        it.  */
+                     delete_insn (insn);
+                   }
+
+                 /* We found an instruction to delete.  Keep looking,
+                    in the hopes of finding a three-way jump.  */
+                 continue;
+               }
+
+             /* We found an instruction which sets the condition
+                code, so don't look any farther.  */
+             break;
+           }
+
+         /* If INSN sets CC_REG in some other way, don't look any
+            farther.  */
+         if (reg_set_p (cc_reg, insn))
+           break;
+       }
+
+      /* If we fell off the bottom of the block, we can keep looking
+        through successors.  We pass CAN_CHANGE_MODE as false because
+        we aren't prepared to handle compatibility between the
+        further blocks and this block.  */
+      if (insn == end)
+       {
+         if (cse_cc_succs (e->dest, cc_reg, cc_src, false) != VOIDmode)
+           found_equiv = true;
+       }
+    }
+
+  if (! found_equiv)
+    return VOIDmode;
+
+  /* Now INSN_COUNT is the number of instructions we found which set
+     CC_REG to a value equivalent to CC_SRC.  The instructions are in
+     INSNS.  The modes used by those instructions are in MODES.  */
+
+  newreg = NULL_RTX;
+  for (i = 0; i < insn_count; ++i)
+    {
+      if (modes[i] != mode)
+       {
+         /* We need to change the mode of CC_REG in INSNS[i] and
+            subsequent instructions.  */
+         if (! newreg)
+           {
+             if (GET_MODE (cc_reg) == mode)
+               newreg = cc_reg;
+             else
+               newreg = gen_rtx_REG (mode, REGNO (cc_reg));
+           }
+         cse_change_cc_mode_insns (NEXT_INSN (insns[i]), last_insns[i],
+                                   newreg);
+       }
+
+      delete_insn (insns[i]);
+    }
+
+  return mode;
+}
+
+/* If we have a fixed condition code register (or two), walk through
+   the instructions and try to eliminate duplicate assignments.  */
+
+void
+cse_condition_code_reg (void)
+{
+  unsigned int cc_regno_1;
+  unsigned int cc_regno_2;
+  rtx cc_reg_1;
+  rtx cc_reg_2;
+  basic_block bb;
+
+  if (! (*targetm.fixed_condition_code_regs) (&cc_regno_1, &cc_regno_2))
+    return;
+
+  cc_reg_1 = gen_rtx_REG (CCmode, cc_regno_1);
+  if (cc_regno_2 != INVALID_REGNUM)
+    cc_reg_2 = gen_rtx_REG (CCmode, cc_regno_2);
+  else
+    cc_reg_2 = NULL_RTX;
+
+  FOR_EACH_BB (bb)
+    {
+      rtx last_insn;
+      rtx cc_reg;
+      rtx insn;
+      rtx cc_src_insn;
+      rtx cc_src;
+      enum machine_mode mode;
+
+      /* Look for blocks which end with a conditional jump based on a
+        condition code register.  Then look for the instruction which
+        sets the condition code register.  Then look through the
+        successor blocks for instructions which set the condition
+        code register to the same value.  There are other possible
+        uses of the condition code register, but these are by far the
+        most common and the ones which we are most likely to be able
+        to optimize.  */
+
+      last_insn = BB_END (bb);
+      if (GET_CODE (last_insn) != JUMP_INSN)
+       continue;
+
+      if (reg_referenced_p (cc_reg_1, PATTERN (last_insn)))
+       cc_reg = cc_reg_1;
+      else if (cc_reg_2 && reg_referenced_p (cc_reg_2, PATTERN (last_insn)))
+       cc_reg = cc_reg_2;
+      else
+       continue;
+
+      cc_src_insn = NULL_RTX;
+      cc_src = NULL_RTX;
+      for (insn = PREV_INSN (last_insn);
+          insn && insn != PREV_INSN (BB_HEAD (bb));
+          insn = PREV_INSN (insn))
+       {
+         rtx set;
+
+         if (! INSN_P (insn))
+           continue;
+         set = single_set (insn);
+         if (set
+             && GET_CODE (SET_DEST (set)) == REG
+             && REGNO (SET_DEST (set)) == REGNO (cc_reg))
+           {
+             cc_src_insn = insn;
+             cc_src = SET_SRC (set);
+             break;
+           }
+         else if (reg_set_p (cc_reg, insn))
+           break;
+       }
+
+      if (! cc_src_insn)
+       continue;
+
+      if (modified_between_p (cc_src, cc_src_insn, NEXT_INSN (last_insn)))
+       continue;
+
+      /* Now CC_REG is a condition code register used for a
+        conditional jump at the end of the block, and CC_SRC, in
+        CC_SRC_INSN, is the value to which that condition code
+        register is set, and CC_SRC is still meaningful at the end of
+        the basic block.  */
+
+      mode = cse_cc_succs (bb, cc_reg, cc_src, true);
+      if (mode != GET_MODE (cc_src) && mode != VOIDmode)
+       {
+         PUT_MODE (cc_src, mode);
+         cse_change_cc_mode_insns (cc_src_insn, NEXT_INSN (last_insn),
+                                   gen_rtx_REG (mode, REGNO (cc_reg)));
+       }
+    }
+}
index 41f1fcb..8f1dfa7 100644 (file)
@@ -5177,6 +5177,34 @@ follows:
 @end smallexample
 @end defmac
 
+@deftypefn {Target Hook} bool TARGET_FIXED_CONDITION_CODE_REGS (unsigned int *, unsigned int *)
+On targets which do not use @code{(cc0)}, and which use a hard
+register rather than a pseudo-register to hold condition codes, the
+regular CSE passes are often not able to identify cases in which the
+hard register is set to a common value.  Use this hook to enable a
+small pass which optimizes such cases.  This hook should return true
+to enable this pass, and it should set the integers to which its
+arguments point to the hard register numbers used for condition codes.
+When there is only one such register, as is true on most systems, the
+integer pointed to by the second argument should be set to
+@code{INVALID_REGNUM}.
+
+The default version of this hook returns false.
+@end deftypefn
+
+@deftypefn {Target Hook} enum machine_mode TARGET_CC_MODES_COMPATIBLE (enum machine_mode, enum machine_mode)
+On targets which use multiple condition code modes in class
+@code{MODE_CC}, it is sometimes the case that a comparison can be
+validly done in more than one mode.  On such a system, define this
+target hook to take two mode arguments and to return a mode in which
+both comparisons may be validly done.  If there is no such mode,
+return @code{VOIDmode}.
+
+The default version of this hook checks whether the modes are the
+same.  If they are, it returns that mode.  If they are different, it
+returns @code{VOIDmode}.
+@end deftypefn
+
 @node Costs
 @section Describing Relative Costs of Operations
 @cindex costs of instructions
index 939ed84..a8cd665 100644 (file)
@@ -1,5 +1,5 @@
 /* General-purpose hooks.
-   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
@@ -177,6 +177,13 @@ hook_bool_rtx_false (rtx a ATTRIBUTE_UNUSED)
 }
 
 bool
+hook_bool_uintp_uintp_false (unsigned int *a ATTRIBUTE_UNUSED,
+                            unsigned int *b ATTRIBUTE_UNUSED)
+{
+  return false;
+}
+
+bool
 hook_bool_rtx_int_int_intp_false (rtx a ATTRIBUTE_UNUSED,
                                  int b ATTRIBUTE_UNUSED,
                                  int c ATTRIBUTE_UNUSED,
index 7711115..583b504 100644 (file)
@@ -1,5 +1,5 @@
 /* General-purpose hooks.
-   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
@@ -31,6 +31,7 @@ extern bool hook_bool_tree_hwi_hwi_tree_false (tree, HOST_WIDE_INT, HOST_WIDE_IN
 extern bool hook_bool_tree_hwi_hwi_tree_true (tree, HOST_WIDE_INT, HOST_WIDE_INT,
                                       tree);
 extern bool hook_bool_rtx_false (rtx);
+extern bool hook_bool_uintp_uintp_false (unsigned int *, unsigned int *);
 extern bool hook_bool_rtx_int_int_intp_false (rtx, int, int, int *);
 extern bool hook_bool_constcharptr_size_t_false (const char *, size_t);
 
index 7fde7ea..f093a00 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2013,6 +2013,7 @@ extern int cse_main (rtx, int, int, FILE *);
 #endif
 extern void cse_end_of_basic_block (rtx, struct cse_basic_block_data *,
                                    int, int, int);
+extern void cse_condition_code_reg (void);
 
 /* In jump.c */
 extern int comparison_dominates_p (enum rtx_code, enum rtx_code);
index 9ff668d..321cd08 100644 (file)
@@ -1,5 +1,5 @@
 /* Default initializers for a generic GCC target.
-   Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
 
 This program is free software; you can redistribute it and/or modify it
 under the terms of the GNU General Public License as published by the
@@ -314,6 +314,10 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 #define TARGET_ENCODE_SECTION_INFO default_encode_section_info
 #endif
 
+#define TARGET_FIXED_CONDITION_CODE_REGS hook_bool_uintp_uintp_false
+
+#define TARGET_CC_MODES_COMPATIBLE default_cc_modes_compatible
+
 #define TARGET_MACHINE_DEPENDENT_REORG 0
 
 #define TARGET_BUILD_BUILTIN_VA_LIST std_build_builtin_va_list
@@ -380,6 +384,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   TARGET_RTX_COSTS,                            \
   TARGET_ADDRESS_COST,                         \
   TARGET_DWARF_REGISTER_SPAN,                   \
+  TARGET_FIXED_CONDITION_CODE_REGS,            \
+  TARGET_CC_MODES_COMPATIBLE,                  \
   TARGET_MACHINE_DEPENDENT_REORG,              \
   TARGET_BUILD_BUILTIN_VA_LIST,                        \
   TARGET_GET_PCH_VALIDITY,                     \
index 787d203..21a12f0 100644 (file)
@@ -377,6 +377,23 @@ struct gcc_target
      hook should return NULL_RTX.  */
   rtx (* dwarf_register_span) (rtx);
 
+  /* Fetch the fixed register(s) which hold condition codes, for
+     targets where it makes sense to look for duplicate assignments to
+     the condition codes.  This should return true if there is such a
+     register, false otherwise.  The arguments should be set to the
+     fixed register numbers.  Up to two condition code registers are
+     supported.  If there is only one for this target, the int pointed
+     at by the second argument should be set to -1.  */
+  bool (* fixed_condition_code_regs) (unsigned int *, unsigned int *);
+
+  /* If two condition code modes are compatible, return a condition
+     code mode which is compatible with both, such that a comparison
+     done in the returned mode will work for both of the original
+     modes.  If the condition code modes are not compatible, return
+     VOIDmode.  */
+  enum machine_mode (* cc_modes_compatible) (enum machine_mode,
+                                            enum machine_mode);
+
   /* Do machine-dependent code transformations.  Called just before
      delayed-branch scheduling.  */
   void (* machine_dependent_reorg) (void);
index eaed481..308ada6 100644 (file)
@@ -70,6 +70,14 @@ default_external_libcall (rtx fun ATTRIBUTE_UNUSED)
 #endif
 }
 
+enum machine_mode
+default_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
+{
+  if (m1 == m2)
+    return m1;
+  return VOIDmode;
+}
+
 bool
 default_promote_function_args (tree fntype ATTRIBUTE_UNUSED)
 {
index e5c5a2a..63525fe 100644 (file)
@@ -1,5 +1,5 @@
 /* Default target hook functions.
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -20,6 +20,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 extern void default_external_libcall (rtx);
 
+extern enum machine_mode default_cc_modes_compatible (enum machine_mode,
+                                                     enum machine_mode);
+
 extern bool default_promote_function_args (tree);
 extern bool default_promote_function_return (tree);
 extern bool default_promote_prototypes (tree);
index 05e753a..4d16201 100644 (file)
@@ -2902,6 +2902,13 @@ rest_of_handle_cse2 (tree decl, rtx insns)
     dump_flow_info (rtl_dump_file);
   /* CFG is no longer maintained up-to-date.  */
   tem = cse_main (insns, max_reg_num (), 1, rtl_dump_file);
+
+  /* Run a pass to eliminate duplicated assignments to condition code
+     registers.  We have to run this after bypass_jumps, because it
+     makes it harder for that pass to determine whether a jump can be
+     bypassed safely.  */
+  cse_condition_code_reg ();
+
   purge_all_dead_edges (0);
   delete_trivially_dead_insns (insns, max_reg_num ());