You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ch...@apache.org on 2009/02/25 17:15:50 UTC

svn commit: r747844 - in /harmony/enhanced/drlvm/trunk/vm/jitrino: config/ia32/ src/codegenerator/ia32/

Author: chunrong
Date: Wed Feb 25 16:15:49 2009
New Revision: 747844

URL: http://svn.apache.org/viewvc?rev=747844&view=rev
Log:
Apply patch for HARMONY-5826, adding global propagation in drlvm jit

Added:
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32GlobalPropagation.cpp   (with props)
Modified:
    harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/server.emconf
    harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/server_aggressive.emconf
    harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/server_static.emconf
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32PeepHole.cpp

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?rev=747844&r1=747843&r2=747844&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/server.emconf (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/server.emconf Wed Feb 25 16:15:49 2009
@@ -67,7 +67,7 @@
 
 -XX:jit.SD1_OPT.path.optimizer=ssa,simplify,dce,uce,vp_instrument,devirt_virtual,edge_instrument,dessa,statprof
 -XX:jit.SD1_OPT.path.devirt_virtual=devirt
--XX:jit.SD1_OPT.path.codegen=bbp,btr,gcpoints,cafl,dce1,i8l,api_magic,light_jni-,early_prop,peephole,itrace-,native,constraints,dce2,regalloc,spillgen,copy,i586,layout,rce+,stack,break-,iprof-,peephole,emitter!,si_insts,gcmap,info
+-XX:jit.SD1_OPT.path.codegen=bbp,btr,gcpoints,cafl,dce1,i8l,api_magic,light_jni-,early_prop,global_prop,peephole,itrace-,native,constraints,dce2,regalloc,spillgen,copy,i586,layout,rce+,stack,break-,iprof-,peephole,emitter!,si_insts,gcmap,info
 -XX:jit.SD1_OPT.path.dce1=cg_dce
 -XX:jit.SD1_OPT.path.dce2=cg_dce
 
@@ -84,7 +84,7 @@
 -XX:jit.SD2_OPT.path.osr_path=gcm,osr,simplify,dce,uce
 -XX:jit.SD2_OPT.path.escape_path=hvn,simplify,dce,uce,escape
 -XX:jit.SD2_OPT.path.abce=classic_abcd,dce,uce,dessa,statprof,peel,ssa,hvn,simplify,dce,uce,memopt,dce,uce,dessa,fastArrayFill,ssa,statprof,dabce,dce,uce
--XX:jit.SD2_OPT.path.codegen=lock_method,bbp,btr,gcpoints,cafl,dce1,i8l,api_magic,light_jni-,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.codegen=lock_method,bbp,btr,gcpoints,cafl,dce1,i8l,api_magic,light_jni-,early_prop,global_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_aggressive.emconf
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/server_aggressive.emconf?rev=747844&r1=747843&r2=747844&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/server_aggressive.emconf (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/server_aggressive.emconf Wed Feb 25 16:15:49 2009
@@ -59,7 +59,7 @@
 
 
 -XX:jit.SD1_OPT.path.optimizer=ssa,simplify,dce,uce,vp_instrument,edge_instrument,dessa,statprof
--XX:jit.SD1_OPT.path.codegen=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
+-XX:jit.SD1_OPT.path.codegen=bbp,btr,gcpoints,cafl,dce1,i8l,api_magic,early_prop,global_prop,peephole,itrace-,native,constraints,dce2,regalloc,spillgen,copy,i586,layout,rce+,stack,break-,iprof-,peephole,emitter!,si_insts,gcmap,info
 -XX:jit.SD1_OPT.path.dce1=cg_dce
 -XX:jit.SD1_OPT.path.dce2=cg_dce
 
@@ -78,7 +78,7 @@
 -XX:jit.SD2_OPT.path.escape_path=hvn,simplify,dce,uce,escape
 -XX:jit.SD2_OPT.path.abce=classic_abcd,dce,uce,dessa,statprof,peel,ssa,hvn,simplify,dce,uce,memopt,dce,uce,dessa,fastArrayFill,ssa,statprof,dabce,dce,uce
 
--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.codegen=lock_method,bbp,btr,gcpoints,cafl,dce1,i8l,api_magic,early_prop,global_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?rev=747844&r1=747843&r2=747844&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/server_static.emconf (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/config/ia32/server_static.emconf Wed Feb 25 16:15:49 2009
@@ -36,7 +36,7 @@
 -XX:jit.SS_OPT.path.osr_path=gcm,osr,simplify,dce,uce
 -XX:jit.SS_OPT.path.escape_path=hvn,simplify,dce,uce,escape
 -XX:jit.SS_OPT.path.abce=classic_abcd,dce,uce,dessa,statprof,peel,ssa,hvn,simplify,dce,uce,memopt,dce,uce,dessa,fastArrayFill,ssa,statprof,dabce,dce,uce
--XX:jit.SS_OPT.path.codegen=lock_method,bbp,btr,gcpoints,cafl,dce1,i8l,api_magic,light_jni-,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.SS_OPT.path.codegen=lock_method,bbp,btr,gcpoints,cafl,dce1,i8l,api_magic,light_jni-,early_prop,global_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.SS_OPT.path.dce1=cg_dce
 -XX:jit.SS_OPT.path.dce2=cg_dce
 

Added: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32GlobalPropagation.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32GlobalPropagation.cpp?rev=747844&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32GlobalPropagation.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32GlobalPropagation.cpp Wed Feb 25 16:15:49 2009
@@ -0,0 +1,536 @@
+/*
+ *  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 Xiaoming GU
+ * @version $Revision$
+ */
+
+#include <fstream>
+#include "Stl.h"
+#include "Log.h"
+#include "Ia32IRManager.h"
+#include "Ia32Printer.h"
+
+namespace Jitrino
+{
+namespace Ia32
+{
+
+//========================================================================================
+// class GlobalPropagation
+//========================================================================================
+/**
+ * This file is about LIR global constant/copy propagation for non-MEM operands. It is 
+ * augmented from "early propagation" which only works for the operands defined just once.
+ *  
+ *   0. Data Structures
+ *         A dst-src pair: [dst, src] which comes from a copy inst - MOV dst,src
+ *         Eache BB: IN, OUT, KILL, GEN 
+ *           IN: the set of dst-src pairs which are valid at the beginning of a BB (StlHashMap)
+ *           OUT: the set of dst-src pairs which are valid at the end of a BB (StlHashMap)
+ *           KILL: the set of variables which are killed in a BB (StlSet)
+ *           GEN: the local set of dst-src pairs which are valid at the end of a BB (StlHashMap)
+ *           VISITED: the flag indicating whether a BB is processed before (bool) 
+ *         A list BBInfoHashMap (StlHashMap) containing BBInfo for each BB
+ *   1. Initialization
+ *       a) Local copy propagation
+ *       b) Do local analysis for all BBs to compute KILL, GEN (OUT) and set IN as null.
+ *   2. Iterative Data-flow Analysis
+ *       While any IN changes, traverse all BBs. (Order doesn't matter on correctness 
+ *       but preorder is better - less iterations.)
+ *           For each BB b
+ *               a) IN(b) = intersect(OUT of all pred(b))
+ *                   + Do lattice computation on the srcs for the multiple pairs with the same dst.
+ *               b) OUT(b) = (IN(b)-KILL(b)) union GEN(b) 
+ *                   + If no change happens in IN, continue to next BB.
+ *                   + Delete the pairs related to KILL.
+ *                   + Add the pairs from GEN to OUT.
+ *   3. Local propagation for the pairs in IN
+ */
+
+//#define DEBUG_GLOBAL_PROP
+class GlobalPropagation : public SessionAction {
+    void runImpl();
+    U_32 getNeedInfo()const{ return 0; }
+};
+
+static ActionFactory<GlobalPropagation> _global_prop("global_prop");
+
+static bool isTypeConversionAllowed(Opnd* fromOpnd, Opnd* toOpnd) {
+    Type * fromType = fromOpnd->getType();
+    Type * toType = toOpnd->getType();
+    bool fromIsGCType = fromType->isObject() || fromType->isManagedPtr();
+    bool toIsGCType = toType->isObject() || toType->isManagedPtr();
+    return fromIsGCType == toIsGCType;
+}
+
+struct BBInfo {
+    StlHashMap<Opnd*, Opnd*> *in;
+    StlHashMap<Opnd*, Opnd*> *out;
+    StlSet<Opnd*> *kill;
+    StlHashMap<Opnd*, Opnd*> *gen;
+    bool visited; //for loop
+    BBInfo()
+            :in(NULL), out(NULL), kill(NULL), gen(NULL) {}
+};
+
+#define BOTTOM NULL
+
+void outputBBInfo(Node* node, BBInfo *bbInfo) {
+    std::cout << "************BB #" << node->getId() << "************" << std::endl;
+    std::cout << "\t\tPred: ";
+    const Edges& edges = node->getInEdges();
+    Edges::const_iterator ite=edges.begin();
+    Edges::const_iterator ende=edges.end();
+    while(ite != ende) {
+        std::cout << (*ite)->getSourceNode()->getId() << "\t";
+        ++ite;
+    }
+    std::cout << std::endl;
+
+    std::cout << "\tIN: " << std::endl;
+    for(StlHashMap<Opnd*, Opnd*>::iterator iter=bbInfo->in->begin();
+        iter!=bbInfo->in->end();++iter) {
+        std::cout << "\t\tdst: " << iter->first->getFirstId();
+        if (iter->second != NULL)
+            std::cout << "\tsrc: " << iter->second->getFirstId() << std::endl;
+        else
+            std::cout << "\tsrc: BOTTOM" << std::endl;
+    }
+
+    std::cout << "\tOUT: " << std::endl;
+    for(StlHashMap<Opnd*, Opnd*>::iterator iter=bbInfo->out->begin();
+        iter!=bbInfo->out->end();++iter) {
+        std::cout << "\t\tdst: " << iter->first->getFirstId();
+        if (iter->second != NULL)
+            std::cout << "\tsrc: " << iter->second->getFirstId() << std::endl;
+        else
+            std::cout << "\tsrc: BOTTOM" << std::endl;
+    }
+
+    std::cout << "\tKILL: " << std::endl;
+    StlSet<Opnd*>::iterator iterr;
+    for(iterr=bbInfo->kill->begin();iterr!=bbInfo->kill->end();++iterr) {
+        std::cout << "\t\topnd: " << (*iterr)->getFirstId() << std::endl;
+    }
+
+    std::cout << "\tGEN: " << std::endl;
+    for(StlHashMap<Opnd*, Opnd*>::iterator iter=bbInfo->gen->begin();
+        iter!=bbInfo->gen->end();++iter) {
+        std::cout << "\t\tdst: " << iter->first->getFirstId() << "\tsrc: " << iter->second->getFirstId() << std::endl;
+    }
+
+    std::cout << "\tvisited: " << bbInfo->visited << std::endl;
+}
+
+//___________________________________________________________________________________________________
+void GlobalPropagation::runImpl()
+{  
+    irManager->updateLoopInfo();
+
+    MemoryManager mm("global_prop");
+    StlHashMap<Node*, BBInfo*> BBInfoList(mm);
+    StlSet<Opnd*> temp(mm);
+    StlHashMap<Opnd*, Opnd*> newIn(mm);
+    
+    /* Local analysis and propagation */
+    const Nodes& postOrdered = irManager->getFlowGraph()->getNodesPostOrder();
+    for (Nodes::const_reverse_iterator it=postOrdered.rbegin(), end=postOrdered.rend();it!=end;++it) {
+        Node * node=*it;
+
+        BBInfo *bbInfo = new(mm) BBInfo;
+        BBInfoList[node] = bbInfo;
+        bbInfo->in = new(mm) StlHashMap<Opnd*, Opnd*>(mm);
+        bbInfo->out = new(mm) StlHashMap<Opnd*, Opnd*>(mm);
+        bbInfo->kill = new(mm) StlSet<Opnd*>(mm);
+        bbInfo->gen = new(mm) StlHashMap<Opnd*, Opnd*>(mm);
+        bbInfo->visited = false;
+        
+        /*
+         * Traverse all INST in a BB in preorder
+         *    For all INST - several DEF, several USE 
+         *        + Replace a USE with [USE, src] in GEN
+         *        + Delete [DEF, ...] and [..., DEF] from GEN 
+         *        + Add DEF to KILL
+         */
+        for (Inst * inst=(Inst*)node->getFirstInst();inst != NULL;inst=inst->getNextInst()) {
+            const bool isCopy = inst->getMnemonic() == Mnemonic_MOV;
+            Inst::Opnds opnds(inst, Inst::OpndRole_All);
+  
+            for (Inst::Opnds::iterator it=opnds.begin();it != opnds.end();it = opnds.next(it)) {
+                Opnd * opnd=inst->getOpnd(it);
+                U_32 roles=inst->getOpndRoles(it);
+                
+                if (roles & Inst::OpndRole_Use) {
+                    if ((roles & Inst::OpndRole_All & Inst::OpndRole_FromEncoder) 
+                        && (roles & Inst::OpndRole_All & Inst::OpndRole_ForIterator)
+                        && (roles & Inst::OpndRole_Changeable) && ((roles & Inst::OpndRole_Def) == 0)
+                        && bbInfo->gen->has(opnd)) {
+                        if (opnd->getType()->isUnmanagedPtr() && (*(bbInfo->gen))[opnd]->getType()->isInteger())
+                            (*(bbInfo->gen))[opnd]->setType(opnd->getType());
+                        inst->setOpnd(it, (*(bbInfo->gen))[opnd]);
+                   }
+                }
+            }
+            
+            for (Inst::Opnds::iterator it = opnds.begin();it != opnds.end();it = opnds.next(it)) {
+                Opnd * opnd=inst->getOpnd(it);
+                U_32 roles=inst->getOpndRoles(it);
+
+                if (roles & Inst::OpndRole_Def) {
+                    if (bbInfo->gen->has(opnd)) {
+                        bbInfo->gen->erase(opnd);
+                    }
+
+                    temp.clear();
+                    for(StlHashMap<Opnd*, Opnd*>::iterator iter=bbInfo->gen->begin();
+                        iter!=bbInfo->gen->end();++iter) {
+                        if (iter->second == opnd) {
+                            temp.insert(iter->first);
+                        }
+                    }
+                    for(StlSet<Opnd*>::iterator iter=temp.begin();
+                        iter!=temp.end();++iter) {
+                        bbInfo->gen->erase(*iter);
+                    }
+
+                    if (!bbInfo->kill->has(opnd))
+                        bbInfo->kill->insert(opnd);
+
+                }
+            }
+
+            /*
+             * For MOV inst which could update the map - one DEF, one USE 
+             *        + Add [DEF, USE] to GEN
+             *           - If [USE, s_old] exists in OUT then add [DEF, s_old] instead.
+             *           - Otherwise add [DEF, USE] itself.
+             */
+            if (isCopy) {
+                Inst::Opnds opnds(inst, Inst::OpndRole_All);
+                Opnd * dst = NULL;
+                Opnd * src = NULL;
+                U_32 counterDef = 0;
+                U_32 counterUse = 0;
+                for (Inst::Opnds::iterator it=opnds.begin();it!=opnds.end();it=opnds.next(it)) {
+                    Opnd * opnd = inst->getOpnd(it);
+                    U_32 roles = inst->getOpndRoles(it);
+                    
+                    if (roles & Inst::OpndRole_Def) {
+                        counterDef++;
+                        dst = opnd;
+                    } else if (roles & Inst::OpndRole_Use) {
+                        counterUse++;
+                        src = opnd;
+                    }
+                }
+
+                if ((counterDef == 1) && (counterUse == 1) && (!dst->hasAssignedPhysicalLocation())) {
+                    bool kindsAreOk = true;
+                    if(src->canBePlacedIn(OpndKind_FPReg) || dst->canBePlacedIn(OpndKind_FPReg)) {
+                        Constraint srcConstr = src->getConstraint(Opnd::ConstraintKind_Calculated);
+                        Constraint dstConstr = dst->getConstraint(Opnd::ConstraintKind_Calculated);
+                        kindsAreOk = ! (srcConstr&dstConstr).isNull();
+                    }
+                    bool typeConvOk = isTypeConversionAllowed(src, dst);
+                    if (typeConvOk && kindsAreOk && ! src->isPlacedIn(OpndKind_Reg)) {
+                        if (bbInfo->gen->has(src)) {
+                            /* The oldest source is selected heuristically. Some chances maybe missed afterward. */
+                            (*(bbInfo->gen))[dst] = (*(bbInfo->gen))[src];
+                        }
+                        else {
+                            (*(bbInfo->gen))[dst] = src;
+                        }
+                    }
+                }
+            }
+        }
+
+        bbInfo->out->insert(bbInfo->gen->begin(), bbInfo->gen->end());
+    }
+
+#ifdef DEBUG_GLOBAL_PROP
+    for (Nodes::const_reverse_iterator it=postOrdered.rbegin(),end=postOrdered.rend();it!=end;++it) {
+        Node * node=*it;
+        if (isMain)
+            outputBBInfo(node, BBInfoList[node]);
+    }
+#endif
+
+    /* Iterative data-flow analysis */
+    bool changed = true;
+    while (changed) {
+        changed = false;
+        
+        for (Nodes::const_reverse_iterator it=postOrdered.rbegin(),end = postOrdered.rend();it!=end;++it) {
+            Node * node = *it;
+            BBInfo *bbInfo = BBInfoList[node];
+            if (!bbInfo->visited)
+                bbInfo->visited = true;
+
+            /* Set IN of a BB as the Intersection of all the OUT of its visited predecessors */
+            const Edges& edges = node->getInEdges();
+            Edges::const_iterator ite=edges.begin();
+            Edges::const_iterator ende=edges.end();
+            Edge* edge = NULL;
+            Node * pred = NULL;
+            BBInfo *predBBInfo = NULL;
+
+            newIn.clear();
+            /* Find the first valid predecessor */
+            while (ite != ende) {
+                edge = *ite;
+                pred = edge->getSourceNode();
+                predBBInfo = BBInfoList[pred];
+                if (predBBInfo->visited)
+                    break;
+                pred = NULL;
+                predBBInfo = NULL;
+                ++ite;
+            }
+            if (predBBInfo) {
+                for(StlHashMap<Opnd*, Opnd*>::iterator iter=predBBInfo->out->begin();
+                    iter!=predBBInfo->out->end();++iter) {
+                    Opnd* dst = iter->first;
+                    Opnd* src = iter->second;
+                    newIn[dst] = src;
+                }
+                ++ite;
+
+                for (;ite!=ende;++ite) {
+                    edge = *ite;
+                    pred = edge->getSourceNode();
+                    predBBInfo = BBInfoList[pred];
+                    if (!predBBInfo->visited)
+                        continue;
+                    
+                    /* Do intersection */
+                    temp.clear();
+                    for(StlHashMap<Opnd*, Opnd*>::iterator iter=newIn.begin();
+                        iter!=newIn.end();++iter) {
+                        Opnd* dst = iter->first;
+                        if (!predBBInfo->out->has(dst)) {
+                            temp.insert(dst);
+                        }
+                        else {
+                            Opnd* src = (*(predBBInfo->out))[dst];
+                            Opnd* exSrc = iter->second;
+                            if (src != BOTTOM) {
+                                if (exSrc == BOTTOM)
+                                    src = BOTTOM;
+                                else if ((exSrc != src) && (!(exSrc->isPlacedIn(OpndKind_Imm) 
+                                           && src->isPlacedIn(OpndKind_Imm) && (exSrc->getImmValue() == src->getImmValue()))))
+                                           src = BOTTOM;
+                            }
+
+                            if (src == BOTTOM) {
+                                temp.insert(dst);
+                            }
+                        }
+                    }
+                    for(StlSet<Opnd*>::iterator iter=temp.begin();
+                        iter!=temp.end();++iter) {
+                        newIn.erase(*iter);
+                    }
+                }
+            }
+
+            bool equal = true;
+            for (StlHashMap<Opnd*, Opnd*>::iterator iter=newIn.begin();
+                iter!=newIn.end();++iter) {
+                if (!((bbInfo->in->has(iter->first)) && ((*(bbInfo->in))[iter->first] == iter->second))) {
+                    equal = false;
+                    break;
+                }
+            }
+            if (equal) {
+                for (StlHashMap<Opnd*, Opnd*>::iterator iter=bbInfo->in->begin();
+                    iter!=bbInfo->in->end();++iter) {
+                    if (!((newIn.has(iter->first)) && (newIn[iter->first] == iter->second))) {
+                        equal = false;
+                        break;
+                    }
+                }
+            }
+            if (!equal) {
+                bbInfo->in->clear();
+                bbInfo->in->insert(newIn.begin(), newIn.end());
+                if (!changed)
+                    changed = true;
+            } else {
+                continue;
+            }
+            
+            /* Compute OUT from current IN and invariant KILL, GEN */
+            bbInfo->out->clear();
+            for(StlHashMap<Opnd*, Opnd*>::iterator iter=bbInfo->in->begin();
+                iter!=bbInfo->in->end();++iter) {
+                Opnd* dst = iter->first;
+                Opnd* src = iter->second;
+                if (!(bbInfo->kill->has(dst) || bbInfo->kill->has(src)))
+                    (*(bbInfo->out))[dst] = src;
+            }
+
+            /*
+             *  Try to add [d_new, s_new] from GEN to OUT
+             *     - If [s_new, s_old] exists in OUT then add [d_new, s_old] instead.
+             *     - Otherwise add [d_new, s_new] itself.
+             */
+            for(StlHashMap<Opnd*, Opnd*>::iterator iterr=bbInfo->gen->begin();
+                iterr!=bbInfo->gen->end();++iterr) {
+                Opnd* dst = iterr->first;
+                Opnd* src = iterr->second;
+                assert(!bbInfo->out->has(dst));
+                if (bbInfo->out->has(src))
+                    (*(bbInfo->out))[dst] = (*(bbInfo->out))[src];
+                else
+                    (*(bbInfo->out))[dst] = src;
+            }
+            	
+        }
+
+#ifdef DEBUG_GLOBAL_PROP
+        for (Nodes::const_reverse_iterator it=postOrdered.rbegin(),end=postOrdered.rend();it!=end;++it) {
+            Node * node=*it;
+            if (isMain)
+                outputBBInfo(node, BBInfoList[node]);
+        }
+#endif
+    }
+
+#ifdef DEBUG_GLOBAL_PROP
+    for (Nodes::const_reverse_iterator it=postOrdered.rbegin(),end=postOrdered.rend();it!=end;++it) {
+        Node * node=*it;
+        if (isMain)
+            outputBBInfo(node, BBInfoList[node]);
+    }
+#endif
+
+    /* Local propagation for the pairs in IN */
+    for (Nodes::const_reverse_iterator it=postOrdered.rbegin(), end=postOrdered.rend();it!=end;++it) {
+        Node * node=*it;
+        if (!node->isBlockNode()) {
+            continue;
+        }
+        BBInfo *bbInfo = BBInfoList[node];
+
+        /*
+         * Traverse all INST in a BB in preorder
+         *    For all INST - several DEF, several USE 
+         *        + Replace a USE with [USE, src] in IN
+         *        + Delete [DEF, ...] and [..., DEF] from IN 
+         *        + Add DEF to KILL
+         */
+        for (Inst * inst=(Inst*)node->getFirstInst();inst != NULL;inst=inst->getNextInst()) {
+            const bool isCopy = inst->getMnemonic() == Mnemonic_MOV;
+            Inst::Opnds opnds(inst, Inst::OpndRole_All);
+  
+            for (Inst::Opnds::iterator it=opnds.begin();it != opnds.end();it = opnds.next(it)) {
+                Opnd * opnd=inst->getOpnd(it);
+                U_32 roles=inst->getOpndRoles(it);
+                
+                if (roles & Inst::OpndRole_Use) {
+                    if ((roles & Inst::OpndRole_All & Inst::OpndRole_FromEncoder) 
+                        && (roles & Inst::OpndRole_All & Inst::OpndRole_ForIterator)
+                        && (roles & Inst::OpndRole_Changeable) && ((roles & Inst::OpndRole_Def) == 0)
+                        && bbInfo->in->has(opnd) && ((*(bbInfo->in))[opnd] != BOTTOM)) {
+                        assert((*(bbInfo->in))[opnd] != BOTTOM);
+                        if (opnd->getType()->isUnmanagedPtr() && (*(bbInfo->in))[opnd]->getType()->isInteger())
+                            (*(bbInfo->in))[opnd]->setType(opnd->getType());
+                        inst->setOpnd(it, (*(bbInfo->in))[opnd]);
+                    }
+                }
+            }
+            
+            for (Inst::Opnds::iterator it = opnds.begin();it != opnds.end();it = opnds.next(it)) {
+                Opnd * opnd=inst->getOpnd(it);
+                U_32 roles=inst->getOpndRoles(it);
+
+                if (roles & Inst::OpndRole_Def) {
+                    if (bbInfo->in->has(opnd)) {
+                        bbInfo->in->erase(opnd);
+                    }
+
+                    temp.clear();
+                    for(StlHashMap<Opnd*, Opnd*>::iterator iter=bbInfo->in->begin();
+                        iter!=bbInfo->in->end();++iter) {
+                        if (iter->second == opnd) {
+                            temp.insert(iter->first);
+                        }
+                    }
+                    for(StlSet<Opnd*>::iterator iter=temp.begin();
+                        iter!=temp.end();++iter) {
+                        bbInfo->in->erase(*iter);
+                    }
+ 
+                    if (!bbInfo->kill->has(opnd))
+                        bbInfo->kill->insert(opnd);
+
+                }
+            }
+
+            /*
+             * For MOV inst which could update the map - one DEF, one USE 
+             *        + Try to add [DEF, USE] to IN
+             *           - If [USE, s_old] exists in IN then add [DEF, s_old] too.
+             *           - Otherwise add [DEF, USE] itself.
+             */
+            if (isCopy) {
+                Inst::Opnds opnds(inst, Inst::OpndRole_All);
+                Opnd * dst = NULL;
+                Opnd * src = NULL;
+                U_32 counterDef = 0;
+                U_32 counterUse = 0;
+                for (Inst::Opnds::iterator it=opnds.begin();it!=opnds.end();it=opnds.next(it)) {
+                    Opnd * opnd = inst->getOpnd(it);
+                    U_32 roles = inst->getOpndRoles(it);
+                    
+                    if (roles & Inst::OpndRole_Def) {
+                        counterDef++;
+                        dst = opnd;
+                    } else if (roles & Inst::OpndRole_Use) {
+                        counterUse++;
+                        src = opnd;
+                    }
+                }
+
+                if ((counterDef == 1) && (counterUse == 1) && (!dst->hasAssignedPhysicalLocation())) {
+                    bool kindsAreOk = true;
+                    if(src->canBePlacedIn(OpndKind_FPReg) || dst->canBePlacedIn(OpndKind_FPReg)) {
+                        Constraint srcConstr = src->getConstraint(Opnd::ConstraintKind_Calculated);
+                        Constraint dstConstr = dst->getConstraint(Opnd::ConstraintKind_Calculated);
+                        kindsAreOk = ! (srcConstr&dstConstr).isNull();
+                    }
+                    bool typeConvOk = isTypeConversionAllowed(src, dst);
+                    if (typeConvOk && kindsAreOk && ! src->isPlacedIn(OpndKind_Reg)) {
+                        if (bbInfo->in->has(src)) {
+                            /* The oldest source is selected heuristically. Some chances maybe missed afterward. */
+                            (*(bbInfo->in))[dst] = (*(bbInfo->in))[src];
+                        }
+                        else {
+                            (*(bbInfo->in))[dst] = src;
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+}}
+

Propchange: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32GlobalPropagation.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp?rev=747844&r1=747843&r2=747844&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp Wed Feb 25 16:15:49 2009
@@ -975,16 +975,14 @@
     (1)         (2)             (3)
     */
     //
-    newSubGFG();
-    Node* entryNode = getSubCfgEntryNode();
+    if (inline_mul64_checks) {
+        newSubGFG();
+        Node* entryNode = getSubCfgEntryNode();
+    
+        Node* longMulNode = newBB();
+        Node* storeResultNode = newBB();
+        setCurrentNode(NULL); 
     
-    Node* longMulNode = newBB();
-    Node* storeResultNode = newBB();
-    setCurrentNode(NULL); 
-    if (!inline_mul64_checks) {
-        connectNodes(entryNode, longMulNode);
-    }
-    else {
         Node* test_A_Node = newBB();
         Node* test_B_Node = newBB();
         Node* simpleMulNode = newBB();
@@ -1018,38 +1016,63 @@
         connectNodeTo(storeResultNode);
         setCurrentNode(NULL);
         simpleMulNode = (Node*)0xDEADBEEF;
-    }
-    entryNode = (Node*)0xDEADBEEF;
-    
-    setCurrentNode(longMulNode);
-    /* mov eax, a_lo*/  newInst(Mnemonic_MOV, eax, a_lo);
-    /* mul     b_hi */  newInst(Mnemonic_MUL, 2, edx, eax, eax, b_hi);
-    //
-    // Now, EAX=a_lo*b_hi, EDX content is dropped
-    //
-                        // save a_lo*b_hi(EAX) 
-    /* mov ecx, eax */  newInst(Mnemonic_MOV, ecx, eax);
-    /* mov eax, a_hi*/  newInst(Mnemonic_MOV, eax, a_hi);
-    /* mul b_lo     */  newInst(Mnemonic_MUL, 2, edx, eax, eax, b_lo);
-    /* add ecx, eax */  newInst(Mnemonic_ADD, 1, ecx, ecx, eax);
-
-    /* mov eax, a_lo */ newInst(Mnemonic_MOV, eax, a_lo);
-    /* mul b_lo      */ newInst(Mnemonic_MUL, 2, edx, eax, eax, b_lo);
-    /* add edx, ecx */  newInst(Mnemonic_ADD, 1, edx, edx, ecx);
-    connectNodes(longMulNode, storeResultNode);
-    setCurrentNode(NULL);
-    longMulNode = (Node*)0xDEADBEEF;
+
+        entryNode = (Node*)0xDEADBEEF;
     
-    //
-    // storeResultNode:
-    //
-    setCurrentNode(storeResultNode);
-    /* mov res_lo, eax*/    newInst(Mnemonic_MOV, res_lo, eax);
-    /* mov res_hi, edx*/    newInst(Mnemonic_MOV, res_hi, edx);
-    setCurrentNode(NULL);
-    connectNodes(storeResultNode, getSubCfgReturnNode());
+        setCurrentNode(longMulNode);
+        /* mov eax, a_lo*/  newInst(Mnemonic_MOV, eax, a_lo);
+        /* mul     b_hi */  newInst(Mnemonic_MUL, 2, edx, eax, eax, b_hi);
+        //
+        // Now, EAX=a_lo*b_hi, EDX content is dropped
+        //
+                            // save a_lo*b_hi(EAX) 
+        /* mov ecx, eax */  newInst(Mnemonic_MOV, ecx, eax);
+        /* mov eax, a_hi*/  newInst(Mnemonic_MOV, eax, a_hi);
+        /* mul b_lo     */  newInst(Mnemonic_MUL, 2, edx, eax, eax, b_lo);
+        /* add ecx, eax */  newInst(Mnemonic_ADD, 1, ecx, ecx, eax);
 
-    propagateSubCFG(inst);
+        /* mov eax, a_lo */ newInst(Mnemonic_MOV, eax, a_lo);
+        /* mul b_lo      */ newInst(Mnemonic_MUL, 2, edx, eax, eax, b_lo);
+        /* add edx, ecx */  newInst(Mnemonic_ADD, 1, edx, edx, ecx);
+        connectNodes(longMulNode, storeResultNode);
+        setCurrentNode(NULL);
+        longMulNode = (Node*)0xDEADBEEF;
+
+        //
+        // storeResultNode:
+        //
+        setCurrentNode(storeResultNode);
+        /* mov res_lo, eax*/    newInst(Mnemonic_MOV, res_lo, eax);
+        /* mov res_hi, edx*/    newInst(Mnemonic_MOV, res_hi, edx);
+        setCurrentNode(NULL);
+        connectNodes(storeResultNode, getSubCfgReturnNode());
+
+        propagateSubCFG(inst);
+    } else {
+        /* mov eax, a_lo */ irManager->newCopyPseudoInst(Mnemonic_MOV, eax, a_lo)->insertBefore(inst);
+        /* mul     b_hi */  irManager->newInstEx(Mnemonic_MUL, 2, edx, eax, eax, b_hi, NULL)->insertBefore(inst);
+        // Now, EAX=low32bit(a_lo*b_hi), EDX content is dropped
+
+        /* mov ecx, eax */  irManager->newCopyPseudoInst(Mnemonic_MOV, ecx, eax)->insertBefore(inst); 
+        // Now, a_lo*b_hi is saved to ECX
+        
+        /* mov eax, a_hi*/  irManager->newCopyPseudoInst(Mnemonic_MOV, eax, a_hi)->insertBefore(inst);
+        /* mul b_lo     */  irManager->newInstEx(Mnemonic_MUL, 2, edx, eax, eax, b_lo, NULL)->insertBefore(inst);
+        // Now, EAX=low32bit(a_hi*b_lo), EDX content is dropped
+        
+        /* add ecx, eax */  irManager->newInstEx(Mnemonic_ADD, 1, ecx, ecx, eax)->insertBefore(inst);
+        // Now, ECX=low32bit(a_lo*b_hi+a_hi*b_lo)
+
+        /* mov eax, a_lo */ irManager->newCopyPseudoInst(Mnemonic_MOV, eax, a_lo)->insertBefore(inst);
+        /* mul b_lo      */ irManager->newInstEx(Mnemonic_MUL, 2, edx, eax, eax, b_lo, NULL)->insertBefore(inst);
+        // Now, EAX=low32bit(a_lo*b_lo) and EDX=high32bit(a_lo*b_lo)
+        
+        /* add edx, ecx */  irManager->newInstEx(Mnemonic_ADD, 1, edx, edx, ecx)->insertBefore(inst);
+        // Now, EDX=low32bit(a_lo*b_hi+a_hi*b_lo)+high32bit(a_lo*b_lo)
+
+        /* mov res_lo, eax*/    irManager->newCopyPseudoInst(Mnemonic_MOV, res_lo, eax)->insertBefore(inst);
+        /* mov res_hi, edx*/    irManager->newCopyPseudoInst(Mnemonic_MOV, res_hi, edx)->insertBefore(inst);
+    }
 }
 
 void I8Lowerer::lowerDiv64(Inst* inst)

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32PeepHole.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32PeepHole.cpp?rev=747844&r1=747843&r2=747844&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32PeepHole.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32PeepHole.cpp Wed Feb 25 16:15:49 2009
@@ -99,10 +99,17 @@
     //
     //
     bool m_bHadAnyChange;
+
+    // For local propagation from new generated MOV
+    StlHashMap<Opnd*, Opnd*> *copyMap;
+    StlSet<Opnd*> *tempSet;
 }; // ~PeepHoleOpt
 
 void PeepHoleOpt::runImpl(void)
 {
+    MemoryManager mm("handleBasicBlock");
+    copyMap = new(mm) StlHashMap<Opnd*, Opnd*>(mm);
+    tempSet = new(mm) StlSet<Opnd*>(mm);
     setIRManager(irManager);
     irManager->calculateOpndStatistics();
     m_bHadAnyChange = false;
@@ -144,6 +151,8 @@
 
 PeepHoleOpt::Changed PeepHoleOpt::handleBasicBlock(Node* node)
 {
+    copyMap->clear();
+    tempSet->clear();
     Inst* inst = (Inst*)node->getFirstInst();
     Changed changedInBB = Changed_Nothing;
     while (inst != NULL) {
@@ -177,11 +186,100 @@
     return changedInBB;
 }
 
+static bool isTypeConversionAllowed(Opnd* fromOpnd, Opnd* toOpnd) {
+    Type * fromType = fromOpnd->getType();
+    Type * toType = toOpnd->getType();
+    bool fromIsGCType = fromType->isObject() || fromType->isManagedPtr();
+    bool toIsGCType = toType->isObject() || toType->isManagedPtr();
+    return fromIsGCType == toIsGCType;
+}
 
 PeepHoleOpt::Changed PeepHoleOpt::handleInst(Inst* inst)
 {
     PeepHoleOpt::Changed temp;
 
+    // Local propagation
+    Inst::Opnds opnds(inst, Inst::OpndRole_All);
+    
+    for (Inst::Opnds::iterator it=opnds.begin();it != opnds.end();it = opnds.next(it)) {
+        Opnd * opnd=inst->getOpnd(it);
+        U_32 roles=inst->getOpndRoles(it);
+                
+        if (roles & Inst::OpndRole_Use) {
+            if ((roles & Inst::OpndRole_All & Inst::OpndRole_FromEncoder) 
+                && (roles & Inst::OpndRole_All & Inst::OpndRole_ForIterator)
+                && (roles & Inst::OpndRole_Changeable) && ((roles & Inst::OpndRole_Def) == 0)
+                && copyMap->has(opnd)) {
+                if (opnd->getType()->isUnmanagedPtr() && (*copyMap)[opnd]->getType()->isInteger())
+                    (*copyMap)[opnd]->setType(opnd->getType());
+                inst->setOpnd(it, (*copyMap)[opnd]);
+            }
+        }
+    }
+
+    for (Inst::Opnds::iterator it = opnds.begin();it != opnds.end();it = opnds.next(it)) {
+        Opnd * opnd=inst->getOpnd(it);
+        U_32 roles=inst->getOpndRoles(it);
+
+        if (roles & Inst::OpndRole_Def) {
+            if (copyMap->has(opnd)) {
+            	if (Log::isEnabled()) Log::out()<<"copy relation DELETED: " << opnd->getFirstId() << "<=" << (*copyMap)[opnd]->getFirstId() <<std::endl;
+                copyMap->erase(opnd);
+            }
+
+            tempSet->clear();
+            for(StlHashMap<Opnd*, Opnd*>::iterator iter=copyMap->begin();
+                iter!=copyMap->end();++iter)
+                if (iter->second == opnd) {
+                    if (Log::isEnabled()) Log::out()<<"copy relation DELETED: " << iter->first->getFirstId() << "<=" << iter->second->getFirstId() <<std::endl;
+                    tempSet->insert(iter->first);
+                }
+            for(StlSet<Opnd*>::iterator iter=tempSet->begin();
+                iter!=tempSet->end();++iter)
+                copyMap->erase(*iter);
+        }
+    }
+
+    if (inst->getMnemonic() == Mnemonic_MOV) {
+        Inst::Opnds opnds(inst, Inst::OpndRole_All);
+        Opnd * dst = NULL;
+        Opnd * src = NULL;
+        U_32 counterDef = 0;
+        U_32 counterUse = 0;
+
+        for (Inst::Opnds::iterator it=opnds.begin();it!=opnds.end();it=opnds.next(it)) {
+            Opnd * opnd = inst->getOpnd(it);
+            U_32 roles = inst->getOpndRoles(it);
+                    
+            if (roles & Inst::OpndRole_Def) {
+                counterDef++;
+                dst = opnd;
+            } else if (roles & Inst::OpndRole_Use) {
+                counterUse++;
+                src = opnd;
+            }
+        }
+
+        if ((counterDef == 1) && (counterUse == 1) && (!dst->hasAssignedPhysicalLocation())) {
+            bool kindsAreOk = true;
+            if(src->canBePlacedIn(OpndKind_FPReg) || dst->canBePlacedIn(OpndKind_FPReg)) {
+                Constraint srcConstr = src->getConstraint(Opnd::ConstraintKind_Calculated);
+                Constraint dstConstr = dst->getConstraint(Opnd::ConstraintKind_Calculated);
+                kindsAreOk = ! (srcConstr&dstConstr).isNull();
+            }
+            bool typeConvOk = src->getSize() == dst->getSize() && isTypeConversionAllowed(src, dst);
+            if (typeConvOk && kindsAreOk && ! src->isPlacedIn(OpndKind_Reg)) {
+                if (copyMap->has(src)) {
+                    (*copyMap)[dst] = (*copyMap)[src];
+                    if (Log::isEnabled()) Log::out()<<"copy relation INSERTED: " << dst->getFirstId() << "<=" << (*copyMap)[src]->getFirstId() <<std::endl;
+                } else {
+                    (*copyMap)[dst] = src;
+                    if (Log::isEnabled()) Log::out()<<"copy relation INSERTED: " << dst->getFirstId() << "<=" << src->getFirstId() <<std::endl;
+                }
+            }
+        }
+    }
+            
     if (inst->hasKind(Inst::Kind_PseudoInst) && inst->getKind() != Inst::Kind_CopyPseudoInst) {
         return Changed_Nothing;
     }
@@ -632,19 +730,32 @@
 
 
 PeepHoleOpt::Changed PeepHoleOpt::handleInst_MUL(Inst* inst) {
-    assert(inst->getMnemonic()==Mnemonic_IMUL || inst->getMnemonic()==Mnemonic_MUL);
+    assert((inst->getMnemonic() == Mnemonic_IMUL) || (inst->getMnemonic() == Mnemonic_MUL));
+    
     if (inst->getForm() == Inst::Form_Native) {
         return Changed_Nothing;
     }
+    
     Inst::Opnds defs(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
-    Opnd* dst = inst->getOpnd(defs.begin());
-    if (defs.next(defs.begin())!=defs.end()) {
+    Opnd* dst1 = inst->getOpnd(defs.begin());
+    Opnd* dst2 = NULL;
+    if ((inst->getMnemonic() == Mnemonic_IMUL) && (defs.next(defs.begin()) != defs.end())){
         return Changed_Nothing;
     }
+    else { //inst->getMnemonic() == Mnemonic_MUL
+        dst2 = inst->getOpnd(defs.next(defs.begin()));
+        if (defs.next(defs.next(defs.begin()))!=defs.end())
+            return Changed_Nothing;
+    }
+
     Inst::Opnds uses(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
     Opnd* src1= inst->getOpnd(uses.begin());
     Opnd* src2= inst->getOpnd(uses.next(uses.begin()));
-    assert(src1!=NULL && src2!=NULL && dst!=NULL);
+    if (inst->getMnemonic() == Mnemonic_IMUL)
+        assert(src1!=NULL && src2!=NULL && dst1!=NULL);
+    else //inst->getMnemonic() == Mnemonic_MUL
+        assert(src1!=NULL && src2!=NULL && dst1!=NULL && dst2!=NULL);
+
     if (isImm(src1)) {
         Opnd* tmp = src1; src1 = src2; src2 = tmp;
     }
@@ -652,33 +763,49 @@
         int immVal = (int)src2->getImmValue();
         if (immVal == 0) {
             if (Log::isEnabled()) Log::out()<<"I"<<inst->getId()<<" -> MUL with 0"<<std::endl;
-            irManager->newCopyPseudoInst(Mnemonic_MOV, dst, src2)->insertAfter(inst);
+            if (inst->getMnemonic() == Mnemonic_IMUL) {
+                irManager->newCopyPseudoInst(Mnemonic_MOV, dst1, src2)->insertAfter(inst);
+            } else { //inst->getMnemonic() == Mnemonic_MUL
+                irManager->newCopyPseudoInst(Mnemonic_MOV, dst1, src2)->insertAfter(inst);
+                irManager->newCopyPseudoInst(Mnemonic_MOV, dst2, src2)->insertAfter(inst);
+            }
             inst->unlink();
             return Changed_Inst;
         } else if (immVal == 1) {
             if (Log::isEnabled()) Log::out()<<"I"<<inst->getId()<<" -> MUL with 1"<<std::endl;
-            irManager->newCopyPseudoInst(Mnemonic_MOV, dst, src1)->insertAfter(inst);
+            if (inst->getMnemonic() == Mnemonic_IMUL) {
+                irManager->newCopyPseudoInst(Mnemonic_MOV, dst1, src1)->insertAfter(inst);
+            } else { //inst->getMnemonic() == Mnemonic_MUL
+                Opnd* zero = irManager->newImmOpnd(dst1->getType(), 0);
+                irManager->newCopyPseudoInst(Mnemonic_MOV, dst1, zero)->insertAfter(inst);
+                irManager->newCopyPseudoInst(Mnemonic_MOV, dst2, src1)->insertAfter(inst);
+            }
             inst->unlink();
             return Changed_Inst;
         } else if (immVal == 2) {
-            if (Log::isEnabled()) Log::out()<<"I"<<inst->getId()<<" -> MUL with 2"<<std::endl;
-            irManager->newInstEx(Mnemonic_ADD, 1, dst, src1, src1)->insertAfter(inst);
-            inst->unlink();
-            return Changed_Inst;
-        } else {
-            int minBit=getMinBit(immVal);   
-            int maxBit=getMaxBit(immVal);
-            if (minBit == maxBit) {
-                assert(minBit>=2);
-                if (Log::isEnabled()) Log::out()<<"I"<<inst->getId()<<" -> MUL with 2^"<<minBit<<std::endl;
-                Type* int32Type = irManager->getTypeManager().getUInt32Type();
-                irManager->newInstEx(Mnemonic_SHL, 1, dst, src1, irManager->newImmOpnd(int32Type, minBit))->insertAfter(inst);
+            if (inst->getMnemonic() == Mnemonic_IMUL) {
+                if (Log::isEnabled()) Log::out()<<"I"<<inst->getId()<<" -> MUL with 2"<<std::endl;
+                irManager->newInstEx(Mnemonic_ADD, 1, dst1, src1, src1)->insertAfter(inst);
                 inst->unlink();
                 return Changed_Inst;
             }
-        }
-    }
-    return Changed_Nothing;
+        } else {
+            if (inst->getMnemonic() == Mnemonic_IMUL) {
+                int minBit=getMinBit(immVal);   
+                int maxBit=getMaxBit(immVal);
+                if (minBit == maxBit) {
+                     assert(minBit>=2);
+                     if (Log::isEnabled()) Log::out()<<"I"<<inst->getId()<<" -> MUL with 2^"<<minBit<<std::endl;
+                     Type* immType = irManager->getTypeManager().getUInt8Type();
+                     irManager->newCopyPseudoInst(Mnemonic_MOV, dst1, src1)->insertBefore(inst);
+                     irManager->newInst(Mnemonic_SHL, dst1, irManager->newImmOpnd(immType, minBit))->insertBefore(inst);
+                     inst->unlink();
+                     return Changed_Inst;
+                 }
+             }
+          }
+      }
+      return Changed_Nothing;
 }
 
 PeepHoleOpt::Changed PeepHoleOpt::handleInst_ALU(Inst* inst)
@@ -734,6 +861,44 @@
                 return Changed_Inst;
             }
         }
+    } else if (mnemonic == Mnemonic_ADD) {
+        /* Change "dst=src+0" to "MOV dst, src" if there is another ADD inst followed in the same BB. */
+        Inst::Opnds defs(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
+        Opnd* dst = inst->getOpnd(defs.begin());
+        Inst::Opnds uses(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
+        Opnd* src1= inst->getOpnd(uses.begin());
+        Opnd* src2= inst->getOpnd(uses.next(uses.begin()));
+
+        bool src1IsZero = false;
+        bool src2IsZero = false;
+        if (src1->isPlacedIn(OpndKind_Imm) && (src1->getImmValue() == 0))
+            src1IsZero = true;
+        if (src2->isPlacedIn(OpndKind_Imm) && (src2->getImmValue() == 0))
+            src2IsZero = true;
+
+        bool anotherADD = false;
+        Inst *iter = inst->getNextInst();
+        while (iter != NULL) {
+            if (iter->getMnemonic() == Mnemonic_ADC)
+                break;
+            if (iter->getMnemonic() == Mnemonic_ADD) {
+                anotherADD = true;
+                break;
+            }
+            iter = iter->getNextInst();;
+        }
+
+        if (anotherADD) {
+            if (src1IsZero) {
+                irManager->newCopyPseudoInst(Mnemonic_MOV, dst, src2)->insertAfter(inst);
+                inst->unlink();
+                return Changed_Inst;
+            } else if (src2IsZero) {
+                irManager->newCopyPseudoInst(Mnemonic_MOV, dst, src1)->insertAfter(inst);
+                inst->unlink();
+                return Changed_Inst;
+            }
+        }
     }
     return Changed_Nothing;
 }