in vm/jitrino/src/codegenerator/ia32/Ia32PeepHole.cpp [906:1141]
PeepHoleOpt::Changed PeepHoleOpt::handleInst_SETcc(Inst* inst)
{
if (((BasicBlock*)inst->getNode())->getLayoutSucc() == NULL)
{
Mnemonic mn = inst->getMnemonic();
Inst* prev = inst->getPrevInst();
Inst *next = inst->getNextInst();
Node *currNode = inst->getNode();
bool methodMarkerOccur = false;
MethodMarkerPseudoInst* methodMarker = NULL;
// ignoring instructions that have no effect and saving method markers to correct them during optimizations
while (next == NULL || next->getKind() == Inst::Kind_MethodEndPseudoInst || next->getMnemonic() == Mnemonic_JMP)
{
if (next == NULL)
{
currNode = currNode->getOutEdge(Edge::Kind_Unconditional)->getTargetNode();
if (currNode->getKind() == Node::Kind_Exit)
return Changed_Nothing;
next = (Inst*) currNode->getFirstInst();
}
else
{
if (next->getKind() == Inst::Kind_MethodEndPseudoInst)
{
//max 1 saved method marker
if (methodMarkerOccur)
{
return Changed_Nothing;
}
methodMarker = (MethodMarkerPseudoInst*)next;
methodMarkerOccur = true;
}
next = next->getNextInst();
}
}
Inst *next2 = next->getNextInst();
bool step1 = true;
currNode = inst->getNode();
while (currNode != next->getNode())
{
currNode = currNode->getOutEdge(Edge::Kind_Unconditional)->getTargetNode();
if (currNode->getInDegree()!=1)
{
step1 = false;
break;
}
}
// step1:
// ------------------------------------------
// MOV opnd, 0 MOV opnd2, 0
// SETcc opnd -> SETcc opnd2
// MOV opnd2, opnd
// ------------------------------------------
// nb: applicable if opnd will not be used further
if (step1 && prev!= NULL && prev->getMnemonic() == Mnemonic_MOV &&
next!= NULL && next->getMnemonic() == Mnemonic_MOV)
{
Opnd *prevopnd1, *prevopnd2, *nextopnd1, *nextopnd2, *setopnd;
if (prev->getKind() == Inst::Kind_CopyPseudoInst)
{
prevopnd1 = prev->getOpnd(0);
prevopnd2 = prev->getOpnd(1);
}
else
{
Inst::Opnds prevuses(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
Inst::Opnds prevdefs(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
prevopnd1 = prev->getOpnd(prevdefs.begin());
prevopnd2 = prev->getOpnd(prevuses.begin());
}
if (next->getKind() == Inst::Kind_CopyPseudoInst)
{
nextopnd1 = next->getOpnd(0);
nextopnd2 = next->getOpnd(1);
}
else
{
Inst::Opnds nextuses(next, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
Inst::Opnds nextdefs(next, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
nextopnd1 = next->getOpnd(nextdefs.begin());
nextopnd2 = next->getOpnd(nextuses.begin());
}
Inst::Opnds setdefs(inst, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
setopnd = inst->getOpnd(setdefs.begin());
if (isReg(nextopnd1) &&
prevopnd1->getId() == setopnd->getId() &&
setopnd->getId() == nextopnd2->getId() &&
isImm(prevopnd2) && prevopnd2->getImmValue() == 0
)
{
BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount());
irManager->updateLivenessInfo();
irManager->getLiveAtExit(next->getNode(), ls);
for (Inst* i = (Inst*)next->getNode()->getLastInst(); i!=next; i = i->getPrevInst()) {
irManager->updateLiveness(i, ls);
}
bool opndNotUsed = !ls.getBit(setopnd->getId());
if (opndNotUsed)
{
if (nextopnd1->getRegName() != RegName_Null &&
Constraint::getAliasRegName(nextopnd1->getRegName(), OpndSize_8) == RegName_Null)
{
nextopnd1->assignRegName(setopnd->getRegName());
}
irManager->newInst(Mnemonic_MOV, nextopnd1, prevopnd2)->insertBefore(inst);
irManager->newInst(mn, nextopnd1)->insertBefore(inst);
prev->unlink();
inst->unlink();
next->unlink();
return Changed_Node;
}
}
}
// step2:
// --------------------------------------------------------------
// MOV opnd, 0 Jcc smwh Jcc smwh
// SETcc opnd -> BB1: v BB1:
// CMP opnd, 0 ...
// Jcc smwh CMP opnd, 0
// BB1: Jcc smwh
// --------------------------------------------------------------
// nb: applicable if opnd will not be used further
// nb: conditions of new jumps are calculated from conditions of old jump and set instructions
if (prev!= NULL && prev->getMnemonic() == Mnemonic_MOV &&
next!= NULL && (next->getMnemonic() == Mnemonic_CMP || next->getMnemonic() == Mnemonic_TEST) &&
next2!= NULL && (next2->getMnemonic() == Mnemonic_JG || next2->getMnemonic() == Mnemonic_JE || next2->getMnemonic() == Mnemonic_JNE) )
{
Opnd* movopnd1;
Opnd* movopnd2;
if (prev->getKind() == Inst::Kind_CopyPseudoInst)
{
movopnd1 = prev->getOpnd(0);
movopnd2 = prev->getOpnd(1);
}
else
{
Inst::Opnds movuses(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
Inst::Opnds movdefs(prev, Inst::OpndRole_Explicit|Inst::OpndRole_Def);
movopnd1 = prev->getOpnd(movdefs.begin());
movopnd2 = prev->getOpnd(movuses.begin());
}
Inst::Opnds cmpuses(next, Inst::OpndRole_Explicit|Inst::OpndRole_Use);
Opnd* cmpopnd1 = next->getOpnd(cmpuses.begin());
Opnd* cmpopnd2 = next->getOpnd(cmpuses.next(cmpuses.begin()));
if (
isImm(movopnd2) && movopnd2->getImmValue() == 0 &&
movopnd1->getId() == cmpopnd1->getId() &&
//case CMP:
(next->getMnemonic() != Mnemonic_CMP || (isImm(cmpopnd2) && cmpopnd2->getImmValue() == 0)) &&
//case TEST:
(next->getMnemonic() != Mnemonic_TEST || cmpopnd1->getId() == cmpopnd2->getId())
)
{
BitSet ls(irManager->getMemoryManager(), irManager->getOpndCount());
irManager->updateLivenessInfo();
irManager->getLiveAtExit(next2->getNode(), ls);
bool opndNotUsed = !ls.getBit(movopnd1->getId());
if (opndNotUsed)
{
BranchInst* br = (BranchInst*) next2;
Mnemonic newjumpmn = Mnemonic_JZ;
if (next2->getMnemonic() == Mnemonic_JE)
{
switch (mn)
{
case Mnemonic_SETG:
newjumpmn = Mnemonic_JLE; break;
case Mnemonic_SETE:
newjumpmn = Mnemonic_JNE; break;
case Mnemonic_SETL:
newjumpmn = Mnemonic_JGE; break;
case Mnemonic_SETNE:
newjumpmn = Mnemonic_JE; break;
default:
assert(0); break;
}
}
else
{
switch (mn)
{
case Mnemonic_SETG:
newjumpmn = Mnemonic_JG; break;
case Mnemonic_SETE:
newjumpmn = Mnemonic_JE; break;
case Mnemonic_SETL:
newjumpmn = Mnemonic_JL; break;
case Mnemonic_SETNE:
newjumpmn = Mnemonic_JNE; break;
default:
assert(0); break;
}
}
if (inst->getNode()->getId() != next->getNode()->getId())
{
ControlFlowGraph* cfg = irManager->getFlowGraph();
cfg->removeEdge(inst->getNode()->getOutEdge(Edge::Kind_Unconditional));
double trueEdgeProb = next2->getNode()->getOutEdge(Edge::Kind_True)->getEdgeProb();
double falseEdgeProb = next2->getNode()->getOutEdge(Edge::Kind_False)->getEdgeProb();
cfg->addEdge(inst->getNode(), br->getTrueTarget(), trueEdgeProb);
cfg->addEdge(inst->getNode(), br->getFalseTarget(), falseEdgeProb);
irManager->newBranchInst(newjumpmn, br->getTrueTarget(), br->getFalseTarget())->insertAfter(inst);
if (methodMarkerOccur)
{
inst->getNode()->appendInst(irManager->newMethodEndPseudoInst(methodMarker->getMethodDesc()));
}
prev->unlink();
inst->unlink();
cfg->purgeUnreachableNodes();
}
else
{
irManager->newBranchInst(newjumpmn, br->getTrueTarget(), br->getFalseTarget())->insertAfter(next2);
prev->unlink();
inst->unlink();
next->unlink();
next2->unlink();
}
return Changed_Node;
}// endif opndNotUsed
}
}
}
return Changed_Nothing;
}