Example #1
0
static  bool    NextCmp( instruction *ins ) {
/*********************************************/

    instruction *next;

    next = ins->head.next;
    if( !_OpIsCondition( next->head.opcode ) ) return( FALSE );
    if( next->table == DoNop ) return( TRUE );
    if( next->u.gen_table == NULL ) return( FALSE );
    if( next->u.gen_table->generate != G_NO ) return( FALSE );
    return( TRUE );
}
Example #2
0
static  instruction     *FindOneCond( block *blk )
/************************************************/
{
    instruction *ins;
    instruction *cond;

    cond = NULL;
    for( ins = blk->ins.hd.next; ins->head.opcode != OP_BLOCK; ins = ins->head.next ) {
         if( _OpIsCondition( ins->head.opcode ) ) {
             if( cond != NULL ) return( NULL );
             cond = ins;
         }
    }
    return( cond );
}
Example #3
0
static  bool    isNiceCondIns( instruction *ins )
/************************************************
* Figure out if an instruction can be converted to OP_SET_LESS
*/
{
    opcode_defs     oc;

    oc = ins->head.opcode;
    if( !_OpIsCondition( oc ) )
        return( FALSE );
    if( oc == OP_CMP_LESS || oc == OP_CMP_GREATER )
        return( TRUE );
    if( (oc == OP_CMP_LESS_EQUAL) && (ins->operands[1]->n.class == N_CONSTANT)
        && (ins->operands[1]->c.const_type == CONS_ABSOLUTE) )
        return( TRUE );
    if( (oc == OP_CMP_GREATER_EQUAL) && (ins->operands[1]->n.class == N_CONSTANT)
        && (ins->operands[1]->c.const_type == CONS_ABSOLUTE) )
        return( TRUE );
    return( FALSE );
}
Example #4
0
/* Take advantage of the SETcc instruction in cases such as
 * x = y ? 3 : 4;
 * by adding a constant to the result of SETcc to directly obtain
 * the result of the assignment.
 */
static  bool    FindFlowOut( block *blk ) {
/*****************************************/

    signed_64           false_cons;
    signed_64           true_cons;
    signed_64           one;
    signed_64           neg_one;
    signed_64           diff;
    instruction         *ins;
    instruction         *ins0;
    instruction         *ins1;
//    instruction         *prev;
    block               *true_blk;
    block               *false_blk;
    block               *join_blk;
    block_edge          *new_edge;
    bool                reverse;
    name                *u1temp;
    name                *temp;
    name                *result;
    name                *konst;
    type_class_def      class;

    for( ins = blk->ins.hd.prev; !_OpIsCondition( ins->head.opcode ); ) {
        ins = ins->head.prev;
    }
//    prev = ins->head.prev;
    if( TypeClassSize[ ins->type_class ] > WORD_SIZE ) return( FALSE );
    true_blk = blk->edge[ _TrueIndex( ins ) ].destination.u.blk;
    if( true_blk->inputs != 1 ) return( FALSE );
    if( true_blk->targets != 1 ) return( FALSE );

    false_blk = blk->edge[ _FalseIndex( ins ) ].destination.u.blk;
    if( false_blk->inputs != 1 ) return( FALSE );
    if( false_blk->targets != 1 ) return( FALSE );

    join_blk = false_blk->edge[ 0 ].destination.u.blk;
    if( join_blk != true_blk->edge[ 0 ].destination.u.blk ) return( FALSE );
    if( join_blk->inputs != 2 ) return( FALSE );
    if( join_blk->class & UNKNOWN_DESTINATION ) return( FALSE );

    ins0 = SetToConst( false_blk, &false_cons );
    if( ins0 == NULL ) return( FALSE );
    ins1 = SetToConst( true_blk, &true_cons );
    if( ins1 == NULL ) return( FALSE );

    I32ToI64( 1, &one );
    I32ToI64( -1, &neg_one );
    U64Sub( &true_cons, &false_cons, &diff );
    if( U64Cmp( &diff, &neg_one ) == 0 ) {
        U64IncDec( &false_cons, -1 );
        reverse = TRUE;
    } else {
        if( U64Cmp( &diff, &one ) != 0 ) return( FALSE );
        reverse = FALSE;
    }
    result = ins0->result;
    if( result != ins1->result ) return( FALSE );
    class = ins0->type_class;
    if( class != ins1->type_class ) return( FALSE );

    if( reverse ) FlipCond( ins );

    u1temp = AllocTemp( U1 );
    temp = AllocTemp( class );

    ins->result = u1temp;
    ins1 = MakeConvert( u1temp, temp, class, U1 );
    SuffixIns( ins, ins1 );
    ins = ins1;

    if( I64Test( &false_cons ) != 0 ) {
        konst = AllocS64Const( false_cons.u._32[I64LO32], false_cons.u._32[I64HI32] );
        ins1 = MakeBinary( OP_ADD, temp, konst, result, class );
    } else {
Example #5
0
static  bool    FindFlowOut( block *blk )
/***************************************/
{
    signed_32           false_cons;
    signed_32           true_cons;
    instruction         *ins;
    instruction         *ins0;
    instruction         *ins1;
    block               *true;
    block               *false;
    block               *join;
    block_edge          *new_edge;
    bool                reverse;
    name                *u4temp;
    name                *temp;
    name                *result;
    type_class_def      class;
    opcode_defs         oc;

    ins = blk->ins.hd.prev;
    while( !_OpIsCondition( ins->head.opcode ) ) {
        ins = ins->head.prev;
    }
    if( !isNiceCondIns( ins ) )
        return( FALSE );
    if( TypeClassSize[ ins->type_class ] > WORD_SIZE )
        return( FALSE );
    true = blk->edge[ _TrueIndex( ins ) ].destination.u.blk;
    if( true->inputs != 1 )
        return( FALSE );
    if( true->targets != 1 )
        return( FALSE );

    false = blk->edge[ _FalseIndex( ins ) ].destination.u.blk;
    if( false->inputs != 1 )
        return( FALSE );
    if( false->targets != 1 )
        return( FALSE );

    join = false->edge[0].destination.u.blk;
    if( join != true->edge[0].destination.u.blk )
        return( FALSE );
    if( join->inputs != 2 )
        return( FALSE );
    if( join->class & UNKNOWN_DESTINATION )
        return( FALSE );

    ins0 = SetToConst( false, &false_cons );
    if( ins0 == NULL )
        return( FALSE );
    ins1 = SetToConst( true, &true_cons );
    if( ins1 == NULL )
        return( FALSE );
    if( true_cons - false_cons == -1 ) {
        true_cons = false_cons;
        false_cons = true_cons - 1;
        reverse = TRUE;
    } else {
        if( true_cons - false_cons != 1 )
            return( FALSE );
        reverse = FALSE;
    }
    result = ins0->result;
    if( result != ins1->result )
        return( FALSE );
    class = ins0->type_class;
    if( class != ins1->type_class )
        return( FALSE );

    oc = ins->head.opcode;
    if( oc == OP_CMP_GREATER || oc == OP_CMP_GREATER_EQUAL )
        reverse = !reverse;

    /* Replace 'x <= const' with 'x < const + 1' */
    if( oc == OP_CMP_LESS_EQUAL || oc == OP_CMP_GREATER_EQUAL ) {
        signed_32           value;
        name                *op1;

        op1 = ins->operands[1];
        assert( op1->n.class == N_CONSTANT && op1->c.const_type == CONS_ABSOLUTE );
        value = op1->c.int_value;
        if( oc == OP_CMP_LESS_EQUAL )
            value += 1;
        else
            value -= 1;
        ins->operands[1] = AllocS32Const( value );
    }
Example #6
0
instruction     *rMAKECALL( instruction *ins )
/*********************************************
    Using the table RTInfo[], do all the necessary stuff to turn
    instruction "ins" into a call to a runtime support routine.  Move
    the parms into registers, and move the return register of the
    runtime routine into the result. Used for 386 and 370 versions
*/
{
    rtn_info            *info;
    label_handle        lbl;
    instruction         *left_ins;
    instruction         *new_ins;
    instruction         *last_ins;
    name                *reg_name;
    hw_reg_set          regs;
    hw_reg_set          all_regs;
    hw_reg_set          tmp;
    rt_class            rtindex;

    if( !_IsConvert( ins ) ) {
        rtindex = LookupRoutine( ins );
    } else { /* look it up again in case we ran out of memory during expansion*/
        rtindex = LookupConvertRoutine( ins );
    }
    info = &RTInfo[rtindex];
    regs = _ParmReg( info->left );
    all_regs = regs;
    left_ins = MakeMove( ins->operands[0], AllocRegName( regs ),
                          info->operand_class );
    ins->operands[0] = left_ins->result;
    MoveSegOp( ins, left_ins, 0 );
    PrefixIns( ins, left_ins );
    regs = _ParmReg( info->right );
    if( !HW_CEqual( regs, HW_EMPTY ) ) {
        new_ins = MakeMove( ins->operands[1], AllocRegName( regs ),
                                info->operand_class );
        ins->operands[1] = new_ins->result;
        MoveSegOp( ins, new_ins, 0 );
        HW_TurnOn( all_regs, regs );
        PrefixIns( ins, new_ins );
    }
#if _TARGET & _TARG_370
    tmp = RAReg();
    HW_TurnOn( all_regs, tmp );
    tmp = LNReg();
    HW_TurnOn( all_regs, tmp );
#elif _TARGET & _TARG_80386
    {
    tmp = ReturnReg( WD, false );
    HW_TurnOn( all_regs, tmp );
    }
#endif
    reg_name = AllocRegName( all_regs );
    lbl = RTLabel( rtindex );
    new_ins = NewIns( 3 );
    new_ins->head.opcode = OP_CALL;
    new_ins->type_class = ins->type_class;
    new_ins->operands[CALL_OP_USED] = reg_name;
    new_ins->operands[CALL_OP_USED2] = reg_name;
    new_ins->operands[CALL_OP_ADDR] = AllocMemory( lbl, 0, CG_LBL, ins->type_class );
    new_ins->result = NULL;
    new_ins->num_operands = 2;         /* special case for OP_CALL*/
#if _TARGET & _TARG_AXP
    {
    HW_CTurnOn( all_regs, HW_FULL );
    HW_TurnOff( all_regs, SavedRegs() );
    HW_CTurnOff( all_regs, HW_UNUSED );
    HW_TurnOn( all_regs, ReturnAddrReg() );
    }
#endif
    new_ins->zap = (register_name *)AllocRegName( all_regs );   /* all parm regs could be zapped*/
    last_ins = new_ins;
    if( ins->result == NULL || _OpIsCondition( ins->head.opcode ) ) {
        /* comparison, still need conditional jumps*/
        ins->operands[0] = AllocIntConst( 0 );
        ins->operands[1] = AllocIntConst( 1 );
        DelSeg( ins );
        DoNothing( ins );               /* just conditional jumps for ins*/
        PrefixIns( ins, new_ins );
        new_ins->ins_flags |= INS_CC_USED;
        last_ins = ins;
    } else {
        regs = _ParmReg( info->result );
        tmp = regs;
        HW_TurnOn( tmp, new_ins->zap->reg );
        new_ins->zap = (register_name *)AllocRegName( tmp );
        reg_name = AllocRegName( regs );
        new_ins->result = reg_name;
        last_ins = MakeMove( reg_name, ins->result, ins->type_class );
        ins->result = last_ins->operands[0];
        MoveSegRes( ins, last_ins );
        SuffixIns( ins, last_ins );
        ReplIns( ins, new_ins );
    }
    FixCallIns( new_ins );
    UpdateLive( left_ins, last_ins );
    return( left_ins );
}