Return-Path: Delivered-To: apmail-harmony-commits-archive@www.apache.org Received: (qmail 18092 invoked from network); 4 Apr 2007 10:06:38 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 4 Apr 2007 10:06:38 -0000 Received: (qmail 85385 invoked by uid 500); 4 Apr 2007 10:06:45 -0000 Delivered-To: apmail-harmony-commits-archive@harmony.apache.org Received: (qmail 85368 invoked by uid 500); 4 Apr 2007 10:06:45 -0000 Mailing-List: contact commits-help@harmony.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@harmony.apache.org Delivered-To: mailing list commits@harmony.apache.org Received: (qmail 85355 invoked by uid 99); 4 Apr 2007 10:06:44 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 04 Apr 2007 03:06:44 -0700 X-ASF-Spam-Status: No, hits=-99.5 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 04 Apr 2007 03:06:37 -0700 Received: by eris.apache.org (Postfix, from userid 65534) id AC0C61A9838; Wed, 4 Apr 2007 03:06:16 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r525483 - in /harmony/enhanced/drlvm/trunk/vm/jitrino/src: codegenerator/ia32/Ia32FastArrayFilling.cpp codegenerator/ia32/Ia32GCSafePoints.cpp codegenerator/ia32/Ia32InstCodeSelector.cpp optimizer/FastArrayFilling.cpp Date: Wed, 04 Apr 2007 10:06:15 -0000 To: commits@harmony.apache.org From: varlax@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20070404100616.AC0C61A9838@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: varlax Date: Wed Apr 4 03:06:12 2007 New Revision: 525483 URL: http://svn.apache.org/viewvc?view=rev&rev=525483 Log: Applied HARMONY-3423 [drlvm][jit][opt] SPECjbb2005 fails on DRLVM on Linux/EM64T in -Xem:server mode with extended inliner parameters Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32FastArrayFilling.cpp harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32GCSafePoints.cpp harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/FastArrayFilling.cpp Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32FastArrayFilling.cpp URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32FastArrayFilling.cpp?view=diff&rev=525483&r1=525482&r2=525483 ============================================================================== --- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32FastArrayFilling.cpp (original) +++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32FastArrayFilling.cpp Wed Apr 4 03:06:12 2007 @@ -35,6 +35,11 @@ void FastArrayFilling::runImpl() { + /* + find and replace particular internal helper (inserted by HLO path) + with a loop providing fast array filling with a constant. + */ + const Nodes& nodes = irManager->getFlowGraph()->getNodesPostOrder(); for (Nodes::const_reverse_iterator it = nodes.rbegin(),end = nodes.rend();it!=end; ++it) { Node* bb = *it; @@ -70,8 +75,8 @@ Node * nextNode = outEdge->getTargetNode(); //extract operands from the internal helper instruction - Inst::Opnds opnds(inst, Inst::OpndRole_Use|Inst::OpndRole_Explicit|Inst::OpndRole_Auxilary); - Inst::Opnds::iterator ito = opnds.begin()+1; + Inst::Opnds opnds(inst, Inst::OpndRole_Use|Inst::OpndRole_Auxilary); + Inst::Opnds::iterator ito = opnds.begin(); // Opnd* args[4] = {valueOp, arrayRef, arrayBound, baseOp}; Opnd * value = inst->getOpnd(ito++); @@ -106,16 +111,21 @@ Opnd * index = irManager->newOpnd(ptrToIntType); bb->appendInst(irManager->newCopyPseudoInst(Mnemonic_MOV, index, arrayBase)); + //create increment + Opnd * incOp = irManager->newOpnd(intPtrType); + bb->appendInst(irManager->newCopyPseudoInst(Mnemonic_MOV, incOp, irManager->newImmOpnd(intPtrType,8))); + Node * loopNode = fg->createNode(Node::Kind_Block); //insert filling instructions Opnd * memOp1 = irManager->newMemOpndAutoKind(value->getType(), index); - Opnd * memOp2 = irManager->newMemOpndAutoKind(value->getType(), index,irManager->newImmOpnd(int32Type,4)); loopNode->appendInst(irManager->newCopyPseudoInst(Mnemonic_MOV, memOp1, value)); +#ifndef _EM64T_ + Opnd * memOp2 = irManager->newMemOpndAutoKind(value->getType(), index,irManager->newImmOpnd(int32Type,4)); loopNode->appendInst(irManager->newCopyPseudoInst(Mnemonic_MOV, memOp2, value)); - +#endif + //increment the element address - Opnd * incOp = irManager->newImmOpnd(intPtrType,8); loopNode->appendInst(irManager->newInst(Mnemonic_ADD, index, incOp)); //compare the element address with the end of the array Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32GCSafePoints.cpp URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32GCSafePoints.cpp?view=diff&rev=525483&r1=525482&r2=525483 ============================================================================== --- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32GCSafePoints.cpp (original) +++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32GCSafePoints.cpp Wed Apr 4 03:06:12 2007 @@ -321,18 +321,35 @@ return res; } +static bool isHeapBase(Opnd* immOpnd) { + assert(immOpnd->isPlacedIn(OpndKind_Imm)); +#ifndef _EM64T_ + return false; +#else + int64 heapBase = (int64)VMInterface::getHeapBase(); + return immOpnd->getImmValue() == heapBase; +#endif +} + +static Opnd* findImmediateSource(Opnd* opnd) { + Opnd* res = opnd; + while (!res->isPlacedIn(OpndKind_Imm)) { + Inst* defInst = res->getDefiningInst(); + if (!defInst || defInst->getMnemonic()!=Mnemonic_MOV) { + return NULL; + } + res = defInst->getOpnd(1); + } + return res; +} int32 GCSafePointsInfo::getOffsetFromImmediate(Opnd* offsetOpnd) const { if (offsetOpnd->isPlacedIn(OpndKind_Immediate)) { if (offsetOpnd->getImmValue() == 0 && offsetOpnd->getRuntimeInfo()!=NULL) { irm.resolveRuntimeInfo(offsetOpnd); } -#ifndef _EM64T_ + assert(!isHeapBase(offsetOpnd)); return (int32)offsetOpnd->getImmValue(); -#else - return offsetOpnd->getImmValue() == (int64)VMInterface::getHeapBase() ? - 0 : (int32)offsetOpnd->getImmValue(); -#endif } return MPTR_OFFSET_UNKNOWN; } @@ -486,16 +503,15 @@ #endif fromOpnd = opnd; Opnd* offsetOpnd = inst->getOpnd(useIndex1); - if (offsetOpnd->isPlacedIn(OpndKind_Immediate)) { - offset = getOffsetFromImmediate(offsetOpnd); + Opnd* immOffset = findImmediateSource(offsetOpnd); + if (immOffset) { + if (isHeapBase(immOffset)) { + offset = 0; + } else { + offset = getOffsetFromImmediate(immOffset); + } } else { - assert(offsetOpnd->isPlacedIn(OpndKind_Memory) || offsetOpnd->isPlacedIn(OpndKind_Reg)); -#ifdef _EM64T_ - if(offsetOpnd->getDefiningInst() && offsetOpnd->getDefiningInst()->getMnemonic() == Mnemonic_MOV && offsetOpnd->getDefiningInst()->getOpnd(1)->isPlacedIn(OpndKind_Immediate)) - offset = getOffsetFromImmediate(offsetOpnd->getDefiningInst()->getOpnd(1)); - else -#endif - offset = MPTR_OFFSET_UNKNOWN; + offset = MPTR_OFFSET_UNKNOWN; } } break; Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp?view=diff&rev=525483&r1=525482&r2=525483 ============================================================================== --- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp (original) +++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp Wed Apr 4 03:06:12 2007 @@ -149,6 +149,7 @@ } void __stdcall fill_array_with_const(uint32 copyOp, uint32 arrayRef, uint32 arrayBound, uint32 baseOp) { + Jitrino::crash("Illegal internal helper was called.\n Please enable cg_fastArrayFill optimization in the code generator path"); assert(0); return; } Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/FastArrayFilling.cpp URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/FastArrayFilling.cpp?view=diff&rev=525483&r1=525482&r2=525483 ============================================================================== --- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/FastArrayFilling.cpp (original) +++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/FastArrayFilling.cpp Wed Apr 4 03:06:12 2007 @@ -48,6 +48,48 @@ void FastArrayFillPass::_run(IRManager& irManager) { + /* + This pass tries to find the array filling code pattern and adds + new code under a branch. The new code will be executed in the case of + array filling goes from first to last index of the array. + + Example (C++ like): + + Old code: + + char[] a = new char[100]; + char c = 1; + int num = 100; + for (int i = 0; i < num; i++) { + a[i] = c; + } + + New code: + + char[] a = new char[100]; + int num = 100; + if (num == lengthof(a)) { + int * b = (int *)a; + int cc = 1 | (1 << 16) + for (int i = 0; i < 100; i += 2) { + b[i] = cc; + } + } else { + char c = 1; + int num = 100; + for (int i = 0; i < num; i++) { + a[i] = c; + } + } + + The pattern depends on loop peeling, de-SSA pass and ABCD pass. + Also it needs cg_fastArrayFill pass in code generator. + + Seems like this pass could be moved into the translator phase with + significant reducing of the pattern and removing of dependencies + from HLO optimizations. + */ + LoopTree * info = irManager.getLoopTree(); if (!info->isValid()) { info->rebuild(false); @@ -60,6 +102,7 @@ Edges loopEdges(tmm); StlMap loopInfo(tmm); + //collect necessary information about loops const Nodes& nodes = irManager.getFlowGraph().getNodes(); for (Nodes::const_iterator it = nodes.begin(), end = nodes.end(); it!=end; ++it) { Node* node = *it; @@ -84,6 +127,37 @@ } //check found loops for pattern + /* Code pattern: + + label .node1 + arraylen arrayRef ((tau1,tau3)) -) arrayBound:int32 + chkub 0 .lt. arrayBound -) tau2:tau + GOTO .node2 + + label .node2 + ldbase arrayRef -) arrayBase:ref:char + stind.unc:chr constValue ((tau1,tau2,tau3)) -) [arrayBase] + stvar startIndex -) index:int32 + GOTO .loopNode1 + + label .loopNode1 + ldvar index -) tmpIndex:int32 + if cge.i4 tmpIndex, fillBound goto .loopExit + GOTO .node2 + + label .loopNode2 + chkub tmpIndex .lt. arrayBound -) tau2:tau + GOTO .node3 + + label .loopNode3 + addindex arrayBase, tmpIndex -) address:ref:char + stind.unc:chr constValue ((tau1,tau2,tau3)) -) [address] + add tmpIndex, addOp -) inc:int32 + stvar inc -) index:int32 + GOTO .node1 + + */ + for(StlMap::const_iterator it = loopInfo.begin(); it != loopInfo.end(); ++it) { Edge * backEdge = it->second.backEdge; @@ -103,6 +177,7 @@ Inst * inst = ((Inst *)startNode->getLastInst()); bool found = false; + //check StVar if (inst->getOpcode() == Op_StVar) { index = inst->getDst(); @@ -210,49 +285,73 @@ inEdge = startNode->getInEdges().front(); //get a new constant - int val = ((ConstInst*)constValue->getInst())->getValue().i4; +#ifdef _EM64T_ + int64 val = (int64)((ConstInst*)constValue->getInst())->getValue().i8; +#else + int32 val = (int32)((ConstInst*)constValue->getInst())->getValue().i4; +#endif switch (((Type*)arrayRef->getType()->asArrayType()->getElementType())->tag) { case Type::Int8: case Type::Boolean: case Type::UInt8: val |= (val << 8); val |= (val << 16); +#ifdef _EM64T_ + val |= (val << 32); +#endif break; case Type::Int16: case Type::UInt16: case Type::Char: val |= (val << 16); +#ifdef _EM64T_ + val |= (val << 32); +#endif break; case Type::Int32: case Type::UInt32: +#ifdef _EM64T_ + val |= (val << 32); + break; +#endif case Type::UIntPtr: case Type::IntPtr: +#ifdef _EM64T_ + case Type::UInt64: + case Type::Int64: +#endif break; default: continue; } + //split node1 (see code pattern) after arraylen instruction + //and insert a check whether fillBound is equal to arrayBound. + //if not equal then go to the regular loop ControlFlowGraph& fg = irManager.getFlowGraph(); Node * preheader = fg.splitNodeAtInstruction(inst, true, false, irManager.getInstFactory().makeLabel()); Inst * cmp = irManager.getInstFactory().makeBranch(Cmp_NE_Un, arrayBound->getType()->tag, arrayBound, fillBound, (LabelInst *)preheader->getFirstInst()); startNode->appendInst(cmp); + //create a node with some instructions to prepare variables for loop Node * prepNode = fg.createBlockNode(irManager.getInstFactory().makeLabel()); fg.addEdge(startNode,prepNode); OpndManager& opndManager = irManager.getOpndManager(); - Opnd * copyOp = opndManager.createArgOpnd(irManager.getTypeManager().getInt32Type()); + Opnd * copyOp = opndManager.createArgOpnd(irManager.getTypeManager().getIntPtrType()); Inst * copyInst = irManager.getInstFactory().makeLdConst(copyOp,val); prepNode->appendInst(copyInst); + //insert ldbase instruction Opnd *baseOp = opndManager.createArgOpnd(irManager.getTypeManager().getIntPtrType()); Inst * ldBaseInst = irManager.getInstFactory().makeLdArrayBaseAddr(arrayRef->getType()->asArrayType()->getElementType(),baseOp, arrayRef); prepNode->appendInst(ldBaseInst); Opnd* args[4] = {copyOp, arrayRef, arrayBound, baseOp}; - // add jit helper + // insert the helper. + // this helper should be expanded in the code generator phase Inst* initInst = irManager.getInstFactory().makeJitHelperCall( OpndManager::getNullOpnd(), FillArrayWithConst, 4, args); prepNode->appendInst(initInst);