diff options
author | Richard Henderson <rth@redhat.com> | 2005-02-11 16:26:57 -0800 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2005-02-11 16:26:57 -0800 |
commit | 7e7e470f9bf455553ee08e9be90943fa3631a07b (patch) | |
tree | d07cd0c8b8b5189a1a0ffc5396fe8bf7003febf4 /gcc/fold-const.c | |
parent | 17e1f1a36faa0f8a07de8b5b7b9a4eb27df96399 (diff) | |
download | gcc-7e7e470f9bf455553ee08e9be90943fa3631a07b.zip gcc-7e7e470f9bf455553ee08e9be90943fa3631a07b.tar.gz gcc-7e7e470f9bf455553ee08e9be90943fa3631a07b.tar.bz2 |
tree-complex.c (expand_complex_libcall): New.
* tree-complex.c (expand_complex_libcall): New.
(expand_complex_multiplication): Use it for c99 compliance.
(expand_complex_division): Likewise.
* fold-const.c (fold_complex_add, fold_complex_mult): New.
(fold): Call them.
* builtins.c (built_in_names): Remove const.
* tree.c (build_common_builtin_nodes): Build complex arithmetic
builtins.
* tree.h (BUILT_IN_COMPLEX_MUL_MIN, BUILT_IN_COMPLEX_MUL_MAX): New.
(BUILT_IN_COMPLEX_DIV_MIN, BUILT_IN_COMPLEX_DIV_MAX): New.
(built_in_names): Remove const.
* c-common.c (c_common_type_for_mode): Handle complex modes.
* flags.h, toplev.c (flag_complex_method): Rename from
flag_complex_divide_method.
* libgcc2.c (__divsc3, __divdc3, __divxc3, __divtc3,
__mulsc3, __muldc3, __mulxc3, __multc3): New.
* libgcc2.h: Declare them.
* libgcc-std.ver: Export them.
* mklibgcc.in (lib2funcs): Build them.
From-SVN: r94909
Diffstat (limited to 'gcc/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 0d73273..5d6e5c50 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -6306,6 +6306,168 @@ fold_to_nonsharp_ineq_using_bound (tree ineq, tree bound) return fold (build2 (GE_EXPR, type, a, y)); } +/* Fold complex addition when both components are accessible by parts. + Return non-null if successful. CODE should be PLUS_EXPR for addition, + or MINUS_EXPR for subtraction. */ + +static tree +fold_complex_add (tree type, tree ac, tree bc, enum tree_code code) +{ + tree ar, ai, br, bi, rr, ri, inner_type; + + if (TREE_CODE (ac) == COMPLEX_EXPR) + ar = TREE_OPERAND (ac, 0), ai = TREE_OPERAND (ac, 1); + else if (TREE_CODE (ac) == COMPLEX_CST) + ar = TREE_REALPART (ac), ai = TREE_IMAGPART (ac); + else + return NULL; + + if (TREE_CODE (bc) == COMPLEX_EXPR) + br = TREE_OPERAND (bc, 0), bi = TREE_OPERAND (bc, 1); + else if (TREE_CODE (bc) == COMPLEX_CST) + br = TREE_REALPART (bc), bi = TREE_IMAGPART (bc); + else + return NULL; + + inner_type = TREE_TYPE (type); + + rr = fold (build2 (code, inner_type, ar, br)); + ri = fold (build2 (code, inner_type, ai, bi)); + + return fold (build2 (COMPLEX_EXPR, type, rr, ri)); +} + +/* Perform some simplifications of complex multiplication when one or more + of the components are constants or zeros. Return non-null if successful. */ + +static tree +fold_complex_mult (tree type, tree ac, tree bc) +{ + tree ar, ai, br, bi, rr, ri, inner_type, zero; + bool ar0, ai0, br0, bi0, bi1; + + if (TREE_CODE (ac) == COMPLEX_EXPR) + ar = TREE_OPERAND (ac, 0), ai = TREE_OPERAND (ac, 1); + else if (TREE_CODE (ac) == COMPLEX_CST) + ar = TREE_REALPART (ac), ai = TREE_IMAGPART (ac); + else + return NULL; + + if (TREE_CODE (bc) == COMPLEX_EXPR) + br = TREE_OPERAND (bc, 0), bi = TREE_OPERAND (bc, 1); + else if (TREE_CODE (bc) == COMPLEX_CST) + br = TREE_REALPART (bc), bi = TREE_IMAGPART (bc); + else + return NULL; + + inner_type = TREE_TYPE (type); + zero = NULL; + + if (SCALAR_FLOAT_TYPE_P (inner_type)) + { + ar0 = ai0 = br0 = bi0 = bi1 = false; + + /* We're only interested in +0.0 here, thus we don't use real_zerop. */ + + if (TREE_CODE (ar) == REAL_CST + && REAL_VALUES_IDENTICAL (TREE_REAL_CST (ar), dconst0)) + ar0 = true, zero = ar; + + if (TREE_CODE (ai) == REAL_CST + && REAL_VALUES_IDENTICAL (TREE_REAL_CST (ai), dconst0)) + ai0 = true, zero = ai; + + if (TREE_CODE (br) == REAL_CST + && REAL_VALUES_IDENTICAL (TREE_REAL_CST (br), dconst0)) + br0 = true, zero = br; + + if (TREE_CODE (bi) == REAL_CST) + { + if (REAL_VALUES_IDENTICAL (TREE_REAL_CST (bi), dconst0)) + bi0 = true, zero = bi; + else if (REAL_VALUES_IDENTICAL (TREE_REAL_CST (bi), dconst1)) + bi1 = true; + } + } + else + { + ar0 = integer_zerop (ar); + if (ar0) + zero = ar; + ai0 = integer_zerop (ai); + if (ai0) + zero = ai; + br0 = integer_zerop (br); + if (br0) + zero = br; + bi0 = integer_zerop (bi); + if (bi0) + { + zero = bi; + bi1 = false; + } + else + bi1 = integer_onep (bi); + } + + /* We won't optimize anything below unless something is zero. */ + if (zero == NULL) + return NULL; + + if (ai0 && br0 && bi1) + { + rr = zero; + ri = ar; + } + else if (ai0 && bi0) + { + rr = fold (build2 (MULT_EXPR, inner_type, ar, br)); + ri = zero; + } + else if (ai0 && br0) + { + rr = zero; + ri = fold (build2 (MULT_EXPR, inner_type, ar, bi)); + } + else if (ar0 && bi0) + { + rr = zero; + ri = fold (build2 (MULT_EXPR, inner_type, ai, br)); + } + else if (ar0 && br0) + { + rr = fold (build2 (MULT_EXPR, inner_type, ai, br)); + rr = fold (build1 (NEGATE_EXPR, inner_type, rr)); + ri = zero; + } + else if (bi0) + { + rr = fold (build2 (MULT_EXPR, inner_type, ar, br)); + ri = fold (build2 (MULT_EXPR, inner_type, ai, br)); + } + else if (ai0) + { + rr = fold (build2 (MULT_EXPR, inner_type, ar, br)); + ri = fold (build2 (MULT_EXPR, inner_type, ar, bi)); + } + else if (br0) + { + rr = fold (build2 (MULT_EXPR, inner_type, ai, bi)); + rr = fold (build1 (NEGATE_EXPR, inner_type, rr)); + ri = fold (build2 (MULT_EXPR, inner_type, ar, bi)); + } + else if (ar0) + { + rr = fold (build2 (MULT_EXPR, inner_type, ai, bi)); + rr = fold (build1 (NEGATE_EXPR, inner_type, rr)); + ri = fold (build2 (MULT_EXPR, inner_type, ai, br)); + } + else + return NULL; + + return fold (build2 (COMPLEX_EXPR, type, rr, ri)); +} + /* Perform constant folding and related simplification of EXPR. The related simplifications include x*1 => x, x*0 => 0, etc., and application of the associative law. @@ -6833,6 +6995,14 @@ fold (tree expr) if (TREE_CODE (arg0) == NEGATE_EXPR && reorder_operands_p (TREE_OPERAND (arg0, 0), arg1)) return fold (build2 (MINUS_EXPR, type, arg1, TREE_OPERAND (arg0, 0))); + + if (TREE_CODE (type) == COMPLEX_TYPE) + { + tem = fold_complex_add (type, arg0, arg1, PLUS_EXPR); + if (tem) + return tem; + } + if (! FLOAT_TYPE_P (type)) { if (integer_zerop (arg1)) @@ -7264,6 +7434,13 @@ fold (tree expr) return fold (build2 (MINUS_EXPR, type, negate_expr (arg1), TREE_OPERAND (arg0, 0))); + if (TREE_CODE (type) == COMPLEX_TYPE) + { + tem = fold_complex_add (type, arg0, arg1, MINUS_EXPR); + if (tem) + return tem; + } + if (! FLOAT_TYPE_P (type)) { if (! wins && integer_zerop (arg0)) @@ -7392,6 +7569,13 @@ fold (tree expr) negate_expr (arg0), TREE_OPERAND (arg1, 0))); + if (TREE_CODE (type) == COMPLEX_TYPE) + { + tem = fold_complex_mult (type, arg0, arg1); + if (tem) + return tem; + } + if (! FLOAT_TYPE_P (type)) { if (integer_zerop (arg1)) |