LCOV - code coverage report
Current view: top level - vm/jit - cfg.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 176 216 81.5 %
Date: 2015-06-10 18:10:59 Functions: 5 8 62.5 %

          Line data    Source code
       1             : /* src/vm/jit/cfg.c - build a control-flow graph
       2             : 
       3             :    Copyright (C) 2006, 2007 R. Grafl, A. Krall, C. Kruegel, C. Oates,
       4             :    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
       5             :    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
       6             :    J. Wenninger, Institut f. Computersprachen - TU Wien
       7             : 
       8             :    This file is part of CACAO.
       9             : 
      10             :    This program is free software; you can redistribute it and/or
      11             :    modify it under the terms of the GNU General Public License as
      12             :    published by the Free Software Foundation; either version 2, or (at
      13             :    your option) any later version.
      14             : 
      15             :    This program is distributed in the hope that it will be useful, but
      16             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      18             :    General Public License for more details.
      19             : 
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program; if not, write to the Free Software
      22             :    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
      23             :    02110-1301, USA.
      24             : 
      25             : */
      26             : 
      27             : #include "vm/jit/cfg.hpp"
      28             : #include <assert.h>                     // for assert
      29             : #include "config.h"
      30             : #include "mm/dumpmemory.hpp"            // for DMNEW
      31             : #include "vm/jit/ir/icmd.hpp"           // for ::ICMD_NOP, etc
      32             : #include "vm/jit/ir/instruction.hpp"    // for instruction, etc
      33             : #include "vm/jit/jit.hpp"               // for basicblock, jitdata, etc
      34             : #include "vm/jit/stack.hpp"
      35             : 
      36             : 
      37             : /* cfg_allocate_predecessors ***************************************************
      38             : 
      39             :    Allocates the predecessor array, if there is none, and resets the
      40             :    predecessor count.
      41             : 
      42             : *******************************************************************************/
      43             : 
      44      305136 : static void cfg_allocate_predecessors(basicblock *bptr)
      45             : {
      46      305136 :         if (bptr->predecessors == NULL) {
      47      222928 :                 bptr->predecessors = DMNEW(basicblock*, bptr->predecessorcount);
      48             : 
      49      222928 :                 bptr->predecessorcount = 0;
      50             :         }
      51      305136 : }
      52             : 
      53             : 
      54             : /* cfg_allocate_successors *****************************************************
      55             : 
      56             :    Allocates the succecessor array, if there is none, and resets the
      57             :    predecessor count.
      58             : 
      59             : *******************************************************************************/
      60             : 
      61      197591 : static void cfg_allocate_successors(basicblock *bptr)
      62             : {
      63      197591 :         if (bptr->successors == NULL) {
      64      197590 :                 bptr->successors = DMNEW(basicblock*, bptr->successorcount);
      65             : 
      66      197590 :                 bptr->successorcount = 0;
      67             :         }
      68      197591 : }
      69             : 
      70             : 
      71             : /* cfg_insert_predecessor ******************************************************
      72             : 
      73             :    Inserts a predecessor into the array, but checks for duplicate
      74             :    entries.  This is used for TABLESWITCH and LOOKUPSWITCH.
      75             : 
      76             : *******************************************************************************/
      77             : 
      78      248565 : static void cfg_insert_predecessors(basicblock *bptr, basicblock *pbptr)
      79             : {
      80             :         basicblock **tbptr;
      81             :         int          i;
      82             : 
      83      248565 :         tbptr = bptr->predecessors;
      84             : 
      85             :         /* check if the predecessors is already stored in the array */
      86             : 
      87      320030 :         for (i = 0; i < bptr->predecessorcount; i++, tbptr++)
      88       71924 :                 if (*tbptr == pbptr)
      89         459 :                         return;
      90             : 
      91             :         /* not found, insert it */
      92             : 
      93      248106 :         bptr->predecessors[bptr->predecessorcount] = pbptr;
      94      248106 :         bptr->predecessorcount++;
      95             : }
      96             : 
      97      248565 : static void cfg_insert_successors(basicblock *bptr, basicblock *pbptr)
      98             : {
      99             :         basicblock **tbptr;
     100             :         int          i;
     101             : 
     102      248565 :         tbptr = bptr->successors;
     103             : 
     104             :         /* check if the successor is already stored in the array */
     105             : 
     106      394762 :         for (i = 0; i < bptr->successorcount; i++, tbptr++)
     107      146656 :                 if (*tbptr == pbptr)
     108         459 :                         return;
     109             : 
     110             :         /* not found, insert it */
     111             : 
     112      248106 :         bptr->successors[bptr->successorcount] = pbptr;
     113      248106 :         bptr->successorcount++;
     114             : }
     115             : 
     116             : 
     117             : /* cfg_build *******************************************************************
     118             : 
     119             :    Build a control-flow graph in finding all predecessors and
     120             :    successors for the basic blocks.
     121             : 
     122             : *******************************************************************************/
     123             : 
     124       86399 : bool cfg_build(jitdata *jd)
     125             : {
     126             :         basicblock      *bptr;
     127             :         basicblock      *tbptr;
     128             :         basicblock      *ntbptr;
     129             :         instruction     *iptr;
     130             :         branch_target_t *table;
     131             :         lookup_target_t *lookup;
     132             :         int              i;
     133             :         bool             has_fallthrough;
     134             : 
     135             :         /* process all basic blocks to find the predecessor/successor counts */
     136             : 
     137       86399 :         bptr = jd->basicblocks;
     138             : 
     139      492080 :         for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
     140             : 
     141      405681 :                 if (bptr->type == basicblock::TYPE_EXH) {
     142             :                         /* predecessorcount for exception handlers is initialized to -1,
     143             :                            so we need to fix it to 0. */
     144        9964 :                         bptr->predecessorcount += 1;
     145             :                 }
     146             : 
     147      405681 :                 if ((bptr->icount == 0) || (bptr->state == basicblock::UNDEF))
     148       86401 :                         continue;
     149             : 
     150      319280 :                 iptr = bptr->iinstr + bptr->icount - 1;
     151             : 
     152             :                 /* skip NOPs at the end of the block */
     153             : 
     154      872662 :                 while (iptr->opc == ICMD_NOP) {
     155      234102 :                         if (iptr == bptr->iinstr)
     156           0 :                                 break;
     157      234102 :                         iptr--;
     158             :                 }
     159             : 
     160      319280 :                 if (iptr->opc == ICMD_GOTO) {
     161             : 
     162             :                         /*
     163             :                          This is needed for the following special case caused by
     164             :                          stack_reach_next_block:
     165             :                          I.e. there might be instructions causing control flow before
     166             :                          a GOTO:
     167             : 
     168             :                          ....
     169             :                          129: 192:  IFEQ            Ti102 0 (0x00000000) --> L052
     170             :                          131: 193:  NOP
     171             :                            0:   0:  GOTO            --> L060
     172             :                         */
     173             : 
     174       34738 :                         bptr->successorcount++;
     175             : 
     176       34738 :                         tbptr = iptr->dst.block;
     177       34738 :                         tbptr->predecessorcount++;
     178             : 
     179       34738 :                         if (iptr == bptr->iinstr) {
     180        7451 :                                 continue;
     181             :                         }
     182             : 
     183       27287 :                         iptr--;
     184             : 
     185       56346 :                         while (iptr->opc == ICMD_NOP) {
     186        1772 :                                 if (iptr == bptr->iinstr) {
     187           0 :                                         break;
     188             :                                 }
     189        1772 :                                 iptr--;
     190             :                         }
     191             : 
     192       27287 :                         has_fallthrough = false;
     193             :                 } else {
     194      284542 :                         has_fallthrough = true;
     195             :                 }
     196             : 
     197      311829 :                 switch (icmd_table[iptr->opc].controlflow) {
     198             : 
     199             :                 case CF_END:
     200      121690 :                         break;
     201             : 
     202             :                 case CF_IF:
     203             : 
     204      106055 :                         bptr->successorcount += 2;
     205             : 
     206      106055 :                         tbptr  = iptr->dst.block;
     207      106055 :                         tbptr->predecessorcount++;
     208             : 
     209      106055 :                         if (has_fallthrough) {
     210      106054 :                                 ntbptr = bptr->next;
     211      106054 :                                 ntbptr->predecessorcount++;
     212             :                         }
     213      106055 :                         break;
     214             : 
     215             :                 case CF_JSR:
     216          17 :                         bptr->successorcount++;
     217             : 
     218          17 :                         tbptr = iptr->sx.s23.s3.jsrtarget.block;
     219          17 :                         tbptr->predecessorcount++;
     220          17 :                         break;
     221             : 
     222             :                 case CF_GOTO:
     223             :                 case CF_RET:
     224          15 :                         bptr->successorcount++;
     225             : 
     226          15 :                         tbptr = iptr->dst.block;
     227          15 :                         tbptr->predecessorcount++;
     228          15 :                         break;
     229             : 
     230             :                 case CF_TABLE:
     231          72 :                         table = iptr->dst.table;
     232             : 
     233          72 :                         bptr->successorcount++;
     234             : 
     235          72 :                         tbptr = table->block;
     236          72 :                         tbptr->predecessorcount++;
     237          72 :                         table++;
     238             : 
     239          72 :                         i = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
     240             : 
     241        1218 :                         while (--i >= 0) {
     242        1074 :                                 bptr->successorcount++;
     243             : 
     244        1074 :                                 tbptr = table->block;
     245        1074 :                                 tbptr->predecessorcount++;
     246        1074 :                                 table++;
     247             :                         }
     248          72 :                         break;
     249             : 
     250             :                 case CF_LOOKUP:
     251          60 :                         lookup = iptr->dst.lookup;
     252             : 
     253          60 :                         bptr->successorcount++;
     254             : 
     255          60 :                         tbptr = iptr->sx.s23.s3.lookupdefault.block;
     256          60 :                         tbptr->predecessorcount++;
     257             : 
     258          60 :                         i = iptr->sx.s23.s2.lookupcount;
     259             : 
     260         600 :                         while (--i >= 0) {
     261         480 :                                 bptr->successorcount++;
     262             : 
     263         480 :                                 tbptr = lookup->target.block;
     264         480 :                                 tbptr->predecessorcount++;
     265         480 :                                 lookup++;
     266             :                         }
     267          60 :                         break;
     268             : 
     269             :                 default:
     270       83920 :                         if (has_fallthrough) {
     271       56634 :                                 bptr->successorcount++;
     272             : 
     273       56634 :                                 tbptr = bptr->next;
     274             : 
     275             :                                 /* An exception handler has no predecessors. */
     276             : 
     277       56634 :                                 if (tbptr->type != basicblock::TYPE_EXH)
     278       56571 :                                         tbptr->predecessorcount++;
     279             :                         }
     280             :                         break;
     281             :                 }
     282             :         }
     283             : 
     284             :         /* Second iteration to allocate the arrays and insert the basic
     285             :            block pointers. */
     286             : 
     287       86399 :         bptr = jd->basicblocks;
     288             : 
     289      492080 :         for (bptr = jd->basicblocks; bptr != NULL; bptr = bptr->next) {
     290      405681 :                 if ((bptr->icount == 0) || (bptr->state == basicblock::UNDEF))
     291       86401 :                         continue;
     292             : 
     293      319280 :                 iptr = bptr->iinstr + bptr->icount - 1;
     294             : 
     295             :                 /* skip NOPs at the end of the block */
     296             : 
     297      872662 :                 while (iptr->opc == ICMD_NOP) {
     298      234102 :                         if (iptr == bptr->iinstr)
     299           0 :                                 break;
     300      234102 :                         iptr--;
     301             :                 }
     302             : 
     303      319280 :                 if (iptr->opc == ICMD_GOTO) {
     304       34738 :                         tbptr = iptr->dst.block;
     305             : 
     306       34738 :                         cfg_allocate_successors(bptr);
     307             : 
     308       34738 :                         cfg_insert_successors(bptr, tbptr);
     309             : 
     310       34738 :                         cfg_allocate_predecessors(tbptr);
     311             : 
     312       34738 :                         cfg_insert_predecessors(tbptr, bptr);
     313             : 
     314       34738 :                         if (iptr == bptr->iinstr) {
     315        7451 :                                 continue;
     316             :                         }
     317             : 
     318       27287 :                         iptr--;
     319             : 
     320       56346 :                         while (iptr->opc == ICMD_NOP) {
     321        1772 :                                 if (iptr == bptr->iinstr) {
     322           0 :                                         break;
     323             :                                 }
     324        1772 :                                 iptr--;
     325             :                         }
     326             : 
     327       27287 :                         has_fallthrough = false;
     328             : 
     329             :                 } else {
     330      284542 :                         has_fallthrough = true;
     331             :                 }
     332             : 
     333      311829 :                 switch (icmd_table[iptr->opc].controlflow) {
     334             : 
     335             :                 case CF_END:
     336      121690 :                         break;
     337             : 
     338             :                 case CF_IF:
     339             : 
     340      106055 :                         tbptr  = iptr->dst.block;
     341      106055 :                         ntbptr = bptr->next;
     342             : 
     343      106055 :                         cfg_allocate_successors(bptr);
     344             : 
     345      106055 :                         cfg_insert_successors(bptr, tbptr);
     346      106055 :                         if (has_fallthrough) {
     347      106054 :                                 cfg_insert_successors(bptr, ntbptr);
     348             :                         }
     349             : 
     350      106055 :                         cfg_allocate_predecessors(tbptr);
     351      106055 :                         if (has_fallthrough) {
     352      106054 :                                 cfg_allocate_predecessors(ntbptr);
     353             :                         }
     354             : 
     355      106055 :                         cfg_insert_predecessors(tbptr, bptr);
     356      106055 :                         if (has_fallthrough) {
     357      106054 :                                 cfg_insert_predecessors(ntbptr, bptr);
     358             :                         }
     359      106055 :                         break;
     360             : 
     361             :                 case CF_JSR:
     362          17 :                         tbptr = iptr->sx.s23.s3.jsrtarget.block;
     363          17 :                         goto goto_tail;
     364             : 
     365             :                 case CF_GOTO:
     366             :                 case CF_RET:
     367             : 
     368          15 :                         tbptr = iptr->dst.block;
     369             : goto_tail:
     370          32 :                         cfg_allocate_successors(bptr);
     371             : 
     372          32 :                         cfg_insert_successors(bptr, tbptr);
     373             : 
     374          32 :                         cfg_allocate_predecessors(tbptr);
     375             : 
     376          32 :                         cfg_insert_predecessors(tbptr, bptr);
     377          32 :                         break;
     378             : 
     379             :                 case CF_TABLE:
     380          72 :                         table = iptr->dst.table;
     381             : 
     382          72 :                         tbptr = table->block;
     383          72 :                         table++;
     384             : 
     385          72 :                         cfg_allocate_successors(bptr);
     386             : 
     387          72 :                         cfg_insert_successors(bptr, tbptr);
     388             : 
     389          72 :                         cfg_allocate_predecessors(tbptr);
     390             : 
     391          72 :                         cfg_insert_predecessors(tbptr, bptr);
     392             : 
     393          72 :                         i = iptr->sx.s23.s3.tablehigh - iptr->sx.s23.s2.tablelow + 1;
     394             : 
     395        1218 :                         while (--i >= 0) {
     396        1074 :                                 tbptr = table->block;
     397        1074 :                                 table++;
     398             : 
     399        1074 :                                 cfg_insert_successors(bptr, tbptr);
     400             : 
     401        1074 :                                 cfg_allocate_predecessors(tbptr);
     402        1074 :                                 cfg_insert_predecessors(tbptr, bptr);
     403             :                         }
     404          72 :                         break;
     405             : 
     406             :                 case CF_LOOKUP:
     407          60 :                         lookup = iptr->dst.lookup;
     408             : 
     409          60 :                         tbptr = iptr->sx.s23.s3.lookupdefault.block;
     410             : 
     411          60 :                         cfg_allocate_successors(bptr);
     412             : 
     413          60 :                         cfg_insert_successors(bptr, tbptr);
     414             : 
     415          60 :                         cfg_allocate_predecessors(tbptr);
     416             : 
     417          60 :                         cfg_insert_predecessors(tbptr, bptr);
     418             : 
     419          60 :                         i = iptr->sx.s23.s2.lookupcount;
     420             : 
     421         600 :                         while (--i >= 0) {
     422         480 :                                 tbptr = lookup->target.block;
     423         480 :                                 lookup++;
     424             : 
     425         480 :                                 cfg_insert_successors(bptr, tbptr);
     426             : 
     427         480 :                                 cfg_allocate_predecessors(tbptr);
     428         480 :                                 cfg_insert_predecessors(tbptr, bptr);
     429             :                         }
     430          60 :                         break;
     431             : 
     432             :                 default:
     433       83920 :                         if (has_fallthrough) {
     434       56634 :                                 tbptr = bptr->next;
     435             : 
     436       56634 :                                 cfg_allocate_successors(bptr);
     437             : 
     438       56634 :                                 bptr->successors[0] = tbptr;
     439       56634 :                                 bptr->successorcount++;
     440             : 
     441             :                                 /* An exception handler has no predecessors. */
     442             : 
     443       56634 :                                 if (tbptr->type != basicblock::TYPE_EXH) {
     444       56571 :                                         cfg_allocate_predecessors(tbptr);
     445             : 
     446       56571 :                                         tbptr->predecessors[tbptr->predecessorcount] = bptr;
     447       56571 :                                         tbptr->predecessorcount++;
     448             :                                 }
     449             :                         }
     450             :                         break;
     451             :                 }
     452             :         }
     453             : 
     454             :         /* everything's ok */
     455             : 
     456       86399 :         return true;
     457             : }
     458             : 
     459             : /* cfg_add_root ****************************************************************
     460             : 
     461             :    Adds an empty root basicblock.
     462             :    The numbers of all other basicblocks are set off by one.
     463             :    Needed for some analyses that require the root basicblock to have no
     464             :    predecessors and to perform special initializations.
     465             : 
     466             : *******************************************************************************/
     467             : 
     468           0 : void cfg_add_root(jitdata *jd) {
     469             :         basicblock *root, *zero, *it;
     470             : 
     471           0 :         zero = jd->basicblocks;
     472             : 
     473           0 :         root = DNEW(basicblock);
     474           0 :         MZERO(root, basicblock, 1);
     475             : 
     476           0 :         root->successorcount = 1;
     477           0 :         root->successors     = DMNEW(basicblock *, 1);
     478           0 :         root->successors[0]  = zero;
     479           0 :         root->next           = zero;
     480           0 :         root->nr             = 0;
     481           0 :         root->type           = basicblock::TYPE_STD;
     482           0 :         root->method         = jd->m;
     483             : 
     484           0 :         if (zero->predecessorcount == 0) {
     485           0 :                 zero->predecessors = DNEW(basicblock *);
     486             :         } else {
     487           0 :                 zero->predecessors = DMREALLOC(zero->predecessors, basicblock *, zero->predecessorcount, zero->predecessorcount + 1);
     488             :         }
     489           0 :         zero->predecessors[zero->predecessorcount] = root;
     490           0 :         zero->predecessorcount += 1;
     491             : 
     492           0 :         jd->basicblocks = root;
     493           0 :         jd->basicblockcount += 1;
     494             : 
     495           0 :         for (it = zero; it; it = it->next) {
     496           0 :                 it->nr += 1;
     497             :         }
     498           0 : }
     499             : 
     500           0 : void cfg_remove_root(jitdata *jd) {
     501             :         basicblock *root, *zero, *it;
     502             : 
     503           0 :         root = jd->basicblocks;
     504           0 :         zero = root->next;
     505             : 
     506           0 :         zero->predecessorcount -= 1;
     507             : 
     508           0 :         jd->basicblocks = zero;
     509             : 
     510           0 :         for (it = zero; it; it = it->next) {
     511           0 :                 it->nr -= 1;
     512             :         }
     513           0 : }
     514             : 
     515           0 : void cfg_clear(jitdata *jd)
     516             : {
     517             : 
     518           0 :         for (basicblock *b = jd->basicblocks; b != NULL; b = b->next)
     519             :         {
     520           0 :                 b->predecessorcount = (b->type == basicblock::TYPE_EXH) ? -1 : 0;
     521           0 :                 b->successorcount   = 0;
     522           0 :                 b->predecessors     = NULL;
     523           0 :                 b->successors       = NULL;
     524             :         }
     525           0 : }
     526             : 
     527             : #if defined(ENABLE_SSA)
     528             : 
     529             : static void cfg_eliminate_edges_to_unreachable(jitdata *jd);
     530             : 
     531             : /* cfg_add_exceptional_edges ***************************************************
     532             : 
     533             :    Edges from basicblocks to their exception handlers and from exception
     534             :    handlers to the blocks they handle exceptions for are added. Further
     535             :    the number of potentially throwing instructions in the basicblocks are
     536             :    counted.
     537             : 
     538             :    We don't consider nor do we determine the types of exceptions thrown. Edges
     539             :    are added from every block to every potential handler.
     540             : 
     541             : *******************************************************************************/
     542             : 
     543             : void cfg_add_exceptional_edges(jitdata *jd) {
     544             :         basicblock *bptr;
     545             :         instruction *iptr;
     546             :         exception_entry *ee;
     547             :         bool unreachable_exh = false;
     548             : 
     549             :         /* Count the number of exceptional exits for every block.
     550             :          * Every PEI is an exceptional out.
     551             :          */
     552             : 
     553             :         FOR_EACH_BASICBLOCK(jd, bptr) {
     554             : 
     555             :                 /* Prepare for reachability calculation. */
     556             :                 bptr->vp = NULL;
     557             : 
     558             :                 if (bptr->state == basicblock::UNDEF) {
     559             :                         continue;
     560             :                 }
     561             : 
     562             :                 FOR_EACH_INSTRUCTION(bptr, iptr) {
     563             :                         if (icmd_table[iptr->opc].flags & ICMDTABLE_PEI) {
     564             :                                 bptr->exouts += 1;
     565             :                         }
     566             :                 }
     567             :         }
     568             : 
     569             :         /* Count the number of exception handlers for every block. */
     570             : 
     571             :         for (ee = jd->exceptiontable; ee; ee = ee->down) {
     572             :                 for (bptr = ee->start; bptr != ee->end; bptr = bptr->next) {
     573             :                         /* Linking a block with a handler, even if there are no exceptional exits
     574             :                            breaks stuff in other passes. */
     575             :                         if (bptr->exouts > 0) {
     576             :                                 bptr->exhandlercount += 1;
     577             :                                 ee->handler->expredecessorcount += 1;
     578             :                         }
     579             :                 }
     580             :         }
     581             : 
     582             :         /* Allocate and fill exception handler arrays. */
     583             : 
     584             :         for (ee = jd->exceptiontable; ee; ee = ee->down) {
     585             : 
     586             :                 if (ee->handler->expredecessorcount == 0) {
     587             :                         /* An exception handler that is unreachable.
     588             :                            This is inconsistent with the semantics of the CFG,
     589             :                            we need to recalculate reachability. */
     590             :                         unreachable_exh = true;
     591             :                 }
     592             : 
     593             :                 for (bptr = ee->start; bptr != ee->end; bptr = bptr->next) {
     594             :                         if (bptr->exouts > 0) {
     595             : 
     596             :                                 if (bptr->exhandlers == NULL) {
     597             :                                         bptr->exhandlers = DMNEW(basicblock *, bptr->exhandlercount);
     598             :                                         /* Move pointer past the end of the array,
     599             :                                          * It will be filled in the reverse order.
     600             :                                          */
     601             :                                         bptr->exhandlers += bptr->exhandlercount;
     602             :                                 }
     603             : 
     604             :                                 bptr->exhandlers -= 1;
     605             :                                 *(bptr->exhandlers) = ee->handler;
     606             : 
     607             :                                 if (ee->handler->expredecessors == NULL) {
     608             :                                         ee->handler->expredecessors = DMNEW(basicblock *, ee->handler->expredecessorcount);
     609             :                                         ee->handler->expredecessors += ee->handler->expredecessorcount;
     610             :                                 }
     611             : 
     612             :                                 ee->handler->expredecessors -= 1;
     613             :                                 *(ee->handler->expredecessors) = bptr;
     614             :                         }
     615             :                 }
     616             :         }
     617             : 
     618             :         if (unreachable_exh) {
     619             : 
     620             :                 /* This is rare in ``normal'' compiler generated code.
     621             : 
     622             :                    The dead block [EXH] is a predecessor of [BB1],
     623             :                    but the edge [EXH] -> [BB1] will never be traversed.
     624             : 
     625             :                    [BB1] --[next]--> [BB2, no peis] ==[exhandler]==> [EXH] --[next]--+
     626             :              ^                                                               |
     627             :                      +---------------------------------------------------------------+
     628             :                 */
     629             : 
     630             :                 /*
     631             :                 fprintf(stderr, "Found unreachable exh, adjusting %s %s",
     632             :                         UTF_TEXT(jd->m->klazz->name), UTF_TEXT(jd->m->name));
     633             :                 fprintf(stderr, "<before>\n");
     634             :                 show_method(jd, 3);
     635             :                 fprintf(stderr, "</before>\n");
     636             :                 */
     637             : 
     638             :                 cfg_eliminate_edges_to_unreachable(jd);
     639             : 
     640             :                 /*
     641             :                 fprintf(stderr, "<after>\n");
     642             :                 show_method(jd, 3);
     643             :                 fprintf(stderr, "</after>\n");
     644             :                 */
     645             :         }
     646             : }
     647             : 
     648             : static void cfg_calculate_reachability(basicblock *bptr) {
     649             :         basicblock **itsucc;
     650             : 
     651             :         /* Block not marked. */
     652             :         assert(bptr->vp == NULL);
     653             : 
     654             :         bptr->vp = bptr; /* Mark block */
     655             : 
     656             :         FOR_EACH_SUCCESSOR(bptr, itsucc) {
     657             :                 if ((*itsucc)->vp == NULL) {
     658             :                         cfg_calculate_reachability(*itsucc);
     659             :                 }
     660             :         }
     661             : 
     662             :         if (bptr->exouts > 0) {
     663             :                 FOR_EACH_EXHANDLER(bptr, itsucc) {
     664             :                         if ((*itsucc)->vp == NULL) {
     665             :                                 cfg_calculate_reachability(*itsucc);
     666             :                         }
     667             :                 }
     668             :         }
     669             : }
     670             : 
     671             : static void cfg_remove_predecessors(basicblock *bptr, basicblock *pbptr) {
     672             :         s4 i;
     673             : 
     674             :         for (i = 0; i < bptr->predecessorcount; ++i) {
     675             :                 /* Search item. */
     676             :                 if (bptr->predecessors[i] == pbptr) {
     677             :                         if (i != (bptr->predecessorcount - 1)) {
     678             :                                 /* If not last element, replace element with last element. */
     679             :                                 bptr->predecessors[i] = bptr->predecessors[bptr->predecessorcount - 1];
     680             :                         }
     681             : 
     682             :                         /* Decrease element count. */
     683             :                         bptr->predecessorcount -= 1;
     684             : 
     685             :                         return;
     686             :                 }
     687             :         }
     688             : }
     689             : 
     690             : static void cfg_eliminate_edges_to_unreachable(jitdata *jd) {
     691             :         basicblock *it;
     692             :         basicblock **itsucc;
     693             : 
     694             :         cfg_calculate_reachability(jd->basicblocks);
     695             : 
     696             :         FOR_EACH_BASICBLOCK(jd, it) {
     697             :                 if (it->vp == NULL) {
     698             : 
     699             :                         /* Mark as unreachable. */
     700             : 
     701             :                         it->state = basicblock::UNDEF;
     702             : 
     703             :                         /* As this block got unreachable, it is no more a predecessor
     704             :                            of its successors. */
     705             : 
     706             :                         FOR_EACH_SUCCESSOR(it, itsucc) {
     707             :                                 cfg_remove_predecessors(*itsucc, it);
     708             :                         }
     709             : 
     710             :                         /* Eliminiate all CFG edges of this block. */
     711             : 
     712             :                         it->predecessorcount = 0;
     713             :                         it->successorcount = 0;
     714             :                         it->expredecessorcount = 0;
     715             :                 }
     716             :         }
     717             : }
     718             : 
     719             : #endif
     720             : 
     721             : /*
     722             :  * These are local overrides for various environment variables in Emacs.
     723             :  * Please do not remove this and leave it at the end of the file, where
     724             :  * Emacs will automagically detect them.
     725             :  * ---------------------------------------------------------------------
     726             :  * Local variables:
     727             :  * mode: c++
     728             :  * indent-tabs-mode: t
     729             :  * c-basic-offset: 4
     730             :  * tab-width: 4
     731             :  * End:
     732             :  * vim:noexpandtab:sw=4:ts=4:
     733             :  */

Generated by: LCOV version 1.11