peepopt.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 664 行 · 第 1/2 页
C
664 行
/****************************************************************************
*
* 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: Perform peephole optimizations.
*
****************************************************************************/
/* - collapse adjacent BIT operations (AND,OR) */
/* - collapse adjacent integral ADD,SUB operations */
/* - collapse adjacent integral MUL operations */
#include "standard.h"
#include "coderep.h"
#include "indvars.h"
#include "opcodes.h"
#include "procdef.h"
#include "typedef.h"
#include "pattern.h"
#include "score.h"
#include "zoiks.h"
extern name *AllocS32Const(signed_32);
extern void FreeIns(instruction*);
extern bool IsVolatile(name*);
extern bool InsOrderDependant(instruction*,instruction*);
extern bool ReDefinedBy( instruction *, name * );
extern bool SameThing( name *, name * );
extern bool SideEffect( instruction * );
extern bool ChangeIns(instruction *,name *,name **,change_type);
extern opcode_entry *ResetGenEntry( instruction *ins );
extern bool VisibleToCall(instruction*,name*,bool);
extern bool VolatileIns(instruction*);
extern block *HeadBlock;
extern type_length TypeClassSize[];
#define OP2VAL( ins ) ( (ins)->operands[1]->c.int_value )
typedef bool (ONE_OP)(instruction *,instruction *);
typedef bool (TWO_OP)(instruction *,instruction *);
typedef bool (THREE_OP)(instruction *,instruction *);
static bool AfterRegAlloc;
static bool InsChangeable( instruction *ins, name *new_op, name **op )
/************************************************************************/
{
if( AfterRegAlloc ) {
return( ChangeIns( ins, new_op, op, CHANGE_GEN | CHANGE_CHECK ) );
}
return( TRUE );
}
static void InsReset( instruction *ins ) {
/********************************************/
if( AfterRegAlloc ) {
ResetGenEntry( ins );
}
}
static bool MergeTwo( instruction *a, instruction *b, signed_32 value )
/*************************************************************************/
{
name *cons;
name *old_res_a;
name *old_res_b;
cons = AllocS32Const( value );
if( a->result == b->result ) {
/* A op X -> A A op f(X,Y) -> A */
/* A op Y -> A */
if( InsChangeable( a, cons, &a->operands[ 1 ] ) ) {
a->operands[ 1 ] = cons;
ResetGenEntry( a );
FreeIns( b );
return( TRUE );
}
} else if( a->operands[ 0 ] == b->operands[ 0 ] ) {
/* A op X -> A A op f(X,Y) -> B */
/* A op Y -> B A op X -> A */
/* becomes */
/* This could be bad if we had something like
A op X -> A
USE( B )
A op Y -> B
which can occur quite frequently after register allocation,
so we make sure all instructions between a and b are
InsOrderDependant with b. BBB - Apr 27, 1994
*/
instruction *ins;
for( ins = a->head.next; ins != b; ins = ins->head.next ) {
if( InsOrderDependant( ins, b ) ) return( FALSE );
if( ins->head.opcode == OP_BLOCK ) {
Zoiks( ZOIKS_111 );
}
}
if( InsChangeable( a, b->result, &a->result ) &&
InsChangeable( b, a->operands[ 0 ], &b->result ) ) {
old_res_a = a->result;
old_res_b = b->result;
a->result = b->result;
b->result = a->operands[0];
if( InsChangeable( a, cons, &a->operands[ 1 ] ) &&
InsChangeable( b, a->operands[ 1 ], &b->operands[ 1 ] ) ) {
b->operands[ 1 ] = a->operands[ 1 ];
a->operands[ 1 ] = cons;
ResetGenEntry( a );
ResetGenEntry( b );
return( TRUE );
} else {
/* retreat! retreat! */
a->result = old_res_a;
b->result = old_res_b;
}
}
} else if( b->operands[ 0 ] != a->operands[0] || b->operands[1] != cons ) {
/* A op X -> B A op X -> B */
/* B op Y -> C A op f(X,Y) -> C */
if( InsChangeable( b, a->operands[ 0 ], &b->operands[ 0 ] ) &&
InsChangeable( b, cons, &b->operands[ 1 ] ) ) {
b->operands[ 0 ] = a->operands[ 0 ];
b->operands[ 1 ] = cons;
ResetGenEntry( b );
return( TRUE );
}
}
return( FALSE );
}
static ONE_OP DoAdd;
static bool DoAdd( instruction *a, instruction *b )
/*******************************************************/
{
return( MergeTwo( a, b, OP2VAL( a ) + OP2VAL( b ) ) );
}
static ONE_OP DoMul;
static bool DoMul( instruction *a, instruction *b )
/*******************************************************/
{
return( MergeTwo( a,b, OP2VAL( a ) * OP2VAL( b ) ) );
}
static ONE_OP DoAnd;
static bool DoAnd( instruction *a, instruction *b )
/**************************************************************/
{
return( MergeTwo( a,b, OP2VAL( a ) & OP2VAL( b ) ) );
}
static ONE_OP DoOr;
static bool DoOr( instruction *a, instruction *b )
/*******************************************************/
{
return( MergeTwo( a,b, OP2VAL( a ) | OP2VAL( b ) ) );
}
static TWO_OP AndOr;
static bool AndOr( instruction *and_ins, instruction *or_ins )
/************************************************************/
{
signed_32 new_and;
name *mask;
if( and_ins->operands[ 0 ] != and_ins->result ) return( FALSE );
if( or_ins->operands[ 0 ] != or_ins->result ) return( FALSE );
new_and = OP2VAL( and_ins ) & ~OP2VAL( or_ins );
if( new_and == OP2VAL( and_ins ) ) return( FALSE );
mask = AllocS32Const( new_and );
if( !InsChangeable( and_ins, mask, &and_ins->operands[ 1 ] ) ) return( FALSE );
and_ins->operands[ 1 ] = mask;
InsReset( and_ins );
return( TRUE );
}
static TWO_OP OrAnd;
static bool OrAnd( instruction *or_ins, instruction *and_ins )
/************************************************************/
{
signed_32 new_or;
signed_32 or;
signed_32 and;
name *mask;
if( or_ins->operands[ 0 ] != or_ins->result ) return( FALSE );
if( and_ins->operands[ 0 ] != and_ins->result ) return( FALSE );
or = OP2VAL( or_ins );
and = OP2VAL( and_ins );
if( ( and & or ) == and ) { // the AND bits are a subset of the OR bits
or_ins->operands[ 0 ] = AllocS32Const( and );
or_ins->num_operands = 1;
or_ins->head.opcode = OP_MOV;
or_ins->table = NULL;
InsReset( or_ins );
FreeIns( and_ins );
return( TRUE );
} else {
new_or = or & and;
if( new_or == OP2VAL( or_ins ) ) return( FALSE );
mask = AllocS32Const( new_or );
if( !InsChangeable( or_ins, mask, &or_ins->operands[ 1 ] ) ) return( FALSE );
or_ins->operands[ 1 ] = mask;
InsReset( or_ins );
return( TRUE );
}
}
static THREE_OP OrAndOr;
static bool OrAndOr( instruction *a, instruction *b )
/***************************************************/
{
signed_32 and_val;
name *mask;
if( a->result != b->result ) return( FALSE );
a->head.opcode = OP_AND;
b->head.opcode = OP_OR;
and_val = OP2VAL( a ) & OP2VAL( b );
mask = AllocS32Const( and_val );
if( InsChangeable( a, b->operands[ 1 ], &a->operands[ 1 ] ) &&
InsChangeable( b, mask, &b->operands[ 1 ] ) ) {
a->operands[ 1 ] = b->operands[ 1 ];
b->operands[ 1 ] = mask;
a->table = b->table = NULL;
InsReset( a );
InsReset( b );
return( TRUE );
}
/* Put things back the way they were */
a->head.opcode = OP_OR;
b->head.opcode = OP_AND;
return( FALSE );
}
static THREE_OP AndOrAnd;
static bool AndOrAnd( instruction *a, instruction *b )
/****************************************************/
{
signed_32 or_val;
name *mask;
if( a->result != b->result ) return( FALSE );
a->head.opcode = OP_OR;
b->head.opcode = OP_AND;
or_val = OP2VAL( a ) | OP2VAL( b );
mask = AllocS32Const( or_val );
if( InsChangeable( a, b->operands[ 1 ], &a->operands[ 1 ] ) &&
InsChangeable( b, mask, &b->operands[ 1 ] ) ) {
a->operands[ 1 ] = b->operands[ 1 ];
b->operands[ 1 ] = mask;
a->table = b->table = NULL;
InsReset( a );
InsReset( b );
return( TRUE );
}
/* Put things back the way they were */
a->head.opcode = OP_AND;
b->head.opcode = OP_OR;
return( FALSE );
}
static bool DoRShift( instruction *a, instruction *b )
/*******************************************************/
{
if( a->type_class != b->type_class ) return( FALSE );
return( DoAdd( a, b ) );
}
static bool DoLShift( instruction *a, instruction *b )
/********************************************************/
{
return( DoAdd( a, b ) );
}
static TWO_OP LRShift;
static bool LRShift( instruction *a, instruction *b )
/*************************************************/
{
a=a;b=b;
return( FALSE );
}
static TWO_OP RLShift;
static bool RLShift( instruction *a, instruction *b )
/*************************************************/
{
a=a;b=b;
return( FALSE );
}
static THREE_OP Nop3;
static bool Nop3( instruction *a, instruction *b )
/****************************************************/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?