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/tree-complex.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/tree-complex.c')
-rw-r--r-- | gcc/tree-complex.c | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c index 3373326..a5708f3 100644 --- a/gcc/tree-complex.c +++ b/gcc/tree-complex.c @@ -105,6 +105,40 @@ expand_complex_addition (block_stmt_iterator *bsi, tree inner_type, update_complex_assignment (bsi, rr, ri); } +/* Expand a complex multiplication or division to a libcall to the c99 + compliant routines. */ + +static void +expand_complex_libcall (block_stmt_iterator *bsi, tree ar, tree ai, + tree br, tree bi, enum tree_code code) +{ + enum machine_mode mode; + enum built_in_function bcode; + tree args, fn, stmt, type; + + args = tree_cons (NULL, bi, NULL); + args = tree_cons (NULL, br, args); + args = tree_cons (NULL, ai, args); + args = tree_cons (NULL, ar, args); + + stmt = bsi_stmt (*bsi); + type = TREE_TYPE (TREE_OPERAND (stmt, 1)); + + mode = TYPE_MODE (type); + gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT); + if (code == MULT_EXPR) + bcode = BUILT_IN_COMPLEX_MUL_MIN + mode - MIN_MODE_COMPLEX_FLOAT; + else if (code == RDIV_EXPR) + bcode = BUILT_IN_COMPLEX_DIV_MIN + mode - MIN_MODE_COMPLEX_FLOAT; + else + gcc_unreachable (); + fn = built_in_decls[bcode]; + + TREE_OPERAND (stmt, 1) + = build3 (CALL_EXPR, type, build_fold_addr_expr (fn), args, NULL); + modify_stmt (stmt); +} + /* Expand complex multiplication to scalars: a * b = (ar*br - ai*bi) + i(ar*bi + br*ai) */ @@ -115,6 +149,12 @@ expand_complex_multiplication (block_stmt_iterator *bsi, tree inner_type, { tree t1, t2, t3, t4, rr, ri; + if (flag_complex_method == 2 && SCALAR_FLOAT_TYPE_P (inner_type)) + { + expand_complex_libcall (bsi, ar, ai, br, bi, MULT_EXPR); + return; + } + t1 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ar, br); t2 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ai, bi); t3 = gimplify_build2 (bsi, MULT_EXPR, inner_type, ar, bi); @@ -311,18 +351,27 @@ expand_complex_division (block_stmt_iterator *bsi, tree inner_type, tree ar, tree ai, tree br, tree bi, enum tree_code code) { - switch (flag_complex_divide_method) + switch (flag_complex_method) { case 0: /* straightforward implementation of complex divide acceptable. */ expand_complex_div_straight (bsi, inner_type, ar, ai, br, bi, code); break; + + case 2: + if (SCALAR_FLOAT_TYPE_P (inner_type)) + { + expand_complex_libcall (bsi, ar, ai, br, bi, code); + return; + } + /* FALLTHRU */ + case 1: /* wide ranges of inputs must work for complex divide. */ expand_complex_div_wide (bsi, inner_type, ar, ai, br, bi, code); break; + default: - /* C99-like requirements for complex divide (not yet implemented). */ gcc_unreachable (); } } |