Skip to content

Commit 43272d6

Browse files
Delete fgMorphBlockOperand (#77688)
* Stop calling fgMorphBlockOperand * Fix missing NO_CSEs * Simplify * Delete fgMorphBlockOperand
1 parent 3e94fdc commit 43272d6

File tree

3 files changed

+32
-207
lines changed

3 files changed

+32
-207
lines changed

src/coreclr/jit/compiler.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5784,7 +5784,6 @@ class Compiler
57845784
GenTree* fgMorphLeaf(GenTree* tree);
57855785
GenTree* fgMorphOneAsgBlockOp(GenTree* tree);
57865786
GenTree* fgMorphInitBlock(GenTree* tree);
5787-
GenTree* fgMorphBlockOperand(GenTree* tree, var_types asgType, ClassLayout* blockLayout, bool isBlkReqd);
57885787
GenTree* fgMorphCopyBlock(GenTree* tree);
57895788
GenTree* fgMorphStoreDynBlock(GenTreeStoreDynBlk* tree);
57905789
GenTree* fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optAssertionPropDone = nullptr);

src/coreclr/jit/morph.cpp

Lines changed: 6 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -8796,150 +8796,6 @@ GenTree* Compiler::fgMorphOneAsgBlockOp(GenTree* tree)
87968796
return tree;
87978797
}
87988798

8799-
//------------------------------------------------------------------------
8800-
// fgMorphBlockOperand: Canonicalize an operand of a block assignment
8801-
//
8802-
// Arguments:
8803-
// tree - The block operand
8804-
// asgType - The type of the assignment
8805-
// blockLayout - The struct layout of the block (for STRUCT "asgType"s)
8806-
// isBlkReqd - true iff this operand must remain a block node
8807-
//
8808-
// Return Value:
8809-
// Returns the morphed block operand
8810-
//
8811-
// Notes:
8812-
// This does the following:
8813-
// - Ensures that a struct operand is a block node or lclVar.
8814-
// - Ensures that any COMMAs are above ADDR nodes.
8815-
// Although 'tree' WAS an operand of a block assignment, the assignment
8816-
// may have been retyped to be a scalar assignment.
8817-
//
8818-
GenTree* Compiler::fgMorphBlockOperand(GenTree* tree, var_types asgType, ClassLayout* blockLayout, bool isBlkReqd)
8819-
{
8820-
GenTree* effectiveVal = tree->gtEffectiveVal();
8821-
8822-
if (asgType != TYP_STRUCT)
8823-
{
8824-
unsigned blockWidth = genTypeSize(asgType);
8825-
8826-
if (effectiveVal->OperIsIndir())
8827-
{
8828-
if (!isBlkReqd)
8829-
{
8830-
GenTree* addr = effectiveVal->AsIndir()->Addr();
8831-
if ((addr->OperGet() == GT_ADDR) && (addr->gtGetOp1()->TypeGet() == asgType))
8832-
{
8833-
effectiveVal = addr->gtGetOp1();
8834-
}
8835-
else if (effectiveVal->OperIsBlk())
8836-
{
8837-
effectiveVal->SetOper(GT_IND);
8838-
}
8839-
}
8840-
effectiveVal->gtType = asgType;
8841-
}
8842-
else if (effectiveVal->TypeGet() != asgType)
8843-
{
8844-
if (effectiveVal->IsCall())
8845-
{
8846-
#ifdef DEBUG
8847-
GenTreeCall* call = effectiveVal->AsCall();
8848-
assert(call->TypeGet() == TYP_STRUCT);
8849-
assert(blockWidth == info.compCompHnd->getClassSize(call->gtRetClsHnd));
8850-
#endif
8851-
}
8852-
else
8853-
{
8854-
GenTree* addr = gtNewOperNode(GT_ADDR, TYP_BYREF, effectiveVal);
8855-
effectiveVal = gtNewIndir(asgType, addr);
8856-
}
8857-
}
8858-
}
8859-
else
8860-
{
8861-
assert(blockLayout != nullptr);
8862-
8863-
GenTreeIndir* indirTree = nullptr;
8864-
GenTreeLclVarCommon* lclNode = nullptr;
8865-
bool needsIndirection = true;
8866-
8867-
if (effectiveVal->OperIsIndir())
8868-
{
8869-
indirTree = effectiveVal->AsIndir();
8870-
GenTree* addr = effectiveVal->AsIndir()->Addr();
8871-
if ((addr->OperGet() == GT_ADDR) && (addr->gtGetOp1()->OperGet() == GT_LCL_VAR))
8872-
{
8873-
lclNode = addr->gtGetOp1()->AsLclVarCommon();
8874-
}
8875-
}
8876-
else if (effectiveVal->OperGet() == GT_LCL_VAR)
8877-
{
8878-
lclNode = effectiveVal->AsLclVarCommon();
8879-
}
8880-
else if (effectiveVal->OperIs(GT_LCL_FLD))
8881-
{
8882-
needsIndirection = false;
8883-
assert(ClassLayout::AreCompatible(effectiveVal->AsLclFld()->GetLayout(), blockLayout));
8884-
}
8885-
else if (effectiveVal->IsCall())
8886-
{
8887-
needsIndirection = false;
8888-
#ifdef DEBUG
8889-
GenTreeCall* call = effectiveVal->AsCall();
8890-
assert(call->TypeGet() == TYP_STRUCT);
8891-
assert(blockLayout->GetSize() == info.compCompHnd->getClassSize(call->gtRetClsHnd));
8892-
#endif
8893-
}
8894-
#ifdef TARGET_ARM64
8895-
else if (effectiveVal->OperIsHWIntrinsic())
8896-
{
8897-
needsIndirection = false;
8898-
#ifdef DEBUG
8899-
GenTreeHWIntrinsic* intrinsic = effectiveVal->AsHWIntrinsic();
8900-
assert(intrinsic->TypeGet() == TYP_STRUCT);
8901-
assert(HWIntrinsicInfo::IsMultiReg(intrinsic->GetHWIntrinsicId()));
8902-
#endif
8903-
}
8904-
#endif // TARGET_ARM64
8905-
8906-
if (lclNode != nullptr)
8907-
{
8908-
const LclVarDsc* varDsc = lvaGetDesc(lclNode);
8909-
if (varTypeIsStruct(varDsc) && ClassLayout::AreCompatible(varDsc->GetLayout(), blockLayout))
8910-
{
8911-
if (effectiveVal != lclNode)
8912-
{
8913-
JITDUMP("Replacing block node [%06d] with lclVar V%02u\n", dspTreeID(tree), lclNode->GetLclNum());
8914-
effectiveVal = lclNode;
8915-
}
8916-
needsIndirection = false;
8917-
}
8918-
else
8919-
{
8920-
// This may be a lclVar that was determined to be address-exposed.
8921-
effectiveVal->gtFlags |= (lclNode->gtFlags & GTF_ALL_EFFECT);
8922-
}
8923-
}
8924-
8925-
if (needsIndirection)
8926-
{
8927-
if ((indirTree != nullptr) && (indirTree->OperIsBlk() || !isBlkReqd))
8928-
{
8929-
effectiveVal->gtType = asgType;
8930-
}
8931-
else
8932-
{
8933-
effectiveVal = gtNewStructVal(blockLayout, gtNewOperNode(GT_ADDR, TYP_BYREF, effectiveVal));
8934-
gtUpdateNodeSideEffects(effectiveVal);
8935-
}
8936-
}
8937-
}
8938-
8939-
assert(effectiveVal->TypeIs(asgType) || (varTypeIsSIMD(asgType) && varTypeIsStruct(effectiveVal)));
8940-
return effectiveVal;
8941-
}
8942-
89438799
#ifdef FEATURE_SIMD
89448800

89458801
//--------------------------------------------------------------------------------------------------------------
@@ -9365,19 +9221,12 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA
93659221
}
93669222
#endif
93679223

9368-
// We can't CSE the LHS of an assignment. Only r-values can be CSEed.
9369-
// Previously, the "lhs" (addr) of a block op was CSE'd. So, to duplicate the former
9370-
// behavior, allow CSE'ing if is a struct type (or a TYP_REF transformed from a struct type)
9371-
// TODO-1stClassStructs: improve this.
9372-
if (op1->IsLocal() || (op1->TypeGet() != TYP_STRUCT))
9373-
{
9374-
op1->gtFlags |= GTF_DONT_CSE;
9375-
}
9224+
// Location nodes cannot be CSEd.
9225+
op1->gtFlags |= GTF_DONT_CSE;
93769226
break;
93779227

93789228
case GT_ADDR:
9379-
9380-
/* op1 of a GT_ADDR is an l-value. Only r-values can be CSEed */
9229+
// Location nodes cannot be CSEd.
93819230
op1->gtFlags |= GTF_DONT_CSE;
93829231
break;
93839232

@@ -10325,17 +10174,11 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA
1032510174
*/
1032610175

1032710176
GenTree* temp;
10328-
GenTree* lclVarTree;
1032910177

1033010178
switch (oper)
1033110179
{
1033210180
case GT_ASG:
10333-
10334-
lclVarTree = fgIsIndirOfAddrOfLocal(op1);
10335-
if (lclVarTree != nullptr)
10336-
{
10337-
lclVarTree->gtFlags |= GTF_VAR_DEF;
10338-
}
10181+
fgAssignSetVarDef(tree);
1033910182

1034010183
if (op2->OperIs(GT_CAST))
1034110184
{
@@ -10347,14 +10190,8 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA
1034710190
op2 = tree->gtGetOp2();
1034810191
}
1034910192

10350-
fgAssignSetVarDef(tree);
10351-
10352-
/* We can't CSE the LHS of an assignment */
10353-
/* We also must set in the pre-morphing phase, otherwise assertionProp doesn't see it */
10354-
if (op1->IsLocal() || (op1->TypeGet() != TYP_STRUCT))
10355-
{
10356-
op1->gtFlags |= GTF_DONT_CSE;
10357-
}
10193+
// Location nodes cannot be CSEd.
10194+
op1->gtFlags |= GTF_DONT_CSE;
1035810195
break;
1035910196

1036010197
case GT_CAST:

src/coreclr/jit/morphblock.cpp

Lines changed: 26 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -357,13 +357,8 @@ void MorphInitBlockHelper::MorphStructCases()
357357

358358
if (m_transformationDecision == BlockTransformation::Undefined)
359359
{
360-
// For an InitBlock we always require a block operand.
361-
m_dst = m_comp->fgMorphBlockOperand(m_dst, m_dst->TypeGet(), m_blockLayout, true /*isBlkReqd*/);
360+
m_result = m_asg;
362361
m_transformationDecision = BlockTransformation::StructBlock;
363-
m_dst->gtFlags |= GTF_DONT_CSE;
364-
m_result = m_asg;
365-
m_result->AsOp()->gtOp1 = m_dst;
366-
m_result->gtFlags |= (m_dst->gtFlags & GTF_ALL_EFFECT);
367362

368363
if (m_dstVarDsc != nullptr)
369364
{
@@ -401,29 +396,20 @@ GenTree* MorphInitBlockHelper::MorphBlock(Compiler* comp, GenTree* tree, bool is
401396
JITDUMP("MorphBlock for %s tree, before:\n", (isDest ? "dst" : "src"));
402397
DISPTREE(tree);
403398

404-
// Src can be a primitive type.
405-
assert(!isDest || varTypeIsStruct(tree));
406-
407-
GenTree* handleTree = nullptr;
408-
GenTree* addr = nullptr;
399+
assert(varTypeIsStruct(tree));
409400

410401
if (tree->OperIs(GT_COMMA))
411402
{
412403
// TODO-Cleanup: this block is not needed for not struct nodes, but
413404
// fgMorphOneAsgBlockOp works wrong without this transformation.
414405
tree = MorphCommaBlock(comp, tree->AsOp());
406+
if (isDest)
407+
{
408+
tree->SetDoNotCSE();
409+
}
415410
}
416411

417-
if (!tree->OperIsBlk())
418-
{
419-
JITDUMP("MorphBlock after:\n");
420-
DISPTREE(tree);
421-
return tree;
422-
}
423-
424-
GenTree* blkAddr = tree->AsBlk()->Addr();
425-
assert(blkAddr != nullptr);
426-
assert(blkAddr->TypeIs(TYP_I_IMPL, TYP_BYREF, TYP_REF));
412+
assert(!tree->OperIsIndir() || varTypeIsI(genActualType(tree->AsIndir()->Addr())));
427413

428414
JITDUMP("MorphBlock after:\n");
429415
DISPTREE(tree);
@@ -833,13 +819,28 @@ void MorphCopyBlockHelper::PrepareSrc()
833819
m_srcVarDsc = m_comp->lvaGetDesc(m_srcLclNum);
834820
}
835821

836-
// Verify that the types on the LHS and RHS match.
822+
// Verify that the types on the LHS and RHS match and morph away "IND<struct>" nodes.
837823
assert(m_dst->TypeGet() == m_src->TypeGet());
838-
// TODO-1stClassStructs: delete the "!IND" condition once "IND<struct>" nodes are no more.
839-
if (m_dst->TypeIs(TYP_STRUCT) && !m_src->OperIs(GT_IND))
824+
if (m_dst->TypeIs(TYP_STRUCT))
840825
{
826+
// TODO-1stClassStructs: delete this once "IND<struct>" nodes are no more.
827+
if (m_src->OperIs(GT_IND))
828+
{
829+
m_src->SetOper(m_blockLayout->IsBlockLayout() ? GT_BLK : GT_OBJ);
830+
m_src->AsBlk()->SetLayout(m_blockLayout);
831+
m_src->AsBlk()->gtBlkOpKind = GenTreeBlk::BlkOpKindInvalid;
832+
#ifndef JIT32_GCENCODER
833+
m_src->AsBlk()->gtBlkOpGcUnsafe = false;
834+
#endif // !JIT32_GCENCODER
835+
}
836+
841837
assert(ClassLayout::AreCompatible(m_blockLayout, m_src->GetLayout(m_comp)));
842838
}
839+
// TODO-1stClassStructs: produce simple "IND<simd>" nodes in importer.
840+
else if (m_src->OperIsBlk())
841+
{
842+
m_src->SetOper(GT_IND);
843+
}
843844
}
844845

845846
// TrySpecialCases: check special cases that require special transformations.
@@ -976,7 +977,7 @@ void MorphCopyBlockHelper::MorphStructCases()
976977
// promotion.
977978
if ((m_srcVarDsc == nullptr) && !m_src->OperIsIndir())
978979
{
979-
JITDUMP(" src is a not an L-value");
980+
JITDUMP(" src is not an L-value");
980981
requiresCopyBlock = true;
981982
}
982983

@@ -1117,18 +1118,6 @@ void MorphCopyBlockHelper::MorphStructCases()
11171118

11181119
if (requiresCopyBlock)
11191120
{
1120-
const var_types asgType = m_dst->TypeGet();
1121-
bool isBlkReqd = (asgType == TYP_STRUCT);
1122-
m_dst = m_comp->fgMorphBlockOperand(m_dst, asgType, m_blockLayout, isBlkReqd);
1123-
m_dst->gtFlags |= GTF_DONT_CSE;
1124-
m_asg->gtOp1 = m_dst;
1125-
1126-
m_src = m_comp->fgMorphBlockOperand(m_src, asgType, m_blockLayout, isBlkReqd);
1127-
m_asg->gtOp2 = m_src;
1128-
1129-
m_asg->SetAllEffectsFlags(m_dst, m_src);
1130-
m_asg->gtFlags |= GTF_ASG;
1131-
11321121
m_result = m_asg;
11331122
m_transformationDecision = BlockTransformation::StructBlock;
11341123
}

0 commit comments

Comments
 (0)