From 5368372525757b54ba1b74dc8498b7945f7f7272 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Wed, 8 Jun 2022 21:46:10 +0200 Subject: [PATCH] JIT: Unspecialize handle types after arithmetic ops in VN VN was retaining the precise handle types when applying arithmetic operations to handles. This meant that we could not rely on handles of types like GTF_ICON_METHOD_HDL actually containing an embedded method handle after constant propagation. This change generalizes the handle type to GTF_ICON_CONST_PTR or GTF_ICON_GLOBAL_PTR whenever VN does anything that semantically "unassociates" the icon from the specialized handle type. --- src/coreclr/jit/valuenum.cpp | 41 ++++++++++++++++++++++++++++++++---- src/coreclr/jit/valuenum.h | 2 ++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index be7fc14611f0f..f32b7d79ddb0b 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -2869,13 +2869,15 @@ ValueNum ValueNumStore::EvalFuncForConstantArgs(var_types typ, VNFunc func, Valu { int resVal = EvalOp(func, ConstantValue(arg0VN)); // Unary op on a handle results in a handle. - return IsVNHandle(arg0VN) ? VNForHandle(ssize_t(resVal), GetHandleFlags(arg0VN)) : VNForIntCon(resVal); + return IsVNHandle(arg0VN) ? VNForHandle(ssize_t(resVal), GetFoldedArithOpResultHandleFlags(arg0VN)) + : VNForIntCon(resVal); } case TYP_LONG: { INT64 resVal = EvalOp(func, ConstantValue(arg0VN)); // Unary op on a handle results in a handle. - return IsVNHandle(arg0VN) ? VNForHandle(ssize_t(resVal), GetHandleFlags(arg0VN)) : VNForLongCon(resVal); + return IsVNHandle(arg0VN) ? VNForHandle(ssize_t(resVal), GetFoldedArithOpResultHandleFlags(arg0VN)) + : VNForLongCon(resVal); } case TYP_FLOAT: { @@ -3106,7 +3108,7 @@ ValueNum ValueNumStore::EvalFuncForConstantArgs(var_types typ, VNFunc func, Valu ValueNum handleVN = IsVNHandle(arg0VN) ? arg0VN : IsVNHandle(arg1VN) ? arg1VN : NoVN; if (handleVN != NoVN) { - result = VNForHandle(ssize_t(resultVal), GetHandleFlags(handleVN)); // Use VN for Handle + result = VNForHandle(ssize_t(resultVal), GetFoldedArithOpResultHandleFlags(handleVN)); } else { @@ -3132,7 +3134,7 @@ ValueNum ValueNumStore::EvalFuncForConstantArgs(var_types typ, VNFunc func, Valu if (handleVN != NoVN) { - result = VNForHandle(ssize_t(resultVal), GetHandleFlags(handleVN)); // Use VN for Handle + result = VNForHandle(ssize_t(resultVal), GetFoldedArithOpResultHandleFlags(handleVN)); } else { @@ -5119,6 +5121,37 @@ GenTreeFlags ValueNumStore::GetHandleFlags(ValueNum vn) return handle->m_flags; } +GenTreeFlags ValueNumStore::GetFoldedArithOpResultHandleFlags(ValueNum vn) +{ + GenTreeFlags flags = GetHandleFlags(vn); + assert((flags & GTF_ICON_HDL_MASK) == flags); + + switch (flags) + { + case GTF_ICON_SCOPE_HDL: + case GTF_ICON_CLASS_HDL: + case GTF_ICON_METHOD_HDL: + case GTF_ICON_FIELD_HDL: + case GTF_ICON_TOKEN_HDL: + case GTF_ICON_STR_HDL: + case GTF_ICON_CONST_PTR: + case GTF_ICON_VARG_HDL: + case GTF_ICON_PINVKI_HDL: + case GTF_ICON_FTN_ADDR: + case GTF_ICON_CIDMID_HDL: + case GTF_ICON_TLS_HDL: + case GTF_ICON_STATIC_BOX_PTR: + return GTF_ICON_CONST_PTR; + case GTF_ICON_STATIC_HDL: + case GTF_ICON_GLOBAL_PTR: + case GTF_ICON_BBC_PTR: + return GTF_ICON_GLOBAL_PTR; + default: + assert(!"Unexpected handle type"); + return flags; + } +} + bool ValueNumStore::IsVNHandle(ValueNum vn) { if (vn == NoVN) diff --git a/src/coreclr/jit/valuenum.h b/src/coreclr/jit/valuenum.h index 22755856066a7..fc9ed09913c63 100644 --- a/src/coreclr/jit/valuenum.h +++ b/src/coreclr/jit/valuenum.h @@ -379,6 +379,8 @@ class ValueNumStore // returns true iff vn is known to be a constant int32 that is > 0 bool IsVNPositiveInt32Constant(ValueNum vn); + GenTreeFlags GetFoldedArithOpResultHandleFlags(ValueNum vn); + public: // Initializes any static variables of ValueNumStore. static void InitValueNumStoreStatics();