From 123328152d5a8f41d731da6afacbe242ab6ef87f Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 21 Nov 2022 01:25:00 +0100 Subject: [PATCH 1/8] Keep FieldSeq in AssertionDesc --- src/coreclr/jit/assertionprop.cpp | 167 +++++++++++++++--------------- src/coreclr/jit/compiler.h | 29 +++++- 2 files changed, 108 insertions(+), 88 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 2c3fca0a28b233..463d9eefbe32ac 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -1141,12 +1141,12 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse if (curAssertion->op1.kind == O1K_EXACT_TYPE) { printf("Exact Type MT(%08X)", dspPtr(curAssertion->op2.u1.iconVal)); - assert(curAssertion->op2.u1.iconFlags != GTF_EMPTY); + assert(curAssertion->Op2HasIconFlags()); } else if (curAssertion->op1.kind == O1K_SUBTYPE) { printf("MT(%08X)", dspPtr(curAssertion->op2.u1.iconVal)); - assert(curAssertion->op2.u1.iconFlags != GTF_EMPTY); + assert(curAssertion->Op2HasIconFlags()); } else if ((curAssertion->op1.kind == O1K_BOUND_OPER_BND) || (curAssertion->op1.kind == O1K_BOUND_LOOP_BND) || @@ -1183,7 +1183,7 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse } else { - if ((curAssertion->op2.u1.iconFlags & GTF_ICON_HDL_MASK) != 0) + if (curAssertion->Op2HasIconFlags()) { printf("[%08p]", dspPtr(curAssertion->op2.u1.iconVal)); } @@ -1495,12 +1495,12 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, vn = optConservativeNormalVN(op1); } - assertion.op1.vn = vn; - assertion.assertionKind = assertionKind; - assertion.op2.kind = O2K_CONST_INT; - assertion.op2.vn = ValueNumStore::VNForNull(); - assertion.op2.u1.iconVal = 0; - assertion.op2.u1.iconFlags = GTF_EMPTY; + assertion.op1.vn = vn; + assertion.assertionKind = assertionKind; + assertion.op2.kind = O2K_CONST_INT; + assertion.op2.vn = ValueNumStore::VNForNull(); + assertion.op2.u1.iconVal = 0; + assertion.SetOp2IconFlags(GTF_EMPTY); } // // Are we making an assertion about a local variable? @@ -1548,13 +1548,13 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, // where a class can be sealed, but they don't behave as exact types because casts to // non-base types sometimes still succeed. // - assertion.op1.kind = O1K_SUBTYPE; - assertion.op1.lcl.lclNum = lclNum; - assertion.op1.vn = optConservativeNormalVN(op1); - assertion.op1.lcl.ssaNum = op1->AsLclVarCommon()->GetSsaNum(); - assertion.op2.u1.iconVal = op2->AsIntCon()->gtIconVal; - assertion.op2.vn = optConservativeNormalVN(op2); - assertion.op2.u1.iconFlags = op2->GetIconHandleFlag(); + assertion.op1.kind = O1K_SUBTYPE; + assertion.op1.lcl.lclNum = lclNum; + assertion.op1.vn = optConservativeNormalVN(op1); + assertion.op1.lcl.ssaNum = op1->AsLclVarCommon()->GetSsaNum(); + assertion.op2.u1.iconVal = op2->AsIntCon()->gtIconVal; + assertion.op2.vn = optConservativeNormalVN(op2); + assertion.SetOp2IconFlags(op2->GetIconHandleFlag()); // // Ok everything has been set and the assertion looks good @@ -1642,8 +1642,8 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, } #endif // TARGET_ARM - assertion.op2.u1.iconVal = iconVal; - assertion.op2.u1.iconFlags = op2->GetIconHandleFlag(); + assertion.op2.u1.iconVal = iconVal; + assertion.SetOp2IconFlags(op2->GetIconHandleFlag(), op2->AsIntCon()->gtFieldSeq); } else if (op2->gtOper == GT_CNS_LNG) { @@ -1792,7 +1792,7 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, /* iconFlags should only contain bits in GTF_ICON_HDL_MASK */ assert((iconFlags & ~GTF_ICON_HDL_MASK) == 0); - assertion.op2.u1.iconFlags = iconFlags; + assertion.SetOp2IconFlags(iconFlags); } // JIT case else if (optIsTreeKnownIntValue(!optLocalAssertionProp, op2, &cnsValue, &iconFlags)) @@ -1804,7 +1804,7 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, /* iconFlags should only contain bits in GTF_ICON_HDL_MASK */ assert((iconFlags & ~GTF_ICON_HDL_MASK) == 0); - assertion.op2.u1.iconFlags = iconFlags; + assertion.SetOp2IconFlags(iconFlags); } else { @@ -2105,13 +2105,11 @@ void Compiler::optDebugCheckAssertion(AssertionDsc* assertion) case O2K_CONST_INT: { // The only flags that can be set are those in the GTF_ICON_HDL_MASK. - assert((assertion->op2.u1.iconFlags & ~GTF_ICON_HDL_MASK) == 0); - switch (assertion->op1.kind) { case O1K_EXACT_TYPE: case O1K_SUBTYPE: - assert(assertion->op2.u1.iconFlags != GTF_EMPTY); + assert(assertion->Op2HasIconFlags()); break; case O1K_LCLVAR: assert((lvaGetDesc(assertion->op1.lcl.lclNum)->lvType != TYP_REF) || @@ -2130,7 +2128,7 @@ void Compiler::optDebugCheckAssertion(AssertionDsc* assertion) { // All handles should be represented by O2K_CONST_INT, // so no handle bits should be set here. - assert((assertion->op2.u1.iconFlags & GTF_ICON_HDL_MASK) == 0); + assert(!assertion->Op2HasIconFlags()); } break; @@ -2336,13 +2334,13 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) if (hasTestAgainstZero && vnStore->IsVNCompareCheckedBoundArith(op1VN)) { AssertionDsc dsc; - dsc.assertionKind = relop->gtOper == GT_EQ ? OAK_EQUAL : OAK_NOT_EQUAL; - dsc.op1.kind = O1K_BOUND_OPER_BND; - dsc.op1.vn = op1VN; - dsc.op2.kind = O2K_CONST_INT; - dsc.op2.vn = vnStore->VNZeroForType(op2->TypeGet()); - dsc.op2.u1.iconVal = 0; - dsc.op2.u1.iconFlags = GTF_EMPTY; + dsc.assertionKind = relop->gtOper == GT_EQ ? OAK_EQUAL : OAK_NOT_EQUAL; + dsc.op1.kind = O1K_BOUND_OPER_BND; + dsc.op1.vn = op1VN; + dsc.op2.kind = O2K_CONST_INT; + dsc.op2.vn = vnStore->VNZeroForType(op2->TypeGet()); + dsc.op2.u1.iconVal = 0; + dsc.SetOp2IconFlags(GTF_EMPTY); AssertionIndex index = optAddAssertion(&dsc); optCreateComplementaryAssertion(index, nullptr, nullptr); return index; @@ -2353,13 +2351,13 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) else if (vnStore->IsVNCompareCheckedBoundArith(relopVN)) { AssertionDsc dsc; - dsc.assertionKind = OAK_NOT_EQUAL; - dsc.op1.kind = O1K_BOUND_OPER_BND; - dsc.op1.vn = relopVN; - dsc.op2.kind = O2K_CONST_INT; - dsc.op2.vn = vnStore->VNZeroForType(op2->TypeGet()); - dsc.op2.u1.iconVal = 0; - dsc.op2.u1.iconFlags = GTF_EMPTY; + dsc.assertionKind = OAK_NOT_EQUAL; + dsc.op1.kind = O1K_BOUND_OPER_BND; + dsc.op1.vn = relopVN; + dsc.op2.kind = O2K_CONST_INT; + dsc.op2.vn = vnStore->VNZeroForType(op2->TypeGet()); + dsc.op2.u1.iconVal = 0; + dsc.SetOp2IconFlags(GTF_EMPTY); AssertionIndex index = optAddAssertion(&dsc); optCreateComplementaryAssertion(index, nullptr, nullptr); return index; @@ -2370,13 +2368,13 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) else if (hasTestAgainstZero && vnStore->IsVNCompareCheckedBound(op1VN)) { AssertionDsc dsc; - dsc.assertionKind = relop->gtOper == GT_EQ ? OAK_EQUAL : OAK_NOT_EQUAL; - dsc.op1.kind = O1K_BOUND_LOOP_BND; - dsc.op1.vn = op1VN; - dsc.op2.kind = O2K_CONST_INT; - dsc.op2.vn = vnStore->VNZeroForType(op2->TypeGet()); - dsc.op2.u1.iconVal = 0; - dsc.op2.u1.iconFlags = GTF_EMPTY; + dsc.assertionKind = relop->gtOper == GT_EQ ? OAK_EQUAL : OAK_NOT_EQUAL; + dsc.op1.kind = O1K_BOUND_LOOP_BND; + dsc.op1.vn = op1VN; + dsc.op2.kind = O2K_CONST_INT; + dsc.op2.vn = vnStore->VNZeroForType(op2->TypeGet()); + dsc.op2.u1.iconVal = 0; + dsc.SetOp2IconFlags(GTF_EMPTY); AssertionIndex index = optAddAssertion(&dsc); optCreateComplementaryAssertion(index, nullptr, nullptr); return index; @@ -2387,13 +2385,13 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) else if (vnStore->IsVNCompareCheckedBound(relopVN)) { AssertionDsc dsc; - dsc.assertionKind = OAK_NOT_EQUAL; - dsc.op1.kind = O1K_BOUND_LOOP_BND; - dsc.op1.vn = relopVN; - dsc.op2.kind = O2K_CONST_INT; - dsc.op2.vn = vnStore->VNZeroForType(TYP_INT); - dsc.op2.u1.iconVal = 0; - dsc.op2.u1.iconFlags = GTF_EMPTY; + dsc.assertionKind = OAK_NOT_EQUAL; + dsc.op1.kind = O1K_BOUND_LOOP_BND; + dsc.op1.vn = relopVN; + dsc.op2.kind = O2K_CONST_INT; + dsc.op2.vn = vnStore->VNZeroForType(TYP_INT); + dsc.op2.u1.iconVal = 0; + dsc.SetOp2IconFlags(GTF_EMPTY); AssertionIndex index = optAddAssertion(&dsc); optCreateComplementaryAssertion(index, nullptr, nullptr); return index; @@ -2430,13 +2428,13 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) else if (hasTestAgainstZero && vnStore->IsVNConstantBound(op1VN)) { AssertionDsc dsc; - dsc.assertionKind = relop->gtOper == GT_EQ ? OAK_EQUAL : OAK_NOT_EQUAL; - dsc.op1.kind = O1K_CONSTANT_LOOP_BND; - dsc.op1.vn = op1VN; - dsc.op2.kind = O2K_CONST_INT; - dsc.op2.vn = vnStore->VNZeroForType(op2->TypeGet()); - dsc.op2.u1.iconVal = 0; - dsc.op2.u1.iconFlags = GTF_EMPTY; + dsc.assertionKind = relop->gtOper == GT_EQ ? OAK_EQUAL : OAK_NOT_EQUAL; + dsc.op1.kind = O1K_CONSTANT_LOOP_BND; + dsc.op1.vn = op1VN; + dsc.op2.kind = O2K_CONST_INT; + dsc.op2.vn = vnStore->VNZeroForType(op2->TypeGet()); + dsc.op2.u1.iconVal = 0; + dsc.SetOp2IconFlags(GTF_EMPTY); AssertionIndex index = optAddAssertion(&dsc); optCreateComplementaryAssertion(index, nullptr, nullptr); return index; @@ -2447,13 +2445,13 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) else if (vnStore->IsVNConstantBound(relopVN)) { AssertionDsc dsc; - dsc.assertionKind = OAK_NOT_EQUAL; - dsc.op1.kind = O1K_CONSTANT_LOOP_BND; - dsc.op1.vn = relopVN; - dsc.op2.kind = O2K_CONST_INT; - dsc.op2.vn = vnStore->VNZeroForType(TYP_INT); - dsc.op2.u1.iconVal = 0; - dsc.op2.u1.iconFlags = GTF_EMPTY; + dsc.assertionKind = OAK_NOT_EQUAL; + dsc.op1.kind = O1K_CONSTANT_LOOP_BND; + dsc.op1.vn = relopVN; + dsc.op2.kind = O2K_CONST_INT; + dsc.op2.vn = vnStore->VNZeroForType(TYP_INT); + dsc.op2.u1.iconVal = 0; + dsc.SetOp2IconFlags(GTF_EMPTY); AssertionIndex index = optAddAssertion(&dsc); optCreateComplementaryAssertion(index, nullptr, nullptr); return index; @@ -2461,13 +2459,13 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) else if (vnStore->IsVNConstantBoundUnsigned(relopVN)) { AssertionDsc dsc; - dsc.assertionKind = OAK_NOT_EQUAL; - dsc.op1.kind = O1K_CONSTANT_LOOP_BND_UN; - dsc.op1.vn = relopVN; - dsc.op2.kind = O2K_CONST_INT; - dsc.op2.vn = vnStore->VNZeroForType(TYP_INT); - dsc.op2.u1.iconVal = 0; - dsc.op2.u1.iconFlags = GTF_EMPTY; + dsc.assertionKind = OAK_NOT_EQUAL; + dsc.op1.kind = O1K_CONSTANT_LOOP_BND_UN; + dsc.op1.vn = relopVN; + dsc.op2.kind = O2K_CONST_INT; + dsc.op2.vn = vnStore->VNZeroForType(TYP_INT); + dsc.op2.u1.iconVal = 0; + dsc.SetOp2IconFlags(GTF_EMPTY); AssertionIndex index = optAddAssertion(&dsc); optCreateComplementaryAssertion(index, nullptr, nullptr); return index; @@ -2557,13 +2555,13 @@ AssertionInfo Compiler::optAssertionGenJtrue(GenTree* tree) dsc.op1.bnd.vnIdx = vnStore->VNForIntCon(con - 1); } - dsc.op1.vn = op1VN; - dsc.op1.kind = O1K_ARR_BND; - dsc.op1.bnd.vnLen = op1VN; - dsc.op2.vn = vnStore->VNConservativeNormalValue(op2->gtVNPair); - dsc.op2.kind = O2K_CONST_INT; - dsc.op2.u1.iconFlags = GTF_EMPTY; - dsc.op2.u1.iconVal = 0; + dsc.op1.vn = op1VN; + dsc.op1.kind = O1K_ARR_BND; + dsc.op1.bnd.vnLen = op1VN; + dsc.op2.vn = vnStore->VNConservativeNormalValue(op2->gtVNPair); + dsc.op2.kind = O2K_CONST_INT; + dsc.op2.u1.iconVal = 0; + dsc.SetOp2IconFlags(GTF_EMPTY); // when con is not zero, create an assertion on the arr.Length == con edge // when con is zero, create an assertion on the arr.Length != 0 edge @@ -3366,7 +3364,7 @@ GenTree* Compiler::optConstantAssertionProp(AssertionDsc* curAssertion, case O2K_CONST_INT: // Don't propagate handles if we need to report relocs. - if (opts.compReloc && ((curAssertion->op2.u1.iconFlags & GTF_ICON_HDL_MASK) != 0)) + if (opts.compReloc && curAssertion->Op2HasIconFlags()) { return nullptr; } @@ -3381,11 +3379,12 @@ GenTree* Compiler::optConstantAssertionProp(AssertionDsc* curAssertion, assert(!varTypeIsSmall(tree) || (curAssertion->op2.u1.iconVal == optCastConstantSmall(curAssertion->op2.u1.iconVal, tree->TypeGet()))); - if (curAssertion->op2.u1.iconFlags & GTF_ICON_HDL_MASK) + if (curAssertion->Op2HasIconFlags()) { // Here we have to allocate a new 'large' node to replace the old one - newTree = gtNewIconHandleNode(curAssertion->op2.u1.iconVal, - curAssertion->op2.u1.iconFlags & GTF_ICON_HDL_MASK); + newTree = gtNewIconHandleNode(curAssertion->op2.u1.iconVal, curAssertion->GetOp2IconFlags()); + + newTree->AsIntCon()->gtFieldSeq = curAssertion->op2.u1.fieldSeq; // Make sure we don't retype const gc handles to TYP_I_IMPL // Although, it's possible for e.g. GTF_ICON_STATIC_HDL diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index a489f9249f1b82..fc90090a8f3f05 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7056,7 +7056,7 @@ class Compiler O1K_COUNT }; - enum optOp2Kind + enum optOp2Kind : uint16_t { O2K_INVALID, O2K_LCLVAR_COPY, @@ -7093,7 +7093,8 @@ class Compiler } op1; struct AssertionDscOp2 { - optOp2Kind kind; // a const or copy assignment + optOp2Kind kind; // a const or copy assignment + uint16_t encodedIconFlags; // encoded icon gtFlags ValueNum vn; struct IntVal { @@ -7101,7 +7102,7 @@ class Compiler #if !defined(HOST_64BIT) unsigned padding; // unused; ensures iconFlags does not overlap lconVal #endif - GenTreeFlags iconFlags; // gtFlags + FieldSeq* fieldSeq; }; union { SsaVar lcl; @@ -7112,6 +7113,25 @@ class Compiler }; } op2; + void SetOp2IconFlags(GenTreeFlags flags, FieldSeq* fieldSeq = nullptr) + { + assert((flags & ~GTF_ICON_HDL_MASK) == 0); + static_assert_no_msg((GTF_ICON_HDL_MASK >> 24) == 0xFF); + op2.encodedIconFlags = flags >> 24; + op2.u1.fieldSeq = fieldSeq; + } + GenTreeFlags GetOp2IconFlags() + { + GenTreeFlags flags = (GenTreeFlags)(op2.encodedIconFlags << 24); + assert((flags & ~GTF_ICON_HDL_MASK) == 0); + static_assert_no_msg((GTF_ICON_HDL_MASK >> 24) == 0xFF); + return flags; + } + bool Op2HasIconFlags() + { + assert(op2.encodedIconFlags <= 0xFF); + return op2.encodedIconFlags != 0; + } bool IsCheckedBoundArithBound() { return ((assertionKind == OAK_EQUAL || assertionKind == OAK_NOT_EQUAL) && op1.kind == O1K_BOUND_OPER_BND); @@ -7218,7 +7238,8 @@ class Compiler { case O2K_IND_CNS_INT: case O2K_CONST_INT: - return ((op2.u1.iconVal == that->op2.u1.iconVal) && (op2.u1.iconFlags == that->op2.u1.iconFlags)); + return ((op2.u1.iconVal == that->op2.u1.iconVal) && + (op2.encodedIconFlags == that->op2.encodedIconFlags)); case O2K_CONST_LONG: return (op2.lconVal == that->op2.lconVal); From 9f57e782adb3353c8d49139485cb9f1a04e18d77 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 21 Nov 2022 12:27:20 +0100 Subject: [PATCH 2/8] Clean up --- src/coreclr/jit/assertionprop.cpp | 50 +++++++++++++++++-------------- src/coreclr/jit/compiler.h | 43 +++++++++++++------------- 2 files changed, 48 insertions(+), 45 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 463d9eefbe32ac..a15b323aa45aa8 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -1141,12 +1141,12 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse if (curAssertion->op1.kind == O1K_EXACT_TYPE) { printf("Exact Type MT(%08X)", dspPtr(curAssertion->op2.u1.iconVal)); - assert(curAssertion->Op2HasIconFlags()); + assert(curAssertion->op2.HasIconFlag()); } else if (curAssertion->op1.kind == O1K_SUBTYPE) { printf("MT(%08X)", dspPtr(curAssertion->op2.u1.iconVal)); - assert(curAssertion->Op2HasIconFlags()); + assert(curAssertion->op2.HasIconFlag()); } else if ((curAssertion->op1.kind == O1K_BOUND_OPER_BND) || (curAssertion->op1.kind == O1K_BOUND_LOOP_BND) || @@ -1183,7 +1183,7 @@ void Compiler::optPrintAssertion(AssertionDsc* curAssertion, AssertionIndex asse } else { - if (curAssertion->Op2HasIconFlags()) + if (curAssertion->op2.HasIconFlag()) { printf("[%08p]", dspPtr(curAssertion->op2.u1.iconVal)); } @@ -1500,7 +1500,7 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, assertion.op2.kind = O2K_CONST_INT; assertion.op2.vn = ValueNumStore::VNForNull(); assertion.op2.u1.iconVal = 0; - assertion.SetOp2IconFlags(GTF_EMPTY); + assertion.op2.SetIconFlag(GTF_EMPTY); } // // Are we making an assertion about a local variable? @@ -1554,7 +1554,7 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, assertion.op1.lcl.ssaNum = op1->AsLclVarCommon()->GetSsaNum(); assertion.op2.u1.iconVal = op2->AsIntCon()->gtIconVal; assertion.op2.vn = optConservativeNormalVN(op2); - assertion.SetOp2IconFlags(op2->GetIconHandleFlag()); + assertion.op2.SetIconFlag(op2->GetIconHandleFlag()); // // Ok everything has been set and the assertion looks good @@ -1643,7 +1643,7 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, #endif // TARGET_ARM assertion.op2.u1.iconVal = iconVal; - assertion.SetOp2IconFlags(op2->GetIconHandleFlag(), op2->AsIntCon()->gtFieldSeq); + assertion.op2.SetIconFlag(op2->GetIconHandleFlag(), op2->AsIntCon()->gtFieldSeq); } else if (op2->gtOper == GT_CNS_LNG) { @@ -1792,7 +1792,7 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, /* iconFlags should only contain bits in GTF_ICON_HDL_MASK */ assert((iconFlags & ~GTF_ICON_HDL_MASK) == 0); - assertion.SetOp2IconFlags(iconFlags); + assertion.op2.SetIconFlag(iconFlags); } // JIT case else if (optIsTreeKnownIntValue(!optLocalAssertionProp, op2, &cnsValue, &iconFlags)) @@ -1804,7 +1804,7 @@ AssertionIndex Compiler::optCreateAssertion(GenTree* op1, /* iconFlags should only contain bits in GTF_ICON_HDL_MASK */ assert((iconFlags & ~GTF_ICON_HDL_MASK) == 0); - assertion.SetOp2IconFlags(iconFlags); + assertion.op2.SetIconFlag(iconFlags); } else { @@ -2109,7 +2109,7 @@ void Compiler::optDebugCheckAssertion(AssertionDsc* assertion) { case O1K_EXACT_TYPE: case O1K_SUBTYPE: - assert(assertion->Op2HasIconFlags()); + assert(assertion->op2.HasIconFlag()); break; case O1K_LCLVAR: assert((lvaGetDesc(assertion->op1.lcl.lclNum)->lvType != TYP_REF) || @@ -2128,7 +2128,7 @@ void Compiler::optDebugCheckAssertion(AssertionDsc* assertion) { // All handles should be represented by O2K_CONST_INT, // so no handle bits should be set here. - assert(!assertion->Op2HasIconFlags()); + assert(!assertion->op2.HasIconFlag()); } break; @@ -2340,7 +2340,7 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) dsc.op2.kind = O2K_CONST_INT; dsc.op2.vn = vnStore->VNZeroForType(op2->TypeGet()); dsc.op2.u1.iconVal = 0; - dsc.SetOp2IconFlags(GTF_EMPTY); + dsc.op2.SetIconFlag(GTF_EMPTY); AssertionIndex index = optAddAssertion(&dsc); optCreateComplementaryAssertion(index, nullptr, nullptr); return index; @@ -2357,7 +2357,7 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) dsc.op2.kind = O2K_CONST_INT; dsc.op2.vn = vnStore->VNZeroForType(op2->TypeGet()); dsc.op2.u1.iconVal = 0; - dsc.SetOp2IconFlags(GTF_EMPTY); + dsc.op2.SetIconFlag(GTF_EMPTY); AssertionIndex index = optAddAssertion(&dsc); optCreateComplementaryAssertion(index, nullptr, nullptr); return index; @@ -2374,7 +2374,7 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) dsc.op2.kind = O2K_CONST_INT; dsc.op2.vn = vnStore->VNZeroForType(op2->TypeGet()); dsc.op2.u1.iconVal = 0; - dsc.SetOp2IconFlags(GTF_EMPTY); + dsc.op2.SetIconFlag(GTF_EMPTY); AssertionIndex index = optAddAssertion(&dsc); optCreateComplementaryAssertion(index, nullptr, nullptr); return index; @@ -2391,7 +2391,7 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) dsc.op2.kind = O2K_CONST_INT; dsc.op2.vn = vnStore->VNZeroForType(TYP_INT); dsc.op2.u1.iconVal = 0; - dsc.SetOp2IconFlags(GTF_EMPTY); + dsc.op2.SetIconFlag(GTF_EMPTY); AssertionIndex index = optAddAssertion(&dsc); optCreateComplementaryAssertion(index, nullptr, nullptr); return index; @@ -2434,7 +2434,7 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) dsc.op2.kind = O2K_CONST_INT; dsc.op2.vn = vnStore->VNZeroForType(op2->TypeGet()); dsc.op2.u1.iconVal = 0; - dsc.SetOp2IconFlags(GTF_EMPTY); + dsc.op2.SetIconFlag(GTF_EMPTY); AssertionIndex index = optAddAssertion(&dsc); optCreateComplementaryAssertion(index, nullptr, nullptr); return index; @@ -2451,7 +2451,7 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) dsc.op2.kind = O2K_CONST_INT; dsc.op2.vn = vnStore->VNZeroForType(TYP_INT); dsc.op2.u1.iconVal = 0; - dsc.SetOp2IconFlags(GTF_EMPTY); + dsc.op2.SetIconFlag(GTF_EMPTY); AssertionIndex index = optAddAssertion(&dsc); optCreateComplementaryAssertion(index, nullptr, nullptr); return index; @@ -2465,7 +2465,7 @@ AssertionInfo Compiler::optCreateJTrueBoundsAssertion(GenTree* tree) dsc.op2.kind = O2K_CONST_INT; dsc.op2.vn = vnStore->VNZeroForType(TYP_INT); dsc.op2.u1.iconVal = 0; - dsc.SetOp2IconFlags(GTF_EMPTY); + dsc.op2.SetIconFlag(GTF_EMPTY); AssertionIndex index = optAddAssertion(&dsc); optCreateComplementaryAssertion(index, nullptr, nullptr); return index; @@ -2561,7 +2561,7 @@ AssertionInfo Compiler::optAssertionGenJtrue(GenTree* tree) dsc.op2.vn = vnStore->VNConservativeNormalValue(op2->gtVNPair); dsc.op2.kind = O2K_CONST_INT; dsc.op2.u1.iconVal = 0; - dsc.SetOp2IconFlags(GTF_EMPTY); + dsc.op2.SetIconFlag(GTF_EMPTY); // when con is not zero, create an assertion on the arr.Length == con edge // when con is zero, create an assertion on the arr.Length != 0 edge @@ -3364,7 +3364,7 @@ GenTree* Compiler::optConstantAssertionProp(AssertionDsc* curAssertion, case O2K_CONST_INT: // Don't propagate handles if we need to report relocs. - if (opts.compReloc && curAssertion->Op2HasIconFlags()) + if (opts.compReloc && curAssertion->op2.HasIconFlag()) { return nullptr; } @@ -3379,12 +3379,16 @@ GenTree* Compiler::optConstantAssertionProp(AssertionDsc* curAssertion, assert(!varTypeIsSmall(tree) || (curAssertion->op2.u1.iconVal == optCastConstantSmall(curAssertion->op2.u1.iconVal, tree->TypeGet()))); - if (curAssertion->Op2HasIconFlags()) + if (curAssertion->op2.HasIconFlag()) { // Here we have to allocate a new 'large' node to replace the old one - newTree = gtNewIconHandleNode(curAssertion->op2.u1.iconVal, curAssertion->GetOp2IconFlags()); - - newTree->AsIntCon()->gtFieldSeq = curAssertion->op2.u1.fieldSeq; + newTree = gtNewIconHandleNode(curAssertion->op2.u1.iconVal, curAssertion->op2.GetIconFlag()); + FieldSeq* seq = curAssertion->op2.u1.fieldSeq; + if ((seq != nullptr) && (curAssertion->op2.GetIconFlag() == GTF_ICON_STATIC_HDL) && + (seq->GetOffset() == curAssertion->op2.u1.iconVal)) + { + newTree->AsIntCon()->gtFieldSeq = seq; + } // Make sure we don't retype const gc handles to TYP_I_IMPL // Although, it's possible for e.g. GTF_ICON_STATIC_HDL diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index fc90090a8f3f05..fc7366fa864e85 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7094,7 +7094,7 @@ class Compiler struct AssertionDscOp2 { optOp2Kind kind; // a const or copy assignment - uint16_t encodedIconFlags; // encoded icon gtFlags + uint16_t encodedIconFlags; // encoded icon gtFlags, don't use directly ValueNum vn; struct IntVal { @@ -7111,27 +7111,27 @@ class Compiler double dconVal; IntegralRange u2; }; + + bool HasIconFlag() + { + assert(encodedIconFlags <= 0xFF); + return encodedIconFlags != 0; + } + GenTreeFlags GetIconFlag() + { + GenTreeFlags flags = (GenTreeFlags)(encodedIconFlags << 24); + assert((flags & ~GTF_ICON_HDL_MASK) == 0); + static_assert_no_msg((0xFF000000 == GTF_ICON_HDL_MASK) && (GTF_ICON_HDL_MASK >> 24) == 0xFF); + return flags; + } + void SetIconFlag(GenTreeFlags flags, FieldSeq* fieldSeq = nullptr) + { + assert((flags & ~GTF_ICON_HDL_MASK) == 0); + encodedIconFlags = flags >> 24; + u1.fieldSeq = fieldSeq; + } } op2; - void SetOp2IconFlags(GenTreeFlags flags, FieldSeq* fieldSeq = nullptr) - { - assert((flags & ~GTF_ICON_HDL_MASK) == 0); - static_assert_no_msg((GTF_ICON_HDL_MASK >> 24) == 0xFF); - op2.encodedIconFlags = flags >> 24; - op2.u1.fieldSeq = fieldSeq; - } - GenTreeFlags GetOp2IconFlags() - { - GenTreeFlags flags = (GenTreeFlags)(op2.encodedIconFlags << 24); - assert((flags & ~GTF_ICON_HDL_MASK) == 0); - static_assert_no_msg((GTF_ICON_HDL_MASK >> 24) == 0xFF); - return flags; - } - bool Op2HasIconFlags() - { - assert(op2.encodedIconFlags <= 0xFF); - return op2.encodedIconFlags != 0; - } bool IsCheckedBoundArithBound() { return ((assertionKind == OAK_EQUAL || assertionKind == OAK_NOT_EQUAL) && op1.kind == O1K_BOUND_OPER_BND); @@ -7238,8 +7238,7 @@ class Compiler { case O2K_IND_CNS_INT: case O2K_CONST_INT: - return ((op2.u1.iconVal == that->op2.u1.iconVal) && - (op2.encodedIconFlags == that->op2.encodedIconFlags)); + return ((op2.u1.iconVal == that->op2.u1.iconVal) && (op2.GetIconFlag() == that->op2.GetIconFlag())); case O2K_CONST_LONG: return (op2.lconVal == that->op2.lconVal); From 1de1bdddf0a4789a2b9d1f270b1a962de9806870 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Mon, 21 Nov 2022 22:05:19 +0100 Subject: [PATCH 3/8] Apply SingleAccretion's patch --- src/coreclr/jit/assertionprop.cpp | 9 ++------- src/coreclr/jit/gentree.cpp | 18 ++++++++++++++++++ src/coreclr/jit/gentree.h | 12 +++++++----- src/coreclr/jit/importer.cpp | 6 ++++++ src/coreclr/jit/morph.cpp | 2 +- 5 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 688d871a47f85e..30aaa8c5be1af2 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -3382,13 +3382,8 @@ GenTree* Compiler::optConstantAssertionProp(AssertionDsc* curAssertion, if (curAssertion->op2.HasIconFlag()) { // Here we have to allocate a new 'large' node to replace the old one - newTree = gtNewIconHandleNode(curAssertion->op2.u1.iconVal, curAssertion->op2.GetIconFlag()); - FieldSeq* seq = curAssertion->op2.u1.fieldSeq; - if ((seq != nullptr) && (curAssertion->op2.GetIconFlag() == GTF_ICON_STATIC_HDL) && - (seq->GetOffset() == curAssertion->op2.u1.iconVal)) - { - newTree->AsIntCon()->gtFieldSeq = seq; - } + newTree = gtNewIconHandleNode(curAssertion->op2.u1.iconVal, curAssertion->op2.GetIconFlag(), + curAssertion->op2.u1.fieldSeq); // Make sure we don't retype const gc handles to TYP_I_IMPL // Although, it's possible for e.g. GTF_ICON_STATIC_HDL diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 140aa56a1d9a9a..9a98bcab1877a8 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -17622,6 +17622,15 @@ bool GenTree::IsFieldAddr(Compiler* comp, GenTree** pBaseAddr, FieldSeq** pFldSe baseAddr = AsOp()->gtOp1; fldSeq = AsOp()->gtOp2->AsIntCon()->gtFieldSeq; offset = AsOp()->gtOp2->AsIntCon()->IconValue(); + + if ((fldSeq != nullptr) && (fldSeq->GetKind() == FieldSeq::FieldKind::SimpleStaticKnownAddress)) + { + if (!baseAddr->IsIntegralConst(0)) + { + // Bail-out, base has to be zero if fldSeq represents a known address (not a small offset) + return false; + } + } } else { @@ -17633,6 +17642,15 @@ bool GenTree::IsFieldAddr(Compiler* comp, GenTree** pBaseAddr, FieldSeq** pFldSe baseAddr = this; fldSeq = AsIntCon()->gtFieldSeq; offset = AsIntCon()->IconValue(); + + if ((fldSeq != nullptr) && (fldSeq->GetKind() == FieldSeq::FieldKind::SimpleStaticKnownAddress)) + { + if (!baseAddr->IsIntegralConst(0)) + { + // Bail-out, base has to be zero if fldSeq represents a known address (not a small offset) + return false; + } + } } else { diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index b78096914ebab2..d879c89e311ce8 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -270,13 +270,14 @@ class FieldSeq public: enum class FieldKind : uintptr_t { - Instance = 0, // An instance field. - SimpleStatic = 1, // Simple static field - the handle represents a unique location. - SharedStatic = 2, // Static field on a shared generic type: "Class<__Canon>.StaticField". + Instance = 0, // An instance field. + SimpleStatic = 1, // Simple static field - the handle represents a unique location. + SimpleStaticKnownAddress = 2, // Simple static field - the handle represents a known location. + SharedStatic = 3, // Static field on a shared generic type: "Class<__Canon>.StaticField". }; private: - static const uintptr_t FIELD_KIND_MASK = 0b11; + static const uintptr_t FIELD_KIND_MASK = 0b111; static_assert_no_msg(sizeof(CORINFO_FIELD_HANDLE) == sizeof(uintptr_t)); @@ -310,7 +311,8 @@ class FieldSeq bool IsStaticField() const { - return (GetKind() == FieldKind::SimpleStatic) || (GetKind() == FieldKind::SharedStatic); + return (GetKind() == FieldKind::SimpleStatic) || (GetKind() == FieldKind::SharedStatic) || + (GetKind() == FieldKind::SimpleStaticKnownAddress); } bool IsSharedStaticField() const diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 6185804f898ff0..560b7fa8745136 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -4387,6 +4387,12 @@ GenTree* Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedT ssize_t offset; if (hasConstAddr) { + if (!isSharedStatic) + { + // Change SharedStatic to SimpleStaticKnownAddress + assert(fieldKind == FieldSeq::FieldKind::SimpleStatic); + fieldKind = FieldSeq::FieldKind::SimpleStaticKnownAddress; + } offset = reinterpret_cast(info.compCompHnd->getFieldAddress(pResolvedToken->hField)); assert(offset != 0); } diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index c1b827e623fd56..6d8310403237ca 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -5408,7 +5408,7 @@ GenTree* Compiler::fgMorphExpandStaticField(GenTree* tree) { // Only simple statics get importred as GT_FIELDs. fieldSeq = GetFieldSeqStore()->Create(fieldHandle, reinterpret_cast(fldAddr), - FieldSeq::FieldKind::SimpleStatic); + FieldSeq::FieldKind::SimpleStaticKnownAddress); } // TODO-CQ: enable this optimization for 32 bit targets. From cd4be835e45c48e6cab15d74d648c643de2a637e Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Mon, 21 Nov 2022 22:27:19 +0100 Subject: [PATCH 4/8] Update src/coreclr/jit/gentree.h Co-authored-by: Jakob Botsch Nielsen --- src/coreclr/jit/gentree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index d879c89e311ce8..de6f900cfafc5b 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -277,7 +277,7 @@ class FieldSeq }; private: - static const uintptr_t FIELD_KIND_MASK = 0b111; + static const uintptr_t FIELD_KIND_MASK = 0b11; static_assert_no_msg(sizeof(CORINFO_FIELD_HANDLE) == sizeof(uintptr_t)); From 679533deb1f182aba615749fdef320715984260d Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Tue, 22 Nov 2022 02:35:47 +0100 Subject: [PATCH 5/8] Update gentree.cpp --- src/coreclr/jit/gentree.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 9a98bcab1877a8..2776b1e71975d9 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -17642,15 +17642,6 @@ bool GenTree::IsFieldAddr(Compiler* comp, GenTree** pBaseAddr, FieldSeq** pFldSe baseAddr = this; fldSeq = AsIntCon()->gtFieldSeq; offset = AsIntCon()->IconValue(); - - if ((fldSeq != nullptr) && (fldSeq->GetKind() == FieldSeq::FieldKind::SimpleStaticKnownAddress)) - { - if (!baseAddr->IsIntegralConst(0)) - { - // Bail-out, base has to be zero if fldSeq represents a known address (not a small offset) - return false; - } - } } else { From 1834b7453cd384151b57be314efa663a48813d64 Mon Sep 17 00:00:00 2001 From: EgorBo Date: Wed, 23 Nov 2022 03:11:54 +0100 Subject: [PATCH 6/8] Address feedback --- src/coreclr/jit/compiler.h | 24 +++++++++++++++--------- src/coreclr/jit/gentree.cpp | 13 +++++-------- src/coreclr/jit/importer.cpp | 14 ++++++-------- 3 files changed, 26 insertions(+), 25 deletions(-) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index 6cec1f2e73c29a..e8da6b72a00340 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7095,9 +7095,11 @@ class Compiler } op1; struct AssertionDscOp2 { - optOp2Kind kind; // a const or copy assignment - uint16_t encodedIconFlags; // encoded icon gtFlags, don't use directly - ValueNum vn; + optOp2Kind kind; // a const or copy assignment + private: + uint16_t m_encodedIconFlags; // encoded icon gtFlags, don't use directly + public: + ValueNum vn; struct IntVal { ssize_t iconVal; // integer @@ -7116,21 +7118,25 @@ class Compiler bool HasIconFlag() { - assert(encodedIconFlags <= 0xFF); - return encodedIconFlags != 0; + assert(m_encodedIconFlags <= 0xFF); + return m_encodedIconFlags != 0; } GenTreeFlags GetIconFlag() { - GenTreeFlags flags = (GenTreeFlags)(encodedIconFlags << 24); + // number of trailing zeros in GTF_ICON_HDL_MASK + const int iconMaskTzc = 24; + static_assert_no_msg((0xFF000000 == GTF_ICON_HDL_MASK) && (GTF_ICON_HDL_MASK >> iconMaskTzc) == 0xFF); + + GenTreeFlags flags = (GenTreeFlags)(m_encodedIconFlags << iconMaskTzc); assert((flags & ~GTF_ICON_HDL_MASK) == 0); - static_assert_no_msg((0xFF000000 == GTF_ICON_HDL_MASK) && (GTF_ICON_HDL_MASK >> 24) == 0xFF); return flags; } void SetIconFlag(GenTreeFlags flags, FieldSeq* fieldSeq = nullptr) { + const int iconMaskTzc = 24; assert((flags & ~GTF_ICON_HDL_MASK) == 0); - encodedIconFlags = flags >> 24; - u1.fieldSeq = fieldSeq; + m_encodedIconFlags = flags >> iconMaskTzc; + u1.fieldSeq = fieldSeq; } } op2; diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 2776b1e71975d9..84adbf3bdf7e23 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -17625,11 +17625,8 @@ bool GenTree::IsFieldAddr(Compiler* comp, GenTree** pBaseAddr, FieldSeq** pFldSe if ((fldSeq != nullptr) && (fldSeq->GetKind() == FieldSeq::FieldKind::SimpleStaticKnownAddress)) { - if (!baseAddr->IsIntegralConst(0)) - { - // Bail-out, base has to be zero if fldSeq represents a known address (not a small offset) - return false; - } + // fldSeq represents a known address (not a small offset) - bail out. + return false; } } else @@ -17639,9 +17636,9 @@ bool GenTree::IsFieldAddr(Compiler* comp, GenTree** pBaseAddr, FieldSeq** pFldSe } else if (IsIconHandle(GTF_ICON_STATIC_HDL)) { - baseAddr = this; - fldSeq = AsIntCon()->gtFieldSeq; - offset = AsIntCon()->IconValue(); + fldSeq = AsIntCon()->gtFieldSeq; + offset = AsIntCon()->IconValue(); + assert((fldSeq == nullptr) || (fldSeq->GetKind() == FieldSeq::FieldKind::SimpleStaticKnownAddress)); } else { diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 560b7fa8745136..e1e08d6b0972bd 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -4381,18 +4381,16 @@ GenTree* Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedT } else { - bool hasConstAddr = (pFieldInfo->fieldAccessor == CORINFO_FIELD_STATIC_ADDRESS) || + bool hasKnownAddr = (pFieldInfo->fieldAccessor == CORINFO_FIELD_STATIC_ADDRESS) || (pFieldInfo->fieldAccessor == CORINFO_FIELD_STATIC_RVA_ADDRESS); ssize_t offset; - if (hasConstAddr) + if (hasKnownAddr) { - if (!isSharedStatic) - { - // Change SharedStatic to SimpleStaticKnownAddress - assert(fieldKind == FieldSeq::FieldKind::SimpleStatic); - fieldKind = FieldSeq::FieldKind::SimpleStaticKnownAddress; - } + // Change SimpleStatic to SimpleStaticKnownAddress + assert(fieldKind == FieldSeq::FieldKind::SimpleStatic); + fieldKind = FieldSeq::FieldKind::SimpleStaticKnownAddress; + offset = reinterpret_cast(info.compCompHnd->getFieldAddress(pResolvedToken->hField)); assert(offset != 0); } From a7d0b2cec6b5dc7450bd01ce8e48a42bd97e72ff Mon Sep 17 00:00:00 2001 From: EgorBo Date: Wed, 23 Nov 2022 03:29:49 +0100 Subject: [PATCH 7/8] fix build --- src/coreclr/jit/compiler.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index e8da6b72a00340..03d9f2b1564fe8 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7124,7 +7124,7 @@ class Compiler GenTreeFlags GetIconFlag() { // number of trailing zeros in GTF_ICON_HDL_MASK - const int iconMaskTzc = 24; + const uint16_t iconMaskTzc = 24; static_assert_no_msg((0xFF000000 == GTF_ICON_HDL_MASK) && (GTF_ICON_HDL_MASK >> iconMaskTzc) == 0xFF); GenTreeFlags flags = (GenTreeFlags)(m_encodedIconFlags << iconMaskTzc); @@ -7133,7 +7133,7 @@ class Compiler } void SetIconFlag(GenTreeFlags flags, FieldSeq* fieldSeq = nullptr) { - const int iconMaskTzc = 24; + const uint16_t iconMaskTzc = 24; assert((flags & ~GTF_ICON_HDL_MASK) == 0); m_encodedIconFlags = flags >> iconMaskTzc; u1.fieldSeq = fieldSeq; From 903b55ca8a3184c3c78130456a01e2c41a10dffc Mon Sep 17 00:00:00 2001 From: EgorBo Date: Wed, 23 Nov 2022 09:48:18 +0100 Subject: [PATCH 8/8] fix assert --- src/coreclr/jit/gentree.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 84adbf3bdf7e23..d1f80d8220cc60 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -17645,8 +17645,6 @@ bool GenTree::IsFieldAddr(Compiler* comp, GenTree** pBaseAddr, FieldSeq** pFldSe return false; } - assert(baseAddr != nullptr); - if (fldSeq == nullptr) { return false;