i87sched.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,092 行 · 第 1/3 页
C
1,092 行
}
}
TempList = SortList( TempList, offsetof( temp_entry, next ), Better );
}
extern void FiniTempEntries( void ) {
/***************************/
temp_entry *temp,*junk;
temp = TempList;
while( temp != NULL ) {
junk = temp;
temp = temp->next;
_Free( junk, sizeof( temp_entry ) );
}
TempList = NULL;
}
static bool StackBetween( instruction *first, instruction *last, int inc ) {
/******************************************************************************/
instruction *ins;
bool enough;
enough = TRUE;
for( ins = first; ins != last; ins = ins->head.next ) {
if( ins->s.stk_depth >= (Max87Stk-1) || _OpIsCall( ins->head.opcode ) ) {
enough = FALSE;
}
ins->s.stk_depth += inc;
}
return( enough );
}
static void KillRelatedTemps( name *op )
/******************************************/
{
temp_entry *temp;
if( op->n.class != N_MEMORY ) return;
for( temp = TempList; temp != NULL; temp = temp->next ) {
if( temp->op->n.class == N_MEMORY &&
temp->op->v.symbol == op->v.symbol ) {
temp->killed = TRUE;
}
}
}
static bool OKToCache( temp_entry *temp ) {
/*********************************************/
instruction *ins;
name *seg;
ins = temp->first;
if( ins->num_operands <= NumOperands( ins ) ) return( TRUE );
seg = ins->operands[ ins->num_operands - 1 ];
ins = ins->head.prev;
while( ins->head.opcode != OP_BLOCK ) {
/*
* Might be a segment load or some other sort of nonsense here.
*/
if( ReDefinedBy( ins, seg ) ) return( FALSE );
ins = ins->head.prev;
}
return( _BLOCK( ins ) == Entry );
}
static void CacheTemps( block *blk ) {
/****************************************/
temp_entry *temp, **owner;
block_edge *exit_edge = NULL;
Entry = NULL;
Exit = NULL;
if( blk->class & LOOP_HEADER
&& blk->inputs == 2 && blk->targets == 2 ) {
if( blk->edge[0].destination == blk ) {
Exit = blk->edge[1].destination;
exit_edge = &blk->edge[1];
} else if( blk->edge[1].destination == blk ) {
Exit = blk->edge[0].destination;
exit_edge = &blk->edge[0];
} else {
Exit = NULL;
}
if( Exit != NULL ) {
if( blk->input_edges->source == blk ) {
Entry = blk->input_edges->next_source->source;
} else if( blk->input_edges->next_source->source == blk ) {
Entry = blk->input_edges->source;
} else {
Entry = NULL;
Exit = NULL;
}
}
if( Entry != NULL ) {
if( Entry->class & JUMP ) {
if( Exit->inputs != 1 ) {
Exit = AddPreBlock( Exit );
MoveEdge( exit_edge, Exit );
}
}
}
}
for( temp = TempList; temp != NULL; temp = temp->next ) {
if( temp->killed ) continue;
if( !OKToCache( temp ) ) {
temp->killed = TRUE;
}
}
for( temp = TempList; temp != NULL; temp = temp->next ) {
if( temp->killed ) {
KillRelatedTemps( temp->op );
}
}
for( temp = TempList; temp != NULL; temp = temp->next ) {
if( temp->killed ) continue;
if( temp->op->v.usage & USE_IN_ANOTHER_BLOCK ) {
if( Entry != NULL ) {
temp->first = blk->ins.hd.next;
temp->last = blk->ins.hd.prev;
temp->whole_block = TRUE;
} else {
if( temp->defined ) continue;
if( temp->first == temp->last ) continue;
}
temp->global = TRUE;
} else {
if( !temp->defined ) continue; // I'm not sure if these save anything
if( temp->defined && temp->first->u.gen_table->generate!=G_MFST ) continue;
if( RegAction( temp->last ) == NULL ) continue;
if( temp->first == temp->last ) continue;
}
if( StackBetween( temp->first, temp->last, 0 ) ) {
StackBetween( temp->first, temp->last, 1 );
temp->cached = TRUE;
}
}
owner = &TempList;
for( ;; ) {
temp = *owner;
if( temp == NULL ) break;
if( temp->cached ) {
owner = &temp->next;
} else {
*owner = temp->next;
_Free( temp, sizeof( temp_entry ) );
}
}
}
// just have to make sure this is not a valid FP-stack depth
#define SEQ_INIT_VALUE 0xff
extern void FPPreSched( block *blk ) {
/****************************************/
temp_entry *temp;
instruction *ins;
int i;
int depth;
MaxSeq = 0;
ins = blk->ins.hd.next;
while( ins->head.opcode != OP_BLOCK ) {
if( ins->sequence > MaxSeq ) MaxSeq = ins->sequence;
ins = ins->head.next;
}
++MaxSeq;
InitTempEntries( blk );
CacheTemps( blk );
for( temp = TempList; temp != NULL; temp = temp->next ) {
StackBetween( temp->first, temp->last, -1 );
}
_Alloc( SeqCurDepth, MaxSeq * sizeof( *SeqCurDepth ) );
_Alloc( SeqMaxDepth, MaxSeq * sizeof( *SeqMaxDepth ) );
for( i = 0; i < MaxSeq; ++i ) {
SeqCurDepth[ i ] = SEQ_INIT_VALUE;
SeqMaxDepth[ i ] = 0;
}
ins = blk->ins.hd.prev;
while( ins->head.opcode != OP_BLOCK ) {
if( SeqCurDepth[ ins->sequence ] == SEQ_INIT_VALUE ) {
if( FPStackIns( ins ) ) {
SeqCurDepth[ ins->sequence ] = ins->stk_exit;
}
}
ins = ins->head.prev;
}
for( i = 0; i < MaxSeq; ++i ) {
if( SeqCurDepth[ i ] == SEQ_INIT_VALUE ) {
SeqCurDepth[ i ] = 0;
}
}
ins = blk->ins.hd.next;
while( ins->head.opcode != OP_BLOCK ) {
/*
* We do this here in order to not be faked out by inheriting bogus values
* when we prefix an instruction to another FP instruction. This would screw
* up our instruction scheduling by digging a hole which FPStkOver would
* be convinced we could not get out of. For an illustration of the problem,
* consider the two sequences "pow a, b -> c" and "pow d, e -> f" before
* RegAlloc et all and how we would schedule these with -fpr.
*/
ins->s.stk_extra = FPStkReq( ins ); // BBB - March 22, 1994
depth = InsMaxDepth( ins ) + ins->s.stk_extra;
ins->t.stk_max = SeqMaxDepth[ ins->sequence ];
if( depth > SeqMaxDepth[ ins->sequence ] ) {
SeqMaxDepth[ ins->sequence ] = depth;
}
ins = ins->head.next;
}
}
static void FiniGlobalTemps( void ) {
/*********************************/
temp_entry *temp;
instruction *ins;
for( temp = TempList; temp != NULL; temp = temp->next ) {
if( temp->whole_block ) {
ins = (instruction *)&Exit->ins;
if( temp->defined ) {
SuffFSTPRes( ins, temp->actual_op, RES_MEM );
} else {
SuffFSTPRes( ins, temp->actual_op, RES_MEM_THROWAWAY );
}
ins->head.next->ins_flags |= FP_INS_INTRODUCED;
}
}
}
static void InitGlobalTemps( void ) {
/*********************************/
temp_entry *temp;
instruction *ins;
int locn;
locn = ACTUAL_0;
for( temp = TempList; temp != NULL; temp = temp->next ) {
if( temp->whole_block ) ++locn;
}
for( temp = TempList; temp != NULL; temp = temp->next ) {
if( temp->whole_block ) {
ins = Entry->ins.hd.prev;
while( ins->head.opcode == OP_NOP ) {
if( ins->flags.nop_flags & NOP_ZAP_INFO ) break;
ins = ins->head.prev;
}
ins = ins->head.next;
PrefFLDOp( ins, OP_MEM, temp->actual_op );
ins->head.prev->ins_flags |= FP_INS_INTRODUCED;
temp->actual_locn = --locn;
}
}
}
static void XchForCall( instruction *ins, int i ) {
/*****************************************************/
byte *actual_i_owner;
byte *actual_0_owner;
if( i <= 0 ) return;
if( InsLoc( ins, VIRTUAL_0+i ) != ACTUAL_0+i ) {
GetToTopOfStack( ins, VIRTUAL_0+i );
if( InsLoc( ins, VIRTUAL_0+i ) != ACTUAL_0+i ) {
PrefixExchange( ins, ACTUAL_0+i );
actual_i_owner = ActualStackOwner( ACTUAL_0+i );
actual_0_owner = ActualStackOwner( ACTUAL_0 );
*actual_i_owner = ACTUAL_0;
*actual_0_owner = ACTUAL_0+i;
}
}
XchForCall( ins, i-1 );
}
static void ReOrderForCall( instruction *ins ) {
/**************************************************/
int i,count;
count = Count87Regs( ins->operands[ CALL_OP_USED ]->r.reg );
XchForCall( ins, count-1 );
for( i = 0; i < count; ++i ) {
PopStack( ins );
}
}
extern void FPPostSched( block *blk ) {
/*****************************************/
fp_attr attr;
instruction *ins;
instruction *next;
int virtual;
temp_entry *temp;
_Free( SeqCurDepth, MaxSeq * sizeof( *SeqCurDepth ) );
_Free( SeqMaxDepth, MaxSeq * sizeof( *SeqMaxDepth ) );
FiniTempEntries();
InitStackLocations();
InitTempEntries( blk );
CacheTemps( blk );
InitGlobalTemps();
ins = blk->ins.hd.next;
while( ins->head.opcode != OP_BLOCK ) {
next = ins;
if( !( ins->ins_flags & FP_INS_INTRODUCED ) ) {
attr = FPAttr( ins );
temp = LookupTempEntry( ins->result );
if( attr & NEEDS_ST0 && temp == NULL ) {
GetToTopOfStack( ins, VIRTUAL_0 );
} else if( attr & NEEDS_ST0_ST1 ) {
if( attr & POPS2 ) {
// the dreaded FCOMPP
next = FComppKluge( ins );
} else {
next = GetST0andST1( ins );
}
} else if( attr & POPS_ALL ) {
ReOrderForCall( ins );
}
if( temp != NULL ) {
attr = ResultToReg( ins, temp, attr );
} else if( attr & SETS_ST1 ) {
SetResultReg( ins, VIRTUAL_1 );
} else if( attr & EXCHANGES ) {
virtual = FPRegNum( ins->result );
SetResultReg( ins, virtual );
}
temp = LookupTempEntry( ins->operands[0] );
if( temp != NULL ) {
next = OpToReg( ins, temp, attr );
} else if( attr & PUSHES ) {
PushStack( ins );
} else if( attr & POPS2 ) {
PopStack( ins );
PopStack( ins );
} else if( attr & POPS ) {
PopStack( ins );
}
}
ins = next->head.next;
}
FiniGlobalTemps();
FiniStackLocations();
FiniTempEntries();
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?