scblock.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 304 行
C
304 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Register scoreboarding on a basic block.
*
****************************************************************************/
#include "standard.h"
#include "coderep.h"
#include "score.h"
#include "opcodes.h"
#include "zerobits.h"
#include "hostsys.h"
extern bool UnChangeable(instruction*);
extern void UpdateLive(instruction*,instruction*);
extern void SCBlip(void);
extern void FreeIns(instruction*);
extern bool SideEffect(instruction*);
extern bool DoesSomething(instruction*);
extern void DoNothing(instruction*);
extern void FreeJunk( block *blk )
/*************************************
Free instructions which aren't going to be generated.
*/
{
instruction *ins;
instruction *next;
ins = blk->ins.hd.next;
while( ins->head.opcode != OP_BLOCK ) {
next = ins->head.next;
if( DoesSomething( ins ) == FALSE
&& SideEffect( ins ) == FALSE
&& ins->head.opcode < FIRST_OP_WITH_LABEL
&& ins->head.opcode != OP_NOP ) { /*% there for zap info*/
FreeIns( ins );
}
ins = next;
}
}
static bool StupidMove( score *sc, instruction *ins )
/***************************************************/
{
score_info info;
int dst_index;
if( ins->head.opcode != OP_MOV ) return( FALSE );
if( ins->result->n.class != N_REGISTER ) return( FALSE );
dst_index = ins->result->r.reg_index;
if( ins->operands[0]->n.class == N_REGISTER ) {
if( !RegsEqual( sc, ins->operands[0]->r.reg_index, dst_index ) ) {
return( FALSE );
}
} else {
ScoreInfo( &info, ins->operands[0] );
if( !ScoreEqual( sc, dst_index, &info ) ) {
return( FALSE );
}
}
/*
We've seen a condition already in the
block, but we've got a move instruction
that assigns a value to the result register that the
register already has. Kill the sucker.
*/
DoNothing( ins );
return( TRUE );
}
static bool RemDeadCode( block *blk )
/****************************************
This removes any instructions in "blk" which assign to a register which
dies immediately following that instruction and has no side effects.
Returns TRUE if any instructions were killed, in which case the
live information must be updated.
*/
{
bool change;
name *result;
instruction *ins;
instruction *next_ins;
ins = blk->ins.hd.next;
change = FALSE;
while( ins->head.opcode != OP_BLOCK ) {
next_ins = ins->head.next;
result = ins->result;
/* if result is a register and it dies after this instruction*/
if( !_OpIsCall( ins->head.opcode )
&& UnChangeable( ins ) == FALSE
&& SideEffect( ins ) == FALSE
&& result != NULL
&& ScConvert( ins ) == FALSE
&& result->n.class == N_REGISTER
&& !HW_Ovlap( ins->head.next->head.live.regs, result->r.reg ) ) {
FreeIns( ins );
change = TRUE;
}
ins = next_ins;
}
return( change );
}
extern bool DoScore( block *blk )
/************************************
Do register scoreboarding on a basic block. Remember which
registers contain which values as we run through the block and
then use that information to try to replace memory references
with register references.
*/
{
instruction *next_ins;
score *scoreboard;
name *dst;
bool change;
bool had_condition;
score_info info;
instruction *ins;
hw_reg_set tmp;
change = FALSE;
for( ;; ) {
SCBlip();
while( RemDeadCode( blk ) ) {
UpdateLive( blk->ins.hd.next, blk->ins.hd.prev );
change = TRUE;
}
if( RegThrash( blk ) == FALSE ) break;
change = TRUE;
}
scoreboard = blk->cc;
ins = blk->ins.hd.next;
had_condition = FALSE;
while( ins->head.opcode != OP_BLOCK ) {
ScoreSegments( scoreboard );
/* May all intel designers rot in hell forever and ever, amen*/
if( _OpIsCondition( ins->head.opcode ) && ins->result == NULL ) {
if( had_condition ) {
blk->class |= MULTIPLE_EXITS;
}
had_condition = TRUE;
}
if( ScoreZero( scoreboard, &ins ) ) {
change = TRUE;
UpdateLive( blk->ins.hd.next, blk->ins.hd.prev );
}
if( ins->head.opcode == OP_BLOCK ) break;
/* ScoreZero freed the last instr!*/
next_ins = ins->head.next;
dst = ins->result;
if( UnChangeable( ins ) ) {
if( dst != NULL ) {
ScoreInfo( &info, dst );
ScoreKillInfo( scoreboard, dst, &info, HW_EMPTY );
RegKill( scoreboard, ins->zap->reg );
}
} else if( DoesSomething( ins ) ) {
if( ins->head.opcode == OP_CALL
|| ins->head.opcode == OP_CALL_INDIRECT ) {
MemChanged( scoreboard,
( ins->flags.call_flags & CALL_WRITES_NO_MEMORY ) == 0 );
RegKill( scoreboard, ins->zap->reg );
if( dst != NULL && dst->n.class != N_REGISTER ) {
ScoreInfo( &info, dst );
ScoreKillInfo( scoreboard, dst, &info, HW_EMPTY );
}
} else {
if( FindRegOpnd( scoreboard, ins ) ) {
change = TRUE;
UpdateLive( blk->ins.hd.next, blk->ins.hd.prev );
}
if( ins->head.opcode == OP_MOV && had_condition == FALSE ) {
if( ScoreMove( scoreboard, ins ) ) {
change = TRUE;
UpdateLive( blk->ins.hd.next, blk->ins.hd.prev );
}
if( next_ins->head.prev == ins ) {
RegKill( scoreboard, ins->zap->reg );
}
} else if( ins->head.opcode == OP_LA && had_condition == FALSE ) {
if( ScoreLA( scoreboard, ins ) ) {
change = TRUE;
UpdateLive( blk->ins.hd.next, blk->ins.hd.prev );
}
if( next_ins->head.prev == ins ) {
RegKill( scoreboard, ins->zap->reg );
}
} else if( dst == NULL ) {
RegKill( scoreboard, ins->zap->reg );
} else if( StupidMove( scoreboard, ins ) ) {
change = TRUE;
} else {
if( dst->n.class == N_REGISTER ) {
tmp = ins->zap->reg;
HW_TurnOn( tmp, dst->r.reg );
RegKill( scoreboard, tmp );
} else {
ScoreInfo( &info, dst );
ScoreKillInfo( scoreboard, dst, &info, HW_EMPTY );
RegKill( scoreboard, ins->zap->reg );
}
if( had_condition == FALSE ) {
ScZeroCheck( scoreboard, ins );
}
}
}
} else {
if( ins->head.opcode == OP_NOP && dst != NULL ) {
ScoreInfo( &info, dst );
ScoreKillInfo( scoreboard, dst, &info, HW_EMPTY );
}
RegKill( scoreboard, ins->zap->reg );
}
ins = next_ins;
}
return( change );
}
extern byte HasZero( score *sc, name *n )
/********************************************
given a scoreboard "sc", determine if name "n" is equal to
zero or has any portions which are equal to zero. This is recursive
since a regisiter like EAX on the 386 has pieces AX, AH, and AL.
*/
{
byte bits;
int i;
int hi;
int lo;
bits = 0;
if( n->n.class == N_CONSTANT ) {
if( n->c.const_type == CONS_ABSOLUTE ) {
if( n->c.int_value == 0 ) {
bits = LO_HALF | HI_HALF;
} else if( n->n.size == 2 ) {
if( ( n->c.int_value & 0x00ff ) == 0 ) {
bits |= LO_HALF;
}
if( ( n->c.int_value & 0xff00 ) == 0 ) {
bits |= HI_HALF;
}
} else if( n->n.size == 4 ) {
if( ( n->c.int_value & 0x0000ffff ) == 0 ) {
bits |= LO_HALF;
}
if( ( n->c.int_value & 0xffff0000 ) == 0 ) {
bits |= HI_HALF;
}
}
}
} else if( n->n.class == N_REGISTER ) {
i = n->r.reg_index;
if( ScoreLookup( &sc[ i ], ScZero ) ) {
bits |= LO_HALF | HI_HALF;
} else {
hi = ScoreList[ i ]->high;
lo = ScoreList[ i ]->low;
if( hi != NO_INDEX && lo != NO_INDEX ) {
if( _IsZero( HasZero( sc, ScoreList[ lo ]->reg_name ) ) ) {
bits |= LO_HALF;
}
if( _IsZero( HasZero( sc, ScoreList[ hi ]->reg_name ) ) ) {
bits |= HI_HALF;
}
}
}
}
if( n->n.size == 1 ) {
bits |= IS_BYTE;
}
return( bits );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?