Skip to content

Commit e61e022

Browse files
Address TODO-FIELDs and delete quirks (#85735)
* Adjust a comment * Simplify CreateAddressNodeForSimdHWIntrinsicCreate No diffs. * Limit the usages of gtNewFieldIndirNode One tiny regression in a Regex method due to us not clearing GLOB_REF where not needed. * Delete the side effects quirk About neutral in improvements and regressions. Both come from the differences in the handling of unused indirs and NULLCHECK nodes. * Add a convenience gtNewFieldAddrNode overload
1 parent 754d9ec commit e61e022

File tree

7 files changed

+51
-103
lines changed

7 files changed

+51
-103
lines changed

src/coreclr/jit/compiler.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2815,6 +2815,11 @@ class Compiler
28152815
GenTree* obj = nullptr,
28162816
DWORD offset = 0);
28172817

2818+
GenTreeFieldAddr* gtNewFieldAddrNode(CORINFO_FIELD_HANDLE fldHnd, GenTree* obj, unsigned offset)
2819+
{
2820+
return gtNewFieldAddrNode(varTypeIsGC(obj) ? TYP_BYREF : TYP_I_IMPL, fldHnd, obj, offset);
2821+
}
2822+
28182823
GenTreeIndir* gtNewFieldIndirNode(var_types type, ClassLayout* layout, GenTreeFieldAddr* addr);
28192824

28202825
GenTreeIndexAddr* gtNewIndexAddr(GenTree* arrayOp,

src/coreclr/jit/gentree.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16308,17 +16308,6 @@ bool Compiler::gtNodeHasSideEffects(GenTree* tree, GenTreeFlags flags)
1630816308
{
1630916309
return true;
1631016310
}
16311-
16312-
// TODO-FIELD: delete this zero-diff quirk.
16313-
if (tree->OperIsIndir() && tree->AsIndir()->Addr()->OperIs(GT_FIELD_ADDR))
16314-
{
16315-
GenTreeFieldAddr* addr = tree->AsIndir()->Addr()->AsFieldAddr();
16316-
if (addr->IsInstance() && ((addr->gtFlags & GTF_FLD_DEREFERENCED) != 0) &&
16317-
fgAddrCouldBeNull(addr->GetFldObj()))
16318-
{
16319-
return true;
16320-
}
16321-
}
1632216311
}
1632316312

1632416313
// Expressions declared as CSE by (e.g.) hoisting code are considered to have relevant side

src/coreclr/jit/importer.cpp

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,14 +1115,7 @@ GenTree* Compiler::impGetStructAddr(GenTree* structVal, unsigned curLevel, bool
11151115
case GT_IND:
11161116
if (willDeref)
11171117
{
1118-
GenTree* addr = structVal->AsIndir()->Addr();
1119-
if (addr->OperIs(GT_FIELD_ADDR))
1120-
{
1121-
// TODO-FIELD: delete this zero-diff quirk.
1122-
addr->gtFlags &= ~GTF_FLD_DEREFERENCED;
1123-
}
1124-
1125-
return addr;
1118+
return structVal->AsIndir()->Addr();
11261119
}
11271120
break;
11281121

@@ -9157,8 +9150,7 @@ void Compiler::impImportBlockCode(BasicBlock* block)
91579150
obj = impGetStructAddr(obj, CHECK_SPILL_ALL, true);
91589151
}
91599152

9160-
op1 = gtNewFieldAddrNode(varTypeIsGC(obj) ? TYP_BYREF : TYP_I_IMPL, resolvedToken.hField, obj,
9161-
fieldInfo.offset);
9153+
op1 = gtNewFieldAddrNode(resolvedToken.hField, obj, fieldInfo.offset);
91629154

91639155
#ifdef FEATURE_READYTORUN
91649156
if (fieldInfo.fieldAccessor == CORINFO_FIELD_INSTANCE_WITH_BASE)
@@ -9464,8 +9456,7 @@ void Compiler::impImportBlockCode(BasicBlock* block)
94649456
case CORINFO_FIELD_INSTANCE_WITH_BASE:
94659457
#endif
94669458
{
9467-
op1 = gtNewFieldAddrNode(varTypeIsGC(obj) ? TYP_BYREF : TYP_I_IMPL, resolvedToken.hField, obj,
9468-
fieldInfo.offset);
9459+
op1 = gtNewFieldAddrNode(resolvedToken.hField, obj, fieldInfo.offset);
94699460

94709461
#ifdef FEATURE_READYTORUN
94719462
if (fieldInfo.fieldAccessor == CORINFO_FIELD_INSTANCE_WITH_BASE)

src/coreclr/jit/importercalls.cpp

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2897,10 +2897,9 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
28972897
CORINFO_FIELD_HANDLE lengthHnd = info.compCompHnd->getFieldInClass(clsHnd, 1);
28982898
const unsigned lengthOffset = info.compCompHnd->getFieldOffset(lengthHnd);
28992899

2900-
GenTreeFieldAddr* lengthFieldAddr =
2901-
gtNewFieldAddrNode(genActualType(ptrToSpan), lengthHnd, ptrToSpan, lengthOffset);
2900+
GenTreeFieldAddr* lengthFieldAddr = gtNewFieldAddrNode(lengthHnd, ptrToSpan, lengthOffset);
2901+
GenTree* length = gtNewIndir(TYP_INT, lengthFieldAddr);
29022902
lengthFieldAddr->SetIsSpanLength(true);
2903-
GenTree* length = gtNewFieldIndirNode(TYP_INT, nullptr, lengthFieldAddr);
29042903

29052904
GenTree* boundsCheck = new (this, GT_BOUNDS_CHECK) GenTreeBoundsChk(index, length, SCK_RNGCHK_FAIL);
29062905

@@ -2914,12 +2913,11 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
29142913
index = gtNewOperNode(GT_MUL, TYP_I_IMPL, index, sizeofNode);
29152914
}
29162915

2917-
CORINFO_FIELD_HANDLE ptrHnd = info.compCompHnd->getFieldInClass(clsHnd, 0);
2918-
const unsigned ptrOffset = info.compCompHnd->getFieldOffset(ptrHnd);
2919-
GenTreeFieldAddr* dataFieldAddr =
2920-
gtNewFieldAddrNode(genActualType(ptrToSpanClone), ptrHnd, ptrToSpanClone, ptrOffset);
2921-
GenTree* data = gtNewFieldIndirNode(TYP_BYREF, nullptr, dataFieldAddr);
2922-
GenTree* result = gtNewOperNode(GT_ADD, TYP_BYREF, data, index);
2916+
CORINFO_FIELD_HANDLE ptrHnd = info.compCompHnd->getFieldInClass(clsHnd, 0);
2917+
const unsigned ptrOffset = info.compCompHnd->getFieldOffset(ptrHnd);
2918+
GenTreeFieldAddr* dataFieldAddr = gtNewFieldAddrNode(ptrHnd, ptrToSpanClone, ptrOffset);
2919+
GenTree* data = gtNewIndir(TYP_BYREF, dataFieldAddr);
2920+
GenTree* result = gtNewOperNode(GT_ADD, TYP_BYREF, data, index);
29232921

29242922
// Prepare result
29252923
var_types resultType = JITtype2varType(sig->retType);
@@ -2962,10 +2960,9 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
29622960
CORINFO_FIELD_HANDLE lengthHnd = info.compCompHnd->getFieldInClass(clsHnd, 1);
29632961
const unsigned lengthOffset = info.compCompHnd->getFieldOffset(lengthHnd);
29642962

2965-
GenTreeFieldAddr* lengthFieldAddr =
2966-
gtNewFieldAddrNode(genActualType(ptrToSpan), lengthHnd, ptrToSpan, lengthOffset);
2963+
GenTreeFieldAddr* lengthFieldAddr = gtNewFieldAddrNode(lengthHnd, ptrToSpan, lengthOffset);
2964+
GenTree* lengthField = gtNewIndir(TYP_INT, lengthFieldAddr);
29672965
lengthFieldAddr->SetIsSpanLength(true);
2968-
GenTree* lengthField = gtNewFieldIndirNode(TYP_INT, nullptr, lengthFieldAddr);
29692966

29702967
return lengthField;
29712968
}

src/coreclr/jit/importervectorization.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -787,10 +787,10 @@ GenTree* Compiler::impSpanEqualsOrStartsWith(bool startsWith, CORINFO_SIG_INFO*
787787
GenTreeLclVar* spanObjRefLcl = gtNewLclvNode(spanObjRef, TYP_BYREF);
788788
GenTreeLclVar* spanDataTmpLcl = gtNewLclvNode(spanDataTmp, TYP_BYREF);
789789

790-
GenTreeFieldAddr* spanLengthAddr = gtNewFieldAddrNode(TYP_BYREF, lengthHnd, gtClone(spanObjRefLcl), lengthOffset);
791-
GenTree* spanLength = gtNewFieldIndirNode(TYP_INT, nullptr, spanLengthAddr);
792-
GenTreeFieldAddr* spanDataAddr = gtNewFieldAddrNode(TYP_BYREF, pointerHnd, spanObjRefLcl);
793-
GenTree* spanData = gtNewFieldIndirNode(TYP_BYREF, nullptr, spanDataAddr);
790+
GenTreeFieldAddr* spanLengthAddr = gtNewFieldAddrNode(lengthHnd, gtClone(spanObjRefLcl), lengthOffset);
791+
GenTree* spanLength = gtNewIndir(TYP_INT, spanLengthAddr);
792+
GenTreeFieldAddr* spanDataAddr = gtNewFieldAddrNode(pointerHnd, spanObjRefLcl, 0);
793+
GenTree* spanData = gtNewIndir(TYP_BYREF, spanDataAddr);
794794

795795
GenTree* unrolled =
796796
impExpandHalfConstEquals(spanDataTmpLcl, spanLength, false, startsWith, (WCHAR*)str, cnsLength, 0, cmpMode);

src/coreclr/jit/morph.cpp

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4436,20 +4436,12 @@ GenTree* Compiler::fgMorphIndexAddr(GenTreeIndexAddr* indexAddr)
44364436
// If the arrRef or index expressions involves an assignment, a call, or reads from global memory,
44374437
// then we *must* allocate a temporary in which to "localize" those values, to ensure that the
44384438
// same values are used in the bounds check and the actual dereference.
4439-
// Also we allocate the temporary when the expression is sufficiently complex/expensive.
4439+
// Also we allocate the temporary when the expression is sufficiently complex/expensive. We special
4440+
// case some simple nodes for which CQ analysis shows it is a little better to do that here than
4441+
// leaving them to CSE.
44404442
//
4441-
// TODO-FIELD: review below comment.
4443+
// TODO-Bug: GLOB_REF is not yet set for all trees in pre-order morph.
44424444
//
4443-
// Note that if the expression is a GT_FIELD, it has not yet been morphed so its true complexity is
4444-
// not exposed. Without that condition there are cases of local struct fields that were previously,
4445-
// needlessly, marked as GTF_GLOB_REF, and when that was fixed, there were some regressions that
4446-
// were mostly ameliorated by adding this condition.
4447-
//
4448-
// Likewise, allocate a temporary if the expression is a GT_LCL_FLD node. These used to be created
4449-
// after fgMorphIndexAddr from GT_FIELD trees so this preserves the existing behavior. This is
4450-
// perhaps a decision that should be left to CSE but FX diffs show that it is slightly better to
4451-
// do this here. Likewise for implicit byrefs.
4452-
44534445
if (((arrRef->gtFlags & (GTF_ASG | GTF_CALL | GTF_GLOB_REF)) != 0) ||
44544446
gtComplexityExceeds(arrRef, MAX_ARR_COMPLEXITY) || arrRef->OperIs(GT_LCL_FLD) ||
44554447
(arrRef->OperIs(GT_LCL_VAR) && lvaIsLocalImplicitlyAccessedByRef(arrRef->AsLclVar()->GetLclNum())))

src/coreclr/jit/simd.cpp

Lines changed: 26 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -689,69 +689,43 @@ bool Compiler::areArgumentsContiguous(GenTree* op1, GenTree* op2)
689689
GenTree* Compiler::CreateAddressNodeForSimdHWIntrinsicCreate(GenTree* tree, var_types simdBaseType, unsigned simdSize)
690690
{
691691
assert(tree->OperIs(GT_IND));
692-
GenTree* addr = tree->AsIndir()->Addr();
693-
GenTree* byrefNode = nullptr;
694-
unsigned offset = 0;
695-
var_types baseType = tree->gtType;
692+
GenTree* addr = tree->AsIndir()->Addr();
696693

697694
if (addr->OperIs(GT_FIELD_ADDR))
698695
{
699696
assert(addr->AsFieldAddr()->IsInstance());
700697

698+
// If the field is directly from a struct, then in this case, we should set this
699+
// struct's lvUsedInSIMDIntrinsic as true, so that this sturct won't be promoted.
701700
GenTree* objRef = addr->AsFieldAddr()->GetFldObj();
702-
if (objRef->IsLclVarAddr())
701+
if (objRef->IsLclVarAddr() && varTypeIsSIMD(lvaGetDesc(objRef->AsLclFld())))
703702
{
704-
// If the field is directly from a struct, then in this case,
705-
// we should set this struct's lvUsedInSIMDIntrinsic as true,
706-
// so that this sturct won't be promoted.
707-
// e.g. s.x x is a field, and s is a struct, then we should set the s's lvUsedInSIMDIntrinsic as true.
708-
// so that s won't be promoted.
709-
// Notice that if we have a case like s1.s2.x. s1 s2 are struct, and x is a field, then it is possible that
710-
// s1 can be promoted, so that s2 can be promoted. The reason for that is if we don't allow s1 to be
711-
// promoted, then this will affect the other optimizations which are depend on s1's struct promotion.
712-
// TODO-CQ:
713-
// In future, we should optimize this case so that if there is a nested field like s1.s2.x and s1.s2.x's
714-
// address is used for initializing the vector, then s1 can be promoted but s2 can't.
715-
if (varTypeIsSIMD(lvaGetDesc(objRef->AsLclFld())))
716-
{
717-
setLclRelatedToSIMDIntrinsic(objRef);
718-
}
703+
setLclRelatedToSIMDIntrinsic(objRef);
719704
}
720705

721-
// TODO-FIELD: this seems unnecessary. Simply "return addr;"?
722-
byrefNode = gtCloneExpr(objRef);
723-
assert(byrefNode != nullptr);
724-
offset = addr->AsFieldAddr()->gtFldOffset;
725-
}
726-
else
727-
{
728-
GenTree* arrayRef = addr->AsIndexAddr()->Arr();
729-
GenTree* index = addr->AsIndexAddr()->Index();
730-
assert(index->IsCnsIntOrI());
731-
732-
GenTree* checkIndexExpr = nullptr;
733-
unsigned indexVal = (unsigned)index->AsIntCon()->gtIconVal;
734-
offset = indexVal * genTypeSize(tree->TypeGet());
735-
736-
// Generate the boundary check exception.
737-
// The length for boundary check should be the maximum index number which should be
738-
// (first argument's index number) + (how many array arguments we have) - 1
739-
// = indexVal + arrayElementsCount - 1
740-
unsigned arrayElementsCount = simdSize / genTypeSize(simdBaseType);
741-
checkIndexExpr = gtNewIconNode(indexVal + arrayElementsCount - 1);
742-
GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, arrayRef, (int)OFFSETOF__CORINFO_Array__length, compCurBB);
743-
GenTreeBoundsChk* arrBndsChk =
744-
new (this, GT_BOUNDS_CHECK) GenTreeBoundsChk(checkIndexExpr, arrLen, SCK_ARG_RNG_EXCPN);
745-
746-
offset += OFFSETOF__CORINFO_Array__data;
747-
byrefNode = gtNewOperNode(GT_COMMA, arrayRef->TypeGet(), arrBndsChk, gtCloneExpr(arrayRef));
706+
return addr;
748707
}
749708

750-
GenTree* address = byrefNode;
751-
if (offset != 0)
752-
{
753-
address = gtNewOperNode(GT_ADD, TYP_BYREF, address, gtNewIconNode(offset, TYP_I_IMPL));
754-
}
709+
GenTree* arrayRef = addr->AsIndexAddr()->Arr();
710+
GenTree* index = addr->AsIndexAddr()->Index();
711+
assert(index->IsCnsIntOrI());
712+
713+
unsigned indexVal = (unsigned)index->AsIntCon()->gtIconVal;
714+
unsigned offset = indexVal * genTypeSize(tree->TypeGet());
715+
716+
// Generate the boundary check exception.
717+
// The length for boundary check should be the maximum index number which should be
718+
// (first argument's index number) + (how many array arguments we have) - 1 = indexVal + arrayElementsCount - 1
719+
//
720+
unsigned arrayElementsCount = simdSize / genTypeSize(simdBaseType);
721+
GenTree* checkIndexExpr = gtNewIconNode(indexVal + arrayElementsCount - 1);
722+
GenTreeArrLen* arrLen = gtNewArrLen(TYP_INT, arrayRef, (int)OFFSETOF__CORINFO_Array__length, compCurBB);
723+
GenTreeBoundsChk* arrBndsChk =
724+
new (this, GT_BOUNDS_CHECK) GenTreeBoundsChk(checkIndexExpr, arrLen, SCK_ARG_RNG_EXCPN);
725+
726+
offset += OFFSETOF__CORINFO_Array__data;
727+
GenTree* address = gtNewOperNode(GT_COMMA, arrayRef->TypeGet(), arrBndsChk, gtCloneExpr(arrayRef));
728+
address = gtNewOperNode(GT_ADD, TYP_BYREF, address, gtNewIconNode(offset, TYP_I_IMPL));
755729

756730
return address;
757731
}

0 commit comments

Comments
 (0)