From patchwork Thu May 16 04:55:49 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Teresa Johnson X-Patchwork-Id: 244212 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 A8CF52C0098 for ; Thu, 16 May 2013 14:56:00 +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:date :to:cc:subject:mime-version:content-type :content-transfer-encoding:message-id:from; q=dns; s=default; b= uuGprXG+UQqIKD9d01Juk8DwQ2DhrmRGE62aPm6MZAk8RzmUyNWOmjvwFg4eMSNT wbYJXaSSsC1L5WpVW4LKkNN4j9+YdE5mvG6y+W6kJMMj1R5MekPKS4eh8fCmFfI/ 9LVosOdLBz79MnGBerVOEzqjdzr78SePBIhMF+bad5U= 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:date :to:cc:subject:mime-version:content-type :content-transfer-encoding:message-id:from; s=default; bh=E/Eu6j fp0mNG6AM9KYe0DPT8rOI=; b=u/N5Ost+pyYXY+yXrsDSzsHxfcOQUmgDkPqQaO vnAlex6P0MbaQL5K7vi+Kz59p7Q2112Sc1ugoaA98VCVd7kL5NNb+fGtyL4S02hu 02WVITpnvAe11Q2fXzks3A0eBJAueRQaJZh+WynOCNSPNEpAi12szJ4Fvjxa6jZw YlRO8= Received: (qmail 8896 invoked by alias); 16 May 2013 04:55:53 -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 8886 invoked by uid 89); 16 May 2013 04:55:53 -0000 X-Spam-SWARE-Status: No, score=-3.6 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, RCVD_IN_HOSTKARMA_YE, RP_MATCHES_RCVD, SPF_PASS, TW_CF autolearn=ham version=3.3.1 Received: from mail-yh0-f73.google.com (HELO mail-yh0-f73.google.com) (209.85.213.73) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Thu, 16 May 2013 04:55:51 +0000 Received: by mail-yh0-f73.google.com with SMTP id a41so180314yho.2 for ; Wed, 15 May 2013 21:55:50 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:date:to:cc:subject:user-agent:mime-version:content-type :content-transfer-encoding:message-id:from:x-gm-message-state; bh=GtIaSy4uIYQ6f52In6fh11qjWLFHm/RoklH2CRyf4r4=; b=SpjM9+cb/i0N/N5Adf3vaGoDpfwBS3MvDv4mOVBpJStYoV5Crok3YwQmzE/8OOpQP7 6uUNt+jJIFeha0OuAe/H3l95A8Ts98B60QuPIIUedemTUd/b63S0i0SPLN/tMY7C7/+K nPCnP1PLcW8c3Ny9VGd2XF6fxCThi31jQKME6DvNz6PU+1G8KqFiykwtvktgYj+BPgGk JwM/Fi28sCOeOsfsjH5AFgAnbCHIcQ09J/UQqezbXw+ZbnbhWV+USAraH6vTrbllB2a9 BYkmRA8gCIY5CdArrSRRNTP6FxUNljPyTX6l4k/nrfBxBzVx6E8JurAEzWwkv29protX Uz4w== X-Received: by 10.236.170.36 with SMTP id o24mr22334093yhl.2.1368680150364; Wed, 15 May 2013 21:55:50 -0700 (PDT) Received: from corp2gmr1-2.hot.corp.google.com (corp2gmr1-2.hot.corp.google.com [172.24.189.93]) by gmr-mx.google.com with ESMTPS id s48si343349yhe.6.2013.05.15.21.55.50 for (version=TLSv1.1 cipher=AES128-SHA bits=128/128); Wed, 15 May 2013 21:55:50 -0700 (PDT) Received: from tjsboxrox.mtv.corp.google.com (tjsboxrox.mtv.corp.google.com [172.17.129.49]) by corp2gmr1-2.hot.corp.google.com (Postfix) with ESMTP id 282055A402F; Wed, 15 May 2013 21:55:50 -0700 (PDT) Received: by tjsboxrox.mtv.corp.google.com (Postfix, from userid 147431) id B71C88086F; Wed, 15 May 2013 21:55:49 -0700 (PDT) Date: Wed, 15 May 2013 21:55:49 -0700 To: law@redhat.com, gcc-patches@gcc.gnu.org Cc: stevenb.gcc@gmail.com Subject: [PATCH] Refactor rtl_verify_flow_info and rtl_verify_flow_info_1 User-Agent: Heirloom mailx 12.5 6/20/10 MIME-Version: 1.0 Message-Id: <20130516045549.B71C88086F@tjsboxrox.mtv.corp.google.com> From: tejohnson@google.com (Teresa Johnson) X-Gm-Message-State: ALoCoQkoCmmngd180TrL/uzGVIyE6pUnWDEC0vVY7qoqyERHNUI4qfWdosVZ6FzVESIKF3fktg1EuwnO1zSq9hrbvBznTlqzC3UV4QL2RKhGwrmtoxG70IkU6XlpsBDZaLSsbyW7BN5VnAAuyJrnXo4bn0F2ccYJEQhhIRRZjl1+Un3vEuseFrMxtptiWHgmQjFEl7jMQPXwDah8JEe9pXyWwtmXYqKv/Q/jdHE21Wppbl7hy1DaHNU= This patch refactors rtl_verify_flow_info_1 and rtl_verify_flow_info by outlining the verification code into several different routines. rtl_verify_flow_info_1 in particular was getting very large. For the most part the functionality is exactly the same, although I did eliminate one redundant check on the BLOCK_FOR_INSN pointer for instructions inside blocks (both were in rtl_verify_flow_info_1, now in rtl_verify_bb_pointers). Bootstrapped and tested on x86_64-unknown-linux-gnu, and built cpu2006int with profile feedback. Ok for trunk? Thanks, Teresa 2013-05-15 Teresa Johnson * cfgrtl.c (verify_hot_cold_block_grouping): Return err. (rtl_verify_edges): New function. (rtl_verify_bb_insns): Ditto. (rtl_verify_bb_pointers): Ditto. (rtl_verify_bb_insn_chain): Ditto. (rtl_verify_fallthru): Ditto. (rtl_verify_bb_layout): Ditto. (rtl_verify_flow_info_1): Outline checks into new functions. (rtl_verify_flow_info): Ditto. Index: cfgrtl.c =================================================================== --- cfgrtl.c (revision 198934) +++ cfgrtl.c (working copy) @@ -2063,7 +2063,7 @@ get_last_bb_insn (basic_block bb) between hot/cold partitions. This condition will not be true until after reorder_basic_blocks is called. */ -static void +static int verify_hot_cold_block_grouping (void) { basic_block bb; @@ -2072,7 +2072,7 @@ verify_hot_cold_block_grouping (void) int current_partition = BB_UNPARTITIONED; if (!crtl->bb_reorder_complete) - return; + return err; FOR_EACH_BB (bb) { @@ -2094,81 +2094,28 @@ verify_hot_cold_block_grouping (void) current_partition = BB_PARTITION (bb); } - gcc_assert(!err); + return err; } -/* Verify the CFG and RTL consistency common for both underlying RTL and - cfglayout RTL. - Currently it does following checks: +/* Perform several checks on the edges out of each block, such as + the consistency of the branch probabilities, the correctness + of hot/cold partition crossing edges, and the number of expected + successor edges. */ - - overlapping of basic blocks - - insns with wrong BLOCK_FOR_INSN pointers - - headers of basic blocks (the NOTE_INSN_BASIC_BLOCK note) - - tails of basic blocks (ensure that boundary is necessary) - - scans body of the basic block for JUMP_INSN, CODE_LABEL - and NOTE_INSN_BASIC_BLOCK - - verify that no fall_thru edge crosses hot/cold partition boundaries - - verify that there are no pending RTL branch predictions - - verify that there is a single hot/cold partition boundary after bbro - - In future it can be extended check a lot of other stuff as well - (reachability of basic blocks, life information, etc. etc.). */ - static int -rtl_verify_flow_info_1 (void) +rtl_verify_edges (void) { - rtx x; int err = 0; basic_block bb; - /* Check the general integrity of the basic blocks. */ FOR_EACH_BB_REVERSE (bb) { - rtx insn; - - if (!(bb->flags & BB_RTL)) - { - error ("BB_RTL flag not set for block %d", bb->index); - err = 1; - } - - FOR_BB_INSNS (bb, insn) - if (BLOCK_FOR_INSN (insn) != bb) - { - error ("insn %d basic block pointer is %d, should be %d", - INSN_UID (insn), - BLOCK_FOR_INSN (insn) ? BLOCK_FOR_INSN (insn)->index : 0, - bb->index); - err = 1; - } - - for (insn = BB_HEADER (bb); insn; insn = NEXT_INSN (insn)) - if (!BARRIER_P (insn) - && BLOCK_FOR_INSN (insn) != NULL) - { - error ("insn %d in header of bb %d has non-NULL basic block", - INSN_UID (insn), bb->index); - err = 1; - } - for (insn = BB_FOOTER (bb); insn; insn = NEXT_INSN (insn)) - if (!BARRIER_P (insn) - && BLOCK_FOR_INSN (insn) != NULL) - { - error ("insn %d in footer of bb %d has non-NULL basic block", - INSN_UID (insn), bb->index); - err = 1; - } - } - - /* Now check the basic blocks (boundaries etc.) */ - FOR_EACH_BB_REVERSE (bb) - { int n_fallthru = 0, n_branch = 0, n_abnormal_call = 0, n_sibcall = 0; int n_eh = 0, n_abnormal = 0; edge e, fallthru = NULL; + edge_iterator ei; rtx note; - edge_iterator ei; if (JUMP_P (BB_END (bb)) && (note = find_reg_note (BB_END (bb), REG_BR_PROB, NULL_RTX)) @@ -2183,6 +2130,7 @@ static int err = 1; } } + FOR_EACH_EDGE (e, ei, bb->succs) { bool is_crossing; @@ -2296,26 +2244,26 @@ static int error ("abnormal edges for no purpose in bb %i", bb->index); err = 1; } + } - for (x = BB_HEAD (bb); x != NEXT_INSN (BB_END (bb)); x = NEXT_INSN (x)) - /* We may have a barrier inside a basic block before dead code - elimination. There is no BLOCK_FOR_INSN field in a barrier. */ - if (!BARRIER_P (x) && BLOCK_FOR_INSN (x) != bb) - { - debug_rtx (x); - if (! BLOCK_FOR_INSN (x)) - error - ("insn %d inside basic block %d but block_for_insn is NULL", - INSN_UID (x), bb->index); - else - error - ("insn %d inside basic block %d but block_for_insn is %i", - INSN_UID (x), bb->index, BLOCK_FOR_INSN (x)->index); + /* Clean up. */ + return err; +} - err = 1; - } +/* Checks on the instructions within blocks. Currently checks that each + block starts with a basic block note, and that basic block notes and + control flow jumps are not found in the middle of the block. */ - /* OK pointers are correct. Now check the header of basic +static int +rtl_verify_bb_insns (void) +{ + rtx x; + int err = 0; + basic_block bb; + + FOR_EACH_BB_REVERSE (bb) + { + /* Now check the header of basic block. It ought to contain optional CODE_LABEL followed by NOTE_BASIC_BLOCK. */ x = BB_HEAD (bb); @@ -2362,8 +2310,58 @@ static int } } - verify_hot_cold_block_grouping(); + /* Clean up. */ + return err; +} +/* Verify that block pointers for instructions in basic blocks, headers and + footers are set appropriately. */ + +static int +rtl_verify_bb_pointers (void) +{ + int err = 0; + basic_block bb; + + /* Check the general integrity of the basic blocks. */ + FOR_EACH_BB_REVERSE (bb) + { + rtx insn; + + if (!(bb->flags & BB_RTL)) + { + error ("BB_RTL flag not set for block %d", bb->index); + err = 1; + } + + FOR_BB_INSNS (bb, insn) + if (BLOCK_FOR_INSN (insn) != bb) + { + error ("insn %d basic block pointer is %d, should be %d", + INSN_UID (insn), + BLOCK_FOR_INSN (insn) ? BLOCK_FOR_INSN (insn)->index : 0, + bb->index); + err = 1; + } + + for (insn = BB_HEADER (bb); insn; insn = NEXT_INSN (insn)) + if (!BARRIER_P (insn) + && BLOCK_FOR_INSN (insn) != NULL) + { + error ("insn %d in header of bb %d has non-NULL basic block", + INSN_UID (insn), bb->index); + err = 1; + } + for (insn = BB_FOOTER (bb); insn; insn = NEXT_INSN (insn)) + if (!BARRIER_P (insn) + && BLOCK_FOR_INSN (insn) != NULL) + { + error ("insn %d in footer of bb %d has non-NULL basic block", + INSN_UID (insn), bb->index); + err = 1; + } + } + /* Clean up. */ return err; } @@ -2372,31 +2370,54 @@ static int cfglayout RTL. Currently it does following checks: - - all checks of rtl_verify_flow_info_1 - - test head/end pointers - - check that all insns are in the basic blocks - (except the switch handling code, barriers and notes) - - check that all returns are followed by barriers - - check that all fallthru edge points to the adjacent blocks. */ + - overlapping of basic blocks + - insns with wrong BLOCK_FOR_INSN pointers + - headers of basic blocks (the NOTE_INSN_BASIC_BLOCK note) + - tails of basic blocks (ensure that boundary is necessary) + - scans body of the basic block for JUMP_INSN, CODE_LABEL + and NOTE_INSN_BASIC_BLOCK + - verify that no fall_thru edge crosses hot/cold partition boundaries + - verify that there are no pending RTL branch predictions + - verify that there is a single hot/cold partition boundary after bbro + + In future it can be extended check a lot of other stuff as well + (reachability of basic blocks, life information, etc. etc.). */ + static int -rtl_verify_flow_info (void) +rtl_verify_flow_info_1 (void) { + int err = 0; + + err |= rtl_verify_bb_pointers (); + + err |= rtl_verify_bb_insns (); + + err |= rtl_verify_edges (); + + err |= verify_hot_cold_block_grouping(); + + return err; +} + +/* Walk the instruction chain and verify that bb head/end pointers + are correct, and that instructions are in exactly one bb and have + correct block pointers. */ + +static int +rtl_verify_bb_insn_chain (void) +{ basic_block bb; - int err = rtl_verify_flow_info_1 (); + int err = 0; rtx x; rtx last_head = get_last_insn (); basic_block *bb_info; - int num_bb_notes; - const rtx rtx_first = get_insns (); - basic_block last_bb_seen = ENTRY_BLOCK_PTR, curr_bb = NULL; const int max_uid = get_max_uid (); bb_info = XCNEWVEC (basic_block, max_uid); FOR_EACH_BB_REVERSE (bb) { - edge e; rtx head = BB_HEAD (bb); rtx end = BB_END (bb); @@ -2406,14 +2427,14 @@ static int if (x == end) break; - /* And that the code outside of basic blocks has NULL bb field. */ - if (!BARRIER_P (x) - && BLOCK_FOR_INSN (x) != NULL) - { - error ("insn %d outside of basic blocks has non-NULL bb field", - INSN_UID (x)); - err = 1; - } + /* And that the code outside of basic blocks has NULL bb field. */ + if (!BARRIER_P (x) + && BLOCK_FOR_INSN (x) != NULL) + { + error ("insn %d outside of basic blocks has non-NULL bb field", + INSN_UID (x)); + err = 1; + } } if (!x) @@ -2449,7 +2470,38 @@ static int } last_head = PREV_INSN (x); + } + for (x = last_head; x != NULL_RTX; x = PREV_INSN (x)) + { + /* Check that the code before the first basic block has NULL + bb field. */ + if (!BARRIER_P (x) + && BLOCK_FOR_INSN (x) != NULL) + { + error ("insn %d outside of basic blocks has non-NULL bb field", + INSN_UID (x)); + err = 1; + } + } + free (bb_info); + + return err; +} + +/* Verify that fallthru edges point to adjacent blocks in layout order and + that barriers exist after non-fallthru blocks. */ + +static int +rtl_verify_fallthru (void) +{ + basic_block bb; + int err = 0; + + FOR_EACH_BB_REVERSE (bb) + { + edge e; + e = find_fallthru_edge (bb->succs); if (!e) { @@ -2493,20 +2545,23 @@ static int } } - for (x = last_head; x != NULL_RTX; x = PREV_INSN (x)) - { - /* Check that the code before the first basic block has NULL - bb field. */ - if (!BARRIER_P (x) - && BLOCK_FOR_INSN (x) != NULL) - { - error ("insn %d outside of basic blocks has non-NULL bb field", - INSN_UID (x)); - err = 1; - } - } - free (bb_info); + return err; +} +/* Verify that blocks are laid out in consecutive order. While walking the + instructions, verify that all expected instructions are inside the basic + blocks, and that all returns are followed by barriers. */ + +static int +rtl_verify_bb_layout (void) +{ + basic_block bb; + int err = 0; + rtx x; + int num_bb_notes; + const rtx rtx_first = get_insns (); + basic_block last_bb_seen = ENTRY_BLOCK_PTR, curr_bb = NULL; + num_bb_notes = 0; last_bb_seen = ENTRY_BLOCK_PTR; @@ -2549,6 +2604,7 @@ static int && returnjump_p (x) && ! condjump_p (x) && ! (next_nonnote_insn (x) && BARRIER_P (next_nonnote_insn (x)))) fatal_insn ("return not followed by barrier", x); + if (curr_bb && x == BB_END (curr_bb)) curr_bb = NULL; } @@ -2560,6 +2616,34 @@ static int return err; } + +/* Verify the CFG and RTL consistency common for both underlying RTL and + cfglayout RTL, plus consistency checks specific to linearized RTL mode. + + Currently it does following checks: + - all checks of rtl_verify_flow_info_1 + - test head/end pointers + - check that blocks are laid out in consecutive order + - check that all insns are in the basic blocks + (except the switch handling code, barriers and notes) + - check that all returns are followed by barriers + - check that all fallthru edge points to the adjacent blocks. */ + +static int +rtl_verify_flow_info (void) +{ + int err = 0; + + err |= rtl_verify_flow_info_1 (); + + err |= rtl_verify_bb_insn_chain (); + + err |= rtl_verify_fallthru (); + + err |= rtl_verify_bb_layout (); + + return err; +} /* Assume that the preceding pass has possibly eliminated jump instructions or converted the unconditional jumps. Eliminate the edges from CFG.