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

Commit 61c44bc

Browse files
committed
table drive Intel hardware intrinsic
1 parent c9e80a7 commit 61c44bc

24 files changed

+1252
-304
lines changed

src/jit/compiler.h

+19-8
Original file line numberDiff line numberDiff line change
@@ -2058,9 +2058,13 @@ class Compiler
20582058

20592059
#if FEATURE_HW_INTRINSICS
20602060
GenTreeHWIntrinsic* gtNewSimdHWIntrinsicNode(
2061-
var_types type, GenTree* op1, NamedIntrinsic hwIntrinsicID, var_types baseType, unsigned size);
2062-
GenTreeHWIntrinsic* gtNewSimdHWIntrinsicNode(
2063-
var_types type, GenTree* op1, GenTree* op2, NamedIntrinsic hwIntrinsicID, var_types baseType, unsigned size);
2061+
var_types type, GenTree* op1, NamedIntrinsic hwIntrinsicID, var_types baseType, unsigned simdSize);
2062+
GenTreeHWIntrinsic* gtNewSimdHWIntrinsicNode(var_types type,
2063+
GenTree* op1,
2064+
GenTree* op2,
2065+
NamedIntrinsic hwIntrinsicID,
2066+
var_types baseType,
2067+
unsigned simdSize);
20642068
GenTreeHWIntrinsic* gtNewScalarHWIntrinsicNode(var_types type, GenTree* op1, NamedIntrinsic hwIntrinsicID);
20652069
GenTreeHWIntrinsic* gtNewScalarHWIntrinsicNode(var_types type,
20662070
GenTree* op1,
@@ -3022,11 +3026,11 @@ class Compiler
30223026
NamedIntrinsic lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method);
30233027

30243028
#if FEATURE_HW_INTRINSICS
3025-
InstructionSet lookupHWIntrinsicISA(const char* className);
3026-
NamedIntrinsic lookupHWIntrinsic(const char* methodName, InstructionSet isa);
3027-
InstructionSet isaOfHWIntrinsic(NamedIntrinsic intrinsic);
3028-
bool isIntrinsicAnIsSupportedPropertyGetter(NamedIntrinsic intrinsic);
3029-
bool isFullyImplmentedISAClass(InstructionSet isa);
3029+
static InstructionSet lookupHWIntrinsicISA(const char* className);
3030+
static NamedIntrinsic lookupHWIntrinsic(const char* methodName, InstructionSet isa);
3031+
static InstructionSet isaOfHWIntrinsic(NamedIntrinsic intrinsic);
3032+
static bool isIntrinsicAnIsSupportedPropertyGetter(NamedIntrinsic intrinsic);
3033+
static bool isFullyImplmentedISAClass(InstructionSet isa);
30303034
#ifdef _TARGET_XARCH_
30313035
GenTree* impUnsupportedHWIntrinsic(unsigned helper,
30323036
CORINFO_METHOD_HANDLE method,
@@ -3098,6 +3102,13 @@ class Compiler
30983102
bool mustExpand);
30993103
bool compSupportsHWIntrinsic(InstructionSet isa);
31003104
bool isScalarISA(InstructionSet isa);
3105+
static int ivalOfHWIntrinsic(NamedIntrinsic intrinsic);
3106+
static int numArgsOfHWIntrinsic(NamedIntrinsic intrinsic);
3107+
static instruction insOfHWIntrinsic(NamedIntrinsic intrinsic, var_types type);
3108+
static HWIntrinsicCategory categoryOfHWIntrinsic(NamedIntrinsic intrinsic);
3109+
static HWIntrinsicFlag flagOfHWIntrinsic(NamedIntrinsic intrinsic);
3110+
GenTree* getArgForHWIntrinsic(var_types argType, CORINFO_CLASS_HANDLE argClass);
3111+
GenTreeArgList* buildArgList(CORINFO_SIG_INFO* sig);
31013112
#endif // _TARGET_XARCH_
31023113
#endif // FEATURE_HW_INTRINSICS
31033114
GenTreePtr impArrayAccessIntrinsic(CORINFO_CLASS_HANDLE clsHnd,

src/jit/compiler.hpp

+13
Original file line numberDiff line numberDiff line change
@@ -4891,6 +4891,19 @@ void GenTree::VisitOperands(TVisitor visitor)
48914891
return;
48924892
#endif // FEATURE_SIMD
48934893

4894+
#if FEATURE_HW_INTRINSICS
4895+
case GT_HWIntrinsic:
4896+
if ((this->AsHWIntrinsic()->gtOp1 != nullptr) && this->AsHWIntrinsic()->gtOp1->OperIsList())
4897+
{
4898+
this->AsHWIntrinsic()->gtOp1->VisitListOperands(visitor);
4899+
}
4900+
else
4901+
{
4902+
VisitBinOpOperands<TVisitor>(visitor);
4903+
}
4904+
return;
4905+
#endif // FEATURE_HW_INTRINSICS
4906+
48944907
// Special nodes
48954908
case GT_CMPXCHG:
48964909
{

src/jit/emit.h

+14
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,7 @@ class emitter
938938
struct
939939
{
940940
regNumber _idReg3 : REGNUM_BITS;
941+
regNumber _idReg4 : REGNUM_BITS;
941942
};
942943
#endif // defined(_TARGET_XARCH_)
943944

@@ -1119,6 +1120,19 @@ class emitter
11191120
idAddr()->_idReg3 = reg;
11201121
assert(reg == idAddr()->_idReg3);
11211122
}
1123+
regNumber idReg4() const
1124+
{
1125+
assert(!idIsTiny());
1126+
assert(!idIsSmallDsc());
1127+
return idAddr()->_idReg4;
1128+
}
1129+
void idReg4(regNumber reg)
1130+
{
1131+
assert(!idIsTiny());
1132+
assert(!idIsSmallDsc());
1133+
idAddr()->_idReg4 = reg;
1134+
assert(reg == idAddr()->_idReg4);
1135+
}
11221136
#endif // defined(_TARGET_XARCH_)
11231137
#ifdef _TARGET_ARMARCH_
11241138
insOpts idInsOpt() const

src/jit/emitfmtsxarch.h

+2
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ IF_DEF(RRW_RRW_CNS, IS_R1_RW|IS_R2_RW, SCNS) // r/w reg , r/w r
110110

111111
IF_DEF(RWR_RRD_RRD, IS_R1_WR|IS_R2_RD|IS_R3_RD, NONE) // write reg , read reg2 , read reg3
112112
IF_DEF(RWR_RRD_RRD_CNS, IS_R1_WR|IS_R2_RD|IS_R3_RD, SCNS) // write reg , read reg2 , read reg3, const
113+
114+
IF_DEF(RWR_RRD_RRD_RRD, IS_R1_WR|IS_R2_RD|IS_R3_RD|IS_R4_RD, NONE) // write reg , read reg2 , read reg3 , read reg4
113115
//----------------------------------------------------------------------------
114116
// The following formats are used for direct addresses (e.g. static data members)
115117
//----------------------------------------------------------------------------

src/jit/emitxarch.cpp

+103-18
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ bool emitter::IsDstDstSrcAVXInstruction(instruction ins)
143143
case INS_pminub:
144144
case INS_pminud:
145145
case INS_pminuw:
146+
case INS_pmuldq:
146147
case INS_pmulld:
147148
case INS_pmullw:
148149
case INS_pmuludq:
@@ -4135,6 +4136,43 @@ void emitter::emitIns_R_R_R_I(
41354136
emitCurIGsize += sz;
41364137
}
41374138

4139+
static bool isAvxBlendv(instruction ins)
4140+
{
4141+
return ins == INS_vblendvps || ins == INS_vblendvpd || ins == INS_vpblendvb;
4142+
}
4143+
4144+
static bool isSse41Blendv(instruction ins)
4145+
{
4146+
return ins == INS_blendvps || ins == INS_blendvpd || ins == INS_pblendvb;
4147+
}
4148+
4149+
void emitter::emitIns_R_R_R_R(
4150+
instruction ins, emitAttr attr, regNumber targetReg, regNumber reg1, regNumber reg2, regNumber reg3)
4151+
{
4152+
assert(isAvxBlendv(ins));
4153+
assert(UseVEXEncoding());
4154+
// Currently vex prefix only use three bytes mode.
4155+
// size = vex + opcode + ModR/M + 1-byte-cns(Reg) = 3 + 1 + 1 + 1 = 6
4156+
// TODO-XArch-CQ: We should create function which can calculate all kinds of AVX instructions size in future
4157+
UNATIVE_OFFSET sz = 6;
4158+
4159+
// AVX/AVX2 supports 4-reg format for vblendvps/vblendvpd/vpblendvb,
4160+
// which encodes the fourth register into imm8[7:4]
4161+
int ival = (reg3 - XMMBASE) << 4; // convert reg3 to ival
4162+
4163+
instrDesc* id = emitNewInstrCns(attr, ival);
4164+
id->idIns(ins);
4165+
id->idInsFmt(IF_RWR_RRD_RRD_RRD);
4166+
id->idReg1(targetReg);
4167+
id->idReg2(reg1);
4168+
id->idReg3(reg2);
4169+
id->idReg4(reg3);
4170+
4171+
id->idCodeSize(sz);
4172+
dispIns(id);
4173+
emitCurIGsize += sz;
4174+
}
4175+
41384176
/*****************************************************************************
41394177
*
41404178
* Add an instruction with a register + static member operands.
@@ -5074,69 +5112,107 @@ void emitter::emitIns_AX_R(instruction ins, emitAttr attr, regNumber ireg, regNu
50745112
}
50755113

50765114
#if FEATURE_HW_INTRINSICS
5077-
void emitter::emitIns_SIMD_R_R_A(
5078-
instruction ins, regNumber reg, regNumber reg1, GenTreeIndir* indir, var_types simdtype)
5115+
void emitter::emitIns_SIMD_R_R_A(instruction ins, emitAttr attr, regNumber reg, regNumber reg1, GenTreeIndir* indir)
50795116
{
50805117
if (UseVEXEncoding())
50815118
{
5082-
emitIns_R_R_A(ins, emitTypeSize(simdtype), reg, reg1, indir, IF_RWR_RRD_ARD);
5119+
emitIns_R_R_A(ins, attr, reg, reg1, indir, IF_RWR_RRD_ARD);
50835120
}
50845121
else
50855122
{
50865123
if (reg1 != reg)
50875124
{
5088-
emitIns_R_R(INS_movaps, emitTypeSize(simdtype), reg, reg1);
5125+
emitIns_R_R(INS_movaps, attr, reg, reg1);
50895126
}
5090-
emitIns_R_A(ins, emitTypeSize(simdtype), reg, indir, IF_RRW_ARD);
5127+
emitIns_R_A(ins, attr, reg, indir, IF_RRW_ARD);
50915128
}
50925129
}
50935130

50945131
void emitter::emitIns_SIMD_R_R_C(
5095-
instruction ins, regNumber reg, regNumber reg1, CORINFO_FIELD_HANDLE fldHnd, int offs, var_types simdtype)
5132+
instruction ins, emitAttr attr, regNumber reg, regNumber reg1, CORINFO_FIELD_HANDLE fldHnd, int offs)
5133+
{
5134+
if (UseVEXEncoding())
5135+
{
5136+
emitIns_R_R_C(ins, attr, reg, reg1, fldHnd, offs);
5137+
}
5138+
else
5139+
{
5140+
if (reg1 != reg)
5141+
{
5142+
emitIns_R_R(INS_movaps, attr, reg, reg1);
5143+
}
5144+
emitIns_R_C(ins, attr, reg, fldHnd, offs);
5145+
}
5146+
}
5147+
5148+
void emitter::emitIns_SIMD_R_R_R(instruction ins, emitAttr attr, regNumber reg, regNumber reg1, regNumber reg2)
50965149
{
50975150
if (UseVEXEncoding())
50985151
{
5099-
emitIns_R_R_C(ins, emitTypeSize(simdtype), reg, reg1, fldHnd, offs);
5152+
emitIns_R_R_R(ins, attr, reg, reg1, reg2);
51005153
}
51015154
else
51025155
{
51035156
if (reg1 != reg)
51045157
{
5105-
emitIns_R_R(INS_movaps, emitTypeSize(simdtype), reg, reg1);
5158+
emitIns_R_R(INS_movaps, attr, reg, reg1);
51065159
}
5107-
emitIns_R_C(ins, emitTypeSize(simdtype), reg, fldHnd, offs);
5160+
emitIns_R_R(ins, attr, reg, reg2);
51085161
}
51095162
}
51105163

5111-
void emitter::emitIns_SIMD_R_R_R(instruction ins, regNumber reg, regNumber reg1, regNumber reg2, var_types simdtype)
5164+
void emitter::emitIns_SIMD_R_R_R_R(
5165+
instruction ins, emitAttr attr, regNumber reg, regNumber reg1, regNumber reg2, regNumber reg3)
51125166
{
5167+
assert(isAvxBlendv(ins) || isSse41Blendv(ins));
51135168
if (UseVEXEncoding())
51145169
{
5115-
emitIns_R_R_R(ins, emitTypeSize(simdtype), reg, reg1, reg2);
5170+
// convert SSE encoding of SSE4.1 instructions to VEX encoding
5171+
switch (ins)
5172+
{
5173+
case INS_blendvps:
5174+
ins = INS_vblendvps;
5175+
break;
5176+
case INS_blendvpd:
5177+
ins = INS_vblendvpd;
5178+
break;
5179+
case INS_pblendvb:
5180+
ins = INS_vpblendvb;
5181+
break;
5182+
default:
5183+
break;
5184+
}
5185+
emitIns_R_R_R_R(ins, attr, reg, reg1, reg2, reg3);
51165186
}
51175187
else
51185188
{
5189+
assert(isSse41Blendv(ins));
5190+
// SSE4.1 blendv* hardcode the mask vector (op3) in XMM0
5191+
if (reg3 != REG_XMM0)
5192+
{
5193+
emitIns_R_R(INS_movaps, attr, REG_XMM0, reg3);
5194+
}
51195195
if (reg1 != reg)
51205196
{
5121-
emitIns_R_R(INS_movaps, emitTypeSize(simdtype), reg, reg1);
5197+
emitIns_R_R(INS_movaps, attr, reg, reg1);
51225198
}
5123-
emitIns_R_R(ins, emitTypeSize(simdtype), reg, reg2);
5199+
emitIns_R_R(ins, attr, reg, reg2);
51245200
}
51255201
}
51265202

5127-
void emitter::emitIns_SIMD_R_R_S(instruction ins, regNumber reg, regNumber reg1, int varx, int offs, var_types simdtype)
5203+
void emitter::emitIns_SIMD_R_R_S(instruction ins, emitAttr attr, regNumber reg, regNumber reg1, int varx, int offs)
51285204
{
51295205
if (UseVEXEncoding())
51305206
{
5131-
emitIns_R_R_S(ins, emitTypeSize(simdtype), reg, reg1, varx, offs);
5207+
emitIns_R_R_S(ins, attr, reg, reg1, varx, offs);
51325208
}
51335209
else
51345210
{
51355211
if (reg1 != reg)
51365212
{
5137-
emitIns_R_R(INS_movaps, emitTypeSize(simdtype), reg, reg1);
5213+
emitIns_R_R(INS_movaps, attr, reg, reg1);
51385214
}
5139-
emitIns_R_S(ins, emitTypeSize(simdtype), reg, varx, offs);
5215+
emitIns_R_S(ins, attr, reg, varx, offs);
51405216
}
51415217
}
51425218
#endif
@@ -7423,6 +7499,14 @@ void emitter::emitDispIns(
74237499
val = emitGetInsSC(id);
74247500
goto PRINT_CONSTANT;
74257501
break;
7502+
case IF_RWR_RRD_RRD_RRD:
7503+
assert(IsAVXOnlyInstruction(ins));
7504+
assert(UseVEXEncoding());
7505+
printf("%s, ", emitRegName(id->idReg1(), attr));
7506+
printf("%s, ", emitRegName(id->idReg2(), attr));
7507+
printf("%s, ", emitRegName(id->idReg3(), attr));
7508+
printf("%s", emitRegName(id->idReg4(), attr));
7509+
break;
74267510
case IF_RRW_RRW_CNS:
74277511
printf("%s,", emitRegName(id->idReg1(), attr));
74287512
printf(" %s", emitRegName(id->idReg2(), attr));
@@ -10046,7 +10130,7 @@ BYTE* emitter::emitOutputRRR(BYTE* dst, instrDesc* id)
1004610130

1004710131
instruction ins = id->idIns();
1004810132
assert(IsAVXInstruction(ins));
10049-
assert(IsThreeOperandAVXInstruction(ins));
10133+
assert(IsThreeOperandAVXInstruction(ins) || isAvxBlendv(ins));
1005010134
regNumber targetReg = id->idReg1();
1005110135
regNumber src1 = id->idReg2();
1005210136
regNumber src2 = id->idReg3();
@@ -11312,6 +11396,7 @@ size_t emitter::emitOutputInstr(insGroup* ig, instrDesc* id, BYTE** dp)
1131211396
sz = emitSizeOfInsDsc(id);
1131311397
break;
1131411398
case IF_RWR_RRD_RRD_CNS:
11399+
case IF_RWR_RRD_RRD_RRD:
1131511400
dst = emitOutputRRR(dst, id);
1131611401
sz = emitSizeOfInsDsc(id);
1131711402
dst += emitOutputByte(dst, emitGetInsSC(id));

src/jit/emitxarch.h

+8-4
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,8 @@ void emitIns_R_R_R(instruction ins, emitAttr attr, regNumber reg1, regNumber reg
386386

387387
void emitIns_R_R_R_I(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, int ival);
388388

389+
void emitIns_R_R_R_R(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3, regNumber reg4);
390+
389391
void emitIns_S(instruction ins, emitAttr attr, int varx, int offs);
390392

391393
void emitIns_S_R(instruction ins, emitAttr attr, regNumber ireg, int varx, int offs);
@@ -441,11 +443,13 @@ void emitIns_R_AX(instruction ins, emitAttr attr, regNumber ireg, regNumber reg,
441443
void emitIns_AX_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, unsigned mul, int disp);
442444

443445
#if FEATURE_HW_INTRINSICS
444-
void emitIns_SIMD_R_R_A(instruction ins, regNumber reg, regNumber reg1, GenTreeIndir* indir, var_types simdtype);
446+
void emitIns_SIMD_R_R_A(instruction ins, emitAttr attr, regNumber reg, regNumber reg1, GenTreeIndir* indir);
445447
void emitIns_SIMD_R_R_C(
446-
instruction ins, regNumber reg, regNumber reg1, CORINFO_FIELD_HANDLE fldHnd, int offs, var_types simdtype);
447-
void emitIns_SIMD_R_R_R(instruction ins, regNumber reg, regNumber reg1, regNumber reg2, var_types simdtype);
448-
void emitIns_SIMD_R_R_S(instruction ins, regNumber reg, regNumber reg1, int varx, int offs, var_types simdtype);
448+
instruction ins, emitAttr attr, regNumber reg, regNumber reg1, CORINFO_FIELD_HANDLE fldHnd, int offs);
449+
void emitIns_SIMD_R_R_S(instruction ins, emitAttr attr, regNumber reg, regNumber reg1, int varx, int offs);
450+
void emitIns_SIMD_R_R_R(instruction ins, emitAttr attr, regNumber reg, regNumber reg1, regNumber reg2);
451+
void emitIns_SIMD_R_R_R_R(
452+
instruction ins, emitAttr attr, regNumber reg, regNumber reg1, regNumber reg2, regNumber reg3);
449453
#endif
450454

451455
#if FEATURE_STACK_FP_X87

0 commit comments

Comments
 (0)