Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(405)

Unified Diff: src/compiler/operation-typer.cc

Issue 2320753002: [turbofan] increased precision of range types for bitshifts (Closed)
Patch Set: [turbofan] precise range analysis for bitshifts Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/operation-typer.cc
diff --git a/src/compiler/operation-typer.cc b/src/compiler/operation-typer.cc
index 4295a22287f1b24939ecb999358e1032170bc53b..598d334c30896b5314da22dfeef9225ad5a451a1 100644
--- a/src/compiler/operation-typer.cc
+++ b/src/compiler/operation-typer.cc
@@ -793,8 +793,35 @@ Type* OperationTyper::NumberShiftLeft(Type* lhs, Type* rhs) {
DCHECK(lhs->Is(Type::Number()));
DCHECK(rhs->Is(Type::Number()));
- // TODO(turbofan): Infer a better type here.
- return Type::Signed32();
+ if (!lhs->IsInhabited() || !rhs->IsInhabited()) return Type::None();
+
+ lhs = NumberToInt32(lhs);
+ rhs = NumberToUint32(rhs);
+
+ int32_t minLhs = lhs->Min();
Jarin 2016/11/21 10:34:59 Style nit: minLhs -> min_lhs.
+ int32_t maxLhs = lhs->Max();
+ uint32_t maxRhs = rhs->Max();
+ uint32_t minRhs = rhs->Min();
+ if (maxRhs > 31) {
+ // rhs can be larger than the bitmask
+ maxRhs = 31;
+ minRhs = 0;
+ }
+
+ if (maxLhs > (kMaxInt >> maxRhs) || minLhs < (kMinInt >> maxRhs)) {
+ // overflow possible
+ return Type::Signed32();
+ }
+
+ double min =
+ std::min(static_cast<int32_t>(static_cast<uint32_t>(minLhs) << minRhs),
+ static_cast<int32_t>(static_cast<uint32_t>(minLhs) << maxRhs));
+ double max =
+ std::max(static_cast<int32_t>(static_cast<uint32_t>(maxLhs) << minRhs),
+ static_cast<int32_t>(static_cast<uint32_t>(maxLhs) << maxRhs));
+
+ if (max == kMaxInt && min == kMinInt) return Type::Signed32();
+ return Type::Range(min, max, zone());
}
Type* OperationTyper::NumberShiftRight(Type* lhs, Type* rhs) {
@@ -806,33 +833,18 @@ Type* OperationTyper::NumberShiftRight(Type* lhs, Type* rhs) {
lhs = NumberToInt32(lhs);
rhs = NumberToUint32(rhs);
- double min = kMinInt;
- double max = kMaxInt;
- if (lhs->Min() >= 0) {
- // Right-shifting a non-negative value cannot make it negative, nor larger.
- min = std::max(min, 0.0);
- max = std::min(max, lhs->Max());
- if (rhs->Min() > 0 && rhs->Max() <= 31) {
- max = static_cast<int>(max) >> static_cast<int>(rhs->Min());
- }
+ int32_t minLhs = lhs->Min();
+ int32_t maxLhs = lhs->Max();
+ uint32_t maxRhs = rhs->Max();
+ uint32_t minRhs = rhs->Min();
+ if (maxRhs > 31) {
+ // rhs can be larger than the bitmask
+ maxRhs = 31;
+ minRhs = 0;
}
- if (lhs->Max() < 0) {
- // Right-shifting a negative value cannot make it non-negative, nor smaller.
- min = std::max(min, lhs->Min());
- max = std::min(max, -1.0);
- if (rhs->Min() > 0 && rhs->Max() <= 31) {
- min = static_cast<int>(min) >> static_cast<int>(rhs->Min());
- }
- }
- if (rhs->Min() > 0 && rhs->Max() <= 31) {
- // Right-shifting by a positive value yields a small integer value.
- double shift_min = kMinInt >> static_cast<int>(rhs->Min());
- double shift_max = kMaxInt >> static_cast<int>(rhs->Min());
- min = std::max(min, shift_min);
- max = std::min(max, shift_max);
- }
- // TODO(jarin) Ideally, the following micro-optimization should be performed
- // by the type constructor.
+ double min = std::min(minLhs >> minRhs, minLhs >> maxRhs);
+ double max = std::max(maxLhs >> minRhs, maxLhs >> maxRhs);
+
if (max == kMaxInt && min == kMinInt) return Type::Signed32();
return Type::Range(min, max, zone());
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698