Example #1
0
static  instruction *CmpRelocZero( instruction *ins, opcnt c, opcnt r )
/*********************************************************************/
{
    name        *cons;
    name        *rel;
    bool        truth;

    if( OpcodeNumOperands( ins ) != 2 )
        return( NULL );
    cons = ins->operands[c];
    if( cons->n.class != N_CONSTANT )
        return( NULL );
    if( cons->c.const_type != CONS_ABSOLUTE )
        return( NULL );
    if( CFTest( cons->c.value ) != 0 )
        return( NULL );
    rel = ins->operands[r];
    if( rel->c.const_type == CONS_OFFSET && !AskSegIsNear( (segment_id)rel->c.lo.int_value ) )
        return( NULL );
    switch( ins->head.opcode ) {
    case OP_BIT_TEST_FALSE:
    case OP_CMP_EQUAL:
    case OP_CMP_LESS:
    case OP_CMP_LESS_EQUAL:
        truth = false;
        break;
    case OP_BIT_TEST_TRUE:
    case OP_CMP_GREATER:
    case OP_CMP_GREATER_EQUAL:
    case OP_CMP_NOT_EQUAL:
        truth = true;
        break;
    default:
        return( false );
    }
    if( !ActiveCompare( ins ) )
        return( NULL );
    if( c != 1 )
        truth = !truth;
    if( truth ) {
        _SetBlockIndex( ins, _TrueIndex(ins), _TrueIndex(ins) );
    } else {
        _SetBlockIndex( ins, _FalseIndex(ins), _FalseIndex(ins) );
    }
    return( KillCompare( ins, AllocIntConst( truth ? FETrue() : 0 ) ) );
}
Example #2
0
static bool ActiveCompare( instruction *ins ) {
/*********************************************/

    if( _FalseIndex( ins ) == _TrueIndex( ins ) )
        return( false );
    /* if unexpanded OR expanded and not just placeholder conditional */
    if( ins->table == NULL )
        return( true );
    if( ins->u.gen_table == NULL )
        return( false );
    if( DoesSomething( ins ) )
        return( true );
    return( false );
}
Example #3
0
static  instruction *StraightLine( instruction *ins, tn fold, bool is_true )
/***************************************************************************
    See if we can turn a comparison into a straight line piece of code.
*/
{
    name        *result;

    result = TGetName( fold );
    if( result == NULL )
        return( NULL );
    if( result->n.class != N_CONSTANT )
        return( NULL );
    if( result->c.const_type != CONS_ABSOLUTE )
        return( NULL );
    if( result->c.lo.int_value == 0 )
        is_true = !is_true;
    if( is_true ) {
        _SetBlockIndex( ins, _TrueIndex(ins), _TrueIndex(ins) );
    } else {
        _SetBlockIndex( ins, _FalseIndex(ins), _FalseIndex(ins) );
    }
    return( KillCompare( ins, result ) );
}
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 );
    }