loopOpt.cpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.13 $ */
00002 /* Copyright (c) 2006, Sun Microsystems, Inc.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
00006 following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
00010           disclaimer in the documentation and/or other materials provided with the distribution.
00011     * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived 
00012           from this software without specific prior written permission.
00013 
00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
00015 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
00016 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
00017 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00018 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00019 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00020 
00021 
00022 */
00023 
00024 # include "incls/_precompiled.incl"
00025 
00026 # ifdef DELTA_COMPILER
00027 # include "incls/_loopOpt.cpp.incl"
00028 
00029 GrowableArray<BB*>* CompiledLoop::_bbs;
00030 
00031 CompiledLoop::CompiledLoop() {
00032   _bbs = NULL;
00033   _startOfLoop = _endOfLoop = _startOfBody = _endOfBody = _startOfCond = _endOfCond = NULL;
00034   _loopVar = NULL;
00035   _lowerBound = NULL; _upperBound = NULL;
00036   _isIntegerLoop = false;
00037   _hoistableTests = NULL;
00038   _loopBranch = NULL;
00039   _isCountingUp = true;   // initial guess
00040 }
00041 
00042 
00043 void CompiledLoop::set_startOfLoop(LoopHeaderNode* current) {
00044   assert(_startOfLoop == NULL, "already set");
00045   assert(current->isLoopHeaderNode(), "expected loop header");
00046   _startOfLoop = _loopHeader = current;
00047   _beforeLoop = current->firstPrev();
00048 }
00049 
00050 
00051 void CompiledLoop::set_endOfLoop(Node* end) {
00052   assert(_endOfLoop == NULL, "already set");
00053   _endOfLoop = end;
00054   _startOfLoop = _startOfLoop->next();    // because original start is node *before* loop
00055   _firstNodeID = _startOfLoop->id() + 1;
00056   _lastNodeID = BasicNode::currentID - 1;  // -1 because currentID is id of next node to be allocated
00057   _scope = _startOfLoop->scope();
00058 }
00059 
00060 
00061 void CompiledLoop::set_startOfBody(Node* current) {
00062   assert(_startOfBody == NULL, "already set");
00063   _startOfBody = current;
00064 }
00065 
00066 
00067 void CompiledLoop::set_endOfBody(Node* current) {
00068   assert(_endOfBody == NULL, "already set");
00069   _endOfBody = current;
00070   // correct startOfBody -- merge node is created before cond
00071   if (isInLoopCond(_startOfBody)) _startOfBody = _startOfBody->next();
00072   assert(!isInLoopCond(_startOfBody), "oops!");
00073 }
00074 
00075 
00076 void CompiledLoop::set_startOfCond(Node* current) {
00077   assert(_startOfCond == NULL, "already set");
00078   _startOfCond = current;
00079 }
00080 
00081 
00082 void CompiledLoop::set_endOfCond(Node* current) {
00083   assert(_endOfCond == NULL, "already set");
00084   _endOfCond = current;
00085 }
00086 
00087 
00088 bool CompiledLoop::isInLoop(Node* n) const {
00089   return _firstNodeID <= n->id() && n->id() <= _lastNodeID;
00090 }
00091 
00092 
00093 bool CompiledLoop::isInLoopCond(Node* n) const {
00094   return _startOfCond->id() <= n->id() && n->id() <= _endOfCond->id();
00095 }
00096 
00097 
00098 bool CompiledLoop::isInLoopBody(Node* n) const {
00099   return _startOfBody->id() <= n->id() && n->id() <= _endOfBody->id();
00100 }
00101 
00102 
00103 char* CompiledLoop::recognize() {
00104   // Recognize integer loop.
00105   // We're looking for a loop where the loopVariable is initialized just before
00106   // the loop starts, is defined only once in the loop (increment/decrement),
00107   // and the loop condition is a comparison against a loop invariant.
00108   discoverLoopNesting();
00109   if (!OptimizeIntegerLoops) return "!OptimizeIntegerLoops";
00110   char* msg;
00111   if ((msg = findUpperBound()) != NULL) return msg;
00112   if ((msg = checkLoopVar()) != NULL) return msg;
00113   if ((msg = checkUpperBound()) != NULL) return msg;
00114   _isIntegerLoop = true;
00115   findLowerBound();     // don't need to know to optimize loop; result may be non-NULL
00116   return NULL;
00117 }
00118 
00119 void CompiledLoop::discoverLoopNesting() {
00120   // discover enclosing loop (if any) and set up loop header links
00121   for (InlinedScope* s = _scope; s != NULL; s = s->sender()) {
00122     GrowableArray<CompiledLoop*>* loops = s->loops();
00123     for (int i = loops->length() - 1; i >= 0; i--) {
00124       CompiledLoop* l = loops->at(i);
00125       if (l->isInLoop(_loopHeader)) {
00126         // this is out enclosing loop
00127         _loopHeader->set_enclosingLoop(l->loopHeader());
00128         l->loopHeader()->addNestedLoop(_loopHeader);
00129         return;
00130       }
00131     }
00132   }
00133 }
00134 
00135 
00136 char* CompiledLoop::findLowerBound() {
00137   // find lower bound; is assigned to loop var (temp) before loop
00138   // NB: throughout this code, "lower" and "upper" bound are used to denote the 
00139   // starting and ending values of the loop; in the case of a downward-counting loop,
00140   // lowerBound will actually be the highest value.
00141   // search for assignment to loopVar that reaches loop head
00142   Node* defNode;
00143   for (defNode = _beforeLoop; 
00144        defNode && defNode->nPredecessors() < 2 && 
00145          (!defNode->hasDest() || ((NonTrivialNode*)defNode)->dest() != _loopVar); 
00146        defNode = defNode->firstPrev()) ;
00147   if (defNode && defNode->isAssignNode()) {
00148     // ok, loopVar is assigned here
00149     _lowerBound = ((NonTrivialNode*)defNode)->src();
00150   }
00151   return "lower bound not found";
00152 }
00153 
00154 
00155 // Helper class to find the last send preceding a certain bci
00156 class SendFinder: public SpecializedMethodClosure {
00157  public:
00158   int theBCI, lastSendBCI;
00159 
00160   SendFinder(methodOop m, int bci) : SpecializedMethodClosure() {
00161     theBCI = bci; lastSendBCI = IllegalBCI;
00162     MethodIterator iter(m, this);
00163   }
00164   void send() { 
00165     int b = bci();
00166     if (b <= theBCI && b > lastSendBCI) lastSendBCI = b; 
00167   }
00168   virtual void normal_send(InterpretedIC* ic) { send(); }
00169   virtual void self_send  (InterpretedIC* ic) { send(); }
00170   virtual void super_send (InterpretedIC* ic) { send(); }
00171 };
00172 
00173 
00174 int CompiledLoop::findStartOfSend(int bci) {
00175   // find send preceding bci; slow but safe
00176   SendFinder f(_scope->method(), bci);
00177   return f.lastSendBCI;
00178 }
00179 
00180 
00181 char* CompiledLoop::findUpperBound() {
00182   // find upper bound and loop variable
00183   int condBCI = findStartOfSend(_endOfCond->bci() - InterpretedIC::size);
00184   if (condBCI == IllegalBCI) return "loop condition: no send found";
00185   // first find comparison in loop condition
00186   Expr* loopCond = _scope->exprStackElems()->at(condBCI);
00187   if (loopCond == NULL) return "loop condition: no expr (possible compiler bug)";
00188   if (loopCond->isMergeExpr()) {
00189     MergeExpr* cond = (MergeExpr*)loopCond;
00190     if (cond->isSplittable()) {
00191       Node* first = cond->exprs->first()->node();
00192       if (first->nPredecessors() == 1) {
00193         Node* prev = first->firstPrev();
00194         if (prev->isBranchNode()) _loopBranch = (BranchNode*)prev;
00195       }
00196     }
00197   }
00198   if (!_loopBranch) return "loop condition: conditional branch not found";
00199   NonTrivialNode* n = (NonTrivialNode*)_loopBranch->firstPrev();
00200   PReg* operand;
00201   if (n->isTArithNode()) {
00202     operand = ((TArithRRNode*)n)->operand();
00203   } else if (n->isArithNode()) {
00204     operand = ((ArithRRNode*)n)->operand();
00205   } else {
00206     return "loop condition: comparison not found";
00207   }
00208   BranchOpCode op = _loopBranch->op();
00209 
00210   // Now see if it's a simple comparison involving the loop variable
00211   // and make an initial guess about the loop variable.
00212   // NB: code generator inverts loop condition, i.e., branch leaves loop
00213   if (op == LTBranchOp || op == LEBranchOp) {
00214     // upperBound > loopVar
00215     _loopVar = operand;
00216     _upperBound = n->src();
00217   } else if (op == GTBranchOp || op == GEBranchOp) {
00218     // loopVar < upperBound
00219     _loopVar = n->src();
00220     _upperBound = operand;
00221   } else {
00222     return "loop condition: not oneof(<, <=, >, >=)";
00223   }
00224 
00225   // The above code assumes a loop counting up; check the loopVar now and switch
00226   // directions if it doesn't work.
00227   if (checkLoopVar()) {
00228     // the reverse guess may be wrong too, but it doesn't hurt to try
00229     PReg* temp = _loopVar; _loopVar = _upperBound; _upperBound = temp;
00230   }
00231   return NULL;
00232 }
00233 
00234 
00235 // closure for finding defs in a loop
00236 class LoopClosure : public Closure<Def*> {
00237 public:
00238   NonTrivialNode* defNode;
00239   CompiledLoop* theLoop;
00240 
00241   LoopClosure(CompiledLoop* l) { defNode = NULL; theLoop = l; }
00242 };
00243 
00244 
00245 // count all defs in loop
00246 class LoopDefCounter : public LoopClosure {
00247 public:
00248   int defCount;
00249   LoopDefCounter(CompiledLoop* l) : LoopClosure(l) { defCount = 0; }
00250 
00251   void do_it(Def* d) { 
00252     if (theLoop->isInLoop(d->node)) {
00253       defCount++;
00254       defNode = (NonTrivialNode*)d->node;
00255     } 
00256   }
00257 };
00258 
00259 
00260 int CompiledLoop::defsInLoop(PReg* r, NonTrivialNode** defNode) {
00261   // returns the number of definitions of r within the loop
00262   // also sets defNode to the last definition
00263   // BUG: won't work if loop has sends -- will ignore possible defs to inst vars etc.
00264   LoopDefCounter ldc(this);
00265   r->forAllDefsDo(&ldc);
00266   if (defNode) *defNode = ldc.defNode;
00267   return ldc.defCount;
00268 }
00269 
00270 
00271 class LoopDefFinder : public LoopClosure {
00272 public:
00273   LoopDefFinder(CompiledLoop* l) : LoopClosure(l) {}      // don't ask why this is necessary... (MS C++ 4.0)
00274   void do_it(Def* d) { if (theLoop->isInLoop(d->node)) defNode = d->node; }
00275 };
00276 
00277 
00278 NonTrivialNode* CompiledLoop::findDefInLoop(PReg* r) {
00279   assert(defsInLoop(r) == 1, "must have single definition in loop");
00280   LoopDefFinder ldf(this);
00281   r->forAllDefsDo(&ldf);
00282   return ldf.defNode;
00283 }
00284 
00285 
00286 char* CompiledLoop::checkLoopVar() {
00287 #ifdef unnecessary
00288   // first check if loop var is initialized to lower bound
00289   BB* beforeLoopBB = _beforeLoop->bb();
00290   // search for assignment preceeding loop
00291   for (Node* n = _beforeLoop; 
00292        n && n->bb() == beforeLoopBB && (!n->isAssignNode() || ((AssignNode*)n)->dest() != loopVar); 
00293        n = n->firstPrev()) ;
00294   if (n && n->bb() == beforeLoopBB) {
00295     // ok, found the assignment
00296     assert(n->isAssignNode() && ((AssignNode*)n)->dest() == loopVar, "oops");
00297   } else {
00298     return "no lower-bound assignment to loop var before loop";
00299   }
00300 #endif
00301   // check usage of loop var within loop
00302 
00303   // quick check: must have at least 2 defs (initialization plus increment)
00304   if (_loopVar->isSinglyAssigned()) return "loopVar has single definition globally";
00305 
00306   // loop variable must have exactly one def in loop, and def must be result of an addition
00307   // usual code pattern: SAPn = add(loopVar, const); ...; loopVar := SAPn
00308   if (defsInLoop(_loopVar) != 1) return "loopVar has != 1 defs in loop";
00309   NonTrivialNode* n1 = findDefInLoop(_loopVar);
00310   if (defsInLoop(n1->src()) != 1) return "loopVar has != 1 defs in loop (2)";
00311   NonTrivialNode* n2 = findDefInLoop(n1->src());
00312   PReg* operand;
00313   ArithOpCode op;
00314   if (n2->isTArithNode()) {
00315     operand = ((TArithRRNode*)n2)->operand();
00316     op = ((TArithRRNode*)n2)->op();
00317   } else if (n2->isArithNode()) {
00318     operand = ((ArithRRNode*)n2)->operand();
00319     op = ((ArithRRNode*)n2)->op();
00320   } else {
00321     return "loopVar def not an arithmetic operation";
00322   }
00323   _incNode = n2;
00324   if (op != tAddArithOp && op != tSubArithOp) return "loopVar def isn't an add/sub";
00325   if (_incNode->src() == _loopVar) {
00326     if (!isIncrement(operand, op)) return "loopVar isn't incremented by constant/loop-invariant";
00327   } else if (operand == _loopVar) {
00328     if (!isIncrement(_incNode->src(), op)) return "loopVar isn't incremented by constant/loop-invariant";
00329   } else {
00330     return "loopVar def isn't an increment";
00331   }
00332 
00333   // at this point, we finally know for sure whether the loop is counting up or down
00334   // check that loop is bounded at all 
00335   BranchOpCode branchOp = _loopBranch->op();
00336   bool loopVarMustBeLeft = (branchOp == GTBranchOp || branchOp == GEBranchOp) ^ !_isCountingUp;
00337   NonTrivialNode* compare = (NonTrivialNode*)_loopBranch->firstPrev();
00338   if (loopVarMustBeLeft != (compare->src() == _loopVar)) {
00339     return "loopVar is on wrong side of comparison (loop not bounded)";
00340   }
00341 
00342   return NULL;
00343 }
00344 
00345 
00346 bool CompiledLoop::isIncrement(PReg* p, ArithOpCode op) {
00347   // is p a suitable increment (i.e., a positive constant or loop-invariant variable)?
00348   _increment = p;
00349   if (p->isConstPReg()) {
00350     oop c = ((ConstPReg*)p)->constant;
00351     if (!c->is_smi()) return false;
00352     _isCountingUp = (smiOop(c)->value() > 0) ^ (op == tSubArithOp);
00353     return true;
00354   } else {
00355     // fix this: need to check sign in loop header
00356     return defsInLoop(p) == 0;
00357   }
00358 }
00359 
00360 
00361 char* CompiledLoop::checkUpperBound() {
00362   // upper bound must not be defined in loop (loop invariant)
00363   _loopArray = NULL;
00364   _loopSizeLoad = NULL;
00365   int ndefs = defsInLoop(_upperBound, NULL);
00366   if (ndefs > 0) return "upper bound isn't loop-invariant";
00367   // ok, no assignments in loop; check if upper bound is size of an array
00368   // search for assignment that reaches loop head
00369   Node* defNode;
00370   for (defNode = _beforeLoop; 
00371        defNode && defNode->nPredecessors() < 2 && 
00372          (!defNode->hasDest() || ((NonTrivialNode*)defNode)->dest() != _upperBound); 
00373        defNode = defNode->firstPrev()) ;
00374   if (defNode && defNode->isArraySizeLoad()) {
00375     // ok, upper bound is an array; can optimize array accesses if it is loop-invariant
00376     if (defsInLoop(_loopArray) == 0) {
00377       _loopSizeLoad = (LoadOffsetNode*)defNode;
00378       _loopArray = _loopSizeLoad->base();
00379     }
00380   }
00381   return NULL;
00382 }
00383 
00384 
00385 void CompiledLoop::optimizeIntegerLoop() {
00386   // need general loop opts as well (for array type checks)
00387   if (!OptimizeLoops) fatal("if OptimizeIntegerLoops is set, OptimizeLoops must be set too");
00388   if (!isIntegerLoop()) return; 
00389   // activate loop header (will check upper bound for smi-ness etc.)
00390   PReg* u = _loopSizeLoad ? NULL : _upperBound;
00391   _loopHeader->activate(_loopVar, _lowerBound, u, _loopSizeLoad);
00392   _loopHeader->_integerLoop = true;
00393   removeTagChecks();
00394   checkForArraysDefinedInLoop();
00395   if (_loopArray) {
00396     // upper bound is loopArray's size --> counter can't overflow
00397     removeLoopVarOverflow();
00398     // also, array accesses need no bounds check
00399     removeBoundsChecks(_loopArray, _loopVar);
00400     // potential performance bug: should do bounds check for all array accesses with loop-invariant index
00401   } else {
00402     // fix this: must check upper bound against maxInt
00403     removeLoopVarOverflow();
00404   }
00405 }
00406 
00407 
00408 // closure for untagging defs/uses of loop var
00409 class UntagClosure : public Closure<Use*> {
00410 public:
00411   CompiledLoop* theLoop;
00412   PReg* theLoopPReg;
00413   GrowableArray<klassOop>* smi_type;
00414 
00415   UntagClosure(CompiledLoop* l, PReg* r) { 
00416     theLoop = l; theLoopPReg = r; smi_type = new GrowableArray<klassOop>(1); smi_type->append(smiKlassObj); 
00417   }
00418   void do_it(Use* u) {
00419     if (theLoop->isInLoop(u->node)) {
00420       u->node->assert_preg_type(theLoopPReg, smi_type, theLoop->loopHeader());
00421     }
00422   }
00423 };
00424 
00425 
00426 void CompiledLoop::removeTagChecks() {
00427   // Eliminate all tag checks for loop variable and upper bound
00428   // As a side effect, this will add all arrays indexed by the loop variable to the LoopHeaderNode
00429   UntagClosure uc(this, _loopVar);
00430   _loopVar->forAllUsesDo(&uc);
00431   if (_lowerBound) {
00432     uc.theLoopPReg = _lowerBound;
00433     _lowerBound->forAllUsesDo(&uc);
00434   }
00435   uc.theLoopPReg = _upperBound;
00436   _upperBound->forAllUsesDo(&uc);
00437 }
00438 
00439 
00440 void CompiledLoop::removeLoopVarOverflow() {
00441   // bug: should remove overflow only if increment is constant and not too large -- fix this
00442   Node* n = _incNode->next();
00443   assert(n->isBranchNode(), "must be branch");
00444   BranchNode* overflowCheck = (BranchNode*)n;
00445   assert(overflowCheck->op() == VSBranchOp, "should be overflow check");
00446   if (CompilerDebug || PrintLoopOpts) {
00447     cout(PrintLoopOpts)->print("*removing overflow check at node N%d\n", overflowCheck->id());
00448   }
00449   Node* taken = overflowCheck->next(1);   // overflow handling code
00450   taken->removeUpToMerge();
00451   overflowCheck->removeNext(taken);       // so overflowCheck can be eliminated
00452   overflowCheck->eliminate(overflowCheck->bb(), NULL, true, false);
00453 
00454   // since increment cannot fail anymore, directly increment loop counter if possible
00455   // need to search for assignment of incremented value to loop var
00456   Node* a = overflowCheck->next();
00457   while (1) {
00458     if (a->nPredecessors() > 1) break;    // can't search beyond merge
00459     if (a->nSuccessors()   > 1) break;    // can't search beyond branches
00460     if (a->isAssignNode()) {
00461       if (!a->deleted) {
00462         AssignNode* assign = (AssignNode*)a;
00463         if (assign->src() == _incNode->dest() && assign->dest() == _loopVar) {
00464           if (CompilerDebug || PrintLoopOpts) {
00465             cout(PrintLoopOpts)->print("*optimizing loopVar increment at N%d\n", _incNode->id());
00466           }
00467           _incNode->setDest(_incNode->bb(), _loopVar);
00468           assign->eliminate(assign->bb(), NULL, true, false);
00469         }
00470       }
00471     } else if (!a->isTrivial()) {
00472       compiler_warning("unexpected nontrivial node N%d after loopVar increment\n", a->id());
00473     }
00474     a = a->next();
00475   }
00476 }
00477 
00478 
00479 void CompiledLoop::checkForArraysDefinedInLoop() {
00480   // remove all arrays from loopHeader's list which are defined in the loop
00481   GrowableArray<AbstractArrayAtNode*> arraysToRemove(10);
00482   int len = _loopHeader->_arrayAccesses->length();
00483   for (int i = 0; i < len; i++) {
00484     AbstractArrayAtNode* n = _loopHeader->_arrayAccesses->at(i);
00485     if (defsInLoop(n->src())) arraysToRemove.append(n);
00486   }
00487   while (arraysToRemove.nonEmpty()) {
00488     AbstractArrayAtNode* n = arraysToRemove.pop();
00489     _loopHeader->_arrayAccesses->remove(n);
00490   }
00491 }
00492 
00493 
00494 void CompiledLoop::optimize() {
00495   // general loop optimizations
00496   hoistTypeTests();
00497   findRegCandidates();
00498 }
00499 
00500 
00501 class TTHoister : public Closure<InlinedScope*> {
00502  public:
00503   GrowableArray<HoistedTypeTest*>* hoistableTests;
00504   CompiledLoop* theLoop;
00505 
00506   TTHoister(CompiledLoop* l, GrowableArray<HoistedTypeTest*>* h) { hoistableTests = h; theLoop = l; }
00507 
00508   void do_it(InlinedScope* s) {
00509     GrowableArray<NonTrivialNode*>* tests = s->typeTests();
00510     int len = tests->length();
00511     for (int i = 0; i < len; i++) {
00512       NonTrivialNode* n = tests->at(i);
00513       assert(n->doesTypeTests(), "shouldn't be in list");
00514       if (n->deleted) continue;
00515       if (n->hasUnknownCode()) continue;          // can't optimize - expects other klasses, so would get uncommon trap at run-time
00516       if (!theLoop->isInLoop(n)) continue;        // not in this loop
00517       GrowableArray<PReg*> regs(4);
00518       GrowableArray<GrowableArray<klassOop>*> klasses(4);
00519       n->collectTypeTests(regs, klasses);
00520       for (int j = 0; j < regs.length(); j++) {
00521         PReg* r = regs.at(j);
00522         if (theLoop->defsInLoop(r) == 0) {
00523           // this test can be hoisted
00524           if (CompilerDebug || PrintLoopOpts) cout(PrintLoopOpts)->print("*moving type test of %s at N%d out of loop\n", r->name(), n->id());
00525           hoistableTests->append(new HoistedTypeTest(n, r, klasses.at(j)));
00526         }
00527       }
00528     }
00529   }
00530 };
00531 
00532 
00533 void CompiledLoop::hoistTypeTests() {
00534   // collect all type tests that can be hoisted out of the loop
00535   _loopHeader->_tests = _hoistableTests = new GrowableArray<HoistedTypeTest*>(10);
00536   TTHoister tth(this, _hoistableTests);
00537   _scope->subScopesDo(&tth);
00538 
00539   // add type tests to loop header for testing (avoid duplicates)
00540   // (currently quadratic algorithm but there should be very few)
00541   GrowableArray<HoistedTypeTest*>* headerTests = new GrowableArray<HoistedTypeTest*>(_hoistableTests->length());
00542   for (int i = _hoistableTests->length() - 1; i >= 0; i--) {
00543     HoistedTypeTest* t = _hoistableTests->at(i);
00544     PReg* tested = t->testedPR;
00545     for (int j = headerTests->length() - 1; j >= 0; j--) {
00546       if (headerTests->at(j)->testedPR == tested) {
00547         // already testing this PReg
00548         if (isEquivalentType(headerTests->at(j)->klasses, t->klasses)) {
00549           // nothing to do
00550         } else {
00551           // Whoa!  The same PReg is tested for different types in different places.
00552           // Possible but rare.
00553           headerTests->at(j)->invalid = t->invalid = true;
00554           if (WizardMode) {
00555             compiler_warning("CompiledLoop::hoistTypeTests: PReg tested for different types\n");
00556             t->print();
00557             headerTests->at(j)->print();
00558           }
00559         }
00560         tested = NULL;    // don't add it to list
00561         break;
00562       }
00563     }
00564     if (tested) headerTests->append(t);
00565   }
00566 
00567   // now delete all hoisted type tests from loop body
00568   for (i = _hoistableTests->length() - 1; i >= 0; i--) {
00569     HoistedTypeTest* t = _hoistableTests->at(i);
00570     if (!t->invalid) {
00571       t->node->assert_preg_type(t->testedPR, t->klasses, _loopHeader);
00572     }
00573   }
00574   if (!_loopHeader->isActivated()) _loopHeader->activate();
00575 }
00576 
00577 bool CompiledLoop::isEquivalentType(GrowableArray<klassOop>* klasses1, GrowableArray<klassOop>* klasses2) {
00578   // are the two lists klasses1 and klasses2 equivalent (i.e., contain the same set of klasses)?
00579   if (klasses1->length() != klasses2->length()) return false;
00580   for (int i = klasses2->length() - 1; i >= 0; i--) {
00581     if (klasses1->at(i) != klasses2->at(i)    // quick check
00582         && (!klasses1->contains(klasses2->at(i)) || !klasses2->contains(klasses1->at(i))) ) { // slow check
00583       return false;
00584     }
00585   }
00586   return true;
00587 }
00588 
00589 
00590 class BoundsCheckRemover : public Closure<Use*> {
00591 public:
00592   CompiledLoop* theLoop;
00593   PReg* theLoopPReg;
00594   GrowableArray<AbstractArrayAtNode*>* theArrayList;
00595 
00596   BoundsCheckRemover(CompiledLoop* l, PReg* r, GrowableArray<AbstractArrayAtNode*>* arrays) {
00597     theLoop = l; theLoopPReg = r; theArrayList = arrays;
00598   }
00599   void do_it(Use* u) {
00600     if (theLoop->isInLoop(u->node) &&
00601         // the cast to AbstractArrayAtNode* isn't correct (u->node may be something else),
00602         // but it's safe since we're only searching in the array list using pointer identity
00603         theArrayList->contains((AbstractArrayAtNode*)u->node)) {
00604       u->node->assert_in_bounds(theLoopPReg, theLoop->loopHeader());
00605     }
00606   }
00607 };
00608 
00609 
00610 void CompiledLoop::removeBoundsChecks(PReg* array, PReg* var) {
00611   // Remove all bounds checks for nodes where var indexes into array.
00612   // This means that the arrays must be type- and bounds-checked in the loop header.
00613   // Thus, only do it for arrays that aren't defined within the loop, i.e.,
00614   // those in the loop header's list of arrays.
00615   BoundsCheckRemover bcr(this, var, _loopHeader->_arrayAccesses);
00616   array->forAllUsesDo(&bcr);
00617 }
00618 
00619 void CompiledLoop::findRegCandidates() {
00620   // Find the PRegs with the highest number of defs & uses in this loop.
00621   // Problem: we don't have a list of all PRegs used in the loop; in fact, we don't even have
00622   // a list of all nodes.
00623   // Solution: iterate through all BBs between start and end of loop (in code generation order)
00624   // and collect the defs and uses.  The BB ordering algorithm should make sure that the BBs
00625   // of the loop are consecutive.
00626   if (_bbs == NULL) _bbs = bbIterator->code_generation_order();
00627   GrowableArray<LoopRegCandidate*> candidates(PReg::currentNo, PReg::currentNo, NULL);
00628   const int len = _bbs->length();
00629   const BB* startBB = _startOfLoop->bb();
00630   int i;
00631   for (i = 0; _bbs->at(i) != startBB; i++) ;    // search for first BB
00632   const BB* endBB = _endOfLoop->bb();
00633   int ncalls = 0;
00634 
00635   // iterate through all BBs in the loop
00636   for (BB* bb = _bbs->at(i); bb != endBB; i++, bb = _bbs->at(i)) {
00637     const int n = bb->duInfo.info->length();
00638     if (bb->last->isCallNode()) ncalls++;
00639     for (int j = 0; j < n; j++) {
00640       DUInfo* info = bb->duInfo.info->at(j);
00641       PReg* r = info->reg;
00642       if (candidates.at(r->id()) == NULL) candidates.at_put(r->id(), new LoopRegCandidate(r));
00643       LoopRegCandidate* c = candidates.at(r->id());
00644       c->incDUs(info->uses.length(), info->defs.length());
00645     }
00646   }
00647   loopHeader()->set_nofCallsInLoop(ncalls);
00648 
00649   // find the top 2 candidates...
00650   LoopRegCandidate* first  = new LoopRegCandidate(NULL);
00651   LoopRegCandidate* second = new LoopRegCandidate(NULL);
00652   for (int j = candidates.length() - 1; j >= 0; j--) {
00653     LoopRegCandidate* c = candidates.at(j);
00654     if (c == NULL) continue;
00655     if (c->weight() > first->weight()) {
00656       second = first; first = c;
00657     } else if (c->weight() > second->weight()) {
00658       second = c;
00659     }
00660   }
00661 
00662   // ...and add them to the loop header 
00663   if (first->preg() != NULL) {
00664     loopHeader()->addRegisterCandidate(first);
00665     if (second->preg() != NULL) {
00666       loopHeader()->addRegisterCandidate(second);
00667     }
00668   } else {
00669     assert(second->preg() == NULL, "bad sorting");
00670   }
00671 }
00672 
00673 void CompiledLoop::print() {
00674   std->print("((CompiledLoop*)%#x) = [N%d..N%d], cond = [N%d..N%d], body = [N%d..N%d] (bci %d..%d)\n", 
00675           this, _firstNodeID, _lastNodeID, _startOfCond->id(), _endOfCond->id(), 
00676           _startOfBody->id(), _endOfBody->id(),
00677           _startOfLoop->bci(), _endOfLoop->bci());
00678   std->print("\tloopVar=%s, lower=%s, upper=%s\n", _loopVar->safeName(), _lowerBound->safeName(), _upperBound->safeName());
00679 }
00680 
00681 
00682 HoistedTypeTest::HoistedTypeTest(NonTrivialNode* node, PReg* testedPR, GrowableArray<klassOop>* klasses) {
00683   this->node = node; this->testedPR = testedPR; this->klasses = klasses; invalid = false;
00684 }
00685 
00686 
00687 void HoistedTypeTest::print_test_on(outputStream* s) {
00688   s->print("%s = {", testedPR->name());
00689   int len = klasses->length();
00690   for (int j = 0; j < len; j++) {
00691     klassOop m = klasses->at(j);
00692     m->print_value_on(s);
00693     if (j < len - 1) s->print(",");
00694   }
00695   s->print("}");
00696 }
00697 
00698 
00699 void HoistedTypeTest::print() {
00700   std->print("((HoistedTypeTest*)%#x): ", this);
00701   print_test_on(std);
00702   std->cr();
00703 }
00704 
00705 void LoopRegCandidate::print() {
00706   std->print("((LoopRegCandidate*)%#x): %s, %d uses, %d defs\n", this, _preg->name(), _nuses, _ndefs);
00707 }
00708 
00709 # endif

Generated on Mon Oct 9 13:37:13 2006 for Strongtalk VM by  doxygen 1.4.7