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