+2015-10-22 Richard Sandiford <richard.sandiford@arm.com>
+
+ * builtins.c (fold_builtin_cproj): Delete.
+ (fold_builtin_1): Handle constant arguments here.
+ (build_complex_cproj): Move and rename to...
+ * tree.c: (build_complex_inf): ...this.
+ * tree.h (build_complex_inf): Declare.
+ * match.pd: Fold cproj(x)->x if x has no infinity.
+ Use build_complex_inf for existing cproj rules.
+
2015-10-22 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
PR target/68015
return NULL_TREE;
}
-/* Build a complex (inf +- 0i) for the result of cproj. TYPE is the
- complex tree type of the result. If NEG is true, the imaginary
- zero is negative. */
-
-static tree
-build_complex_cproj (tree type, bool neg)
-{
- REAL_VALUE_TYPE rinf, rzero = dconst0;
-
- real_inf (&rinf);
- rzero.sign = neg;
- return build_complex (type, build_real (TREE_TYPE (type), rinf),
- build_real (TREE_TYPE (type), rzero));
-}
-
-/* Fold call to builtin cproj, cprojf or cprojl with argument ARG. TYPE is the
- return type. Return NULL_TREE if no simplification can be made. */
-
-static tree
-fold_builtin_cproj (location_t loc, tree arg, tree type)
-{
- if (!validate_arg (arg, COMPLEX_TYPE)
- || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
- return NULL_TREE;
-
- /* If there are no infinities, return arg. */
- if (! HONOR_INFINITIES (type))
- return non_lvalue_loc (loc, arg);
-
- /* Calculate the result when the argument is a constant. */
- if (TREE_CODE (arg) == COMPLEX_CST)
- {
- const REAL_VALUE_TYPE *real = TREE_REAL_CST_PTR (TREE_REALPART (arg));
- const REAL_VALUE_TYPE *imag = TREE_REAL_CST_PTR (TREE_IMAGPART (arg));
-
- if (real_isinf (real) || real_isinf (imag))
- return build_complex_cproj (type, imag->sign);
- else
- return arg;
- }
-
- return NULL_TREE;
-}
-
/* Fold function call to builtin tan, tanf, or tanl with argument ARG.
Return NULL_TREE if no simplification can be made. */
break;
CASE_FLT_FN (BUILT_IN_CPROJ):
- return fold_builtin_cproj (loc, arg0, type);
+ if (TREE_CODE (arg0) == COMPLEX_CST
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
+ {
+ const REAL_VALUE_TYPE *real
+ = TREE_REAL_CST_PTR (TREE_REALPART (arg0));
+ const REAL_VALUE_TYPE *imag
+ = TREE_REAL_CST_PTR (TREE_IMAGPART (arg0));
+
+ if (real_isinf (real) || real_isinf (imag))
+ return build_complex_inf (type, imag->sign);
+ else
+ return arg0;
+ }
+ break;
CASE_FLT_FN (BUILT_IN_CSIN):
if (validate_arg (arg0, COMPLEX_TYPE)
(CABS (complex @0 @0))
(mult (abs @0) { build_real_truncate (type, dconst_sqrt2 ()); })))
+/* 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.
return t;
}
+/* Build a complex (inf +- 0i), such as for the result of cproj.
+ TYPE is the complex tree type of the result. If NEG is true, the
+ imaginary zero is negative. */
+
+tree
+build_complex_inf (tree type, bool neg)
+{
+ REAL_VALUE_TYPE rinf, rzero = dconst0;
+
+ real_inf (&rinf);
+ rzero.sign = neg;
+ return build_complex (type, build_real (TREE_TYPE (type), rinf),
+ build_real (TREE_TYPE (type), rzero));
+}
+
/* Return the constant 1 in type TYPE. If TYPE has several elements, each
element is set to 1. In particular, this is 1 + i for complex types. */
extern tree build_constructor_va (tree, int, ...);
extern tree build_real_from_int_cst (tree, const_tree);
extern tree build_complex (tree, tree, tree);
+extern tree build_complex_inf (tree, bool);
extern tree build_each_one_cst (tree);
extern tree build_one_cst (tree);
extern tree build_minus_one_cst (tree);