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

Unified Diff: src/compiler/typer.cc

Issue 1112123002: Precise bitwise-xor derived result type for all int32 input types. Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Split the bitwise-xor result type derivation into a separate function. Created 5 years, 7 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
Index: src/compiler/typer.cc
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc
index dafd3c95a128f317d0033d1d0b6aeb2e0441f0a2..061109d25009085e54d68f0923e02ab874ab891e 100644
--- a/src/compiler/typer.cc
+++ b/src/compiler/typer.cc
@@ -959,23 +959,113 @@ Type* Typer::Visitor::JSBitwiseAndTyper(Type* lhs, Type* rhs, Typer* t) {
}
+static uint32_t BitwiseXorLow(uint32_t lmin, uint32_t lmax,
+ uint32_t rmin, uint32_t rmax) {
titzer 2015/05/13 14:44:37 Maybe pull these methods into a separate file with
+ uint32_t bit = 0x80000000, mask = 0x7fffffff;
+
+ for (; lmin != lmax || rmin != rmax; bit >>= 1, mask >>= 1) {
+ uint32_t lminb = lmin & bit;
+ uint32_t lmaxb = lmax & bit;
+ uint32_t rminb = rmin & bit;
+ uint32_t rmaxb = rmax & bit;
+ if (lminb != lmaxb || rminb != rmaxb) {
+ if (lminb == lmaxb) {
+ if (lminb) {
+ rmin = (rmin & ~mask) | bit;
+ } else {
+ rmax = (rmax & ~bit) | mask;
+ }
+ } else if (rminb == rmaxb) {
+ if (rminb) {
+ lmin = (lmin & ~mask) | bit;
+ } else {
+ lmax = (lmax & ~bit) | mask;
+ }
+ } else {
+ lmax = (lmax & ~bit) | mask;
+ rmax = (rmax & ~bit) | mask;
+ }
+ }
+ }
+ return lmin ^ rmin;
+}
+
+
+static uint32_t BitwiseXorHigh(uint32_t lmin, uint32_t lmax,
+ uint32_t rmin, uint32_t rmax) {
+ uint32_t bit = 0x80000000, mask = 0x7fffffff;
+
+ for (; lmin != lmax || rmin != rmax; bit >>= 1, mask >>= 1) {
+ uint32_t lminb = lmin & bit;
+ uint32_t lmaxb = lmax & bit;
+ uint32_t rminb = rmin & bit;
+ uint32_t rmaxb = rmax & bit;
+ if (lminb != lmaxb || rminb != rmaxb) {
+ if (lminb == lmaxb) {
+ if (lminb) {
+ rmax = (rmax & ~bit) | mask;
+ } else {
+ rmin = (rmin & ~mask) | bit;
+ }
+ } else if (rminb == rmaxb) {
+ if (rminb) {
+ lmax = (lmax & ~bit) | mask;
+ } else {
+ lmin = (lmin & ~mask) | bit;
+ }
+ } else {
+ lmax = (lmax & ~bit) | mask;
+ rmin = (rmin & ~mask) | bit;
+ }
+ }
+ }
+ return lmax ^ rmax;
+}
+
+
+IntType JSBitwiseXorIntType(IntType lhs, IntType rhs) {
+ uint32_t lminp = uint32_t(std::max(lhs.min, 0));
+ uint32_t lmaxn = uint32_t(std::min(lhs.max, -1));
+ uint32_t rminp = uint32_t(std::max(rhs.min, 0));
+ uint32_t rmaxn = uint32_t(std::min(rhs.max, -1));
+ int32_t min = kMaxInt, max = kMinInt;
+
+ if (lhs.max >= 0 && rhs.max >= 0) {
+ min = std::min(min, int32_t(BitwiseXorLow(lminp, lhs.max,
+ rminp, rhs.max)));
+ max = std::max(max, int32_t(BitwiseXorHigh(lminp, lhs.max,
+ rminp, rhs.max)));
+ }
+ if (lhs.max >= 0 && rhs.min < 0) {
+ min = std::min(min, int32_t(BitwiseXorLow(lminp, lhs.max,
+ rhs.min, rmaxn)));
+ max = std::max(max, int32_t(BitwiseXorHigh(lminp, lhs.max,
+ rhs.min, rmaxn)));
+ }
+ if (lhs.min < 0 && rhs.max >= 0) {
+ min = std::min(min, int32_t(BitwiseXorLow(lhs.min, lmaxn,
+ rminp, rhs.max)));
+ max = std::max(max, int32_t(BitwiseXorHigh(lhs.min, lmaxn,
+ rminp, rhs.max)));
+ }
+ if (lhs.min < 0 && rhs.min < 0) {
+ min = std::min(min, int32_t(BitwiseXorLow(lhs.min, lmaxn,
+ rhs.min, rmaxn)));
+ max = std::max(max, int32_t(BitwiseXorHigh(lhs.min, lmaxn,
+ rhs.min, rmaxn)));
+ }
+ DCHECK(max >= min);
+
+ return IntType(min, max);
+}
+
+
Type* Typer::Visitor::JSBitwiseXorTyper(Type* lhs, Type* rhs, Typer* t) {
lhs = NumberToInt32(ToNumber(lhs, t), t);
rhs = NumberToInt32(ToNumber(rhs, t), t);
- double lmin = lhs->Min();
- double rmin = rhs->Min();
- double lmax = lhs->Max();
- double rmax = rhs->Max();
- if ((lmin >= 0 && rmin >= 0) || (lmax < 0 && rmax < 0)) {
- // Xor-ing negative or non-negative values results in a non-negative value.
- return Type::Unsigned31();
- }
- if ((lmax < 0 && rmin >= 0) || (lmin >= 0 && rmax < 0)) {
- // Xor-ing a negative and a non-negative value results in a negative value.
- // TODO(jarin) Use a range here.
- return Type::Negative32();
- }
- return Type::Signed32();
+ IntType type = JSBitwiseXorIntType(IntType(lhs->Min(), lhs->Max()),
+ IntType(rhs->Min(), rhs->Max()));
+ return Type::Range(type.min, type.max, t->zone());
}

Powered by Google App Engine
This is Rietveld 408576698