Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Commit

Permalink
Handle addressing modes for HW intrinsics
Browse files Browse the repository at this point in the history
Also, eliminate some places where the code size estimates were over-estimating.

Contribute to #19550
Fix #19521
  • Loading branch information
CarolEidt committed Mar 11, 2019
1 parent ee56e58 commit 29ab492
Show file tree
Hide file tree
Showing 17 changed files with 559 additions and 245 deletions.
5 changes: 5 additions & 0 deletions src/jit/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ class CodeGen : public CodeGenInterface
static bool genShouldRoundFP();

GenTreeIndir indirForm(var_types type, GenTree* base);
GenTreeStoreInd storeIndirForm(var_types type, GenTree* base, GenTree* data);

GenTreeIntCon intForm(var_types type, ssize_t value);

Expand Down Expand Up @@ -1042,6 +1043,9 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

void genConsumeRegs(GenTree* tree);
void genConsumeOperands(GenTreeOp* tree);
#ifdef FEATURE_HW_INTRINSICS
void genConsumeHWIntrinsicOperands(GenTreeHWIntrinsic* tree);
#endif // FEATURE_HW_INTRINSICS
void genEmitGSCookieCheck(bool pushReg);
void genSetRegToIcon(regNumber reg, ssize_t val, var_types type = TYP_INT, insFlags flags = INS_FLAGS_DONT_CARE);
void genCodeForShift(GenTree* tree);
Expand Down Expand Up @@ -1311,6 +1315,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

#if defined(_TARGET_XARCH_)
void inst_RV_RV_IV(instruction ins, emitAttr size, regNumber reg1, regNumber reg2, unsigned ival);
void inst_RV_TT_IV(instruction ins, emitAttr attr, regNumber reg1, GenTree* rmOp, int ival);
#endif

void inst_RV_RR(instruction ins, emitAttr size, regNumber reg1, regNumber reg2);
Expand Down
11 changes: 11 additions & 0 deletions src/jit/codegencommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11362,6 +11362,17 @@ GenTreeIndir CodeGen::indirForm(var_types type, GenTree* base)
return i;
}

//------------------------------------------------------------------------
// indirForm: Make a temporary indir we can feed to pattern matching routines
// in cases where we don't want to instantiate all the indirs that happen.
//
GenTreeStoreInd CodeGen::storeIndirForm(var_types type, GenTree* base, GenTree* data)
{
GenTreeStoreInd i(type, base, data);
i.gtRegNum = REG_NA;
return i;
}

//------------------------------------------------------------------------
// intForm: Make a temporary int we can feed to pattern matching routines
// in cases where we don't want to instantiate.
Expand Down
77 changes: 68 additions & 9 deletions src/jit/codegenlinear.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1333,12 +1333,27 @@ void CodeGen::genConsumeRegs(GenTree* tree)
// Update the life of the lcl var.
genUpdateLife(tree);
}
#endif // _TARGET_XARCH_
else if (tree->OperIsInitVal())
#ifdef FEATURE_HW_INTRINSICS
else if (tree->OperIs(GT_HWIntrinsic))
{
genConsumeReg(tree->gtGetOp1());
// Only load/store HW intrinsics can be contained (and the address may also be contained).
HWIntrinsicCategory category = HWIntrinsicInfo::lookupCategory(tree->AsHWIntrinsic()->gtHWIntrinsicId);
assert((category == HW_Category_MemoryLoad) || (category == HW_Category_MemoryStore));
int numArgs = HWIntrinsicInfo::lookupNumArgs(tree->AsHWIntrinsic());
genConsumeAddress(tree->gtGetOp1());
if (category == HW_Category_MemoryStore)
{
assert((numArgs == 2) && !tree->gtGetOp2()->isContained());
genConsumeReg(tree->gtGetOp2());
}
else
{
assert(numArgs == 1);
}
}
else if (tree->OperIsHWIntrinsic())
#endif // FEATURE_HW_INTRINSICS
#endif // _TARGET_XARCH_
else if (tree->OperIsInitVal())
{
genConsumeReg(tree->gtGetOp1());
}
Expand Down Expand Up @@ -1368,11 +1383,6 @@ void CodeGen::genConsumeRegs(GenTree* tree)
// Return Value:
// None.
//
// Notes:
// Note that this logic is localized here because we must do the liveness update in
// the correct execution order. This is important because we may have two operands
// that involve the same lclVar, and if one is marked "lastUse" we must handle it
// after the first.

void CodeGen::genConsumeOperands(GenTreeOp* tree)
{
Expand All @@ -1389,6 +1399,55 @@ void CodeGen::genConsumeOperands(GenTreeOp* tree)
}
}

#ifdef FEATURE_HW_INTRINSICS
//------------------------------------------------------------------------
// genConsumeHWIntrinsicOperands: Do liveness update for the operands of a GT_HWIntrinsic node
//
// Arguments:
// node - the GenTreeHWIntrinsic node whose operands will have their liveness updated.
//
// Return Value:
// None.
//

void CodeGen::genConsumeHWIntrinsicOperands(GenTreeHWIntrinsic* node)
{
int numArgs = HWIntrinsicInfo::lookupNumArgs(node);
GenTree* op1 = node->gtGetOp1();
if (op1 == nullptr)
{
assert((numArgs == 0) && (node->gtGetOp2() == nullptr));
return;
}
if (op1->OperIs(GT_LIST))
{
int foundArgs = 0;
assert(node->gtGetOp2() == nullptr);
for (GenTreeArgList* list = op1->AsArgList(); list != nullptr; list = list->Rest())
{
GenTree* operand = list->Current();
genConsumeRegs(operand);
foundArgs++;
}
assert(foundArgs == numArgs);
}
else
{
genConsumeRegs(op1);
GenTree* op2 = node->gtGetOp2();
if (op2 != nullptr)
{
genConsumeRegs(op2);
assert(numArgs == 2);
}
else
{
assert(numArgs == 1);
}
}
}
#endif // FEATURE_HW_INTRINSICS

#if FEATURE_PUT_STRUCT_ARG_STK
//------------------------------------------------------------------------
// genConsumePutStructArgStk: Do liveness update for the operands of a PutArgStk node.
Expand Down
37 changes: 29 additions & 8 deletions src/jit/emitxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2867,6 +2867,12 @@ void emitter::emitInsLoadInd(instruction ins, emitAttr attr, regNumber dstReg, G
id->idReg1(dstReg);
emitHandleMemOp(mem, id, IF_RWR_ARD, ins);
UNATIVE_OFFSET sz = emitInsSizeAM(id, insCodeRM(ins));
if (Is4ByteSSEInstruction(ins))
{
// The 4-Byte SSE instructions require an additional byte.
sz += 1;
}

id->idCodeSize(sz);
dispIns(id);
emitCurIGsize += sz;
Expand Down Expand Up @@ -4055,6 +4061,12 @@ void emitter::emitIns_R_A(instruction ins, emitAttr attr, regNumber reg1, GenTre
emitHandleMemOp(indir, id, IF_RRW_ARD, ins);

UNATIVE_OFFSET sz = emitInsSizeAM(id, insCodeRM(ins));
if (Is4ByteSSEInstruction(ins))
{
// The 4-Byte SSE instructions require an additional byte.
sz += 1;
}

id->idCodeSize(sz);

dispIns(id);
Expand Down Expand Up @@ -4106,8 +4118,8 @@ void emitter::emitIns_R_AR_I(instruction ins, emitAttr attr, regNumber reg1, reg

if (Is4ByteSSEInstruction(ins))
{
// The 4-Byte SSE instructions require two additional bytes
sz += 2;
// The 4-Byte SSE instructions require an additional byte.
sz += 1;
}

id->idCodeSize(sz);
Expand Down Expand Up @@ -5183,8 +5195,8 @@ void emitter::emitIns_R_AR(instruction ins, emitAttr attr, regNumber ireg, regNu

if (Is4ByteSSEInstruction(ins))
{
// The 4-Byte SSE instructions require two additional bytes
sz += 2;
// The 4-Byte SSE instructions require an additional byte.
sz += 1;
}

id->idCodeSize(sz);
Expand Down Expand Up @@ -5658,7 +5670,7 @@ void emitter::emitIns_AX_R(instruction ins, emitAttr attr, regNumber ireg, regNu

#ifdef FEATURE_HW_INTRINSICS
//------------------------------------------------------------------------
// emitIns_SIMD_R_R_I: emits the code for a SIMD instruction that takes a register operand, an immediate operand
// emitIns_SIMD_R_R_I: emits the code for an instruction that takes a register operand, an immediate operand
// and that returns a value in register
//
// Arguments:
Expand All @@ -5668,6 +5680,13 @@ void emitter::emitIns_AX_R(instruction ins, emitAttr attr, regNumber ireg, regNu
// op1Reg -- The register of the first operand
// ival -- The immediate value
//
// Notes:
// This will handle the required register copy if 'op1Reg' and 'targetReg' are not the same, and
// the 3-operand format is not available.
// This is not really SIMD-specific, but is currently only used in that context, as that's
// where we frequently need to handle the case of generating 3-operand or 2-operand forms
// depending on what target ISA is supported.
//
void emitter::emitIns_SIMD_R_R_I(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, int ival)
{
if (UseVEXEncoding() || IsDstSrcImmAvxInstruction(ins))
Expand Down Expand Up @@ -5722,20 +5741,22 @@ void emitter::emitIns_SIMD_R_R_A(
// targetReg -- The target register
// op1Reg -- The register of the first operand
// base -- The base register used for the memory address
// offset -- The memory offset
//
void emitter::emitIns_SIMD_R_R_AR(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber base)
void emitter::emitIns_SIMD_R_R_AR(
instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber base, int offset)
{
if (UseVEXEncoding())
{
emitIns_R_R_AR(ins, attr, targetReg, op1Reg, base, 0);
emitIns_R_R_AR(ins, attr, targetReg, op1Reg, base, offset);
}
else
{
if (op1Reg != targetReg)
{
emitIns_R_R(INS_movaps, attr, targetReg, op1Reg);
}
emitIns_R_AR(ins, attr, targetReg, base, 0);
emitIns_R_AR(ins, attr, targetReg, base, offset);
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/jit/emitxarch.h
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,8 @@ void emitIns_AX_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg,
void emitIns_SIMD_R_R_I(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, int ival);

void emitIns_SIMD_R_R_A(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, GenTreeIndir* indir);
void emitIns_SIMD_R_R_AR(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber base);
void emitIns_SIMD_R_R_AR(
instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber base, int offset);
void emitIns_SIMD_R_R_C(
instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, CORINFO_FIELD_HANDLE fldHnd, int offs);
void emitIns_SIMD_R_R_R(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, regNumber op2Reg);
Expand Down
20 changes: 20 additions & 0 deletions src/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3510,6 +3510,26 @@ unsigned Compiler::gtSetEvalOrder(GenTree* tree)
costSz = 2 * 2;
break;

#if defined(FEATURE_HW_INTRINSICS) && defined(_TARGET_XARCH_)
case GT_HWIntrinsic:
{
if (tree->AsHWIntrinsic()->OperIsMemoryLoadOrStore())
{
costEx = IND_COST_EX;
costSz = 2;
// See if we can form a complex addressing mode.

GenTree* addr = op1->gtEffectiveVal();

if (addr->OperIs(GT_ADD) && gtMarkAddrMode(addr, &costEx, &costSz, tree->TypeGet()))
{
goto DONE;
}
}
}
break;
#endif // FEATURE_HW_INTRINSICS && _TARGET_XARCH_

case GT_BLK:
case GT_IND:

Expand Down
Loading

0 comments on commit 29ab492

Please sign in to comment.