2004-05-31 Paolo Bonzini <bonzini@gnu.org>
authorbonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 31 May 2004 06:59:47 +0000 (06:59 +0000)
committerbonzini <bonzini@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 31 May 2004 06:59:47 +0000 (06:59 +0000)
Revert this patch:
2004-05-27  Paolo Bonzini  <bonzini@gnu.org>

* combine.c (gen_binary): Remove.
(known_cond, simplify_shift_const
find_split_point, combine_simplify_rtx,
simplify_if_then_else, simplify_set,
simplify_logical, expand_field_assignment,
extract_left_shift, force_to_mode,
if_then_else_cond, apply_distributive_law,
simplify_and_const_int, simplify_shift_const,
gen_lowpart_for_combine, simplify_comparison,
reversed_comparison): Replace with
simplify_gen_binary, simplify_gen_relational or
distribute_and_simplify_rtx.
(distribute_and_simplify_rtx): New function.

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

gcc/ChangeLog
gcc/combine.c

index a76fd14..8ce27ff 100644 (file)
@@ -1,3 +1,22 @@
+2004-05-31  Paolo Bonzini  <bonzini@gnu.org>
+
+       Revert this patch:
+       2004-05-27  Paolo Bonzini  <bonzini@gnu.org>
+
+       * combine.c (gen_binary): Remove.
+       (known_cond, simplify_shift_const
+       find_split_point, combine_simplify_rtx,
+       simplify_if_then_else, simplify_set,
+       simplify_logical, expand_field_assignment,
+       extract_left_shift, force_to_mode,
+       if_then_else_cond, apply_distributive_law,
+       simplify_and_const_int, simplify_shift_const,
+       gen_lowpart_for_combine, simplify_comparison,
+       reversed_comparison): Replace with
+       simplify_gen_binary, simplify_gen_relational or
+       distribute_and_simplify_rtx.
+       (distribute_and_simplify_rtx): New function.
+
 2004-05-30  John David Anglin  <dave.anglin@nrc-cnrc.gc.ca>
 
        * pa.c (emit_move_sequence): Fix loading of non 14-bit CONST operands
 
        * cfgbuild.c (control_flow_insn_p):  Notice noreturn call
 
-2004-05-25  Paolo Bonzini  <bonzini@gnu.org>
+2004-05-27  Paolo Bonzini  <bonzini@gnu.org>
 
        * combine.c (gen_binary): Remove.
        (known_cond, simplify_shift_const
index eb07dbb..64af27c 100644 (file)
@@ -372,7 +372,6 @@ static rtx known_cond (rtx, enum rtx_code, rtx, rtx);
 static int rtx_equal_for_field_assignment_p (rtx, rtx);
 static rtx make_field_assignment (rtx);
 static rtx apply_distributive_law (rtx);
-static rtx distribute_and_simplify_rtx (rtx);
 static rtx simplify_and_const_int (rtx, enum machine_mode, rtx,
                                   unsigned HOST_WIDE_INT);
 static int merge_outer_ops (enum rtx_code *, HOST_WIDE_INT *, enum rtx_code,
@@ -381,6 +380,7 @@ static rtx simplify_shift_const     (rtx, enum rtx_code, enum machine_mode, rtx,
                                 int);
 static int recog_for_combine (rtx *, rtx, rtx *);
 static rtx gen_lowpart_for_combine (enum machine_mode, rtx);
+static rtx gen_binary (enum rtx_code, enum machine_mode, rtx, rtx);
 static enum rtx_code simplify_comparison (enum rtx_code, rtx *, rtx *);
 static void update_table_tick (rtx);
 static void record_value_for_reg (rtx, rtx, rtx);
@@ -3017,16 +3017,14 @@ find_split_point (rtx *loc, rtx insn)
 
          if (src == mask)
            SUBST (SET_SRC (x),
-                  simplify_gen_binary (IOR, mode, dest, GEN_INT (src << pos)));
+                  gen_binary (IOR, mode, dest, GEN_INT (src << pos)));
          else
-           {
-             rtx negmask = gen_int_mode (~(mask << pos), mode);
-             SUBST (SET_SRC (x),
-                    simplify_gen_binary (IOR, mode,
-                                         simplify_gen_binary (AND, mode,
-                                                              dest, negmask),
-                                         GEN_INT (src << pos)));
-           }
+           SUBST (SET_SRC (x),
+                  gen_binary (IOR, mode,
+                              gen_binary (AND, mode, dest,
+                                          gen_int_mode (~(mask << pos),
+                                                        mode)),
+                              GEN_INT (src << pos)));
 
          SUBST (SET_DEST (x), dest);
 
@@ -3601,7 +3599,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
       new = simplify_shift_const (NULL_RTX, ASHIFTRT, mode, new,
                                  INTVAL (XEXP (XEXP (x, 0), 1)));
 
-      SUBST (XEXP (x, 0), simplify_gen_binary (PLUS, mode, new, temp));
+      SUBST (XEXP (x, 0), gen_binary (PLUS, mode, new, temp));
     }
 
   /* If this is a simple operation applied to an IF_THEN_ELSE, try
@@ -3658,14 +3656,12 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
              /* If the result values are STORE_FLAG_VALUE and zero, we can
                 just make the comparison operation.  */
              if (true_rtx == const_true_rtx && false_rtx == const0_rtx)
-               x = simplify_gen_relational (cond_code, mode, VOIDmode,
-                                            cond, cop1);
+               x = gen_binary (cond_code, mode, cond, cop1);
              else if (true_rtx == const0_rtx && false_rtx == const_true_rtx
                       && ((reversed = reversed_comparison_code_parts
                                        (cond_code, cond, cop1, NULL))
                           != UNKNOWN))
-               x = simplify_gen_relational (reversed, mode, VOIDmode,
-                                            cond, cop1);
+               x = gen_binary (reversed, mode, cond, cop1);
 
              /* Likewise, we can make the negate of a comparison operation
                 if the result values are - STORE_FLAG_VALUE and zero.  */
@@ -3673,9 +3669,8 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
                       && INTVAL (true_rtx) == - STORE_FLAG_VALUE
                       && false_rtx == const0_rtx)
                x = simplify_gen_unary (NEG, mode,
-                                       simplify_gen_relational (cond_code,
-                                                                mode, VOIDmode,
-                                                                cond, cop1),
+                                       gen_binary (cond_code, mode, cond,
+                                                   cop1),
                                        mode);
              else if (GET_CODE (false_rtx) == CONST_INT
                       && INTVAL (false_rtx) == - STORE_FLAG_VALUE
@@ -3684,17 +3679,13 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
                                        (cond_code, cond, cop1, NULL))
                           != UNKNOWN))
                x = simplify_gen_unary (NEG, mode,
-                                       simplify_gen_relational (reversed,
-                                                                mode, VOIDmode,
-                                                                cond, cop1),
+                                       gen_binary (reversed, mode,
+                                                   cond, cop1),
                                        mode);
              else
                return gen_rtx_IF_THEN_ELSE (mode,
-                                            simplify_gen_relational (cond_code,
-                                                                     mode,
-                                                                     VOIDmode,
-                                                                     cond,
-                                                                     cop1),
+                                            gen_binary (cond_code, VOIDmode,
+                                                        cond, cop1),
                                             true_rtx, false_rtx);
 
              code = GET_CODE (x);
@@ -3797,7 +3788,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
            }
 
          if (inner)
-           return simplify_gen_binary (code, mode, other, inner);
+           return gen_binary (code, mode, other, inner);
        }
     }
 
@@ -3899,8 +3890,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
       if (GET_CODE (XEXP (x, 0)) == XOR
          && XEXP (XEXP (x, 0), 1) == const1_rtx
          && nonzero_bits (XEXP (XEXP (x, 0), 0), mode) == 1)
-       return simplify_gen_binary (PLUS, mode, XEXP (XEXP (x, 0), 0),
-                                   constm1_rtx);
+       return gen_binary (PLUS, mode, XEXP (XEXP (x, 0), 0), constm1_rtx);
 
       temp = expand_compound_operation (XEXP (x, 0));
 
@@ -4128,9 +4118,8 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
 
          in1 = XEXP (XEXP (XEXP (x, 0), 0), 0);
          in2 = XEXP (XEXP (x, 0), 1);
-         return simplify_gen_binary (MINUS, mode, XEXP (x, 1),
-                                     simplify_gen_binary (MULT, mode,
-                                                          in1, in2));
+         return gen_binary (MINUS, mode, XEXP (x, 1),
+                            gen_binary (MULT, mode, in1, in2));
        }
 
       /* If we have (plus (plus (A const) B)), associate it so that CONST is
@@ -4139,11 +4128,10 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
         they are now checked elsewhere.  */
       if (GET_CODE (XEXP (x, 0)) == PLUS
          && CONSTANT_ADDRESS_P (XEXP (XEXP (x, 0), 1)))
-       return simplify_gen_binary (PLUS, mode,
-                                   simplify_gen_binary (PLUS, mode,
-                                                        XEXP (XEXP (x, 0), 0),
-                                                        XEXP (x, 1)),
-                                   XEXP (XEXP (x, 0), 1));
+       return gen_binary (PLUS, mode,
+                          gen_binary (PLUS, mode, XEXP (XEXP (x, 0), 0),
+                                      XEXP (x, 1)),
+                          XEXP (XEXP (x, 0), 1));
 
       /* (plus (xor (and <foo> (const_int pow2 - 1)) <c>) <-c>)
         when c is (const_int (pow2 + 1) / 2) is a sign extension of a
@@ -4209,7 +4197,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
              & nonzero_bits (XEXP (x, 1), mode)) == 0)
        {
          /* Try to simplify the expression further.  */
-         rtx tor = simplify_gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1));
+         rtx tor = gen_binary (IOR, mode, XEXP (x, 0), XEXP (x, 1));
          temp = combine_simplify_rtx (tor, mode, in_dest);
 
          /* If we could, great.  If not, do not go ahead with the IOR
@@ -4249,10 +4237,8 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
 
          in1 = XEXP (XEXP (XEXP (x, 1), 0), 0);
          in2 = XEXP (XEXP (x, 1), 1);
-         return simplify_gen_binary (PLUS, mode,
-                                     simplify_gen_binary (MULT, mode,
-                                                          in1, in2),
-                                     XEXP (x, 0));
+         return gen_binary (PLUS, mode, gen_binary (MULT, mode, in1, in2),
+                            XEXP (x, 0));
        }
 
       /* Canonicalize (minus (neg A) (mult B C)) to
@@ -4264,20 +4250,17 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
 
          in1 = simplify_gen_unary (NEG, mode, XEXP (XEXP (x, 1), 0), mode);
          in2 = XEXP (XEXP (x, 1), 1);
-         return simplify_gen_binary (MINUS, mode,
-                                     simplify_gen_binary (MULT, mode,
-                                                          in1, in2),
-                                     XEXP (XEXP (x, 0), 0));
+         return gen_binary (MINUS, mode, gen_binary (MULT, mode, in1, in2),
+                            XEXP (XEXP (x, 0), 0));
        }
 
       /* Canonicalize (minus A (plus B C)) to (minus (minus A B) C) for
         integers.  */
       if (GET_CODE (XEXP (x, 1)) == PLUS && INTEGRAL_MODE_P (mode))
-       return simplify_gen_binary (MINUS, mode,
-                                   simplify_gen_binary (MINUS, mode,
-                                                        XEXP (x, 0),
-                                                        XEXP (XEXP (x, 1), 0)),
-                                   XEXP (XEXP (x, 1), 1));
+       return gen_binary (MINUS, mode,
+                          gen_binary (MINUS, mode, XEXP (x, 0),
+                                      XEXP (XEXP (x, 1), 0)),
+                          XEXP (XEXP (x, 1), 1));
       break;
 
     case MULT:
@@ -4287,11 +4270,17 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
 
       if (GET_CODE (XEXP (x, 0)) == PLUS)
        {
-         rtx result = distribute_and_simplify_rtx (x);
-         if (result)
-           return result;
-       }
+         x = apply_distributive_law
+           (gen_binary (PLUS, mode,
+                        gen_binary (MULT, mode,
+                                    XEXP (XEXP (x, 0), 0), XEXP (x, 1)),
+                        gen_binary (MULT, mode,
+                                    XEXP (XEXP (x, 0), 1),
+                                    copy_rtx (XEXP (x, 1)))));
 
+         if (GET_CODE (x) != MULT)
+           return x;
+       }
       /* Try simplify a*(b/c) as (a*b)/c.  */
       if (FLOAT_MODE_P (mode) && flag_unsafe_math_optimizations
          && GET_CODE (XEXP (x, 0)) == DIV)
@@ -4300,7 +4289,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
                                               XEXP (XEXP (x, 0), 0),
                                               XEXP (x, 1));
          if (tem)
-           return simplify_gen_binary (DIV, mode, tem, XEXP (XEXP (x, 0), 1));
+           return gen_binary (DIV, mode, tem, XEXP (XEXP (x, 0), 1));
        }
       break;
 
@@ -4380,9 +4369,9 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int in_dest)
                   && nonzero_bits (op0, mode) == 1)
            {
              op0 = expand_compound_operation (op0);
-             return simplify_gen_binary (XOR, mode,
-                                         gen_lowpart (mode, op0),
-                                         const1_rtx);
+             return gen_binary (XOR, mode,
+                                gen_lowpart (mode, op0),
+                                const1_rtx);
            }
 
          else if (STORE_FLAG_VALUE == 1
@@ -4625,8 +4614,7 @@ simplify_if_then_else (rtx x)
 
   /* Simplify storing of the truth value.  */
   if (comparison_p && true_rtx == const_true_rtx && false_rtx == const0_rtx)
-    return simplify_gen_relational (true_code, mode, VOIDmode,
-                                   XEXP (cond, 0), XEXP (cond, 1));
+    return gen_binary (true_code, mode, XEXP (cond, 0), XEXP (cond, 1));
 
   /* Also when the truth value has to be reversed.  */
   if (comparison_p
@@ -4776,16 +4764,16 @@ simplify_if_then_else (rtx x)
       {
       case GE:
       case GT:
-       return simplify_gen_binary (SMAX, mode, true_rtx, false_rtx);
+       return gen_binary (SMAX, mode, true_rtx, false_rtx);
       case LE:
       case LT:
-       return simplify_gen_binary (SMIN, mode, true_rtx, false_rtx);
+       return gen_binary (SMIN, mode, true_rtx, false_rtx);
       case GEU:
       case GTU:
-       return simplify_gen_binary (UMAX, mode, true_rtx, false_rtx);
+       return gen_binary (UMAX, mode, true_rtx, false_rtx);
       case LEU:
       case LTU:
-       return simplify_gen_binary (UMIN, mode, true_rtx, false_rtx);
+       return gen_binary (UMIN, mode, true_rtx, false_rtx);
       default:
        break;
       }
@@ -4898,14 +4886,12 @@ simplify_if_then_else (rtx x)
 
       if (z)
        {
-         temp = subst (simplify_gen_relational (true_code, m, VOIDmode,
-                                                cond_op0, cond_op1),
+         temp = subst (gen_binary (true_code, m, cond_op0, cond_op1),
                        pc_rtx, pc_rtx, 0, 0);
-         temp = simplify_gen_binary (MULT, m, temp,
-                                     simplify_gen_binary (MULT, m, c1,
-                                                          const_true_rtx));
+         temp = gen_binary (MULT, m, temp,
+                            gen_binary (MULT, m, c1, const_true_rtx));
          temp = subst (temp, pc_rtx, pc_rtx, 0, 0);
-         temp = simplify_gen_binary (op, m, gen_lowpart (m, z), temp);
+         temp = gen_binary (op, m, gen_lowpart (m, z), temp);
 
          if (extend_op != NIL)
            temp = simplify_gen_unary (extend_op, mode, temp, m);
@@ -5090,8 +5076,7 @@ simplify_set (rtx x)
                  PUT_CODE (*cc_use, old_code);
                  other_changed = 0;
 
-                 op0 = simplify_gen_binary (XOR, GET_MODE (op0),
-                                            op0, GEN_INT (mask));
+                 op0 = gen_binary (XOR, GET_MODE (op0), op0, GEN_INT (mask));
                }
            }
        }
@@ -5255,19 +5240,18 @@ simplify_set (rtx x)
               && rtx_equal_p (XEXP (false_rtx, 1), true_rtx))
        term1 = true_rtx, false_rtx = XEXP (false_rtx, 0), true_rtx = const0_rtx;
 
-      term2 = simplify_gen_binary (AND, GET_MODE (src),
-                                  XEXP (XEXP (src, 0), 0), true_rtx);
-      term3 = simplify_gen_binary (AND, GET_MODE (src),
-                                  simplify_gen_unary (NOT, GET_MODE (src),
-                                                      XEXP (XEXP (src, 0), 0),
-                                                      GET_MODE (src)),
-                                  false_rtx);
+      term2 = gen_binary (AND, GET_MODE (src),
+                         XEXP (XEXP (src, 0), 0), true_rtx);
+      term3 = gen_binary (AND, GET_MODE (src),
+                         simplify_gen_unary (NOT, GET_MODE (src),
+                                             XEXP (XEXP (src, 0), 0),
+                                             GET_MODE (src)),
+                         false_rtx);
 
       SUBST (SET_SRC (x),
-            simplify_gen_binary (IOR, GET_MODE (src),
-                                 simplify_gen_binary (IOR, GET_MODE (src),
-                                                      term1, term2),
-                                 term3));
+            gen_binary (IOR, GET_MODE (src),
+                        gen_binary (IOR, GET_MODE (src), term1, term2),
+                        term3));
 
       src = SET_SRC (x);
     }
@@ -5302,31 +5286,29 @@ simplify_logical (rtx x)
       if (GET_CODE (op0) == XOR
          && rtx_equal_p (XEXP (op0, 0), op1)
          && ! side_effects_p (op1))
-       x = simplify_gen_binary (AND, mode,
-                                simplify_gen_unary (NOT, mode,
-                                                    XEXP (op0, 1), mode),
-                                op1);
+       x = gen_binary (AND, mode,
+                       simplify_gen_unary (NOT, mode, XEXP (op0, 1), mode),
+                       op1);
 
       if (GET_CODE (op0) == XOR
          && rtx_equal_p (XEXP (op0, 1), op1)
          && ! side_effects_p (op1))
-       x = simplify_gen_binary (AND, mode,
-                                simplify_gen_unary (NOT, mode,
-                                                    XEXP (op0, 0), mode),
-                                op1);
+       x = gen_binary (AND, mode,
+                       simplify_gen_unary (NOT, mode, XEXP (op0, 0), mode),
+                       op1);
 
       /* Similarly for (~(A ^ B)) & A.  */
       if (GET_CODE (op0) == NOT
          && GET_CODE (XEXP (op0, 0)) == XOR
          && rtx_equal_p (XEXP (XEXP (op0, 0), 0), op1)
          && ! side_effects_p (op1))
-       x = simplify_gen_binary (AND, mode, XEXP (XEXP (op0, 0), 1), op1);
+       x = gen_binary (AND, mode, XEXP (XEXP (op0, 0), 1), op1);
 
       if (GET_CODE (op0) == NOT
          && GET_CODE (XEXP (op0, 0)) == XOR
          && rtx_equal_p (XEXP (XEXP (op0, 0), 1), op1)
          && ! side_effects_p (op1))
-       x = simplify_gen_binary (AND, mode, XEXP (XEXP (op0, 0), 0), op1);
+       x = gen_binary (AND, mode, XEXP (XEXP (op0, 0), 0), op1);
 
       /* We can call simplify_and_const_int only if we don't lose
         any (sign) bits when converting INTVAL (op1) to
@@ -5346,9 +5328,8 @@ simplify_logical (rtx x)
              && GET_CODE (XEXP (op0, 1)) == CONST_INT
              && GET_CODE (op1) == CONST_INT
              && (INTVAL (XEXP (op0, 1)) & INTVAL (op1)) != 0)
-           return simplify_gen_binary (IOR, mode,
-                                       simplify_gen_binary
-                                         (AND, mode, XEXP (op0, 0),
+           return gen_binary (IOR, mode,
+                              gen_binary (AND, mode, XEXP (op0, 0),
                                           GEN_INT (INTVAL (XEXP (op0, 1))
                                                    & ~INTVAL (op1))), op1);
 
@@ -5367,16 +5348,54 @@ simplify_logical (rtx x)
          && ! side_effects_p (XEXP (op0, 1)))
        return op1;
 
-      /* If we have any of (and (ior A B) C) or (and (xor A B) C),
-        apply the distributive law and then the inverse distributive
-        law to see if things simplify.  */
-      if (GET_CODE (op0) == IOR || GET_CODE (op0) == XOR
-          || GET_CODE (op1) == IOR || GET_CODE (op1) == XOR)
+      /* In the following group of tests (and those in case IOR below),
+        we start with some combination of logical operations and apply
+        the distributive law followed by the inverse distributive law.
+        Most of the time, this results in no change.  However, if some of
+        the operands are the same or inverses of each other, simplifications
+        will result.
+
+        For example, (and (ior A B) (not B)) can occur as the result of
+        expanding a bit field assignment.  When we apply the distributive
+        law to this, we get (ior (and (A (not B))) (and (B (not B)))),
+        which then simplifies to (and (A (not B))).
+
+        If we have (and (ior A B) C), apply the distributive law and then
+        the inverse distributive law to see if things simplify.  */
+
+      if (GET_CODE (op0) == IOR || GET_CODE (op0) == XOR)
        {
-         rtx result = distribute_and_simplify_rtx (x);
-         if (result)
-           return result;
+         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),
+                                    copy_rtx (op1))));
+         if (GET_CODE (x) != AND)
+           return x;
        }
+
+      if (GET_CODE (op1) == IOR || GET_CODE (op1) == XOR)
+       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),
+                                  copy_rtx (op0))));
+
+      /* Similarly, taking advantage of the fact that
+        (and (not A) (xor B C)) == (xor (ior A B) (ior A C))  */
+
+      if (GET_CODE (op0) == NOT && GET_CODE (op1) == XOR)
+       return apply_distributive_law
+         (gen_binary (XOR, mode,
+                      gen_binary (IOR, mode, XEXP (op0, 0), XEXP (op1, 0)),
+                      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, copy_rtx (XEXP (op1, 0)), XEXP (op0, 1))));
       break;
 
     case IOR:
@@ -5397,11 +5416,28 @@ simplify_logical (rtx x)
       /* If we have (ior (and A B) C), apply the distributive law and then
         the inverse distributive law to see if things simplify.  */
 
-      if (GET_CODE (op0) == AND || GET_CODE (op1) == AND)
+      if (GET_CODE (op0) == AND)
        {
-         rtx result = distribute_and_simplify_rtx (x);
-         if (result)
-           return result;
+         x = apply_distributive_law
+           (gen_binary (AND, mode,
+                        gen_binary (IOR, mode, XEXP (op0, 0), op1),
+                        gen_binary (IOR, mode, XEXP (op0, 1),
+                                    copy_rtx (op1))));
+
+         if (GET_CODE (x) != IOR)
+           return x;
+       }
+
+      if (GET_CODE (op1) == AND)
+       {
+         x = apply_distributive_law
+           (gen_binary (AND, mode,
+                        gen_binary (IOR, mode, XEXP (op1, 0), op0),
+                        gen_binary (IOR, mode, XEXP (op1, 1),
+                                    copy_rtx (op0))));
+
+         if (GET_CODE (x) != IOR)
+           return x;
        }
 
       /* Convert (ior (ashift A CX) (lshiftrt A CY)) where CX+CY equals the
@@ -5450,7 +5486,7 @@ simplify_logical (rtx x)
       if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
          && (nonzero_bits (op0, mode)
              & nonzero_bits (op1, mode)) == 0)
-       return (simplify_gen_binary (IOR, mode, op0, op1));
+       return (gen_binary (IOR, mode, op0, op1));
 
       /* Convert (XOR (NOT x) (NOT y)) to (XOR x y).
         Also convert (XOR (NOT x) y) to (NOT (XOR x y)), similarly for
@@ -5470,8 +5506,7 @@ simplify_logical (rtx x)
          }
        else if (num_negated == 1)
          return
-           simplify_gen_unary (NOT, mode,
-                               simplify_gen_binary (XOR, mode, op0, op1),
+           simplify_gen_unary (NOT, mode, gen_binary (XOR, mode, op0, op1),
                                mode);
       }
 
@@ -5482,18 +5517,16 @@ simplify_logical (rtx x)
       if (GET_CODE (op0) == AND
          && rtx_equal_p (XEXP (op0, 1), op1)
          && ! side_effects_p (op1))
-       return simplify_gen_binary (AND, mode,
-                                   simplify_gen_unary (NOT, mode,
-                                                       XEXP (op0, 0), mode),
-                                   op1);
+       return gen_binary (AND, mode,
+                          simplify_gen_unary (NOT, mode, XEXP (op0, 0), mode),
+                          op1);
 
       else if (GET_CODE (op0) == AND
               && rtx_equal_p (XEXP (op0, 0), op1)
               && ! side_effects_p (op1))
-       return simplify_gen_binary (AND, mode,
-                                   simplify_gen_unary (NOT, mode,
-                                                       XEXP (op0, 1), mode),
-                                   op1);
+       return gen_binary (AND, mode,
+                          simplify_gen_unary (NOT, mode, XEXP (op0, 1), mode),
+                          op1);
 
       /* (xor (comparison foo bar) (const_int 1)) can become the reversed
         comparison if STORE_FLAG_VALUE is 1.  */
@@ -5762,7 +5795,7 @@ expand_field_assignment (rtx x)
   rtx inner;
   rtx pos;                     /* Always counts from low bit.  */
   int len;
-  rtx mask, cleared, masked;
+  rtx mask;
   enum machine_mode compute_mode;
 
   /* Loop until we find something we can't simplify.  */
@@ -5800,11 +5833,10 @@ expand_field_assignment (rtx x)
                /* If position is ADJUST - X, new position is X.  */
                pos = XEXP (pos, 0);
              else
-               pos = simplify_gen_binary (MINUS, GET_MODE (pos),
-                                          GEN_INT (GET_MODE_BITSIZE (
-                                                   GET_MODE (inner))
-                                                   - len),
-                                          pos);
+               pos = gen_binary (MINUS, GET_MODE (pos),
+                                 GEN_INT (GET_MODE_BITSIZE (GET_MODE (inner))
+                                          - len),
+                                 pos);
            }
        }
 
@@ -5851,30 +5883,30 @@ expand_field_assignment (rtx x)
        }
 
       /* Compute a mask of LEN bits, if we can do this on the host machine.  */
-      if (len >= HOST_BITS_PER_WIDE_INT)
+      if (len < HOST_BITS_PER_WIDE_INT)
+       mask = GEN_INT (((HOST_WIDE_INT) 1 << len) - 1);
+      else
        break;
 
       /* Now compute the equivalent expression.  Make a copy of INNER
         for the SET_DEST in case it is a MEM into which we will substitute;
         we don't want shared RTL in that case.  */
-      mask = GEN_INT (((HOST_WIDE_INT) 1 << len) - 1);
-      cleared = simplify_gen_binary (AND, compute_mode,
-                                    simplify_gen_unary (NOT, compute_mode,
-                                      simplify_gen_binary (ASHIFT,
-                                                           compute_mode,
-                                                           mask, pos),
-                                      compute_mode),
-                                    inner);
-      masked = simplify_gen_binary (ASHIFT, compute_mode,
-                                   simplify_gen_binary (
-                                     AND, compute_mode,
-                                     gen_lowpart (compute_mode, SET_SRC (x)),
-                                     mask),
-                                   pos);
-
-      x = gen_rtx_SET (VOIDmode, copy_rtx (inner),
-                      simplify_gen_binary (IOR, compute_mode,
-                                           cleared, masked));
+      x = gen_rtx_SET
+       (VOIDmode, copy_rtx (inner),
+        gen_binary (IOR, compute_mode,
+                    gen_binary (AND, compute_mode,
+                                simplify_gen_unary (NOT, compute_mode,
+                                                    gen_binary (ASHIFT,
+                                                                compute_mode,
+                                                                mask, pos),
+                                                    compute_mode),
+                                inner),
+                    gen_binary (ASHIFT, compute_mode,
+                                gen_binary (AND, compute_mode,
+                                            gen_lowpart
+                                            (compute_mode, SET_SRC (x)),
+                                            mask),
+                                pos)));
     }
 
   return x;
@@ -6330,8 +6362,8 @@ extract_left_shift (rtx x, int count)
       if (GET_CODE (XEXP (x, 1)) == CONST_INT
          && (INTVAL (XEXP (x, 1)) & ((((HOST_WIDE_INT) 1 << count)) - 1)) == 0
          && (tem = extract_left_shift (XEXP (x, 0), count)) != 0)
-       return simplify_gen_binary (code, mode, tem,
-                                   GEN_INT (INTVAL (XEXP (x, 1)) >> count));
+       return gen_binary (code, mode, tem,
+                          GEN_INT (INTVAL (XEXP (x, 1)) >> count));
 
       break;
 
@@ -6822,8 +6854,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
                  && (cval & ((HOST_WIDE_INT) 1 << (width - 1))) != 0)
                cval |= (HOST_WIDE_INT) -1 << width;
 
-             y = simplify_gen_binary (AND, GET_MODE (x),
-                                      XEXP (x, 0), GEN_INT (cval));
+             y = gen_binary (AND, GET_MODE (x), XEXP (x, 0), GEN_INT (cval));
              if (rtx_cost (y, SET) < rtx_cost (x, SET))
                x = y;
            }
@@ -6915,10 +6946,10 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
        {
          temp = GEN_INT ((INTVAL (XEXP (x, 1)) & mask)
                          << INTVAL (XEXP (XEXP (x, 0), 1)));
-         temp = simplify_gen_binary (GET_CODE (x), GET_MODE (x),
-                                     XEXP (XEXP (x, 0), 0), temp);
-         x = simplify_gen_binary (LSHIFTRT, GET_MODE (x), temp,
-                                  XEXP (XEXP (x, 0), 1));
+         temp = gen_binary (GET_CODE (x), GET_MODE (x),
+                            XEXP (XEXP (x, 0), 0), temp);
+         x = gen_binary (LSHIFTRT, GET_MODE (x), temp,
+                         XEXP (XEXP (x, 0), 1));
          return force_to_mode (x, mode, mask, reg, next_select);
        }
 
@@ -6934,7 +6965,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
                                        reg, next_select));
 
       if (op_mode != GET_MODE (x) || op0 != XEXP (x, 0) || op1 != XEXP (x, 1))
-       x = simplify_gen_binary (code, op_mode, op0, op1);
+       x = gen_binary (code, op_mode, op0, op1);
       break;
 
     case ASHIFT:
@@ -6968,7 +6999,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
                                        mask, reg, next_select));
 
       if (op_mode != GET_MODE (x) || op0 != XEXP (x, 0))
-       x = simplify_gen_binary (code, op_mode, op0, XEXP (x, 1));
+       x = gen_binary (code, op_mode, op0, XEXP (x, 1));
       break;
 
     case LSHIFTRT:
@@ -6996,7 +7027,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
          inner = force_to_mode (inner, op_mode, inner_mask, reg, next_select);
 
          if (GET_MODE (x) != op_mode || inner != XEXP (x, 0))
-           x = simplify_gen_binary (LSHIFTRT, op_mode, inner, XEXP (x, 1));
+           x = gen_binary (LSHIFTRT, op_mode, inner, XEXP (x, 1));
        }
 
       /* If we have (and (lshiftrt FOO C1) C2) where the combination of the
@@ -7018,9 +7049,9 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
          /* Must be more sign bit copies than the mask needs.  */
          && ((int) num_sign_bit_copies (XEXP (x, 0), GET_MODE (XEXP (x, 0)))
              >= exact_log2 (mask + 1)))
-       x = simplify_gen_binary (LSHIFTRT, GET_MODE (x), XEXP (x, 0),
-                                GEN_INT (GET_MODE_BITSIZE (GET_MODE (x))
-                                         - exact_log2 (mask + 1)));
+       x = gen_binary (LSHIFTRT, GET_MODE (x), XEXP (x, 0),
+                       GEN_INT (GET_MODE_BITSIZE (GET_MODE (x))
+                                - exact_log2 (mask + 1)));
 
       goto shiftrt;
 
@@ -7085,8 +7116,7 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
       /* If MASK is 1, convert this to an LSHIFTRT.  This can be done
         even if the shift count isn't a constant.  */
       if (mask == 1)
-       x = simplify_gen_binary (LSHIFTRT, GET_MODE (x),
-                                XEXP (x, 0), XEXP (x, 1));
+       x = gen_binary (LSHIFTRT, GET_MODE (x), XEXP (x, 0), XEXP (x, 1));
 
     shiftrt:
 
@@ -7151,10 +7181,8 @@ force_to_mode (rtx x, enum machine_mode mode, unsigned HOST_WIDE_INT mask,
        {
          temp = gen_int_mode (mask << INTVAL (XEXP (XEXP (x, 0), 1)),
                               GET_MODE (x));
-         temp = simplify_gen_binary (XOR, GET_MODE (x),
-                                     XEXP (XEXP (x, 0), 0), temp);
-         x = simplify_gen_binary (LSHIFTRT, GET_MODE (x),
-                                  temp, XEXP (XEXP (x, 0), 1));
+         temp = gen_binary (XOR, GET_MODE (x), XEXP (XEXP (x, 0), 0), temp);
+         x = gen_binary (LSHIFTRT, GET_MODE (x), temp, XEXP (XEXP (x, 0), 1));
 
          return force_to_mode (x, mode, mask, reg, next_select);
        }
@@ -7264,19 +7292,8 @@ if_then_else_cond (rtx x, rtx *ptrue, rtx *pfalse)
          else if (cond1 == 0)
            true1 = copy_rtx (true1);
 
-         if (COMPARISON_P (x))
-           {
-             *ptrue = simplify_gen_relational (code, mode, VOIDmode,
-                                               true0, true1);
-             *pfalse = simplify_gen_relational (code, mode, VOIDmode,
-                                                false0, false1);
-            }
-         else
-           {
-             *ptrue = simplify_gen_binary (code, mode, true0, true1);
-             *pfalse = simplify_gen_binary (code, mode, false0, false1);
-           }
-
+         *ptrue = gen_binary (code, mode, true0, true1);
+         *pfalse = gen_binary (code, mode, false0, false1);
          return cond0 ? cond0 : cond1;
        }
 
@@ -7306,13 +7323,13 @@ if_then_else_cond (rtx x, rtx *ptrue, rtx *pfalse)
                      && rtx_equal_p (XEXP (cond0, 1), XEXP (cond1, 0))))
              && ! side_effects_p (x))
            {
-             *ptrue = simplify_gen_binary (MULT, mode, op0, const_true_rtx);
-             *pfalse = simplify_gen_binary (MULT, mode,
-                                            (code == MINUS
-                                             ? simplify_gen_unary (NEG, mode,
-                                                                   op1, mode)
-                                             : op1),
-                                             const_true_rtx);
+             *ptrue = gen_binary (MULT, mode, op0, const_true_rtx);
+             *pfalse = gen_binary (MULT, mode,
+                                   (code == MINUS
+                                    ? simplify_gen_unary (NEG, mode, op1,
+                                                          mode)
+                                    : op1),
+                                   const_true_rtx);
              return cond0;
            }
        }
@@ -7816,8 +7833,8 @@ apply_distributive_law (rtx x)
          || GET_MODE_SIZE (GET_MODE (SUBREG_REG (lhs))) > UNITS_PER_WORD)
        return x;
 
-      tem = simplify_gen_binary (code, GET_MODE (SUBREG_REG (lhs)),
-                                SUBREG_REG (lhs), SUBREG_REG (rhs));
+      tem = gen_binary (code, GET_MODE (SUBREG_REG (lhs)),
+                       SUBREG_REG (lhs), SUBREG_REG (rhs));
       return gen_lowpart (GET_MODE (x), tem);
 
     default:
@@ -7843,7 +7860,7 @@ apply_distributive_law (rtx x)
     return x;
 
   /* Form the new inner operation, seeing if it simplifies first.  */
-  tem = simplify_gen_binary (code, GET_MODE (x), lhs, rhs);
+  tem = gen_binary (code, GET_MODE (x), lhs, rhs);
 
   /* There is one exception to the general way of distributing:
      (a | c) ^ (b | c) -> (a ^ b) & ~c  */
@@ -7856,95 +7873,8 @@ apply_distributive_law (rtx x)
   /* We may be able to continuing distributing the result, so call
      ourselves recursively on the inner operation before forming the
      outer operation, which we return.  */
-  return simplify_gen_binary (inner_code, GET_MODE (x),
-                             apply_distributive_law (tem), other);
-}
-
-/* See if X is of the form (* (+ a b) c), and if so convert to
-   (+ (* a c) (* b c)) and try to simplify.
-
-   Most of the time, this results in no change.  However, if some of
-   the operands are the same or inverses of each other, simplifications
-   will result.
-
-   For example, (and (ior A B) (not B)) can occur as the result of
-   expanding a bit field assignment.  When we apply the distributive
-   law to this, we get (ior (and (A (not B))) (and (B (not B)))),
-   which then simplifies to (and (A (not B))).
-   Note that no checks happen on the validity of applying the inverse
-   distributive law.  This is pointless since we can do it in the
-   few places where this routine is called.  */
-static rtx
-distribute_and_simplify_rtx (rtx x)
-{
-  enum machine_mode mode;
-  enum rtx_code outer, inner;
-  rtx op0, op1, inner_op0, inner_op1, new_op0, new_op1;
-
-  mode = GET_MODE (x);
-  outer = GET_CODE (x);
-  op0 = XEXP (x, 0);
-  op1 = XEXP (x, 1);
-  if (ARITHMETIC_P (op0))
-    {
-      inner = GET_CODE (op0);
-      inner_op0 = XEXP (op0, 0);
-      inner_op1 = XEXP (op0, 1);
-
-      /* (and (xor B C) (not A)) == (xor (ior A B) (ior A C))  */
-      if (outer == AND && inner == XOR && GET_CODE (op1) == NOT)
-        {
-         new_op0 = simplify_gen_binary (IOR, mode, inner_op0, op1);
-          new_op1 = simplify_gen_binary (IOR, mode, inner_op1, op1);
-          x = apply_distributive_law (simplify_gen_binary (XOR, mode,
-                                                          new_op0, new_op1));
-
-         if (GET_CODE (x) != AND)
-           return x;
-       }
-      else
-       {
-          new_op0 = simplify_gen_binary (outer, mode, inner_op0, op1);
-          new_op1 = simplify_gen_binary (outer, mode, inner_op1, op1);
-          x = apply_distributive_law (simplify_gen_binary (inner, mode,
-                                                          new_op0, new_op1));
-
-         if (GET_CODE (x) != outer)
-           return x;
-       }
-    }
-
-  if (ARITHMETIC_P (op1))
-    {
-      inner = GET_CODE (op1);
-      inner_op0 = XEXP (op1, 0);
-      inner_op1 = XEXP (op1, 1);
-
-      /* (and (not A) (xor B C)) == (xor (ior A B) (ior A C))  */
-      if (outer == AND && inner == XOR && GET_CODE (op0) == NOT)
-        {
-         new_op0 = simplify_gen_binary (IOR, mode, inner_op0, op0);
-          new_op1 = simplify_gen_binary (IOR, mode, inner_op1, op0);
-          x = apply_distributive_law (simplify_gen_binary (XOR, mode,
-                                                          new_op0, new_op1));
-
-         if (GET_CODE (x) != AND)
-           return x;
-       }
-      else
-       {
-          new_op0 = simplify_gen_binary (outer, mode, op0, inner_op0);
-          new_op1 = simplify_gen_binary (outer, mode, op0, inner_op1);
-          x = apply_distributive_law (simplify_gen_binary (inner, mode,
-                                                          new_op0, new_op1));
-
-         if (GET_CODE (x) != outer)
-           return x;
-       }
-    }
-
-  return NULL_RTX;
+  return gen_binary (inner_code, GET_MODE (x),
+                    apply_distributive_law (tem), other);
 }
 \f
 /* We have X, a logical `and' of VAROP with the constant CONSTOP, to be done
@@ -8011,15 +7941,11 @@ simplify_and_const_int (rtx x, enum machine_mode mode, rtx varop,
       gen_lowpart
        (mode,
         apply_distributive_law
-        (simplify_gen_binary (GET_CODE (varop), GET_MODE (varop),
-                              simplify_and_const_int (NULL_RTX,
-                                                      GET_MODE (varop),
-                                                      XEXP (varop, 0),
-                                                      constop),
-                              simplify_and_const_int (NULL_RTX,
-                                                      GET_MODE (varop),
-                                                      XEXP (varop, 1),
-                                                      constop))));
+        (gen_binary (GET_CODE (varop), GET_MODE (varop),
+                     simplify_and_const_int (NULL_RTX, GET_MODE (varop),
+                                             XEXP (varop, 0), constop),
+                     simplify_and_const_int (NULL_RTX, GET_MODE (varop),
+                                             XEXP (varop, 1), constop))));
 
   /* If VAROP is PLUS, and the constant is a mask of low bite, distribute
      the AND and see if one of the operands simplifies to zero.  If so, we
@@ -8060,7 +7986,7 @@ simplify_and_const_int (rtx x, enum machine_mode mode, rtx varop,
       constop = trunc_int_for_mode (constop, mode);
       /* See how much, if any, of X we can use.  */
       if (x == 0 || GET_CODE (x) != AND || GET_MODE (x) != mode)
-       x = simplify_gen_binary (AND, mode, varop, GEN_INT (constop));
+       x = gen_binary (AND, mode, varop, GEN_INT (constop));
 
       else
        {
@@ -8579,10 +8505,8 @@ simplify_shift_const (rtx x, enum rtx_code code,
              && exact_log2 (INTVAL (XEXP (varop, 1))) >= 0)
            {
              varop
-               = simplify_gen_binary (ASHIFT, GET_MODE (varop),
-                                      XEXP (varop, 0),
-                                      GEN_INT (exact_log2 (
-                                               INTVAL (XEXP (varop, 1)))));
+               = gen_binary (ASHIFT, GET_MODE (varop), XEXP (varop, 0),
+                             GEN_INT (exact_log2 (INTVAL (XEXP (varop, 1)))));
              continue;
            }
          break;
@@ -8593,10 +8517,8 @@ simplify_shift_const (rtx x, enum rtx_code code,
              && exact_log2 (INTVAL (XEXP (varop, 1))) >= 0)
            {
              varop
-               = simplify_gen_binary (LSHIFTRT, GET_MODE (varop),
-                                      XEXP (varop, 0),
-                                      GEN_INT (exact_log2 (
-                                               INTVAL (XEXP (varop, 1)))));
+               = gen_binary (LSHIFTRT, GET_MODE (varop), XEXP (varop, 0),
+                             GEN_INT (exact_log2 (INTVAL (XEXP (varop, 1)))));
              continue;
            }
          break;
@@ -8841,7 +8763,7 @@ simplify_shift_const (rtx x, enum rtx_code code,
             logical expression, make a new logical expression, and apply
             the inverse distributive law.  This also can't be done
             for some (ashiftrt (xor)).  */
-         if (code != ASHIFTRT || GET_CODE (varop) != XOR
+         if (code != ASHIFTRT || GET_CODE (varop)!= XOR
              || 0 <= trunc_int_for_mode (INTVAL (XEXP (varop, 1)),
                                          shift_mode))
            {
@@ -8850,8 +8772,7 @@ simplify_shift_const (rtx x, enum rtx_code code,
              rtx rhs = simplify_shift_const (NULL_RTX, code, shift_mode,
                                              XEXP (varop, 1), count);
 
-             varop = simplify_gen_binary (GET_CODE (varop), shift_mode,
-                                          lhs, rhs);
+             varop = gen_binary (GET_CODE (varop), shift_mode, lhs, rhs);
              varop = apply_distributive_law (varop);
 
              count = 0;
@@ -9105,8 +9026,7 @@ simplify_shift_const (rtx x, enum rtx_code code,
       else if (GET_RTX_CLASS (outer_op) == RTX_UNARY)
        x = simplify_gen_unary (outer_op, result_mode, x, result_mode);
       else
-       x = simplify_gen_binary (outer_op, result_mode, x,
-                                GEN_INT (outer_const));
+       x = gen_binary (outer_op, result_mode, x, GEN_INT (outer_const));
     }
 
   return x;
@@ -9339,6 +9259,63 @@ gen_lowpart_for_combine (enum machine_mode mode, rtx x)
     }
 }
 \f
+/* These routines make binary and unary operations by first seeing if they
+   fold; if not, a new expression is allocated.  */
+
+static rtx
+gen_binary (enum rtx_code code, enum machine_mode mode, rtx op0, rtx op1)
+{
+  rtx result;
+  rtx tem;
+
+  if (GET_CODE (op0) == CLOBBER)
+    return op0;
+  else if (GET_CODE (op1) == CLOBBER)
+    return op1;
+  
+  if (GET_RTX_CLASS (code) == RTX_COMM_ARITH
+      && swap_commutative_operands_p (op0, op1))
+    tem = op0, op0 = op1, op1 = tem;
+
+  if (GET_RTX_CLASS (code) == RTX_COMPARE
+      || GET_RTX_CLASS (code) == RTX_COMM_COMPARE)
+    {
+      enum machine_mode op_mode = GET_MODE (op0);
+
+      /* Strip the COMPARE from (REL_OP (compare X Y) 0) to get
+        just (REL_OP X Y).  */
+      if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
+       {
+         op1 = XEXP (op0, 1);
+         op0 = XEXP (op0, 0);
+         op_mode = GET_MODE (op0);
+       }
+
+      if (op_mode == VOIDmode)
+       op_mode = GET_MODE (op1);
+      result = simplify_relational_operation (code, mode, op_mode, op0, op1);
+    }
+  else
+    result = simplify_binary_operation (code, mode, op0, op1);
+
+  if (result)
+    return result;
+
+  /* Put complex operands first and constants second.  */
+  if (GET_RTX_CLASS (code) == RTX_COMM_ARITH
+      && swap_commutative_operands_p (op0, op1))
+    return gen_rtx_fmt_ee (code, mode, op1, op0);
+
+  /* If we are turning off bits already known off in OP0, we need not do
+     an AND.  */
+  else if (code == AND && GET_CODE (op1) == CONST_INT
+          && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
+          && (nonzero_bits (op0, mode) & ~INTVAL (op1)) == 0)
+    return op0;
+
+  return gen_rtx_fmt_ee (code, mode, op0, op1);
+}
+\f
 /* Simplify a comparison between *POP0 and *POP1 where CODE is the
    comparison code that will be tested.
 
@@ -10173,9 +10150,9 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
                  && c1 != mask
                  && c1 != GET_MODE_MASK (tmode))
                {
-                 op0 = simplify_gen_binary (AND, tmode,
-                                            SUBREG_REG (XEXP (op0, 0)),
-                                            gen_int_mode (c1, tmode));
+                 op0 = gen_binary (AND, tmode,
+                                   SUBREG_REG (XEXP (op0, 0)),
+                                   gen_int_mode (c1, tmode));
                  op0 = gen_lowpart (mode, op0);
                  continue;
                }
@@ -10319,12 +10296,12 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
            {
              rtx inner = XEXP (XEXP (XEXP (op0, 0), 0), 0);
              rtx add_const = XEXP (XEXP (op0, 0), 1);
-             rtx new_const = simplify_gen_binary (ASHIFTRT, GET_MODE (op0),
-                                                  add_const, XEXP (op0, 1));
+             rtx new_const = gen_binary (ASHIFTRT, GET_MODE (op0), add_const,
+                                         XEXP (op0, 1));
 
-             op0 = simplify_gen_binary (PLUS, tmode,
-                                        gen_lowpart (tmode, inner),
-                                        new_const);
+             op0 = gen_binary (PLUS, tmode,
+                               gen_lowpart (tmode, inner),
+                               new_const);
              continue;
            }
 
@@ -10477,11 +10454,11 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
                 make a new AND in the proper mode.  */
              if (GET_CODE (op0) == AND
                  && !have_insn_for (AND, mode))
-               op0 = simplify_gen_binary (AND, tmode,
-                                          gen_lowpart (tmode,
-                                                       XEXP (op0, 0)),
-                                          gen_lowpart (tmode,
-                                                       XEXP (op0, 1)));
+               op0 = gen_binary (AND, tmode,
+                                 gen_lowpart (tmode,
+                                              XEXP (op0, 0)),
+                                 gen_lowpart (tmode,
+                                              XEXP (op0, 1)));
 
              op0 = gen_lowpart (tmode, op0);
              if (zero_extended && GET_CODE (op1) == CONST_INT)
@@ -10496,11 +10473,10 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
          if (op1 == const0_rtx && (code == LT || code == GE)
              && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
            {
-             op0 = simplify_gen_binary (AND, tmode,
-                                        gen_lowpart (tmode, op0),
-                                        GEN_INT ((HOST_WIDE_INT) 1
-                                                 << (GET_MODE_BITSIZE (mode)
-                                                     - 1)));
+             op0 = gen_binary (AND, tmode,
+                               gen_lowpart (tmode, op0),
+                               GEN_INT ((HOST_WIDE_INT) 1
+                                        << (GET_MODE_BITSIZE (mode) - 1)));
              code = (code == LT) ? NE : EQ;
              break;
            }
@@ -10547,7 +10523,7 @@ reversed_comparison (rtx exp, enum machine_mode mode, rtx op0, rtx op1)
   if (reversed_code == UNKNOWN)
     return NULL_RTX;
   else
-    return simplify_gen_relational (reversed_code, mode, VOIDmode, op0, op1);
+    return gen_binary (reversed_code, mode, op0, op1);
 }
 \f
 /* Utility function for following routine.  Called when X is part of a value