i87opt.c

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

C
906
字号
            next = _BLOCK( next )->next_block->ins.hd.next;
        }
    }
    return( FALSE );
}

static  void    UseInOther( name *op )
{
    if( op == NULL ) return;
    switch( op->n.class ) {
    case N_TEMP:
    case N_MEMORY:
        op->v.usage |= USE_IN_ANOTHER_BLOCK;
        break;
    case N_INDEXED:
        UseInOther( op->i.index );
        UseInOther( op->i.base );
        break;
    default:
        break;
    }
}

static  int     FPPushDelay( pn parm, call_state *state ) {
/**********************************************************
    For each parm, move it into a temp, and "push" the temp onto the
    8087 stack just before the call instruction.  If the calculation of
    the parm can be moved down just in front of the call, we do that,
    instead of using a temporary.
*/

    instruction *ins;
    instruction *new_ins;
    an          addr;
    pn          next_parm;
    int         parms;


    parms = 0;
    for( ; parm != NULL; parm = next_parm ) {
        next_parm = parm->next;
        if( parm->ins != NULL ) continue;
        addr = parm->name;
        if( addr->tipe->attr & TYPE_FLOAT && HW_COvlap( parm->regs,HW_FLTS ) ){
            ++parms;
            if( addr->format != NF_INS ) {
                _Zoiks( ZOIKS_043 );
            }
            ins = addr->u.ins;
            if( PushDelayedIfStackOperand( ins, parm, state ) ) continue;
            if( PushDelayedIfRedefinition( ins, parm, state ) ) continue;
            /* we can push it just before the CALL */
            if( addr->flags & ADDR_CROSSED_BLOCKS ) {
                UseInOther( ins->operands[0] );
                if( ins->num_operands > 1 ) UseInOther( ins->operands[1] );
            }
            new_ins = MakeNary( ins->head.opcode, ins->operands[ 0 ],
                                ins->operands[ 1 ], AllocRegName( HW_ST0 ),
                                ins->type_class, ins->base_type_class,
                                ins->num_operands );
            Pushes( new_ins );
            new_ins->num_operands = ins->num_operands;
            AddIns( new_ins );
#if _TARGET & _TARG_80386
            if( state->attr & ROUTINE_STACK_RESERVE ) {
                ReserveStack( state, new_ins, addr->tipe->length );
            }
#endif
            BGDone( addr ); /* so ins DOES get freed*/
            parm->ins = new_ins;
        }
    }
    return( parms );
}

extern  void    FPPushParms( pn parm, call_state *state ) {
/**********************************************************
    "push" parameters onto the 8087 stack.  If parameters can be pushed
    as soon as they are calculated, do that (FPPushImmed), otherwise we
    have to "push" it onto the 8087 just before the call instruction
    (FPPushDelay). For each parameter there is an address_node (an) of
    type NF_INS, which not had the result field filled in yet.
*/


    int parms;

    if( _FPULevel( FPU_87 ) ) {
        parms = 0;
        if( CanPushImmed( parm, &parms ) &&
                parms < Max87Stk &&
                ( state->attr & ROUTINE_STACK_RESERVE ) == 0 ) {
            parms = FPPushImmed( parm );
        } else {
            if( parms != 0 ) {
                parms = FPPushDelay( parm, state );
            }
        }
        HW_CTurnOff( state->parm.used, HW_FLTS );
        while( --parms >= 0 ) {
            HW_TurnOn( state->parm.used, FPRegs[ parms ] );
        }
    }
}



extern  void    FPOptimize( void ) {
/*****************************

    Fix up the 8087 instructions.  The instructions so far
*/

    if( _FPULevel( FPU_87 ) ) {
        if( _IsntModel( NO_OPTIMIZATION ) ) {
            Opt8087();
        }
        Wait8087();
    }
}


#define G(x)    (x)->u.gen_table->generate

static  opcode_entry    FSINCOS = { PRESERVE, 0, G_FSINCOS, 0, FU_TRIG };

#define _OTHER( x ) ( (x) == OP_SIN ? OP_COS : OP_SIN )

static  bool    FSinCos( instruction *ins1 ) {
/********************************************
    find the FSINCOS sequence
*/
    instruction *ins2;
    instruction *ins3;
    instruction *ins4;

    if( !_IsTargetModel( I_MATH_INLINE ) ) {
        return( FALSE );
    }
    ins2 = ins1->head.next;
    ins3 = ins2->head.next;
    ins4 = ins3->head.next;
    if( G( ins1 ) == G_MFLD ) {
        if( ins2->head.opcode != OP_SIN && ins2->head.opcode != OP_COS ) {
            return( FALSE );
        }
        if( G( ins3 ) != G_MFLD ) {
            return( FALSE );
        }
        if( ins1->operands[ 0 ] != ins3->operands[ 0 ] ) {
            return( FALSE );
        }
        if( ins4->head.opcode != _OTHER( ins2->head.opcode ) ) {
            return( FALSE );
        }
    } else if( G( ins1 ) == G_RFLD ) {
        if( ins2->head.opcode != OP_SIN && ins2->head.opcode != OP_COS ) {
            return( FALSE );
        }
        if( G( ins3 ) != G_RFLD ) {
            return( FALSE );
        }
        if( FPRegNum( ins1->operands[ 0 ] ) !=
            FPRegNum( ins3->operands[ 0 ] ) - 1 ) {
                return( FALSE );
            }
        if( ins4->head.opcode != _OTHER( ins2->head.opcode ) ) {
            return( FALSE );
        }
    } else if( ins1->head.opcode == OP_SIN ) {
        if( G( ins2 ) != G_RFLD ) {
            return( FALSE );
        }
        if( FPRegNum( ins2->operands[ 0 ] ) != 1 ) {
            return( FALSE );
        }
        if( ins3->head.opcode != _OTHER( ins1->head.opcode ) ) {
            return( FALSE );
        }
        ins4 = ins3;
        ins3 = ins2;
        ins2 = ins1;
    } else {
        return( FALSE );
    }
    ins2->u.gen_table = &FSINCOS;
    if( ins2->head.opcode != OP_SIN ) {
        PrefFXCH( ins3, 1 );
    }
    FreeIns( ins3 );
    FreeIns( ins4 );
    return( TRUE );
}


static  instruction     *Next87Ins( instruction *ins ) {
/******************************************************/

    instruction *next;

    next = ins->head.next;
    for( ;; ) {
        if( next->head.opcode == OP_BLOCK ) return( ins );
        if( DoesSomething( next ) ) break;
        next = next->head.next;
    }
    return( next );
}

static  bool    RedundantStore( instruction *ins ) {
/***************************************************
*/

    instruction         *next;

    for( next = ins->head.next;
         next->head.opcode != OP_BLOCK; next = next->head.next ) {
        if( next->result == ins->result ) {
            if( G( next ) == G_MFSTNP || G( next ) == G_MFST ) {
                return( TRUE );
            }
        }
        if( InsOrderDependant( ins, next ) ) return( FALSE );
    }
    return( FALSE );
}


static  void    AdjustST( name **p, int adjust )
/**********************************************/
{
    *p = ST( FPRegNum( *p ) + adjust );
}


static  instruction     *BackUpAndFree( instruction *ins, instruction *junk1,
                                        instruction *junk2 ) {
/*************************************************************
*/
    instruction *ret;

    ret = ins->head.prev;
    if( junk1 != NULL ) FreeIns( junk1 );
    if( junk2 != NULL ) FreeIns( junk2 );
    if( ret->head.opcode == OP_BLOCK ) ret = ret->head.next;
    return( ret );
}

#if _TARGET & _TARG_IAPX86
    #define RL_MOVE_REG RL_WORD
#else
    #define RL_MOVE_REG RL_DOUBLE
#endif

static  instruction    *To86Move( instruction *ins, instruction *next ) {
/************************************************************************
    Turn a move which uses the 8087 (FLD X, FSTP Y) into a move using
    the 8086 using an available 8086 register.
*/

    hw_reg_set  *regs;
    name        *reg;
    instruction *ret;

    ret = ins->head.next;
    for( regs = RegSets[ RL_MOVE_REG ]; ; ++regs ) {
        if( HW_CEqual( *regs, HW_EMPTY ) ) return( ret );
        if( HW_Ovlap( *regs, next->head.live.regs ) ) continue;
        if( HW_Ovlap( *regs, ins->head.live.regs ) ) continue;
        reg = AllocRegName( *regs );
        break;
    }
    if( next->result->n.name_class == FS ) {
#if _TARGET & _TARG_80386
        MoveThrough( ins->operands[ 0 ], next->result, ins, next, reg, U4 );
#else
        if( OptForSize > 50 ) return( ret );
        MoveThrough( LowPart( ins->operands[ 0 ], U2 ),
                     LowPart( next->result, U2 ), ins, next, reg, U2 );
        MoveThrough( HighPart( ins->operands[ 0 ], U2 ),
                     HighPart( next->result, U2 ), ins, next, reg, U2 );
#endif
    } else {
        if( OptForSize > 50 ) return( ret );
#if _TARGET & _TARG_80386
        MoveThrough( LowPart( ins->operands[ 0 ], U4 ),
                     LowPart( next->result, U4 ), ins, next, reg, U4 );
        MoveThrough( HighPart( ins->operands[ 0 ], U4 ),
                     HighPart( next->result, U4 ), ins, next, reg, U4 );
#else
        MoveThrough( LowPart( LowPart( ins->operands[ 0 ], U4 ), U2 ),
                     LowPart( LowPart( next->result      , U4 ), U2 ),
                     ins, next, reg, U2 );
        MoveThrough( HighPart( LowPart( ins->operands[ 0 ], U4 ), U2 ),
                     HighPart( LowPart( next->result      , U4 ), U2 ),
                     ins, next, reg, U2 );
        MoveThrough( LowPart( HighPart( ins->operands[ 0 ], U4 ), U2 ),
                     LowPart( HighPart( next->result      , U4 ), U2 ),
                     ins, next, reg, U2 );
        MoveThrough( HighPart( HighPart( ins->operands[ 0 ], U4 ), U2 ),
                     HighPart( HighPart( next->result      , U4 ), U2 ),
                     ins, next, reg, U2 );

⌨️ 快捷键说明

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