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