Author: pallavimathew
Date: 2011-05-24 15:04:01 -0400 (Tue, 24 May 2011)
New Revision: 3625

Modified:
   trunk/osprey/be/lno/simd.cxx
   trunk/osprey/be/lno/small_trips.cxx
   trunk/osprey/be/lno/small_trips.h
   trunk/osprey/be/opt/opt_ssa.cxx
   trunk/osprey/common/com/config_lno.cxx
   trunk/osprey/common/com/config_lno.h
Log:
This patch tries to remove the SIMD raminder loop construct. It handles two 
cases:
1. If the remainder loop has exactly one iteration, remove the loop construct 
(the loop body remains, of course).
2. If the remainder loop has at most one iteration, replace the loop construct 
with if-construct.

This patch also adds flag -LNO:simd_rm_unity_remainder={on|off} to guard these 
changes. By default, the flag is off.

C.R. by Mei Ye.


Modified: trunk/osprey/be/lno/simd.cxx
===================================================================
--- trunk/osprey/be/lno/simd.cxx        2011-05-24 00:25:51 UTC (rev 3624)
+++ trunk/osprey/be/lno/simd.cxx        2011-05-24 19:04:01 UTC (rev 3625)
@@ -91,6 +91,7 @@
 #include "minvariant.h"            // for Minvariant_Removal
 #include "prompf.h"
 #include "simd_util.h"
+#include "small_trips.h"           // for Remove_Unity_Trip_Loop
 
 #define ABS(a) ((a<0)?-(a):(a))
 
@@ -5065,6 +5066,122 @@
   return TRUE;  
 }
 
+// Simd_Remove_Unity_Remainder() is to remove the remainder loop if the number
+// of its iteration is one or at most one.
+//
+// In the case when the iteration number is provably one, the remainder loop
+// construct is removed; otherwise, we guard the remainder loop with 
+// a condition and remove the loop construct.
+//
+// return TRUE iff loop construct is removed.
+//
+static BOOL Simd_Remove_Unity_Remainder 
+    (WN* remainder, BOOL provable_unity, BOOL one_iter_at_most) {
+    
+    if (!LNO_Simd_Rm_Unity_Remainder) 
+        return FALSE;
+
+    // case 1: the remainder loop may have more than one iterations
+    //
+    if (!provable_unity && !one_iter_at_most) {
+        return FALSE;
+    }
+
+    INT64 src_pos = WN_Get_Linenum (remainder);
+
+    // case 2: the remainder loop is provable unity.
+    //
+    if (provable_unity) {
+      WN* wn_first_dumy, *wn_last_dumy;
+      Remove_Unity_Trip_Loop (remainder, FALSE, &wn_first_dumy, 
+                              &wn_last_dumy, adg, Du_Mgr, FALSE);
+      if (debug || LNO_Simd_Verbose) {
+        printf ("SIMD: (%s:%d) remove unity remainder loop\n", 
+                 Src_File_Name, Srcpos_To_Line(src_pos));
+      }
+      return TRUE;
+    }
+
+    // case 3: The remainder loop ain't provable. But, compiler know it 
+    // has at most one iteration.
+    //
+    // Suppose the remander loop is "for (i = LB; i <= UB; i++) {}". 
+    // We guard the loop with "if (LB <= UB)" resulting the as following:
+    //     if (LB <= UB) {
+    //        for (....) {}    
+    //     }
+    // Then Remove_Unity_Trip_Loop() is called to get rid of the loop 
+    // construct. 
+    //
+    
+    // step 1: construct the test-condition
+    // 
+    WN* test = WN_end(remainder);
+    if (SYMBOL (WN_kid0(test)) != SYMBOL(WN_index (remainder))) {
+        // Oops, the condition isn't in the form of "idx < UB"
+        return FALSE;
+    }
+
+    WN* cond = LWN_Copy_Tree (test);
+    LWN_Copy_Def_Use (test, cond, Du_Mgr);
+    LWN_Copy_Frequency_Tree (cond, test);
+
+    // change "idx < UB" to "LB < UB". 
+    //
+    Replace_Ldid_With_Exp_Copy (WN_index (remainder), cond, 
+                                WN_kid0(WN_start (remainder)), Du_Mgr);
+                                
+    // step 2: create empty else-clause
+    //
+    WN* else_clause = WN_CreateBlock ();
+
+    // step 3: create then-clause, and put the remainder in the then clause
+    //
+    WN* then_clause = WN_CreateBlock ();
+    WN* insert_after = WN_prev (remainder);
+    WN* insert_block = LWN_Get_Parent(remainder);
+    FmtAssert((WN_operator(insert_block) == OPR_BLOCK), 
+      ("weird tree encountered"));
+    LWN_Extract_From_Block (remainder);
+    LWN_Insert_Block_Before (then_clause, NULL, remainder);
+
+    // step 4: create the if-construct
+    //
+    WN* if_stmt = LWN_CreateIf (cond, then_clause, else_clause);
+    LWN_Insert_Block_After (insert_block, insert_after, if_stmt);
+
+    // step 5: create IF_INFO for the if-construct
+    //
+    {
+        IF_INFO *ii = CXX_NEW (IF_INFO(&LNO_default_pool, 
+                               TRUE, // contain DO loop
+                               Find_SCF_Inside (remainder, OPC_REGION) != 
NULL), 
+                               &LNO_default_pool);
+        WN_MAP_Set (LNO_Info_Map, if_stmt, (void *)ii);
+
+        DOLOOP_STACK *stack;
+        stack = CXX_NEW (DOLOOP_STACK (&LNO_local_pool), &LNO_local_pool);
+        Build_Doloop_Stack(if_stmt, stack);
+        LNO_Build_If_Access(if_stmt, stack);
+        CXX_DELETE(stack, &LNO_local_pool);
+    }
+
+    // step 6: remove the unity loop
+    //
+    {
+        WN* dummy_first, *dummy_last;
+        Remove_Unity_Trip_Loop (remainder, FALSE, &dummy_first, &dummy_last, 
+                                adg, Du_Mgr, FALSE);
+    }
+
+    if (debug || LNO_Simd_Verbose) {
+        printf ("SIMD: (%s:%d) remainder loop is changed to if-stmt\n", 
+                 Src_File_Name, Srcpos_To_Line(src_pos));
+    }
+
+    return TRUE;
+}
+
 static void Simd_Finalize_Loops(WN *innerloop, WN *remainderloop, INT vect, WN 
*reduction_node)
 {
 
@@ -5333,6 +5450,8 @@
           WN_kid0(loop_start_rloop_tmp));
     }
 
+    BOOL remainder_is_unity = FALSE;
+
     // Bug 2516 - eliminate redundant remainder loop if it is possible to
     // simplify the symbolic (non-constant) expression (loop_end - loop_start).
     // This loop should be eliminated later on but there is no point in
@@ -5347,10 +5466,15 @@
                                 WN_kid1(rloop_end),
                                 WN_kid0(rloop_start));
       WN* simpdiff = WN_Simplify_Tree(diff);
-      if (WN_operator(simpdiff) == OPR_INTCONST &&
-          WN_const_val(simpdiff) < 0)
-        rloop_needed = FALSE;
+      if (WN_operator(simpdiff) == OPR_INTCONST) {
+          if (WN_const_val(simpdiff) < 0)
+            rloop_needed = FALSE;
+         
+          if (WN_const_val(simpdiff) == 0)
+            remainder_is_unity = TRUE;
+      }
     }
+
     // Update def use for new loop end for innerloop
     Simd_Update_Index_Def_Use(innerloop,innerloop,WN_end(innerloop), symbol);
     LWN_Set_Parent(WN_end(innerloop),innerloop);
@@ -5517,6 +5641,11 @@
    
     Simd_Simplify_LB_UB (innerloop, rloop_needed ? remainderloop : NULL, vect);
     adg->Fission_Dep_Update(innerloop, 1);
+
+    if (rloop_needed && (remainder_is_unity || vect == 2) && 
+       LNO_Simd_Rm_Unity_Remainder) {
+      Simd_Remove_Unity_Remainder (remainderloop, remainder_is_unity, TRUE); 
+    }
 }
 
 // Vectorize an innerloop

Modified: trunk/osprey/be/lno/small_trips.cxx
===================================================================
--- trunk/osprey/be/lno/small_trips.cxx 2011-05-24 00:25:51 UTC (rev 3624)
+++ trunk/osprey/be/lno/small_trips.cxx 2011-05-24 19:04:01 UTC (rev 3625)
@@ -71,7 +71,8 @@
 #include "fiz_fuse.h"
 #include "forward.h"
 #include "prompf.h"
- 
+#include "small_trips.h"
+
 #include "ir_reader.h"
 
 //-----------------------------------------------------------------------
@@ -315,7 +316,8 @@
                                   WN** wn_first, 
                                   WN** wn_last, 
                                   ARRAY_DIRECTED_GRAPH16* dg, 
-                                  DU_MANAGER* du)
+                                  DU_MANAGER* du,
+                                  BOOL verify_trip_count)
 {
   // Don't try this on doacross nests. 
   if (Is_Nested_Doacross(wn_loop)) {
@@ -367,9 +369,11 @@
   // If known, there better be 1 iteration
   // It's possible that the caller knows there is 1 even if Iterations
   // isn't smart enough to figure it out
-  INT64 iter = Iterations(wn_loop, &LNO_local_pool);
-  FmtAssert((iter == 1) || (iter == -1),
-    ("Loop not unity trip."));
+  if (verify_trip_count) {
+       INT64 iter = Iterations(wn_loop, &LNO_local_pool);
+       FmtAssert((iter == 1) || (iter == -1),
+               ("Loop not unity trip."));
+  }
 
   // Replace the induction variable with the lower bound.
   WN* kid = NULL;

Modified: trunk/osprey/be/lno/small_trips.h
===================================================================
--- trunk/osprey/be/lno/small_trips.h   2011-05-24 00:25:51 UTC (rev 3624)
+++ trunk/osprey/be/lno/small_trips.h   2011-05-24 19:04:01 UTC (rev 3625)
@@ -50,7 +50,7 @@
 ***
 ***     extern void Remove_Unity_Trip_Loop(WN* wn_loop, BOOL update_access,
 ***      WN** wn_first, WN** wn_last, ARRAY_DIRECTED_GRAPH16* dg, 
-***      DU_MANAGER* du)
+***      DU_MANAGER* du, BOOL verify_trip_count)
 ***
 ***      Remove the unity trip loop 'wdloop'.  If 'update_access',
 ***      update the access vectors, and 'update_do_depths' update the do
@@ -96,12 +96,13 @@
 extern void Remove_Zero_Trip_Loop(WN* wn_loop);
 
 extern void Remove_Unity_Trip_Loop(WN* wn_loop, BOOL update_access,
-  WN** wn_first, WN** wn_last, ARRAY_DIRECTED_GRAPH16* dg, DU_MANAGER* du);
+  WN** wn_first, WN** wn_last, ARRAY_DIRECTED_GRAPH16* dg, DU_MANAGER* du, 
+  BOOL verify_trip_count=TRUE);
 
 extern DOLOOP_STACK* Finalizable_Loops(WN* wn_loop, 
   ARRAY_DIRECTED_GRAPH16* dg, DU_MANAGER* du);
 
-extern WN* Finalize_Loops(WN* func_nd); 
+extern void Finalize_Loops(WN* func_nd); 
 
 extern void Remove_Unity_Trip_Loop_Dep_Update(WN* wn_loop,
   ARRAY_DIRECTED_GRAPH16* dg,

Modified: trunk/osprey/be/opt/opt_ssa.cxx
===================================================================
--- trunk/osprey/be/opt/opt_ssa.cxx     2011-05-24 00:25:51 UTC (rev 3624)
+++ trunk/osprey/be/opt/opt_ssa.cxx     2011-05-24 19:04:01 UTC (rev 3625)
@@ -1604,7 +1604,7 @@
   STMTREP *sr = Find_stmt_containing_chi(chi, 
_opt_stab->Ver_stab_entry(du)->Bb());
   if (_opt_stab->Du_zero_vers(du) ) {
     cr = Get_zero_version_CR(chi->Aux_id(), _opt_stab, du);
-    sr->Set_has_zver();
+    if (sr) sr->Set_has_zver();
   } else {
     cr = Du2cr(_htable, _opt_stab, du, sr);
     cr->Set_flag(CF_DEF_BY_CHI);
@@ -1614,7 +1614,7 @@
   chi->Set_live(TRUE);
   chi->Set_dse_dead(FALSE);
 
-  if (sr->Op() == OPC_OPT_CHI)
+  if (!sr || sr->Op() == OPC_OPT_CHI)
     chi->Set_OPND( Get_zero_version_CR(chi->Aux_id(), _opt_stab, chi->Opnd()));
   else {
     chi->Set_OPND(Revive_phi_chi_opnd(chi->Opnd()));

Modified: trunk/osprey/common/com/config_lno.cxx
===================================================================
--- trunk/osprey/common/com/config_lno.cxx      2011-05-24 00:25:51 UTC (rev 
3624)
+++ trunk/osprey/common/com/config_lno.cxx      2011-05-24 19:04:01 UTC (rev 
3625)
@@ -269,6 +269,7 @@
   FALSE,       /* Simd_Verbose */
   TRUE,         /* Simd_Reduction */
   TRUE,         /* Simd_Avoid_Fusion */
+  FALSE,        /* Simd_Rm_Unity_Remainder */  
   TRUE,         /* Run_hoistif */
   TRUE,                /* Ignore_Feedback */
   TRUE,         /* Run_unswitch */
@@ -489,6 +490,7 @@
   FALSE,       /* Simd_Verbose */
   TRUE,         /* Simd_Reduction */
   TRUE,         /* Simd_Avoid_Fusion */
+  FALSE,         /* Simd_Rm_Unity_Remainder*/
   TRUE,         /* Run_hoistif */
   TRUE,                /* Ignore_Feedback */
   TRUE,         /* Run_unswitch */
@@ -874,6 +876,7 @@
   LNOPT_BOOL ( "simd_verbose",         NULL,   Simd_Verbose ),
   LNOPT_BOOL ( "simd_reduction",       "simd_red",     Simd_Reduction ),
   LNOPT_BOOL ( "simd_avoid_fusion",    NULL,   Simd_Avoid_Fusion ),
+  LNOPT_BOOL ( "simd_rm_unity_remainder", NULL,        
Simd_Rm_Unity_Remainder),
   LNOPT_BOOL ( "hoistif",              NULL,   Run_hoistif ),
   LNOPT_BOOL ( "ignore_feedback",      NULL,   Ignore_Feedback ),
   LNOPT_BOOL ( "unswitch",             NULL,   Run_unswitch ),

Modified: trunk/osprey/common/com/config_lno.h
===================================================================
--- trunk/osprey/common/com/config_lno.h        2011-05-24 00:25:51 UTC (rev 
3624)
+++ trunk/osprey/common/com/config_lno.h        2011-05-24 19:04:01 UTC (rev 
3625)
@@ -321,6 +321,7 @@
   BOOL           Simd_Verbose;
   BOOL           Simd_Reduction;
   BOOL           Simd_Avoid_Fusion;
+  BOOL    Simd_Rm_Unity_Remainder;
   BOOL    Run_hoistif;
   BOOL    Ignore_Feedback;
   BOOL    Run_unswitch;
@@ -571,6 +572,7 @@
 #define LNO_Simd_Verbose               Current_LNO->Simd_Verbose
 #define LNO_Simd_Reduction             Current_LNO->Simd_Reduction
 #define LNO_Simd_Avoid_Fusion          Current_LNO->Simd_Avoid_Fusion
+#define LNO_Simd_Rm_Unity_Remainder    Current_LNO->Simd_Rm_Unity_Remainder
 #define LNO_Run_hoistif                 Current_LNO->Run_hoistif
 #define LNO_Ignore_Feedback             Current_LNO->Ignore_Feedback
 #define LNO_Run_Unswitch                Current_LNO->Run_unswitch


------------------------------------------------------------------------------
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