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

Side by Side Diff: src/compiler/typer.cc

Issue 986073003: [TurboFan] Calculate precise ranges for bitwise-or with positive input ranges. Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Split the bitwise-or 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 unified diff | Download patch
« no previous file with comments | « src/compiler/typer.h ('k') | test/unittests/compiler/typer-unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/base/flags.h" 5 #include "src/base/flags.h"
6 #include "src/bootstrapper.h" 6 #include "src/bootstrapper.h"
7 #include "src/compiler/graph-reducer.h" 7 #include "src/compiler/graph-reducer.h"
8 #include "src/compiler/js-operator.h" 8 #include "src/compiler/js-operator.h"
9 #include "src/compiler/node.h" 9 #include "src/compiler/node.h"
10 #include "src/compiler/node-properties.h" 10 #include "src/compiler/node-properties.h"
(...skipping 882 matching lines...) Expand 10 before | Expand all | Expand 10 after
893 893
894 Type* Typer::Visitor::JSGreaterThanOrEqualTyper( 894 Type* Typer::Visitor::JSGreaterThanOrEqualTyper(
895 Type* lhs, Type* rhs, Typer* t) { 895 Type* lhs, Type* rhs, Typer* t) {
896 return FalsifyUndefined(Invert(JSCompareTyper(lhs, rhs, t), t), t); 896 return FalsifyUndefined(Invert(JSCompareTyper(lhs, rhs, t), t), t);
897 } 897 }
898 898
899 899
900 // JS bitwise operators. 900 // JS bitwise operators.
901 901
902 902
903 // Calculate the result minimum. The algorithm considers one bit at a time, from
904 // the most significant to least significant, refining a copy of the input
905 // ranges and terminating when the ranges are equal.
906 static uint32_t BitwiseOrLow(uint32_t lmin, uint32_t lmax,
907 uint32_t rmin, uint32_t rmax) {
908 uint32_t bit = 0x80000000, mask = 0x7fffffff;
909
910 // Loop, terminating when the ranges are equal, moving down one bit on each
911 // iteration.
912 for (; lmin != lmax || rmin != rmax; bit >>= 1, mask >>= 1) {
913 // Mask off the current bit from each range limit.
914 uint32_t lminb = lmin & bit;
915 uint32_t lmaxb = lmax & bit;
916 uint32_t rminb = rmin & bit;
917 uint32_t rmaxb = rmax & bit;
918 // At this point the higher bits of each range are equal so comparing the
919 // current bit between the upper and lower limit can determine if the bit
920 // changes over the range. If the two input bits are both static across
921 // their ranges then this bit result is known and is the logical OR of each.
922 if (lminb != lmaxb || rminb != rmaxb) {
923 if (lminb == lmaxb) {
924 // The lhs bit is static over its range. The rhs bit changes across it's
925 // range.
926 if (lminb) {
927 // The lhs bit is one forcing the result bit to be one. The rhs bit is
928 // not significant to this bit in the result due to the OR
929 // operation. The rhs minimum of the remaining bits is zero which
930 // occurs when this current bit ticks over to one - which must be
931 // within range because the bit changes. When the lower rhs bits are
932 // zero they do not affect the lower lhs bits and the result is known.
933 rmin &= ~mask;
934 break;
935 } else {
936 // The lhs bit is zero so the result bit equals the rhs bit. The result
937 // minimum occurs when the bit is zero so the rhs range can be culled
938 // to highest input that does not give a one in this bit position. This
939 // is achieved by clearing the bit and setting all the lower bits.
940 rmax = (rmax & ~bit) | mask;
941 }
942 } else if (rminb == rmaxb) {
943 // The rhs bit is static over its range. The lhs bit changes across it's
944 // range. Cull the lhs range as above.
945 if (rminb) {
946 lmin &= ~mask;
947 break;
948 } else {
949 lmax = (lmax & ~bit) | mask;
950 }
951 } else {
952 // Both input bits change across their ranges. The result minimum will
953 // occur then the result bit is zero which demands that both input ranges
954 // be zero in this bit and they are culled as above.
955 lmax = (lmax & ~bit) | mask;
956 rmax = (rmax & ~bit) | mask;
957 }
958 }
959 }
960 return lmin | rmin;
961 }
962
963
964 // Calculate the result maximum. The algorithm is parallel to the above, but the
965 // logic is somewhat reversed because it is calculating the maximum rather than
966 // the minimum, and it is possible to exit early if both input bits change
967 // across their range.
968 static uint32_t BitwiseOrHigh(uint32_t lmin, uint32_t lmax,
969 uint32_t rmin, uint32_t rmax) {
970 uint32_t bit = 0x80000000, mask = 0x7fffffff;
971
972 for (; lmin != lmax || rmin != rmax; bit >>= 1, mask >>= 1) {
973 uint32_t lminb = lmin & bit;
974 uint32_t lmaxb = lmax & bit;
975 uint32_t rminb = rmin & bit;
976 uint32_t rmaxb = rmax & bit;
977 if (lminb != lmaxb || rminb != rmaxb) {
978 if (lminb == lmaxb) {
979 if (lminb) {
980 rmax |= mask;
981 break;
982 } else {
983 rmin = (rmin & ~mask) | bit;
984 }
985 } else if (rminb == rmaxb) {
986 if (rminb) {
987 lmax |= mask;
988 break;
989 } else {
990 lmin = (lmin & ~mask) | bit;
991 }
992 } else {
993 // Both input bits change across their ranges. If this bit changes then
994 // all the lower bits also change across both input ranges, and since
995 // the result is one if either is one then the maximum occurs when all
996 // lower bits are one. The lhsUpperBit is already set at this point, so
997 // this bit does not need setting here too, just the lower bits.
998 lmax |= mask;
999 break;
1000 }
1001 }
1002 }
1003 return lmax | rmax;
1004 }
1005
1006
1007 IntType JSBitwiseOrIntType(IntType lhs, IntType rhs) {
1008 // Or-ing with 0 is essentially a conversion to int32, and or-ing
1009 // with -1 returns -1.
1010 if (rhs.min == rhs.max) {
1011 if (rhs.min == 0) {
1012 return IntType(lhs.min, lhs.max);
1013 }
1014 if (rhs.min == -1) {
1015 return IntType(rhs.min, rhs.max);
1016 }
1017 }
1018 if (lhs.min == lhs.max) {
1019 if (lhs.min == 0) {
1020 return IntType(rhs.min, rhs.max);
1021 }
1022 if (lhs.min == -1) {
1023 return IntType(lhs.min, lhs.max);
1024 }
1025 }
1026
1027 // Divide the calculation into sub-ranges that do not change sign.
1028 uint32_t lminp = uint32_t(std::max(lhs.min, 0));
1029 uint32_t lmaxn = uint32_t(std::min(lhs.max, -1));
1030 uint32_t rminp = uint32_t(std::max(rhs.min, 0));
1031 uint32_t rmaxn = uint32_t(std::min(rhs.max, -1));
1032 int32_t min = kMaxInt, max = kMinInt;
1033
1034 if (lhs.max >= 0 && rhs.max >= 0) {
1035 min = std::min(min, int32_t(BitwiseOrLow(lminp, lhs.max, rminp, rhs.max)));
1036 max = std::max(max, int32_t(BitwiseOrHigh(lminp, lhs.max, rminp, rhs.max)));
1037 }
1038 if (lhs.max >= 0 && rhs.min < 0) {
1039 min = std::min(min, int32_t(BitwiseOrLow(lminp, lhs.max, rhs.min, rmaxn)));
1040 max = std::max(max, int32_t(BitwiseOrHigh(lminp, lhs.max, rhs.min, rmaxn)));
1041 }
1042 if (lhs.min < 0 && rhs.max >= 0) {
1043 min = std::min(min, int32_t(BitwiseOrLow(lhs.min, lmaxn, rminp, rhs.max)));
1044 max = std::max(max, int32_t(BitwiseOrHigh(lhs.min, lmaxn, rminp, rhs.max)));
1045 }
1046 if (lhs.min < 0 && rhs.min < 0) {
1047 min = std::min(min, int32_t(BitwiseOrLow(lhs.min, lmaxn, rhs.min, rmaxn)));
1048 max = std::max(max, int32_t(BitwiseOrHigh(lhs.min, lmaxn, rhs.min, rmaxn)));
1049 }
1050 DCHECK(max >= min);
1051
1052 return IntType(min, max);
1053 }
1054
1055
903 Type* Typer::Visitor::JSBitwiseOrTyper(Type* lhs, Type* rhs, Typer* t) { 1056 Type* Typer::Visitor::JSBitwiseOrTyper(Type* lhs, Type* rhs, Typer* t) {
904 lhs = NumberToInt32(ToNumber(lhs, t), t); 1057 lhs = NumberToInt32(ToNumber(lhs, t), t);
905 rhs = NumberToInt32(ToNumber(rhs, t), t); 1058 rhs = NumberToInt32(ToNumber(rhs, t), t);
906 double lmin = lhs->Min(); 1059 IntType type = JSBitwiseOrIntType(IntType(lhs->Min(), lhs->Max()),
907 double rmin = rhs->Min(); 1060 IntType(rhs->Min(), rhs->Max()));
908 double lmax = lhs->Max(); 1061 return Type::Range(type.min, type.max, t->zone());
909 double rmax = rhs->Max();
910 // Or-ing any two values results in a value no smaller than their minimum.
911 // Even no smaller than their maximum if both values are non-negative.
912 double min =
913 lmin >= 0 && rmin >= 0 ? std::max(lmin, rmin) : std::min(lmin, rmin);
914 double max = Type::Signed32()->Max();
915
916 // Or-ing with 0 is essentially a conversion to int32.
917 if (rmin == 0 && rmax == 0) {
918 min = lmin;
919 max = lmax;
920 }
921 if (lmin == 0 && lmax == 0) {
922 min = rmin;
923 max = rmax;
924 }
925
926 if (lmax < 0 || rmax < 0) {
927 // Or-ing two values of which at least one is negative results in a negative
928 // value.
929 max = std::min(max, -1.0);
930 }
931 return Type::Range(min, max, t->zone());
932 // TODO(neis): Be precise for singleton inputs, here and elsewhere.
933 } 1062 }
934 1063
935 1064
936 Type* Typer::Visitor::JSBitwiseAndTyper(Type* lhs, Type* rhs, Typer* t) { 1065 Type* Typer::Visitor::JSBitwiseAndTyper(Type* lhs, Type* rhs, Typer* t) {
937 lhs = NumberToInt32(ToNumber(lhs, t), t); 1066 lhs = NumberToInt32(ToNumber(lhs, t), t);
938 rhs = NumberToInt32(ToNumber(rhs, t), t); 1067 rhs = NumberToInt32(ToNumber(rhs, t), t);
939 double lmin = lhs->Min(); 1068 double lmin = lhs->Min();
940 double rmin = rhs->Min(); 1069 double rmin = rhs->Min();
941 double lmax = lhs->Max(); 1070 double lmax = lhs->Max();
942 double rmax = rhs->Max(); 1071 double rmax = rhs->Max();
(...skipping 1423 matching lines...) Expand 10 before | Expand all | Expand 10 after
2366 TYPED_ARRAYS(TYPED_ARRAY_CASE) 2495 TYPED_ARRAYS(TYPED_ARRAY_CASE)
2367 #undef TYPED_ARRAY_CASE 2496 #undef TYPED_ARRAY_CASE
2368 } 2497 }
2369 } 2498 }
2370 return Type::Constant(value, zone()); 2499 return Type::Constant(value, zone());
2371 } 2500 }
2372 2501
2373 } // namespace compiler 2502 } // namespace compiler
2374 } // namespace internal 2503 } // namespace internal
2375 } // namespace v8 2504 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/typer.h ('k') | test/unittests/compiler/typer-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698