aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.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/fold-const.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/fold-const.c')
-rw-r--r--gcc/fold-const.c184
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))