optpull.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 283 行
C
283 行
/****************************************************************************
*
* 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!
*
****************************************************************************/
#include "optwif.h"
#include "escape.h"
extern ins_entry *LastIns;
extern bool InsDelete;
extern byte OptForSize;
extern void JmpToRet(ins_entry*,ins_entry*);
extern oc_class NextClass(ins_entry*);
extern ins_entry *DelInstr(ins_entry*);
extern ins_entry *Untangle(ins_entry*);
extern void ChgLblRef(ins_entry*,code_lbl*);
extern code_lbl *AddNewLabel(ins_entry*,int);
extern void InsertQueue(ins_entry*,ins_entry*);
extern void DeleteQueue(ins_entry*);
extern ins_entry *NextIns(ins_entry*);
extern ins_entry *PrevIns(ins_entry*);
extern oc_class PrevClass(ins_entry*);
extern void AddInstr(ins_entry*,ins_entry*);
extern ins_entry *NewInstr(any_oc*);
extern bool CodeHasAbsPatch( oc_entry * );
extern bool FindShort( ins_entry *ins, ins_entry *end ) {
/***********************************************************/
for(;;) {
if( ins == NULL ) break;
if( ins == end ) break;
if( _Class( ins ) == OC_LABEL ) {
if( _Attr( ins ) & ATTR_SHORT ) return( TRUE );
_ClrStatus( _Label( ins ), SHORTREACH );
}
ins = NextIns( ins );
}
return( FALSE );
}
static void DoCloneCode( ins_entry *jmp, ins_entry *hoist ) {
/***************************************************************/
ins_entry *clone_point;
ins_entry *clone;
oc_class cl;
clone_point = PrevIns( jmp );
for( ;; ) {
cl = _Class( hoist );
switch( cl ) {
case OC_LABEL:
case OC_INFO:
case OC_LREF:
break;
default:
clone = NewInstr( &hoist->oc );
AddInstr( clone, clone_point );
if( _TransferClass( cl ) ) return;
clone_point = clone;
break;
}
hoist = NextIns( hoist );
}
}
#define MAX_CLONE_SIZE 40
extern void CloneCode( code_lbl *lbl ) {
/*******************************************
consider:
JMP L1
....
L1: POP AX
RET
we want to clone the code at L1 at the point of the jump,
since it will be faster (and smaller since POP AX/RET is only 2 bytes
while the JMP might be 3/5).
*/
ins_entry *next;
ins_entry *lbl_ins;
ins_entry *hoist;
ins_entry *jmp;
unsigned size;
unsigned max_size;
lbl_ins = lbl->ins;
if( lbl_ins == NULL ) return;
hoist = NextIns( lbl_ins );
next = hoist;
size = 0;
for( ;; ) {
if( next == NULL ) return;
if( _Class( next ) == OC_CODE && CodeHasAbsPatch( &next->oc.oc_entry ) ) return;
if( _Class( next ) != OC_LABEL ) {
size += _ObjLen( next );
if( size > MAX_CLONE_SIZE ) return;
if( _TransferClass( _Class( next ) ) ) break;
}
next = NextIns( next );
}
if( _Class( next ) == OC_JMP && _Label( next ) == lbl ) return;
for( jmp = lbl->refs; jmp != NULL; jmp = _LblRef( jmp ) ) {
if( next == jmp ) continue;
if( !_TransferClass( _Class( jmp ) ) ) continue;
max_size = _ObjLen( jmp );
if( size > max_size && FindShort( jmp, NULL ) ) continue;
if( OptForSize < 50 ) {
max_size *= (100-OptForSize) / 25;
}
if( size > max_size ) continue;
DoCloneCode( jmp, hoist );
DelInstr( jmp );
}
}
extern ins_entry *IsolatedCode( ins_entry *instr ) {
/*********************************************************/
ins_entry *next;
optbegin
next = NextIns( instr );
for(;;) {
if( next == NULL ) optreturn( next );
if( _Class( next ) == OC_LABEL ) break;
_Savings( OPT_ISOLATED, _ObjLen( next ) );
if( _Class( next ) == OC_INFO ) {
next = next->ins.next;
} else {
next = DelInstr( next );
}
if( _Class( instr ) == OC_DEAD ) break;
}
next = Untangle( next );
optreturn( next );
}
extern bool StraightenCode( ins_entry *jump ) {
/*************************************************/
ins_entry *next;
ins_entry *insert;
ins_entry *hoist;
ins_entry *end_hoist;
oc_class cl;
int align;
optbegin
hoist = _Label( jump )->ins;
if( hoist == NULL ) optreturn( FALSE );
if( hoist == LastIns ) optreturn( FALSE );
cl = PrevClass( hoist );
if( !_TransferClass( cl ) ) optreturn( FALSE );
end_hoist = NULL;
next = hoist;
for(;;) {
if( next == jump ) { // pushing code down to jump
if( end_hoist == NULL ) optreturn( FALSE );
if( FindShort( hoist, end_hoist ) ) optreturn( FALSE );
break;
}
if( next == NULL ) { // hauling code up to jump
if( FindShort( jump, hoist ) ) optreturn( FALSE );
break;
}
cl = _Class( next );
if( end_hoist == NULL && _TransferClass( cl ) ) {
end_hoist = next;
}
next = NextIns( next );
}
align = _ObjLen( hoist );
insert = jump;
for(;;) {
if( hoist == NULL ) {
ChgLblRef( jump, AddNewLabel( LastIns, align ) );
next = LastIns;
break;
}
next = NextIns( hoist );
DeleteQueue( hoist );
InsertQueue( hoist, insert );
if( hoist == jump ) optreturn( FALSE );
insert = hoist;
cl = _Class( hoist );
if( _TransferClass( cl ) ) {
IsolatedCode( insert );
break;
}
hoist = next;
}
InsDelete = TRUE;
Untangle( next );
if( _Class( jump ) != OC_DEAD ) {
Untangle( _Label( jump )->ins );
}
optreturn( TRUE );
}
extern void CheckStraightenCode( ins_entry *lbl_ins ) {
/******************************************************************/
code_lbl *lbl;
ins_entry *jmp;
optbegin
if( lbl_ins != NULL ) {
lbl = _Label( lbl_ins );
for( jmp = lbl->refs; jmp != NULL; jmp = _LblRef( jmp ) ) {
if( !_TransferClass( _Class( jmp ) ) ) continue;
if( StraightenCode( jmp ) ) break;
}
}
optend
extern void CallRet( ins_entry *instr ) {
/*******************************************/
ins_entry *lbl;
optbegin
if( _Attr( instr ) & ATTR_POP ) optreturnvoid;
lbl = _Label( instr )->ins;
if( lbl == NULL ) optreturnvoid;
if( NextClass( lbl ) != OC_RET ) optreturnvoid;
_Savings( OPT_CALLTORET, _ObjLen( instr ) );
DelInstr( instr );
optend
extern void JmpRet( ins_entry *instr ) {
/******************************************/
ins_entry *ret;
optbegin
if( InsDelete ) optreturnvoid;
ret = _Label( instr )->ins;
if( ret == NULL ) optreturnvoid;
ret = NextIns( ret );
if( ret == NULL ) optreturnvoid;
if( _Class( ret ) != OC_RET ) optreturnvoid;
JmpToRet( instr, ret );
optend
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?