From patchwork Tue Nov 1 00:46:30 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Teresa Johnson X-Patchwork-Id: 123004 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 E98F5B6F7C for ; Tue, 1 Nov 2011 11:46:53 +1100 (EST) Received: (qmail 11856 invoked by alias); 1 Nov 2011 00:46:50 -0000 Received: (qmail 11839 invoked by uid 22791); 1 Nov 2011 00:46:48 -0000 X-SWARE-Spam-Status: No, hits=-3.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, RP_MATCHES_RCVD, SPF_HELO_PASS, TW_CF X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (74.125.121.67) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 01 Nov 2011 00:46:34 +0000 Received: from hpaq5.eem.corp.google.com (hpaq5.eem.corp.google.com [172.25.149.5]) by smtp-out.google.com with ESMTP id pA10kWEL021387 for ; Mon, 31 Oct 2011 17:46:32 -0700 Received: from vcbfk14 (vcbfk14.prod.google.com [10.220.204.14]) by hpaq5.eem.corp.google.com with ESMTP id pA10kUUl024921 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for ; Mon, 31 Oct 2011 17:46:31 -0700 Received: by vcbfk14 with SMTP id fk14so10362776vcb.2 for ; Mon, 31 Oct 2011 17:46:30 -0700 (PDT) Received: by 10.182.51.66 with SMTP id i2mr3393065obo.5.1320108390614; Mon, 31 Oct 2011 17:46:30 -0700 (PDT) MIME-Version: 1.0 Received: by 10.182.51.66 with SMTP id i2mr3393061obo.5.1320108390485; Mon, 31 Oct 2011 17:46:30 -0700 (PDT) Received: by 10.182.160.98 with HTTP; Mon, 31 Oct 2011 17:46:30 -0700 (PDT) Date: Mon, 31 Oct 2011 17:46:30 -0700 Message-ID: Subject: [google] Enable loop unroll/peel notes under -fopt-info From: Teresa Johnson To: gcc-patches@gcc.gnu.org X-System-Of-Record: true X-IsSubscribed: yes 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 This patch is for google-main only. Tested with bootstrap and regression tests. Print unroll and peel factors along with loop source position under -fopt-info. Teresa 2011-10-31 Teresa Johnson * common.opt (fopt-info): Disable -fopt-info by default. * loop-unroll.c (report_unroll_peel): New function. (unroll_and_peel_loops): Call record_loop_exits for later use. (peel_loops_completely): Print the loop source position in dump info and emit note under -fopt-info. (decide_unroll_and_peeling): Ditto. (decide_peel_once_rolling): Record peel factor for use in note emission. (decide_peel_completely): Ditto. * cfgloop.c (get_loop_location): New function. * cfgloop.h (get_loop_location): Ditto. * tree-ssa-loop-ivcanon.c (try_unroll_loop_completely): Emit note under -fopt-info. --- Teresa Johnson | Software Engineer | tejohnson@google.com | 408-460-2413 Index: tree-ssa-loop-ivcanon.c =================================================================== --- tree-ssa-loop-ivcanon.c (revision 180437) +++ tree-ssa-loop-ivcanon.c (working copy) @@ -52,6 +52,7 @@ #include "flags.h" #include "tree-inline.h" #include "target.h" +#include "diagnostic.h" /* Specifies types of loops that may be unrolled. */ @@ -443,6 +444,17 @@ fprintf (dump_file, "Unrolled loop %d completely by factor %d.\n", loop->num, (int) n_unroll); + if (flag_opt_info >= OPT_INFO_MIN) + { + location_t locus; + locus = gimple_location (cond); + + inform (locus, "Completely Unroll loop by %d (execution count %d, const iterations %d)", + (int) n_unroll, + (int) loop->header->count, + (int) TREE_INT_CST_LOW(niter)); + } + return true; } Index: loop-unroll.c =================================================================== --- loop-unroll.c (revision 180437) +++ loop-unroll.c (working copy) @@ -34,6 +34,7 @@ #include "hashtab.h" #include "recog.h" #include "target.h" +#include "diagnostic.h" /* This pass performs loop unrolling and peeling. We only perform these optimizations on innermost loops (with single exception) because @@ -152,6 +153,30 @@ basic_block); static rtx get_expansion (struct var_to_expand *); +static void +report_unroll_peel(struct loop *loop, location_t locus) +{ + struct niter_desc *desc; + int niters = 0; + + desc = get_simple_loop_desc (loop); + + if (desc->const_iter) + niters = desc->niter; + else if (loop->header->count) + niters = expected_loop_iterations (loop); + + inform (locus, "%s%s loop by %d (execution count %d, %s iterations %d)", + loop->lpt_decision.decision == LPT_PEEL_COMPLETELY ? + "Completely " : "", + loop->lpt_decision.decision == LPT_PEEL_SIMPLE ? + "Peel" : "Unroll", + loop->lpt_decision.times, + (int)loop->header->count, + desc->const_iter?"const":"average", + niters); +} + /* Unroll and/or peel (depending on FLAGS) LOOPS. */ void unroll_and_peel_loops (int flags) @@ -160,6 +185,8 @@ bool check; loop_iterator li; + record_loop_exits(); + /* First perform complete loop peeling (it is almost surely a win, and affects parameters for further decision a lot). */ peel_loops_completely (flags); @@ -234,16 +261,18 @@ { struct loop *loop; loop_iterator li; + location_t locus; /* Scan the loops, the inner ones first. */ FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST) { loop->lpt_decision.decision = LPT_NONE; + locus = get_loop_location(loop); if (dump_file) - fprintf (dump_file, - "\n;; *** Considering loop %d for complete peeling ***\n", - loop->num); + fprintf (dump_file, "\n;; *** Considering loop %d for complete peeling at BB %d from %s:%d ***\n", + loop->num, loop->header->index, LOCATION_FILE(locus), + LOCATION_LINE(locus)); loop->ninsns = num_loop_insns (loop); @@ -253,6 +282,11 @@ if (loop->lpt_decision.decision == LPT_PEEL_COMPLETELY) { + if (flag_opt_info >= OPT_INFO_MIN) + { + report_unroll_peel(loop, locus); + } + peel_loop_completely (loop); #ifdef ENABLE_CHECKING verify_dominators (CDI_DOMINATORS); @@ -268,14 +302,18 @@ { struct loop *loop; loop_iterator li; + location_t locus; /* Scan the loops, inner ones first. */ FOR_EACH_LOOP (li, loop, LI_FROM_INNERMOST) { loop->lpt_decision.decision = LPT_NONE; + locus = get_loop_location(loop); if (dump_file) - fprintf (dump_file, "\n;; *** Considering loop %d ***\n", loop->num); + fprintf (dump_file, "\n;; *** Considering loop %d at BB %d from %s:%d ***\n", + loop->num, loop->header->index, LOCATION_FILE(locus), + LOCATION_LINE(locus)); /* Do not peel cold areas. */ if (optimize_loop_for_size_p (loop)) @@ -315,6 +353,12 @@ decide_unroll_stupid (loop, flags); if (loop->lpt_decision.decision == LPT_NONE) decide_peel_simple (loop, flags); + + if (flag_opt_info >= OPT_INFO_MIN && + loop->lpt_decision.decision != LPT_NONE) + { + report_unroll_peel(loop, locus); + } } } @@ -364,6 +408,7 @@ if (dump_file) fprintf (dump_file, ";; Decided to peel exactly once rolling loop\n"); loop->lpt_decision.decision = LPT_PEEL_COMPLETELY; + loop->lpt_decision.times = 0; } /* Decide whether the LOOP is suitable for complete peeling. */ @@ -459,6 +504,7 @@ if (dump_file) fprintf (dump_file, ";; Decided to peel loop completely npeel %u\n", npeel); loop->lpt_decision.decision = LPT_PEEL_COMPLETELY; + loop->lpt_decision.times = desc->niter; } /* Peel all iterations of LOOP, remove exit edges and cancel the loop Index: common.opt =================================================================== --- common.opt (revision 180437) +++ common.opt (working copy) @@ -1568,7 +1568,7 @@ When possible do not generate stack frames fopt-info -Common Report Var(flag_opt_info) Optimization Init(1) +Common Report Var(flag_opt_info) Optimization Init(0) Enable verbose informational messages for optimizations (same as -fopt-info=1) ; fopt-info=0: no message will be emitted. Index: cfgloop.c =================================================================== --- cfgloop.c (revision 180437) +++ cfgloop.c (working copy) @@ -1640,3 +1640,58 @@ return false; } + +/* Return location corresponding to the loop control condition if possible. */ + +location_t +get_loop_location (struct loop *loop) +{ + rtx insn = NULL; + struct niter_desc *desc = NULL; + edge exit; + + /* For a for or while loop, we would like to return the location + * of the for or while statement, if possible. To do this, look + * for the branch guarding the loop back-edge. + */ + + /* If this is a simple loop with an in_edge, then the loop control + * branch is typically at the end of its source. + */ + desc = get_simple_loop_desc (loop); + if (desc->in_edge) + { + FOR_BB_INSNS_REVERSE (desc->in_edge->src, insn) + { + if (INSN_P (insn)) + return RTL_LOCATION (insn); + } + } + /* If loop has a single exit, then the loop control branch + * must be at the end of its source. + */ + if ((exit = single_exit(loop))) + { + FOR_BB_INSNS_REVERSE (exit->src, insn) + { + if (INSN_P (insn)) + return RTL_LOCATION (insn); + } + } + /* Next check the latch, to see if it is non-empty. */ + FOR_BB_INSNS_REVERSE (loop->latch, insn) + { + if (INSN_P (insn)) + return RTL_LOCATION (insn); + } + /* Finally, if none of the above identifies the loop control branch, + * return the first location in the loop header. + */ + FOR_BB_INSNS (loop->header, insn) + { + if (INSN_P (insn)) + return RTL_LOCATION (insn); + } + /* If all else fails, simply return the current function location. */ + return DECL_SOURCE_LOCATION (current_function_decl); +} Index: cfgloop.h =================================================================== --- cfgloop.h (revision 180437) +++ cfgloop.h (working copy) @@ -237,6 +237,7 @@ extern bool loop_exits_to_bb_p (struct loop *, basic_block); extern bool loop_exits_from_bb_p (struct loop *, basic_block); extern void mark_loop_exit_edges (void); +extern location_t get_loop_location (struct loop *loop); /* Loops & cfg manipulation. */ extern basic_block *get_loop_body (const struct loop *);