//Check that all basic blocks should only end with terminator IR. void IRBB::verify() { UINT c = 0; C<IR*> * ct; for (IR * ir = BB_irlist(this).get_head(&ct); ir != NULL; ir = BB_irlist(this).get_next(&ct)) { ASSERT0(ir->is_single()); ASSERT0(ir->get_bb() == this); switch (IR_code(ir)) { case IR_ST: case IR_STPR: case IR_STARRAY: case IR_IST: case IR_PHI: case IR_REGION: case IR_CALL: case IR_ICALL: case IR_GOTO: case IR_IGOTO: case IR_TRUEBR: case IR_FALSEBR: case IR_RETURN: case IR_SWITCH: break; default: ASSERT(0, ("BB does not supported this kind of IR.")); } if (is_bb_down_boundary(ir)) { ASSERT(ir == BB_last_ir(this), ("invalid BB down boundary.")); } c++; } ASSERT0(c == getNumOfIR()); }
//Canonicalize det of IF. //e.g: if (a=10,b+=3,c<a) {...} //be replaced by // a = 10; // b += 3; // if (c<a) {...} bool IR_CFS_OPT::hoistIf(IR ** head, IR * ir) { ASSERT(ir->is_if(), ("need IF")); ASSERT(IF_det(ir), ("DET is NULL")); IR * det = IF_det(ir); INT i = 0; while (det != NULL) { i++; det = det->get_next(); } IR * new_list = NULL; if (i > 1) { det = IF_det(ir); while (i > 1) { IR * c = det; ASSERT(c->is_stmt(), ("Non-stmt ir should be remove during reshape_ir_tree()")); det = det->get_next(); xcom::remove(&IF_det(ir), c); xcom::add_next(&new_list, c); i--; } xcom::insertbefore(head, ir, new_list); return true; } return false; }
//Before removing bb, revising phi opnd if there are phis //in one of bb's successors. void IRBB::removeSuccessorPhiOpnd(CFG<IRBB, IR> * cfg) { IR_CFG * ircfg = (IR_CFG*)cfg; Region * ru = ircfg->get_ru(); Vertex * vex = ircfg->get_vertex(BB_id(this)); ASSERT0(vex); for (EdgeC * out = VERTEX_out_list(vex); out != NULL; out = EC_next(out)) { Vertex * succ_vex = EDGE_to(EC_edge(out)); IRBB * succ = ircfg->get_bb(VERTEX_id(succ_vex)); ASSERT0(succ); UINT const pos = ircfg->WhichPred(this, succ); for (IR * ir = BB_first_ir(succ); ir != NULL; ir = BB_next_ir(succ)) { if (!ir->is_phi()) { break; } ASSERT0(cnt_list(PHI_opnd_list(ir)) == cnt_list(VERTEX_in_list(succ_vex))); IR * opnd; UINT lpos = pos; for (opnd = PHI_opnd_list(ir); lpos != 0; opnd = IR_next(opnd)) { ASSERT0(opnd); lpos--; } opnd->removeSSAUse(); ((CPhi*)ir)->removeOpnd(opnd); ru->freeIRTree(opnd); } } }
volatile char IRremote(char key, char first) { if(first) { lcd.cls(); menu.setTitle(TEXT("IR Remote")); menu.setBar(TEXT("Delayed"), TEXT("Trigger")); lcd.update(); } switch(key) { case FL_KEY: ir.shutterDelayed(); break; case FR_KEY: ir.shutterNow(); break; case LEFT_KEY: return FN_CANCEL; } return FN_CONTINUE; }
/* Canonicalize det of IF. e.g: if (a=10,b+=3,c<a) {...} be replaced by a = 10; b += 3; if (c<a) {...} */ bool IR_CFS_OPT::hoist_if(IR ** head, IR * ir) { IS_TRUE(IR_type(ir) == IR_IF, ("need IF")); IS_TRUE(IF_det(ir), ("DET is NULL")); IR * det = IF_det(ir); INT i = 0; while (det != NULL) { i++; det = IR_next(det); } IR * new_list = NULL; if (i > 1) { det = IF_det(ir); while (i > 1) { IR * c = det; IS_TRUE(c->is_stmt(), ("Non-stmt ir should be remove during reshape_ir_tree()")); det = IR_next(det); remove(&IF_det(ir), c); add_next(&new_list, c); i--; } insertbefore(head, ir, new_list); return true; } return false; }
//Allocate MDPhi and initialize with the number of operands. //Each operands has zero version to mdid. MDPhi * UseDefMgr::allocMDPhi(UINT mdid, UINT num_operands) { ASSERT0(mdid > 0 && num_operands > 0); MDPhi * phi = (MDPhi*)smpoolMallocConstSize(sizeof(MDPhi), m_phi_pool); phi->init(); MDDEF_id(phi) = m_def_count++; m_def_vec.set(MDDEF_id(phi), phi); VMD const* vmd = allocVMD(mdid, 0); ASSERT0(vmd); MD const* md = m_md_sys->getMD(mdid); ASSERT0(md); IR * last = NULL; for (UINT i = 0; i < num_operands; i++) { IR * opnd = m_ru->buildId(md->get_base()); opnd->setRefMD(md, m_ru); MDSSAInfo * mdssainfo = genMDSSAInfo(opnd); ASSERT0(m_sbs_mgr); mdssainfo->getVOpndSet()->append(vmd, *m_sbs_mgr); xcom::add_next(&MDPHI_opnd_list(phi), &last, opnd); ID_phi(opnd) = phi; } return phi; }
/* Hoist det of loop. e.g: while (a=10,b+=3,c<a) { IR-LIST; } be replaced by a = 10; b += 3; while (c<a) { IR-LIST; a = 10; b += 3; } */ bool IR_CFS_OPT::hoist_loop(IR ** head, IR * ir) { IS_TRUE(IR_type(ir)==IR_DO_WHILE || IR_type(ir)==IR_WHILE_DO || IR_type(ir)==IR_DO_LOOP, ("need LOOP")); IS_TRUE(LOOP_det(ir), ("DET is NULL")); IR * det = LOOP_det(ir); INT i = 0; while (det != NULL) { i++; det = IR_next(det); } IR * new_list = NULL, * new_body_list = NULL; if (i > 1) { det = LOOP_det(ir); while (i > 1) { IR * c = det; IS_TRUE(c->is_stmt(), ("Non-stmt ir should be remove " "during reshape_ir_tree()")); det = IR_next(det); remove(&LOOP_det(ir), c); add_next(&new_list, c); i--; } new_body_list = m_ru->dup_irs_list(new_list); insertbefore(head, ir, new_list); add_next(&LOOP_body(ir), new_body_list); return true; } return false; }
//Hoist det of loop. //e.g: while (a=10,b+=3,c<a) { // IR-List; // } // //be replaced by // // a = 10; // b += 3; // while (c<a) { // IR-List; // a = 10; // b += 3; // } bool IR_CFS_OPT::hoistLoop(IR ** head, IR * ir) { ASSERT0(ir->is_dowhile() || ir->is_whiledo() || ir->is_doloop()); ASSERT(LOOP_det(ir), ("DET is NULL")); IR * det = LOOP_det(ir); INT i = 0; while (det != NULL) { i++; det = det->get_next(); } IR * new_list = NULL, * new_body_list = NULL; if (i > 1) { det = LOOP_det(ir); while (i > 1) { IR * c = det; ASSERT(c->is_stmt(), ("Non-stmt ir should be remove " "during reshape_ir_tree()")); det = det->get_next(); xcom::remove(&LOOP_det(ir), c); xcom::add_next(&new_list, c); i--; } new_body_list = m_ru->dupIRTreeList(new_list); xcom::insertbefore(head, ir, new_list); xcom::add_next(&LOOP_body(ir), new_body_list); return true; } return false; }
//Before removing bb or change bb successor, //you need remove the related PHI operand if BB successor has PHI stmt. void IRBB::removeSuccessorDesignatePhiOpnd(CFG<IRBB, IR> * cfg, IRBB * succ) { ASSERT0(cfg && succ); IR_CFG * ircfg = (IR_CFG*)cfg; Region * ru = ircfg->get_ru(); UINT const pos = ircfg->WhichPred(this, succ); for (IR * ir = BB_first_ir(succ); ir != NULL; ir = BB_next_ir(succ)) { if (!ir->is_phi()) { break; } ASSERT0(cnt_list(PHI_opnd_list(ir)) == succ->getNumOfPred(cfg)); IR * opnd; UINT lpos = pos; for (opnd = PHI_opnd_list(ir); lpos != 0; opnd = opnd->get_next()) { ASSERT0(opnd); lpos--; } if (opnd == NULL) { //PHI does not contain any operand. continue; } opnd->removeSSAUse(); ((CPhi*)ir)->removeOpnd(opnd); ru->freeIRTree(opnd); } }
CE_Eliminator(IR* hir) : _cee_count(0), _ifop_count(0), _hir(hir) { _has_substitution = false; _hir->iterate_preorder(this); if (_has_substitution) { // substituted some ifops/phis, so resolve the substitution SubstitutionResolver sr(_hir); } CompileLog* log = _hir->compilation()->log(); if (log != NULL) log->set_context("optimize name='cee'"); }
void shutter::off(void) { if(conf.devMode) hardware_flashlight(0); if(cable_connected == 0) { if(bulb && shutter_state) { ir.shutterNow(); } shutter_state = 0; } else if(conf.bulbMode == 0) { SHUTTER_CLOSE; MIRROR_DOWN; _delay_ms(50); CHECK_CABLE; } else if(conf.bulbMode == 1 && shutter_state == 1) { SHUTTER_CLOSE; MIRROR_DOWN; _delay_ms(50); CHECK_CABLE; shutter_state = 0; full(); shutter_state = 0; } }
void settings_load() { eeprom_read_block((void*)&conf, &conf_eep, sizeof(settings_t)); if(settings_camera_index > 0) { eeprom_read_block((void*)&conf.camera, &camera_settings_eep[settings_camera_index - 1], sizeof(camera_settings_t)); } if(conf.lcdContrast > 0xf || conf.lcdContrast < 0x1) conf.lcdContrast = 0x8; if(conf.lcdCoefficent > 0x7 || conf.lcdCoefficent < 0x3) conf.lcdCoefficent = 0x7; if(conf.lcdBias > 0x4 || conf.lcdBias < 0x3) conf.lcdBias = 0x4; if(conf.apertureMin > 100 || conf.apertureMin < 2) conf.apertureMin = 2; if(conf.lightIntegrationMinutes == 255 || conf.lightIntegrationMinutes == 0) conf.lightIntegrationMinutes = 10; if(conf.camera.brampGap > 20 || conf.camera.brampGap == 0) conf.camera.brampGap = 6; if(conf.errorAlert > 5) conf.errorAlert = 0; if(conf.linearInterpolation > 1) conf.linearInterpolation = 0; lcd.color(conf.lcdColor); ir.init(); ir.make = conf.camera.cameraMake; if(conf.auxPort != AUX_MODE_DISABLED) { aux1_off(); aux2_off(); } if(bt.present && !remote.connected) { if(conf.btMode == BT_MODE_SLEEP) bt.sleep(); else bt.advertise(); } }
CE_Eliminator(IR* hir) : _cee_count(0), _ifop_count(0), _hir(hir) { _has_substitution = false; _hir->iterate_preorder(this); if (_has_substitution) { // substituted some ifops/phis, so resolve the substitution SubstitutionResolver sr(_hir); } }
//Return true if one of bb's successor has a phi. bool IRBB::successorHasPhi(CFG<IRBB, IR> * cfg) { Vertex * vex = cfg->get_vertex(BB_id(this)); ASSERT0(vex); for (EdgeC * out = VERTEX_out_list(vex); out != NULL; out = EC_next(out)) { Vertex * succ_vex = EDGE_to(EC_edge(out)); IRBB * succ = cfg->get_bb(VERTEX_id(succ_vex)); ASSERT0(succ); for (IR * ir = BB_first_ir(succ); ir != NULL; ir = BB_next_ir(succ)) { if (ir->is_phi()) { return true; } } } return false; }
void IRBB::dump(Region * ru) { if (g_tfile == NULL) { return; } g_indent = 0; fprintf(g_tfile, "\n----- BB%d ------", BB_id(this)); if (get_lab_list().get_elem_count() > 0) { fprintf(g_tfile, "\nLABEL:"); dumpBBLabel(get_lab_list(), g_tfile); } //Attributes fprintf(g_tfile, "\nATTR:"); if (BB_is_entry(this)) { fprintf(g_tfile, "entry_bb "); } //if (BB_is_exit(this)) { // fprintf(g_tfile, "exit_bb "); //} if (BB_is_fallthrough(this)) { fprintf(g_tfile, "fall_through "); } if (BB_is_target(this)) { fprintf(g_tfile, "branch_target "); } //IR list fprintf(g_tfile, "\nSTMT NUM:%d", getNumOfIR()); g_indent += 3; TypeMgr * dm = ru->get_type_mgr(); for (IR * ir = BB_first_ir(this); ir != NULL; ir = BB_irlist(this).get_next()) { ASSERT0(IR_next(ir) == NULL && IR_prev(ir) == NULL); ASSERT0(ir->get_bb() == this); dump_ir(ir, dm, NULL, true, true, false); } g_indent -= 3; fprintf(g_tfile, "\n"); fflush(g_tfile); }
//Control flow struct optimizations. //Transform follow struct to do-while loop // // LABEL: // IR-List // IF DET // GOTO LABEL // ...(DEAD CODE) // ELSE // FALSE-PART // ENDIF // //is replace by // // DO { // IR-List // } WHILE DET // FALSE-PART bool IR_CFS_OPT::transformToDoWhile(IR ** head, IR * ir) { ASSERT(head != NULL && *head != NULL, ("invalid parameter")); if (!ir->is_lab()) { return false; } for (IR * t = ir; t != NULL; t = t->get_next()) { if (!t->is_if()) { continue; } if (IF_truebody(t) != NULL && IF_truebody(t)->is_goto() && isSameLabel(LAB_lab(ir), GOTO_lab(IF_truebody(t)))) { //Start transform. IR * dowhile = m_ru->allocIR(IR_DO_WHILE); LOOP_det(dowhile) = m_ru->dupIRTree(LOOP_det(t)); IR * if_stmt = t; t = ir->get_next(); while (t != NULL && t != if_stmt) { IR * c = t; t = t->get_next(); xcom::remove(head, c); xcom::add_next(&LOOP_body(dowhile), c); } ASSERT(t == if_stmt, ("illegal IR layout")); xcom::remove(head, if_stmt); if (IF_falsebody(if_stmt)) { xcom::add_next(&dowhile, IF_falsebody(if_stmt)); IF_falsebody(if_stmt) = NULL; } xcom::insertafter(&ir, dowhile); m_ru->freeIRTree(if_stmt); //free IF xcom::remove(head, ir); m_ru->freeIRTree(ir); //free LABEL return true; } } return false; }
//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); }
//Collect all USE, where USE is IR expression. void MDSSAInfo::collectUse( OUT DefSBitSetCore & set, IN UseDefMgr * usedefmgr, IN DefMiscBitSetMgr * bsmgr) { ASSERT0(usedefmgr && bsmgr); SEGIter * iter = NULL; Region * rg = usedefmgr->getRegion(); for (INT i = getVOpndSet()->get_first(&iter); i >= 0; i = getVOpndSet()->get_next(i, &iter)) { VMD * vopnd = (VMD*)usedefmgr->getVOpnd(i); ASSERT0(vopnd && vopnd->is_md()); SEGIter * vit = NULL; for (INT i2 = vopnd->getOccSet()->get_first(&vit); i2 >= 0; i2 = vopnd->getOccSet()->get_next(i2, &vit)) { IR * use = rg->getIR(i2); ASSERT0(use && (use->isMemoryRef() || use->is_id())); set.bunion(use->id(), *bsmgr); } } }
void shutter::capture(void) { if(cable_connected == 0) { ir.shutterNow(); // ir.shutterDelayed(); } full(); _delay_ms(75); off(); ir_shutter_state = 0; shutter_state = 0; }
void settings_load() { eeprom_read_block((void*)&conf, &conf_eep, sizeof(settings)); if(conf.lcdContrast > 0xf || conf.lcdContrast < 0x1) conf.lcdContrast = 0x8; if(conf.lcdCoefficent > 0x7 || conf.lcdCoefficent < 0x3) conf.lcdCoefficent = 0x7; if(conf.lcdBias > 0x4 || conf.lcdBias < 0x3) conf.lcdBias = 0x4; if(conf.apertureMin > 100 || conf.apertureMin < 2) conf.apertureMin = 2; lcd.color(conf.lcdColor); ir.init(); ir.make = conf.cameraMake; if(conf.auxPort != AUX_MODE_DISABLED) aux_off(); if(bt.present && !remote.connected) { if(conf.btMode == BT_MODE_SLEEP) bt.sleep(); else bt.advertise(); } }
//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); }
void shutter::half(void) { if(conf.devMode) hardware_flashlight(0); if(cable_connected == 0) { if(bulb && shutter_state) { shutter_state = 0; ir.shutterNow(); } shutter_state = 0; } else { SHUTTER_CLOSE; MIRROR_UP; } }
void shutter::bulbStart(void) { if(cable_connected == 0 && ir_shutter_state != 1) { ir_shutter_state = 1; ir.shutterNow(); // ir.shutterDelayed(); } if(conf.bulbMode == 0) { full(); } else if(conf.bulbMode == 1 && shutter_state != 1) { full(); shutter_state = 1; _delay_ms(75); half(); } }
void shutter::bulbEnd(void) { if(cable_connected == 0 && ir_shutter_state == 1) { ir_shutter_state = 0; ir.shutterNow(); // ir.shutterDelayed(); } if(conf.bulbMode == 0) { off(); } else if(conf.bulbMode == 1 && shutter_state == 1) { full(); shutter_state = 0; _delay_ms(75); off(); } }
void shutter::full(void) { if(conf.devMode) hardware_flashlight(1); if(cable_connected == 0) { if(bulb) shutter_state = 1; else shutter_state = 0; ir.shutterNow(); } else if(conf.bulbMode == 0) { MIRROR_UP; SHUTTER_OPEN; } else if(conf.bulbMode == 1 && shutter_state == 0) { MIRROR_UP; SHUTTER_OPEN; shutter_state = 1; _delay_ms(50); half(); } }
//Duplicate and add an operand that indicated by opnd_pos at phi stmt //in one of bb's successors. void IRBB::dupSuccessorPhiOpnd(CFG<IRBB, IR> * cfg, Region * ru, UINT opnd_pos) { IR_CFG * ircfg = (IR_CFG*)cfg; Vertex * vex = ircfg->get_vertex(BB_id(this)); ASSERT0(vex); for (EdgeC * out = VERTEX_out_list(vex); out != NULL; out = EC_next(out)) { Vertex * succ_vex = EDGE_to(EC_edge(out)); IRBB * succ = ircfg->get_bb(VERTEX_id(succ_vex)); ASSERT0(succ); for (IR * ir = BB_first_ir(succ); ir != NULL; ir = BB_next_ir(succ)) { if (!ir->is_phi()) { break; } ASSERT0(cnt_list(PHI_opnd_list(ir)) >= opnd_pos); IR * opnd; UINT lpos = opnd_pos; for (opnd = PHI_opnd_list(ir); lpos != 0; opnd = opnd->get_next()) { ASSERT0(opnd); lpos--; } IR * newopnd = ru->dupIRTree(opnd); if (opnd->is_read_pr()) { newopnd->copyRef(opnd, ru); ASSERT0(PR_ssainfo(opnd)); PR_ssainfo(newopnd) = PR_ssainfo(opnd); SSA_uses(PR_ssainfo(newopnd)).append(newopnd); } ((CPhi*)ir)->addOpnd(newopnd); } } }
~CE_Eliminator() { CompileLog* log = _hir->compilation()->log(); if (log != NULL) log->clear_context(); // skip marker if nothing was printed }
bool IR_CFS_OPT::CfsOpt( IN OUT IR ** ir_list, SimpCtx const& sc) { bool change = false; for (IR * ir = *ir_list; ir != NULL;) { if (transformToDoWhile(ir_list, ir)) { change = true; ir = *ir_list; continue; } if (ir->is_if() && transformIf1(ir_list, ir)) { change = true; ir = *ir_list; continue; } if (ir->is_if() && transformIf2(ir_list, ir)) { change = true; ir = *ir_list; continue; } if (ir->is_if() && transformIf3(ir_list, ir)) { change = true; ir = *ir_list; continue; } switch (ir->get_code()) { case IR_IF: if (hoistIf(ir_list, ir)) { change = true; ir = *ir_list; continue; } if (CfsOpt(&IF_truebody(ir), sc)) { change = true; ir = *ir_list; continue; } if (CfsOpt(&IF_falsebody(ir), sc)) { change = true; ir = *ir_list; continue; } break; case IR_DO_WHILE: case IR_WHILE_DO: case IR_DO_LOOP: if (hoistLoop(ir_list, ir)) { change = true; ir = *ir_list; continue; } if (CfsOpt(&LOOP_body(ir), sc)) { change = true; ir = *ir_list; continue; } break; case IR_SWITCH: if (CfsOpt(&SWITCH_body(ir), sc)) { change = true; ir = *ir_list; continue; } break; default:; } //end switch ir = ir->get_next(); } return change; }
//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; }