savcode.h
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C头文件 代码 · 共 293 行
H
293 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#ifdef _InRegAssgn
#define _UpdateLive( ins, conf, reg_name ) \
if( ( _GBitOverlap( ins->head.live.out_of_block, \
conf->id.out_of_block ) ) \
|| ( _LBitOverlap( ins->head.live.within_block, \
conf->id.within_block ) ) ) { \
HW_TurnOn( ins->head.live.regs, reg_name->r.reg ); \
}
#define _Equal( op1, op2 ) ContainedIn( op1, op2 )
#define _SuffixLoad( ins, x, y, c ) \
SuffixIns( ins, MakeMove( x, y, c ) ); \
AddSegment( (ins)->head.next )
#define _PrefixLoad( ins, x, y, c ) \
PrefixIns( ins, MakeMove( x, y, c ) ); \
AddSegment( (ins)->head.prev )
#define _SuffixStore( ins, x, y, c ) \
SuffixIns( ins, MakeMove( x, y, c ) ); \
AddSegment( (ins)->head.next )
#define _PrefixStore( ins, x, y, c ) \
PrefixIns( ins, MakeMove( x, y, c ) ); \
AddSegment( (ins)->head.prev )
#define _ReplaceOpnd( tree, ins, i, reg_name, _1 ) \
DelSegOp( ins, i ); \
ins->operands[ i ] \
= FindReg( tree, ins->operands[ i ], reg_name ); \
FixGenEntry( ins );
#define _ReplaceIdxOpnd( tree, ins, i, reg_name ) \
ins->operands[ i ] = \
ReplIndex(ins,tree,ins->operands[ i ],reg_name); \
ins->head.state = INS_NEEDS_WORK
#define _ReplaceResult( tree, ins, reg_name, _1 ) \
DelSegRes( ins ); \
ins->result = FindReg( tree, ins->result, reg_name ); \
FixGenEntry( ins );
#define _ReplaceIdxResult( tree, ins, reg_name ) \
ins->result = ReplIndex( ins, tree, ins->result, reg_name ); \
ins->head.state = INS_NEEDS_WORK
#define _UpdateCost( _1, _2 )
#else
#define _UpdateLive( _1, _2, _3 )
#define _Equal( op1, op2 ) ( ( (op1)->n.class==N_TEMP ? DeAlias(op1) : (op1) ) \
== (op2) )
#define _SuffixLoad( _1, _2, _3, class ) \
block_cost += Save.load_cost[ class ];
#define _PrefixLoad( _1, _2, _3, class ) \
block_cost += Save.load_cost[ class ];
#define _SuffixStore( _1, _2, _3, class ) \
block_cost += Save.store_cost[ class ];
#define _PrefixStore( _1, _2, _3, class ) \
block_cost += Save.store_cost[ class ];
#define _ReplaceOpnd( _1, ins, i, _2, class ) \
block_save += Save.use_save[ class ]; \
if( i == 0 \
&& ins->head.opcode < FIRST_CONDITION \
&& ins->result != NULL \
&& ins->result->n.class == N_REGISTER ) { \
block_save += Save.use_save[ class ]; \
}
#define _ReplaceResult( _1, ins, _2, class ) \
if( ( ins->head.opcode==OP_MOV || ins->head.opcode==OP_CONVERT ) \
&& ins->result->n.class == N_TEMP \
&& ins->operands[ 0 ]->n.class == N_TEMP \
&& ins->result->t.location != NO_LOCATION \
&& ins->result->t.location \
== ins->operands[ 0 ]->t.location ) { \
block_cost+=Save.load_cost[ class ]; \
} else { \
block_save+=Save.def_save[ class ]; \
if( ins->num_operands != 0 \
&& ins->operands[ 0 ]->n.class == N_REGISTER ) { \
block_save+=Save.use_save[ class ]; \
} \
}
#define _ReplaceIdxResult( _1, _2, _3 ) \
block_save += Save.index_save;
#define _ReplaceIdxOpnd( _1, _2, _3, _4 ) \
block_save += Save.index_save;
#define _UpdateCost( blk, reg_name ) \
save += Weight( block_save, blk ); \
cost += Weight( block_cost, blk ); \
block_save = 0; \
block_cost = 0
#endif
class = opnd->n.name_class;
blk = conf->start_block;
ins = conf->ins_range.first;
last = FALSE;
if( _LBitOverlap( conf->ins_range.first->head.live.within_block,
conf->id.within_block ) ) {
flows_in = TRUE;
} else {
flows_in = FALSE;
}
for(;;) {
flow = blk->dataflow;
/* for each block in conflict range */
final_defn = NULL;
/* the very last definition */
last_defn = NULL;
/* the previous reaching definition */
first_use = NULL;
/* the very first use */
for(;;) {
/* for each instruction in conflict range */
if( ins->head.opcode == OP_BLOCK ) break;
next = ins->head.next;
/* reload volatile names after calls */
if( _OpIsCall( ins->head.opcode ) ) {
if( ( ( opnd->v.usage & USE_ADDRESS )
|| ( ( opnd->v.usage & NEEDS_MEMORY )
&& !( conf->state & OK_ACROSS_CALLS ) ) )
&& !_GBitOverlap( conf->id.out_of_block,
flow->call_exempt ) ) {
if( (ins->flags.call_flags & CALL_WRITES_NO_MEMORY) == 0
|| ( opnd->n.class == N_TEMP
&& ( opnd->v.usage & USE_ADDRESS ) ) ) {
_SuffixLoad( ins, opnd, reg_name, class );
}
if( ( last_defn != NULL
|| ( ( opnd->v.usage & USE_IN_ANOTHER_BLOCK )
&& _GBitOverlap( conf->id.out_of_block, flow->in ) ) )
&& ( ( !(ins->flags.call_flags & CALL_WRITES_NO_MEMORY ) )
|| ( !(ins->flags.call_flags & CALL_READS_NO_MEMORY ) )
|| ( opnd->n.class == N_TEMP
&& ( opnd->v.usage & USE_ADDRESS ) ) ) ) {
last_defn = NULL;
temp_ins = ins->head.prev;
_PrefixStore( ins, reg_name, opnd, class );
if( first_use == NULL ) {
first_use = temp_ins->head.next;
}
}
}
if( first_use == NULL ) {
first_use = ins;
}
}
i = ins->num_operands;
while( -- i >= 0 ) {
if( _Equal( ins->operands[ i ], opnd ) ) {
if( first_use == NULL ) {
first_use = ins;
}
_ReplaceOpnd( tree, ins, i, reg_name, class );
} else if( ins->operands[ i ]->n.class == N_INDEXED
&& _Equal( ins->operands[ i ]->i.index, opnd ) ) {
if( first_use == NULL ) {
first_use = ins;
}
_ReplaceIdxOpnd( tree, ins, i, reg_name );
}
}
if( ins->result != NULL ) {
if( _Equal( ins->result, opnd ) ) {
last_defn = ins;
final_defn = ins;
_ReplaceResult( tree, ins, reg_name, class );
} else if( ins->result->n.class == N_INDEXED
&& _Equal( ins->result->i.index, opnd ) ) {
_ReplaceIdxResult( tree, ins, reg_name );
}
}
_UpdateLive( ins, conf, reg_name );
ins = next;
last = ins->head.prev == conf->ins_range.last;
if( last ) break;
}
_UpdateLive( ins, conf, reg_name );
if( opnd->v.usage & USE_IN_ANOTHER_BLOCK ) {
#ifdef _InRegAssgn
if( first_use == NULL ) {
first_use = conf->ins_range.first;
_INS_NOT_BLOCK( first_use );
_INS_NOT_BLOCK( blk->ins.hd.next );
if( first_use->id < blk->ins.hd.next->id ) {
first_use = blk->ins.hd.next;
}
}
if( final_defn == NULL ) {
final_defn = conf->ins_range.last;
_INS_NOT_BLOCK( final_defn );
_INS_NOT_BLOCK( blk->ins.hd.prev );
if( final_defn->id > blk->ins.hd.prev->id ) {
final_defn = blk->ins.hd.prev;
if( ( blk->class & CONDITIONAL )
|| ( blk->class & SELECT ) ) {
final_defn = blk->ins.hd.next;
while( !_OpIsJump( final_defn->head.opcode ) ) {
final_defn = final_defn->head.next;
}
final_defn = final_defn->head.prev;
} else {
while( final_defn->head.opcode == OP_NOP ) {
final_defn = final_defn->head.prev;
}
}
}
}
#endif
if( (instruction *)&blk->ins == blk->ins.hd.next ) {
if( _GBitOverlap( conf->id.out_of_block, flow->need_store ) ) {
_SuffixStore( (instruction *)&blk->ins, reg_name, opnd, class );
}
if( _GBitOverlap( conf->id.out_of_block, flow->need_load ) ) {
_SuffixLoad( (instruction *)&blk->ins, opnd, reg_name, class );
}
} else {
if( _GBitOverlap( conf->id.out_of_block, flow->need_store ) ) {
_SuffixStore( final_defn, reg_name, opnd, class );
}
if( _GBitOverlap( conf->id.out_of_block, flow->need_load ) ) {
#ifdef _InRegAssgn
if( first_use->head.prev == final_defn->head.next ) {
if( first_use->head.prev->head.opcode != OP_BLOCK ) {
first_use = first_use->head.prev;
}
}
#endif
_PrefixLoad( first_use, opnd, reg_name, class );
}
}
} else if( opnd->v.usage & ( NEEDS_MEMORY | USE_ADDRESS ) ) {
if( last_defn != NULL ) {
_SuffixStore( last_defn, reg_name, opnd, class );
/* } else { it was already stored after its last definition */
}
if( flows_in ) {
_PrefixLoad( conf->ins_range.first, opnd, reg_name, class );
}
}
_UpdateCost( blk, opnd );
if( last ) break;
blk = blk->next_block;
ins = blk->ins.hd.next;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?