Author: meiye Date: 2011-05-23 13:14:34 -0400 (Mon, 23 May 2011) New Revision: 3615
Modified: trunk/osprey/be/opt/opt_cfg.cxx trunk/osprey/be/opt/opt_cfg.h trunk/osprey/be/opt/opt_proactive.cxx trunk/osprey/be/opt/opt_wn.cxx Log: Add conditional expression to check runtime values to remove conversions to enable if-merging which leads to more loop fusion opportunites. Also add codes to evaluate multiply operations. CR: Sun Chan Modified: trunk/osprey/be/opt/opt_cfg.cxx =================================================================== --- trunk/osprey/be/opt/opt_cfg.cxx 2011-05-20 21:21:26 UTC (rev 3614) +++ trunk/osprey/be/opt/opt_cfg.cxx 2011-05-23 17:14:34 UTC (rev 3615) @@ -6548,6 +6548,93 @@ return sc_new; } +// Insert a SC_IF before 'sc_insert', 'bb_head' is the new SC_IF's head. +SC_NODE * +CFG::Insert_if_before(SC_NODE * sc_insert, BB_NODE * bb_head) +{ + SC_NODE * sc_prev = sc_insert->Prev_sibling(); + BB_NODE * bb_then = Create_and_allocate_bb(BB_GOTO); + BB_NODE * bb_else = Create_and_allocate_bb(BB_GOTO); + BB_NODE * bb_merge = sc_insert->First_bb(); + + bb_head->Append_succ(bb_else, _mem_pool); + bb_head->Append_succ(bb_then, _mem_pool); + bb_then->Append_pred(bb_head, _mem_pool); + bb_else->Append_pred(bb_head, _mem_pool); + bb_then->Append_succ(bb_merge, _mem_pool); + bb_else->Append_succ(bb_merge, _mem_pool); + + BB_NODE * bb_tmp; + BB_LIST_ITER bb_list_iter; + FOR_ALL_ELEM(bb_tmp, bb_list_iter, Init(bb_merge->Pred())) { + bb_tmp->Replace_succ(bb_merge, bb_head); + if (bb_tmp->Is_branch_to(bb_merge)) { + WN * branch_wn = bb_tmp->Branch_wn(); + Add_label_with_wn(bb_head); + WN_label_number(branch_wn) = bb_head->Labnam(); + } + if (Feedback()) + Feedback()->Move_edge_dest(bb_tmp->Id(), bb_merge->Id(), bb_head->Id()); + } + + bb_head->Set_pred(bb_merge->Pred()); + bb_merge->Set_pred(NULL); + bb_merge->Append_pred(bb_then, _mem_pool); + bb_merge->Append_pred(bb_else, _mem_pool); + + bb_tmp = bb_merge->Prev(); + if (bb_tmp) { + bb_tmp->Set_next(bb_head); + bb_head->Set_prev(bb_tmp); + } + + bb_head->Set_next(bb_then); + bb_then->Set_prev(bb_head); + bb_then->Set_next(bb_else); + bb_else->Set_prev(bb_then); + bb_else->Set_next(bb_merge); + bb_merge->Set_prev(bb_else); + + Add_label_with_wn(bb_else); + WN * wn_tmp = bb_head->Branch_wn(); + WN_label_number(wn_tmp) = bb_else->Labnam(); + + SC_NODE * sc_if = Create_sc(SC_IF); + SC_NODE * sc_then = Create_sc(SC_THEN); + SC_NODE * sc_else = Create_sc(SC_ELSE); + SC_NODE * sc_b1 = Create_sc(SC_BLOCK); + SC_NODE * sc_b2 = Create_sc(SC_BLOCK); + + sc_if->Set_bb_rep(bb_head); + sc_b1->Append_bbs(bb_then); + sc_b2->Append_bbs(bb_else); + + BB_IFINFO * ifinfo = bb_head->Ifinfo(); + ifinfo->Set_cond(bb_head); + ifinfo->Set_merge(bb_merge); + ifinfo->Set_then(bb_then); + ifinfo->Set_else(bb_else); + + sc_if->Append_kid(sc_then); + sc_if->Append_kid(sc_else); + sc_then->Set_parent(sc_if); + sc_else->Set_parent(sc_if); + sc_then->Append_kid(sc_b1); + sc_else->Append_kid(sc_b2); + sc_b1->Set_parent(sc_then); + sc_b2->Set_parent(sc_else); + + sc_insert->Insert_before(sc_if); + + if (sc_prev) + Fix_info(sc_prev); + + Fix_info(sc_insert->Get_real_parent()); + Invalidate_and_update_aux_info(FALSE); + Invalidate_loops(); + return sc_if; +} + // Obtained cloned equivalent of given bb BB_NODE * CFG::Get_cloned_bb(BB_NODE * bb) Modified: trunk/osprey/be/opt/opt_cfg.h =================================================================== --- trunk/osprey/be/opt/opt_cfg.h 2011-05-20 21:21:26 UTC (rev 3614) +++ trunk/osprey/be/opt/opt_cfg.h 2011-05-23 17:14:34 UTC (rev 3615) @@ -744,6 +744,7 @@ SC_NODE * Split(SC_NODE *); SC_NODE * Insert_block_after(SC_NODE *); SC_NODE * Insert_block_before(SC_NODE *); + SC_NODE * Insert_if_before(SC_NODE *, BB_NODE *); void Fix_info(SC_NODE *); // Create a new block and allocate it. Modified: trunk/osprey/be/opt/opt_proactive.cxx =================================================================== --- trunk/osprey/be/opt/opt_proactive.cxx 2011-05-20 21:21:26 UTC (rev 3614) +++ trunk/osprey/be/opt/opt_proactive.cxx 2011-05-23 17:14:34 UTC (rev 3615) @@ -10742,6 +10742,7 @@ *cand1 = NULL; *cand2 = NULL; + CFG * cfg = Get_cu()->Cfg(); SC_LIST_ITER kids_iter; SC_NODE * tmp; @@ -10776,6 +10777,92 @@ Set_pass(s_pass); return tmp; } + else { + WN * cond1 = prev->Get_cond(); + WN * cond2 = next->Get_cond(); + if ((WN_operator(cond1) == WN_operator(cond2)) + && (WN_kid_count(cond1) == 2) + && (WN_Simp_Compare_Trees(WN_kid1(cond1), WN_kid1(cond2)) == 0) + && ((WN_operator(cond1) == OPR_NE) || (WN_operator(cond1) == OPR_EQ)) + && (WN_operator(WN_kid1(cond1)) == OPR_INTCONST) + && (WN_const_val(WN_kid1(cond1)) == 0)) { + cond1 = WN_kid0(cond1); + cond2 = WN_kid0(cond2); + // match patterns like: "(a bitop (1 << cnt)) == 0" or + // "(a bitop (1 << cnt)) != 0", + // where 'a' is a 4-byte, one of 'cond1' and 'cond2' is a 8 byte, and + // the other one is a 4-byte. + if ((WN_operator(cond1) == WN_operator(cond2)) + && WN_is_bit_op(cond1)) { + SC_NODE * sc_l = NULL; + SC_NODE * sc_s = NULL; + + if (MTYPE_byte_size(WN_rtype(cond1)) == 8) + sc_l = prev; + else if (MTYPE_byte_size(WN_rtype(cond2)) == 8) + sc_l = next; + + if (MTYPE_byte_size(WN_rtype(cond1)) == 4) + sc_s = prev; + else if (MTYPE_byte_size(WN_rtype(cond2)) == 4) + sc_s = next; + + if (sc_l && sc_s) { + WN * op1 = WN_kid0(cond1); + WN * op2 = WN_kid0(cond2); + op1 = (WN_operator(op1) == OPR_CVT) ? WN_kid0(op1) : op1; + op2 = (WN_operator(op2) == OPR_CVT) ? WN_kid0(op2) : op2; + if ((WN_Simp_Compare_Trees(op1, op2) == 0) + && (MTYPE_byte_size(WN_desc(op1)) == 4)) { + op1 = WN_kid1(cond1); + op2 = WN_kid1(cond2); + if (WN_is_power_of_2(op1) && WN_is_power_of_2(op2) + && (WN_operator(op1) == OPR_SHL)) { + op1 = WN_get_bit_from_expr(op1); + op2 = WN_get_bit_from_expr(op2); + // Create a new SC_IF with comparision expression "if (cnt < 32)" + // and wrap it around 'prev' and 'next'. + if (op1 && op2 && (WN_Simp_Compare_Trees(op1, op2) == 0) + && !Has_dependency(prev, op1) + && !Has_dependency(next, op2)) { + for (int i = 0; i < 2; i++) { + // Create a comparison expression 'if (cnt < 32)'. + WN * wn_tmp = WN_COPY_Tree_With_Map((i == 0) ? op1 : op2); + wn_tmp = WN_CreateExp2(OPR_LT, MTYPE_I4, MTYPE_I4, wn_tmp, + WN_CreateIntconst(OPR_INTCONST, MTYPE_I4, MTYPE_V, 32)); + // Create a CFG block to host 'wn_tmp'. + BB_NODE * bb_new = NULL; + SC_NODE * sc_cur = ( i == 0) ? prev : next; + cfg->Clone_bbs(sc_cur->Head(), sc_cur->Head(), &bb_new, &bb_new, TRUE, 1.0); + WN * wn_branch = bb_new->Laststmt(); + WN_kid0(wn_branch) = wn_tmp; + // Insert a new if-region before 'prev'. + SC_NODE * sc_tmp = cfg->Insert_if_before(sc_cur, bb_new); + Do_tail_duplication(sc_cur, sc_tmp); + if (i == 0) + *cand1 = sc_tmp; + else + *cand2 = sc_tmp; + + if (sc_cur == sc_l) { + sc_tmp = sc_tmp->Find_kid_of_type(SC_THEN); + sc_tmp = sc_tmp->Find_kid_of_type(SC_IF); + FmtAssert(sc_tmp, ("Expect a SC_IF")); + WN * branch_l = sc_tmp->Head()->Branch_wn(); + WN * branch_s = sc_s->Head()->Branch_wn(); + WN_kid0(branch_l) = WN_COPY_Tree_With_Map(WN_kid0(branch_s)); + } + } + Set_pass(s_pass); + return tmp; + } + } + } + } + } + } + } + Set_pass(s_pass); break; case SC_LOOP: @@ -11655,14 +11742,33 @@ WN * op1 = WN_kid0(wn_tmp); WN * op2 = WN_kid1(wn_tmp); int val; - if ((WN_operator(op2) == OPR_INTCONST) - && (OPERATOR_is_scalar_load(WN_operator(op1))) - && Is_invariant(sc_loop, op1, 0) - ) { - val = WN_const_val(op2); + WN * wn_tmp; + if (WN_operator(op2) == OPR_INTCONST) { + val = WN_const_val(op2); if (opr == OPR_ADD) val = val * -1; - Set_lo(_low_map, op1, val); + if (Is_invariant(sc_loop, op1, 0)) { + opr = WN_operator(op1); + switch (opr) { + case OPR_LDID: + Set_lo(_low_map, op1, val); + break; + case OPR_MPY: + wn_tmp = WN_kid1(op1); + if ((WN_operator(wn_tmp) == OPR_INTCONST) + && (val > 0) + && (val < WN_const_val(wn_tmp))) { + // From pattern: c1 * x >= c2, where c1 > 0, c2 > 0 and c1 > c2, + // we can infer that x >= 1. + wn_tmp = WN_kid0(op1); + if (WN_operator(wn_tmp) == OPR_LDID) + Set_lo(_low_map, wn_tmp, 1); + } + break; + default: + ; + } + } } } else if (OPERATOR_is_scalar_load(opr) @@ -11743,6 +11849,7 @@ _low_map = WN_MAP_Create(_pool); _high_map = WN_MAP_Create(_pool); _def_wn_map = CXX_NEW(MAP(CFG_BB_TAB_SIZE, _pool), _pool); + SC_NODE * nesting_lp = NULL; while (sc_lcp) { SC_TYPE type = sc_lcp->Type(); @@ -11769,9 +11876,15 @@ && sc_lcp->Is_pred_in_tree(_current_scope)) { Infer_lp_bound_val(_current_scope); } + nesting_lp = sc_lcp; } sc_lcp = sc_lcp->Parent(); } + + if (nesting_lp) { + WN * wn_cond = sc1->Get_cond(); + Infer_shift_count_val(wn_cond, nesting_lp); + } } } Modified: trunk/osprey/be/opt/opt_wn.cxx =================================================================== --- trunk/osprey/be/opt/opt_wn.cxx 2011-05-20 21:21:26 UTC (rev 3614) +++ trunk/osprey/be/opt/opt_wn.cxx 2011-05-23 17:14:34 UTC (rev 3615) @@ -1801,6 +1801,8 @@ { int val1, val2; OPERATOR opr = WN_operator(wn); + WN * op1; + WN * op2; if (opr == OPR_INTCONST) { *val = WN_const_val(wn); @@ -1820,7 +1822,24 @@ return TRUE; } break; + case OPR_MPY: + op1 = WN_kid(wn, 0); + op2 = WN_kid(wn, 1); + if (WN_get_val(op1, &val1, wn_map) + && WN_get_val(op2, &val2, wn_map) + && (val1 > 0) + && (val2 > 0) + && ((WN_operator(op1) == OPR_INTCONST) + || (WN_operator(op2) == OPR_INTCONST))) { + // Note that we evaluate "c0 * b" based on ""b <= c1" + // Or "b >= c2", where c0, c1, c2 are constants. + // The inferred value can be incorrect if either "c0", + // "c1" or "c2" is non-positive. + *val = val1 * val2; + return TRUE; + } + break; default: ; } ------------------------------------------------------------------------------ What Every C/C++ and Fortran developer Should Know! Read this article and learn how Intel has extended the reach of its next-generation tools to help Windows* and Linux* C/C++ and Fortran developers boost performance applications - including clusters. http://p.sf.net/sfu/intel-dev2devmay _______________________________________________ Open64-devel mailing list Open64-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/open64-devel