//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; }
/* 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; }
//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; }
/* 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::trans_to_do_while_loop(IR ** head, IR * ir) { IS_TRUE(head != NULL && *head != NULL, ("invalid parameter")); if (ir->is_lab()) { IR * t = ir; LABEL_INFO * li = LAB_lab(ir); while (t != NULL) { if (IR_type(t) == IR_IF) { if (IF_truebody(t) != NULL && IR_type(IF_truebody(t)) == IR_GOTO && is_same_label(LAB_lab(ir), GOTO_lab(IF_truebody(t)))) { //start transform... IR * dowhile = m_ru->new_ir(IR_DO_WHILE); LOOP_det(dowhile) = m_ru->dup_irs(LOOP_det(t)); IR * if_stmt = t; t = IR_next(ir); while (t != NULL && t != if_stmt) { IR * c = t; t = IR_next(t); remove(head, c); add_next(&LOOP_body(dowhile), c); } IS_TRUE(t == if_stmt, ("???")); remove(head, if_stmt); if (IF_falsebody(if_stmt)) { add_next(&dowhile, IF_falsebody(if_stmt)); IF_falsebody(if_stmt) = NULL; } insertafter(&ir, dowhile); m_ru->free_irs(if_stmt); //free IF remove(head, ir); m_ru->free_irs(ir); //free LABEL return true; } } t = IR_next(t); } } return false; }