From patchwork Wed Jul 7 12:04:02 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Biener X-Patchwork-Id: 58105 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 49BE4B6EF7 for ; Wed, 7 Jul 2010 22:04:16 +1000 (EST) Received: (qmail 3859 invoked by alias); 7 Jul 2010 12:04:14 -0000 Received: (qmail 3692 invoked by uid 22791); 7 Jul 2010 12:04:10 -0000 X-SWARE-Spam-Status: No, hits=-5.9 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, TW_TM, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from cantor.suse.de (HELO mx1.suse.de) (195.135.220.2) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 07 Jul 2010 12:04:04 +0000 Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.221.2]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.suse.de (Postfix) with ESMTP id 2CC8793987 for ; Wed, 7 Jul 2010 14:04:02 +0200 (CEST) Date: Wed, 7 Jul 2010 14:04:02 +0200 (CEST) From: Richard Guenther To: gcc-patches@gcc.gnu.org Subject: [PATCH] Fix call stmt verification, fix invalid gimple from nested function lowering and profiling Message-ID: User-Agent: Alpine 2.00 (LNX 1167 2008-08-23) MIME-Version: 1.0 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org It turns out we produce a lot of invalid gimple calls from nested function lowering and profiling (which in turn will cause missed CSE and possibly wrong code). I figured this out when fixing call stmt verification. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2010-07-07 Richard Guenther * tree-ssa-propagate.h (valid_gimple_call_p): Remove. * tree-ssa-propagate.c (valid_gimple_call_p): Make static. Fix. * gimple.h (is_gimple_operand): Remove. * gimple.c (is_gimple_operand): Likewise. (walk_gimple_op): Fix wi->val_only setting for calls. * tree-cfg.c (verify_gimple_call): Fix argument validation. * tree-profile.c (tree_gen_ic_func_profiler): Do not create invalid gimple calls. Index: gcc/tree-ssa-propagate.h =================================================================== --- gcc/tree-ssa-propagate.h (revision 161870) +++ gcc/tree-ssa-propagate.h (working copy) @@ -116,7 +116,6 @@ typedef bool (*ssa_prop_fold_stmt_fn) (g /* In tree-ssa-propagate.c */ void ssa_propagate (ssa_prop_visit_stmt_fn, ssa_prop_visit_phi_fn); bool valid_gimple_rhs_p (tree); -bool valid_gimple_call_p (tree); void move_ssa_defining_stmt_for_defs (gimple, gimple); bool update_call_from_tree (gimple_stmt_iterator *, tree); bool stmt_makes_single_store (gimple); Index: gcc/tree-ssa-propagate.c =================================================================== --- gcc/tree-ssa-propagate.c (revision 161870) +++ gcc/tree-ssa-propagate.c (working copy) @@ -639,7 +639,7 @@ valid_gimple_rhs_p (tree expr) as a single GIMPLE_CALL statement. If the arguments require further gimplification, return false. */ -bool +static bool valid_gimple_call_p (tree expr) { unsigned i, nargs; @@ -649,8 +649,17 @@ valid_gimple_call_p (tree expr) nargs = call_expr_nargs (expr); for (i = 0; i < nargs; i++) - if (! is_gimple_operand (CALL_EXPR_ARG (expr, i))) - return false; + { + tree arg = CALL_EXPR_ARG (expr, i); + if (is_gimple_reg_type (arg)) + { + if (!is_gimple_val (arg)) + return false; + } + else + if (!is_gimple_lvalue (arg)) + return false; + } return true; } Index: gcc/gimple.h =================================================================== --- gcc/gimple.h (revision 161870) +++ gcc/gimple.h (working copy) @@ -879,7 +879,6 @@ tree gimple_get_lhs (const_gimple); void gimple_set_lhs (gimple, tree); void gimple_replace_lhs (gimple, tree); gimple gimple_copy (gimple); -bool is_gimple_operand (const_tree); void gimple_set_modified (gimple, bool); void gimple_cond_get_ops_from_tree (tree, enum tree_code *, tree *, tree *); gimple gimple_build_cond_from_tree (tree, tree, tree); Index: gcc/gimple.c =================================================================== --- gcc/gimple.c (revision 161870) +++ gcc/gimple.c (working copy) @@ -1383,7 +1383,10 @@ walk_gimple_op (gimple stmt, walk_tree_f case GIMPLE_CALL: if (wi) - wi->is_lhs = false; + { + wi->is_lhs = false; + wi->val_only = true; + } ret = walk_tree (gimple_call_chain_ptr (stmt), callback_op, wi, pset); if (ret) @@ -1395,21 +1398,32 @@ walk_gimple_op (gimple stmt, walk_tree_f for (i = 0; i < gimple_call_num_args (stmt); i++) { + if (wi) + wi->val_only = is_gimple_reg_type (gimple_call_arg (stmt, i)); ret = walk_tree (gimple_call_arg_ptr (stmt, i), callback_op, wi, pset); if (ret) return ret; } - if (wi) - wi->is_lhs = true; + if (gimple_call_lhs (stmt)) + { + if (wi) + { + wi->is_lhs = true; + wi->val_only = is_gimple_reg_type (gimple_call_lhs (stmt)); + } - ret = walk_tree (gimple_call_lhs_ptr (stmt), callback_op, wi, pset); - if (ret) - return ret; + ret = walk_tree (gimple_call_lhs_ptr (stmt), callback_op, wi, pset); + if (ret) + return ret; + } if (wi) - wi->is_lhs = false; + { + wi->is_lhs = false; + wi->val_only = true; + } break; case GIMPLE_CATCH: @@ -2538,15 +2552,6 @@ const unsigned char gimple_rhs_class_tab /* Validation of GIMPLE expressions. */ -/* Return true if OP is an acceptable tree node to be used as a GIMPLE - operand. */ - -bool -is_gimple_operand (const_tree op) -{ - return op && get_gimple_rhs_class (TREE_CODE (op)) == GIMPLE_SINGLE_RHS; -} - /* Returns true iff T is a valid RHS for an assignment to a renamed user -- or front-end generated artificial -- variable. */ Index: gcc/tree-cfg.c =================================================================== --- gcc/tree-cfg.c (revision 161870) +++ gcc/tree-cfg.c (working copy) @@ -3114,7 +3114,10 @@ verify_gimple_call (gimple stmt) for (i = 0; i < gimple_call_num_args (stmt); ++i) { tree arg = gimple_call_arg (stmt, i); - if (!is_gimple_operand (arg)) + if ((is_gimple_reg_type (TREE_TYPE (arg)) + && !is_gimple_val (arg)) + || (!is_gimple_reg_type (TREE_TYPE (arg)) + && !is_gimple_lvalue (arg))) { error ("invalid argument to gimple call"); debug_generic_expr (arg); Index: gcc/tree-profile.c =================================================================== --- gcc/tree-profile.c (revision 161870) +++ gcc/tree-profile.c (working copy) @@ -340,7 +340,7 @@ tree_gen_ic_func_profiler (void) basic_block bb; edge_iterator ei; gimple stmt1, stmt2; - tree tree_uid, cur_func; + tree tree_uid, cur_func, counter_ptr, ptr_var; if (cgraph_only_called_directly_p (c_node)) return; @@ -358,13 +358,16 @@ tree_gen_ic_func_profiler (void) build_addr (current_function_decl, current_function_decl), true, NULL_TREE, - true, GSI_SAME_STMT); + true, GSI_NEW_STMT); + counter_ptr = force_gimple_operand_gsi (&gsi, ic_gcov_type_ptr_var, + true, NULL_TREE, false, + GSI_NEW_STMT); + ptr_var = force_gimple_operand_gsi (&gsi, ic_void_ptr_var, + true, NULL_TREE, false, + GSI_NEW_STMT); tree_uid = build_int_cst (gcov_type_node, c_node->pid); stmt1 = gimple_build_call (tree_indirect_call_profiler_fn, 4, - ic_gcov_type_ptr_var, - tree_uid, - cur_func, - ic_void_ptr_var); + counter_ptr, tree_uid, cur_func, ptr_var); gsi_insert_after (&gsi, stmt1, GSI_NEW_STMT); gcc_assert (EDGE_COUNT (bb->succs) == 1); bb = split_edge (EDGE_I (bb->succs, 0));