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
[email protected]
https://lists.sourceforge.net/lists/listinfo/open64-devel