//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; }
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; }