diff options
author | Andy Ayers <andya@microsoft.com> | 2018-05-10 14:43:03 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-10 14:43:03 -0700 |
commit | 67cda04ab3ea8cb89874ebf1fae0ff623241f71f (patch) | |
tree | b96a5cfee4e9db9363ad4e8640c68934e24d5012 | |
parent | 284bc5c6c71cb33da46c6b153dfdf5d01007775f (diff) | |
download | coreclr-67cda04ab3ea8cb89874ebf1fae0ff623241f71f.tar.gz coreclr-67cda04ab3ea8cb89874ebf1fae0ff623241f71f.tar.bz2 coreclr-67cda04ab3ea8cb89874ebf1fae0ff623241f71f.zip |
Value number identities for compares and subs (#17919)
Improve value number support for various subtracts and unsigned compares.
For instance for non-float values, x - x == 0.
Closes #15491.
-rw-r--r-- | src/jit/valuenum.cpp | 57 | ||||
-rw-r--r-- | src/jit/valuenum.h | 6 |
2 files changed, 49 insertions, 14 deletions
diff --git a/src/jit/valuenum.cpp b/src/jit/valuenum.cpp index 5b8537e599..c0e3460916 100644 --- a/src/jit/valuenum.cpp +++ b/src/jit/valuenum.cpp @@ -1137,28 +1137,31 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V { case GT_ADD: // This identity does not apply for floating point (when x == -0.0) - if (!varTypeIsFloating(typ)) + // (x + 0) == (0 + x) => x + ZeroVN = VNZeroForType(typ); + if (VNIsEqual(arg0VN, ZeroVN)) { - // (x + 0) == (0 + x) => x - ZeroVN = VNZeroForType(typ); - if (arg0VN == ZeroVN) - { - resultVN = arg1VN; - } - else if (arg1VN == ZeroVN) - { - resultVN = arg0VN; - } + resultVN = arg1VN; + } + else if (VNIsEqual(arg1VN, ZeroVN)) + { + resultVN = arg0VN; } break; case GT_SUB: + // This identity does not apply for floating point (when x == -0.0) // (x - 0) => x + // (x - x) => 0 ZeroVN = VNZeroForType(typ); - if (arg1VN == ZeroVN) + if (VNIsEqual(arg1VN, ZeroVN)) { resultVN = arg0VN; } + else if (VNIsEqual(arg0VN, arg1VN)) + { + resultVN = ZeroVN; + } break; case GT_MUL: @@ -1249,8 +1252,12 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V break; case GT_EQ: + case GT_GE: + case GT_LE: // (x == x) => true (unless x is NaN) - if (!varTypeIsFloating(TypeOfVN(arg0VN)) && (arg0VN != NoVN) && (arg0VN == arg1VN)) + // (x <= x) => true (unless x is NaN) + // (x >= x) => true (unless x is NaN) + if (VNIsEqual(arg0VN, arg1VN)) { resultVN = VNOneForType(typ); } @@ -1260,9 +1267,14 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V resultVN = VNZeroForType(typ); } break; + case GT_NE: + case GT_GT: + case GT_LT: // (x != x) => false (unless x is NaN) - if (!varTypeIsFloating(TypeOfVN(arg0VN)) && (arg0VN != NoVN) && (arg0VN == arg1VN)) + // (x > x) => false (unless x is NaN) + // (x < x) => false (unless x is NaN) + if (VNIsEqual(arg0VN, arg1VN)) { resultVN = VNZeroForType(typ); } @@ -1285,6 +1297,23 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V } else // must be a VNF_ function { + if (VNIsEqual(arg0VN, arg1VN)) + { + // x <= x ==> true + // x >= x ==> true + if ((func == VNF_LE_UN) || (func == VNF_GE_UN)) + { + return VNOneForType(typ); + } + // x < x ==> false + // x > x ==> false + // x - x ==> 0 + else if ((func == VNF_LT_UN) || (func == VNF_GT_UN) || (func == VNF_SUB_UN)) + { + return VNZeroForType(typ); + } + } + if (func == VNF_CastClass) { // In terms of values, a castclass always returns its second argument, the object being cast. diff --git a/src/jit/valuenum.h b/src/jit/valuenum.h index 489f5191e5..a8aabef5b1 100644 --- a/src/jit/valuenum.h +++ b/src/jit/valuenum.h @@ -670,6 +670,12 @@ public: { }; + // Return true if two value numbers would compare equal. + bool VNIsEqual(ValueNum vn1, ValueNum vn2) + { + return (vn1 == vn2) && (vn1 != NoVN) && !varTypeIsFloating(TypeOfVN(vn1)); + } + private: struct Chunk; |