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

Reply via email to