GenTree* gtNewSIMDVectorOne(var_types simdType, var_types baseType, unsigned size);
#endif
- GenTree* gtNewBlkOpNode(GenTree* dst, GenTree* srcOrFillVal, unsigned size, bool isVolatile, bool isCopyBlock);
+ GenTree* gtNewBlkOpNode(GenTree* dst, GenTree* srcOrFillVal, bool isVolatile, bool isCopyBlock);
GenTree* gtNewPutArgReg(var_types type, GenTree* arg, regNumber argReg);
void gtBlockOpInit(GenTree* result, GenTree* dst, GenTree* srcOrFillVal, bool isVolatile);
public:
- GenTree* gtNewObjNode(CORINFO_CLASS_HANDLE structHnd, GenTree* addr);
+ GenTreeObj* gtNewObjNode(CORINFO_CLASS_HANDLE structHnd, GenTree* addr);
void gtSetObjGcInfo(GenTreeObj* objNode);
GenTree* gtNewStructVal(CORINFO_CLASS_HANDLE structHnd, GenTree* addr);
GenTree* gtNewBlockVal(GenTree* addr, unsigned size);
GenTree* fgMorphOneAsgBlockOp(GenTree* tree);
GenTree* fgMorphInitBlock(GenTree* tree);
GenTree* fgMorphPromoteLocalInitBlock(GenTreeLclVar* destLclNode, GenTree* initVal, unsigned blockSize);
- GenTree* fgMorphBlkToInd(GenTreeBlk* tree, var_types type);
GenTree* fgMorphGetStructAddr(GenTree** pTree, CORINFO_CLASS_HANDLE clsHnd, bool isRValue = false);
GenTree* fgMorphBlkNode(GenTree* tree, bool isDest);
GenTree* fgMorphBlockOperand(GenTree* tree, var_types asgType, unsigned blockWidth, bool isDest);
if (fgStructTempNeedsExplicitZeroInit(lvaTable + tmpNum, block))
{
- tree = gtNewBlkOpNode(gtNewLclvNode(tmpNum, lclTyp), // Dest
- gtNewIconNode(0), // Value
- info.compCompHnd->getClassSize(structType), // Size
- false, // isVolatile
- false); // not copyBlock
+ tree = gtNewBlkOpNode(gtNewLclvNode(tmpNum, lclTyp), // Dest
+ gtNewIconNode(0), // Value
+ false, // isVolatile
+ false); // not copyBlock
newStmt = gtNewStmt(tree, callILOffset);
fgInsertStmtAfter(block, afterStmt, newStmt);
// Return Value:
// Returns a node representing the struct value at the given address.
//
-// Notes:
-// It will currently return a GT_OBJ node for any struct type, but may
-// return a GT_IND or a non-indirection for a scalar type.
-
-GenTree* Compiler::gtNewObjNode(CORINFO_CLASS_HANDLE structHnd, GenTree* addr)
+GenTreeObj* Compiler::gtNewObjNode(CORINFO_CLASS_HANDLE structHnd, GenTree* addr)
{
var_types nodeType = impNormStructType(structHnd);
assert(varTypeIsStruct(nodeType));
- if (!varTypeIsStruct(nodeType))
- {
- if ((addr->gtOper == GT_ADDR) && (addr->gtGetOp1()->TypeGet() == nodeType))
- {
- return addr->gtGetOp1();
- }
- else
- {
- return gtNewOperNode(GT_IND, nodeType, addr);
- }
- }
-
GenTreeObj* objNode = new (this, GT_OBJ) GenTreeObj(nodeType, addr, typGetObjLayout(structHnd));
// An Obj is not a global reference, if it is known to be a local struct.
{
GenTree* lhs = gtNewStructVal(structHnd, dstAddr);
GenTree* src = nullptr;
- unsigned size;
- if (lhs->OperIsBlk())
+ if (lhs->OperIs(GT_OBJ))
{
- size = lhs->AsBlk()->GetLayout()->GetSize();
- if (lhs->OperGet() == GT_OBJ)
- {
- gtSetObjGcInfo(lhs->AsObj());
- }
- }
- else
- {
- size = genTypeSize(lhs->gtType);
+ gtSetObjGcInfo(lhs->AsObj());
}
if (srcAddr->OperGet() == GT_ADDR)
src = gtNewOperNode(GT_IND, lhs->TypeGet(), srcAddr);
}
- GenTree* result = gtNewBlkOpNode(lhs, src, size, isVolatile, true);
+ GenTree* result = gtNewBlkOpNode(lhs, src, isVolatile, true);
return result;
}
// Arguments:
// dst - Destination or target to copy to / initialize the buffer.
// srcOrFillVall - the size of the buffer to copy/initialize or zero, in the case of CpObj.
-// size - The size of the buffer or a class token (in the case of CpObj).
// isVolatile - Whether this is a volatile memory operation or not.
// isCopyBlock - True if this is a block copy (rather than a block init).
//
// If size is zero, the dst must be a GT_OBJ with the class handle.
// 'dst' must be a block node or lclVar.
//
-GenTree* Compiler::gtNewBlkOpNode(GenTree* dst, GenTree* srcOrFillVal, unsigned size, bool isVolatile, bool isCopyBlock)
+GenTree* Compiler::gtNewBlkOpNode(GenTree* dst, GenTree* srcOrFillVal, bool isVolatile, bool isCopyBlock)
{
assert(dst->OperIsBlk() || dst->OperIsLocal());
if (isCopyBlock)
{
sprintf_s(bufp, sizeof(buf), " %s_ovfl%c", name, 0);
}
- else if (tree->OperIsBlk() && !tree->OperIsDynBlk())
- {
- sprintf_s(bufp, sizeof(buf), " %s(%d)", name, tree->AsBlk()->GetLayout()->GetSize());
- }
else
{
sprintf_s(bufp, sizeof(buf), " %s%c", name, 0);
if (tree->gtOper != GT_CAST)
{
printf(" %-6s", varTypeName(tree->TypeGet()));
+
+ if (varTypeIsStruct(tree->TypeGet()))
+ {
+ ClassLayout* layout = nullptr;
+
+ if (tree->OperIs(GT_BLK, GT_OBJ, GT_STORE_BLK, GT_STORE_OBJ))
+ {
+ layout = tree->AsBlk()->GetLayout();
+ }
+ else if (tree->OperIs(GT_LCL_VAR, GT_STORE_LCL_VAR))
+ {
+ LclVarDsc* varDsc = lvaGetDesc(tree->AsLclVar());
+
+ if (varTypeIsStruct(varDsc->TypeGet()))
+ {
+ layout = varDsc->GetLayout();
+ }
+ }
+
+ if (layout != nullptr)
+ {
+ if (layout->IsBlockLayout())
+ {
+ printf("<%u>", layout->GetSize());
+ }
+ else if (varTypeIsSIMD(tree->TypeGet()))
+ {
+ printf("<%s>", layout->GetClassName());
+ }
+ else
+ {
+ printf("<%s, %u>", layout->GetClassName(), layout->GetSize());
+ }
+ }
+ }
+
if (tree->gtOper == GT_LCL_VAR || tree->gtOper == GT_STORE_LCL_VAR)
{
LclVarDsc* varDsc = &lvaTable[tree->AsLclVarCommon()->GetLclNum()];
printf(" %s <- %s", varTypeName(toType), varTypeName(fromType));
}
- if (tree->gtOper == GT_OBJ && (tree->gtFlags & GTF_VAR_DEATH))
- {
- printf(" (last use)");
- }
if (tree->OperIsBlkOp())
{
if (tree->OperIsCopyBlkOp())
GenTree* opAssign = nullptr;
if (type == TYP_STRUCT)
{
- CORINFO_CLASS_HANDLE clsHnd = varDsc->lvVerTypeInfo.GetClassHandle();
-
// We don't need unsafe value cls check here since we are copying the params and this flag
// would have been set on the original param before reaching here.
- lvaSetStruct(shadowVar, clsHnd, false);
+ lvaSetStruct(shadowVar, varDsc->lvVerTypeInfo.GetClassHandle(), false);
- src = gtNewOperNode(GT_ADDR, TYP_BYREF, src);
- dst = gtNewOperNode(GT_ADDR, TYP_BYREF, dst);
+ opAssign = gtNewBlkOpNode(dst, src, false, true);
- opAssign = gtNewCpObjNode(dst, src, clsHnd, false);
lvaTable[shadowVar].lvIsMultiRegArg = lvaTable[lclNum].lvIsMultiRegArg;
lvaTable[shadowVar].lvIsMultiRegRet = lvaTable[lclNum].lvIsMultiRegRet;
}
GenTree* opAssign = nullptr;
if (varDsc->TypeGet() == TYP_STRUCT)
{
- CORINFO_CLASS_HANDLE clsHnd = varDsc->lvVerTypeInfo.GetClassHandle();
- src = gtNewOperNode(GT_ADDR, TYP_BYREF, src);
- dst = gtNewOperNode(GT_ADDR, TYP_BYREF, dst);
-
- opAssign = gtNewCpObjNode(dst, src, clsHnd, false);
+ opAssign = gtNewBlkOpNode(dst, src, false, true);
}
else
{
dataOffset = eeGetArrayDataOffset(elementType);
}
- GenTree* dst = gtNewOperNode(GT_ADD, TYP_BYREF, arrayLocalNode, gtNewIconNode(dataOffset, TYP_I_IMPL));
- GenTree* blk = gtNewBlockVal(dst, blkSize);
- GenTree* src = gtNewIndOfIconHandleNode(TYP_STRUCT, (size_t)initData, GTF_ICON_STATIC_HDL, false);
-
- return gtNewBlkOpNode(blk, // dst
- src, // src
- blkSize, // size
- false, // volatil
- true); // copyBlock
+ GenTree* dstAddr = gtNewOperNode(GT_ADD, TYP_BYREF, arrayLocalNode, gtNewIconNode(dataOffset, TYP_I_IMPL));
+ GenTree* dst = new (this, GT_BLK) GenTreeBlk(GT_BLK, TYP_STRUCT, dstAddr, typGetBlkLayout(blkSize));
+ GenTree* src = gtNewIndOfIconHandleNode(TYP_STRUCT, (size_t)initData, GTF_ICON_STATIC_HDL, false);
+
+ return gtNewBlkOpNode(dst, // dst
+ src, // src
+ false, // volatile
+ true); // copyBlock
}
//------------------------------------------------------------------------
}
CorInfoType jitTyp = info.compCompHnd->asCorInfoType(resolvedToken.hClass);
- unsigned size = info.compCompHnd->getClassSize(resolvedToken.hClass);
if (impIsPrimitive(jitTyp))
{
newObjThisPtr = gtNewBlkOpNode(newObjThisPtr, // Dest
gtNewIconNode(0), // Value
- size, // Size
false, // isVolatile
false); // not copyBlock
impAppendTree(newObjThisPtr, (unsigned)CHECK_SPILL_NONE, impCurStmtOffs);
op2 = gtNewIconNode(0); // Value
op1 = impPopStack().val; // Dest
op1 = gtNewBlockVal(op1, size);
- op1 = gtNewBlkOpNode(op1, op2, size, (prefixFlags & PREFIX_VOLATILE) != 0, false);
+ op1 = gtNewBlkOpNode(op1, op2, (prefixFlags & PREFIX_VOLATILE) != 0, false);
goto SPILL_APPEND;
case CEE_INITBLK:
op1 = new (this, GT_DYN_BLK) GenTreeDynBlk(op1, op3);
size = 0;
}
- op1 = gtNewBlkOpNode(op1, op2, size, (prefixFlags & PREFIX_VOLATILE) != 0, false);
+ op1 = gtNewBlkOpNode(op1, op2, (prefixFlags & PREFIX_VOLATILE) != 0, false);
goto SPILL_APPEND;
op2 = gtNewOperNode(GT_IND, TYP_STRUCT, op2);
}
- op1 = gtNewBlkOpNode(op1, op2, size, (prefixFlags & PREFIX_VOLATILE) != 0, true);
+ op1 = gtNewBlkOpNode(op1, op2, (prefixFlags & PREFIX_VOLATILE) != 0, true);
goto SPILL_APPEND;
case CEE_CPOBJ:
{
if (argx->OperIs(GT_OBJ))
{
- fgMorphBlkToInd(argx->AsObj(), hfaType);
- }
- else
- {
- argx->gtType = hfaType;
+ argx->SetOper(GT_IND);
}
+
+ argx->gtType = hfaType;
}
}
}
// Copy the valuetype to the temp
- unsigned size = info.compCompHnd->getClassSize(copyBlkClass);
- GenTree* copyBlk = gtNewBlkOpNode(dest, argx, size, false /* not volatile */, true /* copyBlock */);
+ GenTree* copyBlk = gtNewBlkOpNode(dest, argx, false /* not volatile */, true /* copyBlock */);
copyBlk = fgMorphCopyBlock(copyBlk);
#if FEATURE_FIXED_OUT_ARGS
GenTree* tree;
if (varTypeIsStruct(varType))
{
- tree = gtNewBlockVal(ptrArg, varDsc->lvExactSize);
+ tree = new (this, GT_BLK) GenTreeBlk(GT_BLK, TYP_STRUCT, ptrArg, typGetBlkLayout(varDsc->lvExactSize));
}
else
{
{
if (newTree->OperIsBlk() && ((tree->gtFlags & GTF_VAR_DEF) == 0))
{
- fgMorphBlkToInd(newTree->AsBlk(), newTree->gtType);
+ newTree->SetOper(GT_IND);
}
return newTree;
}
{
const bool isVolatile = false;
const bool isCopyBlock = false;
- init = gtNewBlkOpNode(lcl, gtNewIconNode(0), varDsc->lvSize(), isVolatile, isCopyBlock);
- init = fgMorphInitBlock(init);
+ init = gtNewBlkOpNode(lcl, gtNewIconNode(0), isVolatile, isCopyBlock);
+ init = fgMorphInitBlock(init);
}
else
{
{
if (newTree->OperIsBlk() && ((tree->gtFlags & GTF_VAR_DEF) == 0))
{
- fgMorphBlkToInd(newTree->AsBlk(), newTree->gtType);
+ newTree->SetOper(GT_IND);
}
return newTree;
}
return tree;
}
-//------------------------------------------------------------------------
-// fgMorphBlkToInd: Change a blk node into a GT_IND of the specified type
-//
-// Arguments:
-// tree - the node to be modified.
-// type - the type of indirection to change it to.
-//
-// Return Value:
-// Returns the node, modified in place.
-//
-// Notes:
-// This doesn't really warrant a separate method, but is here to abstract
-// the fact that these nodes can be modified in-place.
-
-GenTree* Compiler::fgMorphBlkToInd(GenTreeBlk* tree, var_types type)
-{
- tree->SetOper(GT_IND);
- tree->gtType = type;
- return tree;
-}
-
//------------------------------------------------------------------------
// fgMorphGetStructAddr: Gets the address of a struct object
//
// The pattern is that the COMMA should be the address expression.
// Therefore, we insert a GT_ADDR just above the node, and wrap it in an obj or ind.
// TODO-1stClassStructs: Consider whether this can be improved.
- // Also consider whether some of this can be included in gtNewBlockVal (though note
- // that doing so may cause us to query the type system before we otherwise would).
// Example:
// before: [3] comma struct <- [2] comma struct <- [1] LCL_VAR struct
// after: [3] comma byref <- [2] comma byref <- [4] addr byref <- [1] LCL_VAR struct
else
{
tree = gtNewObjNode(structHnd, addr);
- if (tree->OperGet() == GT_OBJ)
- {
- gtSetObjGcInfo(tree->AsObj());
- }
+ gtSetObjGcInfo(tree->AsObj());
}
}
else
}
else if (effectiveVal->OperIsBlk())
{
- effectiveVal = fgMorphBlkToInd(effectiveVal->AsBlk(), asgType);
+ effectiveVal->SetOper(GT_IND);
}
}
effectiveVal->gtType = asgType;
{
if (indirTree->OperIsBlk() && !isBlkReqd)
{
- (void)fgMorphBlkToInd(effectiveVal->AsBlk(), asgType);
+ effectiveVal->SetOper(GT_IND);
+ effectiveVal->gtType = asgType;
}
else
{
else
{
newTree = gtNewObjNode(clsHnd, addr);
- if (newTree->OperGet() == GT_OBJ)
- {
- gtSetObjGcInfo(newTree->AsObj());
- }
+ gtSetObjGcInfo(newTree->AsObj());
}
}
else
dest = fgMorphBlockOperand(dest, asgType, blockWidth, false /*isBlkReqd*/);
if (dest->OperIsBlk())
{
- (void)fgMorphBlkToInd(dest->AsBlk(), TYP_STRUCT);
+ dest->SetOper(GT_IND);
+ dest->gtType = TYP_STRUCT;
}
destAddr = gtNewOperNode(GT_ADDR, TYP_BYREF, dest);
}
if (tree->gtGetOp1()->OperIsBlk())
{
assert(tree->gtGetOp1()->TypeGet() == simdType);
- fgMorphBlkToInd(tree->gtGetOp1()->AsBlk(), simdType);
+ tree->gtGetOp1()->SetOper(GT_IND);
+ tree->gtGetOp1()->gtType = simdType;
}
}
#ifdef DEBUG
GenTree* commaOp2 = commaNode->AsOp()->gtOp2;
if (commaOp2->OperIsBlk())
{
- commaOp2 = fgMorphBlkToInd(commaOp2->AsBlk(), commaOp2->TypeGet());
+ commaOp2->SetOper(GT_IND);
}
if (commaOp2->gtOper == GT_IND)
{
if (lvaIsImplicitByRefLocal(lclNum))
{
- size_t size;
+ unsigned size;
if (varDsc->lvSize() > REGSIZE_BYTES)
{
GenTree* lhs = gtNewLclvNode(newLclNum, varDsc->lvType);
// RHS is an indirection (using GT_OBJ) off the parameter.
GenTree* addr = gtNewLclvNode(lclNum, TYP_BYREF);
- GenTree* rhs = gtNewBlockVal(addr, (unsigned)size);
+ GenTree* rhs = new (this, GT_BLK) GenTreeBlk(GT_BLK, TYP_STRUCT, addr, typGetBlkLayout(size));
GenTree* assign = gtNewAssignNode(lhs, rhs);
fgNewStmtAtBeg(fgFirstBB, assign);
}
else
{
tree = gtNewObjNode(lclVarDsc->lvVerTypeInfo.GetClassHandle(), tree);
- }
- if (structType == TYP_STRUCT)
- {
- gtSetObjGcInfo(tree->AsObj());
+ if (structType == TYP_STRUCT)
+ {
+ gtSetObjGcInfo(tree->AsObj());
+ }
}
// TODO-CQ: If the VM ever stops violating the ABI and passing heap references
// Initialize the object memory if necessary
if (comp->fgStructTempNeedsExplicitZeroInit(comp->lvaTable + lclNum, block))
{
- unsigned int structSize = comp->lvaTable[lclNum].lvSize();
-
//------------------------------------------------------------------------
// STMTx (IL 0x... ???)
// * ASG struct (init)
GenTree* tree = comp->gtNewLclvNode(lclNum, TYP_STRUCT);
const bool isVolatile = false;
const bool isCopyBlock = false;
- tree = comp->gtNewBlkOpNode(tree, comp->gtNewIconNode(0), structSize, isVolatile, isCopyBlock);
+ tree = comp->gtNewBlkOpNode(tree, comp->gtNewIconNode(0), isVolatile, isCopyBlock);
Statement* newStmt = comp->gtNewStmt(tree);
dst->gtFlags |= (src->gtFlags & mask);
}
-// Rewrite a SIMD indirection as GT_IND(GT_LEA(obj.op1)), or as a simple
-// lclVar if possible.
+// RewriteSIMDIndir: Rewrite a SIMD indirection as a simple lclVar if possible.
//
// Arguments:
-// use - A use reference for a block node
-// keepBlk - True if this should remain a block node if it is not a lclVar
-//
-// Return Value:
-// None.
+// use - A use of a GT_IND node of SIMD type
//
// TODO-1stClassStructs: These should be eliminated earlier, once we can handle
// lclVars in all the places that used to have GT_OBJ.
//
-void Rationalizer::RewriteSIMDOperand(LIR::Use& use, bool keepBlk)
+void Rationalizer::RewriteSIMDIndir(LIR::Use& use)
{
#ifdef FEATURE_SIMD
// No lowering is needed for non-SIMD nodes, so early out if SIMD types are not supported.
return;
}
- GenTree* tree = use.Def();
- if (!tree->OperIsIndir())
- {
- return;
- }
- var_types simdType = tree->TypeGet();
+ GenTreeIndir* indir = use.Def()->AsIndir();
+ assert(indir->OperIs(GT_IND));
+ var_types simdType = indir->TypeGet();
+ assert(varTypeIsSIMD(simdType));
- if (!varTypeIsSIMD(simdType))
- {
- return;
- }
+ GenTree* addr = indir->Addr();
- // If we have GT_IND(GT_LCL_VAR_ADDR) and the var is a SIMD type,
- // replace the expression by GT_LCL_VAR or GT_LCL_FLD.
- GenTree* addr = tree->AsIndir()->Addr();
if (addr->OperIs(GT_LCL_VAR_ADDR) && comp->lvaGetDesc(addr->AsLclVar())->lvSIMDType)
{
- BlockRange().Remove(tree);
+ // If we have GT_IND(GT_LCL_VAR_ADDR) and the var is a SIMD type,
+ // replace the expression by GT_LCL_VAR or GT_LCL_FLD.
+ BlockRange().Remove(indir);
var_types lclType = comp->lvaGetDesc(addr->AsLclVar())->TypeGet();
addr->gtType = simdType;
use.ReplaceWith(comp, addr);
}
- else if ((addr->OperGet() == GT_ADDR) && (addr->gtGetOp1()->OperIsSimdOrHWintrinsic()))
+ else if (addr->OperIs(GT_ADDR) && addr->AsUnOp()->gtGetOp1()->OperIsSimdOrHWintrinsic())
{
- // if we have GT_IND(GT_ADDR(GT_SIMD)), remove the GT_IND(GT_ADDR()), leaving just the GT_SIMD.
- BlockRange().Remove(tree);
+ // If we have IND(ADDR(SIMD)) then we can keep only the SIMD node.
+ // This is a special tree created by impNormStructVal to preserve the class layout
+ // needed by call morphing on an OBJ node. This information is no longer needed at
+ // this point (and the address of a SIMD node can't be obtained anyway).
+
+ BlockRange().Remove(indir);
BlockRange().Remove(addr);
- use.ReplaceWith(comp, addr->gtGetOp1());
- }
- else if (!keepBlk)
- {
- tree->SetOper(GT_IND);
- tree->gtType = simdType;
+ use.ReplaceWith(comp, addr->AsUnOp()->gtGetOp1());
}
#endif // FEATURE_SIMD
}
if (varDsc->HasGCPtr())
{
CORINFO_CLASS_HANDLE structHnd = varDsc->lvVerTypeInfo.GetClassHandle();
- GenTreeObj* objNode = comp->gtNewObjNode(structHnd, location)->AsObj();
+ GenTreeObj* objNode = comp->gtNewObjNode(structHnd, location);
objNode->ChangeOper(GT_STORE_OBJ);
objNode->SetData(value);
storeBlk = objNode;
if (varTypeIsSIMD(node))
{
- RewriteSIMDOperand(use, false);
+ RewriteSIMDIndir(use);
}
else
{
break;
case GT_OBJ:
- assert(node->TypeGet() == TYP_STRUCT || !use.User()->OperIsInitBlkOp());
- if (varTypeIsSIMD(node))
+ assert((node->TypeGet() == TYP_STRUCT) || !use.User()->OperIsInitBlkOp());
+ if (varTypeIsSIMD(node->TypeGet()))
{
- // Rewrite these as GT_IND.
- RewriteSIMDOperand(use, false);
+ node->SetOper(GT_IND);
+ RewriteSIMDIndir(use);
}
break;
}
// SIMD related
- void RewriteSIMDOperand(LIR::Use& use, bool keepBlk);
+ void RewriteSIMDIndir(LIR::Use& use);
// Intrinsic related transformations
void RewriteNodeAsCall(GenTree** use,
// GT_OBJ instead of GT_BLK nodes to avoid losing information about the actual vector type.
GenTree* loDest = new (this, GT_BLK)
GenTreeBlk(GT_BLK, simdType, dstAddrLo, typGetBlkLayout(getSIMDTypeSizeInBytes(clsHnd)));
- GenTree* loAsg = gtNewBlkOpNode(loDest, simdTree, getSIMDTypeSizeInBytes(clsHnd),
+ GenTree* loAsg = gtNewBlkOpNode(loDest, simdTree,
false, // not volatile
true); // copyBlock
loAsg->gtFlags |= ((simdTree->gtFlags | dstAddrLo->gtFlags) & GTF_ALL_EFFECT);
simdTree = gtNewSIMDNode(simdType, dupOp1, nullptr, SIMDIntrinsicWidenHi, baseType, size);
GenTree* hiDest = new (this, GT_BLK)
GenTreeBlk(GT_BLK, simdType, dstAddrHi, typGetBlkLayout(getSIMDTypeSizeInBytes(clsHnd)));
- GenTree* hiAsg = gtNewBlkOpNode(hiDest, simdTree, getSIMDTypeSizeInBytes(clsHnd),
+ GenTree* hiAsg = gtNewBlkOpNode(hiDest, simdTree,
false, // not volatile
true); // copyBlock
hiAsg->gtFlags |= ((simdTree->gtFlags | dstAddrHi->gtFlags) & GTF_ALL_EFFECT);
GenTree* dest = new (this, GT_BLK)
GenTreeBlk(GT_BLK, simdType, copyBlkDst, typGetBlkLayout(getSIMDTypeSizeInBytes(clsHnd)));
dest->gtFlags |= GTF_GLOB_REF;
- retVal = gtNewBlkOpNode(dest, simdTree, getSIMDTypeSizeInBytes(clsHnd),
+ retVal = gtNewBlkOpNode(dest, simdTree,
false, // not volatile
true); // copyBlock
retVal->gtFlags |= ((simdTree->gtFlags | copyBlkDst->gtFlags) & GTF_ALL_EFFECT);