peepopt.c

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

C
664
字号
{
    a=a;b=b;
    return( FALSE );
}


static bool SameOpWithConst( instruction *ins, instruction *next )
/*****************************************************************/
{
    name        *op;

    if( ins->result != next->operands[ 0 ] ) return( FALSE );
    op = next->operands[ 1 ];
    if( op->n.class != N_CONSTANT ) return( FALSE );
    if( op->c.const_type != CONS_ABSOLUTE ) return( FALSE );
    return( TRUE );
}


static bool OpConst( instruction *ins )
/*************************************/
{
    name        *op;

    if( ins->num_operands != 2 ) return( FALSE );
    op = ins->operands[ 1 ];
    if( op->n.class != N_CONSTANT ) return( FALSE );
    if( op->c.const_type != CONS_ABSOLUTE ) return( FALSE );
    if( !_IsIntegral( ins->type_class ) ) return( FALSE );
    return( TRUE );
}


static  instruction     *FindInsPair( instruction *ins,
                                     instruction **stopper,
                                     bool *pchange, opcode_defs op,
                                     opcode_defs op2,
                                     ONE_OP *oprtn )
/**********************************************************************/
{
    instruction         *next;

    if( stopper != NULL ) *stopper = NULL;
    next = ins->head.next;
    while( next->head.opcode != OP_BLOCK ) {
        if( next->head.opcode == op && SameOpWithConst( ins, next ) ) {
            if( oprtn( ins, next ) ) {
                *pchange = TRUE;
                return( ins );
            }
        }
        if( InsOrderDependant( ins, next ) ) {
            if( stopper != NULL && next->head.opcode == op2 &&
                SameOpWithConst( ins, next ) ) {
                *stopper = next;
            }
            return( ins->head.next );
        }
        next = next->head.next;
    }
    return( ins->head.next );
}


static instruction *FindInsTriple( instruction *ins, bool *pchange,
                                   opcode_defs op1, opcode_defs op2,
                                   ONE_OP *op1rtn, ONE_OP *op2rtn,
                                   TWO_OP *op12rtn, THREE_OP *op121rtn )
/************************************************************************/
{
    bool        change;
    instruction *ins2;
    instruction *ins3;
    instruction *next;

    change = FALSE;
    next = FindInsPair( ins, &ins2, &change, op1, op2, op1rtn );
    if( change ) {
        *pchange = TRUE;
        return( next );
    } else if( ins2 != NULL ) {
        FindInsPair( ins2, &ins3, &change, op2, op1, op2rtn );
        if( change ) {
            *pchange = TRUE;
            return( ins );
        }
        if( ins3 == NULL ) {
            if( op12rtn( ins, ins2 ) ) {
                *pchange = TRUE;
                return( ins );
            }
            return( next );
        }
        if( op121rtn( ins, ins2 ) ) {
            *pchange = TRUE;
            return( ins );
        }
        return( ins->head.next );
    }
    return( next );
}


static instruction *AddOpt( instruction *ins, bool *pchange )
/***********************************************************/
{
    return( FindInsPair( ins, NULL, pchange, OP_ADD, OP_NOP, DoAdd ) );
}

static instruction *SubOpt( instruction *ins, bool *pchange )
/***********************************************************/
{
    // DoAdd will work fine for subtracts
    return( FindInsPair( ins, NULL, pchange, OP_SUB, OP_NOP, DoAdd ) );
}


static instruction *MulOpt( instruction *ins, bool *pchange )
/***********************************************************/
{
    return( FindInsPair( ins, NULL, pchange, OP_MUL, OP_NOP, DoMul ) );
}


static instruction *OrOpt( instruction *ins, bool *pchange )
/***********************************************************/
{
    return( FindInsTriple( ins, pchange, OP_OR, OP_AND,
                           DoOr, DoAnd, OrAnd, OrAndOr ) );
}


static instruction *AndOpt( instruction *ins, bool *pchange )
/***********************************************************/
{
    return( FindInsTriple( ins, pchange, OP_AND, OP_OR,
                           DoAnd, DoOr, AndOr, AndOrAnd ) );
}


static instruction *LShiftOpt( instruction *ins, bool *pchange )
/**************************************************************/
{
    return( FindInsTriple( ins, pchange, OP_LSHIFT, OP_RSHIFT,
                           DoLShift, DoRShift, LRShift, Nop3 ) );
}


static instruction *RShiftOpt( instruction *ins, bool *pchange )
/**************************************************************/
{
    return( FindInsTriple( ins, pchange, OP_RSHIFT, OP_LSHIFT,
                           DoRShift, DoLShift, RLShift, Nop3 ) );
}

static bool DoArithmeticOps( instruction *ins, bool *change, instruction **n )
/****************************************************************************/
{
    instruction *next;

    if( ins->type_class == I8 || ins->type_class == U8 ) return( FALSE );
    if( !OpConst( ins ) ) return( FALSE );
    switch( ins->head.opcode ) {
    case OP_ADD:
        next = AddOpt( ins, change );
        break;
    case OP_SUB:
        next = SubOpt( ins, change );
        break;
    case OP_MUL:
        next = MulOpt( ins, change );
        break;
    case OP_AND:
        next = AndOpt( ins, change );
        break;
    case OP_OR:
        next = OrOpt( ins, change );
        break;
    case OP_LSHIFT:
        next = LShiftOpt( ins, change );
        break;
    case OP_RSHIFT:
        next = RShiftOpt( ins, change );
        break;
    default:
        return( FALSE );
    }
    *n = next;
    return( TRUE );
}

static bool DoConversionOps( instruction *ins, bool *change, instruction **n )
/****************************************************************************/
{
    instruction *next;

    n = n;
    switch( ins->head.opcode ) {
    case OP_CONVERT:
    case OP_PTR_TO_NATIVE:
    case OP_PTR_TO_FOREIGN:
        break;
    default:
        return( FALSE );
    }
    next = ins->head.next;
    if( ReDefinedBy( ins, ins->operands[ 0 ] ) ) return( FALSE );       // BBB - cnv U2 U1 [eax] -> ax
    while( next->head.opcode != OP_BLOCK ) {
        if( ReDefinedBy( next, ins->result ) ) return( FALSE );
        if( ReDefinedBy( next, ins->operands[ 0 ] ) ) return( FALSE );
        if( ins->head.opcode == OP_CONVERT && next->head.opcode == OP_CONVERT ) {
            if( ins->result == next->operands[ 0 ] &&
                ins->type_class == next->base_type_class ) {

                // change (cnv i1 -> i2; cnv i2 -> i4) into
                //     (cnv i1 -> i2; cnv i1 -> i4) and let dead code take care of
                //         the first ins if it is not needed

                // pointer conversions are too dangerous to fold
                if( _IsPointer( next->type_class ) || _IsPointer( next->base_type_class ) ) return( FALSE );
                if( _IsPointer( ins->type_class ) ) return( FALSE );
                // watch for converting down - bad to fold
                if( ins->type_class < ins->base_type_class ) return( FALSE );
                next->base_type_class = ins->base_type_class;
                next->operands[ 0 ] = ins->operands[ 0 ];
                if( next->operands[ 0 ]->n.class == N_TEMP ) {
                    next->operands[ 0 ]->t.temp_flags &= ~CAN_STACK;
                }
                // in case we are in register allocator
                next->table = NULL;
                *change = TRUE;
                return( TRUE );
            }
        }
        if( ( ins->head.opcode == OP_PTR_TO_NATIVE && next->head.opcode == OP_PTR_TO_FOREIGN ) ||
            ( ins->head.opcode == OP_PTR_TO_FOREIGN && next->head.opcode == OP_PTR_TO_NATIVE ) ) {
            if( ins->result == next->operands[ 0 ] ) {
                next->operands[ 0 ] = ins->operands[ 0 ];
                next->head.opcode = OP_MOV;
                next->table = NULL;
                *change = TRUE;
                return( TRUE );
            }
        }
        next = next->head.next;
    }
    return( FALSE );
}

static bool ReferencedBy( instruction *ins, name *op ) {
/******************************************************/
    int         i;
    name        *curr;

    if( _OpIsCall( ins->head.opcode ) ) {
        if( VisibleToCall( ins, op, FALSE ) ) {
            return( TRUE );
        }
    }
    // this should only be called for index names and USE_ADDRESS temps
    for( i = 0; i < ins->num_operands; i++ ) {
        curr = ins->operands[ i ];
        // assume anything which looks at memory uses op
        if( curr->n.class == N_INDEXED ||
            curr->n.class == N_MEMORY ) return( TRUE );
        if( SameThing( curr, op ) ) return( TRUE );
    }
    return( FALSE );
}

static bool DoMemWrites( instruction *ins, bool *change, instruction **n ) {
/**************************************************************************/
    instruction *next;

    n = n;
    if( ins->result != NULL ) {
        switch( ins->result->n.class ) {
        case N_TEMP:
            if( ( ins->result->v.usage & USE_ADDRESS ) == EMPTY ) break;
        case N_INDEXED:
        case N_MEMORY:
            if( SideEffect( ins ) ) return( FALSE );
            for( next = ins->head.next; next->head.opcode != OP_BLOCK; next = next->head.next ) {
                if( ReferencedBy( next, ins->result ) ) break;
                if( ReDefinedBy( next, ins->result ) ) {
                    if( next->result == ins->result ) {
                        *change = TRUE;
                        FreeIns( ins );
                        return( TRUE );
                    }
                    break;
                }
            }
        }
    }
    return( FALSE );
}

bool PeepOptBlock( block *blk, bool after_reg_alloc )
/***************************************************/
{
    instruction *ins;
    instruction *next;
    bool        change;

    change = FALSE;
    AfterRegAlloc = after_reg_alloc;
    for( ins = blk->ins.hd.next; ins->head.opcode != OP_BLOCK; ins = next ) {
        next = ins->head.next;
        if( VolatileIns( ins ) ) continue;
        if( DoArithmeticOps( ins, &change, &next ) ) continue;
        if( DoConversionOps( ins, &change, &next ) ) continue;
        if( DoMemWrites( ins, &change, &next ) ) continue;
    }
    return( change );
}

bool PeepOpt( block *start, block *(*func)(block *, void *parm), void *parm, bool after_reg_alloc )
/*************************************************************************************************/
{
    block       *blk;
    bool        change;

    change = FALSE;
    blk = start;
    do {
        change |= PeepOptBlock( blk, after_reg_alloc );
        blk = func( blk, parm );
    } while( blk != NULL );
    return( change );
}

⌨️ 快捷键说明

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