You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by va...@apache.org on 2007/02/02 10:17:00 UTC

svn commit: r502549 - in /harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32: Ia32Constraint.cpp Ia32ConstraintsResolver.cpp

Author: varlax
Date: Fri Feb  2 01:16:59 2007
New Revision: 502549

URL: http://svn.apache.org/viewvc?view=rev&rev=502549
Log:
Applied HARMONY-3041 [drlvm][jit][ia32/intel64]A few constraints handling improvements in codegenApplied 
Tested on SUSE10@x86, SUSE9@x86_64

Modified:
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Constraint.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32ConstraintsResolver.cpp

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Constraint.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Constraint.cpp?view=diff&rev=502549&r1=502548&r2=502549
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Constraint.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Constraint.cpp Fri Feb  2 01:16:59 2007
@@ -114,7 +114,7 @@
 
     uint32 newKind=kind, newMask=0;
     uint32 newRegKind=newKind & OpndKind_Reg;
-    if (newRegKind==OpndKind_GPReg){
+    if (newRegKind == OpndKind_GPReg || ( (newRegKind & OpndKind_GPReg) && sz <= OpndSize_16) ){
 #ifndef _EM64T_
         if (sz==OpndSize_8 && (s==OpndSize_16 || s==OpndSize_32))
             newMask=((mask>>4)|mask)&0xf;

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32ConstraintsResolver.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32ConstraintsResolver.cpp?view=diff&rev=502549&r1=502548&r2=502549
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32ConstraintsResolver.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32ConstraintsResolver.cpp Fri Feb  2 01:16:59 2007
@@ -86,15 +86,49 @@
  *
  */
 
+static const char* help = 
+"  The 'constraints' action accepts 3 sets of 3 parameters which \n"
+"  define profile-guided operand splitting for operand\n"
+"  uses, defs, and crossing call sites if these factors make\n"
+"  operand constraints worse (permitting less registers).\n"
+"  Each parameter defines a threshold enabling the splitting.\n"
+"  The threshold is applied to basic block execution count divided \n"
+"  by method entry execution count.\n"
+"  Thus, the threshold being 0 means never, and being 1000000000 means always.\n"
+"  Parameters:\n"
+"      callSplitThresholdForNoRegs=<integer>\n"
+"        Applied if crossing a call site narrows an operand constraint to NO regs.\n"
+"        Default value is 'always'.\n"
+"      callSplitThresholdFor1Reg=<integer>\n"
+"        Applied if crossing a call site narrows an operand constraint to <=1 reg.\n"
+"        Default value is 1 (very cold code).\n"
+"      callSplitThresholdFor4Regs=<integer>\n"
+"        Applied if crossing a call site narrows an operand constraint to <=4 regs.\n"
+"        Default value is 4 (very cold code).\n"
+"      defSplitThresholdForNoRegs=<integer>\n"
+"        Default value is 0 ('never').\n"
+"      defSplitThresholdFor1Reg=<integer>\n"
+"        Default value is 0 ('never').\n"
+"      defSplitThresholdFor4Regs=<integer>\n"
+"        Default value is 0 ('never').\n"
+"      useSplitThresholdForNoRegs=<integer>\n"
+"        Default value is 0 ('never').\n"
+"      useSplitThresholdFor1Reg=<integer>\n"
+"        Default value is 0 ('never').\n"
+"      useSplitThresholdFor4Regs=<integer>\n"
+"        Default value is 0 ('never').\n"
+;
+
 class ConstraintsResolver : public SessionAction {
     /** runImpl is required override, calls ConstraintsResolverImpl.runImpl */
     void runImpl();
     /** This transformer requires up-to-date liveness info */
     uint32 getNeedInfo()const{ return NeedInfo_LivenessInfo; }
     uint32 getSideEffects()const{ return 0; }
+
 };
 
-static ActionFactory<ConstraintsResolver> _constraints("constraints");
+static ActionFactory<ConstraintsResolver> _constraints("constraints", help);
 
 //========================================================================================
 // class ConstraintsResolverImpl
@@ -184,7 +218,8 @@
         liveAtDispatchBlockEntry(memoryManager,0),
         needsOriginalOpnd(memoryManager,0),
         hoveringOpnds(memoryManager,0),
-        opndReplaceWorkset(memoryManager,0)
+        opndReplaceWorkset(memoryManager,0),
+        opndUsage(memoryManager,0)
     {
     }
     
@@ -215,6 +250,11 @@
     /** returns constraint describing safe locations for operands live at dispatch node entries */
     Constraint getDispatchEntryConstraint(Opnd * opnd);
 
+    static bool constraintIsWorse(Constraint cnew, Constraint cold, unsigned normedBBExecCount, 
+        unsigned splitThresholdForNoRegs, unsigned splitThresholdFor1Reg, unsigned splitThresholdFor4Regs
+        );
+   
+
 
     /** Reference to IRManager */ 
     IRManager&                  irManager;
@@ -249,6 +289,23 @@
      *  Reset for each basic blocks (all replacements are local within basic blocks)
      */
     StlVector<Opnd*>            opndReplaceWorkset;
+
+
+    StlVector<uint32>           opndUsage;
+
+    unsigned callSplitThresholdForNoRegs;
+    unsigned callSplitThresholdFor1Reg;
+    unsigned callSplitThresholdFor4Regs;
+
+    unsigned defSplitThresholdForNoRegs;
+    unsigned defSplitThresholdFor1Reg;
+    unsigned defSplitThresholdFor4Regs;
+
+    unsigned useSplitThresholdForNoRegs;
+    unsigned useSplitThresholdFor1Reg;
+    unsigned useSplitThresholdFor4Regs;
+
+    friend class ConstraintsResolver;
 };
 
 
@@ -285,6 +342,11 @@
     for (uint32 i=0; i<originalOpndCount; i++)
         opndReplaceWorkset[i]=NULL;
 
+    opndUsage.resize(originalOpndCount);
+    for (uint32 i=0; i<originalOpndCount; i++)
+        opndUsage[i]=0;
+
+
     hoveringOpnds.resize(originalOpndCount);
 // Fill array of basic blocks and order it
     createBasicBlockArray();
@@ -372,12 +434,35 @@
 }   
 
 //_________________________________________________________________________________________________
+bool ConstraintsResolverImpl::constraintIsWorse(Constraint cnew, Constraint cold, unsigned normedBBExecCount, 
+    unsigned splitThresholdForNoRegs, unsigned splitThresholdFor1Reg, unsigned splitThresholdFor4Regs
+    )
+{
+    if (cnew.isNull())
+        return true;
+    uint32 newMask = cnew.getMask(), oldMask = cold.getMask();
+    if ((newMask & oldMask) != oldMask){
+        uint32 newMaskCount = countOnes(newMask);
+        return 
+            (newMaskCount == 0 && normedBBExecCount < splitThresholdForNoRegs) ||
+            (newMaskCount <= 1 && normedBBExecCount < splitThresholdFor1Reg) ||
+            (newMaskCount <= 4 && normedBBExecCount < splitThresholdFor4Regs);
+    }
+    return false;
+}
+
+//_________________________________________________________________________________________________
 void ConstraintsResolverImpl::resolveConstraintsWithOG(Inst * inst)
 {   
     // Initialize hoveringOpnds with operands live after the call if the inst is CALL
     if (inst->getMnemonic()==Mnemonic_CALL)
         hoveringOpnds.copyFrom(liveOpnds);
 
+    double dblExecCount = 1000. * inst->getBasicBlock()->getExecCount() / irManager.getFlowGraph()->getEntryNode()->getExecCount();
+    if (dblExecCount > 100000000.)
+        dblExecCount = 100000000.;
+    unsigned execCount = (unsigned)dblExecCount;
+
     // first handle all defs
     {Inst::Opnds opnds(inst, Inst::OpndRole_AllDefs);
     for (Inst::Opnds::iterator it = opnds.begin(); it != opnds.end(); it = opnds.next(it)){
@@ -390,8 +475,10 @@
 
         // currentOpnd is either the current replacement or the original operand
         Opnd * currentOpnd=opndReplaceWorkset[originalOpnd->getId()];
-        if (currentOpnd==NULL)
+        if (currentOpnd==NULL){
             currentOpnd=originalOpnd;
+            opndUsage[originalOpnd->getId()]+=execCount;
+        }
         // get what is already collected
         Constraint cc=currentOpnd->getConstraint(Opnd::ConstraintKind_Calculated);
         assert(!cc.isNull());
@@ -401,7 +488,7 @@
         // & the result
         Constraint cr=cc & ci;
         Opnd * opndToSet=currentOpnd;
-        if (!cr.isNull()){
+        if (!constraintIsWorse(cr, cc, execCount, defSplitThresholdForNoRegs, defSplitThresholdFor1Reg, defSplitThresholdFor4Regs)){
             // can substitute currentReplacementOpnd into this position
             currentOpnd->setCalculatedConstraint(cr);
         }else{
@@ -421,6 +508,7 @@
                     Inst * copySequence=irManager.newCopyPseudoInst(Mnemonic_MOV, opndToSet, originalOpnd); 
                     // split above the instruction
                     copySequence->insertBefore(inst);
+                    opndUsage[originalOpnd->getId()]+=execCount;
                 }
             }
         }   
@@ -446,8 +534,10 @@
             assert(!needsOriginalOpnd.getBit(originalOpnd->getId())||opndReplaceWorkset[originalOpnd->getId()]==NULL);
             // currentOpnd is either the current replacement or the original operand
             Opnd * currentOpnd=opndReplaceWorkset[originalOpnd->getId()];
-            if (currentOpnd==NULL)
+            if (currentOpnd==NULL){
                 currentOpnd=originalOpnd;
+                opndUsage[originalOpnd->getId()]+=execCount;
+            }
             Opnd * opndToSet=NULL;
             // was live and is not redefined by this inst
             if (liveOpnds.getBit(originalOpnd->getId())){ 
@@ -460,7 +550,7 @@
                 // & the result
                 Constraint cr=cc & ci;
                 opndToSet=currentOpnd;
-                if ((cr.getMask()!=0 || cc.getMask()==0) && !cr.isNull()){
+                if (!constraintIsWorse(cr, cc, execCount, callSplitThresholdForNoRegs, callSplitThresholdFor1Reg, callSplitThresholdFor4Regs)){
                     // can substitute currentReplacementOpnd into this position
                     opndToSet->setCalculatedConstraint(cr);
                 }else{
@@ -468,7 +558,7 @@
                     // Try to use originalOpnd over this instruction and for the instructions above
                     Constraint co=originalOpnd->getConstraint(Opnd::ConstraintKind_Calculated);
                     Constraint cr=co & ci;
-                    if ((cr.getMask()!=0 || co.getMask()==0)&& !cr.isNull()){ 
+                    if (!constraintIsWorse(cr, cc, execCount, callSplitThresholdForNoRegs, callSplitThresholdFor1Reg, callSplitThresholdFor4Regs)){
                         opndToSet=originalOpnd;
                         opndToSet->setCalculatedConstraint(cr);
                     }else{
@@ -483,7 +573,6 @@
                     // an operand different to the current replacement 
                     // is required to be over this call site, append splitting below the call site
                     // this is like restoring from a call-safe location under a call
-                    assert(currentOpnd->getType() == opndToSet->getType());
                     Inst * copySequence=irManager.newCopyPseudoInst(Mnemonic_MOV, currentOpnd, opndToSet);  
                     copySequence->insertAfter(inst);
                 }
@@ -495,6 +584,7 @@
                     assert(currentOpnd==originalOpnd);
                     Inst * copySequence=irManager.newCopyPseudoInst(Mnemonic_MOV, opndToSet, originalOpnd);
                     copySequence->insertBefore(inst);
+                    opndUsage[originalOpnd->getId()]+=execCount;
                 }
             }
         }
@@ -510,8 +600,10 @@
             assert(!needsOriginalOpnd.getBit(originalOpnd->getId())||opndReplaceWorkset[originalOpnd->getId()]==NULL);
             // currentOpnd is either the current replacement or the original operand
             Opnd * currentOpnd=opndReplaceWorkset[originalOpnd->getId()];
-            if (currentOpnd==NULL)
+            if (currentOpnd==NULL){
                 currentOpnd=originalOpnd;
+                opndUsage[originalOpnd->getId()]+=execCount;
+            }
             // get what is already collected
             Constraint cc=currentOpnd->getConstraint(Opnd::ConstraintKind_Calculated);
             assert(!cc.isNull());
@@ -522,7 +614,7 @@
 
             Opnd * opndToSet=currentOpnd;
 
-            if (!cr.isNull()){
+            if (!constraintIsWorse(cr, cc, execCount, useSplitThresholdForNoRegs, useSplitThresholdFor1Reg, useSplitThresholdFor4Regs)){
                 // can substitute currentReplacementOpnd into this position
                 currentOpnd->setCalculatedConstraint(cr);
             }else{
@@ -556,6 +648,7 @@
 
     // if we come to bb entry with some replacement for an operand and the operand is live at the entry
     // insert copying from the original operand to the replacement operand
+    uint32 execCount = (uint32)bb->getExecCount();
     BitSet * ls = irManager.getLiveAtEntry(bb);
     BitSet::IterB ib(*ls);
     for (int i = ib.getNext(); i != -1; i = ib.getNext()){
@@ -565,9 +658,9 @@
         if (currentOpnd!=NULL){
             if (currentOpnd!=originalOpnd){
 //              assert(irManager.getLiveAtEntry(bb)->isLive(originalOpnd));
-                assert(currentOpnd->getType() == originalOpnd->getType());
                 Inst * copySequence=irManager.newCopyPseudoInst(Mnemonic_MOV, currentOpnd, originalOpnd);
                 bb->prependInst(copySequence);
+                opndUsage[originalOpnd->getId()]+=execCount;
             }
             opndReplaceWorkset[originalOpnd->getId()]=NULL;
         }
@@ -587,13 +680,34 @@
 void ConstraintsResolver::runImpl()
 {
     // call the private implementation of the algorithm
-    ConstraintsResolverImpl(*irManager).run();
+    ConstraintsResolverImpl impl(*irManager);
+    
+    impl.callSplitThresholdForNoRegs = (unsigned)-1; // always
+    getArg("callSplitThresholdForNoRegs", impl.callSplitThresholdForNoRegs);
+    impl.callSplitThresholdFor1Reg = 1; // for very cold code
+    getArg("callSplitThresholdFor1Reg", impl.callSplitThresholdFor1Reg);
+    impl.callSplitThresholdFor4Regs = 1; // for very cold code
+    getArg("callSplitThresholdFor4Regs", impl.callSplitThresholdFor4Regs);
+
+    impl.defSplitThresholdForNoRegs = 0; // never
+    getArg("defSplitThresholdForNoRegs", impl.defSplitThresholdForNoRegs);
+    impl.defSplitThresholdFor1Reg = 0; // never
+    getArg("defSplitThresholdFor1Reg", impl.defSplitThresholdFor1Reg);
+    impl.defSplitThresholdFor4Regs = 0; // never
+    getArg("defSplitThresholdFor4Regs", impl.defSplitThresholdFor4Regs);
+
+    impl.useSplitThresholdForNoRegs = 0; // never
+    getArg("useSplitThresholdForNoRegs", impl.useSplitThresholdForNoRegs);
+    impl.useSplitThresholdFor1Reg = 0; // never
+    getArg("useSplitThresholdFor1Reg", impl.useSplitThresholdFor1Reg);
+    impl.useSplitThresholdFor4Regs = 0; // never
+    getArg("useSplitThresholdFor4Regs", impl.useSplitThresholdFor4Regs);
+
+    impl.run();
 }
 
 
 //_________________________________________________________________________________________________
-
-
 
 }}; //namespace Ia32