simplify-rtx.c (simplify_binary_operation): Remove fall throughs.
authorRoger Sayle <roger@eyesopen.com>
Mon, 12 Apr 2004 17:28:11 +0000 (17:28 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Mon, 12 Apr 2004 17:28:11 +0000 (17:28 +0000)
* simplify-rtx.c (simplify_binary_operation) <UDIV, DIV, UMOD, MOD>:
Remove fall throughs.  Convert 0/x and 0%x into x&0 when x has
side-effects.  Don't convert x/1.0 into x if we honor signaling NaNs.
Convert x/-1.0 into -x if we don't honor signaling NaNs.  Convert
x/-1 into -x.  Optimize x%1 into x&0 if x has side-effects.  Optimize
x%-1 into 0 (or x&0 if x has side-effects).

From-SVN: r80625

gcc/ChangeLog
gcc/simplify-rtx.c

index 94c8ab5dcdc48abeb22f68715fd7fc761960b1fd..ac9f0c9fef2385e3d904eaa1d2658f547575fcc0 100644 (file)
@@ -1,3 +1,12 @@
+2004-04-12  Roger Sayle  <roger@eyesopen.com>
+
+       * simplify-rtx.c (simplify_binary_operation) <UDIV, DIV, UMOD, MOD>:
+       Remove fall throughs.  Convert 0/x and 0%x into x&0 when x has
+       side-effects.  Don't convert x/1.0 into x if we honor signaling NaNs.
+       Convert x/-1.0 into -x if we don't honor signaling NaNs.  Convert
+       x/-1 into -x.  Optimize x%1 into x&0 if x has side-effects.  Optimize
+       x%-1 into 0 (or x&0 if x has side-effects).
+
 2004-04-11  Aldy Hernandez  <aldyh@redhat.com>
 
        * config/rs6000/rs6000.md: Document why a pattern is not
index 49f2d37bd15bffa70f865aa9ddf93fc152654ac1..b6340e54c8b8c1ab7bedd9c280f76aeb09a6fe6e 100644 (file)
@@ -1900,70 +1900,127 @@ simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
          break;
 
        case UDIV:
-         /* Convert divide by power of two into shift (divide by 1 handled
-            below).  */
-         if (GET_CODE (trueop1) == CONST_INT
-             && (arg1 = exact_log2 (INTVAL (trueop1))) > 0)
-           return simplify_gen_binary (LSHIFTRT, mode, op0, GEN_INT (arg1));
-
-         /* Fall through....  */
-
-       case DIV:
-         if (trueop1 == CONST1_RTX (mode))
+         /* 0/x is 0 (or x&0 if x has side-effects).  */
+         if (trueop0 == const0_rtx)
+           return side_effects_p (op1)
+                  ? simplify_gen_binary (AND, mode, op1, const0_rtx)
+                  : const0_rtx;
+         /* x/1 is x.  */
+         if (trueop1 == const1_rtx)
            {
-             /* On some platforms DIV uses narrower mode than its
-                operands.  */
+             /* Handle narrowing UDIV.  */
              rtx x = gen_lowpart_common (mode, op0);
              if (x)
                return x;
-             else if (mode != GET_MODE (op0) && GET_MODE (op0) != VOIDmode)
+             if (mode != GET_MODE (op0) && GET_MODE (op0) != VOIDmode)
                return gen_lowpart_SUBREG (mode, op0);
-             else
-               return op0;
+             return op0;
            }
+         /* Convert divide by power of two into shift.  */
+         if (GET_CODE (trueop1) == CONST_INT
+             && (arg1 = exact_log2 (INTVAL (trueop1))) > 0)
+           return simplify_gen_binary (LSHIFTRT, mode, op0, GEN_INT (arg1));
+         break;
 
-         /* Maybe change 0 / x to 0.  This transformation isn't safe for
-            modes with NaNs, since 0 / 0 will then be NaN rather than 0.
-            Nor is it safe for modes with signed zeros, since dividing
-            0 by a negative number gives -0, not 0.  */
-         if (!HONOR_NANS (mode)
-             && !HONOR_SIGNED_ZEROS (mode)
-             && trueop0 == CONST0_RTX (mode)
-             && ! side_effects_p (op1))
-           return op0;
-
-         /* Change division by a constant into multiplication.  Only do
-            this with -funsafe-math-optimizations.  */
-         else if (GET_CODE (trueop1) == CONST_DOUBLE
-                  && GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_FLOAT
-                  && trueop1 != CONST0_RTX (mode)
-                  && flag_unsafe_math_optimizations)
+       case DIV:
+         /* Handle floating point and integers separately.  */
+         if (GET_MODE_CLASS (mode) == MODE_FLOAT)
            {
-             REAL_VALUE_TYPE d;
-             REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1);
+             /* Maybe change 0.0 / x to 0.0.  This transformation isn't
+                safe for modes with NaNs, since 0.0 / 0.0 will then be
+                NaN rather than 0.0.  Nor is it safe for modes with signed
+                zeros, since dividing 0 by a negative number gives -0.0  */
+             if (trueop0 == CONST0_RTX (mode)
+                 && !HONOR_NANS (mode)
+                 && !HONOR_SIGNED_ZEROS (mode)
+                 && ! side_effects_p (op1))
+               return op0;
+             /* x/1.0 is x.  */
+             if (trueop1 == CONST1_RTX (mode)
+                 && !HONOR_SNANS (mode))
+               return op0;
 
-             if (! REAL_VALUES_EQUAL (d, dconst0))
+             if (GET_CODE (trueop1) == CONST_DOUBLE
+                 && trueop1 != CONST0_RTX (mode))
+               {
+                 REAL_VALUE_TYPE d;
+                 REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1);
+
+                 /* x/-1.0 is -x.  */
+                 if (REAL_VALUES_EQUAL (d, dconstm1)
+                     && !HONOR_SNANS (mode))
+                   return simplify_gen_unary (NEG, mode, op0, mode);
+
+                 /* Change FP division by a constant into multiplication.
+                    Only do this with -funsafe-math-optimizations.  */
+                 if (flag_unsafe_math_optimizations
+                     && !REAL_VALUES_EQUAL (d, dconst0))
+                   {
+                     REAL_ARITHMETIC (d, RDIV_EXPR, dconst1, d);
+                     tem = CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
+                     return simplify_gen_binary (MULT, mode, op0, tem);
+                   }
+               }
+           }
+         else
+           {
+             /* 0/x is 0 (or x&0 if x has side-effects).  */
+             if (trueop0 == const0_rtx)
+               return side_effects_p (op1)
+                      ? simplify_gen_binary (AND, mode, op1, const0_rtx)
+                      : const0_rtx;
+             /* x/1 is x.  */
+             if (trueop1 == const1_rtx)
+               {
+                 /* Handle narrowing DIV.  */
+                 rtx x = gen_lowpart_common (mode, op0);
+                 if (x)
+                   return x;
+                 if (mode != GET_MODE (op0) && GET_MODE (op0) != VOIDmode)
+                   return gen_lowpart_SUBREG (mode, op0);
+                 return op0;
+               }
+             /* x/-1 is -x.  */
+             if (trueop1 == constm1_rtx)
                {
-                 REAL_ARITHMETIC (d, rtx_to_tree_code (DIV), dconst1, d);
-                 tem = CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
-                 return simplify_gen_binary (MULT, mode, op0, tem);
+                 rtx x = gen_lowpart_common (mode, op0);
+                 if (!x)
+                   x = (mode != GET_MODE (op0) && GET_MODE (op0) != VOIDmode)
+                       ? gen_lowpart_SUBREG (mode, op0) : op0;
+                 return simplify_gen_unary (NEG, mode, x, mode);
                }
            }
          break;
 
        case UMOD:
-         /* Handle modulus by power of two (mod with 1 handled below).  */
+         /* 0%x is 0 (or x&0 if x has side-effects).  */
+         if (trueop0 == const0_rtx)
+           return side_effects_p (op1)
+                  ? simplify_gen_binary (AND, mode, op1, const0_rtx)
+                  : const0_rtx;
+         /* x%1 is 0 (of x&0 if x has side-effects).  */
+         if (trueop1 == const1_rtx)
+           return side_effects_p (op0)
+                  ? simplify_gen_binary (AND, mode, op0, const0_rtx)
+                  : const0_rtx;
+         /* Implement modulus by power of two as AND.  */
          if (GET_CODE (trueop1) == CONST_INT
              && exact_log2 (INTVAL (trueop1)) > 0)
            return simplify_gen_binary (AND, mode, op0,
                                        GEN_INT (INTVAL (op1) - 1));
-
-         /* Fall through....  */
+         break;
 
        case MOD:
-         if ((trueop0 == const0_rtx || trueop1 == const1_rtx)
-             && ! side_effects_p (op0) && ! side_effects_p (op1))
-           return const0_rtx;
+         /* 0%x is 0 (or x&0 if x has side-effects).  */
+         if (trueop0 == const0_rtx)
+           return side_effects_p (op1)
+                  ? simplify_gen_binary (AND, mode, op1, const0_rtx)
+                  : const0_rtx;
+         /* x%1 and x%-1 is 0 (or x&0 if x has side-effects).  */
+         if (trueop1 == const1_rtx || trueop1 == constm1_rtx)
+           return side_effects_p (op0)
+                  ? simplify_gen_binary (AND, mode, op0, const0_rtx)
+                  : const0_rtx;
          break;
 
        case ROTATERT: