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 ) ) ); }
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 ); }
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 ) ); }
/* 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 {
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 ); }