//Return true if gvn is able to determine the result of 'ir'. bool IR_GVN::calc_cond_must_val(IN IR const* ir, bool & must_true, bool & must_false) { must_true = false; must_false = false; IS_TRUE0(ir->is_judge()); VN const* v1 = m_ir2vn.get(IR_id(BIN_opnd0(ir))); VN const* v2 = m_ir2vn.get(IR_id(BIN_opnd1(ir))); if (v1 == NULL || v2 == NULL) return false; switch (IR_type(ir)) { case IR_LT: case IR_GT: if (v1 == v2) { must_true = false; must_false = true; return true; } break; case IR_LE: case IR_GE: if (v1 == v2) { must_true = true; must_false = false; return true; } break; case IR_NE: if (v1 == v2) { must_true = false; must_false = true; return true; } if (v1 != v2) { must_true = true; must_false = false; return true; } IS_TRUE0(0); break; case IR_EQ: if (v1 == v2) { must_true = true; must_false = false; return true; } if (v1 != v2) { must_true = false; must_false = true; return true; } IS_TRUE0(0); break; case IR_LAND: case IR_LOR: case IR_LNOT: break; default: IS_TRUE0(0); } return false; }
//The followed forms // x is signed // IF(x > 0x7FFFFFFF) {a=1} ELSE {b=1} => b=1 // IF(x < 0x80000000) {a=1} ELSE {b=1} => b=1 // // x is unsigned // IF(x > 0xFFFFFFFF){a=1} ELSE {b=1} => b=1 // IF(x < 0x0) {a=1} ELSE {b=1} => b=1 bool IR_CFS_OPT::transformIf3(IR ** head, IR * ir) { ASSERT(head && *head, ("invalid parameter")); if (ir == NULL || !ir->is_if()) { return false; } IR * det = IF_det(ir); if (det->is_gt()) { IR * opnd0 = BIN_opnd0(det); IR * opnd1 = BIN_opnd1(det); if (opnd0->is_ld() && opnd0->is_int() && opnd1->is_const() && opnd1->is_int() && m_ru->getIntegerInDataTypeValueRange(opnd1) == m_ru->getMaxInteger(m_tm->get_dtype_bitsize( TY_dtype(opnd1->get_type())), opnd1->is_signed())) { //e.g: //x is unsigned, if(x>0xFFFFFFFF) {a=1} else {b=1} => b=1 //x is signed, if(x>0x7FFFFFFF) {a=1} else {b=1} => b=1 IR * allocIR = NULL; if (IF_falsebody(ir) != NULL) { allocIR = m_ru->dupIRTree(IF_falsebody(ir)); } xcom::replace(head, ir, allocIR); if (allocIR != NULL) { IR_parent(allocIR) = IR_parent(ir); } m_ru->freeIRTree(ir); return true; } } else if (det->is_lt()) { IR * opnd0 = BIN_opnd0(det); IR * opnd1 = BIN_opnd1(det); if (opnd0->is_ld() && opnd0->is_int() && opnd1->is_const() && opnd1->is_int() && m_ru->getIntegerInDataTypeValueRange(opnd1) == m_ru->getMinInteger(m_tm->get_dtype_bitsize( TY_dtype(opnd1->get_type())), opnd1->is_signed())) { //x is signed, IF(x < 0x80000000) {a=1} ELSE {b=1} => b=1 IR * allocIR = NULL; if (IF_falsebody(ir) != NULL) { allocIR = m_ru->dupIRTree(IF_falsebody(ir)); } xcom::replace(head, ir, allocIR); if (allocIR != NULL) { IR_parent(allocIR) = IR_parent(ir); } m_ru->freeIRTree(ir); return true; } else if (opnd0->is_ld() && opnd1->is_const() && opnd0->is_uint() && CONST_int_val(opnd1) == 0) { //x is unsigned, if(x<0) {a=1} else {b=1} => b=1 IR * allocIR = NULL; if (IF_falsebody(ir) != NULL) { allocIR = m_ru->dupIRTree(IF_falsebody(ir)); } xcom::replace(head, ir, allocIR); if (allocIR != NULL) { IR_parent(allocIR) = IR_parent(ir); } m_ru->freeIRTree(ir); return true; } } return false; }
VN * IR_GVN::comp_vn(IR const* exp, bool & change) { IS_TRUE0(exp); switch (IR_type(exp)) { case IR_ADD: case IR_SUB: case IR_MUL: case IR_DIV: case IR_REM: case IR_MOD: case IR_LAND: //logical and && case IR_LOR: //logical or || case IR_BAND: //inclusive and & case IR_BOR: //inclusive or | case IR_XOR: //exclusive or case IR_LT: case IR_LE: case IR_GT: case IR_GE: case IR_EQ: //== case IR_NE: //!= case IR_ASR: case IR_LSR: case IR_LSL: { VN * vn1 = comp_vn(BIN_opnd0(exp), change); VN * vn2 = comp_vn(BIN_opnd1(exp), change); if (vn1 == NULL || vn2 == NULL) { if (m_ir2vn.get(IR_id(exp)) != NULL) { m_ir2vn.set(IR_id(exp), NULL); change = true; } return NULL; } VN * x = register_bin_vn((IR_TYPE)IR_type(exp), vn1, vn2); if (m_ir2vn.get(IR_id(exp)) != x) { m_ir2vn.set(IR_id(exp), x); change = true; } return x; } break; case IR_BNOT: //bitwise not case IR_LNOT: //logical not case IR_NEG: //negative { VN * x = comp_vn(UNA_opnd0(exp), change); if (x == NULL) { if (m_ir2vn.get(IR_id(exp)) != NULL) { m_ir2vn.set(IR_id(exp), NULL); change = true; } return NULL; } x = register_uni_vn((IR_TYPE)IR_type(exp), x); if (m_ir2vn.get(IR_id(exp)) != x) { m_ir2vn.set(IR_id(exp), x); change = true; } return x; } break; case IR_CVT: //type convertion { VN * x = comp_vn(CVT_exp(exp), change); if (x == NULL) { if (m_ir2vn.get(IR_id(exp)) != NULL) { m_ir2vn.set(IR_id(exp), NULL); change = true; } return NULL; } x = register_uni_vn((IR_TYPE)IR_type(exp), x); if (m_ir2vn.get(IR_id(exp)) != x) { m_ir2vn.set(IR_id(exp), x); change = true; } return x; } break; case IR_LDA: { IR const* ldabase = LDA_base(exp); VN * basevn; if (IR_type(ldabase) == IR_ID) { MD const* emd = ldabase->get_exact_ref(); if (emd == NULL) { //e.g: p = &"blabla", regard MD of "blabla" as inexact. IS_TRUE(ldabase->is_str(m_dm), ("only string's MD can be inexact.")); if (m_is_comp_lda_string) { emd = m_du->get_effect_use_md(ldabase); IS_TRUE(emd, ("string should have effect MD")); basevn = register_md_vn(emd); } else { basevn = NULL; } } else { IS_TRUE0(emd); basevn = register_md_vn(emd); } } else { basevn = comp_vn(LDA_base(exp), change); } if (basevn == NULL) { if (m_ir2vn.get(IR_id(exp)) != NULL) { m_ir2vn.set(IR_id(exp), NULL); change = true; } return NULL; } VN * ofstvn = register_int_vn(LDA_ofst(exp)); VN * x = register_bin_vn(IR_LDA, basevn, ofstvn); if (m_ir2vn.get(IR_id(exp)) != x) { m_ir2vn.set(IR_id(exp), x); change = true; } return x; } break; //case IR_ID: case IR_LD: case IR_PR: return comp_sc(exp, change); case IR_ARRAY: return comp_array(exp, change); case IR_ILD: return comp_ild(exp, change); case IR_CONST: { VN * x = m_ir2vn.get(IR_id(exp)); if (x != NULL) { return x; } if (exp->is_int(m_dm)) { x = register_int_vn(CONST_int_val(exp)); } else if (exp->is_fp(m_dm)) { if (!m_is_vn_fp) { return NULL; } x = register_fp_vn(CONST_fp_val(exp)); } else if (exp->is_str(m_dm)) { x = register_str_vn(CONST_str_val(exp)); } else { IS_TRUE(0, ("unsupport const type")); } IS_TRUE0(x); m_ir2vn.set(IR_id(exp), x); change = true; return x; } break; default: break; } return NULL; }
/* The followed forms x is signed IF(x > 0x7FFFFFFF) {a=1} ELSE {b=1} => b=1 IF(x < 0x80000000) {a=1} ELSE {b=1} => b=1 x is unsigned IF(x > 0xFFFFFFFF){a=1} ELSE {b=1} => b=1 IF(x < 0x0) {a=1} ELSE {b=1} => b=1 */ bool IR_CFS_OPT::trans_if3(IR ** head, IR * ir) { IS_TRUE(head && *head, ("invalid parameter")); if (ir == NULL || IR_type(ir) != IR_IF) { return false; } IR * det = IF_det(ir); if (IR_type(det) == IR_GT) { IR * opnd0 = BIN_opnd0(det); IR * opnd1 = BIN_opnd1(det); DTD const* op0_rty = opnd0->get_dtd(m_dm); DTD const* op1_rty = opnd1->get_dtd(m_dm); if (IR_type(opnd0) == IR_LD && opnd1->is_const() && opnd0->is_int(m_dm) && CONST_int_val(opnd1) == MAX_INT_VALUE) { //x is signed, if(x>0x7FFFFFFF) {a=1} else {b=1} => b=1 IR * new_ir = NULL; if (IF_falsebody(ir)) { new_ir = m_ru->dup_irs(IF_falsebody(ir)); } replace(head, ir, new_ir); //Revise IR_parent. IR_parent(new_ir) = IR_parent(ir); m_ru->free_irs(ir); return true; } else if (IR_type(opnd0) == IR_LD && IR_is_const(opnd1) && opnd0->is_uint(m_dm) && CONST_int_val(opnd1) == MAX_UINT_VALUE) { //x is unsigned, if(x>0xFFFFFFFF) {a=1} else {b=1} => b=1 IR * new_ir = NULL; if (IF_falsebody(ir)) { new_ir = m_ru->dup_irs(IF_falsebody(ir)); } replace(head, ir, new_ir); //Revise IR_parent. IR_parent(new_ir) = IR_parent(ir); m_ru->free_irs(ir); return true; } } else if (IR_type(det) == IR_LT) { IR * opnd0 = BIN_opnd0(det); IR * opnd1 = BIN_opnd1(det); DTD const* op0_rty = opnd0->get_dtd(m_dm); DTD const* op1_rty = opnd1->get_dtd(m_dm); if (IR_type(opnd0) == IR_LD && IR_is_const(opnd1) && opnd0->is_int(m_dm) && CONST_int_val(opnd1) == MIN_INT_VALUE) { //x is signed, IF(x < 0x80000000) {a=1} ELSE {b=1} => b=1 IR * new_ir = NULL; if (IF_falsebody(ir)) { new_ir = m_ru->dup_irs(IF_falsebody(ir)); } replace(head, ir, new_ir); m_ru->free_irs(ir); return true; } else if (IR_type(opnd0) == IR_LD && IR_is_const(opnd1) && opnd0->is_uint(m_dm) && CONST_int_val(opnd1) == 0) { //x is unsigned, if(x<0) {a=1} else {b=1} => b=1 IR * new_ir = NULL; if (IF_falsebody(ir)) { new_ir = m_ru->dup_irs(IF_falsebody(ir)); } replace(head, ir, new_ir); //Revise IR_parent. IR_parent(new_ir) = IR_parent(ir); m_ru->free_irs(ir); return true; } } return false; }