in vm/jitrino/src/optimizer/abcd/classic_abcd.cpp [261:370]
void BuildInequalityGraphWalker::applyToInst(Inst* inst)
{
assert(inst);
Type::Tag inst_type = inst->getType();
if ( !Type::isInteger(inst_type) && inst_type != Type::Boolean &&
inst_type != Type::Char ) {
// note: some operations of unsupported type can produce operands of
// supported (int) types, for example,
// inst-compare-two-unmanaged-pointers, we need these operands as
// unconstrained in the graph
Opnd* dst = inst->getDst();
if ( dst && !dst->isNull() &&
(dst->getType()->isInteger() ||
dst->getType()->isBoolean() ) ) {
addOldOrCreateOpnd(dst)->setUnconstrained(true);
}
return;
}
if ( inst->isUnconditionalBranch() || inst->isConditionalBranch() ||
inst->isReturn() ) {
return;
}
IOpndProxy* proxy_dst;
Opcode opc = inst->getOpcode();
switch ( opc ) {
case Op_Phi:
{
proxy_dst = addOldOrCreateOpnd(inst->getDst());
addAllSrcOpndsForPhi(inst);
}
break;
case Op_Copy:
case Op_LdVar:
case Op_StVar:
{
proxy_dst = addOldOrCreateOpnd(inst->getDst());
addDistance(proxy_dst, findProxy(inst->getSrc(0)), 0,
false /* negate */);
}
break;
case Op_Conv:
{
// adding conversions int<->long as zero-length edges to the
// inequality graph. This is a small enhancement to the paper's
// algorithm, but it is safe. The proof is as follows: if we ensure
// that a value of type 'long' is in good bounds for array access,
// then is is proven to be not outside bounds for type 'int'
Opnd* src = inst->getSrc(0);
Opnd* dst = inst->getDst();
if ( isIntOrLong(src->getType()) &&
isIntOrLong(dst->getType()) ) {
proxy_dst = addOldOrCreateOpnd(inst->getDst());
addDistance(proxy_dst, findProxy(inst->getSrc(0)), 0,
false /* negate */);
}else{
addOldOrCreateOpnd(inst->getDst())->setUnconstrained(true);
}
}
break;
case Op_Add:
{
proxy_dst = addOldOrCreateOpnd(inst->getDst());
Opnd* src0 = inst->getSrc(0);
Opnd* src1 = inst->getSrc(1);
addEdgeIfConstOpnd(proxy_dst, src0, src1, false /* negate */)
|| addEdgeIfConstOpnd(proxy_dst, src1, src0, false /* negate */);
}
break;
case Op_Sub:
{
proxy_dst = addOldOrCreateOpnd(inst->getDst());
addEdgeIfConstOpnd(proxy_dst, inst->getSrc(1), inst->getSrc(0),
true /* negate */ );
}
break;
case Op_TauPi:
{
proxy_dst = addOldOrCreateOpnd(inst->getDst());
IOpndProxy* src0 = findProxy(inst->getSrc(0));
addDistance(proxy_dst, src0, 0, false /* negate */);
_map_opnd_to_pi_inst[src0] = inst->asTauPiInst();
if ( Log::isEnabled() ) {
Log::out() << "mapping (src->pi inst): src: ";
src0->printName(Log::out());
Log::out() << " inst: ";
inst->print(Log::out());
Log::out() << std::endl;
}
}
break;
case Op_TauArrayLen:
case Op_LdConstant: case Op_LdStatic: case Op_TauLdInd:
case Op_TauLdField: case Op_TauLdElem:
case Op_DirectCall: case Op_TauVirtualCall: case Op_IndirectCall:
case Op_IndirectMemoryCall: case Op_JitHelperCall: case Op_VMHelperCall:
case Op_DefArg:
// All these load instructions may potentially produce an operand
// that would be a parameter to a newarray, hence we need it to be
// reachable with inequality edges. Need to keep it constrained.
addOldOrCreateOpnd(inst->getDst());
break;
case Op_TauStInd: case Op_TauStElem: case Op_TauStField:
case Op_TauStRef: case Op_TauStStatic:
break;
default:
addOldOrCreateOpnd(inst->getDst())->setUnconstrained(true);
break;
}
}