OSDN Git Service

* toplev.c (rest_of_compilation): Avoid cfg_cleanup calls when not
[pf3gnuchains/gcc-fork.git] / gcc / builtins.c
index 851fc27..d2505cd 100644 (file)
@@ -99,7 +99,9 @@ static rtx expand_builtin_apply               PARAMS ((rtx, rtx, rtx));
 static void expand_builtin_return      PARAMS ((rtx));
 static enum type_class type_to_class   PARAMS ((tree));
 static rtx expand_builtin_classify_type        PARAMS ((tree));
+static void expand_errno_check         PARAMS ((tree, rtx));
 static rtx expand_builtin_mathfn       PARAMS ((tree, rtx, rtx));
+static rtx expand_builtin_mathfn_2     PARAMS ((tree, rtx, rtx));
 static rtx expand_builtin_constant_p   PARAMS ((tree));
 static rtx expand_builtin_args_info    PARAMS ((tree));
 static rtx expand_builtin_next_arg     PARAMS ((tree));
@@ -147,7 +149,7 @@ static rtx expand_builtin_strchr    PARAMS ((tree, rtx,
 static rtx expand_builtin_strrchr      PARAMS ((tree, rtx,
                                                 enum machine_mode));
 static rtx expand_builtin_alloca       PARAMS ((tree, rtx));
-static rtx expand_builtin_ffs          PARAMS ((tree, rtx, rtx));
+static rtx expand_builtin_unop         PARAMS ((tree, rtx, rtx, optab));
 static rtx expand_builtin_frame_address        PARAMS ((tree));
 static rtx expand_builtin_fputs                PARAMS ((tree, int, int));
 static tree stabilize_va_list          PARAMS ((tree, int));
@@ -157,6 +159,7 @@ static tree fold_builtin_classify_type      PARAMS ((tree));
 static tree fold_builtin_inf           PARAMS ((tree, int));
 static tree fold_builtin_nan           PARAMS ((tree, tree, int));
 static int validate_arglist            PARAMS ((tree, ...));
+static tree fold_trunc_transparent_mathfn PARAMS ((tree));
 
 /* Return the alignment in bits of EXP, a pointer valued expression.
    But don't return more than MAX_ALIGN no matter what.
@@ -1468,6 +1471,8 @@ expand_builtin_constant_p (exp)
      case is not obvious, so emit (constant_p_rtx (ARGLIST)) and let CSE
      get a chance to see if it can deduce whether ARGLIST is constant.  */
 
+  current_function_calls_constant_p = 1;
+
   tmp = expand_expr (arglist, NULL_RTX, VOIDmode, 0);
   tmp = gen_rtx_CONSTANT_P_RTX (value_mode, tmp);
   return tmp;
@@ -1504,6 +1509,11 @@ mathfn_built_in (type, fn)
       case BUILT_IN_EXPL:
        fcode = BUILT_IN_EXP;
        break;
+      case BUILT_IN_LOG:
+      case BUILT_IN_LOGF:
+      case BUILT_IN_LOGL:
+       fcode = BUILT_IN_LOG;
+       break;
       case BUILT_IN_FLOOR:
       case BUILT_IN_FLOORF:
       case BUILT_IN_FLOORL:
@@ -1555,6 +1565,11 @@ mathfn_built_in (type, fn)
       case BUILT_IN_EXPL:
        fcode = BUILT_IN_EXPF;
        break;
+      case BUILT_IN_LOG:
+      case BUILT_IN_LOGF:
+      case BUILT_IN_LOGL:
+       fcode = BUILT_IN_LOGF;
+       break;
       case BUILT_IN_FLOOR:
       case BUILT_IN_FLOORF:
       case BUILT_IN_FLOORL:
@@ -1606,6 +1621,11 @@ mathfn_built_in (type, fn)
       case BUILT_IN_EXPL:
        fcode = BUILT_IN_EXPL;
        break;
+      case BUILT_IN_LOG:
+      case BUILT_IN_LOGF:
+      case BUILT_IN_LOGL:
+       fcode = BUILT_IN_LOGL;
+       break;
       case BUILT_IN_FLOOR:
       case BUILT_IN_FLOORF:
       case BUILT_IN_FLOORL:
@@ -1637,6 +1657,50 @@ mathfn_built_in (type, fn)
   return implicit_built_in_decls[fcode];
 }
 
+/* If errno must be maintained, expand the RTL to check if the result,
+   TARGET, of a built-in function call, EXP, is NaN, and if so set
+   errno to EDOM.  */
+
+static void
+expand_errno_check (exp, target)
+     tree exp;
+     rtx target;
+{
+  rtx lab;
+
+  if (flag_errno_math && HONOR_NANS (GET_MODE (target)))
+    {
+      lab = gen_label_rtx ();
+
+      /* Test the result; if it is NaN, set errno=EDOM because
+        the argument was not in the domain.  */
+      emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
+                              0, lab);
+
+#ifdef TARGET_EDOM
+      {
+#ifdef GEN_ERRNO_RTX
+       rtx errno_rtx = GEN_ERRNO_RTX;
+#else
+       rtx errno_rtx
+         = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
+#endif
+
+       emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
+      }
+#else
+      /* We can't set errno=EDOM directly; let the library call do it.
+        Pop the arguments right away in case the call gets deleted.  */
+      NO_DEFER_POP;
+      expand_call (exp, target, 0);
+      OK_DEFER_POP;
+#endif
+
+      emit_label (lab);
+    }
+}
+
+
 /* Expand a call to one of the builtin math functions (sin, cos, or sqrt).
    Return 0 if a normal call should be emitted rather than expanding the
    function in-line.  EXP is the expression that is a call to the builtin
@@ -1742,41 +1806,107 @@ expand_builtin_mathfn (exp, target, subtarget)
       return 0;
     }
 
-  /* If errno must be maintained, we must set it to EDOM for NaN results.  */
+  if (errno_set)
+    expand_errno_check (exp, target);
+
+  /* Output the entire sequence.  */
+  insns = get_insns ();
+  end_sequence ();
+  emit_insn (insns);
+
+  return target;
+}
 
-  if (flag_errno_math && errno_set && HONOR_NANS (argmode))
+/* Expand a call to the builtin binary math functions (pow and atan2).
+   Return 0 if a normal call should be emitted rather than expanding the
+   function in-line.  EXP is the expression that is a call to the builtin
+   function; if convenient, the result should be placed in TARGET.
+   SUBTARGET may be used as the target for computing one of EXP's
+   operands.  */
+
+static rtx
+expand_builtin_mathfn_2 (exp, target, subtarget)
+     tree exp;
+     rtx target, subtarget;
+{
+  optab builtin_optab;
+  rtx op0, op1, insns;
+  tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+  tree arglist = TREE_OPERAND (exp, 1);
+  tree arg0, arg1;
+  enum machine_mode argmode;
+  bool errno_set = true;
+  bool stable = true;
+
+  if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
+    return 0;
+
+  arg0 = TREE_VALUE (arglist);
+  arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+
+  /* Stabilize the arguments.  */
+  if (TREE_CODE (arg0) != VAR_DECL && TREE_CODE (arg0) != PARM_DECL)
+    {
+      arg0 = save_expr (arg0);
+      TREE_VALUE (arglist) = arg0;
+      stable = false;
+    }
+  if (TREE_CODE (arg1) != VAR_DECL && TREE_CODE (arg1) != PARM_DECL)
     {
-      rtx lab1;
+      arg1 = save_expr (arg1);
+      TREE_VALUE (TREE_CHAIN (arglist)) = arg1;
+      stable = false;
+    }
 
-      lab1 = gen_label_rtx ();
+  if (! stable)
+    {
+      exp = copy_node (exp);
+      arglist = tree_cons (NULL_TREE, arg0,
+                          build_tree_list (NULL_TREE, arg1));
+      TREE_OPERAND (exp, 1) = arglist;
+    }
 
-      /* Test the result; if it is NaN, set errno=EDOM because
-        the argument was not in the domain.  */
-      emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
-                              0, lab1);
+  op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
+  op1 = expand_expr (arg1, 0, VOIDmode, 0);
 
-#ifdef TARGET_EDOM
-      {
-#ifdef GEN_ERRNO_RTX
-       rtx errno_rtx = GEN_ERRNO_RTX;
-#else
-       rtx errno_rtx
-         = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
-#endif
+  /* Make a suitable register to place result in.  */
+  target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
 
-       emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
-      }
-#else
-      /* We can't set errno=EDOM directly; let the library call do it.
-        Pop the arguments right away in case the call gets deleted.  */
-      NO_DEFER_POP;
-      expand_call (exp, target, 0);
-      OK_DEFER_POP;
-#endif
+  emit_queue ();
+  start_sequence ();
+
+  switch (DECL_FUNCTION_CODE (fndecl))
+    {
+    case BUILT_IN_POW:
+    case BUILT_IN_POWF:
+    case BUILT_IN_POWL:
+      builtin_optab = pow_optab; break;
+    case BUILT_IN_ATAN2:
+    case BUILT_IN_ATAN2F:
+    case BUILT_IN_ATAN2L:
+      builtin_optab = atan2_optab; break;
+    default:
+      abort ();
+    }
+
+  /* Compute into TARGET.
+     Set TARGET to wherever the result comes back.  */
+  argmode = TYPE_MODE (TREE_TYPE (arg0));
+  target = expand_binop (argmode, builtin_optab, op0, op1,
+                        target, 0, OPTAB_DIRECT);
 
-      emit_label (lab1);
+  /* If we were unable to expand via the builtin, stop the
+     sequence (without outputting the insns) and return 0, causing
+     a call to the library function.  */
+  if (target == 0)
+    {
+      end_sequence ();
+      return 0;
     }
 
+  if (errno_set)
+    expand_errno_check (exp, target);
+
   /* Output the entire sequence.  */
   insns = get_insns ();
   end_sequence ();
@@ -3578,15 +3708,16 @@ expand_builtin_alloca (arglist, target)
   return result;
 }
 
-/* Expand a call to the ffs builtin.  The arguments are in ARGLIST.
+/* Expand a call to a unary builtin.  The arguments are in ARGLIST.
    Return 0 if a normal call should be emitted rather than expanding the
    function in-line.  If convenient, the result should be placed in TARGET.
    SUBTARGET may be used as the target for computing one of EXP's operands.  */
 
 static rtx
-expand_builtin_ffs (arglist, target, subtarget)
+expand_builtin_unop (arglist, target, subtarget, op_optab)
      tree arglist;
      rtx target, subtarget;
+     optab op_optab;
 {
   rtx op0;
   if (!validate_arglist (arglist, INTEGER_TYPE, VOID_TYPE))
@@ -3594,10 +3725,10 @@ expand_builtin_ffs (arglist, target, subtarget)
 
   /* Compute the argument.  */
   op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
-  /* Compute ffs, into TARGET if possible.
+  /* Compute op, into TARGET if possible.
      Set TARGET to wherever the result comes back.  */
   target = expand_unop (TYPE_MODE (TREE_TYPE (TREE_VALUE (arglist))),
-                       ffs_optab, op0, target, 1);
+                       op_optab, op0, target, 1);
   if (target == 0)
     abort ();
   return target;
@@ -3709,7 +3840,7 @@ expand_builtin_expect (arglist, target)
   target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
 
   /* Don't bother with expected value notes for integral constants.  */
-  if (GET_CODE (target) != CONST_INT)
+  if (flag_guess_branch_prob && GET_CODE (target) != CONST_INT)
     {
       /* We do need to force this into a register so that we can be
         moderately sure to be able to correctly interpret the branch
@@ -3881,6 +4012,9 @@ expand_builtin (exp, target, subtarget, mode, ignore)
   tree arglist = TREE_OPERAND (exp, 1);
   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
 
+  /* Perform postincrements before expanding builtin functions.  */
+  emit_queue ();
+
   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
     return (*targetm.expand_builtin) (exp, target, subtarget, mode, ignore);
 
@@ -3901,6 +4035,15 @@ expand_builtin (exp, target, subtarget, mode, ignore)
       case BUILT_IN_EXP:
       case BUILT_IN_EXPF:
       case BUILT_IN_EXPL:
+      case BUILT_IN_LOG:
+      case BUILT_IN_LOGF:
+      case BUILT_IN_LOGL:
+      case BUILT_IN_POW:
+      case BUILT_IN_POWF:
+      case BUILT_IN_POWL:
+      case BUILT_IN_ATAN2:
+      case BUILT_IN_ATAN2F:
+      case BUILT_IN_ATAN2L:
       case BUILT_IN_MEMSET:
       case BUILT_IN_MEMCPY:
       case BUILT_IN_MEMCMP:
@@ -4019,6 +4162,19 @@ expand_builtin (exp, target, subtarget, mode, ignore)
        return target;
       break;
 
+    case BUILT_IN_POW:
+    case BUILT_IN_POWF:
+    case BUILT_IN_POWL:
+    case BUILT_IN_ATAN2:
+    case BUILT_IN_ATAN2F:
+    case BUILT_IN_ATAN2L:
+      if (! flag_unsafe_math_optimizations)
+       break;
+      target = expand_builtin_mathfn_2 (exp, target, subtarget);
+      if (target)
+       return target;
+      break;
+
     case BUILT_IN_APPLY_ARGS:
       return expand_builtin_apply_args ();
 
@@ -4096,7 +4252,42 @@ expand_builtin (exp, target, subtarget, mode, ignore)
       break;
 
     case BUILT_IN_FFS:
-      target = expand_builtin_ffs (arglist, target, subtarget);
+    case BUILT_IN_FFSL:
+    case BUILT_IN_FFSLL:
+      target = expand_builtin_unop (arglist, target, subtarget, ffs_optab);
+      if (target)
+       return target;
+      break;
+
+    case BUILT_IN_CLZ:
+    case BUILT_IN_CLZL:
+    case BUILT_IN_CLZLL:
+      target = expand_builtin_unop (arglist, target, subtarget, clz_optab);
+      if (target)
+       return target;
+      break;
+
+    case BUILT_IN_CTZ:
+    case BUILT_IN_CTZL:
+    case BUILT_IN_CTZLL:
+      target = expand_builtin_unop (arglist, target, subtarget, ctz_optab);
+      if (target)
+       return target;
+      break;
+
+    case BUILT_IN_POPCOUNT:
+    case BUILT_IN_POPCOUNTL:
+    case BUILT_IN_POPCOUNTLL:
+      target = expand_builtin_unop (arglist, target, subtarget,
+                                   popcount_optab);
+      if (target)
+       return target;
+      break;
+
+    case BUILT_IN_PARITY:
+    case BUILT_IN_PARITYL:
+    case BUILT_IN_PARITYLL:
+      target = expand_builtin_unop (arglist, target, subtarget, parity_optab);
       if (target)
        return target;
       break;
@@ -4324,10 +4515,30 @@ builtin_mathfn_code (t)
 
   arglist = TREE_OPERAND (t, 1);
   if (! arglist
-      || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != REAL_TYPE
-      || TREE_CHAIN (arglist))
+      || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != REAL_TYPE)
     return END_BUILTINS;
 
+  arglist = TREE_CHAIN (arglist);
+  switch (DECL_FUNCTION_CODE (fndecl))
+    {
+    case BUILT_IN_POW:
+    case BUILT_IN_POWF:
+    case BUILT_IN_POWL:
+    case BUILT_IN_ATAN2:
+    case BUILT_IN_ATAN2F:
+    case BUILT_IN_ATAN2L:
+      if (! arglist
+         || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != REAL_TYPE
+         || TREE_CHAIN (arglist))
+       return END_BUILTINS;
+      break;
+
+    default:
+      if (arglist)
+       return END_BUILTINS;
+      break;
+    }
+
   return DECL_FUNCTION_CODE (fndecl);
 }
 
@@ -4423,6 +4634,36 @@ fold_builtin_nan (arglist, type, quiet)
   return build_real (type, real);
 }
 
+/* EXP is assumed to me builtin call where truncation can be propagated
+   across (for instance floor((double)f) == (double)floorf (f).
+   Do the transformation.  */
+static tree
+fold_trunc_transparent_mathfn (exp)
+     tree exp;
+{
+  tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+  tree arglist = TREE_OPERAND (exp, 1);
+  enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
+
+  if (optimize && validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+    {
+      tree arg0 = strip_float_extensions (TREE_VALUE (arglist));
+      tree ftype = TREE_TYPE (exp);
+      tree newtype = TREE_TYPE (arg0);
+      tree decl;
+
+      if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
+         && (decl = mathfn_built_in (newtype, fcode)))
+       {
+         arglist =
+           build_tree_list (NULL_TREE, fold (convert (newtype, arg0)));
+         return convert (ftype,
+                         build_function_call_expr (decl, arglist));
+       }
+    }
+  return 0;
+}
+
 /* Used by constant folding to eliminate some builtin calls early.  EXP is
    the CALL_EXPR of a call to a builtin function.  */
 
@@ -4432,6 +4673,7 @@ fold_builtin (exp)
 {
   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
   tree arglist = TREE_OPERAND (exp, 1);
+  tree type = TREE_TYPE (TREE_TYPE (fndecl));
   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
 
   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
@@ -4475,10 +4717,10 @@ fold_builtin (exp)
              REAL_VALUE_TYPE r, x;
 
              x = TREE_REAL_CST (arg);
-             mode = TYPE_MODE (TREE_TYPE (arg));
+             mode = TYPE_MODE (type);
              if (real_sqrt (&r, mode, &x)
                  || (!flag_trapping_math && !flag_errno_math))
-               return build_real (TREE_TYPE (arg), r);
+               return build_real (type, r);
            }
 
          /* Optimize sqrt(exp(x)) = exp(x/2.0).  */
@@ -4489,9 +4731,9 @@ fold_builtin (exp)
                  || fcode == BUILT_IN_EXPL))
            {
              tree expfn = TREE_OPERAND (TREE_OPERAND (arg, 0), 0);
-             arg = build (RDIV_EXPR, TREE_TYPE (arg),
+             arg = build (RDIV_EXPR, type,
                           TREE_VALUE (TREE_OPERAND (arg, 1)),
-                          build_real (TREE_TYPE (arg), dconst2));
+                          build_real (type, dconst2));
              arglist = build_tree_list (NULL_TREE, arg);
              return build_function_call_expr (expfn, arglist);
            }
@@ -4508,7 +4750,7 @@ fold_builtin (exp)
 
          /* Optimize exp(0.0) = 1.0.  */
          if (real_zerop (arg))
-           return build_real (TREE_TYPE (arg), dconst1);
+           return build_real (type, dconst1);
 
          /* Optimize exp(log(x)) = x.  */
          fcode = builtin_mathfn_code (arg);
@@ -4530,7 +4772,7 @@ fold_builtin (exp)
 
          /* Optimize log(1.0) = 0.0.  */
          if (real_onep (arg))
-           return build_real (TREE_TYPE (arg), dconst0);
+           return build_real (type, dconst0);
 
          /* Optimize log(exp(x)) = x.  */
          fcode = builtin_mathfn_code (arg);
@@ -4548,31 +4790,66 @@ fold_builtin (exp)
            {
              tree logfn = build_function_call_expr (fndecl,
                                                     TREE_OPERAND (arg, 1));
-             return fold (build (RDIV_EXPR, TREE_TYPE (arg), logfn,
-                                 build_real (TREE_TYPE (arg), dconst2)));
+             return fold (build (RDIV_EXPR, type, logfn,
+                                 build_real (type, dconst2)));
            }
        }
       break;
 
+    case BUILT_IN_POW:
+    case BUILT_IN_POWF:
+    case BUILT_IN_POWL:
+      if (validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
+       {
+         tree arg0 = TREE_VALUE (arglist);
+         tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+
+         /* Optimize pow(x,0.0) = 1.0.  */
+         if (real_zerop (arg1))
+           return omit_one_operand (type, build_real (type, dconst1), arg0);
+
+         /* Optimize pow(1.0,y) = 1.0.  */
+         if (real_onep (arg0))
+           return omit_one_operand (type, build_real (type, dconst1), arg1);
+       }
+      break;
+
     case BUILT_IN_INF:
     case BUILT_IN_INFF:
     case BUILT_IN_INFL:
-      return fold_builtin_inf (TREE_TYPE (TREE_TYPE (fndecl)), true);
+      return fold_builtin_inf (type, true);
 
     case BUILT_IN_HUGE_VAL:
     case BUILT_IN_HUGE_VALF:
     case BUILT_IN_HUGE_VALL:
-      return fold_builtin_inf (TREE_TYPE (TREE_TYPE (fndecl)), false);
+      return fold_builtin_inf (type, false);
 
     case BUILT_IN_NAN:
     case BUILT_IN_NANF:
     case BUILT_IN_NANL:
-      return fold_builtin_nan (arglist, TREE_TYPE (TREE_TYPE (fndecl)), true);
+      return fold_builtin_nan (arglist, type, true);
 
     case BUILT_IN_NANS:
     case BUILT_IN_NANSF:
     case BUILT_IN_NANSL:
-      return fold_builtin_nan (arglist, TREE_TYPE (TREE_TYPE (fndecl)), false);
+      return fold_builtin_nan (arglist, type, false);
+
+    case BUILT_IN_FLOOR:
+    case BUILT_IN_FLOORF:
+    case BUILT_IN_FLOORL:
+    case BUILT_IN_CEIL:
+    case BUILT_IN_CEILF:
+    case BUILT_IN_CEILL:
+    case BUILT_IN_TRUNC:
+    case BUILT_IN_TRUNCF:
+    case BUILT_IN_TRUNCL:
+    case BUILT_IN_ROUND:
+    case BUILT_IN_ROUNDF:
+    case BUILT_IN_ROUNDL:
+    case BUILT_IN_NEARBYINT:
+    case BUILT_IN_NEARBYINTF:
+    case BUILT_IN_NEARBYINTL:
+      return fold_trunc_transparent_mathfn (exp);
 
     default:
       break;
@@ -4670,26 +4947,23 @@ default_expand_builtin (exp, target, subtarget, mode, ignore)
 void
 purge_builtin_constant_p ()
 {
-  rtx insn, done, set;
-  rtx arg, new, note;
-  basic_block bb;
-
-  FOR_EACH_BB (bb)
-    {
-      done = NEXT_INSN (bb->end);
-      for (insn = bb->head; insn != done; insn = NEXT_INSN (insn))
-       if (INSN_P (insn)
-           && (set = single_set (insn)) != NULL_RTX
-           && GET_CODE (SET_SRC (set)) == CONSTANT_P_RTX)
-         {
-           arg = XEXP (SET_SRC (set), 0);
-           new = CONSTANT_P (arg) ? const1_rtx : const0_rtx;
-           validate_change (insn, &SET_SRC (set), new, 0);
+  rtx insn, set, arg, new, note;
+
+  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+    if (INSN_P (insn)
+       && (set = single_set (insn)) != NULL_RTX
+       && (GET_CODE (arg = SET_SRC (set)) == CONSTANT_P_RTX
+           || (GET_CODE (arg) == SUBREG
+               && (GET_CODE (arg = SUBREG_REG (arg))
+                   == CONSTANT_P_RTX))))
+      {
+       arg = XEXP (arg, 0);
+       new = CONSTANT_P (arg) ? const1_rtx : const0_rtx;
+       validate_change (insn, &SET_SRC (set), new, 0);
 
-           /* Remove the REG_EQUAL note from the insn.  */
-           if ((note = find_reg_note (insn, REG_EQUAL, NULL_RTX)) != 0)
-             remove_note (insn, note);
-         }
-    }
+       /* Remove the REG_EQUAL note from the insn.  */
+       if ((note = find_reg_note (insn, REG_EQUAL, NULL_RTX)) != 0)
+         remove_note (insn, note);
+      }
 }