OSDN Git Service

* combine.c (make_extraction, force_to_mode): Avoid warning on
[pf3gnuchains/gcc-fork.git] / gcc / combine.c
index bc24ce9..f6b8867 100644 (file)
@@ -1,5 +1,5 @@
 /* Optimize by combining instructions for GNU compiler.
-   Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 92-98, 1999, 2000 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -350,72 +350,74 @@ static struct undobuf undobuf;
 
 static int n_occurrences;
 
-static void do_SUBST                   PROTO((rtx *, rtx));
-static void do_SUBST_INT               PROTO((int *, int));
-static void init_reg_last_arrays       PROTO((void));
-static void setup_incoming_promotions   PROTO((void));
-static void set_nonzero_bits_and_sign_copies  PROTO((rtx, rtx, void *));
-static int can_combine_p       PROTO((rtx, rtx, rtx, rtx, rtx *, rtx *));
-static int sets_function_arg_p PROTO((rtx));
-static int combinable_i3pat    PROTO((rtx, rtx *, rtx, rtx, int, rtx *));
-static int contains_muldiv     PROTO((rtx));
-static rtx try_combine         PROTO((rtx, rtx, rtx));
-static void undo_all           PROTO((void));
-static void undo_commit                PROTO((void));
-static rtx *find_split_point   PROTO((rtx *, rtx));
-static rtx subst               PROTO((rtx, rtx, rtx, int, int));
-static rtx combine_simplify_rtx        PROTO((rtx, enum machine_mode, int, int));
-static rtx simplify_if_then_else  PROTO((rtx));
-static rtx simplify_set                PROTO((rtx));
-static rtx simplify_logical    PROTO((rtx, int));
-static rtx expand_compound_operation  PROTO((rtx));
-static rtx expand_field_assignment  PROTO((rtx));
-static rtx make_extraction     PROTO((enum machine_mode, rtx, int, rtx, int,
-                                      int, int, int));
-static rtx extract_left_shift  PROTO((rtx, int));
-static rtx make_compound_operation  PROTO((rtx, enum rtx_code));
-static int get_pos_from_mask   PROTO((unsigned HOST_WIDE_INT, int *));
-static rtx force_to_mode       PROTO((rtx, enum machine_mode,
-                                      unsigned HOST_WIDE_INT, rtx, int));
-static rtx if_then_else_cond   PROTO((rtx, rtx *, rtx *));
-static rtx known_cond          PROTO((rtx, enum rtx_code, rtx, rtx));
-static int rtx_equal_for_field_assignment_p PROTO((rtx, rtx));
-static rtx make_field_assignment  PROTO((rtx));
-static rtx apply_distributive_law  PROTO((rtx));
-static rtx simplify_and_const_int  PROTO((rtx, enum machine_mode, rtx,
-                                         unsigned HOST_WIDE_INT));
-static unsigned HOST_WIDE_INT nonzero_bits  PROTO((rtx, enum machine_mode));
-static int num_sign_bit_copies  PROTO((rtx, enum machine_mode));
-static int merge_outer_ops     PROTO((enum rtx_code *, HOST_WIDE_INT *,
-                                      enum rtx_code, HOST_WIDE_INT,
-                                      enum machine_mode, int *));
-static rtx simplify_shift_const        PROTO((rtx, enum rtx_code, enum machine_mode,
-                                      rtx, int));
-static int recog_for_combine   PROTO((rtx *, rtx, rtx *));
-static rtx gen_lowpart_for_combine  PROTO((enum machine_mode, rtx));
-static rtx gen_rtx_combine PVPROTO((enum rtx_code code, enum machine_mode mode,
-                                 ...));
-static rtx gen_binary          PROTO((enum rtx_code, enum machine_mode,
-                                      rtx, rtx));
-static rtx gen_unary           PROTO((enum rtx_code, enum machine_mode,
-                                      enum machine_mode, rtx));
-static enum rtx_code simplify_comparison  PROTO((enum rtx_code, rtx *, rtx *));
-static int reversible_comparison_p  PROTO((rtx));
-static void update_table_tick  PROTO((rtx));
-static void record_value_for_reg  PROTO((rtx, rtx, rtx));
-static void record_dead_and_set_regs_1  PROTO((rtx, rtx, void *));
-static void record_dead_and_set_regs  PROTO((rtx));
-static int get_last_value_validate  PROTO((rtx *, rtx, int, int));
-static rtx get_last_value      PROTO((rtx));
-static int use_crosses_set_p   PROTO((rtx, int));
-static void reg_dead_at_p_1    PROTO((rtx, rtx, void *));
-static int reg_dead_at_p       PROTO((rtx, rtx));
-static void move_deaths                PROTO((rtx, rtx, int, rtx, rtx *));
-static int reg_bitfield_target_p  PROTO((rtx, rtx));
-static void distribute_notes   PROTO((rtx, rtx, rtx, rtx, rtx, rtx));
-static void distribute_links   PROTO((rtx));
-static void mark_used_regs_combine PROTO((rtx));
-static int insn_cuid           PROTO((rtx));
+static void do_SUBST                   PARAMS ((rtx *, rtx));
+static void do_SUBST_INT               PARAMS ((int *, int));
+static void init_reg_last_arrays       PARAMS ((void));
+static void setup_incoming_promotions   PARAMS ((void));
+static void set_nonzero_bits_and_sign_copies  PARAMS ((rtx, rtx, void *));
+static int can_combine_p       PARAMS ((rtx, rtx, rtx, rtx, rtx *, rtx *));
+static int sets_function_arg_p PARAMS ((rtx));
+static int combinable_i3pat    PARAMS ((rtx, rtx *, rtx, rtx, int, rtx *));
+static int contains_muldiv     PARAMS ((rtx));
+static rtx try_combine         PARAMS ((rtx, rtx, rtx));
+static void undo_all           PARAMS ((void));
+static void undo_commit                PARAMS ((void));
+static rtx *find_split_point   PARAMS ((rtx *, rtx));
+static rtx subst               PARAMS ((rtx, rtx, rtx, int, int));
+static rtx combine_simplify_rtx        PARAMS ((rtx, enum machine_mode, int, int));
+static rtx simplify_if_then_else  PARAMS ((rtx));
+static rtx simplify_set                PARAMS ((rtx));
+static rtx simplify_logical    PARAMS ((rtx, int));
+static rtx expand_compound_operation  PARAMS ((rtx));
+static rtx expand_field_assignment  PARAMS ((rtx));
+static rtx make_extraction     PARAMS ((enum machine_mode, rtx, int, rtx, int,
+                                        int, int, int));
+static rtx extract_left_shift  PARAMS ((rtx, int));
+static rtx make_compound_operation  PARAMS ((rtx, enum rtx_code));
+static int get_pos_from_mask   PARAMS ((unsigned HOST_WIDE_INT, int *));
+static rtx force_to_mode       PARAMS ((rtx, enum machine_mode,
+                                        unsigned HOST_WIDE_INT, rtx, int));
+static rtx if_then_else_cond   PARAMS ((rtx, rtx *, rtx *));
+static rtx known_cond          PARAMS ((rtx, enum rtx_code, rtx, rtx));
+static int rtx_equal_for_field_assignment_p PARAMS ((rtx, rtx));
+static rtx make_field_assignment  PARAMS ((rtx));
+static rtx apply_distributive_law  PARAMS ((rtx));
+static rtx simplify_and_const_int  PARAMS ((rtx, enum machine_mode, rtx,
+                                           unsigned HOST_WIDE_INT));
+static unsigned HOST_WIDE_INT nonzero_bits  PARAMS ((rtx, enum machine_mode));
+static int num_sign_bit_copies  PARAMS ((rtx, enum machine_mode));
+static int merge_outer_ops     PARAMS ((enum rtx_code *, HOST_WIDE_INT *,
+                                        enum rtx_code, HOST_WIDE_INT,
+                                        enum machine_mode, int *));
+static rtx simplify_shift_const        PARAMS ((rtx, enum rtx_code, enum machine_mode,
+                                        rtx, int));
+static int recog_for_combine   PARAMS ((rtx *, rtx, rtx *));
+static rtx gen_lowpart_for_combine  PARAMS ((enum machine_mode, rtx));
+static rtx gen_rtx_combine PARAMS ((enum rtx_code code, enum machine_mode mode,
+                                   ...));
+static rtx gen_binary          PARAMS ((enum rtx_code, enum machine_mode,
+                                        rtx, rtx));
+static rtx gen_unary           PARAMS ((enum rtx_code, enum machine_mode,
+                                        enum machine_mode, rtx));
+static enum rtx_code simplify_comparison  PARAMS ((enum rtx_code, rtx *, rtx *));
+static int reversible_comparison_p  PARAMS ((rtx));
+static void update_table_tick  PARAMS ((rtx));
+static void record_value_for_reg  PARAMS ((rtx, rtx, rtx));
+static void check_promoted_subreg PARAMS ((rtx, rtx));
+static void record_dead_and_set_regs_1  PARAMS ((rtx, rtx, void *));
+static void record_dead_and_set_regs  PARAMS ((rtx));
+static int get_last_value_validate  PARAMS ((rtx *, rtx, int, int));
+static rtx get_last_value      PARAMS ((rtx));
+static int use_crosses_set_p   PARAMS ((rtx, int));
+static void reg_dead_at_p_1    PARAMS ((rtx, rtx, void *));
+static int reg_dead_at_p       PARAMS ((rtx, rtx));
+static void move_deaths                PARAMS ((rtx, rtx, int, rtx, rtx *));
+static int reg_bitfield_target_p  PARAMS ((rtx, rtx));
+static void distribute_notes   PARAMS ((rtx, rtx, rtx, rtx, rtx, rtx));
+static void distribute_links   PARAMS ((rtx));
+static void mark_used_regs_combine PARAMS ((rtx));
+static int insn_cuid           PARAMS ((rtx));
+static void record_promoted_value PARAMS ((rtx, rtx));
 \f
 /* Substitute NEWVAL, an rtx expression, into INTO, a place in some
    insn.  The substitution can be undone by undo_all.  If INTO is already
@@ -608,6 +610,10 @@ combine_instructions (f, nregs)
 
       else if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
        {
+         /* See if we know about function return values before this
+            insn based upon SUBREG flags.  */
+         check_promoted_subreg (insn, PATTERN (insn));
+
          /* Try this insn with each insn it links back to.  */
 
          for (links = LOG_LINKS (insn); links; links = XEXP (links, 1))
@@ -2386,6 +2392,18 @@ try_combine (i3, i2, i1)
       distribute_notes (new_other_notes, undobuf.other_insn,
                        undobuf.other_insn, NULL_RTX, NULL_RTX, NULL_RTX);
     }
+#ifdef HAVE_cc0
+  /* If I2 is the setter CC0 and I3 is the user CC0 then check whether 
+     they are adjacent to each other or not. */
+  {
+    rtx p = prev_nonnote_insn (i3);
+    if (p && p != i2 && GET_CODE (p) == INSN && newi2pat && sets_cc0_p (newi2pat))
+      {
+        undo_all ();
+        return 0;
+      }
+    }
+#endif 
 
   /* We now know that we can do this combination.  Merge the insns and 
      update the status of registers and LOG_LINKS.  */
@@ -2448,19 +2466,22 @@ try_combine (i3, i2, i1)
 
     if (i3_subst_into_i2)
       {
-       for (i = 0; i < XVECLEN (PATTERN (i2), 0); i++)
-         if (GET_CODE (SET_DEST (XVECEXP (PATTERN (i2), 0, i))) == REG
-             && SET_DEST (XVECEXP (PATTERN (i2), 0, i)) != i2dest
-             && ! find_reg_note (i2, REG_UNUSED,
-                                 SET_DEST (XVECEXP (PATTERN (i2), 0, i))))
-           for (temp = NEXT_INSN (i2);
-                temp && (this_basic_block == n_basic_blocks - 1
-                         || BLOCK_HEAD (this_basic_block) != temp);
-                temp = NEXT_INSN (temp))
-             if (temp != i3 && GET_RTX_CLASS (GET_CODE (temp)) == 'i')
-               for (link = LOG_LINKS (temp); link; link = XEXP (link, 1))
-                 if (XEXP (link, 0) == i2)
-                   XEXP (link, 0) = i3;
+       if (GET_CODE (PATTERN (i2)) == PARALLEL)
+         {
+           for (i = 0; i < XVECLEN (PATTERN (i2), 0); i++)
+             if (GET_CODE (SET_DEST (XVECEXP (PATTERN (i2), 0, i))) == REG
+                 && SET_DEST (XVECEXP (PATTERN (i2), 0, i)) != i2dest
+                 && ! find_reg_note (i2, REG_UNUSED,
+                                     SET_DEST (XVECEXP (PATTERN (i2), 0, i))))
+               for (temp = NEXT_INSN (i2);
+                    temp && (this_basic_block == n_basic_blocks - 1
+                             || BLOCK_HEAD (this_basic_block) != temp);
+                    temp = NEXT_INSN (temp))
+                 if (temp != i3 && GET_RTX_CLASS (GET_CODE (temp)) == 'i')
+                   for (link = LOG_LINKS (temp); link; link = XEXP (link, 1))
+                     if (XEXP (link, 0) == i2)
+                       XEXP (link, 0) = i3;
+         }
 
        if (i3notes)
          {
@@ -2634,10 +2655,6 @@ try_combine (i3, i2, i1)
          {
            regno = REGNO (i2dest);
            REG_N_SETS (regno)--;
-           if (REG_N_SETS (regno) == 0
-               && ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start,
-                                     regno))
-             REG_N_REFS (regno) = 0;
          }
       }
 
@@ -2657,10 +2674,6 @@ try_combine (i3, i2, i1)
        if (! added_sets_1 && ! i1dest_in_i1src)
          {
            REG_N_SETS (regno)--;
-           if (REG_N_SETS (regno) == 0
-               && ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start,
-                                     regno))
-             REG_N_REFS (regno) = 0;
          }
       }
 
@@ -3555,9 +3568,13 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
       temp = simplify_relational_operation (code, op0_mode,
                                            XEXP (x, 0), XEXP (x, 1));
 #ifdef FLOAT_STORE_FLAG_VALUE
-      if (temp != 0 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
-       temp = ((temp == const0_rtx) ? CONST0_RTX (GET_MODE (x))
-               : immed_real_const_1 (FLOAT_STORE_FLAG_VALUE, GET_MODE (x)));
+      if (temp != 0 && GET_MODE_CLASS (mode) == MODE_FLOAT)
+       {
+         if (temp == const0_rtx)
+           temp = CONST0_RTX (mode);
+         else
+           temp = immed_real_const_1 (FLOAT_STORE_FLAG_VALUE (mode), mode);
+       }
 #endif
       break;
     case 'c':
@@ -3823,8 +3840,8 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
         perform the above simplification.  */
 
       if (STORE_FLAG_VALUE == -1
-         && XEXP (x, 1) == const1_rtx
          && GET_CODE (XEXP (x, 0)) == ASHIFTRT
+         && XEXP (x, 1) == const1_rtx
          && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
          && INTVAL (XEXP (XEXP (x, 0), 1)) == GET_MODE_BITSIZE (mode) - 1)
        return gen_rtx_combine (GE, mode, XEXP (XEXP (x, 0), 0), const0_rtx);
@@ -4190,7 +4207,8 @@ combine_simplify_rtx (x, op0_mode, last, in_dest)
                         gen_binary (MULT, mode,
                                     XEXP (XEXP (x, 0), 0), XEXP (x, 1)),
                         gen_binary (MULT, mode,
-                                    XEXP (XEXP (x, 0), 1), XEXP (x, 1))));
+                                    XEXP (XEXP (x, 0), 1),
+                                    copy_rtx (XEXP (x, 1)))));
 
          if (GET_CODE (x) != MULT)
            return x;
@@ -5199,7 +5217,8 @@ simplify_logical (x, last)
          x = apply_distributive_law
            (gen_binary (GET_CODE (op0), mode,
                         gen_binary (AND, mode, XEXP (op0, 0), op1),
-                        gen_binary (AND, mode, XEXP (op0, 1), op1)));
+                        gen_binary (AND, mode, XEXP (op0, 1),
+                                    copy_rtx (op1))));
          if (GET_CODE (x) != AND)
            return x;
        }
@@ -5208,7 +5227,8 @@ simplify_logical (x, last)
        return apply_distributive_law
          (gen_binary (GET_CODE (op1), mode,
                       gen_binary (AND, mode, XEXP (op1, 0), op0),
-                      gen_binary (AND, mode, XEXP (op1, 1), op0)));
+                      gen_binary (AND, mode, XEXP (op1, 1),
+                                  copy_rtx (op0))));
 
       /* Similarly, taking advantage of the fact that
         (and (not A) (xor B C)) == (xor (ior A B) (ior A C))  */
@@ -5217,13 +5237,14 @@ simplify_logical (x, last)
        return apply_distributive_law
          (gen_binary (XOR, mode,
                       gen_binary (IOR, mode, XEXP (op0, 0), XEXP (op1, 0)),
-                      gen_binary (IOR, mode, XEXP (op0, 0), XEXP (op1, 1))));
+                      gen_binary (IOR, mode, copy_rtx (XEXP (op0, 0)),
+                                  XEXP (op1, 1))));
                                                            
       else if (GET_CODE (op1) == NOT && GET_CODE (op0) == XOR)
        return apply_distributive_law
          (gen_binary (XOR, mode,
                       gen_binary (IOR, mode, XEXP (op1, 0), XEXP (op0, 0)),
-                      gen_binary (IOR, mode, XEXP (op1, 0), XEXP (op0, 1))));
+                      gen_binary (IOR, mode, copy_rtx (XEXP (op1, 0)), XEXP (op0, 1))));
       break;
 
     case IOR:
@@ -5249,7 +5270,8 @@ simplify_logical (x, last)
          x = apply_distributive_law
            (gen_binary (AND, mode,
                         gen_binary (IOR, mode, XEXP (op0, 0), op1),
-                        gen_binary (IOR, mode, XEXP (op0, 1), op1)));
+                        gen_binary (IOR, mode, XEXP (op0, 1),
+                                    copy_rtx (op1))));
 
          if (GET_CODE (x) != IOR)
            return x;
@@ -5260,7 +5282,8 @@ simplify_logical (x, last)
          x = apply_distributive_law
            (gen_binary (AND, mode,
                         gen_binary (IOR, mode, XEXP (op1, 0), op0),
-                        gen_binary (IOR, mode, XEXP (op1, 1), op0)));
+                        gen_binary (IOR, mode, XEXP (op1, 1),
+                                    copy_rtx (op0))));
 
          if (GET_CODE (x) != IOR)
            return x;
@@ -5480,6 +5503,20 @@ expand_compound_operation (x)
     default:
       return x;
     }
+  /* Convert sign extension to zero extension, if we know that the high
+     bit is not set, as this is easier to optimize.  It will be converted
+     back to cheaper alternative in make_extraction.  */
+  if (GET_CODE (x) == SIGN_EXTEND
+      && (GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
+         && ((nonzero_bits (XEXP (x, 0), GET_MODE (XEXP (x, 0)))
+               & ~ (((unsigned HOST_WIDE_INT)
+                     GET_MODE_MASK (GET_MODE (XEXP (x, 0))))
+                    >> 1))
+              == 0)))
+    {
+      rtx temp = gen_rtx_ZERO_EXTEND (GET_MODE (x), XEXP (x, 0));
+      return expand_compound_operation (temp);
+    }
 
   /* We can optimize some special cases of ZERO_EXTEND.  */
   if (GET_CODE (x) == ZERO_EXTEND)
@@ -5527,30 +5564,6 @@ expand_compound_operation (x)
              & ~ GET_MODE_MASK (GET_MODE (XEXP (x, 0)))) == 0)
        return SUBREG_REG (XEXP (x, 0));
 
-      /* If sign extension is cheaper than zero extension, then use it
-        if we know that no extraneous bits are set, and that the high
-        bit is not set.  */
-      if (flag_expensive_optimizations
-         && ((GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT
-              && ((nonzero_bits (XEXP (x, 0), GET_MODE (x))
-                   & ~ (((unsigned HOST_WIDE_INT)
-                         GET_MODE_MASK (GET_MODE (XEXP (x, 0))))
-                        >> 1))
-                  == 0))
-             || (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
-                 && (GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0)))
-                     <= HOST_BITS_PER_WIDE_INT)
-                 && (((HOST_WIDE_INT) STORE_FLAG_VALUE
-                      & ~ (((unsigned HOST_WIDE_INT)
-                            GET_MODE_MASK (GET_MODE (XEXP (x, 0))))
-                           >> 1))
-                     == 0))))
-       {
-         rtx temp = gen_rtx_SIGN_EXTEND (GET_MODE (x), XEXP (x, 0));
-
-         if (rtx_cost (temp, SET) < rtx_cost (x, SET))
-           return expand_compound_operation (temp);
-       }
     }
 
   /* If we reach here, we want to return a pair of shifts.  The inner
@@ -5660,6 +5673,8 @@ expand_field_assignment (x)
       /* A SUBREG between two modes that occupy the same numbers of words
         can be done by moving the SUBREG to the source.  */
       else if (GET_CODE (SET_DEST (x)) == SUBREG
+              /* We need SUBREGs to compute nonzero_bits properly.  */
+              && nonzero_sign_valid
               && (((GET_MODE_SIZE (GET_MODE (SET_DEST (x)))
                     + (UNITS_PER_WORD - 1)) / UNITS_PER_WORD)
                   == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (SET_DEST (x))))
@@ -5876,7 +5891,7 @@ make_extraction (mode, inner, pos, pos_rtx, len,
        new = force_to_mode (inner, tmode,
                             len >= HOST_BITS_PER_WIDE_INT
                             ? GET_MODE_MASK (tmode)
-                            : ((HOST_WIDE_INT) 1 << len) - 1,
+                            : ((unsigned HOST_WIDE_INT) 1 << len) - 1,
                             NULL_RTX, 0);
 
       /* If this extraction is going into the destination of a SET, 
@@ -5888,12 +5903,35 @@ make_extraction (mode, inner, pos, pos_rtx, len,
                   ? gen_rtx_CLOBBER (tmode, const0_rtx)
                   : gen_rtx_combine (STRICT_LOW_PART, VOIDmode, new)));
 
+      if (mode == tmode)
+       return new;
+
+      /* If we know that no extraneous bits are set, and that the high
+        bit is not set, convert the extraction to the cheaper of
+        sign and zero extension, that are equivalent in these cases.  */
+      if (flag_expensive_optimizations
+         && (GET_MODE_BITSIZE (tmode) <= HOST_BITS_PER_WIDE_INT
+             && ((nonzero_bits (new, tmode)
+                  & ~ (((unsigned HOST_WIDE_INT)
+                        GET_MODE_MASK (tmode))
+                       >> 1))
+                 == 0)))
+       {
+         rtx temp = gen_rtx_ZERO_EXTEND (mode, new);
+         rtx temp1 = gen_rtx_SIGN_EXTEND (mode, new);
+
+         /* Prefer ZERO_EXTENSION, since it gives more information to
+            backends.  */
+         if (rtx_cost (temp, SET) < rtx_cost (temp1, SET))
+           return temp;
+         return temp1;
+       }
+
       /* Otherwise, sign- or zero-extend unless we already are in the
         proper mode.  */
 
-      return (mode == tmode ? new
-             : gen_rtx_combine (unsignedp ? ZERO_EXTEND : SIGN_EXTEND,
-                                mode, new));
+      return (gen_rtx_combine (unsignedp ? ZERO_EXTEND : SIGN_EXTEND,
+                              mode, new));
     }
 
   /* Unless this is a COMPARE or we have a funny memory reference,
@@ -6074,7 +6112,8 @@ make_extraction (mode, inner, pos, pos_rtx, len,
                             pos_rtx
                             || len + orig_pos >= HOST_BITS_PER_WIDE_INT
                             ? GET_MODE_MASK (wanted_inner_mode)
-                            : (((HOST_WIDE_INT) 1 << len) - 1) << orig_pos,
+                            : ((((unsigned HOST_WIDE_INT) 1 << len) - 1)
+                               << orig_pos),
                             NULL_RTX, 0);
     }
 
@@ -6082,7 +6121,30 @@ make_extraction (mode, inner, pos, pos_rtx, len,
      have to zero extend.  Otherwise, we can just use a SUBREG.  */
   if (pos_rtx != 0
       && GET_MODE_SIZE (pos_mode) > GET_MODE_SIZE (GET_MODE (pos_rtx)))
-    pos_rtx = gen_rtx_combine (ZERO_EXTEND, pos_mode, pos_rtx);
+    {
+      rtx temp = gen_rtx_combine (ZERO_EXTEND, pos_mode, pos_rtx);
+
+      /* If we know that no extraneous bits are set, and that the high
+        bit is not set, convert extraction to cheaper one - eighter
+        SIGN_EXTENSION or ZERO_EXTENSION, that are equivalent in these
+        cases.  */
+      if (flag_expensive_optimizations
+         && (GET_MODE_BITSIZE (GET_MODE (pos_rtx)) <= HOST_BITS_PER_WIDE_INT
+             && ((nonzero_bits (pos_rtx, GET_MODE (pos_rtx))
+                  & ~ (((unsigned HOST_WIDE_INT)
+                        GET_MODE_MASK (GET_MODE (pos_rtx)))
+                       >> 1))
+                 == 0)))
+       {
+         rtx temp1 = gen_rtx_SIGN_EXTEND (pos_mode, pos_rtx);
+
+         /* Preffer ZERO_EXTENSION, since it gives more information to
+            backends.  */
+         if (rtx_cost (temp1, SET) < rtx_cost (temp, SET))
+           temp = temp1;
+       }
+      pos_rtx = temp;
+    }
   else if (pos_rtx != 0
           && GET_MODE_SIZE (pos_mode) < GET_MODE_SIZE (GET_MODE (pos_rtx)))
     pos_rtx = gen_lowpart_for_combine (pos_mode, pos_rtx);
@@ -6522,7 +6584,8 @@ force_to_mode (x, mode, mask, reg, just_select)
   if (op_mode)
     fuller_mask = (GET_MODE_BITSIZE (op_mode) >= HOST_BITS_PER_WIDE_INT
                   ? GET_MODE_MASK (op_mode)
-                  : ((HOST_WIDE_INT) 1 << (floor_log2 (mask) + 1)) - 1);
+                  : (((unsigned HOST_WIDE_INT) 1 << (floor_log2 (mask) + 1))
+                     - 1));
   else
     fuller_mask = ~ (HOST_WIDE_INT) 0;
 
@@ -6803,18 +6866,19 @@ force_to_mode (x, mode, mask, reg, just_select)
          && GET_MODE_BITSIZE (op_mode) <= HOST_BITS_PER_WIDE_INT)
        {
          rtx inner = XEXP (x, 0);
+         unsigned HOST_WIDE_INT inner_mask;
 
          /* Select the mask of the bits we need for the shift operand.  */
-         mask <<= INTVAL (XEXP (x, 1));
+         inner_mask = mask << INTVAL (XEXP (x, 1));
 
          /* We can only change the mode of the shift if we can do arithmetic
-            in the mode of the shift and MASK is no wider than the width of
-            OP_MODE.  */
+            in the mode of the shift and INNER_MASK is no wider than the
+            width of OP_MODE.  */
          if (GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT
-             || (mask & ~ GET_MODE_MASK (op_mode)) != 0)
+             || (inner_mask & ~ GET_MODE_MASK (op_mode)) != 0)
            op_mode = GET_MODE (x);
 
-         inner = force_to_mode (inner, op_mode, mask, reg, next_select);
+         inner = force_to_mode (inner, op_mode, inner_mask, reg, next_select);
 
          if (GET_MODE (x) != op_mode || inner != XEXP (x, 0))
            x = gen_binary (LSHIFTRT, op_mode, inner, XEXP (x, 1));
@@ -7171,7 +7235,10 @@ if_then_else_cond (x, ptrue, pfalse)
           && 0 != (cond0 = if_then_else_cond (SUBREG_REG (x),
                                               &true0, &false0)))
     {
-      if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) > UNITS_PER_WORD
+      if ((GET_CODE (SUBREG_REG (x)) == REG
+          || GET_CODE (SUBREG_REG (x)) == MEM
+          || CONSTANT_P (SUBREG_REG (x)))
+         && GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) > UNITS_PER_WORD
          && (WORDS_BIG_ENDIAN || SUBREG_WORD (x) != 0))
        {
          true0 = operand_subword (true0, SUBREG_WORD (x), 0, mode);
@@ -7261,11 +7328,17 @@ known_cond (x, cond, reg, val)
       if (rtx_equal_p (XEXP (x, 0), reg) && rtx_equal_p (XEXP (x, 1), val))
        {
          if (GET_RTX_CLASS (code) == '<')
-           return (comparison_dominates_p (cond, code) ? const_true_rtx
-                   : (comparison_dominates_p (cond,
-                                              reverse_condition (code))
-                      ? const0_rtx : x));
+           {
+             if (comparison_dominates_p (cond, code))
+               return const_true_rtx;
 
+             code = reverse_condition (code);
+             if (code != UNKNOWN
+                 && comparison_dominates_p (cond, code))
+               return const0_rtx;
+             else
+               return x;
+           }
          else if (code == SMAX || code == SMIN
                   || code == UMIN || code == UMAX)
            {
@@ -7454,7 +7527,7 @@ make_field_assignment (x)
                       mode,
                       GET_MODE_BITSIZE (mode) >= HOST_BITS_PER_WIDE_INT
                       ? GET_MODE_MASK (mode)
-                      : ((HOST_WIDE_INT) 1 << len) - 1,
+                      : ((unsigned HOST_WIDE_INT) 1 << len) - 1,
                       dest, 0);
 
   return gen_rtx_combine (SET, VOIDmode, assign, src);
@@ -8039,8 +8112,10 @@ nonzero_bits (x, mode)
          /* If this is a typical RISC machine, we only have to worry
             about the way loads are extended.  */
          if (LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) == SIGN_EXTEND
-             ? (nonzero
-                & (1L << (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) - 1)))
+             ? (((nonzero
+                  & (((unsigned HOST_WIDE_INT) 1
+                      << (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) - 1))))
+                 != 0))
              : LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (x))) != ZERO_EXTEND)
 #endif
            {
@@ -9547,7 +9622,7 @@ gen_lowpart_for_combine (mode, x)
 
 /*VARARGS2*/
 static rtx
-gen_rtx_combine VPROTO((enum rtx_code code, enum machine_mode mode, ...))
+gen_rtx_combine VPARAMS ((enum rtx_code code, enum machine_mode mode, ...))
 {
 #ifndef ANSI_PROTOTYPES
   enum rtx_code code;
@@ -10313,6 +10388,14 @@ simplify_comparison (code, pop0, pop1)
          break;
 
        case MINUS:
+         /* (op (minus A B) 0) -> (op A B) */
+         if (op1 == const0_rtx)
+           {
+             op1 = XEXP (op0, 1);
+             op0 = XEXP (op0, 0);
+             continue;
+           }
+
          /* (eq (minus A B) C) -> (eq A (plus B C)) or
             (eq B (minus A C)), whichever simplifies.  We can only do
             this for equality comparisons due to pathological cases involving
@@ -10792,7 +10875,8 @@ reversible_comparison_p (x)
 {
   if (TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
       || flag_fast_math
-      || GET_CODE (x) == NE || GET_CODE (x) == EQ)
+      || GET_CODE (x) == NE || GET_CODE (x) == EQ
+      || GET_CODE (x) == UNORDERED || GET_CODE (x) == ORDERED)
     return 1;
 
   switch (GET_MODE_CLASS (GET_MODE (XEXP (x, 0))))
@@ -11045,6 +11129,88 @@ record_dead_and_set_regs (insn)
 
   note_stores (PATTERN (insn), record_dead_and_set_regs_1, insn);
 }
+
+/* If a SUBREG has the promoted bit set, it is in fact a property of the
+   register present in the SUBREG, so for each such SUBREG go back and
+   adjust nonzero and sign bit information of the registers that are
+   known to have some zero/sign bits set.
+
+   This is needed because when combine blows the SUBREGs away, the
+   information on zero/sign bits is lost and further combines can be
+   missed because of that.  */
+
+static void
+record_promoted_value (insn, subreg)
+    rtx insn;
+    rtx subreg;
+{
+  rtx links, set;
+  int regno = REGNO (SUBREG_REG (subreg));
+  enum machine_mode mode = GET_MODE (subreg);
+
+  if (GET_MODE_BITSIZE (mode) >= HOST_BITS_PER_WIDE_INT)
+    return;
+
+  for (links = LOG_LINKS (insn); links; )
+    {
+      insn = XEXP (links, 0);
+      set = single_set (insn);
+
+      if (! set || GET_CODE (SET_DEST (set)) != REG
+         || REGNO (SET_DEST (set)) != regno
+         || GET_MODE (SET_DEST (set)) != GET_MODE (SUBREG_REG (subreg)))
+       {
+         links = XEXP (links, 1);
+         continue;
+       }
+
+      if (reg_last_set [regno] == insn)
+        {
+         if (SUBREG_PROMOTED_UNSIGNED_P (subreg))
+           reg_last_set_nonzero_bits [regno] &= GET_MODE_MASK (mode);
+        }
+
+      if (GET_CODE (SET_SRC (set)) == REG)
+       {
+         regno = REGNO (SET_SRC (set));
+         links = LOG_LINKS (insn);
+       }
+      else
+       break;
+    }
+}
+
+/* Scan X for promoted SUBREGs.  For each one found,
+   note what it implies to the registers used in it.  */
+
+static void
+check_promoted_subreg (insn, x)
+    rtx insn;
+    rtx x;
+{
+  if (GET_CODE (x) == SUBREG && SUBREG_PROMOTED_VAR_P (x)
+      && GET_CODE (SUBREG_REG (x)) == REG)
+    record_promoted_value (insn, x);
+  else
+    {
+      const char *format = GET_RTX_FORMAT (GET_CODE (x));
+      int i, j;
+
+      for (i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++)
+       switch (format [i])
+         {
+         case 'e':
+           check_promoted_subreg (insn, XEXP (x, i));
+           break;
+         case 'V':
+         case 'E':
+           if (XVEC (x, i) != 0)
+             for (j = 0; j < XVECLEN (x, i); j++)
+               check_promoted_subreg (insn, XVECEXP (x, i, j));
+           break;
+         }
+    }
+}
 \f
 /* Utility routine for the following function.  Verify that all the registers
    mentioned in *LOC are valid when *LOC was part of a value set when
@@ -11886,18 +12052,6 @@ distribute_notes (notes, from_insn, i3, i2, elim_i2, elim_i1)
          if (XEXP (note, 0) == elim_i2 || XEXP (note, 0) == elim_i1)
            break;
 
-         /* If the register is used in both I2 and I3 and it dies in I3, 
-            we might have added another reference to it.  If reg_n_refs
-            was 2, bump it to 3.  This has to be correct since the 
-            register must have been set somewhere.  The reason this is
-            done is because local-alloc.c treats 2 references as a 
-            special case.  */
-
-         if (place == i3 && i2 != 0 && GET_CODE (XEXP (note, 0)) == REG
-             && REG_N_REFS (REGNO (XEXP (note, 0)))== 2
-             && reg_referenced_p (XEXP (note, 0), PATTERN (i2)))
-           REG_N_REFS (REGNO (XEXP (note, 0))) = 3;
-
          if (place == 0)
            {
              basic_block bb = BASIC_BLOCK (this_basic_block);