in vm/jitrino/src/optimizer/abcd/insertpi.cpp [410:689]
void InsertPi::insertPiForComparison(Node* block,
ComparisonModifier mod,
const PiCondition &bounds,
Opnd* op,
bool swap_operands,
bool negate_comparison)
{
if (Log::isEnabled()) {
Log::out() << "insertPiForComparison(..., ";
Log::out() << printableComparison(mod);
Log::out() << ", ";
bounds.print(Log::out());
Log::out() << ", ";
op->print(Log::out());
Log::out() << ", ";
Log::out() << (swap_operands ? "true" : "false");
Log::out() << ", ";
Log::out() << (negate_comparison ? "true" : "false");
Log::out() << ")" << std::endl;
// Print last inst from all prev blocks.
Edges::const_iterator it = block->getInEdges().begin(),
end = block->getInEdges().end();
for(; it != end; ++it) {
Edge* edge = (*it);
Log::out() << "pred inst---> ";
((Inst*)edge->getSourceNode()->getLastInst())->print(Log::out());
Log::out() << std::endl;
}
}
PiCondition bounds0 = bounds;
// add a Pi node for immediate value.
if (negate_comparison) {
mod = negateComparison(mod);
swap_operands = !swap_operands;
if (Log::isEnabled()) {
Log::out() << "insertPiForComparison: negating comparison to " ;
Log::out() << printableComparison(mod);
Log::out() << std::endl;
}
}
switch (mod) {
case Cmp_EQ:
if (!negate_comparison)
insertPiForOpndAndAliases(block, op, bounds0, NULL);
else {
if (Log::isEnabled()) {
Log::out() << "insertPiForComparison: cannot represent ! Cmp_EQ" << std::endl;
}
}
// we can't represent the other case
break;
case Cmp_NE_Un:
if (negate_comparison)
insertPiForOpndAndAliases(block, op, bounds0, NULL);
else {
if (Log::isEnabled()) {
Log::out() << "insertPiForComparison: cannot represent Cmp_NE_Un" << std::endl;
}
}
// we can't represent the other case
break;
case Cmp_GT_Un:
if (swap_operands) { // op > bounds, only a lower bound on op
Type::Tag optag = op->getType()->tag;
if (!Type::isUnsignedInteger(optag)) {
// 1 is a lower bound on int op
PiCondition oneBounds(PiBound(optag, (int64)1),
PiBound(optag, (int64)1));
PiCondition oneLowerBound(oneBounds.only_lower_bound());
insertPiForOpndAndAliases(block, op, oneLowerBound, NULL);
} else {
// we can be more precise for an unsigned op
bounds0 = bounds0.cast(unsignType(bounds0.getType()));
PiCondition bounds1a(bounds0.only_lower_bound());
PiCondition bounds1(bounds1a.add((int64)1));
if (! bounds1.getLb().isUnknown())
insertPiForOpndAndAliases(block, op, bounds1, NULL);
else {
if (Log::isEnabled()) {
Log::out() << "insertPiForComparison(1): bounds1 LB is Unknown;\n\tbounds is ";
bounds.print(Log::out());
Log::out() << "\n\tbounds0 is ";
bounds0.print(Log::out());
Log::out() << "\n\tbounds1a is ";
bounds1a.print(Log::out());
Log::out() << "\n\tbounds1 is ";
bounds1.print(Log::out());
Log::out() << std::endl;
}
}
}
} else { // bounds > op, only an upper bound on op
Type::Tag optag = op->getType()->tag;
if (Type::isUnsignedInteger(optag)) {
// for an unsigned upper bound, we're ok
bounds0 = bounds0.cast(unsignType(bounds0.getType()));
PiCondition bounds1(bounds0.only_upper_bound().add((int64)-1));
if (! bounds1.getUb().isUnknown())
insertPiForOpndAndAliases(block, op, bounds1, NULL);
else {
if (Log::isEnabled()) {
Log::out() << "insertPiForComparison(2): bounds1 LB is Unknown;\n\tbounds is ";
bounds.print(Log::out());
Log::out() << "\n\tbounds0 is ";
bounds0.print(Log::out());
Log::out() << "\n\tbounds1 is ";
bounds1.print(Log::out());
Log::out() << std::endl;
}
}
} else {
// otherwise, we know nothing unless bound is a small constant
PiCondition bounds1(bounds0.only_upper_bound().add((int64)-1));
if (bounds0.getUb().isConstant()) {
int64 ubConst = bounds1.getUb().getConst();
if (((optag == Type::Int32) &&
((ubConst&0xffffffff) <= 0x7ffffff) &&
((ubConst&0xffffffff) >= 0)) ||
((optag == Type::Int64) &&
((ubConst <= 0x7ffffff) &&
(ubConst >= 0)))) {
insertPiForOpndAndAliases(block, op, bounds1, NULL);
} else {
if (Log::isEnabled()) {
Log::out() << "insertPiForComparison(2): bounds1 LB is Unknown;\n\tbounds is ";
bounds.print(Log::out());
Log::out() << "\n\tbounds0 is ";
bounds0.print(Log::out());
Log::out() << "\n\tbounds1 is ";
bounds1.print(Log::out());
Log::out() << std::endl;
}
}
}
}
}
break;
case Cmp_GT:
if (swap_operands) { // op > bounds, only a lower bound on op
PiCondition bounds1a(bounds0.only_lower_bound());
PiCondition bounds1(bounds1a.add((int64)1));
if (! bounds1.getLb().isUnknown())
insertPiForOpndAndAliases(block, op, bounds1, NULL);
else {
if (Log::isEnabled()) {
Log::out() << "insertPiForComparison(1): bounds1 LB is Unknown;\n\tbounds is ";
bounds.print(Log::out());
Log::out() << "\n\tbounds0 is ";
bounds0.print(Log::out());
Log::out() << "\n\tbounds1a is ";
bounds1a.print(Log::out());
Log::out() << "\n\tbounds1 is ";
bounds1.print(Log::out());
Log::out() << std::endl;
}
}
} else { // bounds > op, only an upper bound on op
PiCondition bounds1(bounds0.only_upper_bound().add((int64)-1));
if (! bounds1.getUb().isUnknown())
insertPiForOpndAndAliases(block, op, bounds1, NULL);
else {
if (Log::isEnabled()) {
Log::out() << "insertPiForComparison(2): bounds1 LB is Unknown;\n\tbounds is ";
bounds.print(Log::out());
Log::out() << "\n\tbounds0 is ";
bounds0.print(Log::out());
Log::out() << "\n\tbounds1 is ";
bounds1.print(Log::out());
Log::out() << std::endl;
}
}
}
break;
case Cmp_GTE_Un:
if (swap_operands) { // op >= bounds, only lower bound on op
Type::Tag optag = op->getType()->tag;
if (!Type::isUnsignedInteger(optag)) {
// 0 is a lower bound on an int op
PiCondition zeroBounds(PiBound(optag, (int64)0),
PiBound(optag, (int64)0));
PiCondition zeroLowerBound(zeroBounds.only_lower_bound());
insertPiForOpndAndAliases(block, op, zeroLowerBound, NULL);
} else {
// we can be more precise for an unsigned op lb
bounds0 = bounds0.cast(unsignType(bounds0.getType()));
if (! bounds0.getLb().isUnknown()) {
insertPiForOpndAndAliases(block, op,
bounds0.only_lower_bound(), NULL);
} else {
if (Log::isEnabled()) {
Log::out() << "insertPiForComparison(3): bounds0 LB is Unknown;\n\tbounds is ";
bounds.print(Log::out());
Log::out() << "\n\tbounds0 is ";
bounds0.print(Log::out());
Log::out() << std::endl;
}
}
}
} else { // bounds >= op, only upper bound on op
Type::Tag optag = op->getType()->tag;
if (Type::isUnsignedInteger(optag)) {
// unsigned ub on unsigned op
bounds0 = bounds0.cast(unsignType(bounds0.getType()));
if (! bounds0.getUb().isUnknown())
insertPiForOpndAndAliases(block, op,
bounds0.only_upper_bound(), NULL);
else {
if (Log::isEnabled()) {
Log::out() << "insertPiForComparison(4): bounds0 UB is Unknown;\n\tbounds is ";
bounds.print(Log::out());
Log::out() << "\n\tbounds0 is ";
bounds0.print(Log::out());
Log::out() << std::endl;
}
}
} else {
// otherwise, we know nothing unless bound is a small constant
if (bounds0.getUb().isConstant()) {
int64 ubConst = bounds0.getUb().getConst();
if (((optag == Type::Int32) &&
((ubConst&0xffffffff) <= 0x7ffffff) &&
((ubConst&0xffffffff) >= 0)) ||
((optag == Type::Int64) &&
((ubConst <= 0x7ffffff) &&
(ubConst >= 0)))) {
insertPiForOpndAndAliases(block, op, bounds0, NULL);
} else {
if (Log::isEnabled()) {
Log::out() << "insertPiForComparison(2): bounds0 LB is Unknown;\n\tbounds is ";
bounds.print(Log::out());
Log::out() << "\n\tbounds0 is ";
bounds0.print(Log::out());
Log::out() << std::endl;
}
}
}
}
}
break;
case Cmp_GTE:
if (swap_operands) { // op >= bounds, only lower bound on op
if (! bounds0.getLb().isUnknown()) {
insertPiForOpndAndAliases(block, op,
bounds0.only_lower_bound(), NULL);
} else {
if (Log::isEnabled()) {
Log::out() << "insertPiForComparison(3): bounds0 LB is Unknown;\n\tbounds is ";
bounds.print(Log::out());
Log::out() << "\n\tbounds0 is ";
bounds0.print(Log::out());
Log::out() << std::endl;
}
}
} else { // bounds >= op, only upper bound on op
if (! bounds0.getUb().isUnknown())
insertPiForOpndAndAliases(block, op,
bounds0.only_upper_bound(), NULL);
else {
if (Log::isEnabled()) {
Log::out() << "insertPiForComparison(4): bounds0 UB is Unknown;\n\tbounds is ";
bounds.print(Log::out());
Log::out() << "\n\tbounds0 is ";
bounds0.print(Log::out());
Log::out() << std::endl;
}
}
}
break;
case Cmp_Zero:
case Cmp_NonZero:
case Cmp_Mask:
assert(0);
break;
default:
assert(false);
break;
}
}