Author: yug Date: 2010-10-20 08:00:35 -0400 (Wed, 20 Oct 2010) New Revision: 3379
Modified: trunk/osprey/be/opt/opt_cfg.cxx trunk/osprey/be/opt/opt_cfg.h trunk/osprey/be/opt/opt_dce.cxx trunk/osprey/common/com/config_wopt.cxx trunk/osprey/common/com/config_wopt.h Log: Open64's always bottom-test loop form (inversioned) are not code-size saving for those while-dos and do-loops with big condition and small body. So, we design a heuristic to filter out those cases and do normal condition headed loop lowering Modified: trunk/osprey/be/opt/opt_cfg.cxx =================================================================== --- trunk/osprey/be/opt/opt_cfg.cxx 2010-10-20 03:46:11 UTC (rev 3378) +++ trunk/osprey/be/opt/opt_cfg.cxx 2010-10-20 12:00:35 UTC (rev 3379) @@ -99,6 +99,7 @@ #include "opt_ssa.h" #include "opt_tail.h" #include "w2op.h" +#include "wn_tree_util.h" CFG::CFG(MEM_POOL *pool, MEM_POOL *lpool) : _bb_vec(pool), @@ -2815,6 +2816,93 @@ // it's added to. // ==================================================================== + + +BOOL CFG::bottom_test_loop(WN* scf_loop){ + + Is_True(scf_loop != NULL,("NULL passed to bottom_test_loop\n")); + + const OPCODE opc = WN_opcode(scf_loop); + const OPERATOR opr = OPCODE_operator(opc); + + Is_True(opr == OPR_WHILE_DO || opr == OPR_DO_LOOP, + ("%s not supported, only handle OPR_WHILE_DO or OPR_DO_LOOP\n",OPCODE_name(opc))); + + WN *do_loopinfo = NULL; + WN *do_tripcount = NULL; + + // for const tripcount(>0) do_loop , we always do bottom_test_loop + if ( (opr == OPR_DO_LOOP) && + (do_loopinfo = WN_do_loop_info(scf_loop)) && + (do_tripcount = WN_loop_trip(do_loopinfo)) && + (WN_operator(do_tripcount) == OPR_INTCONST) && + (WN_const_val(do_tripcount) > 0)) { + if (Trace()) { + fprintf(TFile,"bottom_test_loop:\n"); + fdump_tree_no_st(TFile,scf_loop); + } + return TRUE; + } + + + WN* loop_condition = (opr == OPR_WHILE_DO) ? WN_while_test(scf_loop) : WN_end(scf_loop); + WN* loop_body = (opr == OPR_WHILE_DO) ? WN_while_body(scf_loop) : WN_do_body(scf_loop) ; + + const OPCODE cond_op = WN_opcode(loop_condition); + const OPCODE body_op = WN_opcode(loop_body); + const OPERATOR opr_body = OPCODE_operator(body_op); + + Is_True(OPCODE_is_expression(cond_op), + ("Bad condition opcode %s\n", + OPCODE_name(cond_op))); + Is_True(opr_body == OPR_BLOCK, + ("Bad Body block opcode %s\n", + OPCODE_name(body_op))); + + WN_TREE_CONTAINER<PRE_ORDER> wcpre(loop_condition); + WN_TREE_CONTAINER<PRE_ORDER> ::iterator wipre; + WN_count wc; + INT32 stmt_count=0; + + for (wipre = wcpre.begin(); wipre != wcpre.end(); ++wipre) + wc(wipre.Wn()); + if (wc.num_nodes >= WOPT_Bottom_Test_Loop_Cond_Limit) { + for ( WN *stmt = WN_first(loop_body); stmt != NULL; stmt = WN_next(stmt) ) { + const OPCODE op_in_body = WN_opcode(stmt); + if( ! OPCODE_is_stmt(op_in_body) ) { + if (Trace()) { + fprintf(TFile,"bottom_test_loop:\n"); + fdump_tree_no_st(TFile,scf_loop); + } + return TRUE; + } + if ( ! OPCODE_has_label(op_in_body)) { + stmt_count++; + if (stmt_count >= WOPT_Bottom_Test_Loop_Body_Limit) { + if (Trace()) { + fprintf(TFile,"bottom_test_loop:\n"); + fdump_tree_no_st(TFile,scf_loop); + } + return TRUE; + } + } + } + if (Trace()) { + fprintf(TFile,"non bottom_test_loop:\n"); + fdump_tree_no_st(TFile,scf_loop); + } + return FALSE; + } + else { + if (Trace()) { + fprintf(TFile,"bottom_test_loop:\n"); + fdump_tree_no_st(TFile,scf_loop); + } + return TRUE; + } +} + + void CFG::Add_one_stmt( WN *wn, END_BLOCK *ends_bb ) { @@ -2930,8 +3018,19 @@ case OPR_DO_LOOP: Create_empty_preheader (wn); - if (Lower_fully()) - Lower_do_loop( wn, ends_bb ); + if (Lower_fully()) { + if ( OPT_Space && WOPT_Bottom_Test_Loop_Check ) { + if ( ! bottom_test_loop(wn) ) { + Add_one_do_loop_stmt( wn, ends_bb ); + } + else { + Lower_do_loop( wn, ends_bb ); + } + } + else { + Lower_do_loop( wn, ends_bb ); + } + } else Add_one_do_loop_stmt( wn, ends_bb ); break; @@ -2939,7 +3038,17 @@ case OPR_WHILE_DO: Create_empty_preheader (wn); if (Lower_fully()) { - Lower_while_do( wn, ends_bb ); + if (OPT_Space && WOPT_Bottom_Test_Loop_Check) { + if ( ! bottom_test_loop(wn)) { + Add_one_while_do_stmt(wn, ends_bb); + } + else { + Lower_while_do( wn, ends_bb ); + } + } + else { + Lower_while_do( wn, ends_bb ); + } } else { Add_one_while_do_stmt( wn, ends_bb ); @@ -5327,7 +5436,11 @@ BB_LOOP *loop = bb->Loop(); if (loop != NULL && loop->Header() == bb) { if (loop->End() != NULL) { - loop->Start()->Set_loop(loop); + if(loop->Start()) + loop->Start()->Set_loop(loop); + else { + Is_True(loop->Is_flag_set(LOOP_PRE_WHILE),("wrong non bottom test loop lowering\n")); + } loop->End()->Set_loop(loop); loop->Body()->Set_loop(loop); if (loop->Step()) @@ -5454,12 +5567,15 @@ loop->Loopback()->Kind() == BB_REGIONEXIT, ("found inconsistent BB_LOOP -- loopback is not BB_GOTO")); } else { - Is_True(loop->Start()->Loop() == loop && + Is_True((loop->Start() == NULL || loop->Start()->Loop() == loop) && loop->End()->Loop() == loop && loop->Body()->Loop() == loop && (loop->Step() == NULL || loop->Step()->Loop() == loop), // loop->Merge()->Loop() == loop, ("found inconsistent BB_LOOP and CFG.")); + if (loop->Start() == NULL) { + Is_True(loop->Is_flag_set(LOOP_PRE_WHILE),("wrong non bottom test loop lowering!\n")); + } } } // verify innermost loop Modified: trunk/osprey/be/opt/opt_cfg.h =================================================================== --- trunk/osprey/be/opt/opt_cfg.h 2010-10-20 03:46:11 UTC (rev 3378) +++ trunk/osprey/be/opt/opt_cfg.h 2010-10-20 12:00:35 UTC (rev 3379) @@ -445,6 +445,8 @@ void LMV_clone_BB_IFINFO (LMV_CFG_ADAPTOR* ); void LMV_clone_frequency (LMV_CFG_ADAPTOR*); + //bottom test loop check + BOOL bottom_test_loop(WN* while_do); // From here on, all are public access functions public: Modified: trunk/osprey/be/opt/opt_dce.cxx =================================================================== --- trunk/osprey/be/opt/opt_dce.cxx 2010-10-20 03:46:11 UTC (rev 3378) +++ trunk/osprey/be/opt/opt_dce.cxx 2010-10-20 12:00:35 UTC (rev 3379) @@ -2806,7 +2806,8 @@ // back out during PRE // NOTE: this also picks up the Trip_count_stmt(). BB_NODE *dohead = loop->Start(); - if ( dohead && dohead->Kind() == BB_DOHEAD ) { + if ( (dohead && loop->Is_flag_set(LOOP_DO) && dohead->Kind() == BB_DOHEAD) || + (dohead && loop->Is_flag_set(LOOP_PRE_DO) && dohead->Kind() == BB_DOSTART) ) { STMTREP_ITER stmt_iter(dohead->Stmtlist()); STMTREP *dohead_stmt; FOR_ALL_NODE( dohead_stmt, stmt_iter, Init() ) { @@ -3775,7 +3776,11 @@ // having a live branch is all that's necessary for a valid loop, // but make sure we keep around interesting blocks if ( _cfg->Lower_fully() ) { - Keep_unreached_bb(bb->Loopstart()); + if (bb->Loopstart()) + Keep_unreached_bb(bb->Loopstart()); + else { + Is_True(bb->Loop()->Is_flag_set(LOOP_PRE_WHILE),("wrong non bottom test loop lowering!\n")); + } Keep_unreached_bb(bb->Loopbody()); Keep_unreached_bb(bb->Loopmerge()); Modified: trunk/osprey/common/com/config_wopt.cxx =================================================================== --- trunk/osprey/common/com/config_wopt.cxx 2010-10-20 03:46:11 UTC (rev 3378) +++ trunk/osprey/common/com/config_wopt.cxx 2010-10-20 12:00:35 UTC (rev 3379) @@ -377,6 +377,9 @@ BOOL WOPT_Enable_Aggressive_Iload_CSE = TRUE; // ignore potential iload vsym aliasing #endif +BOOL WOPT_Bottom_Test_Loop_Check=FALSE; +INT32 WOPT_Bottom_Test_Loop_Cond_Limit=3; +INT32 WOPT_Bottom_Test_Loop_Body_Limit=5; /* ==================================================================== * * Descriptor for the -WOPT option group. @@ -854,5 +857,11 @@ { OVK_BOOL, OV_VISIBLE, TRUE, "aggr_iload_cse", "", 0, 0, 0, &WOPT_Enable_Aggressive_Iload_CSE, NULL }, #endif + { OVK_BOOL, OV_INTERNAL, TRUE, "bottom_test_loop_check", "", + 0, 0, 0, &WOPT_Bottom_Test_Loop_Check, NULL}, + { OVK_INT32, OV_VISIBLE, FALSE, "bottom_test_loop_cond", "", + INT32_MAX, 0, INT32_MAX, &WOPT_Bottom_Test_Loop_Cond_Limit, NULL }, + { OVK_INT32, OV_VISIBLE, FALSE, "bottom_test_loop_body", "", + INT32_MAX, 0, INT32_MAX, &WOPT_Bottom_Test_Loop_Body_Limit, NULL }, { OVK_COUNT } /* List terminator -- must be last */ }; Modified: trunk/osprey/common/com/config_wopt.h =================================================================== --- trunk/osprey/common/com/config_wopt.h 2010-10-20 03:46:11 UTC (rev 3378) +++ trunk/osprey/common/com/config_wopt.h 2010-10-20 12:00:35 UTC (rev 3379) @@ -358,5 +358,9 @@ extern BOOL WOPT_Enable_STR_Short; // whether to assume 16bit IV can cross 16 +extern BOOL WOPT_Bottom_Test_Loop_Check; +extern INT32 WOPT_Bottom_Test_Loop_Cond_Limit; +extern INT32 WOPT_Bottom_Test_Loop_Body_Limit; + #endif /* config_wopt_INCLUDED */ ------------------------------------------------------------------------------ Download new Adobe(R) Flash(R) Builder(TM) 4 The new Adobe(R) Flex(R) 4 and Flash(R) Builder(TM) 4 (formerly Flex(R) Builder(TM)) enable the development of rich applications that run across multiple browsers and platforms. Download your free trials today! http://p.sf.net/sfu/adobe-dev2dev _______________________________________________ Open64-devel mailing list Open64-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/open64-devel