Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JIT: Generalize assignment decomposition in physical promotion #85323

Merged
merged 43 commits into from
May 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
52c1022
JIT: Generalize assignment decomposition in physical promotion
jakobbotsch Apr 25, 2023
09db21e
Handle no promoted field
jakobbotsch Apr 25, 2023
813fa83
Add test for no promoted field
jakobbotsch Apr 25, 2023
5a372af
Source may no longer be dying
jakobbotsch Apr 25, 2023
5e54863
Fix a possible out of bounds in OverlappingReplacements
jakobbotsch Apr 25, 2023
22aa3f7
Remove leftover code
jakobbotsch Apr 25, 2023
87e55d6
Handle that source replacements may need a read back
jakobbotsch Apr 25, 2023
70defdc
Always read back partially overlapping destination
jakobbotsch Apr 25, 2023
fc2e53a
JIT: Change GTF_ICON_INITCLASS -> GTF_IND_INITCLASS
jakobbotsch Apr 26, 2023
2b7440a
Propagate indir flags
jakobbotsch Apr 26, 2023
05c848c
More correct propagation of flags
jakobbotsch Apr 26, 2023
58c9d82
Rename scenarios
jakobbotsch Apr 26, 2023
5981e5e
Merge branch 'main' of github.com:dotnet/runtime into more-general-de…
jakobbotsch Apr 26, 2023
043df46
Do struct op last when possible
jakobbotsch Apr 27, 2023
9aed5e5
Merge branch 'main' of github.com:dotnet/runtime into more-general-de…
jakobbotsch Apr 27, 2023
33b899b
Add an assert, fix a comment
jakobbotsch Apr 27, 2023
3b0d92e
Handle remainders
jakobbotsch Apr 27, 2023
63ec4fb
Add logging, add docs, generalize to initialization
jakobbotsch Apr 28, 2023
6c12a74
Run jit-format
jakobbotsch Apr 28, 2023
fb9af8d
Merge branch 'main' of github.com:dotnet/runtime into more-general-de…
jakobbotsch Apr 28, 2023
1eef1d9
Fix
jakobbotsch Apr 28, 2023
9578acd
Move some logging statements
jakobbotsch Apr 28, 2023
be5b809
Add missing address base offset for primitive remainder
jakobbotsch Apr 28, 2023
d84ecf0
Switch to decimal offsets
jakobbotsch Apr 29, 2023
d882e09
Avoid unnecessary write barriers, some cleanup
jakobbotsch Apr 29, 2023
4186c51
Merge branch 'main' of github.com:dotnet/runtime into more-general-de…
jakobbotsch May 2, 2023
6d46dd2
Enhance some logging
jakobbotsch May 2, 2023
d252517
Allow DCE of partial defs
jakobbotsch May 1, 2023
2afbf82
Hack for regex case
jakobbotsch May 2, 2023
846ce0d
Revert "Hack for regex case"
jakobbotsch May 2, 2023
0a9481e
Revert "Allow DCE of partial defs"
jakobbotsch May 2, 2023
5ad9291
Nest some classes to see if it makes github diff work properly
jakobbotsch May 3, 2023
c7254bf
What if I remove this
jakobbotsch May 3, 2023
6f782dd
Extract to a new file
jakobbotsch May 3, 2023
0888806
A few fixes
jakobbotsch May 3, 2023
9641dbe
Remove unnecessary change with GT_FIELD removal
jakobbotsch May 3, 2023
7d96e83
Merge branch 'main' of github.com:dotnet/runtime into more-general-de…
jakobbotsch May 3, 2023
bd2021d
Fix after merge
jakobbotsch May 3, 2023
5929d19
Merge branch 'main' of github.com:dotnet/runtime into more-general-de…
jakobbotsch May 4, 2023
39428e4
Fix after merge
jakobbotsch May 4, 2023
c7a9f8d
Clean up a bit
jakobbotsch May 4, 2023
b346598
Address feedback; factor some code
jakobbotsch May 5, 2023
d431901
Fix bad factoring
jakobbotsch May 5, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -2510,6 +2510,8 @@ class Compiler

GenTree* gtNewOneConNode(var_types type, var_types simdBaseType = TYP_UNDEF);

GenTree* gtNewConWithPattern(var_types type, uint8_t pattern);

GenTreeLclVar* gtNewStoreLclVarNode(unsigned lclNum, GenTree* data);

GenTreeLclFld* gtNewStoreLclFldNode(unsigned lclNum, var_types type, unsigned offset, GenTree* data);
Expand Down Expand Up @@ -6164,8 +6166,10 @@ class Compiler
bool gtTreeContainsOper(GenTree* tree, genTreeOps op);
ExceptionSetFlags gtCollectExceptions(GenTree* tree);

public:
bool fgIsBigOffset(size_t offset);

private:
bool fgNeedReturnSpillTemp();

/*
Expand Down
65 changes: 65 additions & 0 deletions src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7684,6 +7684,71 @@ GenTree* Compiler::gtNewOneConNode(var_types type, var_types simdBaseType /* = T
}
}

//------------------------------------------------------------------------
// CreateInitValue:
// Create an IR node representing a constant value with the specified 8
// byte character broadcast into all of its bytes.
//
// Parameters:
// type - The primitive type. For small types the constant will be
// zero/sign-extended and a TYP_INT node will be returned.
// pattern - A byte pattern.
//
// Returns:
// An IR node representing the constant.
//
// Remarks:
// Should only be called when that pattern can actually be represented; for
// example, GC pointers only support an init pattern of zero.
//
GenTree* Compiler::gtNewConWithPattern(var_types type, uint8_t pattern)
{
switch (type)
{
case TYP_BOOL:
case TYP_UBYTE:
return gtNewIconNode(pattern);
case TYP_BYTE:
return gtNewIconNode((int8_t)pattern);
case TYP_SHORT:
return gtNewIconNode((int16_t)(pattern * 0x0101));
case TYP_USHORT:
return gtNewIconNode((uint16_t)(pattern * 0x0101));
case TYP_INT:
return gtNewIconNode(pattern * 0x01010101);
case TYP_LONG:
return gtNewLconNode(pattern * 0x0101010101010101LL);
case TYP_FLOAT:
float floatPattern;
memset(&floatPattern, pattern, sizeof(floatPattern));
return gtNewDconNode(floatPattern, TYP_FLOAT);
case TYP_DOUBLE:
double doublePattern;
memset(&doublePattern, pattern, sizeof(doublePattern));
return gtNewDconNode(doublePattern);
case TYP_REF:
case TYP_BYREF:
assert(pattern == 0);
return gtNewZeroConNode(type);
#ifdef FEATURE_SIMD
case TYP_SIMD8:
case TYP_SIMD12:
case TYP_SIMD16:
#if defined(TARGET_XARCH)
case TYP_SIMD32:
case TYP_SIMD64:
#endif // TARGET_XARCH
#endif // FEATURE_SIMD
{
GenTreeVecCon* node = gtNewVconNode(type);
memset(&node->gtSimdVal, pattern, sizeof(node->gtSimdVal));
return node;
}
default:
unreached();
}
}

GenTreeLclVar* Compiler::gtNewStoreLclVarNode(unsigned lclNum, GenTree* data)
{
LclVarDsc* varDsc = lvaGetDesc(lclNum);
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/jitstd/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,7 @@ typename vector<T, Allocator>::iterator
assert(last.m_pElem >= m_pArray);
assert(first.m_pElem <= m_pArray + m_nSize);
assert(last.m_pElem <= m_pArray + m_nSize);
assert(last.m_pElem > first.m_pElem);
assert(last.m_pElem >= first.m_pElem);

pointer fptr = first.m_pElem;
pointer lptr = last.m_pElem;
Expand Down
66 changes: 6 additions & 60 deletions src/coreclr/jit/morphblock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,22 +410,19 @@ void MorphInitBlockHelper::TryInitFieldByField()
return;
}

const int64_t initPattern = (initVal->AsIntCon()->IconValue() & 0xFF) * 0x0101010101010101LL;
const uint8_t initPattern = (uint8_t)(initVal->AsIntCon()->IconValue() & 0xFF);

if (initPattern != 0)
{
for (unsigned i = 0; i < destLclVar->lvFieldCnt; ++i)
{
LclVarDsc* fieldDesc = m_comp->lvaGetDesc(destLclVar->lvFieldLclStart + i);

if (varTypeIsSIMD(fieldDesc) || varTypeIsGC(fieldDesc))
if (varTypeIsGC(fieldDesc))
{
// Cannot initialize GC or SIMD types with a non-zero constant.
// The former is completely bogus. The later restriction could be
// lifted by supporting non-zero SIMD constants or by generating
// field initialization code that converts an integer constant to
// the appropriate SIMD value. Unlikely to be very useful, though.
JITDUMP(" dest contains GC and/or SIMD fields and source constant is not 0.\n");
// Cannot initialize GC types with a non-zero constant. The
// former is completely bogus.
JITDUMP(" dest contains GC fields and source constant is not 0.\n");
return;
}
}
Expand All @@ -448,58 +445,7 @@ void MorphInitBlockHelper::TryInitFieldByField()
LclVarDsc* fieldDesc = m_comp->lvaGetDesc(fieldLclNum);
var_types fieldType = fieldDesc->TypeGet();

GenTree* src;
switch (fieldType)
{
case TYP_BOOL:
case TYP_BYTE:
case TYP_UBYTE:
case TYP_SHORT:
case TYP_USHORT:
// Promoted fields are expected to be "normalize on load". If that changes then
// we may need to adjust this code to widen the constant correctly.
assert(fieldDesc->lvNormalizeOnLoad());
FALLTHROUGH;
case TYP_INT:
{
int64_t mask = (int64_t(1) << (genTypeSize(fieldType) * 8)) - 1;
src = m_comp->gtNewIconNode(static_cast<int32_t>(initPattern & mask));
break;
}
case TYP_LONG:
src = m_comp->gtNewLconNode(initPattern);
break;
case TYP_FLOAT:
float floatPattern;
memcpy(&floatPattern, &initPattern, sizeof(floatPattern));
src = m_comp->gtNewDconNode(floatPattern, TYP_FLOAT);
break;
case TYP_DOUBLE:
double doublePattern;
memcpy(&doublePattern, &initPattern, sizeof(doublePattern));
src = m_comp->gtNewDconNode(doublePattern);
break;
case TYP_REF:
case TYP_BYREF:
#ifdef FEATURE_SIMD
case TYP_SIMD8:
case TYP_SIMD12:
case TYP_SIMD16:
#if defined(TARGET_XARCH)
case TYP_SIMD32:
case TYP_SIMD64:
#endif // TARGET_XARCH
#endif // FEATURE_SIMD
{
assert(initPattern == 0);
src = m_comp->gtNewZeroConNode(fieldType);
break;
}

default:
unreached();
}

GenTree* src = m_comp->gtNewConWithPattern(fieldType, initPattern);
GenTree* store = m_comp->gtNewTempAssign(fieldLclNum, src);

if (m_comp->optLocalAssertionProp)
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/jit/promotion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ bool Replacement::Overlaps(unsigned otherStart, unsigned otherSize) const
// LCL_VAR int V01
//
// Parameters:
// compiler - Compiler instance
// compiler - Compiler instance
// structLclNum - Struct local
// replacement - Information about the replacement
//
Expand All @@ -651,7 +651,7 @@ GenTree* Promotion::CreateWriteBack(Compiler* compiler, unsigned structLclNum, c
// LCL_FLD int V00 [+4]
//
// Parameters:
// compiler - Compiler instance
// compiler - Compiler instance
// structLclNum - Struct local
// replacement - Information about the replacement
//
Expand Down
25 changes: 12 additions & 13 deletions src/coreclr/jit/promotion.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ struct Replacement
// a basic block, i.e. all predecessors would have read the replacement
// back before transferring control if necessary.
bool NeedsReadBack = false;
// Arbitrary flag bit used e.g. by decomposition. Assumed to be false.
bool Handled = false;
#ifdef DEBUG
const char* Description;
#endif
Expand All @@ -46,6 +44,8 @@ class Promotion
friend class LocalUses;
friend class LocalsUseVisitor;
friend class ReplaceVisitor;
friend class DecompositionPlan;
friend class StructSegments;

void InsertInitialReadBack(unsigned lclNum, const jitstd::vector<Replacement>& replacements, Statement** prevStmt);
void ExplicitlyZeroInitReplacementLocals(unsigned lclNum,
Expand Down Expand Up @@ -107,6 +107,7 @@ class Promotion
};

class DecompositionStatementList;
class DecompositionPlan;

class ReplaceVisitor : public GenTreeVisitor<ReplaceVisitor>
{
Expand Down Expand Up @@ -150,17 +151,15 @@ class ReplaceVisitor : public GenTreeVisitor<ReplaceVisitor>
Replacement** firstReplacement,
Replacement** endReplacement = nullptr);
void EliminateCommasInBlockOp(GenTreeOp* asg, DecompositionStatementList* result);
void UpdateEarlyRefCount(GenTree* candidate);
void IncrementRefCount(unsigned lclNum);
void InitFieldByField(Replacement* firstRep,
Replacement* endRep,
unsigned char initVal,
DecompositionStatementList* result);
void CopyIntoFields(Replacement* firstRep,
Replacement* endRep,
GenTreeLclVarCommon* dst,
GenTree* src,
DecompositionStatementList* result);
void InitFields(GenTreeLclVarCommon* dst, Replacement* firstRep, Replacement* endRep, DecompositionPlan* plan);
void CopyBetweenFields(GenTree* dst,
Replacement* dstFirstRep,
Replacement* dstEndRep,
GenTree* src,
Replacement* srcFirstRep,
Replacement* srcEndRep,
DecompositionStatementList* statements,
DecompositionPlan* plan);
};

#endif
Loading