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 + -
显示快捷键?