Author: shenruifen Date: 2010-08-10 06:07:31 -0400 (Tue, 10 Aug 2010) New Revision: 3309
Modified: trunk/osprey/be/opt/opt_cfg.cxx trunk/osprey/be/opt/opt_cfg.h Log: Rewrite code for Lower_if_stmt (convert if to select) as in the old version . the program-structure is confusion . cannot handle followed case if (a) return 1; else return 2; . cannot handle embbed-select, such as if (p > 0) a = -1; else if (p == 0) a = 0; else a = 5; . to be improved: - Is_simple_expr must be changed for embedded-select for other target. - "CFG::wn_is_assign_return" is too simple to handle complicated case. . Approved by Sun Chan Modified: trunk/osprey/be/opt/opt_cfg.cxx =================================================================== --- trunk/osprey/be/opt/opt_cfg.cxx 2010-08-09 07:29:36 UTC (rev 3308) +++ trunk/osprey/be/opt/opt_cfg.cxx 2010-08-10 10:07:31 UTC (rev 3309) @@ -1209,7 +1209,7 @@ #if defined(TARG_IA32) || defined(TARG_X8664) if (! MTYPE_is_integral(WN_rtype(wn))) return 0; -#elif defined(TARG_SL) +#elif defined(TARG_SL) if (! MTYPE_is_integral(WN_rtype(wn))) return 0; if (opr == OPR_SELECT) @@ -1429,8 +1429,8 @@ return WN_aux(wn1) == WN_aux(wn2); if (opr1 == OPR_STBITS) return WN_aux(wn1) == WN_aux(wn2) && - WN_bit_offset(wn1) == WN_bit_offset(wn2) && - WN_bit_size(wn1) == WN_bit_size(wn2); + WN_bit_offset(wn1) == WN_bit_offset(wn2) && + WN_bit_size(wn1) == WN_bit_size(wn2); // ISTORE/ISTBITS if (WN_store_offset(wn1) != WN_store_offset(wn2)) return FALSE; @@ -1443,59 +1443,65 @@ return Same_addr_expr(WN_kid1(wn1), WN_kid1(wn2)); } -BOOL CFG::Screen_cand(WN* wn, WN* else_wn, WN* then_wn, BOOL empty_else, BOOL empty_then) +BOOL CFG::Screen_cand(WN* wn) { + FmtAssert(WN_operator(wn) == OPR_IF, ("Screen_cand: Not an if stmt")); + WN *then_wn = WN_then(wn); + WN *else_wn = WN_else(wn); + BOOL empty_then = !then_wn || !WN_first(then_wn); + BOOL empty_else = !else_wn || !WN_first(else_wn); + WN *if_test = WN_if_test(wn); WN *stmt = WN_first(empty_then ? else_wn : then_wn); - + if (WN_operator(stmt) == OPR_MSTORE) return TRUE; - + // Get the desc type MTYPE dsctyp = WN_desc(stmt); - + if (dsctyp == MTYPE_M) { // don't generate select for MTYPE_M because there is no register for // MTYPE_M return TRUE; } - + if (! WOPT_Enable_If_Conv_For_Istore && (WN_operator(stmt) == OPR_ISTORE || WN_operator(stmt) == OPR_ISTBITS)) return TRUE; - + if (WN_operator(stmt) == OPR_STID || WN_operator(stmt) == OPR_STBITS) { if (_opt_stab->Is_volatile(WN_aux(stmt))) return TRUE; #ifdef TARG_NVISA - // shared memory is semi-volatile, in that we can't write multiple - // different values at the same time. - if (ST_in_shared_mem(_opt_stab->St(WN_aux(stmt)))) { - DevWarn("skip if-conversion of shared store"); - return TRUE; - } + // shared memory is semi-volatile, in that we can't write multiple + // different values at the same time. + if (ST_in_shared_mem(_opt_stab->St(WN_aux(stmt)))) { + DevWarn("skip if-conversion of shared store"); + return TRUE; + } #endif } else { if (TY_is_volatile(WN_ty(stmt))) return TRUE; } - + if ((WN_operator(stmt) == OPR_STBITS || WN_operator(stmt) == OPR_ISTBITS) && (empty_then || empty_else)) return TRUE; - + if (!OPCODE_Can_Be_Speculative(OPC_I4I4ILOAD)) { if (WN_operator(stmt) == OPR_STID || WN_operator(stmt) == OPR_STBITS) { if (!empty_then) { - ST *st = _opt_stab->St(WN_aux(WN_first(then_wn))); - if (ST_sclass(st) == SCLASS_FORMAL_REF) - return TRUE; // may be storing into read-only data (bug 12 + ST *st = _opt_stab->St(WN_aux(WN_first(then_wn))); + if (ST_sclass(st) == SCLASS_FORMAL_REF) + return TRUE; // may be storing into read-only data (bug 12 } if (!empty_else) { - ST *st = _opt_stab->St(WN_aux(WN_first(else_wn))); - if (ST_sclass(st) == SCLASS_FORMAL_REF) - return TRUE; // may be storing into read-only data (bug 12 + ST *st = _opt_stab->St(WN_aux(WN_first(else_wn))); + if (ST_sclass(st) == SCLASS_FORMAL_REF) + return TRUE; // may be storing into read-only data (bug 12 } } else if (empty_then || empty_else) { @@ -1504,24 +1510,24 @@ // the addr_expr, it is probably means speculation is unsafe, so give up // bug 7845 if (OPERATOR_is_compare(WN_operator(if_test)) && - (Same_addr_expr(WN_kid0(if_test), addr_expr) || - Same_addr_expr(WN_kid1(if_test), addr_expr))) - return TRUE; - + (Same_addr_expr(WN_kid0(if_test), addr_expr) || + Same_addr_expr(WN_kid1(if_test), addr_expr))) + return TRUE; + // because need to generate an extra ILOAD, see that a similar ILOAD has // occurred unconditionally; check currently limited to conditional expr // plus previous 2 statements if (! Has_iload_with_same_addr_expr(addr_expr, if_test)) { - // check previous statement - if (_current_bb->Laststmt() == NULL) - return TRUE; - if (! Has_iload_with_same_addr_expr(addr_expr, _current_bb->Laststmt())) - { - if (WN_prev(_current_bb->Laststmt()) == NULL) - return TRUE; - if (!Has_iload_with_same_addr_expr(addr_expr, WN_prev(_current_bb->Laststmt()))) - return TRUE; - } + // check previous statement + if (_current_bb->Laststmt() == NULL) + return TRUE; + if (! Has_iload_with_same_addr_expr(addr_expr, _current_bb->Laststmt())) + { + if (WN_prev(_current_bb->Laststmt()) == NULL) + return TRUE; + if (!Has_iload_with_same_addr_expr(addr_expr, WN_prev(_current_bb->Laststmt()))) + return TRUE; + } } } } @@ -1544,7 +1550,7 @@ if ( then_wn == NULL ) empty_then = TRUE; else if ( WN_opcode(then_wn) == OPC_BLOCK && - WN_first(then_wn) == NULL ) + WN_first(then_wn) == NULL ) empty_then = TRUE; WN *else_wn = WN_else(wn); @@ -1553,11 +1559,11 @@ if ( else_wn == NULL ) empty_else = TRUE; else if ( WN_opcode(else_wn) == OPC_BLOCK && - WN_first(else_wn) == NULL ) + WN_first(else_wn) == NULL ) empty_else = TRUE; - if (If_conv_criteria_met(wn, else_wn, then_wn, empty_else, empty_then)) { - if (Screen_cand(wn, else_wn, then_wn, empty_else, empty_then)) { + if (Cand_is_select(wn)) { + if (Screen_cand(wn)) { return FALSE; } return TRUE; @@ -1565,9 +1571,76 @@ return FALSE; } +BOOL CFG::wn_is_assign(WN *wn) +{ + WN *wn_first = WN_first(wn); + WN *wn_last = WN_last(wn); + return ((wn_first && (wn_first == wn_last) && OPERATOR_is_store(WN_operator(wn_first))) + || WN_operator(wn) == OPR_SELECT); +} -BOOL CFG::If_conv_criteria_met(WN* wn, WN* else_wn, WN* then_wn, BOOL empty_else, BOOL empty_then) +BOOL CFG::wn_is_assign_return(WN *wn) { + WN *wn_first = WN_first(wn); + WN *wn_last = WN_last(wn); + + if (wn_last) { + WN *wn_last_prev = WN_prev(WN_last(wn)); + return ((WN_operator(wn_last) == OPR_RETURN) + && (wn_first == wn_last_prev) && OPERATOR_is_store(WN_operator(wn_first))); + } else { + return FALSE; + } +} + +BOOL CFG::Cand_is_return_inside_select(WN *wn) +{ + FmtAssert(WN_operator(wn) == OPR_IF, ("Extract_Return: Unexpected WN")); + + WN *then_wn = WN_then(wn); + WN *else_wn = WN_else(wn); + + WN *then_wn_last = WN_last(then_wn); + WN *else_wn_last = WN_last(else_wn); + + if(!(then_wn_last && else_wn_last + && (WN_operator(then_wn_last) == OPR_RETURN) + && (WN_operator(else_wn_last) == OPR_RETURN))) + return FALSE; + + WN *then_wn_prev = WN_prev(then_wn_last); + WN *else_wn_prev = WN_prev(else_wn_last); + + // During the creation of cfg in RVI phase2, the IF-THEN-ELSE block, + // which was converted from SELECT during wn_lower between RVI phase1 + // and phase2, may be converted again which will expect the opt_stab is + // still valid.Return FALSE to stop the convertion. + if(_opt_stab == NULL) + return FALSE; + + /* both is empty, return FALSE */ + if (then_wn_prev == NULL && else_wn_prev == NULL) + return FALSE; + + /* then is not empty and not assign-return, return FALSE */ + if (then_wn_prev && !wn_is_assign_return(then_wn)) { + return FALSE; + } + + /* then is not empty and not assign-return, return FALSE */ + if (else_wn_prev && !wn_is_assign_return(else_wn)) { + return FALSE; + } + + /* then and else have different target, return FALSE */ + if (then_wn_prev && else_wn_prev && !Same_store_target(then_wn_prev, else_wn_prev)) + return FALSE; + + return TRUE; +} + +BOOL CFG::Cand_is_select(WN* wn) +{ // Perform if-conversion for <simple if-then-else> statements. // // <simple if-then-else> :: if (cond) then <block> else <block> ;; @@ -1580,21 +1653,11 @@ // then and else block are non-empty, they stores to // the same variable. // + WN *then_wn = WN_then(wn); + WN *else_wn = WN_else(wn); + BOOL empty_then = !then_wn || !WN_first(then_wn); + BOOL empty_else = !else_wn || !WN_first(else_wn); -#ifdef TARG_MIPS - if (!(WOPT_Enable_Simple_If_Conv && - // bug 5684: deleting branches interferes with branch profiling - ! Instrumentation_Enabled - // is beneficial for ISA supporting cmov - && Is_Target_ISA_M4Plus())) -#else - if (!(WOPT_Enable_Simple_If_Conv && - // bug 5684: deleting branches interferes with branch profiling - ! Instrumentation_Enabled - )) -#endif - return FALSE; - #if defined(TARG_X8664) // do not if-convert if it has either empty then or else part and it if ( // is the only statement in the BB since CG's cflow can be quite effective @@ -1606,9 +1669,9 @@ (WOPT_Enable_Simple_If_Conv <= 1) && #endif (WN_next(wn) == NULL && - !(_current_bb->Firststmt() != NULL && // no previous statement in BB - (_current_bb->Firststmt() != _current_bb->Laststmt() || // prev is LABEL - (WN_operator(_current_bb->Firststmt()) != OPR_LABEL)))) + !(_current_bb->Firststmt() != NULL && // no previous statement in BB + (_current_bb->Firststmt() != _current_bb->Laststmt() || // prev is LABEL + (WN_operator(_current_bb->Firststmt()) != OPR_LABEL)))) ) ) return FALSE; @@ -1621,35 +1684,20 @@ if(_opt_stab == NULL) return FALSE; - if ( - // at least one of the then or else statement is non-empty - (empty_else && empty_then) - ) + // at least one of the then or else statement is non-empty + if (empty_else && empty_then) return FALSE; - - if (!empty_else) { - // either the else-stmt is empty or has one assignment - if (!(((WN_first(else_wn) == WN_last(else_wn)) && - OPERATOR_is_store(WN_operator(WN_first(else_wn)))) || - (WN_operator(else_wn) == OPR_SELECT))) - return FALSE; - } - if ( - // either the then-stmt is empty or has one assignment - (!empty_then && - !(((WN_first(then_wn) == WN_last(then_wn)) && - OPERATOR_is_store(WN_operator(WN_first(then_wn)))) || (WN_operator(then_wn) == OPR_SELECT))) - ) + // either the else-stmt is empty or has one assignment + if (!empty_else && !(wn_is_assign(else_wn))) + return FALSE; + + // either the then-stmt is empty or has one assignment + if (!empty_then && !wn_is_assign(then_wn)) return FALSE; - - if ( - // both the then and else are empty or has one assignment with same lhs - !(empty_else || - empty_then || - Same_store_target(WN_first(else_wn), - WN_first(then_wn))) - ) + + // both the then and else are empty or has one assignment with same lhs + if ((!empty_else && !empty_then && !Same_store_target(WN_first(else_wn), WN_first(then_wn)))) return FALSE; return TRUE; } @@ -1688,519 +1736,226 @@ } #endif -WN* -CFG::Conv_to_select(WN* wn) +WN * +CFG::if_convert(WN *wn) { - if (WN_opcode(wn) == OPC_BLOCK) { - wn = WN_first(wn); - } + Is_True(WN_operator(wn) == OPR_IF, ("CFG::if_convert: Unexpected wn")); + if (!(WOPT_Enable_Simple_If_Conv + // bug 5684: deleting branches interferes with branch profiling + && !Instrumentation_Enabled +#ifdef TARG_MIPS + && Is_Target_ISA_M4Plus() +#endif + )) + return wn; + WN *then_wn = WN_then(wn); - BOOL empty_then = FALSE; - if ( then_wn == NULL ) - empty_then = TRUE; - else if ( WN_opcode(then_wn) == OPC_BLOCK && - WN_first(then_wn) == NULL ) { - empty_then = TRUE; - if (WN_opcode(then_wn) == OPC_BLOCK) { - then_wn = WN_first(then_wn); - } - } + WN *else_wn = WN_else(wn); - WN *else_wn = WN_else(wn); - BOOL empty_else = FALSE; - - if ( else_wn == NULL ) - empty_else = TRUE; - else if ( WN_opcode(else_wn) == OPC_BLOCK && - WN_first(else_wn) == NULL ) { - empty_else = TRUE; - if (WN_opcode(else_wn) == OPC_BLOCK) { - else_wn = WN_first(else_wn); - } + // Handle embedded if-stmt + if (then_wn && WN_first(then_wn) && WN_first(then_wn) == WN_last(then_wn) + && WN_operator(WN_first(then_wn)) == OPR_IF) { + then_wn = if_convert(WN_first(then_wn)); + WN_then(wn) = then_wn; } + if (else_wn && WN_first(else_wn) && WN_first(else_wn) == WN_last(else_wn) + && WN_operator(WN_first(else_wn)) == OPR_IF) { + else_wn = if_convert(WN_first(else_wn)); + WN_else(wn) = else_wn; + } - if (!If_conv_criteria_met(wn, else_wn, then_wn, empty_else, empty_then)) - return NULL; + BOOL if_select = Cand_is_select(wn); + BOOL if_select_return = Cand_is_return_inside_select(wn); - if (Screen_cand(wn, else_wn, then_wn, empty_else, empty_then)) - return NULL; + if (!if_select && !if_select_return) + return wn; - // - // just evaluate the condition? - // - WN *if_test = WN_if_test(wn); - if ( empty_then && empty_else ) { - WN *eval_stmt = WN_CreateEval( if_test ); - return eval_stmt; - } + WN *return_wn = NULL; + WN *wn_bk = WN_COPY_Tree_With_Map(wn); /* back up wn */ - // Get the store from either the first statement of the non-empty block - WN *stmt = WN_first(empty_then ? else_wn : then_wn); + if (if_select_return) { + /* store return_wn */ + return_wn = WN_last(WN_else(wn)); - WN *load = NULL; - WN *store = WN_CopyNode(stmt); - WN_set_map_id(store, WN_map_id(stmt)); - MTYPE dsctyp = WN_desc(stmt); + /* reset then_block */ + WN *then_block = WN_CreateBlock(); + if (WN_prev(WN_last(then_wn))) + WN_INSERT_BlockFirst(then_block, WN_prev(WN_last(then_wn))); + then_wn = then_block; + WN_then(wn) = then_wn; - if (WN_operator(stmt) == OPR_STID || WN_operator(stmt) == OPR_STBITS) - WN_set_aux(store, WN_aux(stmt)); // setting mapping to indicate ST_is_aux + /* reset else_block */ + WN *else_block = WN_CreateBlock(); + if (WN_prev(WN_last(else_wn))) + WN_INSERT_BlockFirst(else_block, WN_prev(WN_last(else_wn))); + else_wn = else_block; + WN_then(wn) = else_block; + } - // Generate a load for the empty block - if (empty_then || empty_else) { - if (WN_operator(stmt) == OPR_STID) { - load = WN_Ldid(dsctyp, - WN_offset(stmt), - (ST_IDX) WN_aux(stmt), - WN_ty(stmt), - WN_field_id(stmt)); - WN_set_aux(load, WN_aux(stmt)); // setting mapping to indicate ST_is_aux - } - else { - MTYPE rtype = WN_rtype(WN_kid0(stmt)); - if (MTYPE_byte_size(rtype) < MTYPE_byte_size(dsctyp)) - rtype = dsctyp;// rtype should never be smaller than dsctyp (bug 6910) - else rtype = Mtype_TransferSign(dsctyp, rtype); - load = WN_CreateIload(OPR_ILOAD, - rtype, - dsctyp, - WN_offset(stmt), TY_pointed(WN_ty(stmt)), - WN_ty(stmt), - Copy_addr_expr(WN_kid1(stmt), _opt_stab->Alias_classification()), - WN_field_id(stmt)); - // copy alias class info from the ISTORE node - _opt_stab->Alias_classification()->Copy_alias_class(stmt, load); - IDTYPE ip_alias_class = WN_MAP32_Get(WN_MAP_ALIAS_CLASS, stmt); - if (ip_alias_class != OPTIMISTIC_AC_ID) - WN_MAP32_Set(WN_MAP_ALIAS_CLASS, load, ip_alias_class); - } - } - WN *then_expr = empty_then ? load : WN_kid0(WN_first(then_wn)); - WN *else_expr = empty_else ? load : WN_kid0(WN_first(else_wn)); - INT lanswer, ranswer; + if (Screen_cand(wn)) + return wn_bk; - // profitability check - if ( -#if !defined(TARG_IA32) && !defined(TARG_X8664) - // The expr in the then-block can be speculated and non-volatile, - // is a const or LDA. - Is_simple_expr(then_expr) && + BOOL empty_then = !then_wn || !WN_first(then_wn); + BOOL empty_else = !else_wn || !WN_first(else_wn); + + // Get the store from either the first statement of the non-empty block + WN *stmt = WN_first(empty_then ? else_wn : then_wn); - // The expr in the else-block can be speculated and non-volatile, - // is a const or LDA. - Is_simple_expr(else_expr) -#else // allow simple expressions of up to 4 leaf nodes - (lanswer = (empty_then ? 1 : Is_simple_expr(then_expr))) && + WN *load = NULL; + WN *store = WN_COPY_Tree_With_Map(stmt); + MTYPE dsctyp = WN_desc(stmt); - (ranswer = (empty_else ? 1 : Is_simple_expr(else_expr))) && + if (WN_operator(stmt) == OPR_STID || WN_operator(stmt) == OPR_STBITS) + WN_set_aux(store, WN_aux(stmt)); // setting mapping to indicate ST_is_aux - (lanswer + ranswer) <= WOPT_Enable_If_Conv_Limit -#endif - ) { + // Generate a load for the empty block + if (empty_then || empty_else) { + if (WN_operator(stmt) == OPR_STID) { + load = WN_Ldid(dsctyp, WN_offset(stmt), (ST_IDX) WN_aux(stmt), + WN_ty(stmt), WN_field_id(stmt)); + WN_set_aux(load, WN_aux(stmt)); // setting mapping to indicate ST_is_aux + } else { + MTYPE rtype = WN_rtype(WN_kid0(stmt)); + if (MTYPE_byte_size(rtype) < MTYPE_byte_size(dsctyp)) + rtype = dsctyp;// rtype should never be smaller than dsctyp (bug 6910) + else + rtype = Mtype_TransferSign(dsctyp, rtype); + #ifdef TARG_SL - - // - // For such case, - // if(p) - // res = p->a - // else - // res = 0; - // if_conversion is skipped as accessing ZERO-address is illegal for SL. - // - WN *cond_kid0 = WN_kid0(if_test); - WN *cond_kid1 = WN_kid1(if_test); - OPERATOR opr = WN_operator(if_test); - - if ((opr == OPR_EQ || opr == OPR_NE || opr == OPR_GE || opr == OPR_GT || opr == OPR_LE || opr == OPR_LT) - && ((WN_operator(cond_kid1) == OPR_INTCONST) && (WN_const_val(cond_kid1) == 0)) - && (Is_Sub_ILOAD_Tree(then_expr, NULL, cond_kid0) || Is_Sub_ILOAD_Tree(else_expr, NULL, cond_kid0))) - return NULL; + if (rtype == MTYPE_I2 && dsctyp == MTYPE_I2) { + rtype = MTYPE_I4; + } #endif - // Generate a SELECT expression - WN *sel = WN_Select( Mtype_comparison(dsctyp), - WN_if_test(wn), then_expr, else_expr ); - WN_kid0(store) = sel; - WN_Set_Linenum( store, WN_Get_Linenum(wn) ); - return store; - } - return NULL; -} + load = WN_CreateIload(OPR_ILOAD, rtype, dsctyp, WN_offset(stmt), + TY_pointed(WN_ty(stmt)), WN_ty(stmt), + Copy_addr_expr(WN_kid1(stmt), _opt_stab->Alias_classification()), + WN_field_id(stmt)); -// ==================================================================== -// fully lower IF statements -// ==================================================================== -void -CFG::Lower_if_stmt( WN *wn, END_BLOCK *ends_bb ) -{ - Is_True(Lower_fully(), ("CFG::Lower_if_stmt: Lower_fully not true")); - - // The if stmt is lowered into one of 4 forms: - // - // IF there are empty "then" and "else" blocks: - // EVAL cond - // - // IF there are non-empty "then" and "else" blocks: - // if (! cond) - // goto else - // "then" block - // goto merge - // else: - // "else" block (note: "else" block can be a region so put label outside) - // merge: - // - // IF there is empty "else" (and non-empty "then") block: - // if (! cond) - // goto merge - // "then" block - // merge: - // - // IF there is empty "then" (and non-empty "else") block: - // if (cond) - // goto merge - // "else" block - // merge: - // - - WN *then_wn = WN_then(wn); - BOOL empty_then = FALSE; - - if ( then_wn == NULL ) - empty_then = TRUE; - else { - if ( WN_opcode(then_wn) == OPC_BLOCK && - WN_first(then_wn) == NULL ) - empty_then = TRUE; - } - - WN *else_wn = WN_else(wn); - BOOL empty_else = FALSE; - - if ( else_wn == NULL ) - empty_else = TRUE; - else { - if ( WN_opcode(else_wn) == OPC_BLOCK && - WN_first(else_wn) == NULL ) - empty_else = TRUE; - } - - // - // just evaluate the condition? - // - WN *if_test = WN_if_test(wn); - if ( empty_then && empty_else ) { - WN *eval_stmt = WN_CreateEval( if_test ); - WN_Set_Linenum( eval_stmt, WN_Get_Linenum(wn) ); - Add_one_stmt( eval_stmt, NULL ); - - // Lower feedback data - if ( Cur_PU_Feedback ) - Cur_PU_Feedback->FB_lower_branch( wn, NULL ); - - // this statement does not break the block - if ( ends_bb ) - *ends_bb = END_NOT; - return; - } - - // Perform if-conversion for <simple if-then-else> statements. - // - // <simple if-then-else> :: if (cond) then <block> else <block> ;; - // <block> :: <empty_block> | block stid <var> <simple_expr> end_block ;; - // <empty_block> :: block end_block ;; - // <simple_expr> :: <var> | <const> | <f8const> ;; - // - // where <var> can be speculated and is non-volatile. At - // least one of then or else block is non-empty. If both the - // then and else block are non-empty, they stores to - // the same variable. - // -#if defined(TARG_SL) - // more aggressively peer down else and then case for nested selects - if (else_wn && ((WN_first(else_wn) == WN_last(else_wn)) && WN_first(else_wn) && (WN_operator(WN_first(else_wn)) == OPR_IF))) { - WN *sel_stmt = Conv_to_select(else_wn); - if (sel_stmt) { - WN* block = WN_CreateBlock(); - WN_first(block) = sel_stmt; - WN_last(block) = sel_stmt; - else_wn = block; - WN_else(wn) = block; + // copy alias class info from the ISTORE node + _opt_stab->Alias_classification()->Copy_alias_class(stmt, load); + IDTYPE ip_alias_class = WN_MAP32_Get(WN_MAP_ALIAS_CLASS, stmt); + if (ip_alias_class != OPTIMISTIC_AC_ID) + WN_MAP32_Set(WN_MAP_ALIAS_CLASS, load, ip_alias_class); } } - if (then_wn && ((WN_first(then_wn) == WN_last(then_wn)) && WN_first(then_wn) && (WN_operator(WN_first(then_wn)) == OPR_IF))) { - WN *sel_stmt = Conv_to_select(then_wn); - if (sel_stmt) { - WN* block = WN_CreateBlock(); - WN_first(block) = sel_stmt; - WN_last(block) = sel_stmt; - then_wn = block; - WN_then(wn) = block; - } - } -#endif + + WN *then_expr = empty_then ? load : WN_kid0(WN_first(then_wn)); + WN *else_expr = empty_else ? load : WN_kid0(WN_first(else_wn)); + INT lanswer, ranswer; - if (If_conv_criteria_met(wn, else_wn, then_wn, empty_else, empty_then)) { - - if (Screen_cand(wn, else_wn, then_wn, empty_else, empty_then)) - goto skip_if_conversion; + // profitability check + if ( +#if !defined(TARG_IA32) && !defined(TARG_X8664) && !defined(TARG_SL) + // The expr in the then-block can be speculated and non-volatile, + // is a const or LDA. + Is_simple_expr(then_expr) && - // Get the store from either the first statement of the non-empty block - WN *stmt = WN_first(empty_then ? else_wn : then_wn); - - WN *load = NULL; - WN *store = WN_CopyNode(stmt); - WN_set_map_id(store, WN_map_id(stmt)); - MTYPE dsctyp = WN_desc(stmt); - - if (WN_operator(stmt) == OPR_STID || WN_operator(stmt) == OPR_STBITS) - WN_set_aux(store, WN_aux(stmt)); // setting mapping to indicate ST_is_aux - - // Generate a load for the empty block - if (empty_then || empty_else) { - if (WN_operator(stmt) == OPR_STID) { - load = WN_Ldid(dsctyp, - WN_offset(stmt), - (ST_IDX) WN_aux(stmt), - WN_ty(stmt), - WN_field_id(stmt)); - WN_set_aux(load, WN_aux(stmt)); // setting mapping to indicate ST_is_aux - } - else { - MTYPE rtype = WN_rtype(WN_kid0(stmt)); - if (MTYPE_byte_size(rtype) < MTYPE_byte_size(dsctyp)) - rtype = dsctyp;// rtype should never be smaller than dsctyp (bug 6910) - else rtype = Mtype_TransferSign(dsctyp, rtype); -#ifdef TARG_SL - if (rtype == MTYPE_I2 && dsctyp == MTYPE_I2) { - rtype = MTYPE_I4; - } -#endif - load = WN_CreateIload(OPR_ILOAD, - rtype, - dsctyp, - WN_offset(stmt), TY_pointed(WN_ty(stmt)), - WN_ty(stmt), - Copy_addr_expr(WN_kid1(stmt), _opt_stab->Alias_classification()), - WN_field_id(stmt)); - // copy alias class info from the ISTORE node - _opt_stab->Alias_classification()->Copy_alias_class(stmt, load); - IDTYPE ip_alias_class = WN_MAP32_Get(WN_MAP_ALIAS_CLASS, stmt); - if (ip_alias_class != OPTIMISTIC_AC_ID) - WN_MAP32_Set(WN_MAP_ALIAS_CLASS, load, ip_alias_class); - } - } - WN *then_expr = empty_then ? load : WN_kid0(WN_first(then_wn)); - WN *else_expr = empty_else ? load : WN_kid0(WN_first(else_wn)); - INT lanswer, ranswer; - - // profitability check - if ( -#if !defined(TARG_IA32) && !defined(TARG_X8664) - // The expr in the then-block can be speculated and non-volatile, - // is a const or LDA. - Is_simple_expr(then_expr) && - - // The expr in the else-block can be speculated and non-volatile, - // is a const or LDA. - Is_simple_expr(else_expr) + // The expr in the else-block can be speculated and non-volatile, + // is a const or LDA. + Is_simple_expr(else_expr) #else // allow simple expressions of up to 4 leaf nodes - (lanswer = (empty_then ? 1 : Is_simple_expr(then_expr))) && + (lanswer = (empty_then ? 1 : Is_simple_expr(then_expr))) && - (ranswer = (empty_else ? 1 : Is_simple_expr(else_expr))) && + (ranswer = (empty_else ? 1 : Is_simple_expr(else_expr))) && - (lanswer + ranswer) <= WOPT_Enable_If_Conv_Limit + (lanswer + ranswer) <= WOPT_Enable_If_Conv_Limit #endif - ) { - + ) { + // Generate a SELECT expression + WN *sel; #ifdef TARG_SL - // - // For such case, - // if(p) - // res = p->a - // else - // res = 0; - // if_conversion is skipped as accessing ZERO-address is illegal for SL. - // - - WN *cond_kid0 = WN_kid0(if_test); - WN *cond_kid1 = WN_kid1(if_test); - OPERATOR opr = WN_operator(if_test); + // + // For such case, + // if(p) + // res = p->a + // else + // res = 0; + // if_conversion is skipped as accessing ZERO-address is illegal for SL. + // + WN *if_test = WN_if_test(wn); + WN *cond_kid0 = WN_kid0(if_test); + WN *cond_kid1 = WN_kid1(if_test); + OPERATOR opr = WN_operator(if_test); - if ((opr == OPR_EQ || opr == OPR_NE || opr == OPR_GE || opr == OPR_GT || opr == OPR_LE || opr == OPR_LT) - && ((WN_operator(cond_kid1) == OPR_INTCONST) && (WN_const_val(cond_kid1) == 0)) - && (Is_Sub_ILOAD_Tree(then_expr, NULL, cond_kid0) || Is_Sub_ILOAD_Tree(else_expr, NULL, cond_kid0))) - goto skip_if_conversion; -#endif - // Generate a SELECT expression - WN *sel; -#if defined(TARG_SL) - if (opr == OPR_GE || opr == OPR_GT || opr == OPR_LE) { - // SL only have one compare instruction, that is "<". - // So do following convert when generating "SELECT" for better - // optimization of CG phase. - // a >= b ? 5 : 3 ==> a < b ? 3 : 5 - // a > b ? 5 : 3 ==> b < a ? 5 : 3 - // a <= b ? 5 : 3 ==> b < a ? 3 : 5 - WN *left_cond, *right_cond, *true_expr, *false_expr; - switch(opr) { - case OPR_GE: - { - left_cond = cond_kid0; - right_cond = cond_kid1; - true_expr = else_expr; - false_expr = then_expr; - break; - } - case OPR_GT: - { - left_cond = cond_kid1; - right_cond = cond_kid0; - true_expr = then_expr; - false_expr = else_expr; - break; - } + if ((opr == OPR_EQ || opr == OPR_NE || opr == OPR_GE || opr == OPR_GT || opr == OPR_LE || opr == OPR_LT) + && ((WN_operator(cond_kid1) == OPR_INTCONST) && (WN_const_val(cond_kid1) == 0)) + && (Is_Sub_ILOAD_Tree(then_expr, NULL, cond_kid0) || Is_Sub_ILOAD_Tree(else_expr, NULL, cond_kid0))) + return wn_bk; - case OPR_LE: - { - left_cond = cond_kid1; - right_cond = cond_kid0; - true_expr = else_expr; - false_expr = then_expr; - break; - } - default: - Fail_FmtAssertion("Lower_if_stmt: Unexpected compare operator"); + if (opr == OPR_GE || opr == OPR_GT || opr == OPR_LE) { + // SL only have one compare instruction, that is "<". + // So do following convert when generating "SELECT" for better + // optimization of CG phase. + // a >= b ? 5 : 3 ==> a < b ? 3 : 5 + // a > b ? 5 : 3 ==> b < a ? 5 : 3 + // a <= b ? 5 : 3 ==> b < a ? 3 : 5 + WN *left_cond, *right_cond, *true_expr, *false_expr; + switch(opr) { + case OPR_GE: + { + left_cond = cond_kid0; + right_cond = cond_kid1; + true_expr = else_expr; + false_expr = then_expr; + break; } - - WN *test_wn = WN_CreateExp2(OPR_LT, WN_rtype(if_test), WN_desc(if_test), - left_cond, right_cond); - sel = WN_Select( Mtype_comparison(dsctyp), - test_wn, true_expr, false_expr ); - } else -#endif - sel = WN_Select( Mtype_comparison(dsctyp), - WN_if_test(wn), then_expr, else_expr ); - WN_kid0(store) = sel; - WN_Set_Linenum( store, WN_Get_Linenum(wn) ); - Add_one_stmt( store, NULL ); + case OPR_GT: + { + left_cond = cond_kid1; + right_cond = cond_kid0; + true_expr = then_expr; + false_expr = else_expr; + break; + } - // Lower feedback data - if ( Cur_PU_Feedback ) - Cur_PU_Feedback->FB_lower_branch( wn, NULL ); - -// this statement does not break the block - if ( ends_bb ) - *ends_bb = END_NOT; - return; - } - } - - - skip_if_conversion: - - // we need a merge block, but don't connect it yet - BB_NODE *merge_bb = Create_labelled_bb(); - BB_NODE *then_bb = NULL, *else_bb = NULL; - BB_NODE *true_bb = NULL, *false_bb = NULL; - BOOL true_branch; - BOOL then_exists = !empty_then; - BOOL else_exists = !empty_else; - - if (WOPT_Enable_Edge_Placement) { - then_exists = else_exists = TRUE; - } - - // - // do we need to negate the condition? - // - if ( !then_exists ) { - Is_True( ! empty_else, - ("CFG::Lower_if_stmt: empty then and else") ); - else_bb = Create_bb(); - - true_bb = merge_bb; - false_bb = else_bb; - true_branch = TRUE; - } - else { - // create an empty, unconnected, then block - then_bb = Create_bb(); - then_bb->Set_linenum( WN_Get_Linenum(then_wn) ); - - if ( !else_exists ) { - true_bb = then_bb; - false_bb = merge_bb; - true_branch = FALSE; - } - else { - else_bb = Create_labelled_bb(); - else_bb->Set_linenum( WN_Get_Linenum(else_wn) ); - true_bb = then_bb; - false_bb = else_bb; - true_branch = FALSE; - } - } - // Add the conditional branch - WN *wn_branch; - BB_NODE *cond_bb = - Create_conditional( if_test, true_bb, false_bb, true_branch, &wn_branch ); - - // Handle "then" part - if ( then_exists ) { - Append_bb( then_bb ); - Connect_predsucc(cond_bb, then_bb); - END_BLOCK then_end; - Add_one_stmt( then_wn, &then_end ); - - if ( then_end != END_BREAK ) { - // need to get to merge block, either by falling through, or - // by goto - if ( else_exists ) { - // we may need another block to add the goto to - if ( then_end == END_FALLTHRU ) - (void) New_bb( TRUE/*connect*/ ); - - WN *goto_wn = WN_CreateGoto(merge_bb->Labnam()); - // adding the statement connects us to merge block - Add_one_stmt( goto_wn, NULL ); - if(WN_prev(goto_wn) != NULL && (WN_prev(goto_wn)) != NULL) { - WN* prev_wn=WN_prev(goto_wn); - if ( Cur_PU_Feedback ) { - FB_FREQ outgoing_fb=Cur_PU_Feedback->Query_total_out(prev_wn); - Cur_PU_Feedback->Annot(goto_wn, FB_EDGE_OUTGOING, outgoing_fb); - } - + case OPR_LE: + { + left_cond = cond_kid1; + right_cond = cond_kid0; + true_expr = else_expr; + false_expr = then_expr; + break; } + default: + Fail_FmtAssertion("Lower_if_stmt: Unexpected compare operator"); } - else { - Connect_predsucc( _current_bb, merge_bb ); - } - } - } + + WN *test_wn = WN_CreateExp2(OPR_LT, WN_rtype(if_test), WN_desc(if_test), + left_cond, right_cond); + sel = WN_Select(Mtype_comparison(dsctyp), + test_wn, true_expr, false_expr); + } else +#endif + sel = WN_Select(Mtype_comparison(dsctyp), + WN_if_test(wn), then_expr, else_expr); + WN_kid0(store) = sel; + WN_Set_Linenum(store, WN_Get_Linenum(wn)); - // Handle "else" part - if ( else_exists ) { - Append_bb( else_bb ); - if ( !then_exists ) - Connect_predsucc( cond_bb, else_bb ); - END_BLOCK else_end; - Add_one_stmt( else_wn, &else_end ); - - if ( else_end != END_BREAK ) { - Connect_predsucc( _current_bb, merge_bb ); + WN *block = WN_CreateBlock(); + WN_INSERT_BlockFirst(block, store); + if (if_select_return) { + WN_INSERT_BlockAfter(block, store, return_wn); } + return block; + } else { + return wn_bk; } +} - // Handle "merge" block - Append_bb( merge_bb ); +void +CFG::Lower_if_stmt(WN *wn, END_BLOCK *ends_bb) +{ + Is_True(Lower_fully(), ("CFG::Lower_if_stmt: Lower_fully not true")); + WN *conv_wn = if_convert(wn); + if (WN_operator(conv_wn) == OPR_IF) + Add_one_if_stmt(conv_wn, ends_bb); + else + Add_one_stmt(conv_wn, ends_bb); // Lower feedback data - if ( Cur_PU_Feedback ) - Cur_PU_Feedback->FB_lower_branch( wn, wn_branch ); - - // this statement does not break the block because we've created - // a merge point - if ( ends_bb ) - *ends_bb = END_NOT; + if (Cur_PU_Feedback) + Cur_PU_Feedback->FB_lower_branch(wn, NULL); } // ==================================================================== Modified: trunk/osprey/be/opt/opt_cfg.h =================================================================== --- trunk/osprey/be/opt/opt_cfg.h 2010-08-09 07:29:36 UTC (rev 3308) +++ trunk/osprey/be/opt/opt_cfg.h 2010-08-10 10:07:31 UTC (rev 3309) @@ -369,6 +369,10 @@ void Lower_while_do(WN *wn, END_BLOCK *ends_bb ); INT Is_simple_expr(WN *wn); void Lower_if_stmt(WN *wn, END_BLOCK *ends_bb ); + WN *if_convert(WN *wn); + BOOL wn_is_assign(WN *wn); + BOOL wn_is_assign_return(WN *wn); + BOOL wn_is_return_convert(WN *wn); // add various high-level construct statements to CFG so they can // later be raised back up (mostly preopt phase) void Add_one_io_stmt(WN *wn, END_BLOCK *ends_bb); @@ -733,8 +737,10 @@ // for the phase of removing useless store loop BB_NODE * ULSE_insert_bb_and_merge(STMTREP*, BB_NODE*, BB_NODE*); BOOL If_convertible_cond(WN* wn); - BOOL If_conv_criteria_met(WN* wn, WN* else_wn, WN* then_wn, BOOL empty_else, BOOL empty_then); - BOOL Screen_cand(WN* wn, WN* else_wn, WN* then_wn, BOOL empty_else, BOOL empty_then); + BOOL If_conv_criteria_met(WN* wn); + BOOL Cand_is_select(WN *wn); + BOOL Cand_is_return_inside_select(WN *wn); + BOOL Screen_cand(WN* wn); #if defined(TARG_SL) BOOL Is_Sub_ILOAD_Tree(WN *wn, WN *parent_wn, WN * mode_wn); #endif ------------------------------------------------------------------------------ This SF.net email is sponsored by Make an app they can't live without Enter the BlackBerry Developer Challenge http://p.sf.net/sfu/RIM-dev2dev _______________________________________________ Open64-devel mailing list Open64-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/open64-devel