summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Ayers <andya@microsoft.com>2018-05-10 14:43:03 -0700
committerGitHub <noreply@github.com>2018-05-10 14:43:03 -0700
commit67cda04ab3ea8cb89874ebf1fae0ff623241f71f (patch)
treeb96a5cfee4e9db9363ad4e8640c68934e24d5012
parent284bc5c6c71cb33da46c6b153dfdf5d01007775f (diff)
downloadcoreclr-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.cpp57
-rw-r--r--src/jit/valuenum.h6
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;