aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-complex.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2005-02-11 16:26:57 -0800
committerRichard Henderson <rth@gcc.gnu.org>2005-02-11 16:26:57 -0800
commit7e7e470f9bf455553ee08e9be90943fa3631a07b (patch)
treed07cd0c8b8b5189a1a0ffc5396fe8bf7003febf4 /gcc/tree-complex.c
parent17e1f1a36faa0f8a07de8b5b7b9a4eb27df96399 (diff)
downloadgcc-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.c53
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 ();
}
}