Reorganize code for range analysis and suppress unnecessary debug printing of unknown ranges.

Review URL: http://codereview.chromium.org/6611020

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7060 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent eee3c519
......@@ -120,6 +120,44 @@ void Range::AddConstant(int32_t value) {
}
void Range::Intersect(Range* other) {
upper_ = Min(upper_, other->upper_);
lower_ = Max(lower_, other->lower_);
bool b = CanBeMinusZero() && other->CanBeMinusZero();
set_can_be_minus_zero(b);
}
void Range::Union(Range* other) {
upper_ = Max(upper_, other->upper_);
lower_ = Min(lower_, other->lower_);
bool b = CanBeMinusZero() || other->CanBeMinusZero();
set_can_be_minus_zero(b);
}
void Range::Sar(int32_t value) {
int32_t bits = value & 0x1F;
lower_ = lower_ >> bits;
upper_ = upper_ >> bits;
set_can_be_minus_zero(false);
}
void Range::Shl(int32_t value) {
int32_t bits = value & 0x1F;
int old_lower = lower_;
int old_upper = upper_;
lower_ = lower_ << bits;
upper_ = upper_ << bits;
if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) {
upper_ = kMaxInt;
lower_ = kMinInt;
}
set_can_be_minus_zero(false);
}
bool Range::AddAndCheckOverflow(Range* other) {
bool may_overflow = false;
lower_ = AddWithoutOverflow(lower_, other->lower(), &may_overflow);
......@@ -415,7 +453,9 @@ void HInstruction::PrintTo(StringStream* stream) {
stream->Add(" ");
PrintDataTo(stream);
if (range() != NULL) {
if (range() != NULL &&
!range()->IsMostGeneric() &&
!range()->CanBeMinusZero()) {
stream->Add(" range[%d,%d,m0=%d]",
range()->lower(),
range()->upper(),
......@@ -739,6 +779,8 @@ Range* HValue::InferRange() {
} else if (representation().IsNone()) {
return NULL;
} else {
// Untagged integer32 cannot be -0 and we don't compute ranges for
// untagged doubles.
return new Range();
}
}
......@@ -750,7 +792,7 @@ Range* HConstant::InferRange() {
result->set_can_be_minus_zero(false);
return result;
}
return HInstruction::InferRange();
return HValue::InferRange();
}
......@@ -784,7 +826,7 @@ Range* HAdd::InferRange() {
res->set_can_be_minus_zero(m0);
return res;
} else {
return HArithmeticBinaryOperation::InferRange();
return HValue::InferRange();
}
}
......@@ -800,7 +842,7 @@ Range* HSub::InferRange() {
res->set_can_be_minus_zero(a->CanBeMinusZero() && b->CanBeZero());
return res;
} else {
return HArithmeticBinaryOperation::InferRange();
return HValue::InferRange();
}
}
......@@ -818,7 +860,7 @@ Range* HMul::InferRange() {
res->set_can_be_minus_zero(m0);
return res;
} else {
return HArithmeticBinaryOperation::InferRange();
return HValue::InferRange();
}
}
......@@ -843,7 +885,7 @@ Range* HDiv::InferRange() {
}
return result;
} else {
return HArithmeticBinaryOperation::InferRange();
return HValue::InferRange();
}
}
......@@ -860,7 +902,7 @@ Range* HMod::InferRange() {
}
return result;
} else {
return HArithmeticBinaryOperation::InferRange();
return HValue::InferRange();
}
}
......@@ -1021,34 +1063,30 @@ void HBinaryOperation::PrintDataTo(StringStream* stream) {
Range* HBitAnd::InferRange() {
Range* a = left()->range();
Range* b = right()->range();
int32_t a_mask = 0xffffffff;
int32_t b_mask = 0xffffffff;
if (a != NULL) a_mask = a->Mask();
if (b != NULL) b_mask = b->Mask();
int32_t result_mask = a_mask & b_mask;
if (result_mask >= 0) {
return new Range(0, result_mask);
} else {
return HBinaryOperation::InferRange();
}
int32_t left_mask = (left()->range() != NULL)
? left()->range()->Mask()
: 0xffffffff;
int32_t right_mask = (right()->range() != NULL)
? right()->range()->Mask()
: 0xffffffff;
int32_t result_mask = left_mask & right_mask;
return (result_mask >= 0)
? new Range(0, result_mask)
: HValue::InferRange();
}
Range* HBitOr::InferRange() {
Range* a = left()->range();
Range* b = right()->range();
int32_t a_mask = 0xffffffff;
int32_t b_mask = 0xffffffff;
if (a != NULL) a_mask = a->Mask();
if (b != NULL) b_mask = b->Mask();
int32_t result_mask = a_mask | b_mask;
if (result_mask >= 0) {
return new Range(0, result_mask);
} else {
return HBinaryOperation::InferRange();
}
int32_t left_mask = (left()->range() != NULL)
? left()->range()->Mask()
: 0xffffffff;
int32_t right_mask = (right()->range() != NULL)
? right()->range()->Mask()
: 0xffffffff;
int32_t result_mask = left_mask | right_mask;
return (result_mask >= 0)
? new Range(0, result_mask)
: HValue::InferRange();
}
......@@ -1056,20 +1094,14 @@ Range* HSar::InferRange() {
if (right()->IsConstant()) {
HConstant* c = HConstant::cast(right());
if (c->HasInteger32Value()) {
int32_t val = c->Integer32Value();
Range* result = NULL;
Range* left_range = left()->range();
if (left_range == NULL) {
result = new Range();
} else {
result = left_range->Copy();
}
result->Sar(val);
Range* result = (left()->range() != NULL)
? left()->range()->Copy()
: new Range();
result->Sar(c->Integer32Value());
return result;
}
}
return HBinaryOperation::InferRange();
return HValue::InferRange();
}
......@@ -1077,20 +1109,14 @@ Range* HShl::InferRange() {
if (right()->IsConstant()) {
HConstant* c = HConstant::cast(right());
if (c->HasInteger32Value()) {
int32_t val = c->Integer32Value();
Range* result = NULL;
Range* left_range = left()->range();
if (left_range == NULL) {
result = new Range();
} else {
result = left_range->Copy();
}
result->Shl(val);
Range* result = (left()->range() != NULL)
? left()->range()->Copy()
: new Range();
result->Shl(c->Integer32Value());
return result;
}
}
return HBinaryOperation::InferRange();
return HValue::InferRange();
}
......
......@@ -190,81 +190,48 @@ class LChunkBuilder;
class Range: public ZoneObject {
public:
Range() : lower_(kMinInt),
upper_(kMaxInt),
next_(NULL),
can_be_minus_zero_(false) { }
Range()
: lower_(kMinInt),
upper_(kMaxInt),
next_(NULL),
can_be_minus_zero_(false) { }
Range(int32_t lower, int32_t upper)
: lower_(lower), upper_(upper), next_(NULL), can_be_minus_zero_(false) { }
: lower_(lower),
upper_(upper),
next_(NULL),
can_be_minus_zero_(false) { }
bool IsInSmiRange() const {
return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
}
void KeepOrder();
void Verify() const;
int32_t upper() const { return upper_; }
int32_t lower() const { return lower_; }
Range* next() const { return next_; }
Range* CopyClearLower() const { return new Range(kMinInt, upper_); }
Range* CopyClearUpper() const { return new Range(lower_, kMaxInt); }
void ClearLower() { lower_ = kMinInt; }
void ClearUpper() { upper_ = kMaxInt; }
Range* Copy() const { return new Range(lower_, upper_); }
bool IsMostGeneric() const { return lower_ == kMinInt && upper_ == kMaxInt; }
int32_t Mask() const;
void set_can_be_minus_zero(bool b) { can_be_minus_zero_ = b; }
bool CanBeMinusZero() const { return CanBeZero() && can_be_minus_zero_; }
bool CanBeZero() const { return upper_ >= 0 && lower_ <= 0; }
bool CanBeNegative() const { return lower_ < 0; }
bool Includes(int value) const {
return lower_ <= value && upper_ >= value;
}
void Sar(int32_t value) {
int32_t bits = value & 0x1F;
lower_ = lower_ >> bits;
upper_ = upper_ >> bits;
set_can_be_minus_zero(false);
}
void Shl(int32_t value) {
int32_t bits = value & 0x1F;
int old_lower = lower_;
int old_upper = upper_;
lower_ = lower_ << bits;
upper_ = upper_ << bits;
if (old_lower != lower_ >> bits || old_upper != upper_ >> bits) {
upper_ = kMaxInt;
lower_ = kMinInt;
}
set_can_be_minus_zero(false);
bool Includes(int value) const { return lower_ <= value && upper_ >= value; }
bool IsMostGeneric() const { return lower_ == kMinInt && upper_ == kMaxInt; }
bool IsInSmiRange() const {
return lower_ >= Smi::kMinValue && upper_ <= Smi::kMaxValue;
}
// Adds a constant to the lower and upper bound of the range.
void AddConstant(int32_t value);
void KeepOrder();
void Verify() const;
void StackUpon(Range* other) {
Intersect(other);
next_ = other;
}
void Intersect(Range* other) {
upper_ = Min(upper_, other->upper_);
lower_ = Max(lower_, other->lower_);
bool b = CanBeMinusZero() && other->CanBeMinusZero();
set_can_be_minus_zero(b);
}
void Union(Range* other) {
upper_ = Max(upper_, other->upper_);
lower_ = Min(lower_, other->lower_);
bool b = CanBeMinusZero() || other->CanBeMinusZero();
set_can_be_minus_zero(b);
}
void Intersect(Range* other);
void Union(Range* other);
// Compute a new result range and return true, if the operation
// can overflow.
void AddConstant(int32_t value);
void Sar(int32_t value);
void Shl(int32_t value);
bool AddAndCheckOverflow(Range* other);
bool SubAndCheckOverflow(Range* other);
bool MulAndCheckOverflow(Range* other);
......
......@@ -867,8 +867,8 @@ void HRangeAnalysis::InferControlFlowRange(HTest* test, HBasicBlock* dest) {
void HRangeAnalysis::InferControlFlowRange(Token::Value op,
HValue* value,
HValue* other) {
Range* range = other->range();
if (range == NULL) range = new Range();
Range temp_range;
Range* range = other->range() != NULL ? other->range() : &temp_range;
Range* new_range = NULL;
TraceRange("Control flow range infer %d %s %d\n",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment