zerop
CONSTANT_CLASS_P
tree_expr_nonnegative_p
+ integer_valued_real_p
integer_pow2p
HONOR_NANS)
(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)
(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. */
(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)))
|| (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. */
/* 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.
/* 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.