+2006-12-20 Roger Sayle <roger@eyesopen.com>
+
+ * trans-expr.c (is_zero_initializer_p): Determine whether a given
+ constant expression is a zero initializer.
+ (gfc_trans_zero_assign): New function to attempt to optimize
+ "a(:) = 0.0" as a call to __builtin_memset (a, 0, sizeof(a));
+ (gfc_trans_assignment): Special case array assignments to a
+ zero initializer constant, using gfc_trans_zero_assign.
+
2006-12-20 Paul Thomas <pault@gcc.gnu.org>
PR fortran/29992
return gfc_finish_block (&se.pre);
}
+/* Determine whether the given EXPR_CONSTANT is a zero initializer. */
+
+static bool
+is_zero_initializer_p (gfc_expr * expr)
+{
+ if (expr->expr_type != EXPR_CONSTANT)
+ return false;
+ /* We ignore Hollerith constants for the time being. */
+ if (expr->from_H)
+ return false;
+
+ switch (expr->ts.type)
+ {
+ case BT_INTEGER:
+ return mpz_cmp_si (expr->value.integer, 0) == 0;
+
+ case BT_REAL:
+ return mpfr_zero_p (expr->value.real)
+ && MPFR_SIGN (expr->value.real) >= 0;
+
+ case BT_LOGICAL:
+ return expr->value.logical == 0;
+
+ case BT_COMPLEX:
+ return mpfr_zero_p (expr->value.complex.r)
+ && MPFR_SIGN (expr->value.complex.r) >= 0
+ && mpfr_zero_p (expr->value.complex.i)
+ && MPFR_SIGN (expr->value.complex.i) >= 0;
+
+ default:
+ break;
+ }
+ return false;
+}
+
+/* Try to efficiently translate array(:) = 0. Return NULL if this
+ can't be done. */
+
+static tree
+gfc_trans_zero_assign (gfc_expr * expr)
+{
+ tree dest, len, type;
+ tree tmp, args;
+ gfc_symbol *sym;
+
+ sym = expr->symtree->n.sym;
+ dest = gfc_get_symbol_decl (sym);
+
+ type = TREE_TYPE (dest);
+ if (POINTER_TYPE_P (type))
+ type = TREE_TYPE (type);
+ if (!GFC_ARRAY_TYPE_P (type))
+ return NULL_TREE;
+
+ /* Determine the length of the array. */
+ len = GFC_TYPE_ARRAY_SIZE (type);
+ if (!len || TREE_CODE (len) != INTEGER_CST)
+ return NULL_TREE;
+
+ len = fold_build2 (MULT_EXPR, gfc_array_index_type, len,
+ TYPE_SIZE_UNIT (gfc_get_element_type (type)));
+
+ /* Convert arguments to the correct types. */
+ if (!POINTER_TYPE_P (TREE_TYPE (dest)))
+ dest = gfc_build_addr_expr (pvoid_type_node, dest);
+ else
+ dest = fold_convert (pvoid_type_node, dest);
+ len = fold_convert (size_type_node, len);
+
+ /* Construct call to __builtin_memset. */
+ args = build_tree_list (NULL_TREE, len);
+ args = tree_cons (NULL_TREE, integer_zero_node, args);
+ args = tree_cons (NULL_TREE, dest, args);
+ tmp = build_function_call_expr (built_in_decls[BUILT_IN_MEMSET], args);
+ return fold_convert (void_type_node, tmp);
+}
/* Translate an assignment. Most of the code is concerned with
setting up the scalarizer. */
return tmp;
}
+ /* Special case assigning an array to zero. */
+ if (expr1->expr_type == EXPR_VARIABLE
+ && expr1->rank > 0
+ && expr1->ref
+ && gfc_full_array_ref_p (expr1->ref)
+ && is_zero_initializer_p (expr2))
+ {
+ tmp = gfc_trans_zero_assign (expr1);
+ if (tmp)
+ return tmp;
+ }
+
/* Assignment of the form lhs = rhs. */
gfc_start_block (&block);