Author: meiye
Date: 2012-01-26 14:12:56 -0500 (Thu, 26 Jan 2012)
New Revision: 3862

Modified:
   trunk/osprey/be/opt/opt_etable.cxx
   trunk/osprey/be/opt/opt_etable.h
   trunk/osprey/be/opt/opt_lftr2.cxx
   trunk/osprey/be/opt/opt_lftr2.h
Log:
Fix for Bug 778.  Attempt pre-increment transformation to avoid an overflow 
problem in 32-bit x86 caused by the LFTR phase. CR: Sun Chan

Modified: trunk/osprey/be/opt/opt_etable.cxx
===================================================================
--- trunk/osprey/be/opt/opt_etable.cxx  2012-01-20 07:19:49 UTC (rev 3861)
+++ trunk/osprey/be/opt/opt_etable.cxx  2012-01-26 19:12:56 UTC (rev 3862)
@@ -1896,6 +1896,29 @@
   return FALSE;
 }
 
+BOOL
+EXP_WORKLST::Remove_phi_pred_occurrence( STMTREP *stmt)
+{
+  EXP_OCCURS *exp_occ, *prev_occ = NULL, *next_occ;
+  EXP_OCCURS_ITER exp_occ_iter;
+  exp_occ_iter.Init(Phi_pred_occurs().Head());
+  for (exp_occ = exp_occ_iter.First();
+       ! exp_occ_iter.Is_Empty();
+       exp_occ = next_occ) {
+    next_occ = exp_occ_iter.Next();
+
+    if (exp_occ->Encl_stmt_set()
+       && (exp_occ->Stmt() == stmt)) { // found it, remove from list
+      Phi_pred_occurs().Remove(prev_occ, exp_occ);
+      return TRUE;
+    }
+    else
+      prev_occ = exp_occ;
+  }
+  return FALSE;
+}
+
+
 // compare this with w in terms of weight.
 BOOL
 EXP_WORKLST::Weight_less_than(EXP_WORKLST *w)
@@ -3821,7 +3844,7 @@
                           NULL, NULL, NULL, NULL); /* only real occurrences */
          EXP_OCCURS *oc;
          FOR_ALL_NODE(oc, exp_occ_iter, Init()) {
-           if (oc == occur)
+           if (oc == occur) 
              FmtAssert(FALSE,("ETABLE::Replace_occurs: RHS must need rehash"));
            if (oc->Stmt() == occur->Stmt() && 
                oc->Stmt_kid_num() == occur->Stmt_kid_num())
@@ -4574,6 +4597,8 @@
   INT total_dense_ssa_count = 0;
   INT orig_coderep_id_cnt = Htable()->Coderep_id_cnt();
   FOR_ALL_NODE(cur_worklst, worklst_iter, Init()) {
+    if (cur_worklst->Real_occurs().Head() == NULL)
+      continue;
 
     ++cur_worklst_idx;
     if (WOPT_Enable_Exp_PRE_Limit != -1 &&

Modified: trunk/osprey/be/opt/opt_etable.h
===================================================================
--- trunk/osprey/be/opt/opt_etable.h    2012-01-20 07:19:49 UTC (rev 3861)
+++ trunk/osprey/be/opt/opt_etable.h    2012-01-26 19:12:56 UTC (rev 3862)
@@ -1680,6 +1680,7 @@
 
   // remove a single occurrence from one of the worklsts
   BOOL            Remove_real_occurrence(STMTREP *stmt);
+  BOOL            Remove_phi_pred_occurrence(STMTREP *stmt);
 
   // 'this' is the same as 'cr'
   BOOL            Is_the_same_as(const CODEREP *cr);

Modified: trunk/osprey/be/opt/opt_lftr2.cxx
===================================================================
--- trunk/osprey/be/opt/opt_lftr2.cxx   2012-01-20 07:19:49 UTC (rev 3861)
+++ trunk/osprey/be/opt/opt_lftr2.cxx   2012-01-26 19:12:56 UTC (rev 3862)
@@ -733,6 +733,88 @@
   return FALSE;
 }
 
+// Given a CODEREP 'cr_iter', walk its operands, replace the use of 'cr_old' 
with 'cr_new'.
+// The replacement is done without rehashing.
+void
+LFTR::Replace_use(CODEREP * cr_iter, CODEREP * cr_old, CODEREP * cr_new)
+{
+  CODEKIND kind = cr_iter->Kind();
+  CODEREP * cr_copy = NULL;
+  CODEREP * cr_orig = cr_iter;
+
+  if (kind == CK_IVAR) {
+    CODEREP * cr_base = NULL;
+    BOOL is_ilod = FALSE;
+
+    cr_base = cr_iter->Ilod_base();
+    if (cr_base) {
+      if (cr_base == cr_old) {
+       cr_iter->Set_ilod_base(cr_new);
+      }
+      else {
+       Replace_use(cr_base, cr_old, cr_new);
+      }
+    }
+
+    cr_base = cr_iter->Istr_base();
+    if (cr_base) {
+      if (cr_base == cr_old) {
+       cr_iter->Set_istr_base(cr_new);
+      }
+      else {
+       Replace_use(cr_base, cr_old, cr_new);
+      }
+    }
+  }
+  else if (kind == CK_OP) {
+    cr_copy = NULL;
+
+    for (int i = 0; i < cr_iter->Kid_count(); i++) {
+      CODEREP * cr_tmp = cr_iter->Opnd(i);
+      if (cr_tmp->Kind() == CK_VAR) {
+       if (cr_tmp == cr_old) {
+         cr_iter->Set_opnd(i, cr_new);
+       }
+      }
+      else {
+       Replace_use(cr_tmp, cr_old, cr_new);
+      }
+    }
+  }
+}
+
+// Given a loop, iterate all statements, replace the use of 'cr_old' with 
'cr_new'.
+// Skip the definition statement of 'cr_new'.
+void
+LFTR::Replace_use(const BB_LOOP * loop, CODEREP * cr_old, CODEREP * cr_new)
+{
+  BB_NODE * bb;
+  BB_NODE_SET_ITER bb_iter;
+  FOR_ALL_ELEM(bb, bb_iter, Init(loop->True_body_set())) {
+    STMTREP_ITER stmt_iter(bb->Stmtlist());
+    STMTREP *stmt;
+    FOR_ALL_NODE(stmt, stmt_iter, Init()) {
+      if (stmt == cr_new->Defstmt())
+       continue;
+
+      CODEREP * rhs = stmt->Rhs();
+      if (rhs) {
+       if (rhs == cr_old) {
+         stmt->Set_rhs(cr_new);
+         cr_new->IncUsecnt();
+       }
+       else {
+         Replace_use(rhs, cr_old, cr_new);
+       }
+      }
+      CODEREP * lhs = stmt->Lhs();
+      if (lhs) {
+       Replace_use(lhs, cr_old, cr_new);
+      }
+    }
+  }
+}
+
 // ======================================================================
 // Perform the replacement of the comparison
 //   replace lhs with tempcr
@@ -937,7 +1019,7 @@
   CODEREP *tos_lftr_var = Find_lftr_var(tos->Occurrence(), comp_lftr_var);
 
   if (comp_lftr_var == NULL || tos_lftr_var == NULL) {
-    Is_Trace(Trace(), (TFile, "LFTR return 3 - could not find a lftr_var, "
+    Is_Trace(Trace(), (TFile, "LFTR return 3 - could not find Xa lftr_var, "
                       "comp=0x%p, tos=0x%p\n", comp_lftr_var,
                       tos_lftr_var));
     return;
@@ -962,6 +1044,9 @@
 
   // tempcr is the preg load that we want to use for the comparison lhs
   CODEREP *tempcr = tos->Temp_cr();
+  STMTREP * iv_init = NULL;
+  STMTREP * temp_init = NULL;
+  CODEREP * iv_incr = NULL;
   // comp is dominated by a phi, find dominating temp (due to SR injury fix)
   if (tos->Occ_kind() == EXP_OCCURS::OCC_PHI_OCCUR) {
     STMTREP *iv_defstmt = comp_lftr_var->Defstmt();
@@ -986,7 +1071,110 @@
 #endif
        // 3
        Is_True(tempcr != cr, ("LFTR::Replace_comparison, tempcr is same"));
-       tempcr = cr;
+#if defined(TARG_IA32) || defined(TARG_X8664)
+       // Bug 778.  overflow problem for 32-bit architectures.
+       if (Is_Target_32bit()) {
+         CODEREP * sym4 = tempcr;
+         CODEREP * sym5 = cr;
+         tempcr = cr;
+         // Attempt pre-increment transformation for the following pattern to 
avoid overflow.
+         // sym7v3 = const1                 // sym7 corresponds to IV.
+         // sym11v3 = sym7v3 + sym3         // sym11 corresponds to tempcr.
+         // sym11v4 = phi(sym11v3, sym11v5)
+         // LABEL:
+         //    *sym11v4 = ...
+         //    sym11v5 = sym11v4 + const2
+         //    if (sym11v5 <= end)
+         //       goto LABEL
+         //
+         // After the transformation:
+         // sym7v3 = const1
+         // sym11v3 = const1 - const2 + sym3 // The result of 'const1 - 
const2' should use signed type.
+         // sym11v4 = phi(sym11v3, sym11v5)
+         // LABEL:
+         // sym11v5 = sym11v4 + const2           
+         //   *sym11v5  = ...
+         //   if (sym11v5 <= end - const2)
+         //      goto LABEL
+         PHI_NODE * phi = (sym4->Is_flag_set(CF_DEF_BY_PHI)) ? sym4->Defphi() 
: NULL;
+         OPT_STAB * ops = Etable()->Opt_stab();
+         if ((phi != NULL) && (phi->Size() == 2)
+             && (ST_class(ops->St(tempcr->Aux_id())) == CLASS_PREG)
+             && (iv_defstmt->Bb() == comp->Bb())
+             && (tempcr->Usecnt() == 0)
+             && (Find_comp_list(comp_lftr_var_id)->Size() == 1)) {
+           STMTREP * stmt_tmp = tempcr->Defstmt();
+           CODEREP * cr_tmp = stmt_tmp->Rhs();
+           EXP_WORKLST * worklst = Etable()->Get_worklst(cr_tmp, FALSE, TRUE);
+           
+           // Avoid the case that the RHS of 'stmt_tmp' is a CSE since we are 
going to 
+           // replace the use operands without rehashing.
+           if (worklst 
+               && (worklst->Real_occurs().Head() != 
worklst->Real_occurs().Tail()))
+             cr_tmp = NULL;
+           else if (cr_tmp->Usecnt() > 1) {
+             // Additional check to preclude the cases that the RHS of 
'stmt_tmp' is a CSE.
+             cr_tmp = NULL;
+           }
+
+           if (cr_tmp
+               && (cr_tmp->Kind() == CK_OP) 
+               && (cr_tmp->Opr() == OPR_ADD)
+               && (cr_tmp->Opnd(1)->Kind() == CK_CONST)
+               && (cr_tmp->Opnd(1)->Const_val() > 0)) {
+             iv_incr = cr_tmp->Opnd(1);
+             CODEREP * opnd1 = phi->OPND(0);
+             CODEREP * opnd2 = phi->OPND(1);
+             if (opnd1->Defstmt() == stmt_tmp)
+               stmt_tmp = opnd2->Defstmt();
+             else if (opnd2->Defstmt() == stmt_tmp)
+               stmt_tmp = opnd1->Defstmt();    
+             else
+               stmt_tmp = NULL;
+             if (stmt_tmp){
+               temp_init = stmt_tmp;
+               cr_tmp = stmt_tmp->Rhs();
+               if ((cr_tmp->Kind() == CK_OP)
+                   && (cr_tmp->Opr() == OPR_ADD)) {
+                 // Find initial IV definition.
+                 opnd1 = cr_tmp->Opnd(0);
+                 opnd2 = cr_tmp->Opnd(1);
+                 stmt_tmp = NULL;
+                 if (opnd1->Kind() == CK_VAR) 
+                   stmt_tmp = opnd1->Defstmt();
+                 else if (opnd2->Kind() == CK_VAR)
+                   stmt_tmp = opnd2->Defstmt();
+                 if (stmt_tmp) {
+                   cr_tmp = stmt_tmp->Lhs();
+                   if (cr_tmp
+                       && (cr_tmp->Kind() == CK_VAR)
+                       && (cr_tmp->Aux_id() == iv_defstmt->Lhs()->Aux_id())) {
+                     cr_tmp = stmt_tmp->Rhs();
+                     if ((cr_tmp->Kind() == CK_CONST)) {
+                       CODEREP * cr_cmp = comp->Occurrence();
+                       CODEREP * cr_cons = cr_cmp->Opnd(1);
+                       OPERATOR opr = cr_cmp->Opr();
+                       // Limit to the case that loop trip count is at least 2
+                       // to avoid underflow of "end - const2".
+                       if ((cr_cons->Kind() == CK_CONST)
+                           && ((opr == OPR_LE) || (opr == OPR_LT))) {
+                         int trip_cnt = (cr_cons->Const_val() - 
cr_tmp->Const_val())
+                           / iv_incr->Const_val();
+                         if (opr == OPR_LE)
+                           trip_cnt++;
+                         if (trip_cnt >= 2) {
+                           iv_init = stmt_tmp;
+                         }
+                       }
+                     }
+                   }
+                 }
+               }
+             }
+           }
+         }
+       }
+#endif
       }
     }
   } else { // dominated by real occurrence, easy case
@@ -1016,6 +1204,7 @@
                         "not current at temp def\n"));
       return;
     }
+    iv_init = NULL;
   }
   else {
     // The temp is defined by a statement -- either a save to
@@ -1062,6 +1251,7 @@
     else {
       Is_Trace(Trace(), (TFile, "LFTR::Replace_comparison: "
                         "lftr var in rhs of save to temp\n"));
+      iv_init = NULL;
     }
     // If the current version of the lftr var at the temp's definition
     // is different from that in the comparison, we can't replace the
@@ -1131,6 +1321,11 @@
   Is_True(head != NULL,
          ("LFTR::Replace_comparison: loop head must not be NULL"));
 
+  // This allows hoisting the definition statement of 'tempcr' to loop header.
+  if (iv_init && !tempcr->Defstmt()->Bb()->Postdominates(head)) {
+    iv_init = NULL;
+  }
+
   // In spite of the Find_one_variant() call above, there may not be a
   // phi for the temp at the top of the loop, since the loop-variant
   // operand of the comparison may be defined by a killing
@@ -1199,8 +1394,8 @@
                         // exprs but we do not delete them from the work list
     if (fold_cr == NULL) {
       new_cr->Set_coderep_id(0);
-      fold_cr = Htable()->Rehash(new_cr);
-    }
+      fold_cr = Htable()->Rehash(new_cr); 
+   }
 
     // ---- from this point on we are committed to doing the substitution ----
 
@@ -1222,12 +1417,15 @@
     new_compare_type = Mtype_TransferSign(comparison_cr->Dsctyp(), 
                                          new_compare_type);
     if (Is_Target_32bit()
-       && (addressable == ADDRESSABILITY_IS_ADDRESS) 
+       && (addressable == ADDRESSABILITY_IS_ADDRESS)
        && MTYPE_is_signed(new_compare_type)) {
       // For 32-bit targets, force comparison of address expressions to be 
unsigned.
       new_compare_type = Mtype_from_mtype_class_and_size(MTYPE_CLASS_UNSIGNED,
                                                         
MTYPE_size_min(new_compare_type)/8);
     }
+    else {
+      iv_init = NULL;
+    }
 #else
     MTYPE new_compare_type = comparison_cr->Dsctyp();
     if (addressable == ADDRESSABILITY_IS_ADDRESS &&
@@ -1253,6 +1451,60 @@
         break;
       }
     }
+
+    if ((new_compare_opr != OPR_LT) && (new_compare_opr != OPR_LE))
+      iv_init = NULL;
+
+    if (fold_cr->Kind() != CK_OP)
+      iv_init = NULL;
+
+    if (iv_init) {
+      opr = fold_cr->Opr();
+      EXP_WORKLST * worklst = Etable()->Get_worklst(fold_cr, FALSE, TRUE); 
+
+      if (opr != OPR_ADD)
+       iv_init = NULL;
+      else if (worklst && (worklst->Real_occurs().Head())) {
+       // avoid the situation that 'fold_cr' has PRE/CSE occurrences so that
+       // the CODEREP * at other occurrences won't be changed unintentionally.
+       iv_init = NULL;
+      }
+      else {
+       CODEREP * opnd1 = fold_cr->Opnd(0);
+       CODEREP * opnd2 = fold_cr->Opnd(1);
+       CODEREP * opnd = NULL;
+
+       // reduce loop upper bound by IV increment.
+       if (opnd1->Kind() == CK_CONST) 
+         opnd = opnd1;
+       else if (opnd2->Kind() == CK_CONST) 
+         opnd = opnd2;
+       
+       if (opnd) {
+         CODEMAP * codemap = Etable()->Htable();         
+         INT64 const_val = opnd->Const_val() - iv_incr->Const_val();
+         MTYPE type = opnd->Dtyp();
+         if (const_val < 0)
+           type = (MTYPE_byte_size(type) == 4) ? MTYPE_I4 : MTYPE_I8;
+
+         CODEREP * cr_const = codemap->Add_const(type, const_val);
+         CODEREP * cr_new = Alloc_stack_cr(fold_cr->Extra_ptrs_used());
+         cr_new->Copy(*fold_cr);
+       
+         if (opnd == opnd1)
+           cr_new->Set_opnd(0,cr_const);
+         else
+           cr_new->Set_opnd(1,cr_const);
+
+         fold_cr = cr_new;
+         fold_cr->Set_coderep_id(0);
+         fold_cr = Htable()->Rehash(fold_cr);
+       }
+       else
+         iv_init = NULL;
+      }
+    }
+
     comparison_cr->Set_opr(new_compare_opr);
     comparison_cr->Set_dsctyp(new_compare_type);
 
@@ -1309,6 +1561,74 @@
                             OPCODE_UNKNOWN, FALSE);
     }
 
+    if (iv_init != NULL) {
+      // reduce initial value of 'temp_init'.
+      INT64 const_val = iv_init->Rhs()->Const_val() - iv_incr->Const_val();
+      CODEMAP * codemap = Etable()->Htable();
+      CODEREP * cr_old = temp_init->Rhs();
+      MTYPE type = cr_old->Dtyp();
+
+      if (const_val < 0) 
+       type = (MTYPE_byte_size(type) == 4) ? MTYPE_I4 : MTYPE_I8;
+
+      CODEREP * cr_const = codemap->Add_const(type, const_val);
+      CODEREP * cr_new = Alloc_stack_cr(cr_old->Extra_ptrs_used());
+      cr_new->Copy(*cr_old);
+
+      AUX_ID id  = iv_init->Lhs()->Aux_id();
+      CODEREP * opnd1 = cr_new->Opnd(0);
+      CODEREP * opnd2 = cr_new->Opnd(1);
+
+      if ((opnd1->Kind() == CK_VAR)
+         && (opnd1->Aux_id() == id))
+       cr_new->Set_opnd(0, cr_const);
+      else if ((opnd2->Kind() == CK_VAR)
+              && (opnd2->Aux_id() == id))
+       cr_new->Set_opnd(1, cr_const);
+
+      cr_new = Htable()->Rehash(cr_new);
+      temp_init->Set_rhs(cr_new);
+
+      Etable()->Remove_real_occurrence(cr_old, temp_init);
+      EXP_WORKLST * worklst = Etable()->Get_worklst(cr_old, FALSE, TRUE);
+      if (worklst) {
+       worklst->Remove_phi_pred_occurrence(temp_init);
+      }
+      
+      STACK<EXP_OCCURS *> * stk = Etable()->Deferred_ocopy_occurs();
+      for (int i = 0; i < stk->Elements(); i ++) {
+       EXP_OCCURS * occ = stk->Top_nth(i);
+       if (occ->Stmt() == temp_init) {
+         stk->DeleteTop(i);
+         break;
+       }
+      }
+
+      STMTREP * def_stmt = tempcr->Defstmt();
+      def_stmt->Bb()->Stmtlist()->Remove(def_stmt);
+      BB_NODE * bb_head = loop->Header();
+      STMTREP * stmt_ins = NULL;
+      STMTREP_ITER stmt_iter(bb_head->Stmtlist());
+      STMTREP * stmt;
+      FOR_ALL_NODE(stmt, stmt_iter, Init()) {
+       if (stmt->Opr() != OPR_LABEL) {
+         stmt_ins = stmt;
+         break;
+       }
+      }
+      if (stmt_ins) {
+       bb_head->Insert_stmtrep_before(def_stmt, stmt_ins);
+      }
+      else {
+       bb_head->Append_stmtrep(def_stmt);
+      }
+
+      Replace_use(loop, def_stmt->Rhs()->Opnd(0), tempcr);
+      FmtAssert(def_stmt->Rhs()->Opnd(0)->Version() != 
def_stmt->Lhs()->Version(),
+               ("Wrong version for iv."));
+    }
+
+
     Is_Trace(Trace(),(TFile,"LFTR::Replace_comparison, new comparison:\n"));
     Is_Trace_cmd(Trace(),comparison_cr->Print(0,TFile));
   }

Modified: trunk/osprey/be/opt/opt_lftr2.h
===================================================================
--- trunk/osprey/be/opt/opt_lftr2.h     2012-01-20 07:19:49 UTC (rev 3861)
+++ trunk/osprey/be/opt/opt_lftr2.h     2012-01-26 19:12:56 UTC (rev 3862)
@@ -221,6 +221,9 @@
 
   BOOL Can_only_increase(CODEREP *, AUX_ID);
 
+  void Replace_use(const BB_LOOP * loop, CODEREP * cr_old, CODEREP * cr_new);
+  void Replace_use(CODEREP*, CODEREP *, CODEREP *);
+
   // print an occurrence and a string
   void Print_occ(FILE *fp, const char *str, EXP_OCCURS *occ)
     { fprintf(fp,"%s\n",str);


------------------------------------------------------------------------------
Keep Your Developer Skills Current with LearnDevNow!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-d2d
_______________________________________________
Open64-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/open64-devel

Reply via email to