Skip to content

Commit

Permalink
Improve struct inits. (#52292)
Browse files Browse the repository at this point in the history
* Support STORE_LCL_VAR(0) after lowering.

* fix a nice catch from Tanner
  • Loading branch information
Sergey Andreenko committed May 8, 2021
1 parent b9ac0e3 commit d0b9864
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 46 deletions.
17 changes: 3 additions & 14 deletions src/coreclr/jit/codegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3846,20 +3846,9 @@ void CodeGen::genEmitHelperCall(unsigned helper, int argSize, emitAttr retSize,
void CodeGen::genSIMDIntrinsic(GenTreeSIMD* simdNode)
{
// NYI for unsupported base types
if (simdNode->GetSimdBaseType() != TYP_INT && simdNode->GetSimdBaseType() != TYP_LONG &&
simdNode->GetSimdBaseType() != TYP_FLOAT && simdNode->GetSimdBaseType() != TYP_DOUBLE &&
simdNode->GetSimdBaseType() != TYP_USHORT && simdNode->GetSimdBaseType() != TYP_UBYTE &&
simdNode->GetSimdBaseType() != TYP_SHORT && simdNode->GetSimdBaseType() != TYP_BYTE &&
simdNode->GetSimdBaseType() != TYP_UINT && simdNode->GetSimdBaseType() != TYP_ULONG)
{
// We don't need a base type for the Upper Save & Restore intrinsics, and we may find
// these implemented over lclVars created by CSE without full handle information (and
// therefore potentially without a base type).
if ((simdNode->gtSIMDIntrinsicID != SIMDIntrinsicUpperSave) &&
(simdNode->gtSIMDIntrinsicID != SIMDIntrinsicUpperRestore))
{
noway_assert(!"SIMD intrinsic with unsupported base type.");
}
if (!varTypeIsArithmetic(simdNode->GetSimdBaseType()))
{
noway_assert(!"SIMD intrinsic with unsupported base type.");
}

switch (simdNode->gtSIMDIntrinsicID)
Expand Down
30 changes: 15 additions & 15 deletions src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -1688,10 +1688,10 @@ struct GenTree
bool IsValidCallArgument();
#endif // DEBUG

inline bool IsFPZero();
inline bool IsIntegralConst(ssize_t constVal);
inline bool IsIntegralConstVector(ssize_t constVal);
inline bool IsSIMDZero();
inline bool IsFPZero() const;
inline bool IsIntegralConst(ssize_t constVal) const;
inline bool IsIntegralConstVector(ssize_t constVal) const;
inline bool IsSIMDZero() const;

inline bool IsBoxedValue();

Expand Down Expand Up @@ -2922,11 +2922,11 @@ struct GenTreeVal : public GenTree

struct GenTreeIntConCommon : public GenTree
{
inline INT64 LngValue();
inline INT64 LngValue() const;
inline void SetLngValue(INT64 val);
inline ssize_t IconValue();
inline ssize_t IconValue() const;
inline void SetIconValue(ssize_t val);
inline INT64 IntegralValue();
inline INT64 IntegralValue() const;

GenTreeIntConCommon(genTreeOps oper, var_types type DEBUGARG(bool largeNode = false))
: GenTree(oper, type DEBUGARG(largeNode))
Expand Down Expand Up @@ -3090,7 +3090,7 @@ struct GenTreeLngCon : public GenTreeIntConCommon
#endif
};

inline INT64 GenTreeIntConCommon::LngValue()
inline INT64 GenTreeIntConCommon::LngValue() const
{
#ifndef TARGET_64BIT
assert(gtOper == GT_CNS_LNG);
Expand All @@ -3114,7 +3114,7 @@ inline void GenTreeIntConCommon::SetLngValue(INT64 val)
#endif
}

inline ssize_t GenTreeIntConCommon::IconValue()
inline ssize_t GenTreeIntConCommon::IconValue() const
{
assert(gtOper == GT_CNS_INT); // We should never see a GT_CNS_LNG for a 64-bit target!
return AsIntCon()->gtIconVal;
Expand All @@ -3126,7 +3126,7 @@ inline void GenTreeIntConCommon::SetIconValue(ssize_t val)
AsIntCon()->gtIconVal = val;
}

inline INT64 GenTreeIntConCommon::IntegralValue()
inline INT64 GenTreeIntConCommon::IntegralValue() const
{
#ifdef TARGET_64BIT
return LngValue();
Expand Down Expand Up @@ -6942,7 +6942,7 @@ inline bool GenTree::OperIsCopyBlkOp()
// Return Value:
// Returns true iff the tree is an GT_CNS_DBL, with value of 0.0.

inline bool GenTree::IsFPZero()
inline bool GenTree::IsFPZero() const
{
if ((gtOper == GT_CNS_DBL) && (AsDblCon()->gtDconVal == 0.0))
{
Expand All @@ -6965,7 +6965,7 @@ inline bool GenTree::IsFPZero()
// Like gtIconVal, the argument is of ssize_t, so cannot check for
// long constants in a target-independent way.

inline bool GenTree::IsIntegralConst(ssize_t constVal)
inline bool GenTree::IsIntegralConst(ssize_t constVal) const

{
if ((gtOper == GT_CNS_INT) && (AsIntConCommon()->IconValue() == constVal))
Expand All @@ -6991,7 +6991,7 @@ inline bool GenTree::IsIntegralConst(ssize_t constVal)
// Returns:
// True if this represents an integral const SIMD vector.
//
inline bool GenTree::IsIntegralConstVector(ssize_t constVal)
inline bool GenTree::IsIntegralConstVector(ssize_t constVal) const
{
#ifdef FEATURE_SIMD
// SIMDIntrinsicInit intrinsic with a const value as initializer
Expand All @@ -7008,7 +7008,7 @@ inline bool GenTree::IsIntegralConstVector(ssize_t constVal)
#ifdef FEATURE_HW_INTRINSICS
if (gtOper == GT_HWINTRINSIC)
{
GenTreeHWIntrinsic* node = AsHWIntrinsic();
const GenTreeHWIntrinsic* node = AsHWIntrinsic();

if (!varTypeIsIntegral(node->GetSimdBaseType()))
{
Expand Down Expand Up @@ -7058,7 +7058,7 @@ inline bool GenTree::IsIntegralConstVector(ssize_t constVal)
// Returns:
// True if this represents an integral const SIMD vector.
//
inline bool GenTree::IsSIMDZero()
inline bool GenTree::IsSIMDZero() const
{
#ifdef FEATURE_SIMD
if ((gtOper == GT_SIMD) && (AsSIMD()->gtSIMDIntrinsicID == SIMDIntrinsicInit))
Expand Down
45 changes: 44 additions & 1 deletion src/coreclr/jit/lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3120,6 +3120,7 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore)
}
if ((lclStore->TypeGet() == TYP_STRUCT) && !srcIsMultiReg && (src->OperGet() != GT_PHI))
{
bool convertToStoreObj;
if (src->OperGet() == GT_CALL)
{
GenTreeCall* call = src->AsCall();
Expand Down Expand Up @@ -3165,8 +3166,50 @@ void Lowering::LowerStoreLocCommon(GenTreeLclVarCommon* lclStore)
return;
}
#endif // !WINDOWS_AMD64_ABI
convertToStoreObj = false;
}
else if (!src->OperIs(GT_LCL_VAR) || (varDsc->GetLayout()->GetRegisterType() == TYP_UNDEF))
else if (!varDsc->IsEnregisterable())
{
convertToStoreObj = true;
}
else if (src->OperIs(GT_CNS_INT))
{
assert(src->IsIntegralConst(0) && "expected an INIT_VAL for non-zero init.");
var_types regType = varDsc->GetRegisterType();
#ifdef FEATURE_SIMD
if (varTypeIsSIMD(regType))
{
CorInfoType simdBaseJitType = comp->getBaseJitTypeOfSIMDLocal(lclStore);
if (simdBaseJitType == CORINFO_TYPE_UNDEF)
{
// Lie about the type if we don't know/have it.
simdBaseJitType = CORINFO_TYPE_FLOAT;
}
GenTreeSIMD* simdTree =
comp->gtNewSIMDNode(regType, src, SIMDIntrinsicInit, simdBaseJitType, varDsc->lvExactSize);
BlockRange().InsertAfter(src, simdTree);
LowerSIMD(simdTree);
src = simdTree;
lclStore->gtOp1 = src;
convertToStoreObj = false;
}
else
#endif // FEATURE_SIMD
{
convertToStoreObj = false;
}
}
else if (!src->OperIs(GT_LCL_VAR))
{
convertToStoreObj = true;
}
else
{
assert(src->OperIs(GT_LCL_VAR));
convertToStoreObj = false;
}

if (convertToStoreObj)
{
GenTreeLclVar* addr = comp->gtNewLclVarAddrNode(lclStore->GetLclNum(), TYP_BYREF);

Expand Down
24 changes: 13 additions & 11 deletions src/coreclr/jit/rationalize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,23 +398,25 @@ void Rationalizer::RewriteAssignment(LIR::Use& use)
#ifdef FEATURE_SIMD
if (varTypeIsSIMD(location) && assignment->OperIsInitBlkOp())
{
if (location->OperGet() == GT_LCL_VAR)
if (location->OperIs(GT_LCL_VAR))
{
var_types simdType = location->TypeGet();
GenTree* initVal = assignment->AsOp()->gtOp2;
CorInfoType simdBaseJitType = comp->getBaseJitTypeOfSIMDLocal(location);
if (simdBaseJitType != CORINFO_TYPE_UNDEF)
if (simdBaseJitType == CORINFO_TYPE_UNDEF)
{
GenTreeSIMD* simdTree = new (comp, GT_SIMD)
GenTreeSIMD(simdType, initVal, SIMDIntrinsicInit, simdBaseJitType, genTypeSize(simdType));
assignment->AsOp()->gtOp2 = simdTree;
value = simdTree;
initVal->gtNext = simdTree;
simdTree->gtPrev = initVal;

simdTree->gtNext = location;
location->gtPrev = simdTree;
// Lie about the type if we don't know/have it.
simdBaseJitType = CORINFO_TYPE_FLOAT;
}
GenTreeSIMD* simdTree =
comp->gtNewSIMDNode(simdType, initVal, SIMDIntrinsicInit, simdBaseJitType, genTypeSize(simdType));
assignment->AsOp()->gtOp2 = simdTree;
value = simdTree;
initVal->gtNext = simdTree;
simdTree->gtPrev = initVal;

simdTree->gtNext = location;
location->gtPrev = simdTree;
}
}
#endif // FEATURE_SIMD
Expand Down
6 changes: 1 addition & 5 deletions src/coreclr/jit/simdcodegenxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2353,11 +2353,7 @@ void CodeGen::genSIMDIntrinsicUpperRestore(GenTreeSIMD* simdNode)
void CodeGen::genSIMDIntrinsic(GenTreeSIMD* simdNode)
{
// NYI for unsupported base types
if (simdNode->GetSimdBaseType() != TYP_INT && simdNode->GetSimdBaseType() != TYP_LONG &&
simdNode->GetSimdBaseType() != TYP_FLOAT && simdNode->GetSimdBaseType() != TYP_DOUBLE &&
simdNode->GetSimdBaseType() != TYP_USHORT && simdNode->GetSimdBaseType() != TYP_UBYTE &&
simdNode->GetSimdBaseType() != TYP_SHORT && simdNode->GetSimdBaseType() != TYP_BYTE &&
simdNode->GetSimdBaseType() != TYP_UINT && simdNode->GetSimdBaseType() != TYP_ULONG)
if (!varTypeIsArithmetic(simdNode->GetSimdBaseType()))
{
noway_assert(!"SIMD intrinsic with unsupported base type.");
}
Expand Down

0 comments on commit d0b9864

Please sign in to comment.