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