Skip to content

Commit

Permalink
Allow containing ExtractVector128 into Store (dotnet#22896)
Browse files Browse the repository at this point in the history
* Allow containing ExtractVector128 into Store

* Support contained address modes on ExtractVector128
  • Loading branch information
mikedn authored and CarolEidt committed Sep 24, 2019
1 parent ddbdf57 commit f0a8b4d
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 22 deletions.
26 changes: 10 additions & 16 deletions src/jit/emitxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5345,26 +5345,20 @@ void emitter::emitIns_S_R_I(instruction ins, emitAttr attr, int varNum, int offs
emitCurIGsize += sz;
}

void emitter::emitIns_AR_R_I(instruction ins, emitAttr attr, regNumber base, int disp, regNumber ireg, int ival)
void emitter::emitIns_A_R_I(instruction ins, emitAttr attr, GenTreeIndir* indir, regNumber reg, int imm)
{
assert(ins == INS_vextracti128 || ins == INS_vextractf128);
assert(base != REG_NA);
assert(ireg != REG_NA);
instrDesc* id = emitNewInstrAmdCns(attr, disp, ival);
assert((ins == INS_vextracti128) || (ins == INS_vextractf128));
assert(attr == EA_32BYTE);
assert(reg != REG_NA);

instrDesc* id = emitNewInstrAmdCns(attr, indir->Offset(), imm);
id->idIns(ins);
id->idInsFmt(IF_AWR_RRD_CNS);
id->idAddr()->iiaAddrMode.amBaseReg = base;
id->idAddr()->iiaAddrMode.amIndxReg = REG_NA;
id->idReg1(ireg);

assert(emitGetInsAmdAny(id) == disp); // make sure "disp" is stored properly

UNATIVE_OFFSET sz = emitInsSizeAM(id, insCodeMR(ins), ival);
id->idCodeSize(sz);

id->idReg1(reg);
emitHandleMemOp(indir, id, IF_AWR_RRD_CNS, ins);
UNATIVE_OFFSET size = emitInsSizeAM(id, insCodeMR(ins), imm);
id->idCodeSize(size);
dispIns(id);
emitCurIGsize += sz;
emitCurIGsize += size;
}

void emitter::emitIns_AI_R(instruction ins, emitAttr attr, regNumber ireg, ssize_t disp)
Expand Down
2 changes: 1 addition & 1 deletion src/jit/emitxarch.h
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ void emitIns_R_R_AR_I(
instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber base, int offs, int ival);
void emitIns_S_R_I(instruction ins, emitAttr attr, int varNum, int offs, regNumber reg, int ival);

void emitIns_AR_R_I(instruction ins, emitAttr attr, regNumber base, int disp, regNumber ireg, int ival);
void emitIns_A_R_I(instruction ins, emitAttr attr, GenTreeIndir* indir, regNumber reg, int imm);

void emitIns_R_R_C_I(
instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, CORINFO_FIELD_HANDLE fldHnd, int offs, int ival);
Expand Down
2 changes: 2 additions & 0 deletions src/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17897,6 +17897,8 @@ bool GenTree::isContainableHWIntrinsic() const
case NI_SSE2_LoadVector128:
case NI_AVX_LoadAlignedVector256:
case NI_AVX_LoadVector256:
case NI_AVX_ExtractVector128:
case NI_AVX2_ExtractVector128:
{
return true;
}
Expand Down
29 changes: 24 additions & 5 deletions src/jit/hwintrinsiccodegenxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,30 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
if (category == HW_Category_MemoryStore)
{
genConsumeAddress(op1);
genConsumeReg(op2);
// Until we improve the handling of addressing modes in the emitter, we'll create a
// temporary GT_STORE_IND to generate code with.
GenTreeStoreInd store = storeIndirForm(node->TypeGet(), op1, op2);
emit->emitInsStoreInd(ins, simdSize, &store);

if (((intrinsicId == NI_SSE_Store) || (intrinsicId == NI_SSE2_Store)) && op2->isContained())
{
GenTreeHWIntrinsic* extract = op2->AsHWIntrinsic();

assert((extract->gtHWIntrinsicId == NI_AVX_ExtractVector128) ||
(extract->gtHWIntrinsicId == NI_AVX2_ExtractVector128));

regNumber regData = genConsumeReg(extract->gtGetOp1());

ins = HWIntrinsicInfo::lookupIns(extract->gtHWIntrinsicId, extract->gtSIMDBaseType);
ival = static_cast<int>(extract->gtGetOp2()->AsIntCon()->IconValue());

GenTreeIndir indir = indirForm(TYP_SIMD16, op1);
emit->emitIns_A_R_I(ins, EA_32BYTE, &indir, regData, ival);
}
else
{
genConsumeReg(op2);
// Until we improve the handling of addressing modes in the emitter, we'll create a
// temporary GT_STORE_IND to generate code with.
GenTreeStoreInd store = storeIndirForm(node->TypeGet(), op1, op2);
emit->emitInsStoreInd(ins, simdSize, &store);
}
break;
}
genConsumeRegs(op1);
Expand Down
8 changes: 8 additions & 0 deletions src/jit/lowerxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2985,6 +2985,14 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node)
{
GenTree** pAddr = &node->gtOp1;
ContainCheckHWIntrinsicAddr(node, pAddr);

if (((intrinsicId == NI_SSE_Store) || (intrinsicId == NI_SSE2_Store)) && op2->OperIsHWIntrinsic() &&
((op2->AsHWIntrinsic()->gtHWIntrinsicId == NI_AVX_ExtractVector128) ||
(op2->AsHWIntrinsic()->gtHWIntrinsicId == NI_AVX2_ExtractVector128)) &&
op2->gtGetOp2()->IsIntegralConst())
{
MakeSrcContained(node, op2);
}
break;
}
case HW_Category_SimpleSIMD:
Expand Down

0 comments on commit f0a8b4d

Please sign in to comment.