Move more cproj simplifications to match.pd

Also make build_complex_cproj available globally and use
it for the existing match.pd rules.

Tested on x86_64-linux-gnu, aarch64-linux-gnu and arm-linux-gnueabi.

gcc/
	* 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.

From-SVN: r229164
This commit is contained in:
Richard Sandiford 2015-10-22 08:27:04 +00:00 committed by Richard Sandiford
parent 7477de01a8
commit 92c52eab97
5 changed files with 49 additions and 60 deletions

View file

@ -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

View file

@ -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)

View file

@ -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.

View file

@ -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. */

View file

@ -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);