//Check and replace 'exp' with 'cand_expr' if they are //equal, and update SSA info. If 'cand_expr' is NOT leaf, //that will create redundant computation, and //depends on later Redundancy Elimination to reverse back. // //'cand_expr': substitute cand_expr for exp. // e.g: exp is pr1 of S2, cand_expr is 10. // pr1 = 10 //S1 // g = pr1 //S2 // => // pr1 = 10 // g = 10 // //NOTE: Do NOT handle stmt. void IR_CP::replaceExpViaSSADu(IR * exp, IR const* cand_expr, IN OUT CPCtx & ctx) { ASSERT0(exp && exp->is_exp() && cand_expr && cand_expr->is_exp()); ASSERT0(exp->get_exact_ref()); if (!checkTypeConsistency(exp, cand_expr)) { return; } IR * parent = IR_parent(exp); if (parent->is_ild()) { CPC_need_recomp_aa(ctx) = true; } else if (parent->is_ist() && exp == IST_base(parent)) { if (!cand_expr->is_ld() && !cand_expr->is_pr() && !cand_expr->is_lda()) { return; } CPC_need_recomp_aa(ctx) = true; } IR * newir = m_ru->dupIRTree(cand_expr); if (cand_expr->is_read_pr() && PR_ssainfo(cand_expr) != NULL) { PR_ssainfo(newir) = PR_ssainfo(cand_expr); SSA_uses(PR_ssainfo(newir)).append(newir); } else { m_du->copyIRTreeDU(newir, cand_expr, true); } //cand_expr may be IR tree. And there might be PR or LD on the tree. newir->copyRefForTree(cand_expr, m_ru); //Add SSA use for new exp. SSAInfo * cand_ssainfo = NULL; if ((cand_ssainfo = cand_expr->get_ssainfo()) != NULL) { SSA_uses(cand_ssainfo).append(newir); } //Remove old exp SSA use. SSAInfo * exp_ssainfo = exp->get_ssainfo(); ASSERT0(exp_ssainfo); ASSERT0(SSA_uses(exp_ssainfo).find(exp)); SSA_uses(exp_ssainfo).remove(exp); CPC_change(ctx) = true; ASSERT0(exp->get_stmt()); bool doit = parent->replaceKid(exp, newir, false); ASSERT0(doit); UNUSED(doit); m_ru->freeIRTree(exp); }
//Check and replace 'ir' with 'cand_expr' if they are //equal, and update DU info. If 'cand_expr' is NOT leaf, //that will create redundant computation, and //depends on later Redundancy Elimination to reverse back. //exp: expression which will be replaced. // //cand_expr: substitute cand_expr for exp. // e.g: cand_expr is *p, cand_expr_md is MD3 // *p(MD3) = 10 //p point to MD3 // ... // g = *q(MD3) //q point to MD3 // //exp_use_ssadu: true if exp used SSA du info. // //NOTE: Do NOT handle stmt. void IR_CP::replaceExp(IR * exp, IR const* cand_expr, IN OUT CPCtx & ctx, bool exp_use_ssadu) { ASSERT0(exp && exp->is_exp() && cand_expr); ASSERT0(exp->get_exact_ref()); if (!checkTypeConsistency(exp, cand_expr)) { return; } IR * parent = IR_parent(exp); if (parent->is_ild()) { CPC_need_recomp_aa(ctx) = true; } else if (parent->is_ist() && exp == IST_base(parent)) { if (!cand_expr->is_ld() && !cand_expr->is_pr() && !cand_expr->is_lda()) { return; } CPC_need_recomp_aa(ctx) = true; } IR * newir = m_ru->dupIRTree(cand_expr); m_du->copyIRTreeDU(newir, cand_expr, true); ASSERT0(cand_expr->get_stmt()); if (exp_use_ssadu) { //Remove exp SSA use. ASSERT0(exp->get_ssainfo()); ASSERT0(exp->get_ssainfo()->get_uses().find(exp)); exp->removeSSAUse(); } else { m_du->removeUseOutFromDefset(exp); } CPC_change(ctx) = true; ASSERT0(exp->get_stmt()); bool doit = parent->replaceKid(exp, newir, false); ASSERT0(doit); UNUSED(doit); m_ru->freeIRTree(exp); }
//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; }
//The followed forms // if (cond) { // t=1 // a=1 // goto L1; // } // f=1 // goto L2; // L1: // //is replaced with // // if (!cond) { // f=1 // goto L2; // } // t=1 // a=1 // L1: // //'goto L1' is removed and free, and L1 is removed if it is not a target //of some other instruction. bool IR_CFS_OPT::transformIf1(IR ** head, IR * ir) { ASSERT(head && *head, ("invalid parameter")); if (ir == NULL || !ir->is_if()) { return false; } //Check true part. IR * t = IF_truebody(ir); while (t != NULL) { if (!is_non_branch_ir(t)) { break; } t = t->get_next(); } if (t != NULL && t->get_next() == NULL && t->is_goto()) { IR * first_goto = t; t = ir->get_next(); while (t != NULL) { if (!is_non_branch_ir(t)) { break; } t = t->get_next(); } if (t != NULL && t->is_goto()) { IR * second_goto = t; if (IR_next(second_goto) != NULL && IR_next(second_goto)->is_lab() && isSameLabel(GOTO_lab(first_goto), LAB_lab(IR_next(second_goto)))) { //Start transforming. m_ru->invertCondition(&IF_det(ir)); IR * new_list1 = NULL; IR * new_list2 = NULL; t = IF_truebody(ir); //Split true body of IF. IR * last = NULL; while (t != first_goto) { IR * c = t; t = t->get_next(); xcom::remove(&IF_truebody(ir), c); xcom::add_next(&new_list1, &last, c); } ASSERT(t && t == first_goto, ("invalid control flow")); xcom::remove(&IF_truebody(ir), first_goto); m_ru->freeIRTree(first_goto); //Split all irs between IF and L1. t = ir->get_next(); while (t != second_goto) { IR * c = t; t = t->get_next(); xcom::remove(head, c); xcom::add_next(&new_list2, c); } ASSERT(t != NULL && t == second_goto, ("???")); xcom::remove(head, second_goto); xcom::add_next(&new_list2, second_goto); //Swap new_list1 and new_list2 xcom::insertbefore(&IF_truebody(ir), IF_truebody(ir), new_list2); //Update the IR_parent for new_list2. for (IR * tmp = new_list2; tmp != NULL; tmp = IR_next(tmp)) { IR_parent(tmp) = ir; } ASSERT(IF_truebody(ir) == new_list2, ("illegal insertbefore<T>")); xcom::insertafter(&ir, new_list1); //Update the IR_parent for new_list1. for (IR * tmp = new_list1; tmp != NULL; tmp = IR_next(tmp)) { IR_parent(tmp) = IR_parent(ir); } return true; } } } 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::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; }
/* The followed forms if (cond) { t=1 a=1 goto L1; } f=1 goto L2; L1: is replaced by if (!cond) { f=1 goto L2; } t=1 a=1 L1: 'goto L1' is removed and free, and L1 is removed if it is not a target of some other instruction. */ bool IR_CFS_OPT::trans_if1(IR ** head, IR * ir) { IS_TRUE(head && *head, ("invalid parameter")); if (ir == NULL || IR_type(ir) != IR_IF) { return false; } //Check true part. IR * t = IF_truebody(ir); while (t != NULL) { if (!is_non_branch_ir(t)) { break; } t = IR_next(t); } if (t != NULL && IR_next(t) == NULL && IR_type(t) == IR_GOTO) { IR * first_goto = t; t = IR_next(ir); while (t != NULL) { if (!is_non_branch_ir(t)) break; t = IR_next(t); } if (t != NULL && IR_type(t) == IR_GOTO) { IR * second_goto = t; if (IR_next(second_goto) != NULL && IR_next(second_goto)->is_lab() && is_same_label(GOTO_lab(first_goto), LAB_lab(IR_next(second_goto)))) { //Here we start to transform... m_ru->invert_cond(&IF_det(ir)); IR * new_list1 = NULL; IR * new_list2 = NULL; t = IF_truebody(ir); //Split true body of IF. IR * last = NULL; while (t != first_goto) { IR * c = t; t = IR_next(t); remove(&IF_truebody(ir), c); add_next(&new_list1, &last, c); } IS_TRUE(t && t == first_goto, ("invalid control flow")); remove(&IF_truebody(ir), first_goto); m_ru->free_irs(first_goto); //Split all irs between IF and L1. t = IR_next(ir); while (t != second_goto) { IR * c = t; t = IR_next(t); remove(head, c); add_next(&new_list2, c); } IS_TRUE(t != NULL && t == second_goto, ("???")); remove(head, second_goto); add_next(&new_list2, second_goto); //Swap new_list1 and new_list2 insertbefore(&IF_truebody(ir), IF_truebody(ir), new_list2); //Update the IR_parent for new_list2. for (IR * tmp = new_list2; tmp != NULL; tmp = IR_next(tmp)) { IR_parent(tmp) = ir; } IS_TRUE(IF_truebody(ir) == new_list2, ("illegal insertbefore<T>")); insertafter(&ir, new_list1); //Update the IR_parent for new_list1. for (IR * tmp = new_list1; tmp != NULL; tmp = IR_next(tmp)) { IR_parent(tmp) = IR_parent(ir); } return true; } } } return false; }