From patchwork Wed Aug 7 05:23:37 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Teresa Johnson X-Patchwork-Id: 265328 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]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 579FC2C0130 for ; Wed, 7 Aug 2013 15:23:57 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:in-reply-to:references:date:message-id:subject :from:to:content-type; q=dns; s=default; b=IBuCT8Efh4Rppytd2asvy 4TeoWu4xLZ7kZbLxYlobYVwQ6+YflYDgX3ryGBkJOV+MuagSfdgU7RV0tlTQOmek uc3iN1KeH6B9kbVfkvwFeBy0mnTaz+8Sj7baLDMp5XcBhHzQkGYYztWV9Uen3Bbi i6jBT9Q6tfwHUSdyPlkDDI= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:in-reply-to:references:date:message-id:subject :from:to:content-type; s=default; bh=DX7mqf6H/SOtiYkCWpcZR0uv0Cw =; b=dRQVvvzHkg9ZQeYGGAqGexMOY5/uycvN6udxwFpyyh+DgD7W4zlvD06plnw VO20uceAosNirmdZ8k2LD+sVHbQrRMnXpcLQgCu/aJI3f7KNxBaIMyx42plYx06z N06vvepF7M2ibcyTe2gB9yopxthOiYMnJDpFuCjcJc0jyrSg= Received: (qmail 15965 invoked by alias); 7 Aug 2013 05:23:49 -0000 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 Received: (qmail 15948 invoked by uid 89); 7 Aug 2013 05:23:48 -0000 X-Spam-SWARE-Status: No, score=-3.6 required=5.0 tests=AWL, BAYES_00, KHOP_THREADED, RCVD_IN_DNSWL_LOW, RCVD_IN_HOSTKARMA_YE, RDNS_NONE, SPF_PASS autolearn=ham version=3.3.1 Received: from Unknown (HELO mail-qa0-f41.google.com) (209.85.216.41) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Wed, 07 Aug 2013 05:23:45 +0000 Received: by mail-qa0-f41.google.com with SMTP id bs12so2149763qab.0 for ; Tue, 06 Aug 2013 22:23:37 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-gm-message-state:mime-version:in-reply-to:references:date :message-id:subject:from:to:content-type; bh=TNDQnVBZ98GejvPEm1U3uPgoT94ikWjwKd2SpEKZV60=; b=fjYQ5YCO9bC0wT0j1P0OrmpDBl5vQhyPPZOez/82JPT2UqSg/AVYZ/DoYENeUcW/k5 KXEfEdHe2y0AAdjTrH3yb5AV/R5KpKL94j4Afz4c+qGkKMKzusrxJjOwzN9zbbomS0SN wr4igr8EkWaIXAQYwp30ZyZwFjgwIeCS+q2gx75JWSLZjNHtkVGge+eLSxJGqp2TL6wO XJMwO06td9vPkO6nBZbp072PPzjTSwCcR+50JokxplLL+w94os+rTckKWS4tyAfW7WFK PLfjfZolEkiORpmVJpbsGj1T1v/RQWRzPQTtc4jRO/D7m6zkk36wja5jwxfXmIYT+8Nv XnBw== X-Gm-Message-State: ALoCoQmRl3gFQAOo4K4vY2ZVft9BLRpA77S1zUjH6Ms/0apYrD6e8ITHmJgJVPeR0brufivZw3OwZ9EolsgSKIT4F2txOfuDp7b3onpbV9VmRIMQ9ncv1gSQO2Xa03mtxY2PbRhUYzTThRZYttS+J9e2VYbzPXcmr0//KRUiJUWEtQGpL/NFHMoCDb8XQxyACxl2cRLHWZSeFJgH8vFT3V7+aoB98jU6Gg== MIME-Version: 1.0 X-Received: by 10.49.107.105 with SMTP id hb9mr1753810qeb.74.1375853017795; Tue, 06 Aug 2013 22:23:37 -0700 (PDT) Received: by 10.49.40.162 with HTTP; Tue, 6 Aug 2013 22:23:37 -0700 (PDT) In-Reply-To: References: <20130806123714.GD3166@virgil.suse> <20130806160102.GE3166@virgil.suse> Date: Tue, 6 Aug 2013 22:23:37 -0700 Message-ID: Subject: Re: [PATCH] Convert more passes to new dump framework From: Teresa Johnson To: Teresa Johnson , "gcc-patches@gcc.gnu.org" , Dehao Chen , Sharad Singhai On Tue, Aug 6, 2013 at 9:29 AM, Teresa Johnson wrote: > On Tue, Aug 6, 2013 at 9:01 AM, Martin Jambor wrote: >> Hi, >> >> On Tue, Aug 06, 2013 at 07:14:42AM -0700, Teresa Johnson wrote: >>> On Tue, Aug 6, 2013 at 5:37 AM, Martin Jambor wrote: >>> > On Mon, Aug 05, 2013 at 10:37:00PM -0700, Teresa Johnson wrote: >>> >> This patch ports messages to the new dump framework, >>> > >>> > It would be great this new framework was documented somewhere. I lost >>> > track of what was agreed it would be and from the uses in the >>> > vectorizer I was never quite sure how to utilize it in other passes. >>> >>> Cc'ing Sharad who implemented this - Sharad, is this documented on a >>> wiki or elsewhere? >> >> Thanks >> >>> >>> > >>> > I'd also like to point out two other minor things inline: >>> > >>> > [...] >>> > >>> >> 2013-08-06 Teresa Johnson >>> >> Dehao Chen >>> >> >>> >> * dumpfile.c (dump_loc): Add column number to output, make newlines >>> >> consistent. >>> >> * dumpfile.h (OPTGROUP_OTHER): Add and enable under OPTGROUP_ALL. >>> >> * ipa-inline-transform.c (clone_inlined_nodes): >>> >> (cgraph_node_opt_info): New function. >>> >> (cgraph_node_call_chain): Ditto. >>> >> (dump_inline_decision): Ditto. >>> >> (inline_call): Invoke dump_inline_decision. >>> >> * doc/invoke.texi: Document optall -fopt-info flag. >>> >> * profile.c (read_profile_edge_counts): Use new dump framework. >>> >> (compute_branch_probabilities): Ditto. >>> >> * passes.c (pass_manager::register_one_dump_file): Use OPTGROUP_OTHER >>> >> when pass not in any opt group. >>> >> * value-prof.c (check_counter): Use new dump framework. >>> >> (find_func_by_funcdef_no): Ditto. >>> >> (check_ic_target): Ditto. >>> >> * coverage.c (get_coverage_counts): Ditto. >>> >> (coverage_init): Setup new dump framework. >>> >> * ipa-inline.c (inline_small_functions): Set is_in_ipa_inline. >>> >> * ipa-inline.h (is_in_ipa_inline): Declare. >>> >> >>> >> * testsuite/gcc.dg/pr40209.c: Use -fopt-info. >>> >> * testsuite/gcc.dg/pr26570.c: Ditto. >>> >> * testsuite/gcc.dg/pr32773.c: Ditto. >>> >> * testsuite/g++.dg/tree-ssa/dom-invalid.C (struct C): Ditto. >>> >> >>> > >>> > [...] >>> > >>> >> Index: ipa-inline-transform.c >>> >> =================================================================== >>> >> --- ipa-inline-transform.c (revision 201461) >>> >> +++ ipa-inline-transform.c (working copy) >>> >> @@ -192,6 +192,108 @@ clone_inlined_nodes (struct cgraph_edge *e, bool d >>> >> } >>> >> >>> >> >>> >> +#define MAX_INT_LENGTH 20 >>> >> + >>> >> +/* Return NODE's name and profile count, if available. */ >>> >> + >>> >> +static const char * >>> >> +cgraph_node_opt_info (struct cgraph_node *node) >>> >> +{ >>> >> + char *buf; >>> >> + size_t buf_size; >>> >> + const char *bfd_name = lang_hooks.dwarf_name (node->symbol.decl, 0); >>> >> + >>> >> + if (!bfd_name) >>> >> + bfd_name = "unknown"; >>> >> + >>> >> + buf_size = strlen (bfd_name) + 1; >>> >> + if (profile_info) >>> >> + buf_size += (MAX_INT_LENGTH + 3); >>> >> + >>> >> + buf = (char *) xmalloc (buf_size); >>> >> + >>> >> + strcpy (buf, bfd_name); >>> >> + >>> >> + if (profile_info) >>> >> + sprintf (buf, "%s ("HOST_WIDEST_INT_PRINT_DEC")", buf, node->count); >>> >> + return buf; >>> >> +} >>> > >>> > I'm not sure if output of this function is aimed only at the user or >>> > if it is supposed to be used by gcc developers as well. If the >>> > latter, an incredibly useful thing is to also dump node->symbol.order >>> > too. We usually dump it after "/" sign separating it from node name. >>> > It is invaluable when examining decisions in C++ code where you can >>> > have lots of clones of a node (and also because existing dumps print >>> > it, it is easy to combine them). >>> >>> The output is useful for both power users doing performance tuning of >>> their application, and by gcc developers. Adding the id is not so >>> useful for the former, but I agree that it is very useful for compiler >>> developers. In fact, in the google branch version we emit more verbose >>> information (the lipo module id and the funcdef_no) to help uniquely >>> identify the routines and to aid in post-processing by humans and >>> tools. So it is probably useful to add something similar here too. Is >>> the node->symbol.order more or less unique than the funcdef_no? I see >>> that you added a patch a few months ago to print the >>> node->symbol.order in the function header, and it also has the >>> advantage as you note of matching up with existing ipa dumps. >> >> node->symbol.order is unique and if I remember correctly, it is not >> even recycled. Clones, inline clones, thunks, every symbol table node >> gets its own symbol order so it should be more unique than funcdef_no. >> On the other hand it may be a bit cryptic for users but at the same >> time it is only one number. > > Ok, I am going to go ahead and add this to the output. > >> >>> >>> > >>> > [...] >>> > >>> >> Index: ipa-inline.c >>> >> =================================================================== >>> >> --- ipa-inline.c (revision 201461) >>> >> +++ ipa-inline.c (working copy) >>> >> @@ -118,6 +118,9 @@ along with GCC; see the file COPYING3. If not see >>> >> static int overall_size; >>> >> static gcov_type max_count; >>> >> >>> >> +/* Global variable to denote if it is in ipa-inline pass. */ >>> >> +bool is_in_ipa_inline = false; >>> >> + >>> >> /* Return false when inlining edge E would lead to violating >>> >> limits on function unit growth or stack usage growth. >>> >> >>> > >>> > In this age of removing global variables, are you sure you need this? >>> > The only user of this seems to be a function that is only being called >>> > from inline_call... can that ever happen when not inlining? If you >>> > plan to use this function also elsewhere, perhaps the callers will >>> > know whether we are inlining or not and can provide this in a >>> > parameter? >>> >>> This is to distinguish early inlining from ipa inlining. >> >> Oh, right, I did not realize that the IPA part was the important bit >> of the name. >> >>> The volume of >>> early inlining messages is too high to be on for the default setting >>> of -fopt-info, and are not as interesting usually for performance >>> tuning. The dumper will only emit the early inline messages under a >>> more verbose setting (MSG_NOTE): >>> dump_printf_loc (is_in_ipa_inline ? MSG_OPTIMIZED_LOCATIONS : MSG_NOTE ... >>> The other way I can see to distinguish this would be to check the >>> always_inline_functions_inlined flag on the caller's function. It >>> could also be possible to pass down a flag from the callers of >>> inline_call, but at least one caller (flatten_functions) is shared >>> between early and late inlining, so the flag needs to be passed >>> through that as well. WDYT? >> >> Did you mean flatten_function? It already has a bool "early" >> parameter. But I can see that being able to quickly figure out >> whether we are in early inliner or ipa inliner without much hassle is >> useful enough to justify a global variable a month ago, however I >> suppose we should not be introducing them now and so you'd have to put >> such stuff into... well, you'd probably have to put into the universe >> object somewhere because it is basically shared between two passes. >> Another option, even though somewhat hackish, would be to look at >> current_pass and see which pass it is. I don't know, do what is >> easier or what you like more, just be aware of the problem. > > After thinking about this some more, I think passing down an early > flag from callers is the cleanest way to go. > > I'll fix these and post a new patch later today. New patch below that removes this global variable, and also outputs the node->symbol.order (in square brackets after the function name so as to not clutter it). Inline messages with profile data look look: test.c:8:3: note: foobar [0] (99999000) inlined into foo [2] (1000) with call count 99999000 (via inline instance bar [3] (99999000)) (without FDO the counts in parentheses and the call count would not be included). Ok for trunk? Thanks, Teresa 013-08-06 Teresa Johnson Dehao Chen * dumpfile.c (dump_loc): Output column number, make newlines consistent. * dumpfile.h (OPTGROUP_OTHER): Add and enable under OPTGROUP_ALL. * ipa-inline-transform.c (cgraph_node_opt_info): New function. (cgraph_node_call_chain): Ditto. (dump_inline_decision): Ditto. (inline_call): Invoke dump_inline_decision, new parameter. * doc/invoke.texi: Document optall -fopt-info flag. * profile.c (read_profile_edge_counts): Use new dump framework. (compute_branch_probabilities): Ditto. * passes.c (pass_manager::register_one_dump_file): Use OPTGROUP_OTHER when pass not in any opt group. * value-prof.c (check_counter): Use new dump framework. (find_func_by_funcdef_no): Ditto. (check_ic_target): Ditto. * coverage.c (get_coverage_counts): Ditto. (coverage_init): Setup new dump framework. * ipa-inline.c (recursive_inlining): New inline_call parameter. (inline_small_functions): Ditto. (flatten_function): Ditto. (ipa_inline): Ditto. (inline_always_inline_functions): Ditto. (early_inline_small_functions): Ditto. * ipa-inline.h: Ditto. * testsuite/gcc.dg/pr40209.c: Use -fopt-info. * testsuite/gcc.dg/pr26570.c: Ditto. * testsuite/gcc.dg/pr32773.c: Ditto. * testsuite/g++.dg/tree-ssa/dom-invalid.C: Ditto. * testsuite/gcc.dg/inline-dump.c: New test. +int bar(void) { return foo(); } > > Thanks, > Teresa > >> >> Thanks, >> >> Martin > > > > -- > Teresa Johnson | Software Engineer | tejohnson@google.com | 408-460-2413 Index: dumpfile.c =================================================================== --- dumpfile.c (revision 201461) +++ dumpfile.c (working copy) @@ -257,16 +257,18 @@ dump_open_alternate_stream (struct dump_file_info void dump_loc (int dump_kind, FILE *dfile, source_location loc) { - /* Currently vectorization passes print location information. */ if (dump_kind) { + /* Ensure dump message starts on a new line. */ + fprintf (dfile, "\n"); if (LOCATION_LOCUS (loc) > BUILTINS_LOCATION) - fprintf (dfile, "\n%s:%d: note: ", LOCATION_FILE (loc), - LOCATION_LINE (loc)); + fprintf (dfile, "%s:%d:%d: note: ", LOCATION_FILE (loc), + LOCATION_LINE (loc), LOCATION_COLUMN (loc)); else if (current_function_decl) - fprintf (dfile, "\n%s:%d: note: ", + fprintf (dfile, "%s:%d:%d: note: ", DECL_SOURCE_FILE (current_function_decl), - DECL_SOURCE_LINE (current_function_decl)); + DECL_SOURCE_LINE (current_function_decl), + DECL_SOURCE_COLUMN (current_function_decl)); } } Index: dumpfile.h =================================================================== --- dumpfile.h (revision 201461) +++ dumpfile.h (working copy) @@ -97,8 +97,9 @@ enum tree_dump_index #define OPTGROUP_LOOP (1 << 2) /* Loop optimization passes */ #define OPTGROUP_INLINE (1 << 3) /* Inlining passes */ #define OPTGROUP_VEC (1 << 4) /* Vectorization passes */ +#define OPTGROUP_OTHER (1 << 5) /* All other passes */ #define OPTGROUP_ALL (OPTGROUP_IPA | OPTGROUP_LOOP | OPTGROUP_INLINE \ - | OPTGROUP_VEC) + | OPTGROUP_VEC | OPTGROUP_OTHER) /* Define a tree dump switch. */ struct dump_file_info Index: ipa-inline-transform.c =================================================================== --- ipa-inline-transform.c (revision 201461) +++ ipa-inline-transform.c (working copy) @@ -192,6 +192,111 @@ clone_inlined_nodes (struct cgraph_edge *e, bool d } +#define MAX_INT_LENGTH 20 + +/* Return NODE's name and profile count, if available. */ + +static const char * +cgraph_node_opt_info (struct cgraph_node *node) +{ + char *buf; + size_t buf_size; + const char *bfd_name = lang_hooks.dwarf_name (node->symbol.decl, 0); + + if (!bfd_name) + bfd_name = "unknown"; + + buf_size = strlen (bfd_name) + 1; + if (profile_info) + buf_size += (MAX_INT_LENGTH + 3); + buf_size += MAX_INT_LENGTH; + + buf = (char *) xmalloc (buf_size); + + strcpy (buf, bfd_name); + //sprintf (buf, "%s/%i", buf, node->symbol.order); + sprintf (buf, "%s [%i]", buf, node->symbol.order); + + if (profile_info) + sprintf (buf, "%s ("HOST_WIDEST_INT_PRINT_DEC")", buf, node->count); + return buf; +} + + +/* Return CALLER's inlined call chain. Save the cgraph_node of the ultimate + function that the caller is inlined to in FINAL_CALLER. */ + +static const char * +cgraph_node_call_chain (struct cgraph_node *caller, + struct cgraph_node **final_caller) +{ + struct cgraph_node *node; + const char *via_str = " (via inline instance"; + size_t current_string_len = strlen (via_str) + 1; + size_t buf_size = current_string_len; + char *buf = (char *) xmalloc (buf_size); + + buf[0] = 0; + gcc_assert (caller->global.inlined_to != NULL); + strcat (buf, via_str); + for (node = caller; node->global.inlined_to != NULL; + node = node->callers->caller) + { + const char *name = cgraph_node_opt_info (node); + current_string_len += (strlen (name) + 1); + if (current_string_len >= buf_size) + { + buf_size = current_string_len * 2; + buf = (char *) xrealloc (buf, buf_size); + } + strcat (buf, " "); + strcat (buf, name); + } + strcat (buf, ")"); + *final_caller = node; + return buf; +} + + +/* Dump the inline decision of EDGE. */ + +static void +dump_inline_decision (struct cgraph_edge *edge, bool early) +{ + location_t locus; + const char *inline_chain_text; + const char *call_count_text; + struct cgraph_node *final_caller = edge->caller; + + if (final_caller->global.inlined_to != NULL) + inline_chain_text = cgraph_node_call_chain (final_caller, &final_caller); + else + inline_chain_text = ""; + + if (edge->count > 0) + { + const char *call_count_str = " with call count "; + char *buf = (char *) xmalloc (strlen (call_count_str) + MAX_INT_LENGTH); + sprintf (buf, "%s"HOST_WIDEST_INT_PRINT_DEC, call_count_str, + edge->count); + call_count_text = buf; + } + else + { + call_count_text = ""; + } + + locus = gimple_location (edge->call_stmt); + dump_printf_loc (early ? MSG_NOTE : MSG_OPTIMIZED_LOCATIONS, + locus, + "%s inlined into %s%s%s\n", + cgraph_node_opt_info (edge->callee), + cgraph_node_opt_info (final_caller), + call_count_text, + inline_chain_text); +} + + /* Mark edge E as inlined and update callgraph accordingly. UPDATE_ORIGINAL specify whether profile of original function should be updated. If any new indirect edges are discovered in the process, add them to NEW_EDGES, unless @@ -205,7 +310,8 @@ clone_inlined_nodes (struct cgraph_edge *e, bool d bool inline_call (struct cgraph_edge *e, bool update_original, vec *new_edges, - int *overall_size, bool update_overall_summary) + int *overall_size, bool update_overall_summary, + bool early) { int old_size = 0, new_size = 0; struct cgraph_node *to = NULL; @@ -218,6 +324,9 @@ inline_call (struct cgraph_edge *e, bool update_or bool predicated = inline_edge_summary (e)->predicate != NULL; #endif + if (dump_enabled_p ()) + dump_inline_decision (e, early); + /* Don't inline inlined edges. */ gcc_assert (e->inline_failed); /* Don't even think of inlining inline clone. */ Index: doc/invoke.texi =================================================================== --- doc/invoke.texi (revision 201461) +++ doc/invoke.texi (working copy) @@ -6234,6 +6234,9 @@ Enable dumps from all loop optimizations. Enable dumps from all inlining optimizations. @item vec Enable dumps from all vectorization optimizations. +@item optall +Enable dumps from all optimizations. This is a superset of +the optimization groups listed above. @end table For example, Index: profile.c =================================================================== --- profile.c (revision 201461) +++ profile.c (working copy) @@ -432,8 +432,8 @@ read_profile_edge_counts (gcov_type *exec_counts) if (flag_profile_correction) { static bool informed = 0; - if (!informed) - inform (input_location, + if (dump_enabled_p () && !informed) + dump_printf_loc (MSG_NOTE, input_location, "corrupted profile info: edge count exceeds maximal count"); informed = 1; } @@ -692,10 +692,11 @@ compute_branch_probabilities (unsigned cfg_checksu { /* Inconsistency detected. Make it flow-consistent. */ static int informed = 0; - if (informed == 0) + if (dump_enabled_p () && informed == 0) { informed = 1; - inform (input_location, "correcting inconsistent profile data"); + dump_printf_loc (MSG_NOTE, input_location, + "correcting inconsistent profile data"); } correct_negative_edge_counts (); /* Set bb counts to the sum of the outgoing edge counts */ Index: passes.c =================================================================== --- passes.c (revision 201461) +++ passes.c (working copy) @@ -524,6 +524,11 @@ pass_manager::register_one_dump_file (struct opt_p flag_name = concat (prefix, name, num, NULL); glob_name = concat (prefix, name, NULL); optgroup_flags |= pass->optinfo_flags; + /* For any passes that do not have an optgroup set, and which are not + IPA passes setup above, set the optgroup to OPTGROUP_OTHER so that + any dump messages are emitted properly under -fopt-info(-optall). */ + if (optgroup_flags == OPTGROUP_NONE) + optgroup_flags = OPTGROUP_OTHER; id = dump_register (dot_name, flag_name, glob_name, flags, optgroup_flags); set_pass_for_id (id, pass); full_name = concat (prefix, pass->name, num, NULL); Index: value-prof.c =================================================================== --- value-prof.c (revision 201461) +++ value-prof.c (working copy) @@ -585,9 +585,11 @@ check_counter (gimple stmt, const char * name, : DECL_SOURCE_LOCATION (current_function_decl); if (flag_profile_correction) { - inform (locus, "correcting inconsistent value profile: " - "%s profiler overall count (%d) does not match BB count " - "(%d)", name, (int)*all, (int)bb_count); + if (dump_enabled_p ()) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, locus, + "correcting inconsistent value profile: %s " + "profiler overall count (%d) does not match BB " + "count (%d)", name, (int)*all, (int)bb_count); *all = bb_count; if (*count > *all) *count = *all; @@ -1209,9 +1211,11 @@ find_func_by_funcdef_no (int func_id) int max_id = get_last_funcdef_no (); if (func_id >= max_id || cgraph_node_map[func_id] == NULL) { - if (flag_profile_correction) - inform (DECL_SOURCE_LOCATION (current_function_decl), - "Inconsistent profile: indirect call target (%d) does not exist", func_id); + if (flag_profile_correction && dump_enabled_p ()) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, + DECL_SOURCE_LOCATION (current_function_decl), + "Inconsistent profile: indirect call target (%d) " + "does not exist", func_id); else error ("Inconsistent profile: indirect call target (%d) does not exist", func_id); @@ -1235,8 +1239,10 @@ check_ic_target (gimple call_stmt, struct cgraph_n return true; locus = gimple_location (call_stmt); - inform (locus, "Skipping target %s with mismatching types for icall ", - cgraph_node_name (target)); + if (dump_enabled_p ()) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, locus, + "Skipping target %s with mismatching types for icall ", + cgraph_node_name (target)); return false; } Index: coverage.c =================================================================== --- coverage.c (revision 201461) +++ coverage.c (working copy) @@ -43,6 +43,7 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "hash-table.h" #include "tree-iterator.h" +#include "tree-pass.h" #include "cgraph.h" #include "dumpfile.h" #include "diagnostic-core.h" @@ -341,11 +342,13 @@ get_coverage_counts (unsigned counter, unsigned ex { static int warned = 0; - if (!warned++) - inform (input_location, (flag_guess_branch_prob - ? "file %s not found, execution counts estimated" - : "file %s not found, execution counts assumed to be zero"), - da_file_name); + if (!warned++ && dump_enabled_p ()) + dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, input_location, + (flag_guess_branch_prob + ? "file %s not found, execution counts estimated" + : "file %s not found, execution counts assumed to " + "be zero"), + da_file_name); return NULL; } @@ -369,21 +372,25 @@ get_coverage_counts (unsigned counter, unsigned ex warning_at (input_location, OPT_Wcoverage_mismatch, "the control flow of function %qE does not match " "its profile data (counter %qs)", id, ctr_names[counter]); - if (warning_printed) + if (warning_printed && dump_enabled_p ()) { - inform (input_location, "use -Wno-error=coverage-mismatch to tolerate " - "the mismatch but performance may drop if the function is hot"); + dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, input_location, + "use -Wno-error=coverage-mismatch to tolerate " + "the mismatch but performance may drop if the " + "function is hot"); if (!seen_error () && !warned++) { - inform (input_location, "coverage mismatch ignored"); - inform (input_location, flag_guess_branch_prob - ? G_("execution counts estimated") - : G_("execution counts assumed to be zero")); + dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, input_location, + "coverage mismatch ignored"); + dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, input_location, + flag_guess_branch_prob + ? G_("execution counts estimated") + : G_("execution counts assumed to be zero")); if (!flag_guess_branch_prob) - inform (input_location, - "this can result in poorly optimized code"); + dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, input_location, + "this can result in poorly optimized code"); } } @@ -1103,6 +1110,11 @@ coverage_init (const char *filename) int len = strlen (filename); int prefix_len = 0; + /* Since coverage_init is invoked very early, before the pass + manager, we need to set up the dumping explicitly. This is + similar to the handling in finish_optimization_passes. */ + dump_start (pass_profile.pass.static_pass_number, NULL); + if (!profile_data_prefix && !IS_ABSOLUTE_PATH (filename)) profile_data_prefix = getpwd (); @@ -1145,6 +1157,8 @@ coverage_init (const char *filename) gcov_write_unsigned (bbg_file_stamp); } } + + dump_finish (pass_profile.pass.static_pass_number); } /* Performs file-level cleanup. Close notes file, generate coverage Index: ipa-inline.c =================================================================== --- ipa-inline.c (revision 201461) +++ ipa-inline.c (working copy) @@ -1322,7 +1322,7 @@ recursive_inlining (struct cgraph_edge *edge, reset_edge_growth_cache (curr); } - inline_call (curr, false, new_edges, &overall_size, true); + inline_call (curr, false, new_edges, &overall_size, true, false); lookup_recursive_calls (node, curr->callee, heap); n++; } @@ -1612,7 +1612,8 @@ inline_small_functions (void) fprintf (dump_file, " Peeling recursion with depth %i\n", depth); gcc_checking_assert (!callee->global.inlined_to); - inline_call (edge, true, &new_indirect_edges, &overall_size, true); + inline_call (edge, true, &new_indirect_edges, &overall_size, true, + false); if (flag_indirect_inlining) add_new_edges_to_heap (edge_heap, new_indirect_edges); @@ -1733,7 +1734,7 @@ flatten_function (struct cgraph_node *node, bool e xstrdup (cgraph_node_name (callee)), xstrdup (cgraph_node_name (e->caller))); orig_callee = callee; - inline_call (e, true, NULL, NULL, false); + inline_call (e, true, NULL, NULL, false, early); if (e->callee != orig_callee) orig_callee->symbol.aux = (void *) node; flatten_function (e->callee, early); @@ -1852,7 +1853,8 @@ ipa_inline (void) inline_summary (node->callers->caller)->size); } - inline_call (node->callers, true, NULL, NULL, true); + inline_call (node->callers, true, NULL, NULL, true, + false); if (dump_file) fprintf (dump_file, " Inlined into %s which now has %i size\n", @@ -1925,7 +1927,7 @@ inline_always_inline_functions (struct cgraph_node fprintf (dump_file, " Inlining %s into %s (always_inline).\n", xstrdup (cgraph_node_name (e->callee)), xstrdup (cgraph_node_name (e->caller))); - inline_call (e, true, NULL, NULL, false); + inline_call (e, true, NULL, NULL, false, true); inlined = true; } if (inlined) @@ -1977,7 +1979,7 @@ early_inline_small_functions (struct cgraph_node * fprintf (dump_file, " Inlining %s into %s.\n", xstrdup (cgraph_node_name (callee)), xstrdup (cgraph_node_name (e->caller))); - inline_call (e, true, NULL, NULL, true); + inline_call (e, true, NULL, NULL, true, true); inlined = true; } Index: ipa-inline.h =================================================================== --- ipa-inline.h (revision 201461) +++ ipa-inline.h (working copy) @@ -228,7 +228,8 @@ void free_growth_caches (void); void compute_inline_parameters (struct cgraph_node *, bool); /* In ipa-inline-transform.c */ -bool inline_call (struct cgraph_edge *, bool, vec *, int *, bool); +bool inline_call (struct cgraph_edge *, bool, vec *, int *, + bool, bool); unsigned int inline_transform (struct cgraph_node *); void clone_inlined_nodes (struct cgraph_edge *e, bool, bool, int *); Index: testsuite/gcc.dg/pr40209.c =================================================================== --- testsuite/gcc.dg/pr40209.c (revision 201461) +++ testsuite/gcc.dg/pr40209.c (working copy) @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fprofile-use" } */ +/* { dg-options "-O2 -fprofile-use -fopt-info" } */ void process(const char *s); Index: testsuite/gcc.dg/pr26570.c =================================================================== --- testsuite/gcc.dg/pr26570.c (revision 201461) +++ testsuite/gcc.dg/pr26570.c (working copy) @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -fprofile-generate -fprofile-use" } */ +/* { dg-options "-O2 -fprofile-generate -fprofile-use -fopt-info" } */ unsigned test (unsigned a, unsigned b) { Index: testsuite/gcc.dg/pr32773.c =================================================================== --- testsuite/gcc.dg/pr32773.c (revision 201461) +++ testsuite/gcc.dg/pr32773.c (working copy) @@ -1,6 +1,6 @@ /* { dg-do compile } */ -/* { dg-options "-O -fprofile-use" } */ -/* { dg-options "-O -m4 -fprofile-use" { target sh-*-* } } */ +/* { dg-options "-O -fprofile-use -fopt-info" } */ +/* { dg-options "-O -m4 -fprofile-use -fopt-info" { target sh-*-* } } */ void foo (int *p) { Index: testsuite/g++.dg/tree-ssa/dom-invalid.C =================================================================== --- testsuite/g++.dg/tree-ssa/dom-invalid.C (revision 201461) +++ testsuite/g++.dg/tree-ssa/dom-invalid.C (working copy) @@ -1,7 +1,7 @@ // PR tree-optimization/39557 // invalid post-dom info leads to infinite loop // { dg-do run } -// { dg-options "-Wall -fno-exceptions -O2 -fprofile-use -fno-rtti" } +// { dg-options "-Wall -fno-exceptions -O2 -fprofile-use -fopt-info -fno-rtti" } struct C { Index: testsuite/gcc.dg/inline-dump.c =================================================================== --- testsuite/gcc.dg/inline-dump.c (revision 0) +++ testsuite/gcc.dg/inline-dump.c (revision 0) @@ -0,0 +1,11 @@ +/* Verify that -fopt-info can output correct inline info. */ +/* { dg-do compile } */ +/* { dg-options "-Wall -fopt-info-inline=stderr -O2 -fno-early-inlining" } */ +static inline int leaf() { + int i, ret = 0; + for (i = 0; i < 10; i++) + ret += i; + return ret; +} +static inline int foo(void) { return leaf(); } /* { dg-message "note: leaf .*inlined into bar .*via inline instance foo.*\n" } */