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 + -
显示快捷键?