* Return contained bitcast to arm lowering.
* Supported contained bitcast for arm64.
* support contained bitcast arm32.
* Fix arm32.
* fix
* fix assert
* improve comments
// Ensure that lclVar nodes are typed correctly.
assert(!varDsc->lvNormalizeOnStore() || targetType == genActualType(varDsc->TypeGet()));
- GenTree* data = tree->gtOp1;
-
- assert(!data->isContained());
+ GenTree* data = tree->gtOp1;
+ regNumber dataReg = REG_NA;
genConsumeReg(data);
- regNumber dataReg = data->GetRegNum();
+
+ if (data->isContained())
+ {
+ assert(data->OperIs(GT_BITCAST));
+ const GenTree* bitcastSrc = data->AsUnOp()->gtGetOp1();
+ assert(!bitcastSrc->isContained());
+ dataReg = bitcastSrc->GetRegNum();
+ }
+ else
+ {
+
+ dataReg = data->GetRegNum();
+ }
+ assert(dataReg != REG_NA);
+
if (tree->IsOffsetMisaligned())
{
// Arm supports unaligned access only for integer types,
else
{
emitAttr attr = emitTypeSize(targetType);
- instruction ins = ins_Store(targetType);
+ instruction ins = ins_StoreFromSrc(dataReg, targetType);
emit->emitIns_S_R(ins, attr, dataReg, varNum, offset);
}
{
genConsumeRegs(data);
- assert(!data->isContained());
- regNumber dataReg = data->GetRegNum();
+ regNumber dataReg = REG_NA;
+
+ if (data->isContained())
+ {
+ assert(data->OperIs(GT_BITCAST));
+ const GenTree* bitcastSrc = data->AsUnOp()->gtGetOp1();
+ assert(!bitcastSrc->isContained());
+ dataReg = bitcastSrc->GetRegNum();
+ }
+ else
+ {
+ dataReg = data->GetRegNum();
+ }
assert(dataReg != REG_NA);
regNumber targetReg = tree->GetRegNum();
{
inst_set_SV_var(tree);
- instruction ins = ins_Store(targetType);
+ instruction ins = ins_StoreFromSrc(dataReg, targetType);
emitAttr attr = emitTypeSize(targetType);
emitter* emit = GetEmitter();
assert(data->IsIntegralConst(0));
dataReg = REG_ZR;
}
+ else if (data->isContained())
+ {
+ assert(data->OperIs(GT_BITCAST));
+ const GenTree* bitcastSrc = data->AsUnOp()->gtGetOp1();
+ assert(!bitcastSrc->isContained());
+ dataReg = bitcastSrc->GetRegNum();
+ }
else
{
assert(!data->isContained());
}
assert(dataReg != REG_NA);
- instruction ins = ins_Store(targetType);
+ instruction ins = ins_StoreFromSrc(dataReg, targetType);
emitAttr attr = emitActualTypeSize(targetType);
regNumber dataReg = REG_NA;
if (data->isContained())
{
- // This is only possible for a zero-init.
- assert(data->IsIntegralConst(0) || data->IsSIMDZero());
+ // This is only possible for a zero-init or bitcast.
+ const bool zeroInit = (data->IsIntegralConst(0) || data->IsSIMDZero());
+ assert(zeroInit || data->OperIs(GT_BITCAST));
- if (varTypeIsSIMD(targetType))
+ if (zeroInit && varTypeIsSIMD(targetType))
{
if (targetReg != REG_NA)
{
}
return;
}
-
- dataReg = REG_ZR;
+ if (zeroInit)
+ {
+ dataReg = REG_ZR;
+ }
+ else
+ {
+ const GenTree* bitcastSrc = data->AsUnOp()->gtGetOp1();
+ assert(!bitcastSrc->isContained());
+ dataReg = bitcastSrc->GetRegNum();
+ }
}
else
{
{
inst_set_SV_var(lclNode);
- instruction ins = ins_Store(targetType);
+ instruction ins = ins_StoreFromSrc(dataReg, targetType);
emitAttr attr = emitActualTypeSize(targetType);
emit->emitIns_S_R(ins, attr, dataReg, varNum, /* offset */ 0);
// Return Value:
// the instruction to use
//
-// Notes:
-// The function currently does not expect float srcReg with integral dstType and will assert on such cases.
-//
instruction CodeGenInterface::ins_StoreFromSrc(regNumber srcReg, var_types dstType, bool aligned /*=false*/)
{
+ assert(srcReg != REG_NA);
+
bool dstIsFloatType = isFloatRegType(dstType);
bool srcIsFloatReg = genIsValidFloatReg(srcReg);
if (srcIsFloatReg == dstIsFloatType)
{
return ins_Store(dstType, aligned);
}
-
- assert(!srcIsFloatReg && dstIsFloatType && "not expecting an integer type passed in a float reg");
- assert(!varTypeIsSmall(dstType) && "not expecting small float types");
-
- instruction ins = INS_invalid;
-#if defined(TARGET_XARCH)
- ins = INS_mov;
-#elif defined(TARGET_ARMARCH)
- ins = INS_str;
-#else
- NYI("ins_Store");
-#endif
- assert(ins != INS_invalid);
- return ins;
+ else
+ {
+ // We know that we are writing to memory, so make the destination type same
+ // as the source type.
+ var_types dstTypeForStore = TYP_UNDEF;
+ unsigned dstSize = genTypeSize(dstType);
+ switch (dstSize)
+ {
+ case 4:
+ dstTypeForStore = srcIsFloatReg ? TYP_FLOAT : TYP_INT;
+ break;
+#if defined(TARGET_64BIT)
+ case 8:
+ dstTypeForStore = srcIsFloatReg ? TYP_DOUBLE : TYP_LONG;
+ break;
+#endif // TARGET_64BIT
+ default:
+ assert(!"unexpected write to the stack.");
+ break;
+ }
+ return ins_Store(dstTypeForStore, aligned);
+ }
}
#if defined(TARGET_XARCH)
assert(storeLoc->OperIsLocalStore());
GenTree* op1 = storeLoc->gtGetOp1();
-#if 0
- // TODO-ARMARCH-CQ: support contained bitcast under STORE_LCL_VAR/FLD,
- // currently codegen does not expect it.
if (op1->OperIs(GT_BITCAST))
{
// If we know that the source of the bitcast will be in a register, then we can make
return;
}
}
-#endif
const LclVarDsc* varDsc = comp->lvaGetDesc(storeLoc);
// Second, use source registers.
- if (op1->IsMultiRegNode())
+ if (op1->IsMultiRegNode() && (op1->GetMultiRegCount() > 1))
{
// This is the case where the source produces multiple registers.
// This must be a store lclvar.