cachecon.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 268 行
C
268 行
/****************************************************************************
*
* 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 "standard.h"
#include "coderep.h"
#include "opcodes.h"
#include "stackok.h"
#include "sysmacro.h"
#include "conflict.h"
#include "stackok.h"
extern type_class_def Unsigned[];
extern name *Names[];
extern block *HeadBlock;
extern name *AllocTemp(type_class_def);
extern instruction *MakeMove(name*,name*,type_class_def);
extern instruction *rDOCVT(instruction*);
extern name *TempOffset(name*,type_length,type_class_def);
extern void SuffixIns(instruction*,instruction*);
extern void PrefixIns(instruction*,instruction*);
extern name *DeAlias(name*);
extern void DoNothing(instruction*);
extern pointer InMemory(pointer);
extern bool IsStackReg(name*);
extern instruction *FoldIns(instruction*);
static block *Head;
static block *(*Next)(block*);
static int CountOps( instruction *ins, name *cons ) {
/********************************************************/
int num_operands;
switch( ins->head.opcode ) {
case OP_LSHIFT:
case OP_RSHIFT:
num_operands = 1;
break;
case OP_ADD:
case OP_SUB:
if( IsStackReg( ins->result ) ) {
num_operands = 0;
} else if( cons->c.int_value == 1 ) {
num_operands = 1;
} else {
num_operands = ins->num_operands;
}
break;
case OP_CALL:
case OP_CALL_INDIRECT:
/* operands of a call are special, and never should use CONST_TEMP's */
num_operands = 0;
break;
default:
num_operands = ins->num_operands;
break;
}
return( num_operands );
}
static type_class_def FindMaxClass( name *cons, int *prefs ) {
/******************************************************************
Run through the instructions and find the maximimum class of
all instructions in which "cons" is used.
*/
block *blk;
instruction *ins;
int i;
int class;
int num_operands;
class = -1;
*prefs = 0;
for( blk = Head; blk != NULL; blk = Next( blk ) ) {
ins = blk->ins.hd.next;
while( ins->head.opcode != OP_BLOCK ) {
num_operands = CountOps( ins, cons );
for( i = 0; i < num_operands; ++i ) {
if( ins->operands[i] == cons ) {
++*prefs;
if( (int)ins->type_class >= class ) {
class = _OpClass( ins );
}
}
}
ins = ins->head.next;
}
}
if( class == -1 ) return( XX );
// return( Unsigned[ class ] );
// why? BBB - June 28, 1995
return( class );
}
static bool ReplaceConst( name *cons,
name *temp, type_class_def tmp_class ) {
/*****************************************************************************
Replace all occurences of "cons" with "temp". As a hack, we
never replace the operands of a shift, since it's always
better to do a shift by a constant on both the 370 and x86
architectures.
*/
block *blk;
instruction *ins;
int i;
int class;
int ins_class;
bool change;
int num_operands;
tmp_class = tmp_class;
class = -1;
change = FALSE;
for( blk = Head; blk != NULL; blk = Next( blk ) ) {
ins = blk->ins.hd.next;
while( ins->head.opcode != OP_BLOCK ) {
ins_class = Unsigned[ _OpClass( ins ) ];
num_operands = CountOps( ins, cons );
for( i = 0; i < num_operands; ++i ) {
if( ins->operands[i] == cons ) {
if( ins_class == temp->n.name_class ) {
ins->operands[i] = temp;
change = TRUE;
} else {
#if !( _TARGET & _TARG_AXP ) && ( _TARG_MEMORY & _TARG_LOW_FIRST )
if( _IsIntegral(ins_class) && _IsIntegral(tmp_class) ) {
ins->operands[i] = TempOffset( temp, 0, ins_class );
change = TRUE;
}
#endif
}
}
}
ins = ins->head.next;
}
}
return( change );
}
extern void ConstToTemp( block *pre, block *head, block*(*next)(block*) ) {
/******************************************************************************
Turn constant referneces into temp references so that they can
get register allocated.
*/
name *cons;
name *temp;
type_class_def class;
int num_refs;
Head = head;
Next = next;
for( cons = Names[ N_CONSTANT ]; cons != NULL; cons = cons->n.next_name ) {
if( cons->c.const_type == CONS_TEMP_ADDR ) continue;
class = FindMaxClass( cons, &num_refs );
if( class == XX ) continue;
if( head == HeadBlock && num_refs < 2 ) continue;
temp = AllocTemp( class );
temp->t.temp_flags |= CONST_TEMP;
temp->v.symbol = cons;
if( !ReplaceConst( cons, temp, class ) ) continue;
temp->v.usage |= USE_IN_ANOTHER_BLOCK;
SuffixIns( pre->ins.hd.prev, MakeMove( cons, temp, class ) );
}
}
extern void MemConstTemp( conflict_node *conf ) {
/************************************************************
We've decided to put a CONST_TEMP into memory. Go through the
instruction list and change all occurences back into the original
constant reference. Also, do the same for any other CONST_TEMP
temporaries whose only purpose is to define this one.
*/
block *blk;
instruction *ins;
int i;
name *other;
name *temp;
instruction *folded;
temp = conf->name;
other = NULL;
for( blk = HeadBlock; blk != NULL; blk = blk->next_block ) {
ins = blk->ins.hd.next;
while( ins->head.opcode != OP_BLOCK ) {
for( i = 0; i < ins->num_operands; ++i ) {
if( ins->operands[i]->n.class != N_TEMP ) continue;
if( DeAlias( ins->operands[i] ) != temp ) continue;
ins->head.state = INS_NEEDS_WORK;
ins->operands[i] = ins->operands[i]->v.symbol;
if( ins->head.opcode == OP_CONVERT ) {
ins = rDOCVT( ins );
}
}
if( ins->result != NULL && ins->result->n.class == N_TEMP ) {
if( DeAlias( ins->result ) == temp ) {
other = ins->operands[0];
ins->head.opcode = OP_NOP;
ins->num_operands = 0;
ins->result = NULL;
DoNothing( ins );
}
}
folded = FoldIns( ins );
if( folded != NULL ) {
ins = folded;
}
ins = ins->head.next;
}
}
if( other == NULL ) return;
if( !_ConstTemp( other ) ) return;
if( other->v.conflict == NULL ) return;
for( blk = HeadBlock; blk != NULL; blk = blk->next_block ) {
ins = blk->ins.hd.next;
while( ins->head.opcode != OP_BLOCK ) {
for( i = 0; i < ins->num_operands; ++i ) {
if( ins->operands[i]->n.class != N_TEMP ) continue;
if( DeAlias( ins->operands[i] ) == other ) return;
}
ins = ins->head.next;
}
}
SafeRecurse( InMemory, other->v.conflict );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?