* Support STORE_LCL_VAR(0) after lowering.
* fix a nice catch from Tanner
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)
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();
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))
#endif
};
-inline INT64 GenTreeIntConCommon::LngValue()
+inline INT64 GenTreeIntConCommon::LngValue() const
{
#ifndef TARGET_64BIT
assert(gtOper == GT_CNS_LNG);
#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;
AsIntCon()->gtIconVal = val;
}
-inline INT64 GenTreeIntConCommon::IntegralValue()
+inline INT64 GenTreeIntConCommon::IntegralValue() const
{
#ifdef TARGET_64BIT
return LngValue();
// 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))
{
// 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))
// 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
#ifdef FEATURE_HW_INTRINSICS
if (gtOper == GT_HWINTRINSIC)
{
- GenTreeHWIntrinsic* node = AsHWIntrinsic();
+ const GenTreeHWIntrinsic* node = AsHWIntrinsic();
if (!varTypeIsIntegral(node->GetSimdBaseType()))
{
// 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))
}
if ((lclStore->TypeGet() == TYP_STRUCT) && !srcIsMultiReg && (src->OperGet() != GT_PHI))
{
+ bool convertToStoreObj;
if (src->OperGet() == GT_CALL)
{
GenTreeCall* call = src->AsCall();
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);
#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
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.");
}