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;
}