harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mfur...@apache.org
Subject svn commit: r557942 [1/2] - in /harmony/enhanced/drlvm/trunk/vm: jitrino/config/ia32/ jitrino/src/codegenerator/ jitrino/src/codegenerator/ia32/ jitrino/src/codegenerator/ipf/include/ jitrino/src/optimizer/ jitrino/src/shared/ vmcore/src/jit/
Date Fri, 20 Jul 2007 09:40:10 GMT
Author: mfursov
Date: Fri Jul 20 02:40:02 2007
New Revision: 557942

URL: http://svn.apache.org/viewvc?view=rev&rev=557942
Log:
Loop unrolling optimization is integrated and added into IA32 configs (HARMONY-3076)
+
HARMONY-4025 and HARMONY-4026 - adding 'unsafe' markup for TC
HARMONY-2533 - minor cleanup of  unused and deprecated  opcodes in HIR


Added:
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/loop_unroll.cpp
Modified:
    harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/client.emconf
    harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/opt.emconf
    harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/server.emconf
    harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/server_static.emconf
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/CodeGenIntfc.h
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32BBPolling.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.h
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ipf/include/IpfCodeSelector.h
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/CodeSelectors.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/FlowGraph.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/FlowGraph.h
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/IRBuilder.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/IRBuilder.h
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Inst.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Inst.h
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Loop.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Opcode.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Opcode.h
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/codelowerer.h
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/hashvaluenumberer.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/lazyexceptionopt.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/memoryopt.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/reassociate.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/simplifier.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/simplifier.h
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/simplifytaus.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/shared/ControlFlowGraph.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/shared/ControlFlowGraph.h
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/shared/LoopTree.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/jit/jit_runtime_support.cpp

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/client.emconf
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/client.emconf?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/client.emconf (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/client.emconf Fri Jul 20 02:40:02 2007
@@ -53,7 +53,7 @@
 
 -XX:jit.CD_OPT.path=opt_init,translator,optimizer,hir2lir,codegen
 
--XX:jit.CD_OPT.path.optimizer=ssa,devirt,inline,uce,purge,simplify,dce,uce,lazyexc,memopt,simplify,dce,uce,lower,dessa,statprof,markglobals
+-XX:jit.CD_OPT.path.optimizer=ssa,devirt,inline,uce,purge,simplify,dce,uce,lazyexc,memopt,simplify,dce,uce,lower,statprof,unroll,ssa,simplify,dce,uce,dessa,statprof,markglobals
 -XX:jit.CD_OPT.path.codegen=lock_method,bbp,btr,gcpoints,cafl,dce1,i8l,api_magic,early_prop,peephole,itrace-,native,constraints,dce2,regalloc,spillgen,copy,i586,layout,rce+,stack,break-,iprof-,peephole,emitter!,si_insts,gcmap,info,unlock_method
 -XX:jit.CD_OPT.path.dce1=cg_dce
 -XX:jit.CD_OPT.path.dce2=cg_dce

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/opt.emconf
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/opt.emconf?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/opt.emconf (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/opt.emconf Fri Jul 20 02:40:02 2007
@@ -24,7 +24,7 @@
 
 -XX:jit.CS_OPT.path=opt_init,translator,optimizer,hir2lir,codegen
 
--XX:jit.CS_OPT.path.optimizer=ssa,devirt,inline,uce,purge,simplify,dce,uce,lazyexc,escape,dce,uce,memopt,simplify,dce,uce,lower,dessa,statprof,markglobals
+-XX:jit.CS_OPT.path.optimizer=ssa,devirt,inline,uce,purge,simplify,dce,uce,lazyexc,escape,dce,uce,memopt,simplify,dce,uce,lower,statprof,unroll,ssa,simplify,dce,uce,dessa,statprof,markglobals
 -XX:jit.CS_OPT.path.codegen=lock_method,bbp,btr,gcpoints,cafl,dce1,i8l,api_magic,early_prop,peephole,itrace-,native,constraints,dce2,regalloc,spillgen,copy,i586,layout,rce+,stack,break-,iprof-,peephole,emitter!,si_insts,gcmap,info,unlock_method
 -XX:jit.CS_OPT.path.dce1=cg_dce
 -XX:jit.CS_OPT.path.dce2=cg_dce

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/server.emconf
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/server.emconf?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/server.emconf (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/server.emconf Fri Jul 20 02:40:02 2007
@@ -71,7 +71,7 @@
 
 -XX:jit.SD2_OPT.path=opt_init,translator,optimizer,hir2lir,codegen
 
--XX:jit.SD2_OPT.path.optimizer=ssa,simplify,dce,uce,devirt_virtual,edge_annotate,unguard,devirt_intf,inline,uce,purge,simplify,dce,uce,lazyexc,so2-,simplify,dce,uce,escape,inline_helpers,purge,simplify,uce,dce,dessa,statprof,peel,ssa,hvn,simplify,dce,uce,lower,dce,uce,memopt,reassoc,dce,uce,hvn,dce,uce,classic_abcd,dce,uce,gcm,dessa,fastArrayFill,statprof,markglobals
+-XX:jit.SD2_OPT.path.optimizer=ssa,simplify,dce,uce,devirt_virtual,edge_annotate,unguard,devirt_intf,inline,uce,purge,simplify,dce,uce,lazyexc,so2-,simplify,dce,uce,escape,inline_helpers,purge,simplify,uce,dce,dessa,statprof,peel,ssa,hvn,simplify,dce,uce,lower,dce,uce,statprof,unroll,ssa,simplify,dce,uce,memopt,reassoc,dce,uce,hvn,dce,uce,classic_abcd,dce,uce,gcm,dessa,fastArrayFill,statprof,markglobals
 -XX:jit.SD2_OPT.path.codegen=lock_method,bbp,btr,gcpoints,cafl,dce1,i8l,api_magic,early_prop,peephole,itrace-,native,cg_fastArrayFill,constraints,dce2,regalloc,spillgen,copy,i586,layout,rce+,stack,break-,iprof-,peephole,emitter!,si_insts,gcmap,info,unlock_method
 -XX:jit.SD2_OPT.path.dce1=cg_dce
 -XX:jit.SD2_OPT.path.dce2=cg_dce

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/server_static.emconf
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/server_static.emconf?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/server_static.emconf (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/server_static.emconf Fri Jul 20 02:40:02 2007
@@ -24,7 +24,7 @@
 
 -XX:jit.SS_OPT.path=opt_init,translator,optimizer,hir2lir,codegen
 
--XX:jit.SS_OPT.path.optimizer=ssa,simplify,dce,uce,statprof,devirt,inline,uce,purge,simplify,dce,uce,lazyexc,hvn,dce,uce,dessa,statprof,peel,ssa,hvn,simplify,dce,uce,lower,dce,uce,memopt,reassoc,dce,uce,hvn,dce,uce,classic_abcd,dce,uce,gcm,dessa,statprof,markglobals
+-XX:jit.SS_OPT.path.optimizer=ssa,simplify,dce,uce,statprof,devirt,inline,uce,purge,simplify,dce,uce,lazyexc,statprof,hvn,dce,uce,dessa,statprof,peel,ssa,hvn,simplify,dce,uce,lower,dce,uce,unroll,ssa,simplify,dce,uce,memopt,reassoc,dce,uce,hvn,dce,uce,classic_abcd,dce,uce,gcm,dessa,statprof,markglobals
 -XX:jit.SS_OPT.path.codegen=lock_method,bbp,btr,gcpoints,cafl,dce1,i8l,api_magic,early_prop,peephole,itrace-,native,constraints,dce2,regalloc,spillgen,copy,i586,layout,rce+,stack,break-,iprof-,peephole,emitter!,si_insts,gcmap,info,unlock_method
 -XX:jit.SS_OPT.path.dce1=cg_dce
 -XX:jit.SS_OPT.path.dce2=cg_dce

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/CodeGenIntfc.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/CodeGenIntfc.h?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/CodeGenIntfc.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/CodeGenIntfc.h Fri Jul 20 02:40:02 2007
@@ -190,7 +190,6 @@
     virtual CG_OpndHandle*  sub(ArithmeticOp::Types,CG_OpndHandle* src1,CG_OpndHandle* src2) = 0;
     virtual CG_OpndHandle*  subRef(RefArithmeticOp::Types,CG_OpndHandle* refSrc, CG_OpndHandle* intSrc) = 0;
     virtual CG_OpndHandle*  diffRef(bool ovf, CG_OpndHandle* ref1,CG_OpndHandle* ref2) = 0;
-    virtual CG_OpndHandle*  scaledDiffRef(CG_OpndHandle*, CG_OpndHandle*, Type*, Type*) = 0;
     virtual CG_OpndHandle*  mul(ArithmeticOp::Types,CG_OpndHandle* src1,CG_OpndHandle* src2) = 0;
     virtual CG_OpndHandle*  tau_div(DivOp::Types,CG_OpndHandle* src1,CG_OpndHandle* src2,
                                     CG_OpndHandle *tauSrc1NonZero) = 0;
@@ -222,7 +221,6 @@
     // END PRED DEPRECATED
 
     // result is a predicate
-    virtual CG_OpndHandle*  pred_cmp(CompareOp::Operators,CompareOp::Types,CG_OpndHandle* src1,CG_OpndHandle* src2) = 0;
     virtual CG_OpndHandle*  pred_czero(CompareZeroOp::Types,CG_OpndHandle* src) = 0;
     virtual CG_OpndHandle*  pred_cnzero(CompareZeroOp::Types,CG_OpndHandle* src) = 0;
 
@@ -231,8 +229,6 @@
     virtual void            bzero(CompareZeroOp::Types,CG_OpndHandle* src) = 0;
     virtual void            bnzero(CompareZeroOp::Types,CG_OpndHandle* src) = 0;
     // END PRED DEPRECATED
-
-    virtual void            pred_btrue(CG_OpndHandle* src1) = 0;
 
     virtual void            jump() = 0;
     virtual void            tableSwitch(CG_OpndHandle* src, uint32 nTargets) = 0;       

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32BBPolling.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32BBPolling.cpp?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32BBPolling.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32BBPolling.cpp Fri Jul 20 02:40:02 2007
@@ -220,7 +220,7 @@
             // CFG for inlining
             Node* bbpCFGController = bbp.getBBPSubCFGController(originalTargetId,sourceDispatchId);
             if (bbpCFGController) { // just retarget the edge
-                fg->replaceEdgeTarget(edge, bbpCFGController);
+                fg->replaceEdgeTarget(edge, bbpCFGController, true);
             } else { // we need a new bbpCFG
                 ControlFlowGraph* bbpCFG = bbp.createBBPSubCFG(*irManager, tlsBaseReg);
             
@@ -293,7 +293,7 @@
         Edge* other = otherEdges[otherIdx];
         if (other->getTargetNode() != loopHeader)
             break;
-        fg->replaceEdgeTarget(other, bbpFlagAddrBlock);
+        fg->replaceEdgeTarget(other, bbpFlagAddrBlock, true);
     }
 
     assert(loopHeader->isBlockNode());

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=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.cpp Fri Jul 20 02:40:02 2007
@@ -671,49 +671,6 @@
     return sub(ArithmeticOp::I4, ref1, ref2);
 }   
 
-//_______________________________________________________________________________________________________________
-//  Subtract reference from reference and scale down by element type.
-
-CG_OpndHandle*    InstCodeSelector::scaledDiffRef(CG_OpndHandle* ref1, 
-                                                  CG_OpndHandle* ref2,
-                                                  Type*          type1,
-                                                  Type*          type2)  
-{ 
-    Opnd* r1 = (Opnd*)ref1;
-    Type * elemRefType = r1->getType();
-
-#ifdef _DEBUG
-    Opnd* r2 = (Opnd*)ref2;
-    assert( elemRefType->isManagedPtr() && elemRefType==r2->getType() );
-#endif
-    Type * elemType = ((PtrType *)elemRefType)->getPointedToType();
-
-    uint32 size = getByteSize(irManager.getTypeSize(elemType));
-    assert(size > 0);
-    uint32 shift;
-    switch(size) {
-    case 1:
-        shift = 0; 
-        break; 
-    case 2:
-        shift = 1; 
-        break; 
-    case 4:
-        shift = 2; 
-        break; 
-    default:
-        assert(0);
-        return NULL;
-    }
-    
-    Opnd *dstOpnd = (Opnd *)diffRef(false, ref1, ref2);
-
-    if(shift == 0) {
-        return dstOpnd;
-    } else {
-        return shr(IntegerOp::I4,dstOpnd,irManager.newImmOpnd(typeManager.getUInt8Type(),shift));
-    }
-}    
  
 //_______________________________________________________________________________________________________________
 //  Multiply numeric values
@@ -3139,13 +3096,6 @@
     return getTauUnsafe();
 }
 
-//_______________________________________________________________________________________________________________
-// result is a predicate
-CG_OpndHandle*  InstCodeSelector::pred_cmp(CompareOp::Operators,CompareOp::Types,CG_OpndHandle* src1,CG_OpndHandle* src2)
-{
-    ICS_ASSERT(0);
-    return 0;
-}
 
 //_______________________________________________________________________________________________________________
 CG_OpndHandle*  InstCodeSelector::pred_czero(CompareZeroOp::Types,CG_OpndHandle* src)
@@ -3161,11 +3111,6 @@
     return 0;
 }
 
-//_______________________________________________________________________________________________________________
-void InstCodeSelector::pred_btrue(CG_OpndHandle* src1)
-{
-    ICS_ASSERT(0);
-}
 
 // END new tau instructions
 

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.h?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32InstCodeSelector.h Fri Jul 20 02:40:02 2007
@@ -65,10 +65,8 @@
     virtual CG_OpndHandle*  tauSafe();   // operation is always safe
 
     // result is a predicate
-    virtual CG_OpndHandle*  pred_cmp(CompareOp::Operators,CompareOp::Types,CG_OpndHandle* src1,CG_OpndHandle* src2);
     virtual CG_OpndHandle*  pred_czero(CompareZeroOp::Types,CG_OpndHandle* src);
     virtual CG_OpndHandle*  pred_cnzero(CompareZeroOp::Types,CG_OpndHandle* src);
-    virtual void            pred_btrue(CG_OpndHandle* src1);
     // END new tau instructions
 
     //
@@ -80,7 +78,6 @@
     CG_OpndHandle* sub(ArithmeticOp::Types,CG_OpndHandle* src1,CG_OpndHandle* src2);
     CG_OpndHandle* subRef(RefArithmeticOp::Types,CG_OpndHandle* refSrc, CG_OpndHandle* intSrc);
     CG_OpndHandle* diffRef(bool ovf, CG_OpndHandle* ref1,CG_OpndHandle* ref2);
-    CG_OpndHandle* scaledDiffRef(CG_OpndHandle* ref1,CG_OpndHandle* ref2, Type*, Type*);
     CG_OpndHandle* mul(ArithmeticOp::Types,CG_OpndHandle* src1,CG_OpndHandle* src2);
     CG_OpndHandle* tau_div(DivOp::Types,CG_OpndHandle* src1,CG_OpndHandle* src2,CG_OpndHandle *tauSrc1NonZero);
     CG_OpndHandle* tau_rem(DivOp::Types,CG_OpndHandle* src1,CG_OpndHandle* src2,CG_OpndHandle *tauSrc2NonZero);

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ipf/include/IpfCodeSelector.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ipf/include/IpfCodeSelector.h?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ipf/include/IpfCodeSelector.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ipf/include/IpfCodeSelector.h Fri Jul 20 02:40:02 2007
@@ -126,7 +126,6 @@
     CG_OpndHandle *addRef(RefArithmeticOp::Types, CG_OpndHandle*, CG_OpndHandle*);
     CG_OpndHandle *subRef(RefArithmeticOp::Types, CG_OpndHandle*, CG_OpndHandle*);
     CG_OpndHandle *diffRef(bool, CG_OpndHandle*, CG_OpndHandle*);
-    CG_OpndHandle *scaledDiffRef(CG_OpndHandle*,CG_OpndHandle*, Type*, Type*);
 
     CG_OpndHandle *tau_div(DivOp::Types, CG_OpndHandle*, CG_OpndHandle*, CG_OpndHandle*);
     CG_OpndHandle *tau_rem(DivOp::Types, CG_OpndHandle*, CG_OpndHandle*, CG_OpndHandle*);
@@ -278,7 +277,6 @@
     CG_OpndHandle *tau_callvirt(uint32, CG_OpndHandle**, Type*, MethodDesc*, CG_OpndHandle*, CG_OpndHandle*)  { NOT_IMPLEMENTED_C("tau_callvirt") }
     CG_OpndHandle *select(CompareOp::Types, CG_OpndHandle*, CG_OpndHandle*, CG_OpndHandle*) { NOT_IMPLEMENTED_C("select") }
     CG_OpndHandle *cmp3(CompareOp::Operators,CompareOp::Types, CG_OpndHandle*, CG_OpndHandle*) { NOT_IMPLEMENTED_C("cmp3") }
-    CG_OpndHandle *pred_cmp(CompareOp::Operators,CompareOp::Types, CG_OpndHandle*, CG_OpndHandle*) { NOT_IMPLEMENTED_C("pred_cmp") }
     CG_OpndHandle *tau_optimisticBalancedMonitorEnter(CG_OpndHandle*, CG_OpndHandle*, CG_OpndHandle*) { NOT_IMPLEMENTED_C("tau_optimisticBalancedMonitorEnter") }
     CG_OpndHandle *addOffsetPlusHeapbase(Type*, CG_OpndHandle*, CG_OpndHandle*) { NOT_IMPLEMENTED_C("addOffsetPlusHeapbase") }
     CG_OpndHandle *tau_ldField(Type*, CG_OpndHandle*, Type::Tag, FieldDesc*, bool, CG_OpndHandle*, CG_OpndHandle*) { NOT_IMPLEMENTED_C("tau_ldField") }
@@ -291,7 +289,6 @@
     void          initValueObj(Type*, CG_OpndHandle*)                     { NOT_IMPLEMENTED_V("initValueObj") }
     void          copyValueObj(Type*, CG_OpndHandle*, CG_OpndHandle*)     { NOT_IMPLEMENTED_V("copyValueObj") }
     void          prefetch(CG_OpndHandle*, uint32, int)                   { NOT_IMPLEMENTED_V("prefetch") }
-    void          pred_btrue(CG_OpndHandle*)                              { NOT_IMPLEMENTED_V("pred_btrue") }
     void          jump()                                                  { NOT_IMPLEMENTED_V("jump") }
     void          throwLazyException(uint32, CG_OpndHandle**, MethodDesc*) { NOT_IMPLEMENTED_V("throwLazyException") }
     void          tau_stStatic(CG_OpndHandle*, FieldDesc*, Type::Tag, bool, CG_OpndHandle*) { NOT_IMPLEMENTED_V("tau_stStatic") } 

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/CodeSelectors.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/CodeSelectors.cpp?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/CodeSelectors.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/CodeSelectors.cpp Fri Jul 20 02:40:02 2007
@@ -1285,16 +1285,6 @@
                     getCGInst(inst->getSrc(1)));
             }
             break;
-            // subtract 2 reference to yield difference as # of elements
-        case Op_ScaledDiffRef:
-            {
-                assert(inst->getNumSrcOperands() == 2);
-                cgInst = instructionCallback.scaledDiffRef(getCGInst(inst->getSrc(0)),
-                    getCGInst(inst->getSrc(1)),
-                    (Type *)inst->getSrc(0)->getType(),
-                    (Type *)inst->getSrc(1)->getType());
-            }
-            break;
         case Op_UncompressRef:
             {
                 assert(inst->getNumSrcOperands() == 1);
@@ -1996,35 +1986,6 @@
         case Op_TauIsNonNull:
             {
                 cgInst = instructionCallback.tauPoint();
-            }
-            break;
-        case Op_PredCmp:
-            {
-                if (inst->getNumSrcOperands() == 2) {
-                    // binary comparison
-                    CompareOp::Operators cmpOp = mapToComparisonOp(inst);
-                    CompareOp::Types opType = mapToCompareOpType(inst);
-                    cgInst = instructionCallback.pred_cmp(cmpOp, opType,
-                        getCGInst(inst->getSrc(0)),
-                        getCGInst(inst->getSrc(1)));
-                } else {
-                    assert(inst->getNumSrcOperands() == 1);
-                    // unary comparison against zero
-                    if (inst->getComparisonModifier() == Cmp_Zero) {
-                        cgInst = instructionCallback.pred_czero(mapToCompareZeroOpType(inst),
-                            getCGInst(inst->getSrc(0)));
-                    } else {
-                        // Nonzero
-                        cgInst = instructionCallback.pred_cnzero(mapToCompareZeroOpType(inst),
-                            getCGInst(inst->getSrc(0)));
-                    }
-                }
-            }
-            break;
-        case Op_PredBranch:
-            {
-                assert(inst->getNumSrcOperands() == 1);
-                instructionCallback.pred_btrue(getCGInst(inst->getSrc(0)));
             }
             break;
         default:

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/FlowGraph.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/FlowGraph.cpp?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/FlowGraph.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/FlowGraph.cpp Fri Jul 20 02:40:02 2007
@@ -41,30 +41,6 @@
 
 namespace Jitrino {
 
-class NodeRenameTable : public HashTable<Node,Node> {
-public:
-    typedef HashTableIter<Node, Node> Iter;
-
-    NodeRenameTable(MemoryManager& mm,uint32 size) :
-                    HashTable<Node,Node>(mm,size) {}
-    Node *getMapping(Node *node) {
-        return (Node*)lookup(node);
-    }
-    void     setMapping(Node *node, Node *to) {
-        insert(node,to);
-    }
-    
-protected:
-    virtual bool keyEquals(Node* key1,Node* key2) const {
-        return key1 == key2;
-    }
-    virtual uint32 getKeyHashCode(Node* key) const {
-        // return hash of address bits
-        return ((uint32)(((POINTER_SIZE_INT)key) >> sizeof(void*)));
-    }
-};
-
-
 void         
 FlowGraph::foldBranch(ControlFlowGraph& fg, BranchInst* br, bool isTaken)
 {
@@ -127,7 +103,7 @@
     Node* copy = duplicateRegion(irm, tail, region, defUses);
 
     // Specialize for pred.
-    Edge* edge = fg.replaceEdgeTarget(pred->findTargetEdge(tail), copy);
+    Edge* edge = fg.replaceEdgeTarget(pred->findTargetEdge(tail), copy, true);
     copy->setExecCount(pred->getExecCount()*edge->getEdgeProb());
     if(copy->getExecCount() < tail->getExecCount())  {
         tail->setExecCount(tail->getExecCount() - copy->getExecCount());
@@ -260,8 +236,8 @@
                                 Node* succ =  node->getUnconditionalEdge()->getTargetNode();
                                 Edge* succEdge = node->findTargetEdge(succ);
                                 stBlock->setExecCount(node->getExecCount()*succEdge->getEdgeProb());
-                                fg.replaceEdgeTarget(succEdge, stBlock);
-                                fg.replaceEdgeTarget(newNode->findTargetEdge(succ), stBlock);
+                                fg.replaceEdgeTarget(succEdge, stBlock, true);
+                                fg.replaceEdgeTarget(newNode->findTargetEdge(succ), stBlock, true);
                                 fg.addEdge(stBlock, succ)->setEdgeProb(1.0);
                                 defUses->addUses(stVar);
                                 nodesInRegion->resize(stBlock->getId()+1);
@@ -325,7 +301,7 @@
         if(succ != entry && nodesInRegion.getBit(succ->getId())) {
             Node* newSucc = _duplicateRegion(irm, succ, entry, nodesInRegion, defUses, nodeRenameTable, opndRenameTable);
             assert(newSucc != NULL);
-            fg.replaceEdgeTarget(newNode->findTargetEdge(succ), newSucc);
+            fg.replaceEdgeTarget(newNode->findTargetEdge(succ), newSucc, true);
         }
     }    
 
@@ -333,7 +309,7 @@
 }
 
 
-static Node* _duplicateRegion(IRManager& irm, Node* entry, StlBitVector& nodesInRegion, DefUseBuilder& defUses, NodeRenameTable& nodeRenameTable, OpndRenameTable& opndRenameTable, double newEntryFreq) {
+Node* FlowGraph::duplicateRegion(IRManager& irm, Node* entry, StlBitVector& nodesInRegion, DefUseBuilder& defUses, NodeRenameTable& nodeRenameTable, OpndRenameTable& opndRenameTable, double newEntryFreq) {
     Node* newEntry = _duplicateRegion(irm, entry, entry, nodesInRegion, &defUses, &nodeRenameTable, &opndRenameTable);
     if(newEntryFreq == 0) {
         return newEntry;
@@ -356,7 +332,7 @@
     // prepare the hashtable for the operand rename translation
     OpndRenameTable    *opndRenameTable = new (dupMemManager) OpndRenameTable(dupMemManager,10);
     NodeRenameTable *nodeRenameTable = new (dupMemManager) NodeRenameTable(dupMemManager,10);
-    return _duplicateRegion(irm, entry, nodesInRegion, defUses, *nodeRenameTable, *opndRenameTable, newEntryFreq);
+    return duplicateRegion(irm, entry, nodesInRegion, defUses, *nodeRenameTable, *opndRenameTable, newEntryFreq);
 }
 
 void FlowGraph::renameOperandsInNode(Node *node, OpndRenameTable *renameTable) {
@@ -614,7 +590,7 @@
         OpndRenameTable    *opndRenameTable = new (inlineManager) OpndRenameTable(inlineManager,10);
         NodeRenameTable *nodeRenameTable = new (inlineManager) NodeRenameTable(inlineManager,10);
 
-        Node* newEntry = _duplicateRegion(*irManager, entryJSR, nodesInJSR, defUses, *nodeRenameTable, *opndRenameTable, 0);
+        Node* newEntry = FlowGraph::duplicateRegion(*irManager, entryJSR, nodesInJSR, defUses, *nodeRenameTable, *opndRenameTable, 0);
 
         fg.removeEdge(block,retTarget);
         fg.removeEdge(block,entryJSR);

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/FlowGraph.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/FlowGraph.h?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/FlowGraph.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/FlowGraph.h Fri Jul 20 02:40:02 2007
@@ -69,6 +69,8 @@
     static Node* tailDuplicate(IRManager& irm, Node* pred, Node* tail, DefUseBuilder& defUses);
 
     static Node* duplicateRegion(IRManager& irm, Node* entry, StlBitVector& nodesInRegion, DefUseBuilder& defUses, double newEntryFreq=0.0);
+    static Node* duplicateRegion(IRManager& irm, Node* entry, StlBitVector& nodesInRegion, DefUseBuilder& defUses, NodeRenameTable& nodeRenameTable, OpndRenameTable& opndRenameTable, double newEntryFreq = 0.0);
+    
 
     static void  renameOperandsInNode(Node *node, OpndRenameTable *renameTable);
 
@@ -83,6 +85,21 @@
 
     static void printDotFile(ControlFlowGraph& cfg, MethodDesc& methodDesc,const char *suffix);
 
+};
+
+class NodeRenameTable : public HashTable<Node,Node> {
+public:
+    typedef HashTableIter<Node, Node> Iter;
+
+    NodeRenameTable(MemoryManager& mm,uint32 size):HashTable<Node,Node>(mm,size) {}
+    Node *getMapping(Node *node) { return (Node*)lookup(node);  }
+    void     setMapping(Node *node, Node *to) { insert(node,to); }
+
+protected:
+    virtual bool keyEquals(Node* key1,Node* key2) const { return key1 == key2; }
+    
+    // return hash of address bits
+    virtual uint32 getKeyHashCode(Node* key) const { return ((uint32)(((POINTER_SIZE_INT)key) >> sizeof(void*))); }
 };
 
 } //namespace Jitrino 

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/IRBuilder.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/IRBuilder.cpp?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/IRBuilder.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/IRBuilder.cpp Fri Jul 20 02:40:02 2007
@@ -1061,34 +1061,6 @@
     return dst;
 }
 
-// Comparison with predicate result
-Opnd*
-IRBuilder::genPredCmp(Type* dstType,
-                      Type::Tag instType, // source type for inst
-                      ComparisonModifier mod,
-                      Opnd* src1,
-                      Opnd* src2) {
-    src1 = propagateCopy(src1);
-    src2 = propagateCopy(src2);
-    
-    Operation operation(Op_PredCmp, instType, mod);
-    uint32 hashcode = operation.encodeForHashing();
-    Opnd* dst = lookupHash(hashcode, src1, src2);
-    if (dst) return dst;
-    
-    if (irBuilderFlags.doSimplify) {
-        dst = simplifier->simplifyPredCmp(dstType, instType, mod, src1, src2);
-    }
-    if (!dst) {
-        // result of comparison is always a 32-bit int
-        dst = createOpnd(dstType);
-        Inst *i = instFactory->makePredCmp(mod, instType, dst, src1, src2);
-        appendInst(i);
-    }
-    insertHash(hashcode, src1, src2, dst->getInst());
-    return dst;
-}
-
 // Comparison
 Opnd*
 IRBuilder::genCmp(Type* dstType,
@@ -1189,19 +1161,6 @@
     appendInst(instFactory->makeBranch(mod, instType, src, label));
 }
 
-void
-IRBuilder::genPredBranch(LabelInst* label,
-                         Opnd* src) {
-    src = propagateCopy(src);
-    if (irBuilderFlags.doSimplify) {
-        if (simplifier->simplifyPredBranch(label, src)) {
-            // simplified branch was emitted;
-            return;
-        }
-    }
-    appendInst(instFactory->makePredBranch(src, label));
-}
-
 
 void
 IRBuilder::genJump(LabelInst* label) {
@@ -2360,18 +2319,6 @@
     return dst;
 }
 
-Opnd*
-IRBuilder::genScaledDiffRef(Opnd* src1, Opnd* src2) {
-    src1 = propagateCopy(src1);
-    src2 = propagateCopy(src2);
-    Opnd* dst = lookupHash(Op_ScaledDiffRef, src1, src2);
-    if (dst) return dst;
-
-    dst = createOpnd(typeManager->getInt32Type());
-    appendInst(instFactory->makeScaledDiffRef(dst, src1, src2));
-    insertHash(Op_ScaledDiffRef, src1, src2, dst->getInst());
-    return dst;
-}
 
 Opnd*
 IRBuilder::genUncompressRef(Opnd *compref)

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/IRBuilder.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/IRBuilder.h?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/IRBuilder.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/IRBuilder.h Fri Jul 20 02:40:02 2007
@@ -376,7 +376,6 @@
     Opnd*      genPrefetch(Opnd* base, Opnd *offset, Opnd *hints);
     Opnd*      genCopy(Opnd* src);
     Opnd*      genTauPi(Opnd* src, Opnd *tau, PiCondition *cond);
-    Opnd*      genScaledDiffRef(Opnd* src1, Opnd* src2);
     // compressed reference instructions
     Opnd*      genLdFieldOffset(FieldDesc* fieldDesc);
     Opnd*      genLdArrayBaseOffset(Type *elemType);
@@ -396,12 +395,6 @@
 private:
 
     void readFlagsFromCommandLine(SessionAction* argSource, const char* argPrefix);
-
-    // RECURSIVE GEN
-    // additional gen methods used only recursively
-    Opnd*      genPredCmp(Type *dstType, Type::Tag instType, ComparisonModifier mod,
-                          Opnd *src1, Opnd *src2);
-    void       genPredBranch(LabelInst* label, Opnd *src);
 
 private:
     //

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Inst.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Inst.cpp?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Inst.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Inst.cpp Fri Jul 20 02:40:02 2007
@@ -2227,12 +2227,6 @@
 }
 
 //
-Inst* InstFactory::makeScaledDiffRef(Opnd* dst, Opnd* src1, Opnd *src2) {
-    return makeInst(Op_ScaledDiffRef, Modifier(), dst->getType()->tag, dst, 
-                    src1, src2);
-}
-
-//
 Inst* InstFactory::makeUncompressRef(Opnd* dst, Opnd* compref)
 {
     return makeInst(Op_UncompressRef, Modifier(), dst->getType()->tag, 
@@ -2664,14 +2658,6 @@
                     Type::Tau, dst, src);
 }
 
-Inst* InstFactory::makePredCmp(ComparisonModifier mod, Type::Tag type, Opnd *dst,
-                               Opnd *src1, Opnd *src2) {
-    return makeInst(Op_PredCmp, mod, type, dst, src1, src2);
-}
-
-Inst* InstFactory::makePredBranch(Opnd *predSrc, LabelInst* labelInst) {
-    return makeBranchInst(Op_PredBranch, predSrc, labelInst);
-}
 
 //-----------------------------------------------------------------------------
 // InstOptimizer methods
@@ -2749,7 +2735,6 @@
     case Op_TauArrayLen:           return caseTauArrayLen(inst);
     case Op_LdArrayBaseAddr:    return caseLdArrayBaseAddr(inst);
     case Op_AddScaledIndex:     return caseAddScaledIndex(inst);
-    case Op_ScaledDiffRef:      return caseScaledDiffRef(inst);
     case Op_StVar:              return caseStVar(inst);
     case Op_TauStInd:              return caseTauStInd(inst);
     case Op_TauStField:            return caseTauStField(inst);
@@ -2826,8 +2811,6 @@
     case Op_TauHasType:         return caseTauHasType(inst->asTypeInst());
     case Op_TauHasExactType:    return caseTauHasExactType(inst->asTypeInst());
     case Op_TauIsNonNull:       return caseTauIsNonNull(inst);
-    case Op_PredCmp:            return casePredCmp(inst);
-    case Op_PredBranch:         return casePredBranch(inst->asBranchInst());
 
     default:
         ::std::cerr << "Unknown opcode! " << inst->getOpcode() << " : "

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Inst.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Inst.h?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Inst.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Inst.h Fri Jul 20 02:40:02 2007
@@ -1193,7 +1193,6 @@
                              Opnd *tauBaseIsArray);
     Inst*    makeLdArrayBaseAddr(Type* type, Opnd* dst, Opnd* array);
     Inst*    makeAddScaledIndex(Opnd* dst, Opnd* base, Opnd* index);
-    Inst*    makeScaledDiffRef(Opnd* dst, Opnd* src1, Opnd *src2);
     Inst*    makeStVar(VarOpnd* var, Opnd* src);
     Inst*    makeStVar(SsaVarOpnd* var, Opnd* src);
     Inst*    makeTauStInd(Modifier, Type::Tag, Opnd* src, Opnd* ptr, Opnd *tauNonNullBase,
@@ -1297,9 +1296,7 @@
     Inst*    makeTauHasType(Opnd *taudst, Opnd* src, Type* type);
     Inst*    makeTauHasExactType(Opnd *taudst, Opnd* src, Type* type);
     Inst*    makeTauIsNonNull(Opnd *taudst, Opnd* src);
-    Inst*    makePredCmp(ComparisonModifier mod, Type::Tag type, Opnd* dst, Opnd* src1, Opnd* src2);
-    Inst*    makePredBranch(Opnd *predSrc, LabelInst* labelInst);
-
+    
     //
     //
     //
@@ -1776,9 +1773,6 @@
     caseAddScaledIndex(Inst* inst)=0;// {return caseDefault(inst);}
 
     virtual Inst*
-    caseScaledDiffRef(Inst* inst)=0;// {return caseDefault(inst);}
-
-    virtual Inst*
     caseStVar(Inst* inst)=0;//              {return caseDefault(inst);}
 
     virtual Inst*
@@ -2031,12 +2025,6 @@
 
     virtual Inst*
     caseTauIsNonNull(Inst* inst)=0;//         {return caseDefault(inst);}
-
-    virtual Inst*
-    casePredCmp(Inst* inst)=0;//         {return caseDefault(inst);}
-
-    virtual Inst*
-    casePredBranch(BranchInst* inst)=0;//         {return caseDefault(inst);}
 
     virtual Inst*
     caseDefault(Inst* inst)=0;//            {return NULL;}

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Loop.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Loop.cpp?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Loop.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Loop.cpp Fri Jul 20 02:40:02 2007
@@ -465,8 +465,7 @@
             //
             Opcode op1 = ((Inst*)tail->getLastInst())->getOpcode();
             Opcode op2 = ((Inst*)header->getLastInst())->getOpcode();
-            if(flags.invert && (op1 != Op_Branch) && (op1 != Op_PredBranch)
-               && (op2 != Op_Branch) && (op2 != Op_PredBranch)) {
+            if(flags.invert && (op1 != Op_Branch) && (op2 != Op_Branch)) {
                 if(isInversionCandidate(originalInvertedHeader, header, nodesInLoop, next, exit)) {
                     preheader = FlowGraph::tailDuplicate(irManager, preheader, header, defUses); 
                     tail = header;

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Opcode.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Opcode.cpp?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Opcode.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Opcode.cpp Fri Jul 20 02:40:02 2007
@@ -147,7 +147,6 @@
     { Op_TauArrayLen,           false, MB::CSEable,       MK::None,                                  "arraylen ",        "arraylen  %0 ((%1,%2)) -) %l",           },       
     { Op_LdArrayBaseAddr,       false, MB::CSEable,       MK::None,                                  "ldbase",        "ldbase    %s -) %l",           }, // load the base (zero'th element) address of array
     { Op_AddScaledIndex,        false, MB::Movable,       MK::None,                                  "addindex",      "addindex  %s -) %l",           }, // Add a scaled index to an array element address
-    { Op_ScaledDiffRef,         false, MB::Movable,       MK::None,                                  "diffref",       "diffref   %s -) %l",           }, // Subtract two references to yield a difference in number of objects
     { Op_StVar,                 true,  MB::None,          MK::None,                                  "stvar ",        "stvar     %0 -) %l",           },
     { Op_TauStInd,              true,  MB::StoreOrSync,   MK::Store_AutoCompress,                    "stind",         "stind%m:%t %0 ((%2,%3,%4)) -) [%1]",        },
     { Op_TauStField,            true,  MB::StoreOrSync,   MK::Store_AutoCompress,                    "stfld",         "stfld%m:%t %0 ((%2,%3)) -) [%1.%d]",     },
@@ -237,10 +236,6 @@
     { Op_TauHasType,            false, MB::Movable,       MK::None,                             "tauhastype ",        "tauhastype      %0,%d -) %l",        }, // temporary declaration that source is of given type
     { Op_TauHasExactType,       false, MB::CSEable,       MK::None,                             "tauexacttype ",        "tauexacttype      %0,%d -) %l",        }, // temporary declaration that source is exactly of given type
     { Op_TauIsNonNull,          true, MB::CSEable,       MK::None,                             "tauisnonnull ",        "tauisnonnull      %0 -) %l",        }, // temporary declaration that source null
-
-    { Op_PredCmp,               false, MB::Movable,       MK::Comparison,                            "predcmp",        "pc%m:%t %s -) %l",              }, 
-    { Op_PredBranch,            true,  MB::ControlFlow,   MK::None,                                  "predbr",        "if %s goto %l",         }, 
-
 };                                                             
 
 unsigned short Modifier::encode(Opcode opcode, uint32 numbits) const

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Opcode.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Opcode.h?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Opcode.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/Opcode.h Fri Jul 20 02:40:02 2007
@@ -359,7 +359,6 @@
     Op_TauArrayLen,        
     Op_LdArrayBaseAddr,             // load the base (zero'th element) address of array
     Op_AddScaledIndex,              // Add a scaled index to an array element address
-    Op_ScaledDiffRef,               // Subtract two references to yield a difference in number of objects
     // Store instructions
     Op_StVar,
     Op_TauStInd,                  // StoreModifier
@@ -471,9 +470,6 @@
     Op_TauHasType,
     Op_TauHasExactType,
     Op_TauIsNonNull,
-
-    Op_PredCmp,
-    Op_PredBranch,
 
     // prefixes: unaligned, volatile, tail,
     NumOpcodes,

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/codelowerer.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/codelowerer.h?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/codelowerer.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/codelowerer.h Fri Jul 20 02:40:02 2007
@@ -197,8 +197,6 @@
 
     Inst* caseAddScaledIndex(Inst* inst) {return caseDefault(inst);}
 
-    Inst* caseScaledDiffRef(Inst* inst) {return caseDefault(inst);}
-
     Inst* caseStVar(Inst* inst) {return caseDefault(inst);}
 
     Inst* caseTauStInd(Inst* inst) {return caseDefault(inst);}
@@ -360,10 +358,6 @@
     Inst* caseTauHasExactType(TypeInst* inst) {return caseDefault(inst);}
 
     Inst* caseTauIsNonNull(Inst* inst) {return caseDefault(inst);}
-
-    Inst* casePredCmp(Inst* inst) {return caseDefault(inst);}
-
-    Inst* casePredBranch(BranchInst* inst) {return caseDefault(inst);}
 
     IRManager& _irm;
     bool _preserveSsa;

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/hashvaluenumberer.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/hashvaluenumberer.cpp?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/hashvaluenumberer.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/hashvaluenumberer.cpp Fri Jul 20 02:40:02 2007
@@ -516,7 +516,6 @@
     }
     Inst* caseLdArrayBaseAddr(Inst* inst)           { return hashInst(inst); }
     Inst* caseAddScaledIndex(Inst* inst)            { return hashInst(inst); }
-    Inst* caseScaledDiffRef(Inst* inst)             { return hashInst(inst); }
 
     // Stores:
     Inst* caseStVar(Inst* inst) { return caseDefault(inst); }
@@ -992,12 +991,6 @@
         return hashInst(inst);
     }
 
-    virtual Inst*
-    casePredCmp(Inst* inst) { return hashInst(inst); }
-
-    virtual Inst*
-    casePredBranch(BranchInst* inst) { return lookupInst(inst); }
-
     // default
     Inst* caseDefault(Inst* inst)                   { return inst; }
 private:
@@ -1355,7 +1348,6 @@
     void addBranchConditions(DominatorNode* domNode);
 private:
     void addInfoFromBranch(Node* targetNode, BranchInst *branchi, bool isTrueEdge);
-    void addInfoFromPredBranch(Node* targetNode, BranchInst *branchi, bool isTrueEdge);
     void addInfoFromBranchCompare(Node* targetNode, 
                                   ComparisonModifier mod,
                                   Type::Tag comparisonType,
@@ -1548,11 +1540,7 @@
             assert(branchi1 != NULL);
             BranchInst* branchi = branchi1->asBranchInst();
             if (branchi) {
-                if (branchi->getOpcode() == Op_PredBranch) {
-                    addInfoFromPredBranch(block, branchi, taken);
-                } else if (branchi->getOpcode() != Op_Switch || !taken) {
-                    addInfoFromBranch(block, branchi, taken);
-                }
+                addInfoFromBranch(block, branchi, taken);
             } else {
                 // default edge of switch, skip it
             }
@@ -1972,35 +1960,6 @@
                              (numSrcs==2 ? branchi->getSrc(1) : 0));
 }
 
-void InstValueNumberer::addInfoFromPredBranch(Node* targetNode, BranchInst *branchi, 
-                                              bool isTrueEdge)
-{
-    const OptimizerFlags& optimizerFlags = irManager.getOptimizerFlags();     
-    if (!optimizerFlags.elim_checks) return;
-
-    if (Log::isEnabled()) {
-        Log::out() << "addInfoFromPredBranch " << (isTrueEdge ? "taken " : "notTaken ");
-        branchi->print(Log::out());
-        Log::out() << ::std::endl;
-    }
-
-    Opnd *srcOp = branchi->getSrc(0);
-    Inst *pcmpi = srcOp->getInst();
-    if (pcmpi->getOpcode() != Op_PredCmp) {
-        return; 
-    }
-
-        pcmpi->getComparisonModifier();
-    uint32 numSrcs = pcmpi->getNumSrcOperands();
-    addInfoFromBranchCompare(targetNode, 
-                             pcmpi->getComparisonModifier(),
-                             pcmpi->getType(),
-                             isTrueEdge,
-                             pcmpi->getNumSrcOperands(),
-                             pcmpi->getSrc(0),
-                             (numSrcs==2 ? branchi->getSrc(1) : 0));
-}
-
 void InstValueNumberer::recordHasTypeTau(Opnd *opnd,
                                          Type *type,
                                          Inst *tauHasTypeInst)
@@ -2063,8 +2022,6 @@
     Operation negCmpOperation(Op_Cmp, comparisonType, negModhere);
     Operation branchOperation(Op_Branch, comparisonType, modhere);
     Operation negBranchOperation(Op_Branch, comparisonType, negModhere);
-    Operation predCmpOperation(Op_PredCmp, comparisonType, modhere);
-    Operation negPredCmpOperation(Op_PredCmp, comparisonType, negModhere);
     switch (numSrcOperands) {
     case 1:
         {
@@ -2083,14 +2040,10 @@
                 Log::out() << "cmpOperation.hashcode() == "
                            << (int) cmpOperation.encodeForHashing()
                            << ::std::endl;
-                Log::out() << "predCmpOperation.hashcode() == "
-                           << (int) predCmpOperation.encodeForHashing()
-                           << ::std::endl;
             }
             Inst *tauEdge = getBlockTauEdge(targetNode)->getInst();
             setHashToInst(tauEdge, getKey(branchOperation, src0->getId()));
             setHashToInst(tauEdge, getKey(cmpOperation, src0->getId()));
-            setHashToInst(tauEdge, getKey(predCmpOperation, src0->getId()));
             
             if (Log::isEnabled()) {
                 Log::out() << "adding false comparison: ";
@@ -2107,14 +2060,10 @@
                 Log::out() << "negCmpOperation.hashcode() == "
                            << (int) negCmpOperation.encodeForHashing()
                            << ::std::endl;
-                Log::out() << "negPredCmpOperation.hashcode() == "
-                           << (int) negPredCmpOperation.encodeForHashing()
-                           << ::std::endl;
             }
 
             setHashToInst(getTauUnsafe(), getKey(negBranchOperation, src0->getId()));
             setHashToInst(getTauUnsafe(), getKey(negCmpOperation, src0->getId()));
-            setHashToInst(getTauUnsafe(), getKey(negPredCmpOperation, src0->getId()));
         }
         break;
     case 2:
@@ -2146,8 +2095,6 @@
                           getKey(branchOperation, posSrc0->getId(), posSrc1->getId()));
             setHashToInst(tauEdge,
                           getKey(cmpOperation, posSrc0->getId(), posSrc1->getId()));
-            setHashToInst(tauEdge,
-                          getKey(predCmpOperation, posSrc0->getId(), posSrc1->getId()));
 
             if (Log::isEnabled()) {
                 Log::out() << "adding false comparison: ";
@@ -2172,8 +2119,6 @@
             setHashToInst(getTauUnsafe(),
                           getKey(negCmpOperation, negSrc0->getId(), 
                                  negSrc1->getId()));
-            setHashToInst(getTauUnsafe(),
-                          getKey(negPredCmpOperation, src0->getId(), src1->getId()));
         }
         break;
     default:

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/lazyexceptionopt.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/lazyexceptionopt.cpp?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/lazyexceptionopt.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/lazyexceptionopt.cpp Fri Jul 20 02:40:02 2007
@@ -944,7 +944,6 @@
         case Op_TauArrayLen:
         case Op_LdArrayBaseAddr:
         case Op_AddScaledIndex:
-        case Op_ScaledDiffRef:
             return true;
         case Op_StVar:
             return false;
@@ -1096,9 +1095,6 @@
         case Op_TauHasType:
         case Op_TauHasExactType:
         case Op_TauIsNonNull:
-            return false;
-        case Op_PredCmp:
-        case Op_PredBranch:
             return false;
         default:
             return true;

Added: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/loop_unroll.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/loop_unroll.cpp?view=auto&rev=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/loop_unroll.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/loop_unroll.cpp Fri Jul 20 02:40:02 2007
@@ -0,0 +1,748 @@
+/*
+*  Licensed to the Apache Software Foundation (ASF) under one or more
+*  contributor license agreements.  See the NOTICE file distributed with
+*  this work for additional information regarding copyright ownership.
+*  The ASF licenses this file to You under the Apache License, Version 2.0
+*  (the "License"); you may not use this file except in compliance with
+*  the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+*  Unless required by applicable law or agreed to in writing, software
+*  distributed under the License is distributed on an "AS IS" BASIS,
+*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+*  See the License for the specific language governing permissions and
+*  limitations under the License.
+*/
+
+/**
+* @author Intel, Mikhail Y. Fursov
+*/
+
+#include "escapeanalyzer.h"
+#include "Log.h"
+#include "Inst.h"
+#include "Dominator.h"
+#include "irmanager.h"
+#include "LoopTree.h"
+#include "FlowGraph.h"
+#include "ssa/SSA.h"
+#include "Opnd.h"
+
+namespace Jitrino {
+
+//TODOs:
+// 1) support parents loop unrolling -> easy
+// 2) support complete loop elimination if limit is const -> easy  (or do not unroll at all)
+// 3) support more branch types (Cmp_Eq, Cmp_NotEq, Cmp_Zero..)
+// 4) support loop unrolling for counters with long, float and double types
+
+class UnrollFlags {
+public:
+    UnrollFlags() 
+        : smallLoopSize(0), smallLoopHotness(0), smallLoopUnrollCount(0),
+        mediumLoopSize(0), mediumLoopHotness(0), mediumLoopUnrollCount(0),
+        largeLoopSize(0), largeLoopHotness(0), largeLoopUnrollCount(0)
+    {}
+
+    int  smallLoopSize;
+    int  smallLoopHotness;
+    int  smallLoopUnrollCount;
+
+    int  mediumLoopSize;
+    int  mediumLoopHotness;
+    int  mediumLoopUnrollCount;
+
+    int  largeLoopSize;
+    int  largeLoopHotness;
+    int  largeLoopUnrollCount;
+
+    bool unrollParentLoops;
+};
+
+class LoopUnrollAction : public Action {
+public:
+    void init();
+    const UnrollFlags& getFlags() {return flags;}
+protected:
+    UnrollFlags flags;
+};
+
+DEFINE_SESSION_ACTION_WITH_ACTION(LoopUnrollPass, LoopUnrollAction, unroll, "Loop Unrolling")
+
+
+//loop structure is
+//loop {
+// BodyA
+// check
+// BodyB
+//}
+// all paths from bodyA to bodyB must go through the 'check'
+//
+class LoopUnrollInfo {
+public:
+    LoopUnrollInfo() 
+        : header(NULL), branchInst(NULL), branchTargetIsExit(false),
+        branchLimitOpndPos(0), increment(0), unrollCount(0), doUnroll(false) 
+    {}
+
+    Node* header;
+    BranchInst* branchInst;
+    bool  branchTargetIsExit;
+    int   branchLimitOpndPos;
+    
+    int increment; 
+    int unrollCount;
+    bool   doUnroll;
+
+    
+    Opnd* getLimitOpnd() const {return branchLimitOpndPos==0?branchInst->getSrc(0) : branchInst->getSrc(1);}
+    Opnd* getIdxOpnd() const {return branchLimitOpndPos==0?branchInst->getSrc(1) : branchInst->getSrc(0);}
+    
+    void print(std::ostream& out) const {
+        out<<"LoopHead=";FlowGraph::printLabel(out, header);
+        out<<" inst=I"<<branchInst->getId();
+        out<<" idx-opndId="<<getIdxOpnd()->getId();
+        out<<" limit-opndId="<<getLimitOpnd()->getId();
+        out<<" increment="<<increment;
+        out<<" unroll_count="<<unrollCount;
+        out<<" do_unroll="<<doUnroll;
+    }
+};
+
+class OpndLoopInfo {
+public:
+    enum OpndType {DEF_OUT_OF_LOOP, LD_CONST, COUNTER, UNDEF};
+    OpndLoopInfo() {type=DEF_OUT_OF_LOOP; val=0; phiSplit= false;}
+
+    OpndType getType() const {return type;}
+    void setType(OpndType newType) {assert(type!=newType);type = newType; val=0;}
+    bool isCounter() const {return type == COUNTER;}
+    bool isLDConst() const {return type == LD_CONST;}
+    bool isDOL() const {return type == DEF_OUT_OF_LOOP;}
+    bool isUndefined() const {return type == UNDEF;}
+    int getConst() const {assert(getType()==LD_CONST); return val;}
+    void setConst(int32 v) {assert(getType()==LD_CONST); val=v;}
+    int getIncrement() const {assert(getType()==COUNTER); return val;}
+    void setIncrement(int32 v) {assert(getType()==COUNTER); val=v;}
+    bool isPhiSplit() const {return phiSplit;}
+    void markPhiSplit() {assert(isCounter()); phiSplit = true;}
+    
+    
+    void print(std::ostream& out) {
+        if (type == DEF_OUT_OF_LOOP) out << "DOL"; 
+        else if (type == LD_CONST)   out << "LDC:"<<getConst();
+        else if (type == COUNTER)    out << "CNT:"<<getIncrement() << (phiSplit?" splt":"");
+        else                         out << "UNDEF";
+    }
+private:
+    OpndType type;
+    int      val;
+    bool     phiSplit; //only 1 phi split with DOL is allowed for counters.
+};
+
+typedef StlVector<Inst*> InstStack;
+typedef StlVector<LoopUnrollInfo*> UnrollInfos;
+
+static void log_ident(int n)  {for (int i=0;i<n;++i) Log::out()<<"  "; }
+static int signof(int v) { return (v == 0) ? 0 : ( v < 0 ? -1 : 1); }
+
+
+
+static void findLoopsToUnroll(MemoryManager& mm, IRManager& irm, UnrollInfos& result, const UnrollFlags& flags);
+static void doUnroll(MemoryManager& mm, IRManager& irm, const LoopUnrollInfo* info, const UnrollFlags& flags);
+static void calculateReachableNodesInLoop(LoopNode* loop, Node* node, Node* stopNode, BitSet& flags);
+
+
+void LoopUnrollAction::init() {
+    flags.smallLoopSize = getIntArg("small_loop_max_size", 5);
+    flags.smallLoopHotness = getIntArg("small_loop_hotness_percent", 300);
+    flags.smallLoopUnrollCount = getIntArg("small_loop_unroll_count", 8);
+
+    flags.mediumLoopSize = getIntArg("medium_loop_max_size", 10);
+    flags.mediumLoopHotness = getIntArg("medium_loop_hotness_percent", 300);
+    flags.mediumLoopUnrollCount = getIntArg("medium_loop_unroll_count", 4);
+
+    flags.largeLoopSize = getIntArg("large_loop_max_size", 20);
+    flags.largeLoopHotness = getIntArg("large_loop_hotness_percent", 300);
+    flags.largeLoopUnrollCount = getIntArg("large_loop_unroll_count", 2);
+
+//TODO: support unrolling of parent loops
+    flags.unrollParentLoops = false;//getBoolArg("unroll_parent_loops", false);
+}
+
+void LoopUnrollPass::_run(IRManager& irm) {
+    const UnrollFlags& flags = ((LoopUnrollAction*)getAction())->getFlags();
+    
+    OptPass::computeDominatorsAndLoops(irm);
+    ControlFlowGraph& cfg = irm.getFlowGraph();
+    LoopTree* lt = cfg.getLoopTree();
+    if (!lt->hasLoops()) {
+        return;
+    }
+    
+    MemoryManager mm("loopUnrollMM");
+    UnrollInfos loopsToUnroll(mm);
+    findLoopsToUnroll(mm, irm, loopsToUnroll, flags);
+    if (loopsToUnroll.empty()) {
+        if (Log::isEnabled()) Log::out() << "No candidates found to unroll"<<std::endl;
+        return;
+    }
+    if (Log::isEnabled()) {
+        Log::out()<<"Loops to unroll before filtering:"<<std::endl;
+        for (UnrollInfos::const_iterator it = loopsToUnroll.begin(), end = loopsToUnroll.end();it!=end; ++it) {
+            const LoopUnrollInfo* info = *it;
+            info->print(Log::out()); Log::out()<<std::endl;
+        }
+    }
+    bool hasProfile =  cfg.hasEdgeProfile();
+    //filter out that can't be unrolled, calculate BodyA and BodyB
+    BitSet bodyANodes(mm, cfg.getMaxNodeId()), bodyBNodes(mm, cfg.getMaxNodeId());
+    for (UnrollInfos::iterator it = loopsToUnroll.begin(), end = loopsToUnroll.end();it!=end; ++it) {
+        LoopUnrollInfo* info = *it;
+        if (info == NULL) {
+            continue;
+        }
+        if (!info->doUnroll) {
+            *it=NULL;
+            continue;
+        }
+        Node* header=info->header;
+        LoopNode* loopHeader = lt->getLoopNode(header, false);
+        assert(loopHeader->getHeader() == header);
+
+        Node* checkNode = info->branchInst->getNode();
+        bodyANodes.clear();
+        bodyBNodes.clear();
+        calculateReachableNodesInLoop(loopHeader, loopHeader->getHeader(), checkNode, bodyANodes);
+        calculateReachableNodesInLoop(loopHeader, checkNode, NULL, bodyBNodes);
+        bodyANodes.intersectWith(bodyBNodes);
+        bool checkNodeIsJunctionPoint = bodyANodes.isEmpty();
+        if (!checkNodeIsJunctionPoint) {
+            if (Log::isEnabled()) {
+                Log::out()<<"Check node is not a junction point -> removing from the list: branch inst id=I"<<info->branchInst->getId()<<std::endl;
+            }
+            *it=NULL;
+            continue;
+        }
+        //check if branch semantic is OK
+        ComparisonModifier cmpMod = info->branchInst->getModifier().getComparisonModifier();
+        if (cmpMod!=Cmp_GT && cmpMod!=Cmp_GTE && cmpMod!=Cmp_GT_Un && cmpMod!=Cmp_GTE_Un) {
+            if (Log::isEnabled()) {
+                Log::out()<<"Branch is not a range comparison -> removing from the list: branch inst id=I"<<info->branchInst->getId()<<std::endl;
+            }
+            *it=NULL;
+            continue;
+        }
+
+        //check config settings
+        bool failed = false;
+        int nodesInLoop = loopHeader->getNodesInLoop().size();
+        const char* reason = "unknown";
+        if (nodesInLoop > flags.largeLoopSize) {
+            reason = "loop is too large";
+            failed = true;
+        } else if (hasProfile) {
+            int headHotness = (int)(header->getExecCount()*100.0  / cfg.getEntryNode()->getExecCount());
+            int minHeaderHotness= nodesInLoop <= flags.smallLoopSize ? flags.smallLoopHotness :
+                nodesInLoop <= flags.mediumLoopSize ? flags.mediumLoopHotness : flags.largeLoopHotness;
+            info->unrollCount = nodesInLoop <= flags.smallLoopSize ? flags.smallLoopUnrollCount :
+                nodesInLoop <= flags.mediumLoopSize? flags.mediumLoopUnrollCount: flags.largeLoopUnrollCount;
+            failed = headHotness < minHeaderHotness || info->unrollCount < 1;
+            if (failed) {
+                reason = "loop is too cold";
+            }
+        }
+        if (failed) {
+            if (Log::isEnabled()) {
+                Log::out()<<"Loop does not match unroll configuration ("<<reason<<") -> removing from the list: branch inst id=I"<<info->branchInst->getId()<<std::endl;
+            }
+            *it=NULL;
+        }
+    }    
+    //filter out loops with multiple exits 
+    for (UnrollInfos::iterator it1 = loopsToUnroll.begin(), end = loopsToUnroll.end();it1!=end; ++it1) {
+        const LoopUnrollInfo* info1 = *it1;
+        if (info1== NULL) {
+            continue;
+        }
+        Node* header=info1->header;
+        for (UnrollInfos::iterator it2 = it1+1; it2!=end; ++it2) {
+            const LoopUnrollInfo* info2 = *it2;
+            if (info2!=NULL && header==info2->header) {
+                if (Log::isEnabled()) {
+                    Log::out() << "Found multiple exits:"; FlowGraph::printLabel(Log::out(), header);Log::out()<<std::endl;
+                }
+                if (hasProfile)  {
+                    Node* check1 = info1->branchInst->getNode();
+                    Node* check2 = info2->branchInst->getNode();
+                    if (check1->getExecCount() > check2->getExecCount()) {
+                        *it2 = NULL;
+                    } else {
+                        *it1 = NULL;
+                    }
+                } else { // random selection
+                    *it2=NULL;
+                }
+            }
+        }
+    }    
+    loopsToUnroll.erase(std::remove(loopsToUnroll.begin(), loopsToUnroll.end(), (LoopUnrollInfo*)NULL), loopsToUnroll.end());
+    if (loopsToUnroll.empty()) {
+        if (Log::isEnabled()) Log::out() << "--------No candidates to unroll left after filtering"<<std::endl;
+        return;
+    }
+    
+    //dessa CFG before unrolling -> need to duplicate regions and we can do it on dessa form only today
+    {
+        SSABuilder::deconvertSSA(&cfg, irm.getOpndManager());
+        irm.setInSsa(false);
+    }
+
+    if (Log::isEnabled()) {
+        Log::out()<<"--------Loops to unroll after filtering : n="<<loopsToUnroll.size()<<std::endl;
+            for (UnrollInfos::const_iterator it = loopsToUnroll.begin(), end = loopsToUnroll.end();it!=end; ++it) {
+                const LoopUnrollInfo* info = *it;
+                info->print(Log::out()); Log::out()<<std::endl;
+            }
+    }
+
+    for (UnrollInfos::const_iterator it = loopsToUnroll.begin(), end = loopsToUnroll.end();it!=end; ++it) {
+        const LoopUnrollInfo* info = *it;
+        doUnroll(mm, irm, info, flags);
+    }
+};
+
+static void calculateReachableNodesInLoop(LoopNode* loop, Node* node, Node* stopNode, BitSet& flags) {
+    int id = node->getId();
+    if (!loop->inLoop(node) || node == stopNode || flags.getBit(id)) {
+        return;
+    }
+    flags.setBit(id, true);
+    const Edges& edges = node->getOutEdges();
+    for (Edges::const_iterator ite = edges.begin(), ende = edges.end(); ite!=ende; ++ite) {
+        Edge* e = *ite;
+        Node* nextNode = e->getTargetNode();
+        if (nextNode != loop->getHeader()) {
+            calculateReachableNodesInLoop(loop, nextNode, stopNode, flags);
+        }
+    }
+}
+
+
+static OpndLoopInfo processOpnd(LoopNode* loopHead, LoopTree* lt, InstStack& defStack, Opnd* opnd) {
+    OpndLoopInfo result;
+    Inst* defInst = opnd->getInst();
+    if (Log::isEnabled()) {
+        log_ident(defStack.size()); defInst->print(Log::out()); Log::out()<<"]"<<std::endl;
+    }
+    if (std::find(defStack.begin(), defStack.end(), defInst)!=defStack.end()) {
+        result.setType(OpndLoopInfo::COUNTER);
+        result.setIncrement(0);
+        if (Log::isEnabled()) {
+            log_ident(defStack.size()); 
+            Log::out()<<"Found duplicate in def stack -> stopping recursion. ";result.print(Log::out()); Log::out()<<std::endl;
+        }
+        return result;
+    }
+    Node* defNode = defInst->getNode();
+    Opcode opcode = defInst->getOpcode();
+
+    if (opcode == Op_LdConstant) {
+        result.setType(OpndLoopInfo::LD_CONST);
+        result.setConst(defInst->asConstInst()->getValue().i4);
+        if (Log::isEnabled()) {
+            log_ident(defStack.size()); 
+            Log::out()<<"assigning to const -> stopping recursion. ";result.print(Log::out());Log::out()<<std::endl;
+        }
+        return result;
+    }
+    if (!loopHead->inLoop(defNode)) {
+        if (Log::isEnabled()) {
+            log_ident(defStack.size());
+            Log::out()<<"Inst out of the loop -> stopping recursion. ";result.print(Log::out()); Log::out()<<std::endl;
+        }
+        return result;
+    }
+
+    defStack.push_back(defInst);
+    if (opcode == Op_Phi) {
+        OpndLoopInfo info1 = processOpnd(loopHead, lt, defStack, defInst->getSrc(0));
+        OpndLoopInfo info2 = processOpnd(loopHead, lt, defStack, defInst->getSrc(1));
+        if (Log::isEnabled()) {
+            log_ident(defStack.size());
+            Log::out()<<"PHI(";info1.print(Log::out());Log::out()<<",";info2.print(Log::out());Log::out()<<")"<<std::endl;
+        }
+        if ((info1.isCounter() && !info1.isPhiSplit()) && (info2.isDOL() || info2.isLDConst())
+            || (info2.isCounter() && !info2.isPhiSplit()) && (info1.isDOL() || info1.isLDConst()))
+        {
+            result.setType(OpndLoopInfo::COUNTER);
+            result.setIncrement(info1.isCounter() ? info1.getIncrement() : info2.getIncrement());
+            result.markPhiSplit();
+        } else {
+            result.setType(OpndLoopInfo::UNDEF);
+        }
+    } else if (opcode == Op_Add || opcode == Op_Sub) { //todo: LADD 
+        Opnd *op1 = defInst->getSrc(0);
+        Opnd *op2 = defInst->getSrc(1);
+        OpndLoopInfo info1 = processOpnd(loopHead, lt, defStack, op1);
+        OpndLoopInfo info2 = processOpnd(loopHead, lt, defStack, op2);
+        if ((info1.isLDConst() || info1.isDOL()) && (info2.isLDConst() || info2.isDOL())) {
+            if (info1.isLDConst() && info2.isLDConst() && info1.getConst() == info2.getConst()) {
+                result.setType(OpndLoopInfo::LD_CONST);
+                result.setConst(info1.getConst());
+            } else {
+                //result is DOL (default type)
+            }
+        } else if ((info1.isCounter() && info2.isLDConst()) || (info2.isCounter() && info1.isLDConst())) {
+            int increment = info1.isCounter()? info1.getIncrement(): info2.getIncrement();
+            int diff = info1.isLDConst()? info1.getConst(): info2.getConst(); 
+
+            //we use SSA form to analyze how opnd changes in loop and we do not analyze actual control flow, 
+            // so we can unroll loops with monotonically changing 'counters' only.
+            //Example: when 'counter' changes not monotonically and we can't unroll:
+            //idx=0; loop {idx+=100; if(idx>=100) break; idx-=99;} ->'increment'=1 but not monotonicaly.
+            bool monotonousFlag = increment == 0 || diff == 0 
+                || (opcode == Op_Add && signof(diff) == signof(increment)) 
+                || (opcode == Op_Sub && signof(diff) != signof(increment));
+            if (monotonousFlag) {
+                result.setType(OpndLoopInfo::COUNTER);
+                if ((info1.isCounter() && info1.isPhiSplit()) || (info2.isCounter() && info2.isPhiSplit())) {
+                    result.markPhiSplit();
+                }
+                //TO IMPROVE: for loops like: for (; length-1>=0;length--){...}
+                //we have 2 SUBs by -1 => "-2", but real counter is changed by "-1".
+                //Loop unroll will use "-2". It's ok, because this value is used in a guard inst
+                //and ABS(increment_in_unroll) >= ABS(real_increment). This work only for monotonous loops.
+                //To make increment_in_unroll == real_increment we must track modifications (SUB,ADD) that affects vars only.
+                if (opcode == Op_Add) {
+                    result.setIncrement(increment + diff);
+                } else {
+                    result.setIncrement(increment - diff);
+                }
+            } else {
+                result.setType(OpndLoopInfo::UNDEF);
+            }
+        } else {
+            result.setType(OpndLoopInfo::UNDEF);
+        }
+    } else if (opcode == Op_StVar  || opcode == Op_LdVar) {
+        Opnd* newOpnd = defInst->getSrc(0);
+        result  = processOpnd(loopHead, lt, defStack, newOpnd);
+    } else if (opcode == Op_TauArrayLen) {
+        Opnd* arrayOpnd  = defInst->getSrc(0);
+        result  = processOpnd(loopHead, lt, defStack, arrayOpnd);
+    } else { //unsupported op
+        result.setType(OpndLoopInfo::UNDEF);
+        if (Log::isEnabled()) {
+            log_ident(defStack.size()); Log::out()<<"unknown op -> stopping recursion. ";
+        }
+    }
+    defStack.pop_back();
+    if (Log::isEnabled()) {
+        log_ident(defStack.size());
+        result.print(Log::out());Log::out()<<std::endl;
+    }
+    return result;
+}
+
+static LoopUnrollInfo* prepareUnrollInfo(MemoryManager& mm, LoopTree* lt, BranchInst* branchInst) {
+
+    if (Log::isEnabled()) {
+        Log::out()<<"==Checking loop exit:"; branchInst->print(Log::out()); Log::out()<<std::endl;
+    }
+
+    //traverse loop and track all modifications
+    Node* node = branchInst->getNode();
+    LoopNode* loopHeader = lt->getLoopNode(node, false);
+    Opnd* opnd1 = branchInst->getSrc(0);
+    Opnd* opnd2 = branchInst->getNumSrcOperands()==1?NULL:branchInst->getSrc(1);
+    
+    if (opnd2==NULL) {
+        assert(branchInst->getComparisonModifier() == Cmp_Zero || branchInst->getComparisonModifier() == Cmp_NonZero);
+        assert(opnd1->getType()->isObject());
+        if (Log::isEnabled()) {
+            Log::out()<<"----Unsupported comparison modifier."<<std::endl;
+        }
+        return NULL;
+    }
+    
+    if (!opnd1->getType()->isInteger() || opnd1->getType()->isInt8()
+        || !opnd2->getType()->isInteger() || opnd2->getType()->isInt8()) 
+    {
+        if (Log::isEnabled()) {
+            Log::out()<<"----Unsupported opnd types."<<std::endl;
+        }
+        return NULL;        //IMPROVE: longs and floating types are not supported
+    }
+
+    InstStack defStack(mm);
+
+    Log::out()<<"----Analyzing opnd1 id="<<opnd1->getId()<<std::endl;
+    OpndLoopInfo opndInfo1 = processOpnd(loopHeader, lt, defStack, opnd1);
+    assert(defStack.empty());
+    
+    Log::out()<<"----Analyzing opnd2 id="<<opnd2->getId()<<std::endl;
+    OpndLoopInfo opndInfo2 = processOpnd(loopHeader, lt, defStack, opnd2);
+    assert(defStack.empty());
+
+    if(Log::isEnabled()) {
+        Log::out()<<"----Result: opndId1="<<opnd1->getId()<<" type=";opndInfo1.print(Log::out());
+        Log::out()<<", opndId2="<<opnd2->getId()<<" type=";opndInfo2.print(Log::out());Log::out()<<std::endl;
+    }
+
+    //default values -> this item will not be unrolled unless all constraints are OK
+    LoopUnrollInfo* info = new (mm) LoopUnrollInfo();
+    info->header = loopHeader->getHeader();
+    info->branchInst = branchInst;
+    info->branchTargetIsExit = !loopHeader->inLoop(branchInst->getTargetLabel()->getNode());
+    info->doUnroll = false;
+
+    if (opndInfo1.isCounter() && (opndInfo2.isDOL() || opndInfo2.isLDConst())) {
+        info->doUnroll = true;
+        info->branchLimitOpndPos=1;
+        info->increment = opndInfo1.getIncrement();
+    } else  if (opndInfo2.isCounter() && (opndInfo1.isDOL() || opndInfo1.isLDConst())) {
+        info->doUnroll = true;
+        info->branchLimitOpndPos=0;
+        info->increment = opndInfo2.getIncrement();
+    } 
+    return info;
+}
+
+void findLoopsToUnroll(MemoryManager& tmpMM, IRManager& irm, UnrollInfos& result, const UnrollFlags& flags) {
+
+    ControlFlowGraph& fg = irm.getFlowGraph();
+    LoopTree* lt = fg.getLoopTree();
+
+    //find all loop exits
+    Edges loopExits(tmpMM);
+    const Nodes& nodes = fg.getNodes();
+    for (Nodes::const_iterator it = nodes.begin(), end = nodes.end(); it!=end; ++it) {
+       Node* node = *it;
+        LoopNode* loopNode = lt->getLoopNode(node, false);
+        if (loopNode == NULL) {
+            continue; //node not in a loop
+        }
+        if (!flags.unrollParentLoops && loopNode->getChild()!=NULL) {
+            continue; //skip parent loops
+        }
+        const Edges& edges = node->getOutEdges();
+        for (Edges::const_iterator ite = edges.begin(), ende = edges.end(); ite!=ende; ++ite) {
+           Edge* edge = *ite;
+            if (lt->isLoopExit(edge)) {
+                loopExits.push_back(edge);
+            }
+        }
+    }
+   
+    //filter out all edges except branches
+    for (Edges::iterator ite = loopExits.begin(), ende = loopExits.end(); ite!=ende; ++ite) {
+       Edge* edge = *ite;
+        if (edge->isDispatchEdge() || edge->isUnconditionalEdge() || edge->isCatchEdge()) {
+            *ite = NULL;
+            continue;
+        }
+        Inst* lastInst = (Inst*)edge->getSourceNode()->getLastInst();
+        if (lastInst->isSwitch()) {
+            *ite = NULL;
+            continue;
+        }
+        assert(lastInst->isBranch());
+        assert(edge->isFalseEdge() || edge->isTrueEdge());
+    }
+    loopExits.erase(std::remove(loopExits.begin(), loopExits.end(), (Edge*)NULL), loopExits.end());
+
+    // analyze every loop exit and prepare unroll info
+    for (Edges::const_iterator ite = loopExits.begin(), ende = loopExits.end(); ite!=ende; ++ite) {
+        Edge* edge = *ite;
+        Node* sourceNode = edge->getSourceNode();
+        Inst* lastInst = (Inst*)sourceNode->getLastInst();
+        assert(lastInst->isBranch());
+        LoopUnrollInfo* info = prepareUnrollInfo(tmpMM, lt, lastInst->asBranchInst());
+        if (info == NULL) {
+            continue;
+        }
+        if (Log::isEnabled()) {
+            info->print(Log::out());
+            Log::out()<<std::endl;
+        }
+        result.push_back(info);
+    }
+}
+
+static void doUnroll(MemoryManager& mm, IRManager& irm, const LoopUnrollInfo* info, const UnrollFlags& flags) {
+    //unroll algorithm does the following
+    //before:
+    // loopOrig {
+    //    bodyA
+    //    check(idxOpnd,limitOpnd)
+    //    bodyB
+    // }
+    //after:
+    // unrolledIncOpnd = unrollCount * idx->increment
+    // unrolledLimitOpnd = limitOpnd-unrolledIncOpnd;
+    // bodyA 
+    // loopUnrolled {
+    //     check(idxOpnd,unrolledLimitOpnd)
+    //     bodyB
+    //     bodyA
+    //     bodyB
+    //     ...
+    //     bodyA
+    // }
+    // loopEpilogue {
+    //    check(idxOpnd,limitOpnd)
+    //    bodyB
+    //    bodyA
+    // }
+    //
+    //where:
+    // bodyA - all nodes of the same loop accessible from checkNode via incoming edges
+    // bodyB - all nodes except bodyA and checkNode
+
+    ControlFlowGraph& cfg = irm.getFlowGraph();
+    LoopTree* lt = cfg.getLoopTree();
+    InstFactory& instFactory = irm.getInstFactory();
+    OpndManager& opndManager = irm.getOpndManager();
+    Type* opType = info->getLimitOpnd()->getType();
+    
+ //   printf("UNROLL\n");
+
+    //STEP 0: cache all data needed
+    assert(info->unrollCount >= 1);
+    Node* origHeader = info->header;
+    assert(origHeader->getInDegree() == 2); //loop is normalized
+
+    OptPass::computeLoops(irm);//recompute loop info if needed
+    LoopNode* loopNode = lt->getLoopNode(origHeader, false); 
+    
+    Edge* entryEdge = origHeader->getInEdges().front();
+    if (lt->isBackEdge(entryEdge)) {
+        entryEdge = origHeader->getInEdges().back();
+    }
+    Node* origCheckNode = info->branchInst->getNode();
+    Edge* origLoopExitEdge = info->branchTargetIsExit ? origCheckNode->getTrueEdge() : origCheckNode->getFalseEdge();
+    
+    uint32 maxNodeId = cfg.getMaxNodeId()+1; //+1 for a split check node
+    StlBitVector nodesInLoop(mm, maxNodeId);
+    {
+        const Nodes& loopNodes = loopNode->getNodesInLoop();
+        for (Nodes::const_iterator it = loopNodes.begin(), end = loopNodes.end(); it!=end; ++it) {
+            Node* node = *it;
+            nodesInLoop.setBit(node->getId());
+        }
+    }
+    
+    
+    //STEP 1: calculate bodyA nodes
+    BitSet aFlags(mm, maxNodeId);
+    calculateReachableNodesInLoop(loopNode, origHeader, origCheckNode, aFlags);
+    StlBitVector bodyANodes(mm, maxNodeId);
+    for (uint32 i=0;i<maxNodeId;i++) bodyANodes.setBit(i, aFlags.getBit(i));
+    
+    //STEP 2: make checkNode a separate node, prepare loop region
+    bodyANodes.setBit(origCheckNode->getId(), true);
+    Node* checkNode = cfg.splitNodeAtInstruction(info->branchInst->prev(), true, false, instFactory.makeLabel());
+    nodesInLoop.setBit(checkNode->getId(), true);
+    Node* preCheckNode = origCheckNode;
+    bodyANodes.setBit(preCheckNode->getId(), true);
+    
+    //STEP 3: rotate original loop
+    // before: {bodyA1, check , bodyB}
+    // after:  bodyA2 {check, bodyB, bodyA1}
+    Edge* bodyA2ToCheckEdge = NULL;
+    Opnd* limitOpndInBodyA2 = NULL;
+    {
+        //WARN: info->limitOpnd and info->indexOpnd can be replaced after code duplication if promoted to vars
+        Opnd* limitOpndBefore = info->getLimitOpnd();
+
+        assert(preCheckNode->getOutDegree()==1 && preCheckNode->getUnconditionalEdgeTarget() == checkNode);
+        DefUseBuilder defUses(mm);
+        defUses.initialize(cfg);
+        OpndRenameTable opndRenameTable(mm, maxNodeId); //todo: maxNodeId is overkill estimate here
+        NodeRenameTable nodeRenameTable(mm, maxNodeId);
+        Node* bodyA2 = FlowGraph::duplicateRegion(irm, origHeader, bodyANodes, defUses, nodeRenameTable, opndRenameTable);
+        cfg.replaceEdgeTarget(entryEdge, bodyA2, true);
+        
+        // while duplicating a region new nodes could be created and 'nodesInRegion' bitvector param is updated. 
+        // BodyA is part of the loop -> if new nodes were created in the loop we must track them.
+        nodesInLoop.resize(bodyANodes.size());
+        for (uint32 i=0;i<bodyANodes.size();i++) nodesInLoop.setBit(i, bodyANodes.getBit(i) || nodesInLoop.getBit(i));
+
+        Node* bodyA2PreCheckNode = nodeRenameTable.getMapping(preCheckNode);
+        assert(bodyA2PreCheckNode->getOutDegree()==1 && bodyA2PreCheckNode->getUnconditionalEdgeTarget() == checkNode);
+        bodyA2ToCheckEdge = bodyA2PreCheckNode->getUnconditionalEdge();
+        limitOpndInBodyA2 = limitOpndBefore;
+        if (nodeRenameTable.getMapping(limitOpndBefore->getInst()->getNode())!=NULL) {
+            limitOpndInBodyA2 = opndRenameTable.getMapping(limitOpndBefore);
+        }
+        assert(limitOpndInBodyA2!=NULL);
+    }
+
+    //STEP 4: prepare epilogue loop: {check, bodyB, bodyA}
+    Node* epilogueLoopHead = NULL;
+    {
+        DefUseBuilder defUses(mm);
+        defUses.initialize(cfg);
+        OpndRenameTable opndRenameTable(mm, maxNodeId); //todo: maxNodeId is overkill estimate here
+        NodeRenameTable nodeRenameTable(mm, maxNodeId);
+        epilogueLoopHead = FlowGraph::duplicateRegion(irm, checkNode, nodesInLoop, defUses, nodeRenameTable, opndRenameTable);        
+        cfg.replaceEdgeTarget(origLoopExitEdge, epilogueLoopHead, true);
+
+        //backedge was not duplicated -> this is a feature (Loop.cpp depends on it), find using tailNode
+        Node* newTailNode = nodeRenameTable.getMapping(preCheckNode);
+        assert(newTailNode->getOutDegree() == 1 && newTailNode->getUnconditionalEdgeTarget() == checkNode);
+        Edge* backedge = newTailNode->getUnconditionalEdge();
+        cfg.replaceEdgeTarget(backedge, epilogueLoopHead, true);
+    }
+
+    //STEP 5: prepare unrolledLimitOpnd and replace it in original loop's check
+    {
+        Node* unrolledPreheader = cfg.spliceBlockOnEdge(bodyA2ToCheckEdge, instFactory.makeLabel());
+        Opnd* unrolledIncOpnd = opndManager.createSsaTmpOpnd(opType);
+        unrolledPreheader->appendInst(instFactory.makeLdConst(unrolledIncOpnd, info->increment * info->unrollCount));
+        Opnd* unrolledLimitOpnd = opndManager.createSsaTmpOpnd(opType);
+        Modifier mod = Modifier(SignedOp)|Modifier(Strict_No)|Modifier(Overflow_None)|Modifier(Exception_Never);
+        unrolledPreheader->appendInst(instFactory.makeSub(mod, unrolledLimitOpnd, limitOpndInBodyA2, unrolledIncOpnd));
+        info->branchInst->setSrc(info->branchLimitOpndPos, unrolledLimitOpnd);
+    }
+
+    //STEP 6: unroll original loop and remove all checks in duplicated bodies
+    {
+        Edge* backedge = preCheckNode->getUnconditionalEdge();
+        for (int i=1;i<info->unrollCount;i++) {
+            DefUseBuilder defUses(mm);
+            OpndRenameTable opndRenameTable(mm, maxNodeId);
+            NodeRenameTable nodeRenameTable(mm, maxNodeId);
+
+            Node* unrolledRegionHeader = FlowGraph::duplicateRegion(irm, checkNode, nodesInLoop, defUses, nodeRenameTable, opndRenameTable);
+            cfg.replaceEdgeTarget(backedge, unrolledRegionHeader, true); 
+
+            Node* newTail = nodeRenameTable.getMapping(preCheckNode);
+            assert(newTail->getOutDegree()==1 );
+            backedge = newTail->getUnconditionalEdge();
+            if (i>1) {
+                cfg.replaceEdgeTarget(backedge, checkNode, true);
+            }
+            
+            //remove check from duplicated code
+            Node* duplicateCheckNode = nodeRenameTable.getMapping(checkNode);
+            assert(duplicateCheckNode->getOutDegree()==2);
+            Edge* exitEdge = info->branchTargetIsExit ? duplicateCheckNode->getTrueEdge() : duplicateCheckNode->getFalseEdge();
+            duplicateCheckNode->getLastInst()->unlink();
+            cfg.removeEdge(exitEdge);
+        }
+    }
+    
+    //STEP 7: make old loop colder
+    if (cfg.hasEdgeProfile()) {
+        Edge* epilogueExit = info->branchTargetIsExit ? epilogueLoopHead->getTrueEdge() : epilogueLoopHead->getFalseEdge();
+        epilogueExit->setEdgeProb(epilogueExit->getEdgeProb() * 5);
+    }
+}   
+
+
+}//namespace
+
+

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/memoryopt.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/memoryopt.cpp?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/memoryopt.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/memoryopt.cpp Fri Jul 20 02:40:02 2007
@@ -924,7 +924,6 @@
     case Op_AddOffset:
     case Op_AddOffsetPlusHeapbase:
         
-    case Op_ScaledDiffRef:
         // the following are irrelevant, but cased so we
         // notice any additions:
 
@@ -967,8 +966,6 @@
     case Op_TauHasType:
     case Op_TauHasExactType:
     case Op_TauIsNonNull:
-    case Op_PredCmp:
-    case Op_PredBranch:
         break;
 
     //case Op_TauStRef:

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/reassociate.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/reassociate.cpp?view=diff&rev=557942&r1=557941&r2=557942
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/reassociate.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/optimizer/reassociate.cpp Fri Jul 20 02:40:02 2007
@@ -375,7 +375,6 @@
         case Op_LdArrayLenOffset:
         case Op_LdArrayLenOffsetPlusHeapbase:
         case Op_AddScaledIndex:
-        case Op_ScaledDiffRef:
         case Op_TauArrayLen:
     default:
         break;



Mime
View raw message