⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 regalloc.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/****************************************************************************
*
*                            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:  Register allocator.
*
****************************************************************************/


#include "standard.h"
#include "coderep.h"
#include "opcodes.h"
#include "conflict.h"
#include "regset.h"
#include "pattern.h"
#include "procdef.h"
#include "hostsys.h"
#include "zoiks.h"
#include "model.h"

enum allocation_state {
    ALLOC_DONE,
    ALLOC_BITS,
    ALLOC_CONST_TEMP
};

extern  bool            SideEffect(instruction*);
extern  void            NowDead(name*,conflict_node*,name_set*,block*);
extern  void            PrefixIns(instruction*,instruction*);
extern  void            BurnRegTree(reg_tree*);
extern  void            IMBlip(void);
extern  conflict_node   *NameConflict(instruction*,name*);
extern  void            BuildNameTree(conflict_node*);
extern  void            AxeDeadCode(void);
extern  void            BurnNameTree(reg_tree*);
extern  bool            WorthProlog(conflict_node*,hw_reg_set);
extern  instruction     *MakeMove(name*,name*,type_class_def);
extern  void            DoNothing(instruction*);
extern  int             ExpandOps(bool);
extern  void            FindReferences(void);
extern  void            NowAlive(name*,conflict_node*,name_set*,block*);
extern  name            *DeAlias(name*);
extern  void            BuildRegTree(conflict_node*);
extern  void            FreeAConflict(conflict_node*);
extern  bool            IsIndexReg(hw_reg_set,type_class_def,bool);
extern  void            LiveInfoUpdate(void);
extern  void            MakeLiveInfo(void);
extern  void            FreeConflicts(void);
extern  reg_set_index   SegIndex(void);
extern  void            DelSegOp(instruction*,int);
extern  void            FixChoices(void);
extern  void            DelSegRes(instruction*);
extern  void            MakeConflicts(void);
extern  void            AddSegment(instruction*);
extern  void            SuffixIns(instruction*,instruction*);
extern  name            *ScaleIndex(name*,name*,type_length,type_class_def,type_length,int,i_flags);
extern  void            FixGenEntry(instruction*);
extern  int             NumOperands(instruction*);
extern  void            CalcSavings(conflict_node*);
extern  hw_reg_set      LowOffsetReg(hw_reg_set);
extern  name            *AllocRegName(hw_reg_set);
extern  bool            PropagateMoves(void);
extern  bool            PropRegsOne(void);
extern  conflict_node   *FindConflictNode(name*,block*,instruction*);
extern  hw_reg_set      HighOffsetReg(hw_reg_set);
extern  void            DeadInstructions(void);
extern  void            GRBlip(void);
extern  bool            IsSegReg(hw_reg_set);
extern  void            *SortList(void *,unsigned,bool (*)(void*,void*) );
extern  bool            MoreConflicts(void);
extern  void            DBAllocReg(name*,name*);
extern  void            MemConstTemp(conflict_node*);
extern  void            ConstSavings(void);
extern  void            RegInsDead(void);
extern  instruction     *FoldIns( instruction * );
extern  bool            IsUncacheableMemory( name * );
extern  hw_reg_set      MustSaveRegs(void);

extern  proc_def         *CurrProc;
extern  conflict_node    *ConfList;
extern  op_regs          RegList[];
extern  hw_reg_set       *RegSets[];
extern  hw_reg_set       GivenRegisters;
extern  name             *Names[];
extern  bool             BlockByBlock;
extern  bool             HaveLiveInfo;
extern  block           *HeadBlock;




static  bool    ContainedIn( name *name1, name *name2 ) {
/********************************************************
    Returns true if name1 is completely contained within the location
    occupied by name2
*/

    if( name1->n.class != name2->n.class ) return( FALSE );
    if( name1->n.class == N_TEMP ) {
        if( DeAlias( name1 ) != DeAlias( name2 ) ) return( FALSE );
    } else if( name1->n.class == N_MEMORY ) {
        if( name1 != name2 ) return( FALSE );
    } else {
        return( FALSE );
    }
    if( name1->v.offset < name2->v.offset ) return( FALSE );
    if( name1->v.offset + name1->n.size > name2->v.offset + name2->n.size )
        return( FALSE );
    return( TRUE );
}


static  hw_reg_set      SearchTree( reg_tree *tree,
                                    name *opnd, hw_reg_set reg ) {
/*****************************************************************
    Given a register "reg", and a reg_tree "tree", return the
    appropriate piece of "reg" to be associated with name "opnd".
*/

    if( tree->offset == opnd->v.offset && tree->size == opnd->n.size ) {
        return( reg );
    }
    if( opnd->v.offset < tree->offset + ( tree->size / 2 ) ) {
        return( SearchTree( tree->lo, opnd, LowOffsetReg( reg ) ) );
    } else {
        return( SearchTree( tree->hi, opnd, HighOffsetReg( reg ) ) );
    }
}


static  name    *FindReg( reg_tree *tree, name *opnd, name *reg ) {
/******************************************************************
    see SearchTree
*/

    return( AllocRegName( SearchTree( tree, opnd, reg->r.reg ) ) );
}


static  name    *ReplIndex( instruction *ins,
                            reg_tree *tree, name *x, name *reg ) {
/*****************************************************************
    Replace the index field of "x" with register "reg" in instruction "ins".
*/

    name        *new_x;

    ins->t.index_needs = RL_;
    reg = FindReg( tree, x->i.index, reg );
    new_x = ScaleIndex(reg, x->i.base, x->i.constant,
                        x->n.name_class, x->n.size, x->i.scale,
                        x->i.index_flags );
    return( new_x );
}


static  void    AssignMoreBits( void )
/*************************************
    Run through the list of conflicts and turn off the CONFLICT_ON_HOLD
    bit.  This is on for conflicts that needed an id bit but didn't get
    one.  MoreConflicts will assign a bit to any of these that weren't
    allocated the first time around.
*/
{
    conflict_node       *conf;

    conf = ConfList;
    while( conf != NULL ) {
        conf->state &= ~CONFLICT_ON_HOLD;
        conf = conf->next_conflict;
    }
    if( MoreConflicts() ) {
        MakeLiveInfo();
        AxeDeadCode();
    } else {
        LiveInfoUpdate();
    }
}


static  void    InitAChoice( name *temp ) {
/*****************************************/

    name        *alias;

    if( temp->n.class != N_TEMP ) return;
    if( temp->t.temp_flags & ALIAS ) return;
    alias = temp;
    do {
        alias->t.possible = RL_NUMBER_OF_SETS;
        alias = alias->t.alias;
    } while( alias != temp );
}


static  void    InitChoices( void )
/**********************************
    Set the possible register choices of all conflicts/temps to be
    RL_NUMBER_OF_SETS meaning there are no restrictions as yet.  This
    choice gets more restricted as each instruction involving the
    conflict is expanded.
*/
{
    conflict_node       *conf;
    name                *opnd;
    block               *blk;
    instruction         *ins;
    int                 i;

    conf = ConfList;
    while( conf != NULL ) {
        conf->possible = RL_NUMBER_OF_SETS;
        conf = conf->next_conflict;
    }
    if( BlockByBlock ) {
        /* this is WAY faster for BlockByBlock */
        blk = HeadBlock;
        while( blk != NULL ) {
            ins = blk->ins.hd.next;
            while( ins->head.opcode != OP_BLOCK ) {
                i = ins->num_operands;
                while( --i >= 0 ) {
                    InitAChoice( ins->operands[i] );
                }
                if( ins->result != NULL ) {
                    InitAChoice( ins->result );
                }
                ins = ins->head.next;
            }
            blk = blk->next_block;
        }
    } else {
        opnd = Names[ N_TEMP ];
        while( opnd != NULL ) {
            opnd->t.possible = RL_NUMBER_OF_SETS;
            opnd = opnd->n.next_name;
        }
    }
}


static  void    ReAlias( reg_tree *tree ) {
/******************************************
    Given a name tree, turn all temporaries into MASTER (not ALIAS)
    temporaries if their ancestor in the tree has no restrictions on
    which register it can have.  This effectively detaches the hi and lo
    part of a temporary so they may be treated separately during
    register allocation.
*/

    name        *curr;
    name        *new_ring;
    name        **owner;
    type_length endpoint;
    type_length begpoint;

    if( tree != NULL ) {
        if( tree->idx == RL_NUMBER_OF_SETS ) {
            ReAlias( tree->lo );
            ReAlias( tree->hi );
        } else {
            begpoint = tree->offset;
            endpoint = tree->size + begpoint;
            owner = &tree->temp->t.alias;
            new_ring = NULL;
            for(;;) {
                curr = *owner;
                if( curr->v.offset < begpoint
                 || curr->v.offset + curr->n.size > endpoint ) {
                    owner = &curr->t.alias;
                } else {
                    *owner = curr->t.alias;
                    if( new_ring == NULL ) {
                        new_ring = curr;
                        new_ring->t.alias = new_ring;
                    } else {
                        curr->t.alias = new_ring->t.alias;
                        new_ring->t.alias = curr;
                    }
                }
                if( curr == tree->temp ) break;
            }
            curr->t.temp_flags &= ~ALIAS;
        }
    }
}


static  bool    SplitConflicts( void )
/*************************************
    Build a name tree for each conflict, and then if the top of the tree
    has no restrictions on which registers it can have, its name mustn't
    be referenced by any instructions, so we call ReAlias to split make
    the high and low part their own "MASTER" rather than aliases of the
    temporary for the top of the tree.  See REGTREE.C for info re: name
    trees.

*/
{
    conflict_node       *conf;
    bool                change;

    change = FALSE;
    conf = ConfList;
    while( conf != NULL ) {
        BuildNameTree( conf );
        if( conf->tree != NULL
         && conf->tree->idx == RL_NUMBER_OF_SETS ) {
            change = TRUE;
            ReAlias( conf->tree );
            if( conf->tree->temp != NULL ) {
                conf->tree->temp->v.usage |= USE_MEMORY;
            }
            if( conf->tree->alt != NULL ) {
                conf->tree->alt->v.usage |= USE_MEMORY;
            }
        }
        BurnNameTree( conf->tree );
        conf->tree = NULL;
        conf = conf->next_conflict;
    }
    return( change );
}


extern  void    NullConflicts( var_usage off ) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -