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
[email protected]
https://lists.sourceforge.net/lists/listinfo/open64-devel