flograph.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 581 行 · 第 1/2 页

C
581
字号
                add = FALSE;
                for( ;; ) {
                    test = IntervalNo( edge->source, level - 1 );
                                                /* guess - internal edge*/
                    if( test != curr ) {
                                                /* guess - lower level head*/
                        test = test->parent;
                        if( test == NULL ) {
                            add = TRUE;
                            break;
                        }
                                                /* guess - no other predecessor*/
                        if( prev_int == NULL ) {
                            prev_int = test;
                        } else {
                                                /* guess - different predecessor*/
                            if( test != prev_int ) {
                                add = TRUE;
                                break;
                            }
                        }
                    }
                    edge = edge->next_source;
                    if( edge == NULL ) break;
                }
                if( add == FALSE ) {
                    curr->parent = prev_int;
                    prev_int->last_block = curr->last_block;
                    test = prev_int->sub_int;
                    while( test->next_sub_int != NULL ) {
                        test = test->next_sub_int;
                    }
                    test->next_sub_int = curr;
                } else {                        /* admit - create a new interval*/
                    NewInterval( blk, level );
                    num ++;
                }
            }
        }
        ++ level;
        if( num == prev_num || num == 1 ) break;
    }
    return( num == 1 );
}


static  void    ReorderBlocks( void )
/***********************************/
/*   Reorder blocks according to the interval ordering*/
/*   This allows each interval to be identified as a continuous range of blocks*/
{
    interval_def        *curr;
    block               *last_block;
    block               *next_block;

    last_block = HeadBlock;
    curr = HeadBlock->u.interval;
    for( ;; ) {
        for( ;; ) {
            if( curr->next_sub_int != NULL ) break;
            curr = curr->parent;
            if( curr == NULL )break;
            curr->last_block = last_block;
        }
        if( curr == NULL )break;
        curr = curr->next_sub_int;
        while( curr->level > 0 ) {
            curr = curr->sub_int;
        }
        next_block = curr->first_block;
        next_block->prev_block = last_block;
        last_block->next_block = next_block;
        next_block->id = last_block->id + 1;
        last_block = next_block;
    }
    last_block->next_block = NULL;
    BlockList = last_block;
}


static  void    EdgeLevels( void )
/********************************/
{
    block               *blk;
    block_edge          *edge;
    interval_def        *interval;
    block_num           id;

    blk = HeadBlock;
    for( ;; ) {
        edge = blk->input_edges;
        while( edge != NULL ) {
            id = edge->source->id;
            interval = blk->u.interval;
            for( ;; ) {
                if( id >= interval->first_block->id
                    && id <= interval->last_block->id ) break;
                edge->join_level = interval->level;
                interval = interval->parent;
                if( interval == NULL ) break;
            }
            edge = edge->next_source;
        }
        blk = blk->next_block;
        if( blk == NULL ) break;
    }
}


static  void    NewInterval( block *blk, int level )
/**************************************************/
{
    interval_def        *prev;
    interval_def        *new;

    prev = IntervalNo( blk, level - 1 );
    _Alloc( new, sizeof( interval_def ) );
    new->link = Intervals;
    Intervals = new;
    new->sub_int = prev;
    new->next_sub_int = NULL;
    new->level = level;
    new->parent = NULL;
    new->first_block = blk;
    new->last_block = blk;
    prev->parent = new;
}


static  void    NestingDepth( void )
/**********************************/
{
    block               *blk;
    int                 level;
    interval_def        *interval;
    block_edge          *edge;
    block               *target;
    int                 i;
    bool                change;

    interval = BlockList->u.interval->parent;
    while( interval->parent != NULL ) {
        level = interval->level - 1;
        blk = BlockList;               /* borrow 'next_block'*/
        for( ;; ) {                         /* identify all back edges at this level*/
            blk->next_block = NULL;
            i = blk->targets;
            while( --i >= 0 ) {
                edge = &blk->edge[ i ];
                target = edge->destination;
                if( target->id <= blk->id ) {     /* if back edge*/
                    if( edge->join_level == level ) {
                        blk->next_block = target;
                        if( blk->loop_head == NULL ) {
                            blk->loop_head = target;
                        }
                        blk->depth ++;
                        break;
                    }
                }
            }
            blk = blk->prev_block;
            if( blk == NULL ) break;
        }
        for( ;; ) {
            change = FALSE;
            blk = BlockList;
            for( ;; ) {
                if( blk->next_block == NULL ) {
                    i = blk->targets;
                    while( --i >= 0 ) {
                        edge = & blk->edge[ i ];
                        if( edge->join_level <= level ) {
                            target = edge->destination->next_block;
                            if( target != NULL ) {
                                blk->depth ++;
                                blk->next_block = target;  /* store head in node*/
                                if( blk->loop_head == NULL && blk != target ) {
                                    blk->loop_head = target;
                                }
                                target->class |= LOOP_HEADER;
                                change = TRUE;
                                break;
                            }
                        }
                    }
                }
                blk = blk->prev_block;
                if( blk == NULL ) break;
            }
            if( change == FALSE ) break;
        }
        interval = interval->parent;
    }

/*   Restore 'next_block'*/

    blk = BlockList;
    HeadBlock = NULL;
    for( ;; ) {
        blk->next_block = HeadBlock;
        HeadBlock = blk;
        blk = blk->prev_block;
        if( blk == NULL ) break;
    }
}

static  void    KillIntervals( void )
/***********************************/
{
    interval_def        *junk;
    block               *blk;

    while( Intervals != NULL ) {
        junk = Intervals;
        Intervals = Intervals->link;
        _Free( junk, sizeof( interval_def ) );
    }
    blk = HeadBlock;
    while( blk != NULL ) {
        blk->u.interval = NULL;
        blk = blk->next_block;
    }
}

static bool functionDegenerate;

static  bool    FlowDone( block *curr, void *parm )
/*************************************************/
{
    if( curr == (block *)parm ) {
        functionDegenerate = TRUE;
        return( FALSE );
    }
    return( TRUE );
}

static  bool    Degenerate( void )
/********************************/
{
    block       *blk;
    block_edge  *edge;

    for( blk = HeadBlock; blk != NULL; blk = blk->next_block ) {
        if( ( blk->class & LOOP_HEADER ) == EMPTY ) continue;
        for( edge = blk->input_edges; edge != NULL; edge = edge->next_source ) {
            if( ( edge->source->class & SELECT ) != EMPTY ) {
                functionDegenerate = FALSE;
                FloodForward( edge->source, FlowDone, blk );
                if( functionDegenerate ) return( TRUE );
            }
        }
    }
    return( FALSE );
}

extern  void    MakeFlowGraph( void )
/***********************************/
{
    Irreducable();
    if( CurrProc->state.attr & ROUTINE_WANTS_DEBUGGING ) {
        return;
    }
    NoBlocksToSelf();
    Intervals = NULL;
    if( HeadBlock != NULL ) {
        if( !DepthFirstSearch() ) {
            Irreducable();
            RestoreLinks();
            Renumber();
            return;
        }
        FixLinks();
        if( FindIntervals() ) {
            ReorderBlocks();
            EdgeLevels();
            NestingDepth();
            if( Degenerate() ) {
                Irreducable();
            }
       } else {
            /* irreducable flow graph. repair prev_block links*/
            Irreducable();
        }
        KillIntervals();
        ReturnsToBottom();
        Renumber();
    }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?