i87sched.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,092 行 · 第 1/3 页

C
1,092
字号
        }
    }
    TempList = SortList( TempList, offsetof( temp_entry, next ), Better );
}


extern  void    FiniTempEntries( void ) {
/***************************/

    temp_entry  *temp,*junk;

    temp = TempList;
    while( temp != NULL ) {
        junk = temp;
        temp = temp->next;
        _Free( junk, sizeof( temp_entry ) );
    }
    TempList = NULL;
}


static  bool    StackBetween( instruction *first, instruction *last, int inc ) {
/******************************************************************************/

    instruction *ins;
    bool        enough;

    enough = TRUE;
    for( ins = first; ins != last; ins = ins->head.next ) {
        if( ins->s.stk_depth >= (Max87Stk-1) || _OpIsCall( ins->head.opcode ) ) {
            enough = FALSE;
        }
        ins->s.stk_depth += inc;
    }
    return( enough );
}


static  void    KillRelatedTemps( name *op )
/******************************************/
{
    temp_entry  *temp;

    if( op->n.class != N_MEMORY ) return;
    for( temp = TempList; temp != NULL; temp = temp->next ) {
        if( temp->op->n.class == N_MEMORY &&
            temp->op->v.symbol == op->v.symbol ) {
            temp->killed = TRUE;
        }
    }
}

static  bool    OKToCache( temp_entry *temp ) {
/*********************************************/

    instruction         *ins;
    name                *seg;

    ins = temp->first;
    if( ins->num_operands <= NumOperands( ins ) ) return( TRUE );
    seg = ins->operands[ ins->num_operands - 1 ];
    ins = ins->head.prev;
    while( ins->head.opcode != OP_BLOCK ) {
        /*
         * Might be a segment load or some other sort of nonsense here.
         */
        if( ReDefinedBy( ins, seg ) ) return( FALSE );
        ins = ins->head.prev;
    }
    return( _BLOCK( ins ) == Entry );
}

static  void    CacheTemps( block *blk ) {
/****************************************/

    temp_entry *temp, **owner;
    block_edge  *exit_edge = NULL;

    Entry = NULL;
    Exit = NULL;
    if( blk->class & LOOP_HEADER
        && blk->inputs == 2 && blk->targets == 2 ) {
        if( blk->edge[0].destination == blk ) {
            Exit = blk->edge[1].destination;
            exit_edge = &blk->edge[1];
        } else if( blk->edge[1].destination == blk ) {
            Exit = blk->edge[0].destination;
            exit_edge = &blk->edge[0];
        } else {
            Exit = NULL;
        }
        if( Exit != NULL ) {
            if( blk->input_edges->source == blk ) {
                Entry = blk->input_edges->next_source->source;
            } else if( blk->input_edges->next_source->source == blk ) {
                Entry = blk->input_edges->source;
            } else {
                Entry = NULL;
                Exit = NULL;
            }
        }
        if( Entry != NULL ) {
            if( Entry->class & JUMP ) {
                if( Exit->inputs != 1 ) {
                    Exit = AddPreBlock( Exit );
                    MoveEdge( exit_edge, Exit );
                }
            }
        }
    }
    for( temp = TempList; temp != NULL; temp = temp->next ) {
        if( temp->killed ) continue;
        if( !OKToCache( temp ) ) {
            temp->killed = TRUE;
        }
    }
    for( temp = TempList; temp != NULL; temp = temp->next ) {
        if( temp->killed ) {
            KillRelatedTemps( temp->op );
        }
    }
    for( temp = TempList; temp != NULL; temp = temp->next ) {
        if( temp->killed ) continue;
        if( temp->op->v.usage & USE_IN_ANOTHER_BLOCK ) {
            if( Entry != NULL ) {
                temp->first = blk->ins.hd.next;
                temp->last = blk->ins.hd.prev;
                temp->whole_block = TRUE;
            } else {
                if( temp->defined ) continue;
                if( temp->first == temp->last ) continue;
            }
            temp->global = TRUE;
        } else {
            if( !temp->defined ) continue; // I'm not sure if these save anything
            if( temp->defined && temp->first->u.gen_table->generate!=G_MFST ) continue;
            if( RegAction( temp->last ) == NULL ) continue;
            if( temp->first == temp->last ) continue;
        }
        if( StackBetween( temp->first, temp->last, 0 ) ) {
            StackBetween( temp->first, temp->last, 1 );
            temp->cached = TRUE;
        }
    }
    owner = &TempList;
    for( ;; ) {
        temp = *owner;
        if( temp == NULL ) break;
        if( temp->cached ) {
            owner = &temp->next;
        } else {
            *owner = temp->next;
            _Free( temp, sizeof( temp_entry ) );
        }
    }
}

// just have to make sure this is not a valid FP-stack depth

#define SEQ_INIT_VALUE  0xff

extern  void    FPPreSched( block *blk ) {
/****************************************/

    temp_entry  *temp;
    instruction *ins;
    int         i;
    int         depth;

    MaxSeq = 0;
    ins = blk->ins.hd.next;
    while( ins->head.opcode != OP_BLOCK ) {
        if( ins->sequence > MaxSeq ) MaxSeq = ins->sequence;
        ins = ins->head.next;
    }
    ++MaxSeq;
    InitTempEntries( blk );
    CacheTemps( blk );
    for( temp = TempList; temp != NULL; temp = temp->next ) {
        StackBetween( temp->first, temp->last, -1 );
    }
    _Alloc( SeqCurDepth, MaxSeq * sizeof( *SeqCurDepth ) );
    _Alloc( SeqMaxDepth, MaxSeq * sizeof( *SeqMaxDepth ) );
    for( i = 0; i < MaxSeq; ++i ) {
        SeqCurDepth[ i ] = SEQ_INIT_VALUE;
        SeqMaxDepth[ i ] = 0;
    }
    ins = blk->ins.hd.prev;
    while( ins->head.opcode != OP_BLOCK ) {
        if( SeqCurDepth[ ins->sequence ] == SEQ_INIT_VALUE ) {
            if( FPStackIns( ins ) ) {
                SeqCurDepth[ ins->sequence ] = ins->stk_exit;
            }
        }
        ins = ins->head.prev;
    }
    for( i = 0; i < MaxSeq; ++i ) {
        if( SeqCurDepth[ i ] == SEQ_INIT_VALUE ) {
            SeqCurDepth[ i ] = 0;
        }
    }
    ins = blk->ins.hd.next;
    while( ins->head.opcode != OP_BLOCK ) {
        /*
         * We do this here in order to not be faked out by inheriting bogus values
         * when we prefix an instruction to another FP instruction. This would screw
         * up our instruction scheduling by digging a hole which FPStkOver would
         * be convinced we could not get out of. For an illustration of the problem,
         * consider the two sequences "pow a, b -> c" and "pow d, e -> f" before
         * RegAlloc et all and how we would schedule these with -fpr.
         */
        ins->s.stk_extra = FPStkReq( ins ); // BBB - March 22, 1994
        depth = InsMaxDepth( ins ) + ins->s.stk_extra;
        ins->t.stk_max = SeqMaxDepth[ ins->sequence ];
        if( depth > SeqMaxDepth[ ins->sequence ] ) {
            SeqMaxDepth[ ins->sequence ] = depth;
        }
        ins = ins->head.next;
    }
}


static  void    FiniGlobalTemps( void ) {
/*********************************/

    temp_entry  *temp;
    instruction *ins;

    for( temp = TempList; temp != NULL; temp = temp->next ) {
        if( temp->whole_block ) {
            ins = (instruction *)&Exit->ins;
            if( temp->defined ) {
                SuffFSTPRes( ins, temp->actual_op, RES_MEM );
            } else {
                SuffFSTPRes( ins, temp->actual_op, RES_MEM_THROWAWAY );
            }
            ins->head.next->ins_flags |= FP_INS_INTRODUCED;
        }
    }
}


static  void    InitGlobalTemps( void ) {
/*********************************/

    temp_entry  *temp;
    instruction *ins;
    int         locn;

    locn = ACTUAL_0;
    for( temp = TempList; temp != NULL; temp = temp->next ) {
        if( temp->whole_block ) ++locn;
    }
    for( temp = TempList; temp != NULL; temp = temp->next ) {
        if( temp->whole_block ) {
            ins = Entry->ins.hd.prev;
            while( ins->head.opcode == OP_NOP ) {
                if( ins->flags.nop_flags & NOP_ZAP_INFO ) break;
                ins = ins->head.prev;
            }
            ins = ins->head.next;
            PrefFLDOp( ins, OP_MEM, temp->actual_op );
            ins->head.prev->ins_flags |= FP_INS_INTRODUCED;
            temp->actual_locn = --locn;
        }
    }
}


static  void    XchForCall( instruction *ins, int i ) {
/*****************************************************/

    byte        *actual_i_owner;
    byte        *actual_0_owner;

    if( i <= 0 ) return;
    if( InsLoc( ins, VIRTUAL_0+i ) != ACTUAL_0+i ) {
        GetToTopOfStack( ins, VIRTUAL_0+i );
        if( InsLoc( ins, VIRTUAL_0+i ) != ACTUAL_0+i ) {
            PrefixExchange( ins, ACTUAL_0+i );
            actual_i_owner = ActualStackOwner( ACTUAL_0+i );
            actual_0_owner = ActualStackOwner( ACTUAL_0 );
            *actual_i_owner = ACTUAL_0;
            *actual_0_owner = ACTUAL_0+i;
        }
    }
    XchForCall( ins, i-1 );
}


static  void    ReOrderForCall( instruction *ins ) {
/**************************************************/

    int         i,count;

    count = Count87Regs( ins->operands[ CALL_OP_USED ]->r.reg );
    XchForCall( ins, count-1 );
    for( i = 0; i < count; ++i ) {
        PopStack( ins );
    }
}


extern  void    FPPostSched( block *blk ) {
/*****************************************/

    fp_attr     attr;
    instruction *ins;
    instruction *next;
    int         virtual;
    temp_entry  *temp;

    _Free( SeqCurDepth, MaxSeq * sizeof( *SeqCurDepth ) );
    _Free( SeqMaxDepth, MaxSeq * sizeof( *SeqMaxDepth ) );
    FiniTempEntries();
    InitStackLocations();
    InitTempEntries( blk );
    CacheTemps( blk );
    InitGlobalTemps();
    ins = blk->ins.hd.next;
    while( ins->head.opcode != OP_BLOCK ) {
        next = ins;
        if( !( ins->ins_flags & FP_INS_INTRODUCED ) ) {
            attr = FPAttr( ins );
            temp = LookupTempEntry( ins->result );
            if( attr & NEEDS_ST0 && temp == NULL ) {
                GetToTopOfStack( ins, VIRTUAL_0 );
            } else if( attr & NEEDS_ST0_ST1 ) {
                if( attr & POPS2 ) {
                    // the dreaded FCOMPP
                    next = FComppKluge( ins );
                } else {
                    next = GetST0andST1( ins );
                }
            } else if( attr & POPS_ALL ) {
                ReOrderForCall( ins );
            }
            if( temp != NULL ) {
                attr = ResultToReg( ins, temp, attr );
            } else if( attr & SETS_ST1 ) {
                SetResultReg( ins, VIRTUAL_1 );
            } else if( attr & EXCHANGES ) {
                virtual = FPRegNum( ins->result );
                SetResultReg( ins, virtual );
            }
            temp = LookupTempEntry( ins->operands[0] );
            if( temp != NULL ) {
                next = OpToReg( ins, temp, attr );
            } else if( attr & PUSHES ) {
                PushStack( ins );
            } else if( attr & POPS2 ) {
                PopStack( ins );
                PopStack( ins );
            } else if( attr & POPS ) {
                PopStack( ins );
            }
        }
        ins = next->head.next;
    }
    FiniGlobalTemps();
    FiniStackLocations();
    FiniTempEntries();
}

⌨️ 快捷键说明

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