This patch contains several bug fixes for proactive/aggressive loop fusions.
- Fix successor list in "Do_tail_duplication".
- Fix several compilation seg faults for several corner cases like avoid using
a deleted loop WHIRL;
skip loops that are not flagged LOOP_PRE_DO for normalization in proactive
loop fusion; avoid using list iterator to prevent access to deleted SC nodes
and etc.
- Add a heuristic to turn off level 2 loop fusion if there exists a write to
formal paramters. This is a workaround for a program bug in CPU2006 gameness
that was exposed by level 2 loop fusion.
- Flag pass-by-reference parameters in scalarization to avoid deleting stores
that appear dead but actually not since the variable is passed by referenc
Index: be/opt/opt_proactive.cxx
===================================================================
--- be/opt/opt_proactive.cxx (revision 3617)
+++ be/opt/opt_proactive.cxx (working copy)
@@ -4946,6 +4946,8 @@
MAP_LIST * map_lst;
SC_NODE * sc_blk;
WN * branch_wn;
+ BB_NODE *pred;
+ BB_LIST_ITER bb_iter;
switch (type) {
case SC_LOOP:
@@ -5102,7 +5104,11 @@
if (cfg->Feedback())
cfg->Feedback()->Delete_edge(old_exit->Id(), tmp2->Id());
-
+
+ FOR_ALL_ELEM (pred, bb_iter, Init(tmp2->Pred())) {
+ pred->Set_succ(pred->Succ()->Remove(tmp2, pool));
+ }
+
bb_list = tmp2->Pred();
while (bb_list) {
bb_list = bb_list->Remove(bb_list->Node(), pool);
@@ -5822,15 +5828,16 @@
_local_stack->Push(sc);
}
- SC_NODE * child;
- SC_LIST_ITER sc_iter;
-
- FOR_ALL_ELEM(child, sc_iter, Init(sc->Kids())) {
+ SC_NODE * child = sc->First_kid();
+ SC_NODE * next;
+ while (child) {
+ next = child->Next_sibling();
if (Top_down_trans(child)) {
return FALSE;
}
+ child = next;
}
-
+
BOOL do_restart = FALSE;
if (sc->Type() == SC_LOOP) {
@@ -10427,7 +10434,11 @@
void
PRO_LOOP_EXT_TRANS::Hash_if_conds(SC_NODE * sc)
{
- if (sc->Type() == SC_LOOP) {
+ // Skip loops that are not flagged LOOP_PRE_DO since the
+ // the CFG transformation infrastructure does not support
+ // these loops at this moment.
+ if ((sc->Type() == SC_LOOP)
+ && sc->Loopinfo()->Is_flag_set(LOOP_PRE_DO)) {
sc->Set_next(NULL);
std::pair<SC_NODE *, bool> p_ret = sc->Get_nesting_if();
SC_NODE * sc_if = p_ret.first;
@@ -11265,6 +11276,9 @@
std::pair<SC_NODE *, bool> p_ret = inner->Get_nesting_if();
SC_NODE * sc_n1 = p_ret.first;
SC_NODE * sc_iter = sc_n1;
+
+ if (sc_iter == outer)
+ return FALSE;
while (sc_iter && (sc_iter != outer)) {
if (!sc_iter->Is_well_behaved())
Index: be/opt/opt_cfg.cxx
===================================================================
--- be/opt/opt_cfg.cxx (revision 3618)
+++ be/opt/opt_cfg.cxx (working copy)
@@ -6534,8 +6534,9 @@
BB_NODE * bb_new = Create_and_allocate_bb(BB_GOTO);
SC_NODE * sc_new = Create_sc(SC_BLOCK);
sc_new->Append_bbs(bb_new);
+
+ BB_NODE * bb_head = sc->First_bb();
- BB_NODE * bb_head = sc->Get_bb_rep();
BB_NODE * bb_prev = bb_head->Prev();
BB_LIST_ITER bb_list_iter;
BB_NODE * bb_tmp;
Index: be/lno/outer.cxx
===================================================================
--- be/lno/outer.cxx (revision 3607)
+++ be/lno/outer.cxx (working copy)
@@ -345,8 +345,44 @@
}
return FALSE;
}
-
+// Check whether there exists write to formal parameters in 'writes'.
+static BOOL Has_parm_ref(REF_LIST_STACK * writes)
+{
+ for (int i = 0; i < writes->Elements(); i++) {
+ REFERENCE_ITER w_iter(writes->Bottom_nth(i));
+ for (REFERENCE_NODE * node1 = w_iter.First(); !w_iter.Is_Empty();
+ node1 = w_iter.Next()) {
+ WN * wn_node = node1->Wn;
+ if (wn_node) {
+ OPERATOR opr = WN_operator(wn_node);
+ if (OPERATOR_is_store(opr)) {
+ if (OPERATOR_is_scalar_store(opr)) {
+ if (WN_has_sym(wn_node)) {
+ ST *st = WN_st(wn_node);
+ if ((ST_sclass(st) == SCLASS_FORMAL)
+ || (ST_sclass(st) == SCLASS_FORMAL_REF)) {
+ return TRUE;
+ }
+ }
+ }
+ else {
+ WN * base = WN_array_base(WN_kid(wn_node,1));
+ if (base && WN_has_sym(base)) {
+ ST * st = WN_st(base);
+ if ((ST_sclass(st) == SCLASS_FORMAL)
+ || (ST_sclass(st) == SCLASS_FORMAL_REF)) {
+ return TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return FALSE;
+}
+
static FISSION_FUSION_STATUS Fuse_Outer_Loops(WN** loop1_p, WN** loop2_p,
FIZ_FUSE_INFO* ffi, WN2UINT *wn2ffi,
UINT* fusion_level_io) {
@@ -627,13 +663,34 @@
if (array_ref_count2 == -1)
return Failed;
+ // This is a workaround for Fortran program error that is exposed by
+ // more aggressive loop fusions.
+ if (LNO_Fusion >= 2) {
+ if (Has_parm_ref(writes1))
+ dli1->No_Fusion = 1;
+ else if (Has_parm_ref(writes2))
+ dli2->No_Fusion = 1;
+
+ if (dli1->No_Fusion || dli2->No_Fusion) {
+ if (LNO_Verbose)
+ outer_fusion_verbose_info(srcpos1,srcpos2,
+ "Loops with writes to reference parameter cannot be outer fused.");
+ if (LNO_Analysis)
+ outer_fusion_analysis_info(FAIL,srcpos1,srcpos2,0,0,
+ "Loops with writes to reference paramater cannot be outer fused.");
+ if (LNO_Tlog)
+ outer_fusion_tlog_info(FAIL,srcpos1,srcpos2,0,0,
+ "Loops with writes to reference parameter cannot be outer fused.");
+ return Failed;
+ }
+ }
+
BOOL prefer_fuse = FALSE;
-
if (Do_Aggressive_Fuse) {
// If two loops have many array data dependencies, fusion can enable
scalarization
// to reduce memory bandwith.
if ((dli1->Prefer_Fuse != 1)
- && (Array_Data_Dependence_Count(writes1, reads2) >=
LNO_Fusion_Ddep_Limit))
+ && (Array_Data_Dependence_Count(writes1, reads2) >=
LNO_Fusion_Ddep_Limit))
dli1->Prefer_Fuse = 1;
prefer_fuse = (dli1->Prefer_Fuse == 1) ? TRUE : FALSE;
}
@@ -947,8 +1004,13 @@
if (Move_Adjacent(WN_prev(wn_dep), last_use, TRUE)) {
// Fuse loops starting from wn_dep, and flag No_Fusion bit.
Outer_Loop_Fusion_Walk(wn_dep, ffi, wn2ffi);
- DO_LOOP_INFO * dli_dep = Get_Do_Loop_Info(wn_dep);
- dli_dep->No_Fusion = TRUE;
+ if (WN_operator(wn_dep) == OPR_DO_LOOP) {
+ DO_LOOP_INFO * dli_dep = Get_Do_Loop_Info(wn_dep);
+ dli_dep->No_Fusion = TRUE;
+ }
+ else {
+ DevWarn("Loop may be deleted");
+ }
}
}
}
Index: be/lno/sclrze.cxx
===================================================================
--- be/lno/sclrze.cxx (revision 3607)
+++ be/lno/sclrze.cxx (working copy)
@@ -344,6 +344,18 @@
else
Check_use(st, wn, dep_graph, FALSE);
}
+ // Flag ADDR_TAKEN bit for parameters passed by reference.
+ WN * wn_p = LWN_Get_Parent(wn);
+ if (wn_p && (WN_operator(wn_p) == OPR_PARM)) {
+ INT flag = WN_flag(wn_p);
+ if (flag & WN_PARM_BY_REFERENCE) {
+ int val = Array_Use_Hash->Find(st);
+ val |= ADDR_TAKEN;
+ if (val) {
+ Array_Use_Hash->Find_And_Set(st, val);
+ }
+ }
+ }
}
break;
@@ -716,6 +728,7 @@
}
}
}
+
}
// Given that there is a must dependence between store and load,
------------------------------------------------------------------------------
vRanger cuts backup time in half-while increasing security.
With the market-leading solution for virtual backup and recovery,
you get blazing-fast, flexible, and affordable data protection.
Download your free trial now.
http://p.sf.net/sfu/quest-d2dcopy1
_______________________________________________
Open64-devel mailing list
Open64-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/open64-devel