示例#1
0
static  bool  ZapsMemory( name *result, name *op, bool for_index ) {
/*********************************************************************
    Could redefining "result" redefine N_MEMORY name "op"?
*/

    switch( result->n.class ) {
    case N_TEMP:
        return( false );
    case N_MEMORY:
        if( result->v.symbol != op->v.symbol )
            return( false );
        /* can be used for memory ops as well */
        if( for_index )
            return( true );
        return( TempsOverlap( result, op ) );
    case N_INDEXED:
        if( result->i.base == NULL ) {
            if( _IsModel( FORTRAN_ALIASING ) )
                return( false );
            if( op->v.usage & USE_ADDRESS )
                return( true );
            return( _IsntModel( RELAX_ALIAS ) );
        }
        if( result->i.base->n.class == N_TEMP ) {
            return( _IsntModel( RELAX_ALIAS ) );
        } else { /* it must be N_MEMORY*/
            return( ZapsMemory( result->i.base, op, true ) );
        }
    case N_REGISTER:
        return( false );
    default:
        _Zoiks( ZOIKS_023 );
        return( false );
    }
示例#2
0
static  void            PreOptimize( void )
/*****************************************/
{
    bool        change;

    if( _IsntModel( NO_OPTIMIZATION ) ) {
//      CharsAndShortsToInts();
        MakeMovAddrConsts();
        PushPostOps();
        DeadTemps();
        InsDead();
        MakeFlowGraph();
        BlockTrim();
        CommonSex( _IsModel( LOOP_OPTIMIZATION ) );
        SetOnCondition();
        BlockTrim();
        AddANop();
        if( _IsModel( LOOP_OPTIMIZATION ) ) {
            change = FALSE;
            if( TransLoops( FALSE ) ) {
                change = TRUE;
            }
            if( LoopInvariant() ) {
                change = TRUE;
            }
            if( change ) {
                CommonSex(TRUE);
                InsDead();
                CommonInvariant();
            }
            if( IndVars() ) {
                CommonSex(FALSE);
                InsDead();
                change = TRUE;
            }
            BlockTrim();
            if( TransLoops( TRUE ) ) {
                BlockTrim();
                CommonSex( FALSE );
                change = TRUE;
            }
            if( change ) {
                ReConstFold();
            }
            LoopEnregister();
            if( change ) {
                BlockTrim();
            }
        }
        MulToShiftAdd();
        KillMovAddrConsts();
        FindReferences();
    } else {
        MakeFlowGraph();
        AddANop();
        FindReferences();
    }
}
示例#3
0
static  bool    FlushSomeOpt( pointer_int size )
/**********************************************/
{
    seg_id      old;
    bool        freed;

    if( InOptimizer == 0 && HaveCodeSeg() ) {
        old = SetOP( AskCodeSeg() );
        freed = ShrinkQueue( size );
        SetOP( old );
        if( _IsntModel( NO_OPTIMIZATION ) && IckyWicky == FALSE ) {
            IckyWicky = TRUE;
            FEMessage( MSG_PEEPHOLE_FLUSHED, NULL );
        }
    } else {
        freed = FALSE;
    }
    return( freed );
}
示例#4
0
static  void    BlockToCode( bool partly_done )
/*********************************************/
{
    block_num           inputs;
    block_num           targets;
    block_edge          *input_edges;
    conflict_node       *curr;
    conflict_node       **owner;
    conflict_node       *conflist;
    block_num           id;



    /* try to get back some memory*/
    _MemLow;

    /* make the block look like an entire procedure*/

    HeadBlock = CurrBlock;
    BlockList = CurrBlock;
    HeadBlock->prev_block = NULL;
    if( HeadBlock->next_block != NULL ) {
        HeadBlock->next_block->prev_block = NULL;
    }
    /* Kludge - need a pointer to the next block for CALL_LABEL - puke! */
    if( HeadBlock->class & CALL_LABEL ) {
        HeadBlock->v.next = HeadBlock->next_block;
    }
    HeadBlock->next_block = NULL;

    /* force anything that spans blocks to memory */

    HeadBlock->u.partition = HeadBlock;
    ConstFold( HeadBlock );
    HeadBlock->u.partition = NULL;

    ForceTempsMemory();
    if( partly_done == FALSE ) {
        FixMemRefs();
        HaveLiveInfo = FALSE;
        if( _IsntModel( NO_OPTIMIZATION | FORTRAN_ALIASING ) ) {
            FindReferences();
            CommonSex(FALSE);
            PushPostOps();
        }
        FindReferences();
        DeadTemps();
        if( _IsModel( NO_OPTIMIZATION ) ) {
            SetInOut( HeadBlock );
        } else {
            MakeConflicts();
        }
        MakeLiveInfo();
        HaveLiveInfo = TRUE;
        AxeDeadCode();
        FixIndex();
        FixSegments();
        FPRegAlloc();
        RegAlloc( TRUE );
        FreeConflicts();
        HaveLiveInfo = FALSE;
    } else {
        conflist = NULL;
        owner = &ConfList;
        for( ;; ) {
            curr = *owner;
            if( curr == NULL ) break;
            if( curr->start_block == HeadBlock ) {
                *owner = curr->next_conflict;
                curr->next_conflict = conflist;
                conflist = curr;
            } else {
                owner = &curr->next_conflict;
            }
        }
        curr = ConfList;
        ConfList = conflist;
        RegAlloc( TRUE );
        FreeConflicts();
        ConfList = curr;
    }
    input_edges = HeadBlock->input_edges;
    inputs = HeadBlock->inputs;
    targets = HeadBlock->targets;
    HeadBlock->inputs = 0;
    HeadBlock->input_edges = NULL;
    HeadBlock->targets = 0;
    FPParms();
    PostOptimize();
    HeadBlock->input_edges = input_edges;
    HeadBlock->inputs = inputs;
    HeadBlock->targets = targets;

    /* generate a prolog that saves all registers*/

    if( ( CurrProc->prolog_state & GENERATED_PROLOG ) == 0 ) {
        CurrProc->state.used = AllCacheRegs();
        GenProlog();
    }

    id = CurrBlock->id;
    AssgnMoreTemps( id );
    OptSegs();

    /* generate the code for the block*/

    if( CurrBlock->class & RETURN ) {
        GenObject();
        FiniStackMap();
        FreeProc();
    } else {
示例#5
0
static  void            PostOptimize( void )
/******************************************/
{
    if( _IsntModel( NO_OPTIMIZATION ) ) {
        // Run peephole optimizer again. Important: It is critical that the
        // new instructions can be directly generated because RegAlloc is
        // done by now. PeepOpt() is responsible for verifying that.
        if( PeepOpt( HeadBlock, NextBlock, NULL, TRUE ) ) {
            LiveInfoUpdate();
        }
        // this is important as BuildIndex cannot handle instructions with no operands
        DeadInstructions();
        BuildIndex();
        DeadInstructions();
    }
    MergeIndex();
    if( _IsntModel( NO_OPTIMIZATION ) ) {
    #if !(_TARGET & _TARG_RISC)
        //
        // Calling Conditions() at this point has nice optimization effect,
        // but doesn't working correctly right now. It optimizes conditions
        // making them dependent from previous conditions codes, but riscifier
        // generates XOR's which will trash cond. codes. Either Conditions()
        // either riscifier must be fixed to handle this situation.
        //
    #if 0
        // Get rid of unused conditions on variables level
        // to decrease number of referenced vars in LdStAlloc() and Score()
        if( _IsntTargetModel( STATEMENT_COUNTING ) ) {
            Conditions();
            DeadInstructions(); // cleanup junk after Conditions()
        }
    #endif
    #endif
        // OptCloseMoves();  // todo: merge constant moves before riscifier
        LdStAlloc();
        Score();
        DeadInstructions(); // cleanup junk after Score()
        // deRISCify before LoopRegInvariant() or Shedule() are run:
        // they're moving RISCified pair.
        LdStCompress();
        // Reuse registers freed by deriscifier
        Score();
        DeadInstructions(); // cleanup junk after Score()
        if( !BlockByBlock ) LoopRegInvariant();
    #if !(_TARGET & _TARG_RISC)
        // Get rid of remaining unused conditions on register level.
        if( _IsntTargetModel( STATEMENT_COUNTING ) ) {
            Conditions();
        }
    #endif
    }
    FPExpand();
    if( _IsntModel( NO_OPTIMIZATION ) ) {
        DeadInstructions();   // cleanup junk after Conditions()
        // Run scheduler last, when all instructions are stable
        if( _IsModel( INS_SCHEDULING ) ) {
            HaveLiveInfo = FALSE;
            Schedule(); /* NOTE: Schedule messes up live information */
            LiveInfoUpdate();
            HaveLiveInfo = TRUE;
        }
        // run this again in case Scheduler messed around with indices
        if( PeepOpt( HeadBlock, NextBlock, NULL, TRUE ) ) {
            LiveInfoUpdate();
        }
    }
    FPOptimize();
}
示例#6
0
void FlowSave( hw_reg_set *preg )
/*******************************/
{
    int                 score;
    int                 i, j;
    int                 best;
    int                 num_blocks;
    int                 num_regs;
    int                 curr_reg;
    hw_reg_set          *curr_push;
    reg_flow_info       *reg_info;
    block               *save;
    block               *restore;
    instruction         *ins;
    type_class_def      reg_type;

    HW_CAsgn( flowedRegs, HW_EMPTY );
    if( _IsntModel( FLOW_REG_SAVES ) ) return;
    if( !HaveDominatorInfo ) return;
    // we can't do this if we have push's which are 'live' at the end of a block
    // - this flag is set when we see a push being generated for a call in a different
    //   block
#if _TARGET & _TARG_INTEL
    if( CurrProc->targ.never_sp_frame ) return;
#endif
    num_regs = CountRegs( *preg );
    if( num_regs == 0 ) return;
    reg_info = CGAlloc( num_regs * sizeof( reg_flow_info ) );
    num_blocks = CountBlocks();
    InitBlockArray();
    curr_push = PushRegs;
    for( curr_reg = 0; curr_reg < num_regs; curr_reg++ ) {
        while( !HW_Ovlap( *curr_push, *preg ) ) curr_push++;
        HW_Asgn( reg_info[curr_reg].reg, *curr_push );
        reg_info[curr_reg].save = NULL;
        reg_info[curr_reg].restore = NULL;
    #if _TARGET & _TARG_INTEL
        if( HW_COvlap( *curr_push, HW_BP ) ) continue;  // don't mess with BP - it's magical
    #endif
        GetRegUsage( &reg_info[curr_reg] );
        best = 0;
        for( i = 0; i < num_blocks; i++ ) {
            for( j = 0; j < num_blocks; j++ ) {
                if( PairOk( blockArray[i], blockArray[j], &reg_info[0], curr_reg ) ) {
                    // we use the number of blocks dominated by the save block plus
                    // the number of blocks post-dominated by the restore block as a
                    // rough metric for determining how much we like a given (valid)
                    // pair of blocks - the more blocks dominated, the further 'in'
                    // we have pushed the save, which should be good
                    score =  CountDomBits( &blockArray[i]->dom.dominator );
                    score += CountDomBits( &blockArray[j]->dom.post_dominator );
                    if( score > best ) {
                        best = score;
                        reg_info[curr_reg].save    = blockArray[i];
                        reg_info[curr_reg].restore = blockArray[j];
                    }
                }
            }
        }
        // so now we know where we are going to save and restore the register
        // emit the instructions to do so, and remove reg from the set to push
        // in the normal prolog sequence
        save = reg_info[curr_reg].save;
        restore = reg_info[curr_reg].restore;
        if( ( save != NULL && save != HeadBlock ) && ( restore != NULL && !_IsBlkAttr( restore, BLK_RETURN ) ) ) {
            reg_type = WD;
        #if _TARGET & _TARG_INTEL
            if( IsSegReg( reg_info[curr_reg].reg ) ) {
                reg_type = U2;
            }
        #endif
            ins = MakeUnary( OP_PUSH, AllocRegName( reg_info[curr_reg].reg ), NULL, reg_type );
            ResetGenEntry( ins );
            PrefixIns( save->ins.hd.next, ins );
            ins = MakeUnary( OP_POP, NULL, AllocRegName( reg_info[curr_reg].reg ), reg_type );
            ins->num_operands = 0;
            ResetGenEntry( ins );
            SuffixIns( restore->ins.hd.prev, ins );
            HW_TurnOff( *preg, reg_info[curr_reg].reg );
            HW_TurnOn( flowedRegs, reg_info[curr_reg].reg );
            FixStackDepth( save, restore );
        }
        curr_push++;
    }
    CGFree( reg_info );
}
示例#7
0
extern  void    DFObjInitDbgInfo( void ) {
/*****************************************************/
/* called by objinit to init segments and dwarf writing library */
    static const dw_funcs cli_funcs = {
        CLIReloc,
        CLIWrite,
        CLISeek,
        CLITell,
        CLIAlloc,
        CLIFree
    };
    dw_init_info    info;
    cg_sym_handle   abbrev_sym;
    cg_sym_handle   debug_pch;
    fe_attr         attr;

    if( _IsntModel( DBG_LOCALS | DBG_TYPES ) ){
        return;
    }
    info.compiler_options = DW_CM_DEBUGGER;
    info.abbrev_sym = 0;
    info.producer_name = SetDwarfProducer();
    info.language = SetLang();
    if( setjmp( info.exception_handler ) == 0 ) {
        info.funcs = cli_funcs;
        InitSegBck(); // start each seg with a ref label
        if( _IsModel( DBG_PREDEF ) ) {
            abbrev_sym = FEAuxInfo( NULL, DBG_PREDEF_SYM );
            info.abbrev_sym = (dw_sym_handle)abbrev_sym;
            attr = FEAttr( abbrev_sym );
            if( (attr & FE_IMPORT) ) {
                info.compiler_options |= DW_CM_ABBREV_PRE;
            }else{
                back_handle bck;
                segment_id  old;

                info.compiler_options |= DW_CM_ABBREV_GEN;
                bck = FEBack( abbrev_sym ); // dump out export label
                bck->seg = DwarfSegs[DW_DEBUG_ABBREV].seg;
                old = SetOP( DwarfSegs[DW_DEBUG_ABBREV].seg );
                DataLabel( bck->lbl );
                SetOP( old );
            }
        }
        debug_pch = FEAuxInfo( NULL, DBG_PCH_SYM );
        if( debug_pch != NULL ){
            attr = FEAttr( debug_pch );
            if( !(attr & FE_IMPORT) ) {
                back_handle bck;
                segment_id  old;

                bck = FEBack( debug_pch );
                bck->seg = DwarfSegs[DW_DEBUG_INFO].seg;
                old = SetOP( DwarfSegs[DW_DEBUG_INFO].seg );
                DataLabel( bck->lbl );
                SetOP( old );
                debug_pch = NULL;
            }
        }
        Client = DWInit( &info );
        if( Client == NULL ) {
            Zoiks( ZOIKS_107 ); /* Bad */
        }
        DFBegCCU( AskCodeSeg(), (dw_sym_handle)debug_pch );
    } else {
        Zoiks( ZOIKS_107 ); /* Big Error */
    }
}
示例#8
0
extern  void    DFBegCCU( segment_id code, dw_sym_handle dbg_pch )
/****************************************************************/
// Call when codeseg hase been defined
{
    dw_cu_info      cu;
    back_handle     bck;
    segment_id      old;
    type_def        *tipe_addr;

    if( _IsntModel( DBG_LOCALS | DBG_TYPES ) ) {
        return;
    }
    if( CcuDef ) {
        cu.source_filename = FEAuxInfo( NULL, SOURCE_NAME );
        cu.directory = "";
        cu.dbg_pch = dbg_pch;
        cu.inc_list = NULL;
        cu.inc_list_len = 0;
        old = SetOP( code );
#if _TARGET & ( _TARG_IAPX86 | _TARG_80386 )
        if( _IsTargetModel( FLAT_MODEL ) ) {
            bck = MakeLabel();
            OutLabel( bck->lbl );
            Pc_Low = bck;
            Pc_High = MakeLabel();
            // Emitting DW_AT_low_pc and DW_AT_high_pc is valid *only* if the
            // compilation unit's code is in a single contiguous block (see
            // DWARF 2, section 3.1).
            // I don't know how to find out at the time of this call if there's
            // only one code segment or not, hence these attributes are always
            // disabled. The low/high pc attribs should probably be handled by
            // the linker.
            cu.flags = false;
            cu.segment_size = 0;
        } else {
            bck = NULL;
            cu.flags = false;
            Pc_Low = NULL;
            Pc_High = NULL;
            cu.segment_size = 2;
        }
#else
        bck = MakeLabel();
        OutLabel( bck->lbl );
        Pc_Low = bck;
        Pc_High = MakeLabel();
        cu.flags = true;
        cu.segment_size = 0;
#endif
        SetOP( old );
        Comp_High = Pc_High;
        tipe_addr = TypeAddress( TY_NEAR_POINTER );
        cu.offset_size = tipe_addr->length;
        switch( GetMemModel() ) {
            case 'h':
                cu.model = DW_MODEL_HUGE;
                break;
            case 'l':
                cu.model = DW_MODEL_LARGE;
                break;
            case 'f':
                cu.model = DW_MODEL_FLAT;
                break;
            case 's':
                cu.model = DW_MODEL_SMALL;
                break;
            default:
                cu.model = DW_MODEL_NONE;
                break;
        }
        DWBeginCompileUnit( Client, &cu );
        if( cu.flags ) {
            BEFreeBack( bck );
        }
    } else {
        CcuDef = true;
    }
}
示例#9
0
extern  bool            CreateBreak( void )
/*****************************************/
{
    block       *blk;
    block       *break_blk;
    block       *back_break_blk;
    block       *exit_blk;
    block_edge  *edge;
    block_edge  *next_edge;
    block_num   targets;
    int         pending;
    edge_list   *exit_edge;

    if( HeadBlock == NULL ) {
        return( false );
    }
    if( _IsntModel( FORTRAN_ALIASING ) ) {
        return( false );
    }
    if( !FixReturns() ) {
        return( false );
    }
    FixEdges();

/*
    Run through the blocks and find a place (break_blk) where no previous
    blocks are branched to from later blocks. IE: there are no backward branches
    around break_blk.
*/
    _MarkBlkAllUnVisited();
    break_blk = NULL;
    back_break_blk = NULL;
    pending = 0;
    BranchOuts = NULL;
    for( blk = HeadBlock; blk != NULL; blk = blk->next_block ) {
        if( AskIfReachedLabel( blk->label ) && blk != HeadBlock )
            break;
        if( (blk->edge[0].flags & BLOCK_LABEL_DIES) == 0 && blk != HeadBlock ) {
            _MarkBlkVisited( blk );
            ++pending;
        } else if( pending == 0 ) {
            break_blk = blk;
        }
        edge = &blk->edge[0];
        for( targets = blk->targets; targets > 0; --targets ) {
            if( edge->flags & DEST_IS_BLOCK ) {
                if( edge->flags & DEST_LABEL_DIES ) {
                    if( _IsBlkVisited( edge->destination.u.blk ) ) {
                        _MarkBlkUnVisited( edge->destination.u.blk );
                        if( --pending == 0 ) {
                            back_break_blk = blk->next_block;
                        }
                    }
                }
            }
            ++edge;
        }
    }
    /* clean up the BLOCK_VISITED flags */
    _MarkBlkAllUnVisited();
    if( back_break_blk != NULL ) {
        break_blk = back_break_blk; /* always better to break on a back edge */
    }
    if( break_blk == NULL ) {
        break_blk = HeadBlock;
    }
    if( break_blk == HeadBlock ) {
        break_blk = break_blk->next_block;
    }
    if( break_blk == NULL ) {
        UnFixEdges();
        return( false );
    }

/*
    create a new block and link it after break_blk. Point Break to the rest
    of the blocks and unhook them from the block list.
*/
    Break = break_blk;
    Curr = CurrBlock;
    Tail = BlockList;
    exit_blk = NewBlock( NULL, false );
    exit_blk->gen_id = BlockList->gen_id + 1;
    exit_blk->id = BlockList->id + 1;
    exit_blk->ins.hd.line_num = 0;
    BlockList = exit_blk;
    exit_blk->prev_block = break_blk->prev_block;
    exit_blk->next_block = NULL;
    _SetBlkAttr( exit_blk, BLK_UNKNOWN_DESTINATION );
    break_blk->prev_block->next_block = exit_blk;
    break_blk->prev_block = NULL;

/*
    run throuch all the blocks before break_blk, and create a 'BranchOut' for
    and edge that goes to a block after break_blk
*/
    for( blk = HeadBlock; blk != NULL; blk = blk->next_block ) {
        edge = &blk->edge[0];
        for( targets = blk->targets; targets > 0; --targets ) {
            if( (edge->flags & DEST_IS_BLOCK) == 0 || edge->destination.u.blk->gen_id >= break_blk->gen_id ) {
                exit_edge = CGAlloc( sizeof( edge_list ) );
                exit_edge->edge = edge;
                exit_edge->next = BranchOuts;
                exit_edge->gen_id = blk->gen_id;
                BranchOuts = exit_edge;
            }
            ++edge;
        }
    }

/*
    now, point all 'BranchOuts' at the new 'exit' block, saving their original
    labels in the 'lbl' field of the exit_list
*/

    for( exit_edge = BranchOuts; exit_edge != NULL; exit_edge = exit_edge->next ) {
        edge = exit_edge->edge;
        if( edge->flags & DEST_IS_BLOCK ) {
            exit_edge->lbl = edge->destination.u.blk->label;
            RemoveInputEdge( edge );
        } else {
            exit_edge->lbl = edge->destination.u.lbl;
        }
        edge->destination.u.blk = exit_blk;
        edge->flags |= DEST_IS_BLOCK;
        edge->next_source = exit_blk->input_edges;
        exit_blk->input_edges = edge;
        exit_blk->inputs++;
    }

    if( exit_blk->inputs == 0 ) {
        BlockList = exit_blk->prev_block;
        BlockList->next_block = NULL;
        exit_blk->prev_block = NULL;
        FreeABlock( exit_blk );
    }

    _MarkBlkAttr( HeadBlock, BLK_BIG_LABEL );
    HaveBreak = true;
/*
    change any branches to HeadBlock from a block after break_blk into
    a label (~DEST_IS_BLOCK) branch.
*/
    for( edge = HeadBlock->input_edges; edge != NULL; edge = next_edge ) {
        next_edge = edge->next_source;
        if( edge->source->gen_id >= break_blk->gen_id ) {
            RemoveInputEdge( edge );
            edge->destination.u.lbl = edge->destination.u.blk->label;
            edge->flags &= ~DEST_IS_BLOCK;
        }
    }
/*
    Now, set up a new HeadBlock, and redirect all unknowns branches to it.
    Known branches may still go to the old HeadBlock. This is so that
    HeadBlock will not be a loop header. The loop optimizer will
    screw up if it is.
*/
    blk = NewBlock( NULL, false );
    blk->input_edges = NULL;
    blk->inputs = 0;
    blk->label = HeadBlock->label;
    blk->ins.hd.line_num = HeadBlock->ins.hd.line_num;
    HeadBlock->ins.hd.line_num = 0;
    blk->gen_id = 0;
    blk->id = 0;
    HeadBlock->label = AskForNewLabel();
    blk->targets = 1;
    _SetBlkAttr( blk, BLK_BIG_LABEL | BLK_JUMP );
    _MarkBlkAttrNot( HeadBlock, BLK_BIG_LABEL );
    edge = &blk->edge[0];
    edge->flags = DEST_IS_BLOCK;
    edge->destination.u.blk = HeadBlock;
    edge->source = blk;
    edge->next_source = HeadBlock->input_edges;
    HeadBlock->input_edges = edge;
    HeadBlock->inputs++;
    HeadBlock->prev_block = blk;
    blk->prev_block = NULL;
    blk->next_block = HeadBlock;
    HeadBlock = blk;
    return( true );
}