- 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 && bi0)
- {
- rr = fold_build2 (code, inner_type, ar, br);
- ri = zero;
- }
- else if (ai0 && br0)
- {
- rr = zero;
- ri = fold_build2 (code, inner_type, ar, bi);
- ri = fold_build1 (NEGATE_EXPR, inner_type, ri);
- }
- else if (ar0 && bi0)
- {
- rr = zero;
- ri = fold_build2 (code, inner_type, ai, br);
- }
- else if (ar0 && br0)
- {
- rr = fold_build2 (code, inner_type, ai, bi);
- ri = zero;
- }
- else if (bi0)
- {
- rr = fold_build2 (code, inner_type, ar, br);
- ri = fold_build2 (code, inner_type, ai, br);
- }
- else if (br0)
- {
- rr = fold_build2 (code, inner_type, ai, bi);
- ri = fold_build2 (code, inner_type, ar, bi);
- ri = fold_build1 (NEGATE_EXPR, inner_type, ri);
- }
- else
- return NULL;
-
- return fold_build2 (COMPLEX_EXPR, type, rr, ri);
-}
-
-static tree
-fold_complex_div (tree type, tree ac, tree bc, enum tree_code code)
-{
- tree ar, ai, br, bi;
-
- 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;
-
- return fold_complex_div_parts (type, ar, ai, br, bi, code);
-}
-
-/* Fold a unary expression of code CODE and type TYPE with operand
- OP0. Return the folded expression if folding is successful.
- Otherwise, return NULL_TREE. */
-
-static tree
-fold_unary (enum tree_code code, tree type, tree op0)
-{
- tree tem;
- tree arg0;
- enum tree_code_class kind = TREE_CODE_CLASS (code);
-
- gcc_assert (IS_EXPR_CODE_CLASS (kind)
- && TREE_CODE_LENGTH (code) == 1);