Skip to content

Commit

Permalink
Contain block store addresses (dotnet/coreclr#21711)
Browse files Browse the repository at this point in the history
Commit migrated from dotnet/coreclr@d572975
  • Loading branch information
Sergey Andreenko authored Nov 5, 2019
2 parents 0c51654 + b67df34 commit 22fcd80
Show file tree
Hide file tree
Showing 7 changed files with 368 additions and 76 deletions.
117 changes: 88 additions & 29 deletions src/coreclr/src/jit/codegenarmarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1943,8 +1943,33 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node)
{
assert(node->OperIs(GT_STORE_BLK));

regNumber dstAddrBaseReg = genConsumeReg(node->Addr());
unsigned dstOffset = 0;
unsigned dstLclNum = BAD_VAR_NUM;
regNumber dstAddrBaseReg = REG_NA;
int dstOffset = 0;
GenTree* dstAddr = node->Addr();

if (!dstAddr->isContained())
{
dstAddrBaseReg = genConsumeReg(dstAddr);
}
else if (dstAddr->OperIsAddrMode())
{
assert(!dstAddr->AsAddrMode()->HasIndex());

dstAddrBaseReg = genConsumeReg(dstAddr->AsAddrMode()->Base());
dstOffset = dstAddr->AsAddrMode()->Offset();
}
else
{
assert(dstAddr->OperIsLocalAddr());
dstLclNum = dstAddr->AsLclVarCommon()->GetLclNum();

if (dstAddr->OperIs(GT_LCL_FLD_ADDR))
{
assert(dstAddr->AsLclFld()->gtLclOffs <= INT32_MAX);
dstOffset = dstAddr->AsLclFld()->gtLclOffs;
}
}

regNumber srcReg;
GenTree* src = node->Data();
Expand Down Expand Up @@ -1977,10 +2002,20 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node)
emitter* emit = GetEmitter();
unsigned size = node->GetLayout()->GetSize();

assert(size <= INT32_MAX);
assert(dstOffset < INT32_MAX - static_cast<int>(size));

#ifdef _TARGET_ARM64_
for (unsigned regSize = 2 * REGSIZE_BYTES; size >= regSize; size -= regSize, dstOffset += regSize)
{
emit->emitIns_R_R_R_I(INS_stp, EA_8BYTE, srcReg, srcReg, dstAddrBaseReg, dstOffset);
if (dstLclNum != BAD_VAR_NUM)
{
emit->emitIns_S_S_R_R(INS_stp, EA_8BYTE, EA_8BYTE, srcReg, srcReg, dstLclNum, dstOffset);
}
else
{
emit->emitIns_R_R_R_I(INS_stp, EA_8BYTE, srcReg, srcReg, dstAddrBaseReg, dstOffset);
}
}
#endif

Expand All @@ -1998,30 +2033,31 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node)
{
case 1:
storeIns = INS_strb;
#ifdef _TARGET_ARM64_
attr = EA_1BYTE;
#else
attr = EA_4BYTE;
#endif
attr = EA_4BYTE;
break;
case 2:
storeIns = INS_strh;
#ifdef _TARGET_ARM64_
attr = EA_2BYTE;
#else
attr = EA_4BYTE;
#endif
attr = EA_4BYTE;
break;
case 4:
#ifdef _TARGET_ARM64_
case 8:
#endif
storeIns = INS_str;
attr = EA_ATTR(regSize);
break;
default:
unreached();
}

emit->emitIns_R_R_I(storeIns, attr, srcReg, dstAddrBaseReg, dstOffset);
if (dstLclNum != BAD_VAR_NUM)
{
emit->emitIns_S_R(storeIns, attr, srcReg, dstLclNum, dstOffset);
}
else
{
emit->emitIns_R_R_I(storeIns, attr, srcReg, dstAddrBaseReg, dstOffset);
}
}
}

Expand All @@ -2037,13 +2073,20 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node)

unsigned dstLclNum = BAD_VAR_NUM;
regNumber dstAddrBaseReg = REG_NA;
unsigned dstOffset = 0;
int dstOffset = 0;
GenTree* dstAddr = node->Addr();

if (!dstAddr->isContained())
{
dstAddrBaseReg = genConsumeReg(dstAddr);
}
else if (dstAddr->OperIsAddrMode())
{
assert(!dstAddr->AsAddrMode()->HasIndex());

dstAddrBaseReg = genConsumeReg(dstAddr->AsAddrMode()->Base());
dstOffset = dstAddr->AsAddrMode()->Offset();
}
else
{
// TODO-ARM-CQ: If the local frame offset is too large to be encoded, the emitter automatically
Expand All @@ -2057,20 +2100,30 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node)

assert(dstAddr->OperIsLocalAddr());
dstLclNum = dstAddr->AsLclVarCommon()->GetLclNum();
dstOffset = dstAddr->OperIs(GT_LCL_FLD_ADDR) ? dstAddr->AsLclFld()->gtLclOffs : 0;

if (dstAddr->OperIs(GT_LCL_FLD_ADDR))
{
assert(dstAddr->AsLclFld()->gtLclOffs <= INT32_MAX);
dstOffset = dstAddr->AsLclFld()->gtLclOffs;
}
}

unsigned srcLclNum = BAD_VAR_NUM;
regNumber srcAddrBaseReg = REG_NA;
unsigned srcOffset = 0;
int srcOffset = 0;
GenTree* src = node->Data();

assert(src->isContained());

if (src->OperIs(GT_LCL_VAR, GT_LCL_FLD))
{
srcLclNum = src->AsLclVarCommon()->GetLclNum();
srcOffset = src->OperIs(GT_LCL_FLD) ? src->AsLclFld()->gtLclOffs : 0;

if (src->OperIs(GT_LCL_FLD))
{
assert(src->AsLclFld()->gtLclOffs <= INT32_MAX);
srcOffset = static_cast<int>(src->AsLclFld()->gtLclOffs);
}
}
else
{
Expand All @@ -2081,11 +2134,21 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node)
{
srcAddrBaseReg = genConsumeReg(srcAddr);
}
else if (srcAddr->OperIsAddrMode())
{
srcAddrBaseReg = genConsumeReg(srcAddr->AsAddrMode()->Base());
srcOffset = srcAddr->AsAddrMode()->Offset();
}
else
{
assert(srcAddr->OperIsLocalAddr());
srcLclNum = srcAddr->AsLclVarCommon()->GetLclNum();
srcOffset = srcAddr->OperIs(GT_LCL_FLD_ADDR) ? srcAddr->AsLclFld()->gtLclOffs : 0;

if (srcAddr->OperIs(GT_LCL_FLD_ADDR))
{
assert(srcAddr->AsLclFld()->gtLclOffs <= INT32_MAX);
srcOffset = static_cast<int>(srcAddr->AsLclFld()->gtLclOffs);
}
}
}

Expand All @@ -2097,6 +2160,10 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node)
emitter* emit = GetEmitter();
unsigned size = node->GetLayout()->GetSize();

assert(size <= INT32_MAX);
assert(srcOffset < INT32_MAX - static_cast<int>(size));
assert(dstOffset < INT32_MAX - static_cast<int>(size));

regNumber tempReg = node->ExtractTempReg(RBM_ALLINT);

#ifdef _TARGET_ARM64_
Expand Down Expand Up @@ -2144,20 +2211,12 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node)
case 1:
loadIns = INS_ldrb;
storeIns = INS_strb;
#ifdef _TARGET_ARM64_
attr = EA_1BYTE;
#else
attr = EA_4BYTE;
#endif
attr = EA_4BYTE;
break;
case 2:
loadIns = INS_ldrh;
storeIns = INS_strh;
#ifdef _TARGET_ARM64_
attr = EA_2BYTE;
#else
attr = EA_4BYTE;
#endif
attr = EA_4BYTE;
break;
case 4:
#ifdef _TARGET_ARM64_
Expand Down
Loading

0 comments on commit 22fcd80

Please sign in to comment.