Move some complex simplifications to match.pd
[platform/upstream/gcc.git] / gcc / fold-const.c
index f2bb602..a5d58a8 100644 (file)
@@ -7732,21 +7732,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
        }
       return NULL_TREE;
 
-    case CONJ_EXPR:
-      if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
-       return fold_convert_loc (loc, type, arg0);
-      if (TREE_CODE (arg0) == COMPLEX_EXPR)
-       {
-         tree itype = TREE_TYPE (type);
-         tree rpart = fold_convert_loc (loc, itype, TREE_OPERAND (arg0, 0));
-         tree ipart = fold_convert_loc (loc, itype, TREE_OPERAND (arg0, 1));
-         return fold_build2_loc (loc, COMPLEX_EXPR, type, rpart,
-                             negate_expr (ipart));
-       }
-      if (TREE_CODE (arg0) == CONJ_EXPR)
-       return fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
-      return NULL_TREE;
-
     case BIT_NOT_EXPR:
       /* Convert ~(X ^ Y) to ~X ^ Y or X ^ ~Y if ~X or ~Y simplify.  */
       if (TREE_CODE (arg0) == BIT_XOR_EXPR
@@ -7776,81 +7761,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0)
        return NULL_TREE;
       return fold_convert_loc (loc, type, tem);
 
-    case REALPART_EXPR:
-      if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
-       return fold_convert_loc (loc, type, arg0);
-      if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
-       {
-         tree itype = TREE_TYPE (TREE_TYPE (arg0));
-         tem = fold_build2_loc (loc, TREE_CODE (arg0), itype,
-                            fold_build1_loc (loc, REALPART_EXPR, itype,
-                                         TREE_OPERAND (arg0, 0)),
-                            fold_build1_loc (loc, REALPART_EXPR, itype,
-                                         TREE_OPERAND (arg0, 1)));
-         return fold_convert_loc (loc, type, tem);
-       }
-      if (TREE_CODE (arg0) == CONJ_EXPR)
-       {
-         tree itype = TREE_TYPE (TREE_TYPE (arg0));
-         tem = fold_build1_loc (loc, REALPART_EXPR, itype,
-                            TREE_OPERAND (arg0, 0));
-         return fold_convert_loc (loc, type, tem);
-       }
-      if (TREE_CODE (arg0) == CALL_EXPR)
-       {
-         tree fn = get_callee_fndecl (arg0);
-         if (fn && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL)
-           switch (DECL_FUNCTION_CODE (fn))
-             {
-             CASE_FLT_FN (BUILT_IN_CEXPI):
-               fn = mathfn_built_in (type, BUILT_IN_COS);
-               if (fn)
-                 return build_call_expr_loc (loc, fn, 1, CALL_EXPR_ARG (arg0, 0));
-               break;
-
-             default:
-               break;
-             }
-       }
-      return NULL_TREE;
-
-    case IMAGPART_EXPR:
-      if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
-       return build_zero_cst (type);
-      if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
-       {
-         tree itype = TREE_TYPE (TREE_TYPE (arg0));
-         tem = fold_build2_loc (loc, TREE_CODE (arg0), itype,
-                            fold_build1_loc (loc, IMAGPART_EXPR, itype,
-                                         TREE_OPERAND (arg0, 0)),
-                            fold_build1_loc (loc, IMAGPART_EXPR, itype,
-                                         TREE_OPERAND (arg0, 1)));
-         return fold_convert_loc (loc, type, tem);
-       }
-      if (TREE_CODE (arg0) == CONJ_EXPR)
-       {
-         tree itype = TREE_TYPE (TREE_TYPE (arg0));
-         tem = fold_build1_loc (loc, IMAGPART_EXPR, itype, TREE_OPERAND (arg0, 0));
-         return fold_convert_loc (loc, type, negate_expr (tem));
-       }
-      if (TREE_CODE (arg0) == CALL_EXPR)
-       {
-         tree fn = get_callee_fndecl (arg0);
-         if (fn && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL)
-           switch (DECL_FUNCTION_CODE (fn))
-             {
-             CASE_FLT_FN (BUILT_IN_CEXPI):
-               fn = mathfn_built_in (type, BUILT_IN_SIN);
-               if (fn)
-                 return build_call_expr_loc (loc, fn, 1, CALL_EXPR_ARG (arg0, 0));
-               break;
-
-             default:
-               break;
-             }
-       }
-      return NULL_TREE;
-
     case INDIRECT_REF:
       /* Fold *&X to X if X is an lvalue.  */
       if (TREE_CODE (op0) == ADDR_EXPR)
@@ -9421,7 +9331,7 @@ fold_binary_loc (location_t loc,
            /* Only create rotates in complete modes.  Other cases are not
               expanded properly.  */
            && (element_precision (rtype)
-               == element_precision (TYPE_MODE (rtype))))
+               == GET_MODE_UNIT_PRECISION (TYPE_MODE (rtype))))
          {
            tree tree01, tree11;
            enum tree_code code01, code11;
@@ -9947,127 +9857,6 @@ fold_binary_loc (location_t loc,
 
          if (flag_unsafe_math_optimizations)
            {
-             enum built_in_function fcode0 = builtin_mathfn_code (arg0);
-             enum built_in_function fcode1 = builtin_mathfn_code (arg1);
-
-             /* Optimizations of root(...)*root(...).  */
-             if (fcode0 == fcode1 && BUILTIN_ROOT_P (fcode0))
-               {
-                 tree rootfn, arg;
-                 tree arg00 = CALL_EXPR_ARG (arg0, 0);
-                 tree arg10 = CALL_EXPR_ARG (arg1, 0);
-
-                 /* Optimize sqrt(x)*sqrt(x) as x.  */
-                 if (BUILTIN_SQRT_P (fcode0)
-                     && operand_equal_p (arg00, arg10, 0)
-                     && ! HONOR_SNANS (element_mode (type)))
-                   return arg00;
-
-                 /* Optimize root(x)*root(y) as root(x*y).  */
-                 rootfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
-                 arg = fold_build2_loc (loc, MULT_EXPR, type, arg00, arg10);
-                 return build_call_expr_loc (loc, rootfn, 1, arg);
-               }
-
-             /* Optimize expN(x)*expN(y) as expN(x+y).  */
-             if (fcode0 == fcode1 && BUILTIN_EXPONENT_P (fcode0))
-               {
-                 tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
-                 tree arg = fold_build2_loc (loc, PLUS_EXPR, type,
-                                         CALL_EXPR_ARG (arg0, 0),
-                                         CALL_EXPR_ARG (arg1, 0));
-                 return build_call_expr_loc (loc, expfn, 1, arg);
-               }
-
-             /* Optimizations of pow(...)*pow(...).  */
-             if ((fcode0 == BUILT_IN_POW && fcode1 == BUILT_IN_POW)
-                 || (fcode0 == BUILT_IN_POWF && fcode1 == BUILT_IN_POWF)
-                 || (fcode0 == BUILT_IN_POWL && fcode1 == BUILT_IN_POWL))
-               {
-                 tree arg00 = CALL_EXPR_ARG (arg0, 0);
-                 tree arg01 = CALL_EXPR_ARG (arg0, 1);
-                 tree arg10 = CALL_EXPR_ARG (arg1, 0);
-                 tree arg11 = CALL_EXPR_ARG (arg1, 1);
-
-                 /* Optimize pow(x,y)*pow(z,y) as pow(x*z,y).  */
-                 if (operand_equal_p (arg01, arg11, 0))
-                   {
-                     tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
-                     tree arg = fold_build2_loc (loc, MULT_EXPR, type,
-                                             arg00, arg10);
-                     return build_call_expr_loc (loc, powfn, 2, arg, arg01);
-                   }
-
-                 /* Optimize pow(x,y)*pow(x,z) as pow(x,y+z).  */
-                 if (operand_equal_p (arg00, arg10, 0))
-                   {
-                     tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
-                     tree arg = fold_build2_loc (loc, PLUS_EXPR, type,
-                                             arg01, arg11);
-                     return build_call_expr_loc (loc, powfn, 2, arg00, arg);
-                   }
-               }
-
-             /* Optimize tan(x)*cos(x) as sin(x).  */
-             if (((fcode0 == BUILT_IN_TAN && fcode1 == BUILT_IN_COS)
-                  || (fcode0 == BUILT_IN_TANF && fcode1 == BUILT_IN_COSF)
-                  || (fcode0 == BUILT_IN_TANL && fcode1 == BUILT_IN_COSL)
-                  || (fcode0 == BUILT_IN_COS && fcode1 == BUILT_IN_TAN)
-                  || (fcode0 == BUILT_IN_COSF && fcode1 == BUILT_IN_TANF)
-                  || (fcode0 == BUILT_IN_COSL && fcode1 == BUILT_IN_TANL))
-                 && operand_equal_p (CALL_EXPR_ARG (arg0, 0),
-                                     CALL_EXPR_ARG (arg1, 0), 0))
-               {
-                 tree sinfn = mathfn_built_in (type, BUILT_IN_SIN);
-
-                 if (sinfn != NULL_TREE)
-                   return build_call_expr_loc (loc, sinfn, 1,
-                                           CALL_EXPR_ARG (arg0, 0));
-               }
-
-             /* Optimize x*pow(x,c) as pow(x,c+1).  */
-             if (fcode1 == BUILT_IN_POW
-                 || fcode1 == BUILT_IN_POWF
-                 || fcode1 == BUILT_IN_POWL)
-               {
-                 tree arg10 = CALL_EXPR_ARG (arg1, 0);
-                 tree arg11 = CALL_EXPR_ARG (arg1, 1);
-                 if (TREE_CODE (arg11) == REAL_CST
-                     && !TREE_OVERFLOW (arg11)
-                     && operand_equal_p (arg0, arg10, 0))
-                   {
-                     tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg1), 0);
-                     REAL_VALUE_TYPE c;
-                     tree arg;
-
-                     c = TREE_REAL_CST (arg11);
-                     real_arithmetic (&c, PLUS_EXPR, &c, &dconst1);
-                     arg = build_real (type, c);
-                     return build_call_expr_loc (loc, powfn, 2, arg0, arg);
-                   }
-               }
-
-             /* Optimize pow(x,c)*x as pow(x,c+1).  */
-             if (fcode0 == BUILT_IN_POW
-                 || fcode0 == BUILT_IN_POWF
-                 || fcode0 == BUILT_IN_POWL)
-               {
-                 tree arg00 = CALL_EXPR_ARG (arg0, 0);
-                 tree arg01 = CALL_EXPR_ARG (arg0, 1);
-                 if (TREE_CODE (arg01) == REAL_CST
-                     && !TREE_OVERFLOW (arg01)
-                     && operand_equal_p (arg1, arg00, 0))
-                   {
-                     tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
-                     REAL_VALUE_TYPE c;
-                     tree arg;
-
-                     c = TREE_REAL_CST (arg01);
-                     real_arithmetic (&c, PLUS_EXPR, &c, &dconst1);
-                     arg = build_real (type, c);
-                     return build_call_expr_loc (loc, powfn, 2, arg1, arg);
-                   }
-               }
 
              /* Canonicalize x*x as pow(x,2.0), which is expanded as x*x.  */
              if (!in_gimple_form
@@ -10479,152 +10268,6 @@ fold_binary_loc (location_t loc,
                                TREE_OPERAND (arg1, 0));
        }
 
-      if (flag_unsafe_math_optimizations)
-       {
-         enum built_in_function fcode0 = builtin_mathfn_code (arg0);
-         enum built_in_function fcode1 = builtin_mathfn_code (arg1);
-
-         /* Optimize sin(x)/cos(x) as tan(x).  */
-         if (((fcode0 == BUILT_IN_SIN && fcode1 == BUILT_IN_COS)
-              || (fcode0 == BUILT_IN_SINF && fcode1 == BUILT_IN_COSF)
-              || (fcode0 == BUILT_IN_SINL && fcode1 == BUILT_IN_COSL))
-             && operand_equal_p (CALL_EXPR_ARG (arg0, 0),
-                                 CALL_EXPR_ARG (arg1, 0), 0))
-           {
-             tree tanfn = mathfn_built_in (type, BUILT_IN_TAN);
-
-             if (tanfn != NULL_TREE)
-               return build_call_expr_loc (loc, tanfn, 1, CALL_EXPR_ARG (arg0, 0));
-           }
-
-         /* Optimize cos(x)/sin(x) as 1.0/tan(x).  */
-         if (((fcode0 == BUILT_IN_COS && fcode1 == BUILT_IN_SIN)
-              || (fcode0 == BUILT_IN_COSF && fcode1 == BUILT_IN_SINF)
-              || (fcode0 == BUILT_IN_COSL && fcode1 == BUILT_IN_SINL))
-             && operand_equal_p (CALL_EXPR_ARG (arg0, 0),
-                                 CALL_EXPR_ARG (arg1, 0), 0))
-           {
-             tree tanfn = mathfn_built_in (type, BUILT_IN_TAN);
-
-             if (tanfn != NULL_TREE)
-               {
-                 tree tmp = build_call_expr_loc (loc, tanfn, 1,
-                                             CALL_EXPR_ARG (arg0, 0));
-                 return fold_build2_loc (loc, RDIV_EXPR, type,
-                                     build_real (type, dconst1), tmp);
-               }
-           }
-
-         /* Optimize sin(x)/tan(x) as cos(x) if we don't care about
-            NaNs or Infinities.  */
-         if (((fcode0 == BUILT_IN_SIN && fcode1 == BUILT_IN_TAN)
-              || (fcode0 == BUILT_IN_SINF && fcode1 == BUILT_IN_TANF)
-              || (fcode0 == BUILT_IN_SINL && fcode1 == BUILT_IN_TANL)))
-           {
-             tree arg00 = CALL_EXPR_ARG (arg0, 0);
-             tree arg01 = CALL_EXPR_ARG (arg1, 0);
-
-             if (! HONOR_NANS (arg00)
-                 && ! HONOR_INFINITIES (element_mode (arg00))
-                 && operand_equal_p (arg00, arg01, 0))
-               {
-                 tree cosfn = mathfn_built_in (type, BUILT_IN_COS);
-
-                 if (cosfn != NULL_TREE)
-                   return build_call_expr_loc (loc, cosfn, 1, arg00);
-               }
-           }
-
-         /* Optimize tan(x)/sin(x) as 1.0/cos(x) if we don't care about
-            NaNs or Infinities.  */
-         if (((fcode0 == BUILT_IN_TAN && fcode1 == BUILT_IN_SIN)
-              || (fcode0 == BUILT_IN_TANF && fcode1 == BUILT_IN_SINF)
-              || (fcode0 == BUILT_IN_TANL && fcode1 == BUILT_IN_SINL)))
-           {
-             tree arg00 = CALL_EXPR_ARG (arg0, 0);
-             tree arg01 = CALL_EXPR_ARG (arg1, 0);
-
-             if (! HONOR_NANS (arg00)
-                 && ! HONOR_INFINITIES (element_mode (arg00))
-                 && operand_equal_p (arg00, arg01, 0))
-               {
-                 tree cosfn = mathfn_built_in (type, BUILT_IN_COS);
-
-                 if (cosfn != NULL_TREE)
-                   {
-                     tree tmp = build_call_expr_loc (loc, cosfn, 1, arg00);
-                     return fold_build2_loc (loc, RDIV_EXPR, type,
-                                         build_real (type, dconst1),
-                                         tmp);
-                   }
-               }
-           }
-
-         /* Optimize pow(x,c)/x as pow(x,c-1).  */
-         if (fcode0 == BUILT_IN_POW
-             || fcode0 == BUILT_IN_POWF
-             || fcode0 == BUILT_IN_POWL)
-           {
-             tree arg00 = CALL_EXPR_ARG (arg0, 0);
-             tree arg01 = CALL_EXPR_ARG (arg0, 1);
-             if (TREE_CODE (arg01) == REAL_CST
-                 && !TREE_OVERFLOW (arg01)
-                 && operand_equal_p (arg1, arg00, 0))
-               {
-                 tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0);
-                 REAL_VALUE_TYPE c;
-                 tree arg;
-
-                 c = TREE_REAL_CST (arg01);
-                 real_arithmetic (&c, MINUS_EXPR, &c, &dconst1);
-                 arg = build_real (type, c);
-                 return build_call_expr_loc (loc, powfn, 2, arg1, arg);
-               }
-           }
-
-         /* Optimize a/root(b/c) into a*root(c/b).  */
-         if (BUILTIN_ROOT_P (fcode1))
-           {
-             tree rootarg = CALL_EXPR_ARG (arg1, 0);
-
-             if (TREE_CODE (rootarg) == RDIV_EXPR)
-               {
-                 tree rootfn = TREE_OPERAND (CALL_EXPR_FN (arg1), 0);
-                 tree b = TREE_OPERAND (rootarg, 0);
-                 tree c = TREE_OPERAND (rootarg, 1);
-
-                 tree tmp = fold_build2_loc (loc, RDIV_EXPR, type, c, b);
-
-                 tmp = build_call_expr_loc (loc, rootfn, 1, tmp);
-                 return fold_build2_loc (loc, MULT_EXPR, type, arg0, tmp);
-               }
-           }
-
-         /* Optimize x/expN(y) into x*expN(-y).  */
-         if (BUILTIN_EXPONENT_P (fcode1))
-           {
-             tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg1), 0);
-             tree arg = negate_expr (CALL_EXPR_ARG (arg1, 0));
-             arg1 = build_call_expr_loc (loc,
-                                     expfn, 1,
-                                     fold_convert_loc (loc, type, arg));
-             return fold_build2_loc (loc, MULT_EXPR, type, arg0, arg1);
-           }
-
-         /* Optimize x/pow(y,z) into x*pow(y,-z).  */
-         if (fcode1 == BUILT_IN_POW
-             || fcode1 == BUILT_IN_POWF
-             || fcode1 == BUILT_IN_POWL)
-           {
-             tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg1), 0);
-             tree arg10 = CALL_EXPR_ARG (arg1, 0);
-             tree arg11 = CALL_EXPR_ARG (arg1, 1);
-             tree neg11 = fold_convert_loc (loc, type,
-                                            negate_expr (arg11));
-             arg1 = build_call_expr_loc (loc, powfn, 2, arg10, neg11);
-             return fold_build2_loc (loc, MULT_EXPR, type, arg0, arg1);
-           }
-       }
       return NULL_TREE;
 
     case TRUNC_DIV_EXPR:
@@ -11002,17 +10645,6 @@ fold_binary_loc (location_t loc,
          && code == NE_EXPR)
         return non_lvalue_loc (loc, fold_convert_loc (loc, type, arg0));
 
-      /* Similarly for a BIT_XOR_EXPR;  X ^ C1 == C2 is X == (C1 ^ C2).  */
-      if (TREE_CODE (arg0) == BIT_XOR_EXPR
-         && TREE_CODE (arg1) == INTEGER_CST
-         && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST)
-       return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
-                           fold_build2_loc (loc, BIT_XOR_EXPR, TREE_TYPE (arg0),
-                                        fold_convert_loc (loc,
-                                                          TREE_TYPE (arg0),
-                                                          arg1),
-                                        TREE_OPERAND (arg0, 1)));
-
       /* Transform comparisons of the form X +- Y CMP X to Y CMP 0.  */
       if ((TREE_CODE (arg0) == PLUS_EXPR
           || TREE_CODE (arg0) == POINTER_PLUS_EXPR
@@ -11693,45 +11325,6 @@ fold_binary_loc (location_t loc,
     case UNGE_EXPR:
     case UNEQ_EXPR:
     case LTGT_EXPR:
-      if (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) == REAL_CST)
-       {
-         t1 = fold_relational_const (code, type, arg0, arg1);
-         if (t1 != NULL_TREE)
-           return t1;
-       }
-
-      /* If the first operand is NaN, the result is constant.  */
-      if (TREE_CODE (arg0) == REAL_CST
-         && REAL_VALUE_ISNAN (TREE_REAL_CST (arg0))
-         && (code != LTGT_EXPR || ! flag_trapping_math))
-       {
-         t1 = (code == ORDERED_EXPR || code == LTGT_EXPR)
-              ? integer_zero_node
-              : integer_one_node;
-         return omit_one_operand_loc (loc, type, t1, arg1);
-       }
-
-      /* If the second operand is NaN, the result is constant.  */
-      if (TREE_CODE (arg1) == REAL_CST
-         && REAL_VALUE_ISNAN (TREE_REAL_CST (arg1))
-         && (code != LTGT_EXPR || ! flag_trapping_math))
-       {
-         t1 = (code == ORDERED_EXPR || code == LTGT_EXPR)
-              ? integer_zero_node
-              : integer_one_node;
-         return omit_one_operand_loc (loc, type, t1, arg0);
-       }
-
-      /* Simplify unordered comparison of something with itself.  */
-      if ((code == UNLE_EXPR || code == UNGE_EXPR || code == UNEQ_EXPR)
-         && operand_equal_p (arg0, arg1, 0))
-       return constant_boolean_node (1, type);
-
-      if (code == LTGT_EXPR
-         && !flag_trapping_math
-         && operand_equal_p (arg0, arg1, 0))
-       return constant_boolean_node (0, type);
-
       /* Fold (double)float1 CMP (double)float2 into float1 CMP float2.  */
       {
        tree targ0 = strip_float_extensions (arg0);