Author: meiye Date: 2012-02-01 15:15:09 -0500 (Wed, 01 Feb 2012) New Revision: 3865
Modified: trunk/osprey/be/opt/opt_bb.cxx trunk/osprey/be/opt/opt_proactive.cxx trunk/osprey/be/opt/opt_proactive.h trunk/osprey/be/opt/opt_wn.cxx trunk/osprey/be/vho/vho_lower.cxx trunk/osprey/common/com/wn.cxx trunk/osprey/common/com/wn.h Log: Allow tail duplication of SC_Ifs to enable more if-merging. Enhance extended-proactive-loop-opt phase to remove more bit-operations and if-regions. Minor code-reorg for code sharing. CR:Michael Lai Modified: trunk/osprey/be/opt/opt_bb.cxx =================================================================== --- trunk/osprey/be/opt/opt_bb.cxx 2012-01-30 13:30:05 UTC (rev 3864) +++ trunk/osprey/be/opt/opt_bb.cxx 2012-02-01 20:15:09 UTC (rev 3865) @@ -1640,6 +1640,9 @@ WN * stmt1 = Firststmt(); WN * stmt2 = bb->Firststmt(); + if (!stmt1 || !stmt2) + return FALSE; + while (stmt1 && stmt2) { OPERATOR opr = WN_operator(stmt1); @@ -1650,10 +1653,15 @@ if (WN_Simp_Compare_Trees(WN_kid0(stmt1), WN_kid0(stmt2)) != 0) return FALSE; } - else if ((opr != OPR_LABEL) && (opr != OPR_PRAGMA) - && WN_Simp_Compare_Trees(stmt1, stmt2) != 0) - return FALSE; - + else if ((opr != OPR_LABEL) && (opr != OPR_PRAGMA)) { + if (OPERATOR_is_store(opr)) { + if (!Identical_stmt(stmt1, stmt2)) + return FALSE; + } + else if (WN_Simp_Compare_Trees(stmt1, stmt2) != 0) + return FALSE; + } + stmt1 = WN_next(stmt1); stmt2 = WN_next(stmt2); } Modified: trunk/osprey/be/opt/opt_proactive.cxx =================================================================== --- trunk/osprey/be/opt/opt_proactive.cxx 2012-01-30 13:30:05 UTC (rev 3864) +++ trunk/osprey/be/opt/opt_proactive.cxx 2012-02-01 20:15:09 UTC (rev 3865) @@ -214,6 +214,19 @@ } +// Find the first kid that contains an executable block. +SC_NODE * +SC_NODE:: First_executable_kid() +{ + SC_LIST_ITER iter; + SC_NODE * tmp; + FOR_ALL_ELEM(tmp, iter, Init(kids)) { + if (tmp->First_executable_blk() != NULL) + return tmp; + } + return NULL; +} + // Return next sibling SC_NODE from the same parent. SC_NODE * @@ -237,6 +250,19 @@ return NULL; } +// Return next executable sibling. +SC_NODE * +SC_NODE::Next_executable_sibling() +{ + SC_NODE * sc_iter = Next_sibling(); + while (sc_iter) { + if (sc_iter->First_executable_blk() != NULL) + return sc_iter; + sc_iter = sc_iter->Next_sibling(); + } + return NULL; +} + // Return next SC_NODE in the SC tree that immediately succeeds this SC_NODE in source order. SC_NODE * SC_NODE::Next_in_tree() @@ -315,6 +341,24 @@ return std::pair<SC_NODE *, int> (sc_out, count); } +// Get outermost nesting SC_LOOP and number of nesting loops. +std::pair<SC_NODE *, int> +SC_NODE::Get_outermost_nesting_loop() +{ + SC_NODE * sc_tmp = Parent(); + SC_NODE * outer_loop = NULL; + int nest_level = 0; + while (sc_tmp) { + if (sc_tmp->Type() == SC_LOOP) { + nest_level++; + outer_loop = sc_tmp; + } + sc_tmp = sc_tmp->Parent(); + } + + return std::pair<SC_NODE *, int> (outer_loop, nest_level); +} + // Return closest next sibling SC_NODE of the given type SC_NODE * SC_NODE::Next_sibling_of_type(SC_TYPE match_type) @@ -471,6 +515,35 @@ return NULL; } +// Return the first real statement's containing block in this SC_NODE. + +BB_NODE * +SC_NODE::First_executable_blk() +{ + BB_NODE * bb_tmp = Get_bb_rep(); + if (bb_tmp && (bb_tmp->First_executable_stmt() != NULL)) + return bb_tmp; + + BB_LIST * bb_list = Get_bbs(); + if (bb_list) { + BB_LIST_ITER bb_list_iter(bb_list); + FOR_ALL_ELEM(bb_tmp, bb_list_iter, Init()) { + if (bb_tmp->First_executable_stmt() != NULL) + return bb_tmp; + } + } + + SC_LIST_ITER sc_list_iter(kids); + SC_NODE * sc_tmp; + FOR_ALL_ELEM(sc_tmp, sc_list_iter, Init()) { + bb_tmp = sc_tmp->First_executable_blk(); + if (bb_tmp) + return bb_tmp; + } + + return NULL; +} + // Walk upward in the ancestor sub-tree of this node and look for real nodes that // are not boundary delimiters. SC_NODE * @@ -922,7 +995,7 @@ bb_merge = Merge(); if (bb_head->Is_dom(this) - && bb_merge->Is_postdom(this)) + && bb_merge->Is_postdom(this)) ret_val= TRUE; } break; @@ -1478,7 +1551,7 @@ if (!wn_last) wn_last = wn_tmp; - else + else if (wn_tmp) wn_last = WN_CreateExp2(OPR_ADD, MTYPE_I4, MTYPE_V, wn_last, wn_tmp); CXX_DELETE(l_stk, _pool); @@ -1645,8 +1718,9 @@ SC_LIST_ITER sc_list_iter(this); SC_NODE * tmp; FOR_ALL_ELEM(tmp, sc_list_iter, Init()) { - if (tmp) - fprintf(fp, "%d ",tmp->Id()); + if (tmp) { + fprintf(fp, "%d(%s) ",tmp->Id(), tmp->Type_name_abbr()); + } } fprintf(fp, "\n "); } @@ -2015,6 +2089,7 @@ ALIAS_MANAGER * alias_mgr = _cu->Alias_mgr(); WN * call_wn = NULL; WN * load_wn = NULL; + WN * store_wn = NULL; TY_ITER i ; ST *st; int ii; @@ -2127,10 +2202,16 @@ else if (OPERATOR_is_scalar_load(WN_operator(wn2))) load_wn = wn2; + if (OPERATOR_is_scalar_store(WN_operator(wn1))) + store_wn = wn1; + else if (OPERATOR_is_scalar_store(WN_operator(wn2))) + store_wn = wn2; + if (Aliased(alias_mgr, wn1, wn2) != NOT_ALIASED) { + OPT_STAB * opt_stab = _cu->Opt_stab(); + if (call_wn && load_wn) { AUX_ID load_aux = WN_aux(load_wn); - OPT_STAB * opt_stab = _cu->Opt_stab(); ST * load_st = NULL; if (load_aux && (load_aux <= opt_stab->Lastidx())) @@ -2158,6 +2239,19 @@ else if (load_st && (ST_class(load_st) == CLASS_PREG)) return FALSE; } + else if (call_wn && store_wn) { + AUX_ID store_aux = WN_aux(store_wn); + + if (store_aux && (store_aux <= opt_stab->Lastidx())) { + ST * store_st = opt_stab->Aux_stab_entry(store_aux)->St(); + if (store_st && (ST_class(store_st) == CLASS_PREG) + && (WN_operator(WN_kid(store_wn, 0)) == OPR_INTCONST)) { + // Store of a constant to a preg does not alias with a call. + return FALSE; + } + } + } + return TRUE; } @@ -2420,7 +2514,7 @@ FOR_ALL_ELEM(tmp, kids_iter, Init(sc->Kids())) { this->Top_down_trans(tmp); } - + if (do_analyze_loops && !cfg->Loops_valid()) cfg->Analyze_loops(); } @@ -2740,6 +2834,15 @@ if (opc == OPC_IO) return TRUE; + // Disambiguate bit-reduction operations on the same object. + WN * wn_red1 = WN_get_bit_reduction(wn1); + WN * wn_red2 = WN_get_bit_reduction(wn_root); + if (wn_red1 && wn_red2 && (WN_Simp_Compare_Trees(WN_kid0(wn_red1), WN_kid0(wn_red2)) == 0)) { + if (!Maybe_assigned_expr(wn1, wn_red2) + && !Maybe_assigned_expr(wn_root, wn_red1)) + return FALSE; + } + ALIAS_MANAGER * alias_mgr = _cu->Alias_mgr(); if ((OPCODE_is_store(opc) || OPCODE_is_call(opc)) @@ -3119,6 +3222,10 @@ if (sc1->Parent() != sc2->Parent()) return FALSE; + // Avoid compgoto complication. + if (sc1->Parent()->Find_kid_of_type(SC_COMPGOTO)) + return FALSE; + BB_NODE * rep1 = sc1->Get_bb_rep(); BB_NODE * rep2 = sc2->Get_bb_rep(); @@ -3207,6 +3314,7 @@ BOOL do_flip = FALSE; BOOL can_skip_taildup = FALSE; + SC_NODE * sc_flip = NULL; if (!no_alias) { if (!do_query && (_action == DO_IFFLIP)) { @@ -3319,6 +3427,7 @@ } do_flip = TRUE; + sc_flip = next_sibling; } next_sibling = next_sibling->Next_sibling(); } @@ -3368,10 +3477,26 @@ return TRUE; } - if (do_flip && can_skip_taildup) { - Delete_val_range_maps(); - Do_flip(sc2); - return TRUE; + if (do_flip) { + if (can_skip_taildup) { + Delete_val_range_maps(); + Do_flip(sc2); + return TRUE; + } + + // Instead of tail-duplication, we can sink the flip statement to sc2's merge block + // if it has no dependency on sc2's then-path and else-path. + if (!Has_dependency(sc2->First_kid(), sc_flip) + && !Has_dependency(sc2->Last_kid(), sc_flip)) { + BB_NODE * bb_merge = sc2->Merge(); + BB_NODE * bb_tmp = sc_flip->First_executable_blk(); + WN * wn_flip = bb_tmp->First_executable_stmt(); + bb_tmp->Unlink_stmt(wn_flip); + bb_merge->Prepend_stmt(wn_flip); + Delete_val_range_maps(); + Do_flip(sc2); + return TRUE; + } } // For every sibling between sc1 and sc2 (exclusive), if it has @@ -3379,12 +3504,19 @@ // duplication. BOOL has_dep = FALSE; - BOOL all_blk = TRUE; + BOOL do_tail_dup = TRUE; BOOL has_non_sp = FALSE; - BOOL all_sese = TRUE; next_sibling = sc1->Next_sibling(); + SC_NODE * sc2_next_sibling = sc2->Next_sibling_of_type(SC_IF); int count = 0; + + // Get outermost nesting loop and nesting level. + std::pair<SC_NODE *, int> p_ret; + p_ret = sc1->Get_outermost_nesting_loop(); + SC_NODE * outer_loop = p_ret.first; + int nest_level = p_ret.second; + while (next_sibling && (next_sibling != sc2)) { count++; FOR_ALL_ELEM(tmp, sc_list_iter, Init(sc2->Kids())) { @@ -3395,10 +3527,56 @@ if (!Can_be_speculative(next_sibling)) has_non_sp = TRUE; - if (next_sibling->Type() != SC_BLOCK) - all_blk = FALSE; - else if (!next_sibling->Is_sese()) - all_sese = FALSE; + SC_TYPE type = next_sibling->Type(); + WN * cond1 = next_sibling->Get_cond(); + WN * cond2 = NULL; + + if (!next_sibling->Is_sese()) + do_tail_dup = FALSE; + else if (type == SC_IF) { + BOOL can_merge = FALSE; + if (nest_level >= 2) { + // check whether next_sibling can potentially be if-merged with + // sc2's next sibling. + if (sc2_next_sibling) { + cond2 = sc2_next_sibling->Get_cond(); + if( WN_Simp_Compare_Trees(cond1, cond2) == 0) { + can_merge = TRUE; + WN * wn_tmp = WN_kid0(expr1); + if (wn_tmp && WN_is_bit_op(wn_tmp) && !Is_invariant(outer_loop, WN_kid1(wn_tmp), 0)) { + wn_tmp = WN_kid0(cond2); + if (WN_is_bit_op(wn_tmp) && Is_invariant(outer_loop, WN_kid1(wn_tmp), 0)) { + can_merge = FALSE; + } + } + } + } + if (!can_merge) { + // check whether next_sibling can potentially be if-merged with sc1's children. + for (int i = 0; i < 2; i++) { + SC_NODE * sc_tmp = NULL; + if (i == 0) + sc_tmp = sc1->Find_kid_of_type(SC_THEN)->Find_kid_of_type(SC_IF); + else + sc_tmp = sc1->Find_kid_of_type(SC_ELSE)->Find_kid_of_type(SC_IF); + + while (sc_tmp) { + cond2 = sc_tmp->Get_cond(); + if (WN_Simp_Compare_Trees(cond1, cond2) == 0) { + can_merge = TRUE; + break; + } + sc_tmp = sc_tmp->Next_sibling_of_type(SC_IF); + } + } + } + } + + if (!can_merge) + do_tail_dup = FALSE; + } + else if (type != SC_BLOCK) + do_tail_dup = FALSE; next_sibling = next_sibling->Next_sibling(); } @@ -3418,7 +3596,7 @@ return TRUE; } - if (!all_blk || !all_sese) + if (!do_tail_dup) return FALSE; // Heuristic: in the global pass, avoid tail duplication unless both @@ -3832,6 +4010,7 @@ SC_NODE * cand2 = NULL; SC_NODE * tmp1; SC_NODE * tmp2; + SC_NODE * tmp; SC_LIST * list1; SC_LIST * list2; @@ -3906,6 +4085,20 @@ for (list2 = list1->Next(); list2; list2 = list2->Next()) { tmp2 = list2->Node(); + // Avoid picking candidates in a sequence of loops that are adjacent to each other. + BOOL is_adjacent = TRUE; + tmp = tmp1->Next_sibling(); + while (tmp && (tmp != tmp2)) { + if ((tmp->Type() != SC_LOOP) + || (tmp->Class_id() != tmp1->Class_id())) { + is_adjacent = FALSE; + break; + } + tmp = tmp->Next_sibling(); + } + if (is_adjacent) + continue; + if (!sc_root->Is_pred_in_tree(tmp2)) continue; @@ -3920,7 +4113,11 @@ // Condition 1.1 if (tmp1->Class_id() == tmp2->Class_id()) { SC_NODE * lcp = tmp1->Find_lcp(tmp2); - + + // Avoid compgoto complication. + if (lcp->Find_kid_of_type(SC_COMPGOTO)) + continue; + // Condition 1.3 if (lcp == sc_root) { BB_NODE * bb1 = tmp1->First_bb(); @@ -4120,7 +4317,7 @@ stmt_count *= 2; } else if (next_type == SC_LOOP) { - if (!Get_ext_trans() + if (!Do_ext_trans() || (cand1->Type() != SC_LOOP) || !Can_be_speculative(next) || Has_dependency(cand1, next) @@ -4178,7 +4375,7 @@ _tmp_stack = NULL; _def_map = NULL; _def_cnt_map = NULL; - _ext_trans = FALSE; + _ext_trans = EXT_TRANS_NONE; _current_scope = NULL; } @@ -4296,12 +4493,6 @@ cfg->Feedback()->Move_edge_dest(tmp->Id(), bb_merge2->Id(), first_bb1->Id()); } - FOR_ALL_ELEM(tmp, bb_list_iter, Init(first_bb1->Pred())) { - tmp->Replace_succ(first_bb1, first_bb2); - if (cfg->Feedback()) - cfg->Feedback()->Move_edge_dest(tmp->Id(), first_bb1->Id(), first_bb2->Id()); - } - BB_LIST * bb_list = first_bb2->Pred(); first_bb2->Set_pred(first_bb1->Pred()); first_bb1->Set_pred(bb_merge2->Pred()); @@ -4410,6 +4601,8 @@ BB_NODE * bb_exit = sc2->Exit(); WN * branch_wn = bb_exit->Branch_wn(); FmtAssert(WN_label_number(branch_wn), ("Null label")); + if (first_bb1->Labnam() == 0) + cfg->Add_label_with_wn(first_bb1); WN_label_number(branch_wn) = first_bb1->Labnam(); } else if (sc2_type == SC_IF) { @@ -5394,9 +5587,9 @@ } else if (sc_type == SC_LOOP) { if (sc->Loopinfo()->Is_flag_set(LOOP_PRE_DO)) { - if (Get_ext_trans() - && sc->Is_ctrl_equiv(next) - && !Has_dependency(sc, next)) { + if (sc->Is_ctrl_equiv(next) + && !Has_dependency(sc, next) + && Can_be_speculative(next)) { Do_code_motion(sc, next); } else { @@ -5433,7 +5626,7 @@ if (next != sc2) { Do_code_motion(sc, next); } - else if (Get_ext_trans() && Can_fuse(sc)) { + else if (Do_ext_fusion() && Can_fuse(sc)) { sc = Do_loop_fusion(sc, 1); _loop_list = _loop_list->Remove(sc2, _pool); } @@ -5538,9 +5731,22 @@ PRO_LOOP_FUSION_TRANS::Top_down_trans(SC_NODE * sc_root) { if (sc_root->Has_flag(HAS_SYMM_LOOP)) { - int orig_transform_count = _transform_count; - Nonrecursive_trans(sc_root, TRUE); + int orig_transform_count = _transform_count; + if (!Do_ext_trans() || Do_ext_traverse()) + Nonrecursive_trans(sc_root, TRUE); + + if (Do_ext_fusion()) { + SC_NODE * sc_loop = sc_root->First_kid_of_type(SC_LOOP); + // Attempt loop fusion to expose if-merging opportunities. + while (sc_loop) { + if (Can_fuse(sc_loop)) + sc_loop = Do_loop_fusion(sc_loop, 0); + if (sc_loop) + sc_loop = sc_loop->Next_sibling_of_type(SC_LOOP); + } + } + if (_transform_count > orig_transform_count) { IF_MERGE_TRANS::Top_down_trans(sc_root); Classify_loops(sc_root); @@ -6990,9 +7196,15 @@ // - It is not the first kid of sc. // - Every preceding sibling has no dependency on it. // - Every succeeding sibling is either a loop fusion candidate or an empty block. +// +// In addition, 'sc' should not have compgoto as its immediate child. SC_NODE * PRO_LOOP_INTERCHANGE_TRANS::Find_dist_cand(SC_NODE * sc) { + // avoid compgoto complication. + if (sc->Find_kid_of_type(SC_COMPGOTO)) + return NULL; + SC_NODE * sc_loop = sc->Find_kid_of_type(SC_LOOP); SC_NODE * sc_cur; @@ -7100,6 +7312,7 @@ // 4. Both the outer loop and the inner loop are a do-loop. // 5. The outer loop and the inner loop are interchangable if there was no intervening statement // between them. +// 6. None of its siblings and immediate child has SC_COMPGOTO type. // // Note that the restriction of "SC_BLOCK" is to simplify the low level transformation machinery // (head/tail duplication, code motion etc.). It is not a restriction of the generic proactive @@ -7132,6 +7345,12 @@ BOOL is_invar_outer = FALSE; BOOL is_invar_inner = FALSE; WN * wn_cond = NULL; + + // Rule 6. + if (parent_node->Find_kid_of_type(SC_COMPGOTO)) { + is_cand = FALSE; + break; + } // Rule 1. switch (type) { @@ -8584,10 +8803,6 @@ SC_NODE * sc_then = sc_if->Find_kid_of_type(SC_THEN); SC_NODE * sc_else = sc_if->Find_kid_of_type(SC_ELSE); - - FmtAssert((sc_then->Is_empty() || sc_else->Is_empty()), - ("Expect an empty then-path or else-path")); - SC_NODE * sc_p = sc_if->Parent(); SC_NODE * sc_prev = sc_if->Prev_sibling(); SC_NODE * sc_merge = sc_if->Next_sibling(); @@ -8596,26 +8811,46 @@ BB_NODE * bb_merge = sc_if->Merge(); BB_NODE * bb_first = NULL; BB_NODE * bb_last = NULL; + BB_NODE * bb_tmp; + BB_LIST * bb_list_new; + BB_LIST_ITER bb_list_iter; + MEM_POOL * pool = cfg->Mem_pool(); for (int i = 0; i < 2; i ++) { SC_NODE * sc_kid; - if (i == 0) + if (i == 0) { sc_kid = sc_then; - else + bb_first = sc_kid->First_bb(); + bb_last = sc_kid->Last_bb(); + } + else { sc_kid = sc_else; + BB_NODE * bb_cur = sc_kid->First_bb(); + if (cfg->Feedback()) { + FOR_ALL_ELEM(bb_tmp, bb_list_iter, Init(bb_cur->Pred())) { + cfg->Feedback()->Delete_edge(bb_tmp->Id(), bb_cur->Id()); + } - if (sc_kid->Is_empty()) { - continue; + FOR_ALL_ELEM(bb_tmp, bb_list_iter, Init(bb_last->Succ())) { + cfg->Feedback()->Move_edge_dest(bb_last->Id(), bb_tmp->Id(), bb_first->Id()); + } + } + + bb_last->Remove_succs(pool); + bb_list_new = CXX_NEW(BB_LIST(bb_cur), pool); + bb_last->Set_succ(bb_list_new); + bb_cur->Remove_preds(pool); + bb_list_new = CXX_NEW(BB_LIST(bb_last), pool); + bb_cur->Set_pred(bb_list_new); + bb_cur->Set_prev(bb_last); + bb_last->Set_next(bb_cur); + bb_last = sc_kid->Last_bb(); } SC_NODE * sc_tmp = sc_kid->First_kid(); - while (sc_tmp) { SC_NODE * sc_next = sc_tmp->Next_sibling(); - if (!bb_first) - bb_first = sc_tmp->First_bb(); - bb_last = sc_tmp->Last_bb(); sc_tmp->Unlink(); sc_merge->Insert_before(sc_tmp); sc_tmp = sc_next; @@ -8625,15 +8860,18 @@ sc_if->Unlink(); sc_if->Delete(); - BB_NODE * bb_tmp; - BB_LIST_ITER bb_list_iter; FOR_ALL_ELEM(bb_tmp, bb_list_iter, Init(bb_head->Pred())) { + if (bb_tmp->Is_branch_to(bb_head)) { + WN * branch_wn = bb_tmp->Branch_wn(); + cfg->Add_label_with_wn(bb_first); + WN_label_number(branch_wn) = bb_first->Labnam(); + } + bb_tmp->Replace_succ(bb_head, bb_first); if (cfg->Feedback()) cfg->Feedback()->Move_edge_dest(bb_tmp->Id(), bb_head->Id(), bb_first->Id()); } - - MEM_POOL * pool = cfg->Mem_pool(); + bb_first->Remove_preds(pool); bb_first->Set_pred(bb_head->Pred()); bb_tmp = bb_head->Prev(); @@ -8657,13 +8895,14 @@ } bb_last->Remove_succs(pool); - BB_LIST * bb_list_new = CXX_NEW(BB_LIST(bb_merge), pool); + bb_list_new = CXX_NEW(BB_LIST(bb_merge), pool); bb_last->Set_succ(bb_list_new); bb_merge->Remove_preds(pool); bb_list_new = CXX_NEW(BB_LIST(bb_last), pool); bb_merge->Set_pred(bb_list_new); bb_last->Set_next(bb_merge); bb_merge->Set_prev(bb_last); + Delete_branch(bb_head); if (sc_prev) cfg->Fix_info(sc_prev); @@ -8755,10 +8994,16 @@ // WN_aux(wn) may not be set correctly in the memory references // in the expression trees for IO statements, so we should avoid // traversing these statements. - if (opr == OPR_IO) + if (opr == OPR_IO) { + if (wn_addr) + *wn_addr = NULL; return FALSE; + } + if (OPERATOR_is_load(opr) || OPERATOR_is_store(opr)) { if (OPERATOR_is_scalar_store(opr)) { + if (wn_addr) + *wn_addr = NULL; return FALSE; } else if (OPERATOR_is_scalar_load(opr)) { @@ -8775,25 +9020,47 @@ } sc_iter = sc_iter->Parent(); } - if (!is_index) - return Is_invariant(sc_loop, wn, 0); + if (!is_index) { + if (Is_invariant(sc_loop, wn, 0)) + return TRUE; + else { + if (wn_addr) + *wn_addr = NULL; + return FALSE; + } + } } else { WN * wn_tmp = OPERATOR_is_load(opr) ? WN_kid0(wn) : WN_kid1(wn); - + if ((*wn_addr) == NULL) *wn_addr = wn_tmp; else if (WN_Simp_Compare_Trees(*wn_addr, wn_tmp) != 0) { + if (wn_addr) + *wn_addr = NULL; return FALSE; } + + if (OPERATOR_is_load(opr)) + return TRUE; + else { + if (Get_unique_ref(WN_kid0(wn), sc_loop, wn_addr, sc_loc)) + return TRUE; + else { + if (wn_addr) + *wn_addr = NULL; + return FALSE; + } + } } - - return TRUE; } for (int i = 0; i < WN_kid_count(wn); i++) { - if (!Get_unique_ref(WN_kid(wn, i), sc_loop, wn_addr, sc_loc)) + if (!Get_unique_ref(WN_kid(wn, i), sc_loop, wn_addr, sc_loc)) { + if (wn_addr) + *wn_addr = NULL; return FALSE; + } } return TRUE; @@ -9393,9 +9660,10 @@ return TRUE; } -// Remove consecutive bitop operations that flip the same bit. +// Prune WHIRLs in SC_BLOCKs. +// - Remove consecutive bitop operations that flip the same bit. void -IF_MERGE_TRANS::Remove_redundant_bitops(SC_NODE * sc) +IF_MERGE_TRANS::Prune_block(SC_NODE * sc) { if (sc->Type() == SC_BLOCK) { BB_LIST * bb_list = sc->Get_bbs(); @@ -9436,17 +9704,65 @@ wn_iter = wn_next; } } + + if (wn1) { + // Find next sibling which is a non-empty SC_BLOCK. + SC_NODE * sc2 = sc->Next_sibling_of_type(SC_BLOCK); + while (sc2 && sc2->Is_empty()) { + sc2 = sc2->Next_sibling_of_type(SC_BLOCK); + } + + if (sc2) { + BB_NODE * bb2 = sc2->First_executable_blk(); + if (bb2) { + WN * wn2 = bb2->First_executable_stmt(); + if (wn2 && WN_get_bit_reduction(wn2) + && (WN_Simp_Compare_Trees(WN_kid0(wn1), WN_kid0(wn2)) == 0) + && sc->Is_ctrl_equiv(sc2)) { + SC_NODE * sc_tmp = sc->Next_sibling(); + BOOL has_dep = FALSE; + + Infer_val_range(sc, sc2); + + // Check whether wn1 has dependency on siblings between sc and sc2. + while (sc_tmp && (sc_tmp != sc2)) { + if (Has_dependency(sc_tmp, wn1)) { + has_dep = TRUE; + break; + } + sc_tmp = sc_tmp->Next_sibling(); + } + + Delete_val_range_maps(); + + if (!has_dep) { + bb1->Unlink_stmt(wn1); + bb2->Unlink_stmt(wn2); + WN_Delete(wn1); + WN_Delete(wn2); + } + } + } + } + } } } // Bottom-up prune dead codes for the SC tree rooted at 'sc'. -void +// Return TRUE if 'sc' is unlinked or deleted. +BOOL IF_MERGE_TRANS::Bottom_up_prune(SC_NODE * sc) { SC_NODE * tmp = sc->First_kid(); + SC_NODE * sc_next; + + if ((WOPT_Enable_Pro_Loop_Limit >= 0) + && (Transform_count() >= WOPT_Enable_Pro_Loop_Limit)) + return FALSE; + while (tmp) { // Merge consecutive blocks if possible. - SC_NODE * sc_next = tmp->Next_sibling(); + sc_next = tmp->Next_sibling(); if (tmp->Type() == SC_BLOCK) { SC_NODE * sc_cur = tmp; while (sc_next && (sc_next->Type() == SC_BLOCK)) { @@ -9458,22 +9774,52 @@ } } + // Remove unused label statements. + BB_NODE * bb_rep = tmp->Get_bb_rep(); + if (bb_rep) { + WN * wn_label = bb_rep->Firststmt(); + if (wn_label && (WN_operator(wn_label) == OPR_LABEL)) { + BOOL is_branch_target = FALSE; + BB_NODE * bb_tmp; + BB_LIST_ITER bb_list_iter; + FOR_ALL_ELEM(bb_tmp, bb_list_iter, Init(bb_rep->Pred())) { + WN * wn_branch = bb_tmp->Branch_wn(); + if (wn_branch) { + OPERATOR opr = WN_operator(wn_branch); + if (((opr != OPR_FALSEBR) && (opr != OPR_TRUEBR) + && (opr != OPR_GOTO)) + || bb_tmp->Is_branch_to(bb_rep)) { + is_branch_target = TRUE; + break; + } + } + } + if (!is_branch_target) + bb_rep->Unlink_stmt(wn_label); + } + } + sc_next = tmp->Next_sibling(); - Bottom_up_prune(tmp); + if (Bottom_up_prune(tmp)) + break; tmp = sc_next; } - + SC_TYPE type = sc->Type(); - BOOL do_iter = FALSE; + BOOL unlinked = FALSE; SC_NODE * sc_prev = sc->Prev_sibling(); SC_NODE * sc_parent = sc->Get_real_parent(); + SC_NODE * first_kid = sc->First_kid(); + SC_NODE * last_kid = sc->Last_kid(); CFG * cfg = _cu->Cfg(); - tmp = sc->Parent(); - + SC_NODE * sc_p = sc->Parent(); + IDTYPE id = sc->Id(); + switch (type) { case SC_IF: - if (sc->First_kid()->Is_empty() - && sc->Last_kid()->Is_empty()) { + if (sc->Head()->Executable_stmt_count() == 1) { + if (first_kid->Is_empty() + && last_kid->Is_empty()) { BB_NODE * bb_tmp; BB_LIST_ITER bb_list_iter; BB_NODE * bb_head = sc->Head(); @@ -9485,7 +9831,7 @@ cfg->Add_label_with_wn(bb_merge); WN_label_number(branch_wn) = bb_merge->Labnam(); } - + bb_tmp->Replace_succ(bb_head, bb_merge); if (cfg->Feedback()) cfg->Feedback()->Move_edge_dest(bb_tmp->Id(), bb_head->Id(), bb_merge->Id()); @@ -9498,25 +9844,79 @@ sc->Unlink(); sc->Delete(); - do_iter = TRUE; - if (sc_prev) - cfg->Fix_info(sc_prev); - cfg->Fix_info(sc_parent); - cfg->Invalidate_and_update_aux_info(FALSE); - cfg->Invalidate_loops(); - Inc_transform_count(); + unlinked = TRUE; } - break; + else if (sc->Is_sese()) { + SC_NODE * sc_iter1 = first_kid->First_executable_kid(); + SC_NODE * sc_iter2 = last_kid->First_executable_kid(); + BOOL is_same = TRUE; + + while (sc_iter1 && sc_iter2) { + if (!sc_iter1->Compare_Trees(sc_iter2)) { + is_same = FALSE; + break; + } + sc_iter1 = sc_iter1->Next_executable_sibling(); + sc_iter2 = sc_iter2->Next_executable_sibling(); + } + + BB_NODE * bb_prev; + BB_NODE * bb_iter1; + BB_NODE * bb_iter2; + BB_NODE * bb_merge = sc->Merge(); + + // If sc's then-path and else-path are identical, remove the condition. + if (is_same && (sc_iter1 == NULL) && (sc_iter2 == NULL)) { + sc_iter1 = last_kid->First_kid(); + sc_iter2 = last_kid->Last_kid(); + FmtAssert((first_kid->Last_kid()->Type() == SC_BLOCK), ("Expect a SC_BLOCK.")); + bb_prev = first_kid->Last_bb(); + bb_iter1 = last_kid->First_bb(); + bb_iter2 = last_kid->Last_bb(); + + Do_if_cond_unwrap(sc); + + tmp = sc_iter1; + SC_NODE * sc_end = sc_iter2->Next_sibling(); + while (tmp && (tmp != sc_end)) { + sc_next = tmp->Next_sibling(); + tmp->Unlink(); + tmp->Delete(); + tmp = sc_next; + } + + bb_prev->Set_succ(bb_iter2->Succ()); + bb_merge->Set_pred(bb_iter1->Pred()); + bb_iter2->Set_succ(NULL); + bb_iter1->Set_pred(NULL); + bb_prev->Set_next(bb_merge); + bb_merge->Set_prev(bb_prev); + unlinked = TRUE; + } + } + } + break; case SC_BLOCK: - Remove_redundant_bitops(sc); + Prune_block(sc); break; default: ; } - if (do_iter) { - Bottom_up_prune(tmp); + if (unlinked) { + if (sc_prev) + cfg->Fix_info(sc_prev); + cfg->Fix_info(sc_parent); + cfg->Invalidate_and_update_aux_info(FALSE); + cfg->Invalidate_loops(); + Inc_transform_count(); + + if (_trace) + printf("\n\t\t Prune IF (SC%d)\n", id); + Bottom_up_prune(sc_p); } + + return unlinked; } // Check whether the expression tree rooted at the given wn has the following characteristic: @@ -9586,7 +9986,7 @@ { if ((sc->Type() != SC_IF) || (sc->Head()->Executable_stmt_count() != 1)) return FALSE; - + SC_NODE * sc_p = sc->Get_real_parent(); SC_NODE * sc_prev = sc->Prev_sibling(); @@ -10368,13 +10768,20 @@ PRO_LOOP_EXT_TRANS::Init(); SC_NODE * sc_lcp = Normalize(sc_root); PRO_LOOP_EXT_TRANS::Delete(); + SC_NODE * sc_iter; if (sc_lcp) { IF_MERGE_TRANS::Top_down_trans(sc_lcp); - Set_ext_trans(TRUE); - PRO_LOOP_FUSION_TRANS::Doit(sc_lcp); - PRO_LOOP_EXT_TRANS::Top_down_trans(sc_lcp); + sc_iter = sc_lcp; + Set_ext_trans(EXT_TRANS_TRAVERSE | EXT_TRANS_FUSION); } + else { + sc_iter = sc_root; + Set_ext_trans(EXT_TRANS_FUSION); + } + + PRO_LOOP_FUSION_TRANS::Doit(sc_iter); + PRO_LOOP_EXT_TRANS::Top_down_trans(sc_iter); } // Obtain hash key for 'wn'. @@ -10593,14 +11000,15 @@ sc_last->Set_next(sc); } } - // Only do it for the outermost loop at this time. - return; } - SC_LIST_ITER kids_iter; - SC_NODE * tmp; - FOR_ALL_ELEM(tmp, kids_iter, Init(sc->Kids())) { - Hash_if_conds(tmp); + if (sc->Type() != SC_LOOP) { + // Only do it for the outermost loop at this time. + SC_LIST_ITER kids_iter; + SC_NODE * tmp; + FOR_ALL_ELEM(tmp, kids_iter, Init(sc->Kids())) { + Hash_if_conds(tmp); + } } } @@ -10799,9 +11207,10 @@ // Find a pair of candidates among the child nodes of 'sc' to invoke // extended transformations. Such candidates satisfy the following criteria: // 1. The type is either a SC_IF or a SC_LOOP. -// 2. The pair are separated by a SC_IF with an empty else-path or an empty if-path. +// 2. The pair are separated by a SC_IF with an empty else-path or an empty if-path +// and the SC_IF is a SESE. // 3. The pair are if-merging candidates or loops with same trip counts -// +// 'sc' should not have any immediate child having SC_COMPGOTO type. // If found, return the SC_IF node between the candidates. SC_NODE * @@ -10810,6 +11219,9 @@ *cand1 = NULL; *cand2 = NULL; + if (sc->Find_kid_of_type(SC_COMPGOTO)) + return NULL; + CFG * cfg = Get_cu()->Cfg(); SC_LIST_ITER kids_iter; SC_NODE * tmp; @@ -10819,7 +11231,8 @@ if ((type != SC_IF) || (!tmp->First_kid()->Is_empty() - && !tmp->Last_kid()->Is_empty())) + && !tmp->Last_kid()->Is_empty()) + || !tmp->Is_sese()) continue; SC_NODE * prev = tmp->Prev_sibling(); @@ -10832,7 +11245,8 @@ next = next->Next_sibling(); } - if (!prev || !next || (prev->Type() != next->Type())) + if (!prev || !next || (prev->Type() != next->Type()) + || !prev->Is_sese() || !next->Is_sese()) continue; IF_MERGE_PASS s_pass = Get_pass(); @@ -11047,8 +11461,13 @@ SC_NODE * tmp; SC_NODE * cand1 = NULL; SC_NODE * cand2 = NULL; + SC_TYPE type = sc->Type(); - if (sc->Type() == SC_LP_BODY) { + // Avoid COMPGOTO complication. + if (sc->Find_kid_of_type(SC_COMPGOTO)) + return; + + if (type == SC_LP_BODY) { SC_NODE * sc_if = Find_cand(sc, &cand1, &cand2); while (sc_if) { @@ -11109,9 +11528,16 @@ sc_if = Find_cand(sc, &cand1, &cand2); } } + else if (type == SC_IF) { + if (Bottom_up_prune(sc)) + return; + } - FOR_ALL_ELEM(tmp, kids_iter, Init(sc->Kids())) { - this->Top_down_trans(tmp); + SC_NODE * sc_iter = sc->First_kid(); + while (sc_iter) { + SC_NODE * sc_next = sc_iter->Next_sibling(); + this->Top_down_trans(sc_iter); + sc_iter = sc_next; } } @@ -11172,6 +11598,57 @@ return in_order; } +// Compare this SC_NODE to 'sc', return TRUE if they are identical, return FALSE otherwise. +BOOL +SC_NODE::Compare_Trees(SC_NODE * sc) +{ + if (this == sc) + return TRUE; + + if (Type() != sc->Type()) + return FALSE; + + BB_NODE * bb_tmp1 = Get_bb_rep(); + BB_NODE * bb_tmp2 = sc->Get_bb_rep(); + + if (bb_tmp1 && bb_tmp2 && + !bb_tmp1->Compare_Trees(bb_tmp2)) + return FALSE; + + BB_LIST * bb_list1 = Get_bbs(); + BB_LIST * bb_list2 = sc->Get_bbs(); + + if (bb_list1 && bb_list2) { + BB_LIST_ITER bb_iter1(bb_list1); + BB_LIST_ITER bb_iter2(bb_list2); + bb_tmp1 = bb_iter1.First_elem(); + bb_tmp2 = bb_iter2.First_elem(); + + while ((bb_tmp1 != NULL) + && (bb_tmp2 != NULL)) { + if (!bb_tmp1->Compare_Trees(bb_tmp2)) + return FALSE; + + bb_tmp1 =(!bb_iter1.Is_Empty()) ? bb_iter1.Next_elem() : NULL; + bb_tmp2 =(!bb_iter2.Is_Empty()) ? bb_iter2.Next_elem() : NULL; + } + } + + SC_NODE * tmp1; + SC_NODE * tmp2; + tmp1 = First_executable_kid(); + tmp2 = sc->First_executable_kid(); + + while (tmp1 && tmp2) { + if (!tmp1->Compare_Trees(tmp2)) + return FALSE; + tmp1 = tmp1->Next_executable_sibling(); + tmp2 = tmp2->Next_executable_sibling(); + } + + return ((tmp1 == NULL) && (tmp2 == NULL)); +} + // Do normalization in lock-step for nesting if-conditions of 'sc1' and 'sc2'. // 'action' gives the portion of if-condition tree to apply tree-height-reduction. void @@ -11327,6 +11804,7 @@ // no dependencies on all SC_IF nodes on the successor part of the path (head duplication // legality). If there exists a succeeding sibling, the succeeding sibling must be a SC_BLOCK // or a SC_LOOP. +// 3. None of its sibings and immediate child has SC_COMPGOTO type. BOOL PRO_LOOP_EXT_TRANS::Is_candidate(SC_NODE * outer, SC_NODE * inner) { @@ -11336,11 +11814,17 @@ if (sc_iter == outer) return FALSE; + + if (outer->Find_kid_of_type(SC_COMPGOTO)) + return FALSE; while (sc_iter && (sc_iter != outer)) { if (!sc_iter->Is_well_behaved()) return FALSE; + if (sc_iter->Find_kid_of_type(SC_COMPGOTO)) + return FALSE; + SC_NODE * sc_tmp = sc_iter->Next_sibling(); while (sc_tmp) { if ((sc_tmp->Type() != SC_BLOCK) @@ -11634,8 +12118,8 @@ return wn; } -// Given a 'wn_key' whose value is greater or equal to 'val', -// set up map. +// Set the lower bound for 'wn_key', if 'wn_key' already has a lower bound, +// tighten it if possible. void CFG_TRANS::Set_lo(WN_MAP & map, WN * wn_key, int val) { @@ -11646,7 +12130,7 @@ std::pair<bool,int> p_val = WN_get_val(wn_key, map); val_tmp = p_val.second; if (p_val.first - && (val_tmp < val)) + && (val_tmp > val)) return; } @@ -11705,12 +12189,25 @@ val = p_val.second; if (p_val.first) { - Set_map(_low_map, op1, op2); + wn_tmp = Get_const_wn(val + 1); + Set_map(_low_map, op1, wn_tmp); Infer_val_range(op1, TRUE, TRUE); } break; + case OPR_GE: + op1 = WN_kid(wn, 0); + op2 = WN_kid(wn, 1); + p_val = WN_get_val(op2, _low_map); + val = p_val.second; + + if (p_val.first) { + Set_map(_low_map, op1, op2); + Infer_val_range(op1, TRUE, TRUE); + } + break; + case OPR_LT: op1 = WN_kid(wn, 0); op2 = WN_kid(wn, 1); @@ -11718,7 +12215,8 @@ val = p_val.second; if (p_val.first) { - Set_map(_low_map, op2, op1); + wn_tmp = Get_const_wn(val + 1); + Set_map(_low_map, op2, wn_tmp); Infer_val_range(op2, TRUE, TRUE); } break; @@ -11730,8 +12228,7 @@ val = p_val.second; if (p_val.first) { - wn_tmp = Get_const_wn(val - 1); - Set_map(_low_map, op2, wn_tmp); + Set_map(_low_map, op2, op1); Infer_val_range(op2, TRUE, TRUE); } break; @@ -11860,14 +12357,15 @@ 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); + if (WN_operator(wn_tmp) == OPR_INTCONST) { + if ((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: @@ -11952,7 +12450,7 @@ { SC_NODE * sc_lcp = sc1->Find_lcp(sc2); - if (_invar_map || Get_ext_trans()) { + if (_invar_map || Do_ext_trans()) { _low_map = WN_MAP_Create(_pool); _high_map = WN_MAP_Create(_pool); _def_wn_map = CXX_NEW(MAP(CFG_BB_TAB_SIZE, _pool), _pool); @@ -11964,7 +12462,7 @@ && sc_lcp->Loopinfo()->Is_flag_set(LOOP_PRE_DO)) { Infer_lp_bound_val(sc_lcp); - if (Get_ext_trans()) { + if (Do_ext_trans()) { // Infer value ranges from the loop entry. SC_NODE * sc_body = sc_lcp->Find_kid_of_type(SC_LP_BODY); SC_NODE * sc_tmp = sc_body->First_kid(); @@ -11988,7 +12486,7 @@ sc_lcp = sc_lcp->Parent(); } - if (nesting_lp) { + if (nesting_lp && (sc1->Type() == SC_IF)) { WN * wn_cond = sc1->Get_cond(); Infer_shift_count_val(wn_cond, nesting_lp); } @@ -12153,8 +12651,8 @@ } // Given a SC_IF node 'sc' and a bit-operation expression 'wn', if both the then-path and -// the else-path contain only SC_BLOCKs whose statements are bit reductions on the same object, -// and each path has only one statement that alters the same bit as 'wn', sink that statement to +// the else-path end with a SC_BLOCK whose statements are bit reductions on the same object, +// and there exists only one statement that alters the same bit as 'wn', sink that statement to // the merge block. BOOL CFG_TRANS::Do_flip_tail_merge(SC_NODE * sc, WN * wn) { @@ -12168,10 +12666,13 @@ SC_NODE * tmp; for (int i = 0; i < 2; i++) { tmp = (i == 0) ? sc->First_kid() : sc->Last_kid(); - if (tmp->First_kid() != tmp->Last_kid()) + SC_NODE * first_kid = tmp->First_kid(); + SC_NODE * last_kid = tmp->Last_kid(); + + if (!first_kid->Is_ctrl_equiv(last_kid)) return FALSE; - tmp = tmp->First_kid(); - if (tmp->Type() != SC_BLOCK) + + if (last_kid->Type() != SC_BLOCK) return FALSE; } @@ -12186,11 +12687,11 @@ for (int i = 0; i < 2; i++) { tmp = (i == 0) ? sc->First_kid() : sc->Last_kid(); - tmp = tmp->First_kid(); - + tmp = tmp->Last_kid(); + BB_LIST_ITER bb_list_iter(tmp->Get_bbs()); BB_NODE * bb_iter; - + FOR_ALL_ELEM(bb_iter, bb_list_iter, Init()) { WN * wn_iter; STMT_ITER stmt_iter; Modified: trunk/osprey/be/opt/opt_proactive.h =================================================================== --- trunk/osprey/be/opt/opt_proactive.h 2012-01-30 13:30:05 UTC (rev 3864) +++ trunk/osprey/be/opt/opt_proactive.h 2012-02-01 20:15:09 UTC (rev 3865) @@ -137,12 +137,22 @@ {"NONE", "IF", "THEN", "ELSE", "LOOP", "BLOCK", "FUNC", "LP_START", "LP_COND", "LP_STEP", "LP_BACKEDGE", "LP_BODY", "COMPGOTO", "OTHER"}; +static const char * sc_type_name_abbr[] = + {"", "^", "", "", "o", "-", "", + "", "", "", "", "", "", ""}; + // bit mask. enum SC_NODE_FLAG { HAS_SYMM_LOOP = 0x1 }; +// bit mask for transformations at the extended transformation (EXT) phase. +enum EXT_TRANS_KIND { + EXT_TRANS_NONE = 0, // Do not do EXT. + EXT_TRANS_FUSION = 1, // Do loop fusions at the EXT phase. + EXT_TRANS_TRAVERSE = 2 // Do traversal transformations at the EXT phase. +}; // Structure component nodes. class SC_NODE { @@ -182,6 +192,7 @@ SC_TYPE Type(void) const { return type; } void Set_type(SC_TYPE i) { type = i; } const char * Type_name(void) const { return sc_type_name[type]; } + const char * Type_name_abbr(void) const { return sc_type_name_abbr[type]; } BB_NODE * Get_bb_rep() const { return (SC_type_has_rep(type) ? u1.bb_rep : NULL); } void Set_bb_rep(BB_NODE * i) { @@ -237,13 +248,16 @@ void Insert_after(SC_NODE * sc); SC_NODE * Last_kid(); SC_NODE * First_kid(); + SC_NODE * First_executable_kid(); SC_NODE * Next_sibling(); SC_NODE * Prev_sibling(); SC_NODE * Next_sibling_of_type(SC_TYPE); SC_NODE * Next_in_tree(); + SC_NODE * Next_executable_sibling(); SC_NODE * Get_nesting_if(SC_NODE *); std::pair<SC_NODE *, bool> Get_nesting_if(); std::pair<SC_NODE *, int> Get_outermost_nesting_if(); + std::pair<SC_NODE *, int> Get_outermost_nesting_loop(); SC_NODE * First_kid_of_type(SC_TYPE); BOOL Contains(BB_NODE *); BB_NODE * Then(); @@ -269,6 +283,8 @@ BB_NODE * Last_bb(); // Find first executable statement in this SC_NODE. WN * First_executable_stmt(); + // Find first executable statement's containing block in this SC_NODE. + BB_NODE * First_executable_blk(); BOOL Is_pred_in_tree(SC_NODE *); int Num_of_loops(SC_NODE *, BOOL, BOOL); int Executable_stmt_count(); @@ -279,6 +295,7 @@ WN * Get_cond(); BOOL Is_ctrl_equiv(SC_NODE *); BOOL Get_bounds(WN **, WN **, WN **); + BOOL Compare_Trees(SC_NODE *); }; class SC_LIST : public SLIST_NODE { @@ -355,8 +372,8 @@ MAP * _def_map; // Map symbol auxiliary Id to definition WN *. MAP * _const_wn_map; // map an integer constant to WHIRL. MAP * _def_cnt_map; // hash aux id to def count - BOOL _ext_trans; // do extended transformations. - + int _ext_trans; // do extended transformations. + protected: COMP_UNIT * _cu; BOOL _trace; @@ -469,14 +486,19 @@ BOOL Hoist_succ_blocks(SC_NODE *); SC_NODE * Merge_block(SC_NODE *, SC_NODE *); BOOL Have_same_trip_count(SC_NODE *, SC_NODE *); - BOOL Get_ext_trans() { return _ext_trans; } void Replace_wn(SC_NODE *, WN *, WN *); void Replace_wn(BB_NODE *, WN *, WN *); BOOL Replace_wn(WN *, WN *, WN *); WN * Simplify_wn(WN *); BOOL Do_flip_tail_merge(SC_NODE *, WN *); void Do_flip(SC_NODE *); - + // Whether to do EXT. + BOOL Do_ext_trans() { return (_ext_trans != EXT_TRANS_NONE); } + // Whether to do traverse transformations at the EXT phase. + BOOL Do_ext_traverse() { return ((_ext_trans & EXT_TRANS_TRAVERSE) != 0); } + // Whether to do loop fusions at the EXT phase. + BOOL Do_ext_fusion() { return ((_ext_trans & EXT_TRANS_FUSION) != 0); } + public: void Set_trace(BOOL i) { _trace = i; } void Set_dump(BOOL i) { _dump = i; } @@ -487,7 +509,7 @@ void Do_tail_duplication(SC_NODE *, SC_NODE *); void Hash_def_cnt_map(SC_NODE *); void Init(); - void Set_ext_trans(BOOL in) { _ext_trans = in; } + void Set_ext_trans(int in) { _ext_trans = in; } }; // bit mask for if-merging actions. @@ -519,7 +541,7 @@ void Merge_CFG(SC_NODE *, SC_NODE *); void Merge_SC(SC_NODE *, SC_NODE *); BOOL Is_if_collapse_cand(SC_NODE * sc1, SC_NODE * sc2); - void Remove_redundant_bitops(SC_NODE *); + void Prune_block(SC_NODE *); protected: void Set_region_id(int i) { _region_id = i; } @@ -527,7 +549,7 @@ BOOL Is_candidate(SC_NODE *, SC_NODE *, BOOL); void Clear(void); BOOL Do_reverse_loop_unswitching(SC_NODE *, SC_NODE *, SC_NODE *); - void Bottom_up_prune(SC_NODE *); + BOOL Bottom_up_prune(SC_NODE *); public: void Top_down_trans(SC_NODE * sc); Modified: trunk/osprey/be/opt/opt_wn.cxx =================================================================== --- trunk/osprey/be/opt/opt_wn.cxx 2012-01-30 13:30:05 UTC (rev 3864) +++ trunk/osprey/be/opt/opt_wn.cxx 2012-02-01 20:15:09 UTC (rev 3865) @@ -1856,56 +1856,6 @@ return std::pair<bool,int>(FALSE,0); } -// Walk nodes in the given WHIRL tree, collect operands for ADD operators. -// -// For example, given the following tree, -// I4I4LDID 0 <st 2> -// I4I4LDID 49 <st 80> -// I4SUB -// I4INTCONST -1 (0xffffffffffffffff) -// I4ADD -// -// We will collect two nodes: -// I4I4LDID 0 <st 2> -// I4I4LDID 49 <st 80> -// I4SUB -// -// I4INTCONST -1 (0xffffffffffffffff) - -static STACK<WN *> * -Collect_operands(WN * wn, MEM_POOL * pool) -{ - STACK<WN *> * stack1 = NULL; - STACK<WN *> * stack2 = NULL; - OPERATOR opr = WN_operator(wn); - - if ((opr == OPR_ADD) || (OPERATOR_is_load(opr))) { - stack1 = CXX_NEW(STACK<WN *>(pool), pool); - stack1->Push(wn); - } - - while (stack1 && !stack1->Is_Empty()) { - WN * wn_iter = stack1->Pop(); - OPERATOR opr_iter = WN_operator(wn_iter); - - if (opr_iter == OPR_ADD) { - stack1->Push(WN_kid(wn_iter, 0)); - stack1->Push(WN_kid(wn_iter, 1)); - } - else { - if (stack2 == NULL) - stack2 = CXX_NEW(STACK<WN *>(pool), pool); - - stack2->Push(wn_iter); - } - } - - if (stack1) - CXX_DELETE(stack1, pool); - - return stack2; -} - // Query whether two integral WHIRLs have disjointed value ranges. // Return FALSE if this is not the case or if we can't tell. // lo_map and hi_map are maps from "WN *" to "UNSIGNED long long" that @@ -1967,17 +1917,58 @@ } else { MEM_POOL * pool = Malloc_Mem_Pool; - STACK<WN *> * stack1 = Collect_operands(wn1, pool); - STACK<WN *> * stack2 = Collect_operands(wn2, pool); - STACK<WN *> * stack_tmp = NULL; + STACK<WN *> * add_stk = CXX_NEW(STACK<WN *> (pool), pool); + STACK<WN *> * sub_stk = CXX_NEW(STACK<WN *> (pool), pool); + STACK<WN *> * stack1 = NULL; + STACK<WN *> * stack2 = NULL; + WN * wn_iter; + + Collect_operands(wn1, add_stk, sub_stk); + while (!add_stk->Is_Empty()) { + wn_iter = add_stk->Pop(); + if (!stack1) + stack1 = CXX_NEW(STACK<WN *>(pool), pool); + stack1->Push(wn_iter); + } + + while (!sub_stk->Is_Empty()) { + wn_iter = sub_stk->Pop(); + if (!stack2) + stack2 = CXX_NEW(STACK<WN *>(pool), pool); + + stack2->Push(wn_iter); + } + + Collect_operands(wn2, add_stk, sub_stk); + while (!add_stk->Is_Empty()) { + wn_iter = add_stk->Pop(); + if (!stack2) + stack2 = CXX_NEW(STACK<WN *>(pool), pool); + + stack2->Push(wn_iter); + } + + while (!sub_stk->Is_Empty()) { + wn_iter = sub_stk->Pop(); + if (!stack1) + stack1 = CXX_NEW(STACK<WN *>(pool), pool); + + stack1->Push(wn_iter); + } + + CXX_DELETE(add_stk, pool); + CXX_DELETE(sub_stk, pool); + + STACK<WN *> * stack_tmp1 = NULL; + // Shuffle stack1 and stack2 so that stack1 contains more elements. if ((!stack1 && stack2) || ((stack1 && stack2) && (stack1->Elements() < stack2->Elements()))) { - stack_tmp = stack1; + stack_tmp1 = stack1; stack1 = stack2; - stack2 = stack_tmp; + stack2 = stack_tmp1; } // Evaluate diff of stack1 and stack2. @@ -2003,6 +1994,7 @@ int delta_lo = delta; int delta_hi = delta; std::pair<bool, int> p_val; + stack_tmp1 = CXX_NEW(STACK<WN *>(pool), pool); if (stack2) { for (int i = 0; i < stack2->Elements(); i++) { @@ -2011,16 +2003,52 @@ if (WN_operator(wn2_iter) == OPR_INTCONST) continue; + WN * wn_mul = NULL; BOOL found = FALSE; + + if ((WN_operator(wn2_iter) == OPR_MPY) + && (WN_operator(WN_kid1(wn2_iter)) == OPR_INTCONST)) + wn_mul = WN_kid0(wn2_iter); for (int j = 0; j < stack1->Elements(); j++) { WN * wn1_iter = stack1->Top_nth(j); - if (wn1_iter && (WN_Simp_Compare_Trees(wn1_iter, wn2_iter) == 0)) { + if (WN_Simp_Compare_Trees(wn1_iter, wn2_iter) == 0) { stack1->DeleteTop(j); found = TRUE; break; } + else if (wn_mul + && (WN_Simp_Compare_Trees(wn1_iter, wn_mul) == 0)) { + // Identify expressions like 'x+x' is equal to '2*x'. + int cnt = 0; + WN * wn_tmp; + + while (!stack_tmp1->Is_Empty()) + stack_tmp1->Pop(); + + for (int k = 0; k < stack1->Elements(); k++) { + wn_tmp = stack1->Top_nth(k); + if (WN_Simp_Compare_Trees(wn_mul, wn_tmp) == 0) + cnt++; + else + stack_tmp1->Push(wn_tmp); + } + + if (cnt == WN_const_val(WN_kid1(wn2_iter))) { + // Remove matched elements from 'stack1'. + while (!stack1->Is_Empty()) + stack1->Pop(); + + while (!stack_tmp1->Is_Empty()) { + wn_tmp = stack_tmp1->Pop(); + stack1->Push(wn_tmp); + } + + found = TRUE; + break; + } + } } if (!found) { @@ -2038,6 +2066,7 @@ else { CXX_DELETE(stack1, pool); CXX_DELETE(stack2, pool); + CXX_DELETE(stack_tmp1, pool); return FALSE; } } @@ -2066,6 +2095,7 @@ CXX_DELETE(stack1, pool); if (stack2) CXX_DELETE(stack2, pool); + CXX_DELETE(stack_tmp1, pool); return FALSE; } } @@ -2078,6 +2108,8 @@ if (stack2) CXX_DELETE(stack2, pool); + CXX_DELETE(stack_tmp1, pool); + if ((delta_lo > 0) || (delta_hi < 0)) return TRUE; } Modified: trunk/osprey/be/vho/vho_lower.cxx =================================================================== --- trunk/osprey/be/vho/vho_lower.cxx 2012-01-30 13:30:05 UTC (rev 3864) +++ trunk/osprey/be/vho/vho_lower.cxx 2012-02-01 20:15:09 UTC (rev 3865) @@ -8236,84 +8236,6 @@ return wn; } /* vho_lower_if */ -#ifdef KEY // bug 8581 -// determine if two WHIRL statements are identical; only handle store statements -// for now -static BOOL -Identical_stmt(WN *stmt1, WN *stmt2) -{ - if (stmt1 == NULL || stmt2 == NULL) - return FALSE; - if (WN_opcode(stmt1) != WN_opcode(stmt2)) - return FALSE; - switch(WN_operator(stmt1)) { - case OPR_STID: - if (WN_store_offset(stmt1) != WN_store_offset(stmt2)) - return FALSE; - if (WN_field_id(stmt1) != WN_field_id(stmt2)) - return FALSE; - if (WN_desc(stmt1) != WN_desc(stmt2)) - return FALSE; - if (WN_st_idx(stmt1) != WN_st_idx(stmt2)) - return FALSE; - return WN_Simp_Compare_Trees(WN_kid0(stmt1), WN_kid0(stmt2)) == 0; - case OPR_STBITS: - if (WN_store_offset(stmt1) != WN_store_offset(stmt2)) - return FALSE; - if (WN_bit_offset(stmt1) != WN_bit_offset(stmt2)) - return FALSE; - if (WN_bit_size(stmt1) != WN_bit_size(stmt2)) - return FALSE; - if (WN_st_idx(stmt1) != WN_st_idx(stmt2)) - return FALSE; - return WN_Simp_Compare_Trees(WN_kid0(stmt1), WN_kid0(stmt2)) == 0; - case OPR_ISTORE: - if (WN_store_offset(stmt1) != WN_store_offset(stmt2)) - return FALSE; - if (WN_field_id(stmt1) != WN_field_id(stmt2)) - return FALSE; - if (WN_desc(stmt1) != WN_desc(stmt2)) - return FALSE; - if (WN_Simp_Compare_Trees(WN_kid0(stmt1), WN_kid0(stmt2)) != 0) - return FALSE; - return WN_Simp_Compare_Trees(WN_kid1(stmt1), WN_kid1(stmt2)) == 0; - case OPR_ISTBITS: - if (WN_store_offset(stmt1) != WN_store_offset(stmt2)) - return FALSE; - if (WN_bit_offset(stmt1) != WN_bit_offset(stmt2)) - return FALSE; - if (WN_bit_size(stmt1) != WN_bit_size(stmt2)) - return FALSE; - if (WN_Simp_Compare_Trees(WN_kid0(stmt1), WN_kid0(stmt2)) != 0) - return FALSE; - return WN_Simp_Compare_Trees(WN_kid1(stmt1), WN_kid1(stmt2)) == 0; - case OPR_MSTORE: - if (WN_store_offset(stmt1) != WN_store_offset(stmt2)) - return FALSE; - if (WN_field_id(stmt1) != WN_field_id(stmt2)) - return FALSE; - if (WN_Simp_Compare_Trees(WN_kid0(stmt1), WN_kid0(stmt2)) != 0) - return FALSE; - if (WN_Simp_Compare_Trees(WN_kid1(stmt1), WN_kid1(stmt2)) != 0) - return FALSE; - return WN_Simp_Compare_Trees(WN_kid2(stmt1), WN_kid2(stmt2)) == 0; - case OPR_BLOCK: { - WN *s1 = WN_first(stmt1); - WN *s2 = WN_first(stmt2); - for ( ; ; ) { - if (s1 == NULL && s2 == NULL) - return TRUE; - if (! Identical_stmt(s1, s2)) - return FALSE; - s1 = WN_next(s1); - s2 = WN_next(s2); - } - } - default: ; - } - return FALSE; -} - // If the given IF has a nested IF in the ELSE part with identical THEN stmt: // // IF (A) THEN S1; ELSE { if (B) THEN S1; ELSE S2; } @@ -8433,7 +8355,6 @@ WN_DELETE_Tree(then_wn); return wn; } -#endif static WN * vho_lower_block ( WN * old_block ) Modified: trunk/osprey/common/com/wn.cxx =================================================================== --- trunk/osprey/common/com/wn.cxx 2012-01-30 13:30:05 UTC (rev 3864) +++ trunk/osprey/common/com/wn.cxx 2012-02-01 20:15:09 UTC (rev 3865) @@ -3765,7 +3765,85 @@ return NULL; } +// bug 8581 +// determine if two WHIRL statements are identical; only handle store statements +// for now BOOL +Identical_stmt(WN *stmt1, WN *stmt2) +{ + if (stmt1 == NULL || stmt2 == NULL) + return FALSE; + if (WN_opcode(stmt1) != WN_opcode(stmt2)) + return FALSE; + switch(WN_operator(stmt1)) { + case OPR_STID: + if (WN_store_offset(stmt1) != WN_store_offset(stmt2)) + return FALSE; + if (WN_field_id(stmt1) != WN_field_id(stmt2)) + return FALSE; + if (WN_desc(stmt1) != WN_desc(stmt2)) + return FALSE; + if (WN_st_idx(stmt1) != WN_st_idx(stmt2)) + return FALSE; + return WN_Simp_Compare_Trees(WN_kid0(stmt1), WN_kid0(stmt2)) == 0; + case OPR_STBITS: + if (WN_store_offset(stmt1) != WN_store_offset(stmt2)) + return FALSE; + if (WN_bit_offset(stmt1) != WN_bit_offset(stmt2)) + return FALSE; + if (WN_bit_size(stmt1) != WN_bit_size(stmt2)) + return FALSE; + if (WN_st_idx(stmt1) != WN_st_idx(stmt2)) + return FALSE; + return WN_Simp_Compare_Trees(WN_kid0(stmt1), WN_kid0(stmt2)) == 0; + case OPR_ISTORE: + if (WN_store_offset(stmt1) != WN_store_offset(stmt2)) + return FALSE; + if (WN_field_id(stmt1) != WN_field_id(stmt2)) + return FALSE; + if (WN_desc(stmt1) != WN_desc(stmt2)) + return FALSE; + if (WN_Simp_Compare_Trees(WN_kid0(stmt1), WN_kid0(stmt2)) != 0) + return FALSE; + return WN_Simp_Compare_Trees(WN_kid1(stmt1), WN_kid1(stmt2)) == 0; + case OPR_ISTBITS: + if (WN_store_offset(stmt1) != WN_store_offset(stmt2)) + return FALSE; + if (WN_bit_offset(stmt1) != WN_bit_offset(stmt2)) + return FALSE; + if (WN_bit_size(stmt1) != WN_bit_size(stmt2)) + return FALSE; + if (WN_Simp_Compare_Trees(WN_kid0(stmt1), WN_kid0(stmt2)) != 0) + return FALSE; + return WN_Simp_Compare_Trees(WN_kid1(stmt1), WN_kid1(stmt2)) == 0; + case OPR_MSTORE: + if (WN_store_offset(stmt1) != WN_store_offset(stmt2)) + return FALSE; + if (WN_field_id(stmt1) != WN_field_id(stmt2)) + return FALSE; + if (WN_Simp_Compare_Trees(WN_kid0(stmt1), WN_kid0(stmt2)) != 0) + return FALSE; + if (WN_Simp_Compare_Trees(WN_kid1(stmt1), WN_kid1(stmt2)) != 0) + return FALSE; + return WN_Simp_Compare_Trees(WN_kid2(stmt1), WN_kid2(stmt2)) == 0; + case OPR_BLOCK: { + WN *s1 = WN_first(stmt1); + WN *s2 = WN_first(stmt2); + for ( ; ; ) { + if (s1 == NULL && s2 == NULL) + return TRUE; + if (! Identical_stmt(s1, s2)) + return FALSE; + s1 = WN_next(s1); + s2 = WN_next(s2); + } + } + default: ; + } + return FALSE; +} + +BOOL WN_is_assign(WN * wn) { WN *wn_first = WN_first(wn); Modified: trunk/osprey/common/com/wn.h =================================================================== --- trunk/osprey/common/com/wn.h 2012-01-30 13:30:05 UTC (rev 3864) +++ trunk/osprey/common/com/wn.h 2012-02-01 20:15:09 UTC (rev 3865) @@ -1545,7 +1545,7 @@ extern WN * WN_find_loop_by_index(WN *, ST *, WN_MAP); extern BOOL WN_has_const_diff(WN *, WN *, int *); extern BOOL WN_has_compatible_iter_space(WN *, WN *, int *, int *, BOOL); - +extern BOOL Identical_stmt(WN *, WN *); extern BOOL WN_is_assign(WN *); extern BOOL WN_is_assign_return(WN *); ------------------------------------------------------------------------------ Keep Your Developer Skills Current with LearnDevNow! The most comprehensive online learning library for Microsoft developers is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3, Metro Style Apps, more. Free future releases when you subscribe now! http://p.sf.net/sfu/learndevnow-d2d _______________________________________________ Open64-devel mailing list Open64-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/open64-devel