optimize.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 474 行 · 第 1/2 页
C
474 行
/****************************************************************************
*
* 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: Instruction reordering and dead code elimination.
*
****************************************************************************/
#include "standard.h"
#include "coderep.h"
#include "conflict.h"
#include "opcodes.h"
#include "cgdefs.h"
#include "zoiks.h"
extern block *HeadBlock;
extern conflict_node *ConfList;
extern bool PropagateMoves(void);
extern instruction_id Renumber(void);
extern bool FPIsStack(name*);
extern bool SideEffect(instruction*);
extern void FreeIns(instruction*);
extern conflict_node* FindConflictNode(name*,block*,instruction*);
extern void FreeConflicts(void);
extern void NullConflicts(var_usage);
extern void FindReferences(void);
extern void MakeConflicts(void);
extern void MakeLiveInfo(void);
extern bool ReDefinedBy(instruction*,name*);
extern void FreeJunk(block*);
typedef enum {
MOVEABLE = 0x01,
SWAPABLE = 0x02,
SIDE_EFFECT = 0x04,
PUSHABLE = 0x08
} opcode_attr;
static opcode_attr OpAttrs[LAST_OP-FIRST_OP+1] = {
/********************************
define the attributes of any given opcode
*/
FALSE, /* OP_NOP,*/
/* NOP's are always where they are for a good reason*/
/* binary operators*/
PUSHABLE, /* OP_ADD,*/
MOVEABLE, /* OP_EXT_ADD,*/
PUSHABLE, /* OP_SUB,*/
MOVEABLE, /* OP_EXT_SUB,*/
MOVEABLE + SWAPABLE, /* OP_MUL,*/
MOVEABLE + SWAPABLE, /* OP_EXT_MUL,*/
MOVEABLE + SWAPABLE, /* OP_DIV,*/
MOVEABLE + SWAPABLE, /* OP_MOD,*/
MOVEABLE + SWAPABLE, /* OP_AND,*/
MOVEABLE + SWAPABLE, /* OP_OR,*/
MOVEABLE + SWAPABLE, /* OP_XOR,*/
MOVEABLE + SWAPABLE, /* OP_RSHIFT,*/
MOVEABLE + SWAPABLE, /* OP_LSHIFT,*/
MOVEABLE + SWAPABLE, /* OP_POW */
MOVEABLE + SWAPABLE, /* OP_P5FDIV */
MOVEABLE + SWAPABLE, /* OP_ATAN2 */
MOVEABLE + SWAPABLE, /* OP_FMOD */
MOVEABLE + SWAPABLE, /* OP_NEGATE,*/
MOVEABLE + SWAPABLE, /* OP_COMPLEMENT,*/
MOVEABLE + SWAPABLE, /* OP_LOG */
MOVEABLE + SWAPABLE, /* OP_COS */
MOVEABLE + SWAPABLE, /* OP_SIN */
MOVEABLE + SWAPABLE, /* OP_TAN */
MOVEABLE + SWAPABLE, /* OP_SQRT */
MOVEABLE + SWAPABLE, /* OP_FABS */
MOVEABLE + SWAPABLE, /* OP_ACOS */
MOVEABLE + SWAPABLE, /* OP_ASIN */
MOVEABLE + SWAPABLE, /* OP_ATAN */
MOVEABLE + SWAPABLE, /* OP_COSH */
MOVEABLE + SWAPABLE, /* OP_EXP */
MOVEABLE + SWAPABLE, /* OP_LOG10 */
MOVEABLE + SWAPABLE, /* OP_SINH */
MOVEABLE + SWAPABLE, /* OP_TANH */
MOVEABLE + SWAPABLE, /* OP_PTR_TO_NATIVE */
MOVEABLE + SWAPABLE, /* OP_PTR_TO_FOREIGN */
FALSE, /* OP_SLACK */
MOVEABLE + SWAPABLE, /* OP_CONVERT,*/
MOVEABLE + SWAPABLE, /* OP_LA,*/
MOVEABLE + SWAPABLE, /* OP_CAREFUL_LA*/
MOVEABLE + SWAPABLE, /* OP_ROUND,*/
MOVEABLE + SWAPABLE, /* OP_MOV,*/
/* Calling operators*/
SIDE_EFFECT, /* OP_CALL_INDIRECT,*/
SWAPABLE, /* OP_PUSH,*/
SWAPABLE, /* OP_POP,*/
FALSE, /* OP_PARM_DEF,*/
/* Select statement operator*/
FALSE, /* OP_SELECT*/
/* Condition code setting instructions (no result, third operand is a label)*/
SIDE_EFFECT, /* OP_BIT_TEST_TRUE,*/
SIDE_EFFECT, /* OP_BIT_TEST_FALSE,*/
SIDE_EFFECT, /* OP_CMP_EQUAL,*/
SIDE_EFFECT, /* OP_CMP_NOT_EQUAL,*/
SIDE_EFFECT, /* OP_CMP_GREATER,*/
SIDE_EFFECT, /* OP_CMP_LESS_EQUAL,*/
SIDE_EFFECT, /* OP_CMP_LESS,*/
SIDE_EFFECT, /* OP_CMP_GREATER_EQUAL,*/
/* Operator whose argument is a label*/
SIDE_EFFECT, /* OP_CALL,*/
SIDE_EFFECT, /* OP_SET_EQUAL,*/
SIDE_EFFECT, /* OP_SET_NOT_EQUAL,*/
SIDE_EFFECT, /* OP_SET_GREATER,*/
SIDE_EFFECT, /* OP_SET_LESS_EQUAL,*/
SIDE_EFFECT, /* OP_SET_LESS,*/
SIDE_EFFECT, /* OP_SET_GREATER_EQUAL,*/
FALSE, /* OP_DEBUG_INFO */
FALSE, /* OP_CHEAP_NOP */
FALSE, /* OP_LOAD_UNALIGNED */
FALSE, /* OP_STORE_UNALIGNED */
FALSE, /* OP_EXTRACT_LOW */
FALSE, /* OP_EXTRACT_HIGH */
FALSE, /* OP_INSERT_LOW */
FALSE, /* OP_INSERT_HIGH */
FALSE, /* OP_MASK_LOW */
FALSE, /* OP_MASK_HIGH */
FALSE, /* OP_ZAP */
FALSE, /* OP_ZAP_NOT */
FALSE, /* OP_STK_ALLOC */
FALSE, /* OP_VA_START */
/* add opcodes here */
FALSE, /* OP_SLACK */
FALSE, /* OP_SLACK */
FALSE, /* OP_SLACK */
FALSE, /* OP_SLACK */
FALSE, /* OP_SLACK */
FALSE, /* OP_SLACK */
FALSE, /* OP_SLACK */
FALSE, /* OP_SLACK */
FALSE /* OP_BLOCK */
};
#define _IsIns( ins, attr ) ( OpAttrs[ ins->head.opcode ] & attr )
#define _IsntIns( ins, attr ) ( _IsIns( ins, attr ) == FALSE )
static bool ReDefinesOps( instruction *of, instruction *ins ) {
/******************************************************************
return true if instruction "ins" redefines any of the operands
or the result of instruction "of"
*/
int i;
i = of->num_operands;
while( --i >= 0 ) {
if( of->operands[ i ]->n.class == N_REGISTER ) return( TRUE );
if( ReDefinedBy( ins, of->operands[ i ] ) ) return( TRUE );
}
if( of->result != NULL ) {
if( of->result->n.class == N_REGISTER ) return( TRUE );
if( ReDefinedBy( ins, of->result ) ) return( TRUE );
}
return( FALSE );
}
static bool CanReorder( instruction *try, instruction *after ) {
/*******************************************************************
return try if "try" could be moved past instruction "after"
*/
if( ReDefinesOps( try, after ) ) return( FALSE );
if( ReDefinesOps( after, try ) ) return( FALSE );
return( TRUE );
}
static instruction *CanMoveAfter( instruction *ins ) {
/**********************************************************
Decide whether we can/should push down instruction "ins". If we can,
return a pointer to the instruction we could put it after.
*/
instruction *next;
if( _IsntIns( ins, PUSHABLE ) ) return( NULL );
if( ins->operands[ 0 ] != ins->result ) return( NULL );
if( ins->operands[ 1 ]->n.class != N_CONSTANT ) return( NULL );
if( _IsFloating( ins->type_class ) ) return( NULL );
if( _IsFloating( ins->base_type_class ) ) return( NULL );
next = ins->head.next;
for(;;) {
if( _IsntIns( next, SWAPABLE ) ) break;
if( CanReorder( ins, next ) == FALSE ) break;
next = next->head.next;
if( next == NULL ) break;
}
if( next == ins->head.next ) return( NULL );
return( next );
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?