Hello,
just trying to shrink fold-const.c a bit more.
The tests "if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)" seem
useless, I did one bootstrap+testsuite with asserts there to make sure, so
I am dropping them. The CONJ_EXPR simplifications don't seem very useful,
as far as I can tell CONJ_EXPR is immediatly replaced with a piecewise
operation (where the transformations are obvious), but it seemed easier to
keep the transformations, in case they are not completely useless. I may
have been a bit too enthusiastic with the :s on some transformations, but
again they seem to be dead code... The converts also seem to be not so
useful since they are expanded piecewise, even the ones that should be
NOPS, so for
_Complex unsigned f(_Complex int i){return i;}
we generate:
movl %edi, %eax
shrq $32, %rdi
salq $32, %rdi
orq %rdi, %rax
...
Bootstrap+testsuite on ppc64le-redhat-linux.
2015-08-31 Marc Glisse <marc.gli...@inria.fr>
gcc/
* match.pd (SIN, COS, TAN, COSH): Reorder for consistency.
(CEXPI): New operator list.
(real (conj (x)), imag (conj (x)), real (x +- y), real (cexpi (x)),
imag (cexpi (x)), conj (conj (x)), conj (complex (x, y))):
Converted from ...
* fold-const.c (fold_unary_loc, fold_binary_loc): ... here. Remove.
gcc/testsuite/
* gcc.dg/tree-ssa/complex-7.c: New file.
--
Marc Glisse
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c (revision 227316)
+++ gcc/fold-const.c (working copy)
@@ -7725,35 +7725,20 @@ fold_unary_loc (location_t loc, enum tre
/* Strip sign ops from argument. */
if (TREE_CODE (type) == REAL_TYPE)
{
tem = fold_strip_sign_ops (arg0);
if (tem)
return fold_build1_loc (loc, ABS_EXPR, type,
fold_convert_loc (loc, type, tem));
}
return NULL_TREE;
- case CONJ_EXPR:
- if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
- return fold_convert_loc (loc, type, arg0);
- if (TREE_CODE (arg0) == COMPLEX_EXPR)
- {
- tree itype = TREE_TYPE (type);
- tree rpart = fold_convert_loc (loc, itype, TREE_OPERAND (arg0, 0));
- tree ipart = fold_convert_loc (loc, itype, TREE_OPERAND (arg0, 1));
- return fold_build2_loc (loc, COMPLEX_EXPR, type, rpart,
- negate_expr (ipart));
- }
- if (TREE_CODE (arg0) == CONJ_EXPR)
- return fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0));
- return NULL_TREE;
-
case BIT_NOT_EXPR:
/* Convert ~(X ^ Y) to ~X ^ Y or X ^ ~Y if ~X or ~Y simplify. */
if (TREE_CODE (arg0) == BIT_XOR_EXPR
&& (tem = fold_unary_loc (loc, BIT_NOT_EXPR, type,
fold_convert_loc (loc, type,
TREE_OPERAND (arg0, 0)))))
return fold_build2_loc (loc, BIT_XOR_EXPR, type, tem,
fold_convert_loc (loc, type,
TREE_OPERAND (arg0, 1)));
else if (TREE_CODE (arg0) == BIT_XOR_EXPR
@@ -7769,95 +7754,20 @@ fold_unary_loc (location_t loc, enum tre
case TRUTH_NOT_EXPR:
/* Note that the operand of this must be an int
and its values must be 0 or 1.
("true" is a fixed value perhaps depending on the language,
but we don't handle values other than 1 correctly yet.) */
tem = fold_truth_not_expr (loc, arg0);
if (!tem)
return NULL_TREE;
return fold_convert_loc (loc, type, tem);
- case REALPART_EXPR:
- if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
- return fold_convert_loc (loc, type, arg0);
- if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
- {
- tree itype = TREE_TYPE (TREE_TYPE (arg0));
- tem = fold_build2_loc (loc, TREE_CODE (arg0), itype,
- fold_build1_loc (loc, REALPART_EXPR, itype,
- TREE_OPERAND (arg0, 0)),
- fold_build1_loc (loc, REALPART_EXPR, itype,
- TREE_OPERAND (arg0, 1)));
- return fold_convert_loc (loc, type, tem);
- }
- if (TREE_CODE (arg0) == CONJ_EXPR)
- {
- tree itype = TREE_TYPE (TREE_TYPE (arg0));
- tem = fold_build1_loc (loc, REALPART_EXPR, itype,
- TREE_OPERAND (arg0, 0));
- return fold_convert_loc (loc, type, tem);
- }
- if (TREE_CODE (arg0) == CALL_EXPR)
- {
- tree fn = get_callee_fndecl (arg0);
- if (fn && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL)
- switch (DECL_FUNCTION_CODE (fn))
- {
- CASE_FLT_FN (BUILT_IN_CEXPI):
- fn = mathfn_built_in (type, BUILT_IN_COS);
- if (fn)
- return build_call_expr_loc (loc, fn, 1, CALL_EXPR_ARG (arg0,
0));
- break;
-
- default:
- break;
- }
- }
- return NULL_TREE;
-
- case IMAGPART_EXPR:
- if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE)
- return build_zero_cst (type);
- if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
- {
- tree itype = TREE_TYPE (TREE_TYPE (arg0));
- tem = fold_build2_loc (loc, TREE_CODE (arg0), itype,
- fold_build1_loc (loc, IMAGPART_EXPR, itype,
- TREE_OPERAND (arg0, 0)),
- fold_build1_loc (loc, IMAGPART_EXPR, itype,
- TREE_OPERAND (arg0, 1)));
- return fold_convert_loc (loc, type, tem);
- }
- if (TREE_CODE (arg0) == CONJ_EXPR)
- {
- tree itype = TREE_TYPE (TREE_TYPE (arg0));
- tem = fold_build1_loc (loc, IMAGPART_EXPR, itype, TREE_OPERAND (arg0,
0));
- return fold_convert_loc (loc, type, negate_expr (tem));
- }
- if (TREE_CODE (arg0) == CALL_EXPR)
- {
- tree fn = get_callee_fndecl (arg0);
- if (fn && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL)
- switch (DECL_FUNCTION_CODE (fn))
- {
- CASE_FLT_FN (BUILT_IN_CEXPI):
- fn = mathfn_built_in (type, BUILT_IN_SIN);
- if (fn)
- return build_call_expr_loc (loc, fn, 1, CALL_EXPR_ARG (arg0,
0));
- break;
-
- default:
- break;
- }
- }
- return NULL_TREE;
-
case INDIRECT_REF:
/* Fold *&X to X if X is an lvalue. */
if (TREE_CODE (op0) == ADDR_EXPR)
{
tree op00 = TREE_OPERAND (op0, 0);
if ((TREE_CODE (op00) == VAR_DECL
|| TREE_CODE (op00) == PARM_DECL
|| TREE_CODE (op00) == RESULT_DECL)
&& !TREE_READONLY (op00))
return op00;
Index: gcc/match.pd
===================================================================
--- gcc/match.pd (revision 227316)
+++ gcc/match.pd (working copy)
@@ -48,24 +48,25 @@ along with GCC; see the file COPYING3.
(define_operator_list LOG BUILT_IN_LOGF BUILT_IN_LOG BUILT_IN_LOGL)
(define_operator_list EXP BUILT_IN_EXPF BUILT_IN_EXP BUILT_IN_EXPL)
(define_operator_list LOG2 BUILT_IN_LOG2F BUILT_IN_LOG2 BUILT_IN_LOG2L)
(define_operator_list EXP2 BUILT_IN_EXP2F BUILT_IN_EXP2 BUILT_IN_EXP2L)
(define_operator_list LOG10 BUILT_IN_LOG10F BUILT_IN_LOG10 BUILT_IN_LOG10L)
(define_operator_list EXP10 BUILT_IN_EXP10F BUILT_IN_EXP10 BUILT_IN_EXP10L)
(define_operator_list POW BUILT_IN_POWF BUILT_IN_POW BUILT_IN_POWL)
(define_operator_list POW10 BUILT_IN_POW10F BUILT_IN_POW10 BUILT_IN_POW10L)
(define_operator_list SQRT BUILT_IN_SQRTF BUILT_IN_SQRT BUILT_IN_SQRTL)
(define_operator_list CBRT BUILT_IN_CBRTF BUILT_IN_CBRT BUILT_IN_CBRTL)
-(define_operator_list SIN BUILT_IN_SIN BUILT_IN_SINL BUILT_IN_SINF)
-(define_operator_list COS BUILT_IN_COS BUILT_IN_COSL BUILT_IN_COSF)
-(define_operator_list TAN BUILT_IN_TAN BUILT_IN_TANL BUILT_IN_TANF)
-(define_operator_list COSH BUILT_IN_COSH BUILT_IN_COSHL BUILT_IN_COSHF)
+(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 COSH BUILT_IN_COSHF BUILT_IN_COSH BUILT_IN_COSHL)
+(define_operator_list CEXPI BUILT_IN_CEXPIF BUILT_IN_CEXPI BUILT_IN_CEXPIL)
/* Simplifications of operations with one constant operand and
simplifications to constants or single values. */
(for op (plus pointer_plus minus bit_ior bit_xor)
(simplify
(op @0 integer_zerop)
(non_lvalue @0)))
/* 0 +p index -> (type)index */
@@ -1305,20 +1306,50 @@ along with GCC; see the file COPYING3.
(simplify
(complex (realpart @0) (imagpart @0))
@0)
(simplify
(realpart (complex @0 @1))
@0)
(simplify
(imagpart (complex @0 @1))
@1)
+/* Sometimes we only care about half of a complex expression. */
+(simplify
+ (realpart (convert?:s (conj:s @0)))
+ (convert (realpart @0)))
+(simplify
+ (imagpart (convert?:s (conj:s @0)))
+ (convert (negate (imagpart @0))))
+(for part (realpart imagpart)
+ (for op (plus minus)
+ (simplify
+ (part (convert?:s@2 (op:s @0 @1)))
+ (convert (op (part @0) (part @1))))))
+(simplify
+ (realpart (convert?:s (CEXPI:s @0)))
+ (convert (COS @0)))
+(simplify
+ (imagpart (convert?:s (CEXPI:s @0)))
+ (convert (SIN @0)))
+
+/* conj(conj(x)) -> x */
+(simplify
+ (conj (convert? (conj @0)))
+ (if (tree_nop_conversion_p (TREE_TYPE (@0), type))
+ (convert @0)))
+
+/* conj({x,y}) -> {x,-y} */
+(simplify
+ (conj (convert?:s (complex:s @0 @1)))
+ (with { tree itype = TREE_TYPE (type); }
+ (complex (convert:itype @0) (negate (convert:itype @1)))))
/* BSWAP simplifications, transforms checked by gcc.dg/builtin-bswap-8.c. */
(for bswap (BUILT_IN_BSWAP16 BUILT_IN_BSWAP32 BUILT_IN_BSWAP64)
(simplify
(bswap (bswap @0))
@0)
(simplify
(bswap (bit_not (bswap @0)))
(bit_not @0))
(for bitop (bit_xor bit_ior bit_and)
Index: gcc/testsuite/gcc.dg/tree-ssa/complex-7.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/complex-7.c (revision 0)
+++ gcc/testsuite/gcc.dg/tree-ssa/complex-7.c (working copy)
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-forwprop1" } */
+
+float f(_Complex float x, _Complex float y){
+ x += y;
+ return __builtin_cimagf (x);
+}
+
+double g(double x){
+ _Complex double c = __builtin_cexpi (x);
+ return __builtin_creal (c);
+}
+
+/* { dg-final { scan-tree-dump "__builtin_cos" "forwprop1"} } */
+/* { dg-final { scan-tree-dump-times "IMAGPART_EXPR" 2 "forwprop1"} } */