Move fold_trunc_transparent_mathfn to match.pd
[gcc.git] / gcc / match.pd
index c5aa001cd71e0d3021384646d463f86155121a86..060363656f3620c5eb48ed7a353ce6e19ac55c42 100644 (file)
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3.  If not see
    zerop
    CONSTANT_CLASS_P
    tree_expr_nonnegative_p
+   integer_valued_real_p
    integer_pow2p
    HONOR_NANS)
 
@@ -59,6 +60,7 @@ along with GCC; see the file COPYING3.  If not see
 (define_operator_list SIN BUILT_IN_SINF BUILT_IN_SIN BUILT_IN_SINL)
 (define_operator_list COS BUILT_IN_COSF BUILT_IN_COS BUILT_IN_COSL)
 (define_operator_list TAN BUILT_IN_TANF BUILT_IN_TAN BUILT_IN_TANL)
+(define_operator_list ATAN BUILT_IN_ATANF BUILT_IN_ATAN BUILT_IN_ATANL)
 (define_operator_list COSH BUILT_IN_COSHF BUILT_IN_COSH BUILT_IN_COSHL)
 (define_operator_list CEXPI BUILT_IN_CEXPIF BUILT_IN_CEXPI BUILT_IN_CEXPIL)
 (define_operator_list CPROJ BUILT_IN_CPROJF BUILT_IN_CPROJ BUILT_IN_CPROJL)
@@ -68,6 +70,15 @@ along with GCC; see the file COPYING3.  If not see
 (define_operator_list COPYSIGN BUILT_IN_COPYSIGNF
                               BUILT_IN_COPYSIGN
                               BUILT_IN_COPYSIGNL)
+(define_operator_list CABS BUILT_IN_CABSF BUILT_IN_CABS BUILT_IN_CABSL)
+(define_operator_list TRUNC BUILT_IN_TRUNCF BUILT_IN_TRUNC BUILT_IN_TRUNCL)
+(define_operator_list FLOOR BUILT_IN_FLOORF BUILT_IN_FLOOR BUILT_IN_FLOORL)
+(define_operator_list CEIL BUILT_IN_CEILF BUILT_IN_CEIL BUILT_IN_CEILL)
+(define_operator_list ROUND BUILT_IN_ROUNDF BUILT_IN_ROUND BUILT_IN_ROUNDL)
+(define_operator_list NEARBYINT BUILT_IN_NEARBYINTF
+                               BUILT_IN_NEARBYINT
+                               BUILT_IN_NEARBYINTL)
+(define_operator_list RINT BUILT_IN_RINTF BUILT_IN_RINT BUILT_IN_RINTL)
 
 /* Simplifications of operations with one constant operand and
    simplifications to constants or single values.  */
@@ -394,6 +405,13 @@ along with GCC; see the file COPYING3.  If not see
   (ccoss (negate @0))
    (ccoss @0)))
 
+/* cabs(-x) and cos(conj(x)) -> cabs(x).  */
+(for ops (conj negate)
+ (for cabss (CABS)
+  (simplify
+   (cabss (ops @0))
+   (cabss @0))))
+
 /* Fold (a * (1 << b)) into (a << b)  */
 (simplify
  (mult:c @0 (convert? (lshift integer_onep@1 @2)))
@@ -1047,7 +1065,57 @@ along with GCC; see the file COPYING3.  If not see
         || (POINTER_TYPE_P (TREE_TYPE (@0))
             && TREE_CODE (@1) == INTEGER_CST
             && tree_int_cst_sign_bit (@1) == 0))
-     (convert @1))))))
+     (convert @1))))
+
+  /* (T)P - (T)(P + A) -> -(T) A */
+  (for add (plus pointer_plus)
+   (simplify
+    (minus (convert @0)
+     (convert (add @0 @1)))
+    (if (element_precision (type) <= element_precision (TREE_TYPE (@1))
+        /* For integer types, if A has a smaller type
+           than T the result depends on the possible
+           overflow in P + A.
+           E.g. T=size_t, A=(unsigned)429497295, P>0.
+           However, if an overflow in P + A would cause
+           undefined behavior, we can assume that there
+           is no overflow.  */
+        || (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+            && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+        /* For pointer types, if the conversion of A to the
+           final type requires a sign- or zero-extension,
+           then we have to punt - it is not defined which
+           one is correct.  */
+        || (POINTER_TYPE_P (TREE_TYPE (@0))
+            && TREE_CODE (@1) == INTEGER_CST
+            && tree_int_cst_sign_bit (@1) == 0))
+     (negate (convert @1)))))
+
+  /* (T)(P + A) - (T)(P + B) -> (T)A - (T)B */
+  (for add (plus pointer_plus)
+   (simplify
+    (minus (convert (add @0 @1))
+     (convert (add @0 @2)))
+    (if (element_precision (type) <= element_precision (TREE_TYPE (@1))
+        /* For integer types, if A has a smaller type
+           than T the result depends on the possible
+           overflow in P + A.
+           E.g. T=size_t, A=(unsigned)429497295, P>0.
+           However, if an overflow in P + A would cause
+           undefined behavior, we can assume that there
+           is no overflow.  */
+        || (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+            && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (@0)))
+        /* For pointer types, if the conversion of A to the
+           final type requires a sign- or zero-extension,
+           then we have to punt - it is not defined which
+           one is correct.  */
+        || (POINTER_TYPE_P (TREE_TYPE (@0))
+            && TREE_CODE (@1) == INTEGER_CST
+            && tree_int_cst_sign_bit (@1) == 0
+            && TREE_CODE (@2) == INTEGER_CST
+            && tree_int_cst_sign_bit (@2) == 0))
+     (minus (convert @1) (convert @2)))))))
 
 
 /* Simplifications of MIN_EXPR and MAX_EXPR.  */
@@ -2366,7 +2434,36 @@ along with GCC; see the file COPYING3.  If not see
   /* cbrt(expN(x)) -> expN(x/3).  */
   (simplify
    (cbrts (exps @0))
-   (exps (mult @0 { build_real_truncate (type, dconst_third ()); })))))
+   (exps (mult @0 { build_real_truncate (type, dconst_third ()); }))))
+
+ /* tan(atan(x)) -> x.  */
+ (for tans (TAN)
+      atans (ATAN)
+  (simplify
+   (tans (atans @0))
+   @0)))
+
+/* cabs(x+0i) or cabs(0+xi) -> abs(x).  */
+(simplify
+ (CABS (complex:c @0 real_zerop@1))
+ (abs @0))
+
+/* trunc(trunc(x)) -> trunc(x), etc.  */
+(for fns (TRUNC FLOOR CEIL ROUND NEARBYINT RINT)
+ (simplify
+  (fns (fns @0))
+  (fns @0)))
+/* f(x) -> x if x is integer valued and f does nothing for such values.  */
+(for fns (TRUNC FLOOR CEIL ROUND NEARBYINT)
+ (simplify
+  (fns integer_valued_real_p@0)
+  @0))
+/* Same for rint.  We have to check flag_errno_math because
+   integer_valued_real_p accepts +Inf, -Inf and NaNs as integers.  */
+(if (!flag_errno_math)
+ (simplify
+  (RINT integer_valued_real_p@0)
+  @0))
 
 /* Canonicalization of sequences of math builtins.  These rules represent
    IL simplifications but are not necessarily optimizations.
@@ -2459,32 +2556,82 @@ along with GCC; see the file COPYING3.  If not see
   /* cbrt(pow(x,y)) -> pow(x,y/3), iff x is nonnegative.  */
   (simplify
    (cbrts (pows tree_expr_nonnegative_p@0 @1))
-   (pows @0 (mult @1 { build_real_truncate (type, dconst_third ()); })))))
+   (pows @0 (mult @1 { build_real_truncate (type, dconst_third ()); }))))
+
+ /* cabs(x+xi) -> fabs(x)*sqrt(2).  */
+ (simplify
+  (CABS (complex @0 @0))
+  (mult (abs @0) { build_real_truncate (type, dconst_sqrt2 ()); })))
+
+(if (canonicalize_math_p ())
+ /* floor(x) -> trunc(x) if x is nonnegative.  */
+ (for floors (FLOOR)
+      truncs (TRUNC)
+  (simplify
+   (floors tree_expr_nonnegative_p@0)
+   (truncs @0))))
+
+(match double_value_p
+ @0
+ (if (TYPE_MAIN_VARIANT (TREE_TYPE (@0)) == double_type_node)))
+(for froms (BUILT_IN_TRUNCL
+           BUILT_IN_FLOORL
+           BUILT_IN_CEILL
+           BUILT_IN_ROUNDL
+           BUILT_IN_NEARBYINTL
+           BUILT_IN_RINTL)
+     tos (BUILT_IN_TRUNC
+         BUILT_IN_FLOOR
+         BUILT_IN_CEIL
+         BUILT_IN_ROUND
+         BUILT_IN_NEARBYINT
+         BUILT_IN_RINT)
+ /* truncl(extend(x)) -> extend(trunc(x)), etc., if x is a double.  */
+ (if (optimize && canonicalize_math_p ())
+  (simplify
+   (froms (convert double_value_p@0))
+   (convert (tos @0)))))
+
+(match float_value_p
+ @0
+ (if (TYPE_MAIN_VARIANT (TREE_TYPE (@0)) == float_type_node)))
+(for froms (BUILT_IN_TRUNCL BUILT_IN_TRUNC
+           BUILT_IN_FLOORL BUILT_IN_FLOOR
+           BUILT_IN_CEILL BUILT_IN_CEIL
+           BUILT_IN_ROUNDL BUILT_IN_ROUND
+           BUILT_IN_NEARBYINTL BUILT_IN_NEARBYINT
+           BUILT_IN_RINTL BUILT_IN_RINT)
+     tos (BUILT_IN_TRUNCF BUILT_IN_TRUNCF
+         BUILT_IN_FLOORF BUILT_IN_FLOORF
+         BUILT_IN_CEILF BUILT_IN_CEILF
+         BUILT_IN_ROUNDF BUILT_IN_ROUNDF
+         BUILT_IN_NEARBYINTF BUILT_IN_NEARBYINTF
+         BUILT_IN_RINTF BUILT_IN_RINTF)
+ /* truncl(extend(x)) and trunc(extend(x)) -> extend(truncf(x)), etc.,
+    if x is a float.  */
+ (if (optimize && canonicalize_math_p ())
+  (simplify
+   (froms (convert float_value_p@0))
+   (convert (tos @0)))))
+
+/* cproj(x) -> x if we're ignoring infinities.  */
+(simplify
+ (CPROJ @0)
+ (if (!HONOR_INFINITIES (type))
+   @0))
 
 /* If the real part is inf and the imag part is known to be
    nonnegative, return (inf + 0i).  */
 (simplify
  (CPROJ (complex REAL_CST@0 tree_expr_nonnegative_p@1))
  (if (real_isinf (TREE_REAL_CST_PTR (@0)))
-  (with
-    {
-      REAL_VALUE_TYPE rinf;
-      real_inf (&rinf);
-    }
-   { build_complex (type, build_real (TREE_TYPE (type), rinf),
-                   build_zero_cst (TREE_TYPE (type))); })))
+  { build_complex_inf (type, false); }))
+
 /* If the imag part is inf, return (inf+I*copysign(0,imag)).  */
 (simplify
  (CPROJ (complex @0 REAL_CST@1))
  (if (real_isinf (TREE_REAL_CST_PTR (@1)))
-  (with
-    {
-      REAL_VALUE_TYPE rinf, rzero = dconst0;
-      real_inf (&rinf);
-      rzero.sign = TREE_REAL_CST_PTR (@1)->sign;
-    }
-   { build_complex (type, build_real (TREE_TYPE (type), rinf),
-                   build_real (TREE_TYPE (type), rzero)); })))
+  { build_complex_inf (type, TREE_REAL_CST_PTR (@1)->sign); }))
 
 
 /* Narrowing of arithmetic and logical operations.