Skip to content

Commit

Permalink
[JIT] Add legacy extended EVEX encoding and EVEX.ND/NF feature to x64…
Browse files Browse the repository at this point in the history
… emitter backend (#108796)

* Ruihan: POC with REX2

Update comments.

Merge the REX2 changes into the original legacy emit path

bug fix: Set REX2.W with correct mask code.

register encoding and prefix emitting logics.

Add REX2 prefix emit logic

bug fixes

Add Stress mode for REX2 encoding and some bug fixes

resolve comments:
1. add assertion check for UD opcodes.
2. add checks for EGPRs.

Add REX2 to emitOutputAM, and let LEA to be REX2 compatible.

Add REX2.X encoding for SIB byte

But fixes: add REX2 prefix on the path in RI where MOV is specially handled.

Enable REX2 encoding for `movups`

fixed bugs in REX2 prefix emitting logic when working with map 1 instructions, and enabled REX2 for POPCNT

legacy map index-er

bug fixes

some clean-up

Adding initial APX unit testing path.

Adding a coredistools dll that has LLVM APX disasm capability.

It must be coppied into a CORE_ROOT manually.

clean up work for REX2

narrow the REX2 scope to `sub` only

some clean up based on the comments.

bug fix

resolve comment

* resolve comments

* refactor register encoding for REX2

* merge REX2 path to legacy path

* Enable REX2 in more instructions.

* Avoid repeatedly estimate the size of REX2 prefix

* Enable REX2 encoding on RI and SV path
 - SV path is mostly for debugging purposes

Added encoding unit tests for instructions with immediates

* Add rex2 support to rotate and shift.

* CR session.

* Testing infra updates: assert REX2 is enabled.
Code refactoring: AddX86PrefixIfNeeded.

* revert rcl_N and rcr_N, tp and latency data for these instructions is missing in JIT, may indicate these instructions are not being used in JIT, drop them for now.

* partially enable REX2 on emitOutputAM, case covered: R_AR and AR_R.

* Adding unit tests.

* push, pop, inc, dec, neg, not, xadd, shld, shrd, cmpxchg, setcc, bswap.

* bug fix for bswap

* bt

* xchg, idiv

* Make sure add REX2 prefix if register encoding for EGPRs are being called before adding any prefix.

* Ensure code size is correctly computed in R_R_I path.

* clean up

* Change all AddSimdPrefix to AddX86Prefix
Refactor REX2 encoding stress logics.

* div, mulEAX

* filter out test from REX2 encoding when using ACC form.
(this will have side effect that the estimated code will go up and mismatch with actual code size.)

* Make sure REX prefix will not be added when emitting with REX2.

* resolve comments.

* make sure the APX debug knob is only available under debug build.

* clean up some out-dated code.

* enable movsxd

* Enable "Call"

* Enable "JMP"

* resolve merge errors

* formatting

* remote coredistools.dll for internal tests only

* bug fix

* SUB reg, reg, reg

* enable NDD on genCodeForBinary

* consolidate TakesLegacyPromotedEvexPrefix logics.

* ensure register encoding is correct under legacy-promoted-evex encoding.

* Make sure the overflow check is correctly emitted.

* simplify the compiler setup logics.

* emitInsNddBinary

* make sure REX will not be added when EVEX presents.

* resolve comment and clean up.

* enable more NDD instructions.

* bug fixes

* enable imul

* add emitter unit tests, and fix encoding error for CMOVcc

* bug fixes:
1. make sure RWR_RRD_SHF has correct register update mode
2. make sure shift instructions will get correct opcode in RR path.

* refactor emitInsBinary

* clean up

* clean up and refactor some code

* make sure the code size estimation is correct for some apx promoted instructions.

* add tuning knob to EVEX.ND feature.

* flip the Evex.nd knob.

* put NDD control knob to the correct place.

* resolve merge errors

* Make sure APX related knobs are defined properly across platforms

* Add Evex.nf to instrDesc

* {nf} add reg, reg

* Enable EVEX.NF in more instructions

* more instructions

* comments.

* lzcnt, tzcnt, popcnt

* Exclude ACC form from EVEX promotion.

* BMI instructions.

* bug fixes

* Tweak the code size calculation to make sure REX2 and APX-EVEX are properly handled.

* bug fixes for stress mode

* Add idEvexNoPromotion to emitter to exclude the APX-EVEX promotion from LOCK prefixd instructions.

* resolve merge error

* fix merge error

* Revert "Add idEvexNoPromotion to emitter to exclude the APX-EVEX promotion from LOCK prefixd instructions."

This reverts commit 1be4b12.

* bug fix

* introduce _no_evex suffix for some instructions for cases when LOCK will be prefixed.

* resolve merge comflict

* fix merge error.

* fix comments and some checks.

* formatting

* remove unneeded env var.

* Make sure the BMI instruction is properly hidden behind APX stress knob and will not be EVEX-encoded when JitStressEvexEncoding is set.

* resolve merge error.

* Resolve comments.

* formatting.

* Add rcr/rcl emitter unit tests for extended EVEX.

* Resolve merge error.

* formatting

* resolve comments

* formatting

* use the right size for neg and not code gen.
  • Loading branch information
Ruihan-Yin authored Jan 30, 2025
1 parent 4e01649 commit f652094
Show file tree
Hide file tree
Showing 10 changed files with 1,614 additions and 412 deletions.
182 changes: 148 additions & 34 deletions src/coreclr/jit/codegenxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,12 +402,13 @@ void CodeGen::instGen_Set_Reg_To_Imm(emitAttr size,
else
{
// For section constant, the immediate will be relocatable
GetEmitter()->emitIns_R_I(INS_mov, size, reg, imm DEBUGARG(targetHandle) DEBUGARG(gtFlags));
GetEmitter()->emitIns_R_I(INS_mov, size, reg, imm,
INS_OPTS_NONE DEBUGARG(targetHandle) DEBUGARG(gtFlags));
}
}
else
{
GetEmitter()->emitIns_R_I(INS_mov, size, reg, imm DEBUGARG(targetHandle) DEBUGARG(gtFlags));
GetEmitter()->emitIns_R_I(INS_mov, size, reg, imm, INS_OPTS_NONE DEBUGARG(targetHandle) DEBUGARG(gtFlags));
}
}
regSet.verifyRegUsed(reg);
Expand Down Expand Up @@ -738,12 +739,10 @@ void CodeGen::genCodeForNegNot(GenTree* tree)
{
GenTree* operand = tree->gtGetOp1();
assert(operand->isUsedFromReg());
regNumber operandReg = genConsumeReg(operand);
regNumber operandReg = genConsumeReg(operand);
instruction ins = genGetInsForOper(tree->OperGet(), targetType);

inst_Mov(targetType, targetReg, operandReg, /* canSkip */ true);

instruction ins = genGetInsForOper(tree->OperGet(), targetType);
inst_RV(ins, targetReg, targetType);
GetEmitter()->emitIns_BASE_R_R(ins, emitActualTypeSize(tree), targetReg, operandReg);
}

genProduceReg(tree);
Expand Down Expand Up @@ -1063,6 +1062,8 @@ void CodeGen::genCodeForBinary(GenTreeOp* treeNode)
GenTree* op1 = treeNode->gtGetOp1();
GenTree* op2 = treeNode->gtGetOp2();

bool eligibleForNDD = false;

// Commutative operations can mark op1 as contained or reg-optional to generate "op reg, memop/immed"
if (!op1->isUsedFromReg())
{
Expand Down Expand Up @@ -1158,31 +1159,57 @@ void CodeGen::genCodeForBinary(GenTreeOp* treeNode)
// reg3 = reg3 op reg2
else
{
var_types op1Type = op1->TypeGet();
inst_Mov(op1Type, targetReg, op1reg, /* canSkip */ false);
regSet.verifyRegUsed(targetReg);
gcInfo.gcMarkRegPtrVal(targetReg, op1Type);
dst = treeNode;
src = op2;
// when reg3 != reg1 && reg3 != reg2, and NDD is available, we can use APX-EVEX.ND to optimize the codegen.
eligibleForNDD = emit->DoJitUseApxNDD(ins);
if (!eligibleForNDD)
{
var_types op1Type = op1->TypeGet();
inst_Mov(op1Type, targetReg, op1reg, /* canSkip */ false);
regSet.verifyRegUsed(targetReg);
gcInfo.gcMarkRegPtrVal(targetReg, op1Type);
dst = treeNode;
src = op2;
}
else
{
dst = op1;
src = op2;
}
}

// we can assume all the floating instructions are processed and returned above.
assert(!varTypeIsFloating(treeNode));

// try to use an inc or dec
if (oper == GT_ADD && !varTypeIsFloating(treeNode) && src->isContainedIntOrIImmed() && !treeNode->gtOverflowEx())
if (oper == GT_ADD && src->isContainedIntOrIImmed() && !treeNode->gtOverflowEx())
{
if (src->IsIntegralConst(1))
{
emit->emitIns_R(INS_inc, emitTypeSize(treeNode), targetReg);
emit->emitIns_BASE_R_R(INS_inc, emitTypeSize(treeNode), targetReg, dst->GetRegNum());
genProduceReg(treeNode);
return;
}
else if (src->IsIntegralConst(-1))
{
emit->emitIns_R(INS_dec, emitTypeSize(treeNode), targetReg);
emit->emitIns_BASE_R_R(INS_dec, emitTypeSize(treeNode), targetReg, dst->GetRegNum());
genProduceReg(treeNode);
return;
}
}
regNumber r = emit->emitInsBinary(ins, emitTypeSize(treeNode), dst, src);

regNumber r = REG_NA;
if (eligibleForNDD)
{
// operands should be already formatted above
assert(dst->isUsedFromReg());
assert(op1reg != targetReg);
assert(op2reg != targetReg);
r = emit->emitIns_BASE_R_R_RM(ins, emitTypeSize(treeNode), targetReg, treeNode, dst, src);
}
else
{
r = emit->emitInsBinary(ins, emitTypeSize(treeNode), dst, src);
}
noway_assert(r == targetReg);

if (treeNode->gtOverflowEx())
Expand Down Expand Up @@ -1295,10 +1322,7 @@ void CodeGen::genCodeForMul(GenTreeOp* treeNode)
}
assert(regOp->isUsedFromReg());

// Setup targetReg when neither of the source operands was a matching register
inst_Mov(targetType, mulTargetReg, regOp->GetRegNum(), /* canSkip */ true);

emit->emitInsBinary(ins, size, treeNode, rmOp);
emit->emitIns_BASE_R_R_RM(ins, size, mulTargetReg, treeNode, regOp, rmOp);

// Move the result to the desired register, if necessary
if (ins == INS_mulEAX)
Expand Down Expand Up @@ -4406,23 +4430,24 @@ void CodeGen::genCodeForLockAdd(GenTreeOp* node)
if (imm == 1)
{
// inc [addr]
GetEmitter()->emitIns_AR(INS_inc, size, addr->GetRegNum(), 0);
GetEmitter()->emitIns_AR(INS_inc, size, addr->GetRegNum(), 0, INS_OPTS_EVEX_NoApxPromotion);
}
else if (imm == -1)
{
// dec [addr]
GetEmitter()->emitIns_AR(INS_dec, size, addr->GetRegNum(), 0);
GetEmitter()->emitIns_AR(INS_dec, size, addr->GetRegNum(), 0, INS_OPTS_EVEX_NoApxPromotion);
}
else
{
// add [addr], imm
GetEmitter()->emitIns_I_AR(INS_add, size, imm, addr->GetRegNum(), 0);
GetEmitter()->emitIns_I_AR(INS_add, size, imm, addr->GetRegNum(), 0, INS_OPTS_EVEX_NoApxPromotion);
}
}
else
{
// add [addr], data
GetEmitter()->emitIns_AR_R(INS_add, size, data->GetRegNum(), addr->GetRegNum(), 0);
GetEmitter()->emitIns_AR_R(INS_add, size, data->GetRegNum(), addr->GetRegNum(), 0,
INS_OPTS_EVEX_NoApxPromotion);
}
}

Expand Down Expand Up @@ -4459,7 +4484,8 @@ void CodeGen::genLockedInstructions(GenTreeOp* node)
// or/and dword ptr [addrReg], val
//
instGen(INS_lock);
GetEmitter()->emitIns_AR_R(ins, size, data->GetRegNum(), addr->GetRegNum(), 0);
GetEmitter()->emitIns_AR_R(ins, size, data->GetRegNum(), addr->GetRegNum(), 0,
INS_OPTS_EVEX_NoApxPromotion);
}
else
{
Expand Down Expand Up @@ -4842,11 +4868,10 @@ void CodeGen::genCodeForShift(GenTree* tree)
return;
}
#endif
// First, move the operand to the destination register and
// later on perform the shift in-place.
// (LSRA will try to avoid this situation through preferencing.)
inst_Mov(targetType, tree->GetRegNum(), operandReg, /* canSkip */ true);
inst_RV_SH(ins, size, tree->GetRegNum(), shiftByValue);
ins = genMapShiftInsToShiftByConstantIns(ins, shiftByValue);
GetEmitter()->emitIns_BASE_R_R_I(ins, emitTypeSize(tree), tree->GetRegNum(), operandReg, shiftByValue);
genProduceReg(tree);
return;
}
}
#if defined(TARGET_64BIT)
Expand Down Expand Up @@ -4887,8 +4912,7 @@ void CodeGen::genCodeForShift(GenTree* tree)
// The operand to be shifted must not be in ECX
noway_assert(operandReg != REG_RCX);

inst_Mov(targetType, tree->GetRegNum(), operandReg, /* canSkip */ true);
inst_RV(ins, tree->GetRegNum(), targetType);
GetEmitter()->emitIns_BASE_R_R(ins, emitTypeSize(tree), tree->GetRegNum(), operandReg);
}

genProduceReg(tree);
Expand Down Expand Up @@ -9237,6 +9261,96 @@ void CodeGen::genAmd64EmitterUnitTestsApx()

theEmitter->emitIns_S(INS_neg, EA_2BYTE, 0, 0);
theEmitter->emitIns_S(INS_not, EA_2BYTE, 0, 0);

// APX-EVEX

theEmitter->emitIns_R_R_R(INS_add, EA_8BYTE, REG_R10, REG_EAX, REG_ECX, INS_OPTS_EVEX_nd);
theEmitter->emitIns_R_R_R(INS_sub, EA_2BYTE, REG_R10, REG_EAX, REG_ECX, INS_OPTS_EVEX_nd);
theEmitter->emitIns_R_R_R(INS_or, EA_2BYTE, REG_R10, REG_EAX, REG_ECX, INS_OPTS_EVEX_nd);
theEmitter->emitIns_R_R_R(INS_and, EA_2BYTE, REG_R10, REG_EAX, REG_ECX, INS_OPTS_EVEX_nd);
theEmitter->emitIns_R_R_R(INS_xor, EA_1BYTE, REG_R10, REG_EAX, REG_ECX, INS_OPTS_EVEX_nd);

theEmitter->emitIns_R_R_I(INS_or, EA_2BYTE, REG_R10, REG_EAX, 10565, INS_OPTS_EVEX_nd);
theEmitter->emitIns_R_R_I(INS_or, EA_8BYTE, REG_R10, REG_EAX, 10, INS_OPTS_EVEX_nd);
theEmitter->emitIns_R_R_S(INS_or, EA_8BYTE, REG_R10, REG_EAX, 0, 1, INS_OPTS_EVEX_nd);

theEmitter->emitIns_R_R(INS_neg, EA_2BYTE, REG_R10, REG_ECX, INS_OPTS_EVEX_nd);

theEmitter->emitIns_R_R(INS_shl, EA_2BYTE, REG_R11, REG_EAX, INS_OPTS_EVEX_nd);
theEmitter->emitIns_R_R(INS_shl_1, EA_2BYTE, REG_R11, REG_EAX, INS_OPTS_EVEX_nd);
theEmitter->emitIns_R_R_I(INS_shl_N, EA_2BYTE, REG_R11, REG_ECX, 7, INS_OPTS_EVEX_nd);
theEmitter->emitIns_R_R_I(INS_shl_N, EA_2BYTE, REG_R11, REG_ECX, 7, INS_OPTS_EVEX_nd);
theEmitter->emitIns_R_R_I(INS_rcr_N, EA_2BYTE, REG_R11, REG_ECX, 7, INS_OPTS_EVEX_nd);
theEmitter->emitIns_R_R_I(INS_rcl_N, EA_2BYTE, REG_R11, REG_ECX, 7, INS_OPTS_EVEX_nd);

theEmitter->emitIns_R_R(INS_inc, EA_2BYTE, REG_R11, REG_ECX, INS_OPTS_EVEX_nd);
theEmitter->emitIns_R_R(INS_dec, EA_2BYTE, REG_R11, REG_ECX, INS_OPTS_EVEX_nd);

theEmitter->emitIns_R_R_R(INS_cmovo, EA_4BYTE, REG_R12, REG_R11, REG_EAX, INS_OPTS_EVEX_nd);

theEmitter->emitIns_R_R_R(INS_imul, EA_4BYTE, REG_R12, REG_R11, REG_ECX, INS_OPTS_EVEX_nd);
theEmitter->emitIns_R_R_S(INS_imul, EA_4BYTE, REG_R12, REG_R11, 0, 1, INS_OPTS_EVEX_nd);

theEmitter->emitIns_R_R(INS_add, EA_4BYTE, REG_R12, REG_R11, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_R(INS_sub, EA_4BYTE, REG_R12, REG_R11, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_R(INS_and, EA_4BYTE, REG_R12, REG_R11, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_R(INS_or, EA_4BYTE, REG_R12, REG_R11, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_R(INS_xor, EA_4BYTE, REG_R12, REG_R11, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R(INS_inc, EA_4BYTE, REG_R12, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R(INS_dec, EA_4BYTE, REG_R12, INS_OPTS_EVEX_nf);

theEmitter->emitIns_R_I(INS_add, EA_4BYTE, REG_R12, 5, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_I(INS_sub, EA_4BYTE, REG_R12, 5, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_I(INS_and, EA_4BYTE, REG_R12, 5, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_I(INS_or, EA_4BYTE, REG_R12, 5, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_I(INS_xor, EA_4BYTE, REG_R12, 5, INS_OPTS_EVEX_nf);

theEmitter->emitIns_R_S(INS_add, EA_4BYTE, REG_R12, 0, 1, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_S(INS_sub, EA_4BYTE, REG_R12, 0, 1, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_S(INS_and, EA_4BYTE, REG_R12, 0, 1, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_S(INS_or, EA_4BYTE, REG_R12, 0, 1, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_S(INS_xor, EA_4BYTE, REG_R12, 0, 1, INS_OPTS_EVEX_nf);

theEmitter->emitIns_R(INS_neg, EA_2BYTE, REG_R11, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R(INS_shl, EA_2BYTE, REG_R11, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R(INS_shl_1, EA_2BYTE, REG_R11, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_I(INS_shl_N, EA_2BYTE, REG_R11, 7, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_I(INS_shl_N, EA_2BYTE, REG_R11, 7, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_I(INS_rcr_N, EA_2BYTE, REG_R11, 7, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_I(INS_rcl_N, EA_2BYTE, REG_R11, 7, INS_OPTS_EVEX_nf);

theEmitter->emitIns_R_R(INS_imul, EA_4BYTE, REG_R12, REG_R11, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_S(INS_imul, EA_4BYTE, REG_R12, 0, 1, INS_OPTS_EVEX_nf);

theEmitter->emitIns_R_I(INS_imul_15, EA_4BYTE, REG_R12, 5, INS_OPTS_EVEX_nf);

theEmitter->emitIns_R(INS_imulEAX, EA_8BYTE, REG_R12, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R(INS_mulEAX, EA_8BYTE, REG_R12, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R(INS_div, EA_8BYTE, REG_R12, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R(INS_idiv, EA_8BYTE, REG_R12, INS_OPTS_EVEX_nf);

theEmitter->emitIns_R_R(INS_tzcnt_apx, EA_8BYTE, REG_R12, REG_R11, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_R(INS_lzcnt_apx, EA_8BYTE, REG_R12, REG_R11, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_R(INS_popcnt_apx, EA_8BYTE, REG_R12, REG_R11, INS_OPTS_EVEX_nf);

theEmitter->emitIns_R_S(INS_tzcnt_apx, EA_8BYTE, REG_R12, 0, 1, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_S(INS_lzcnt_apx, EA_8BYTE, REG_R12, 0, 1, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_S(INS_popcnt_apx, EA_8BYTE, REG_R12, 0, 1, INS_OPTS_EVEX_nf);

theEmitter->emitIns_R_R_R(INS_add, EA_2BYTE, REG_R12, REG_R13, REG_R11,
(insOpts)(INS_OPTS_EVEX_nf | INS_OPTS_EVEX_nd));

theEmitter->emitIns_R_R_R(INS_andn, EA_8BYTE, REG_R11, REG_R13, REG_R11, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_R_R(INS_bextr, EA_8BYTE, REG_R11, REG_R13, REG_R11, INS_OPTS_EVEX_nf);

theEmitter->emitIns_R_R(INS_blsi, EA_8BYTE, REG_R11, REG_R13, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_R(INS_blsmsk, EA_8BYTE, REG_R11, REG_R13, INS_OPTS_EVEX_nf);
theEmitter->emitIns_R_S(INS_blsr, EA_8BYTE, REG_R11, 0, 1);

theEmitter->emitIns_AR(INS_inc, EA_4BYTE, REG_EAX, 0, INS_OPTS_EVEX_NoApxPromotion);

theEmitter->emitIns_BASE_R_R(INS_inc, EA_4BYTE, REG_R11, REG_R12);
theEmitter->emitIns_BASE_R_R_I(INS_add, EA_4BYTE, REG_R11, REG_R12, 5);
}

void CodeGen::genAmd64EmitterUnitTestsAvx10v2()
Expand Down Expand Up @@ -11434,7 +11548,7 @@ void CodeGen::instGen_MemoryBarrier(BarrierKind barrierKind)
if (barrierKind == BARRIER_FULL)
{
instGen(INS_lock);
GetEmitter()->emitIns_I_AR(INS_or, EA_4BYTE, 0, REG_SPBASE, 0);
GetEmitter()->emitIns_I_AR(INS_or, EA_4BYTE, 0, REG_SPBASE, 0, INS_OPTS_EVEX_NoApxPromotion);
}
}

Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2299,6 +2299,7 @@ void Compiler::compSetProcessor()
if (canUseApxEncoding())
{
codeGen->GetEmitter()->SetUseRex2Encoding(true);
codeGen->GetEmitter()->SetUsePromotedEVEXEncoding(true);
}
}
#endif // TARGET_XARCH
Expand Down
31 changes: 24 additions & 7 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -4014,7 +4014,7 @@ class Compiler

// false: we can add new tracked variables.
// true: We cannot add new 'tracked' variable
bool lvaTrackedFixed = false;
bool lvaTrackedFixed = false;

unsigned lvaCount; // total number of locals, which includes function arguments,
// special arguments, IL local variables, and JIT temporary variables
Expand Down Expand Up @@ -6924,15 +6924,15 @@ class Compiler
unsigned acdCount = 0;

// Get the index to use as part of the AddCodeDsc key for sharing throw blocks
unsigned bbThrowIndex(BasicBlock* blk, AcdKeyDesignator* dsg);
unsigned bbThrowIndex(BasicBlock* blk, AcdKeyDesignator* dsg);

struct AddCodeDscKey
{
public:
AddCodeDscKey(): acdKind(SCK_NONE), acdData(0) {}
AddCodeDscKey(SpecialCodeKind kind, BasicBlock* block, Compiler* comp);
AddCodeDscKey(AddCodeDsc* add);

static bool Equals(const AddCodeDscKey& x, const AddCodeDscKey& y)
{
return (x.acdData == y.acdData) && (x.acdKind == y.acdKind);
Expand Down Expand Up @@ -10013,10 +10013,10 @@ class Compiler
}

//------------------------------------------------------------------------
// canUseRex2Encoding - Answer the question: Is Rex2 encoding supported on this target.
// canUseApxEncoding - Answer the question: Are APX encodings supported on this target.
//
// Returns:
// `true` if Rex2 encoding is supported, `false` if not.
// `true` if APX encoding is supported, `false` if not.
//
bool canUseApxEncoding() const
{
Expand Down Expand Up @@ -10068,7 +10068,7 @@ class Compiler
bool DoJitStressRex2Encoding() const
{
#ifdef DEBUG
if (JitConfig.JitStressRex2Encoding() && compOpportunisticallyDependsOn(InstructionSet_APX))
if (JitConfig.JitStressRex2Encoding())
{
// we should make sure EVEX is also stressed when REX2 is stressed, as we will need to guarantee EGPR
// functionality is properly turned on for every instructions when REX2 is stress.
Expand All @@ -10083,13 +10083,30 @@ class Compiler
// JitStressEvexEncoding- Answer the question: Is Evex stress knob set
//
// Returns:
// `true` if user requests REX2 encoding.
// `true` if user requests EVEX encoding.
//
bool JitStressEvexEncoding() const
{
#ifdef DEBUG
return JitConfig.JitStressEvexEncoding() || JitConfig.JitStressRex2Encoding();
#endif // DEBUG
return false;
}

//------------------------------------------------------------------------
// DoJitStressPromotedEvexEncoding- Answer the question: Do we force promoted EVEX encoding.
//
// Returns:
// `true` if user requests promoted EVEX encoding.
//
bool DoJitStressPromotedEvexEncoding() const
{
#ifdef DEBUG
if (JitConfig.JitStressPromotedEvexEncoding())
{
return true;
}
#endif // DEBUG

return false;
}
Expand Down
Loading

0 comments on commit f652094

Please sign in to comment.