blktrim.c

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

C
513
字号


static  bool    Retarget( block *blk )
/************************************/
{
    block_edge  *edge;
    block_edge  *next;
    block       *target;
    bool        success;

    success = TRUE;                    /* assume can get rid of block*/
    target = blk->edge[ 0 ].destination;
    edge = blk->input_edges;
    blk->input_edges = NULL;
    while( edge != NULL ) {
        next = edge->next_source;
        if( edge->source->class & ( SELECT | LABEL_RETURN ) ) {
            success = FALSE;   /* let the optimizer do it later on*/
            edge->next_source = blk->input_edges;
            blk->input_edges = edge;
        } else {
            edge->destination = target;
            edge->next_source = target->input_edges;
            target->input_edges = edge;
            target->inputs++;
            blk->inputs--;
        }
        edge = next;
    }
    if( success ) {
        MoveHead( blk, target );
        RemoveBlock( blk );
    }
    return( success );
}


static  void    JoinBlocks( block *jump, block *target )
/******************************************************/
{
    block_edge          *edge;
    source_line_number  line_num;
    label_handle        label;
    instruction         *nop;

    /*  To get here, 'target' is only entered from 'jump'*/
    /*  Thus, the only input edge to 'target' is from jump, and can be tossed*/

    /* keep the label from jump in case it's referenced in a SELECT block*/

    label = target->label;
    target->label = jump->label;
    if( jump->class & BIG_LABEL ) target->class |= BIG_LABEL;
    jump->label = label;
    line_num = target->ins.hd.line_num;
    target->ins.hd.line_num = jump->ins.hd.line_num;

    /*  Move the inputs to 'jump' to be inputs to 'target'*/

    target->inputs = jump->inputs;
    edge = jump->input_edges;
    target->input_edges = edge;
    while( edge != NULL ) {
        edge->destination = target;    /* was 'jump' before*/
        edge = edge->next_source;
    }

    /*  Now join the instruction streams*/

    nop = jump->ins.hd.prev;
    if( nop->head.opcode == OP_NOP ) {
        if( nop->flags.nop_flags & NOP_SOURCE_QUEUE ) {
            /* this nop is only here to hold source info so we just
             * attach the source info to the next instruction and
             * nuke this nop so that it can't inhibit optimization */
             if( target->ins.hd.next->head.line_num == 0 ) {
                 target->ins.hd.next->head.line_num = nop->head.line_num;
             }
             FreeIns( nop );
        }
    }

    if( jump->ins.hd.next != (instruction *)&jump->ins ) {
        if( line_num != 0 ) {
            jump->ins.hd.prev->head.line_num = line_num;
        }
        jump->ins.hd.prev->head.next = target->ins.hd.next;
        target->ins.hd.next->head.prev = jump->ins.hd.prev;
        target->ins.hd.next = jump->ins.hd.next;
        target->ins.hd.next->head.prev = (instruction *)&target->ins;
        jump->ins.hd.next = (instruction *)&jump->ins;/* so RemoveBlock won't*/
        jump->ins.hd.prev = (instruction *)&jump->ins;/* free the instr list*/
    }

    jump->inputs = 0;
    jump->targets = 0;
    MoveHead( jump, target );
    RemoveBlock( jump );
}


static  bool    SameTarget( block *blk )
/**************************************/
{
    instruction *ins;
    block       *targ1, *targ2;

    targ1 = blk->edge[ 0 ].destination;
    targ2 = blk->edge[ 1 ].destination;
    if( targ1 != targ2 ) return( FALSE );
    if( ( targ1->class | targ2->class ) & UNKNOWN_DESTINATION ) return( FALSE );
    blk->class &= ~CONDITIONAL;
    blk->class |= JUMP;
    RemoveEdge( &blk->edge[1] );
    ins = blk->ins.hd.prev;
    while( !_OpIsCondition( ins->head.opcode ) ) {
        ins = ins->head.prev;
    }
    FreeIns( ins );
    return( TRUE );
}


static  bool    DoBlockTrim( void )
/*********************************/
{
    block       *blk;
    block       *next;
    block       *target;
    instruction *ins;
    bool        change;
    bool        any_change = FALSE;

    for( ;; ) {
        change = FALSE;
        MarkReachableBlocks();
        blk = HeadBlock->next_block;
        while( blk != NULL ) {
            next = blk->next_block;
            if( !( blk->class & ( UNKNOWN_DESTINATION | BLOCK_VISITED ) ) ) {
                while( blk->input_edges != NULL ) {
                    RemoveInputEdge( blk->input_edges );
                }
                RemoveBlock( blk );
                change = TRUE;
            } else if( blk->class & CONDITIONAL ) {
                change |= SameTarget( blk );
            } else if( blk->class & JUMP ) {
                target = blk->edge[ 0 ].destination;
                if( target != blk && !(target->class & UNKNOWN_DESTINATION) ) {
                    ins = blk->ins.hd.next;
                    while( ins->head.opcode == OP_NOP ) {
                        if( ins->flags.nop_flags & (NOP_DBGINFO|NOP_DBGINFO_START) ) break;
                        ins = ins->head.next;
                    }
                    if( ins->head.opcode == OP_BLOCK ) { /* was an empty block*/
                        if( ( blk->class & BIG_LABEL ) == 0 ) {
                            change |= Retarget( blk );
                        }
                    } else if( target->inputs == 1
                          && ( target->class & BIG_LABEL ) == 0
                          && ( CountIns(blk)+CountIns(target) ) <= INS_PER_BLOCK
                          ) {
                        if( !( blk->class & ( RETURNED_TO | BIG_LABEL ) )
                           && !( target->class & CALL_LABEL ) ) {
                            JoinBlocks( blk, target );
                            change = TRUE;
                        }
                    }
                }
            }
            blk = next;
        }
        UnMarkBlocks();
        if( change == FALSE ) break;
        BlocksUnTrimmed = FALSE;
        any_change = TRUE;
    }
    if( HeadBlock != NULL ) {
        HeadBlock->id = 1;
        blk = HeadBlock;
        for( ;; ) {
            next = blk->next_block;
            if( next == NULL ) break;
            next->id = blk->id + 1;
            blk = next;
        }
    }
    return( any_change );
}

extern void KillCondBlk( block *blk, instruction *ins, int dest )
/***************************************************************/
// Assume blk is a conditional with compare ins
// Make dest the destination and delete the unused edge
// Change blk to a JMP to dest edge
{
    block_edge  *edge;
    block       *dest_blk;

    RemoveInputEdge( &blk->edge[ 0 ] );
    RemoveInputEdge( &blk->edge[ 1 ] );
    blk->class &= ~CONDITIONAL;
    blk->class |= JUMP;
    blk->targets = 1;
    dest_blk = blk->edge[dest].destination;
    edge = &blk->edge[0];
    edge->flags = blk->edge[dest].flags;
    edge->source = blk;
    edge->destination = dest_blk;
    edge->next_source = dest_blk->input_edges;
    dest_blk->input_edges = edge;
    dest_blk->inputs++;
    FreeIns( ins );
}

extern  bool    DeadBlocks( void )
/********************************/
{
    block       *blk;
    instruction *ins;
    int         dest;
    bool        change;

    change = FALSE;
    for( blk = HeadBlock; blk != NULL; blk = blk->next_block ) {
        if( blk->class & CONDITIONAL ) {
            ins = FindOneCond( blk );
            if( ins == NULL ) continue;
            if( ins->result != NULL ) continue;
            dest = _TrueIndex( ins );
            if( dest != _FalseIndex( ins ) ) continue;
            KillCondBlk( blk, ins, dest );
            change = TRUE;
        }
    }
    if( change ) {
        BlockTrim();
        return( TRUE );
    }
    return( FALSE );
}


extern  bool    BlockTrim( void )
/*******************************/
{
    bool    change = FALSE;

    if( ( CurrProc->state.attr & ROUTINE_WANTS_DEBUGGING ) == 0 ) {
        change = DoBlockTrim();
        Renumber();
    }
    return( change );
}

⌨️ 快捷键说明

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