summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/builtins.c59
-rw-r--r--gcc/match.pd24
-rw-r--r--gcc/tree.c15
-rw-r--r--gcc/tree.h1
5 files changed, 49 insertions, 60 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7385acdc788..bd5aef52c91 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+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
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 2318b2859fc..eec4b8898c1 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -7538,50 +7538,6 @@ fold_fixed_mathfn (location_t loc, tree fndecl, tree arg)
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. */
@@ -9504,7 +9460,20 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0)
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)
diff --git a/gcc/match.pd b/gcc/match.pd
index 0a9598e1f79..6b181897e2b 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2479,30 +2479,24 @@ along with GCC; see the file COPYING3. If not see
(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.
diff --git a/gcc/tree.c b/gcc/tree.c
index adc874847ff..09df67ebf88 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -1986,6 +1986,21 @@ build_complex (tree type, tree real, tree imag)
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. */
diff --git a/gcc/tree.h b/gcc/tree.h
index 300077cac05..ece083bed3e 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -3853,6 +3853,7 @@ extern tree build_constructor_from_list (tree, tree);
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);