Skip to content

Commit

Permalink
ARM64-SVE: Always call emitIns_Mov when canskip is true (#106693)
Browse files Browse the repository at this point in the history
  • Loading branch information
a74nh authored Aug 21, 2024
1 parent 779baa6 commit eb655cf
Showing 1 changed file with 57 additions and 133 deletions.
190 changes: 57 additions & 133 deletions src/coreclr/jit/hwintrinsiccodegenarm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,13 +368,9 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
{
if (isRMW)
{
if (targetReg != op1Reg)
{
assert(targetReg != op2Reg);
assert(targetReg != op3Reg);

GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);
}
assert((targetReg == op1Reg) || (targetReg != op2Reg));
assert((targetReg == op1Reg) || (targetReg != op3Reg));
GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);

HWIntrinsicImmOpHelper helper(this, intrin.op4, node);

Expand Down Expand Up @@ -416,14 +412,9 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
{
if (isRMW)
{
if (targetReg != op1Reg)
{
assert(targetReg != op2Reg);
assert(targetReg != op3Reg);

GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);
}

assert((targetReg == op1Reg) || (targetReg != op2Reg));
assert((targetReg == op1Reg) || (targetReg != op3Reg));
GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);
GetEmitter()->emitIns_R_R_R_I(ins, emitSize, targetReg, op2Reg, op3Reg, 0, opt);
}
else
Expand Down Expand Up @@ -773,21 +764,16 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
switch (intrinEmbMask.id)
{
case NI_Sve_CreateBreakPropagateMask:
if (targetReg != embMaskOp1Reg)
{
GetEmitter()->emitIns_Mov(INS_sve_mov, emitSize, targetReg, embMaskOp2Reg,
/* canSkip */ true);
}
assert((targetReg == embMaskOp2Reg) || (targetReg != embMaskOp1Reg));
GetEmitter()->emitIns_Mov(INS_sve_mov, emitSize, targetReg, embMaskOp2Reg,
/* canSkip */ true);
emitInsHelper(targetReg, maskReg, embMaskOp1Reg);
break;

case NI_Sve_AddSequentialAcross:
assert(targetReg != embMaskOp2Reg);
if (targetReg != embMaskOp1Reg)
{
GetEmitter()->emitIns_Mov(INS_fmov, GetEmitter()->optGetSveElemsize(embOpt),
targetReg, embMaskOp1Reg, /* canSkip */ true);
}
assert((targetReg == op1Reg) || (targetReg != embMaskOp2Reg));
GetEmitter()->emitIns_Mov(INS_fmov, GetEmitter()->optGetSveElemsize(embOpt), targetReg,
embMaskOp1Reg, /* canSkip */ true);
emitInsHelper(targetReg, maskReg, embMaskOp2Reg);
break;

Expand Down Expand Up @@ -1063,15 +1049,10 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
{
if (isRMW)
{
if (targetReg != op2Reg)
{
assert(targetReg != op1Reg);

GetEmitter()->emitIns_Mov(ins_Move_Extend(intrin.op2->TypeGet(), false),
emitTypeSize(node), targetReg, op2Reg,
/* canSkip */ true);
}

assert((targetReg == op2Reg) || (targetReg != op1Reg));
GetEmitter()->emitIns_Mov(ins_Move_Extend(intrin.op2->TypeGet(), false),
emitTypeSize(node), targetReg, op2Reg,
/* canSkip */ true);
GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op1Reg, opt);
}
else
Expand All @@ -1088,13 +1069,9 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
}
else if (isRMW)
{
if (targetReg != op1Reg)
{
assert(targetReg != op2Reg);

GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg,
/* canSkip */ true);
}
assert((targetReg == op1Reg) || (targetReg != op2Reg));
GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg,
/* canSkip */ true);
GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op2Reg, opt);
}
else
Expand All @@ -1110,27 +1087,20 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
{
if (HWIntrinsicInfo::IsExplicitMaskedOperation(intrin.id))
{
if (targetReg != op2Reg)
{
assert(targetReg != op1Reg);
assert(targetReg != op3Reg);

GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op2Reg,
/* canSkip */ true);
}
assert((targetReg == op1Reg) || (targetReg != op1Reg));
assert((targetReg == op1Reg) || (targetReg != op3Reg));

GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op2Reg,
/* canSkip */ true);
GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op1Reg, op3Reg, opt);
}
else
{
if (targetReg != op1Reg)
{
assert(targetReg != op2Reg);
assert(targetReg != op3Reg);
assert((targetReg == op1Reg) || (targetReg != op2Reg));
assert((targetReg == op1Reg) || (targetReg != op3Reg));

GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg,
/* canSkip */ true);
}
GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg,
/* canSkip */ true);
GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op2Reg, op3Reg, opt);
}
}
Expand Down Expand Up @@ -1384,12 +1354,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
case NI_AdvSimd_InsertScalar:
{
assert(isRMW);
if (targetReg != op1Reg)
{
assert(targetReg != op3Reg);

GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);
}
assert((targetReg == op1Reg) || (targetReg != op3Reg));
GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);

HWIntrinsicImmOpHelper helper(this, intrin.op2, node);

Expand All @@ -1405,12 +1371,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
case NI_AdvSimd_Arm64_InsertSelectedScalar:
{
assert(isRMW);
if (targetReg != op1Reg)
{
assert(targetReg != op3Reg);

GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);
}
assert((targetReg == op1Reg) || (targetReg != op3Reg));
GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);

const int resultIndex = (int)intrin.op2->AsIntCon()->gtIconVal;
const int valueIndex = (int)intrin.op4->AsIntCon()->gtIconVal;
Expand All @@ -1421,12 +1383,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
case NI_AdvSimd_LoadAndInsertScalar:
{
assert(isRMW);
if (targetReg != op1Reg)
{
assert(targetReg != op3Reg);

GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);
}
assert((targetReg == op1Reg) || (targetReg != op3Reg));
GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);

HWIntrinsicImmOpHelper helper(this, intrin.op2, node);

Expand Down Expand Up @@ -1466,11 +1424,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
targetFieldReg = node->GetRegByIndex(fieldIdx);
op1FieldReg = fieldNode->GetRegNum();

if (targetFieldReg != op1FieldReg)
{
GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(fieldNode), targetFieldReg, op1FieldReg,
/* canSkip */ true);
}
GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(fieldNode), targetFieldReg, op1FieldReg,
/* canSkip */ true);
fieldIdx++;
}

Expand Down Expand Up @@ -2000,11 +1955,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
break;
}

if (targetReg != op1Reg)
{
assert(targetReg != op3Reg);
GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);
}
assert((targetReg == op1Reg) || (targetReg != op3Reg));
GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);
GetEmitter()->emitIns_R_R_R(ins, emitSize, targetReg, op2Reg, op3Reg, opt);
break;
}
Expand Down Expand Up @@ -2330,12 +2282,9 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
case NI_Sve_SaturatingIncrementBy8BitElementCount:
{
assert(isRMW);
if (targetReg != op1Reg)
{
assert(targetReg != op2Reg);
assert(targetReg != op3Reg);
GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);
}
assert((targetReg == op1Reg) || (targetReg != op2Reg));
assert((targetReg == op1Reg) || (targetReg != op3Reg));
GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);

if (intrin.op2->IsCnsIntOrI() && intrin.op3->IsCnsIntOrI())
{
Expand Down Expand Up @@ -2387,11 +2336,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
case NI_Sve_SaturatingIncrementByActiveElementCount:
{
// RMW semantics
if (targetReg != op1Reg)
{
assert(targetReg != op2Reg);
GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);
}
assert((targetReg == op1Reg) || (targetReg != op2Reg));
GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);

// Switch instruction if arg1 is unsigned.
if (varTypeIsUnsigned(node->GetAuxiliaryType()))
Expand Down Expand Up @@ -2430,13 +2376,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
case NI_Sve_ExtractVector:
{
assert(isRMW);

if (targetReg != op1Reg)
{
assert(targetReg != op2Reg);

GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);
}
assert((targetReg == op1Reg) || (targetReg != op2Reg));
GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);

HWIntrinsicImmOpHelper helper(this, intrin.op3, node);

Expand All @@ -2454,13 +2395,9 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
{
assert(isRMW);
assert(emitter::isFloatReg(op2Reg) == varTypeIsFloating(intrin.baseType));
if (targetReg != op1Reg)
{
assert(targetReg != op2Reg);
GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg,
/* canSkip */ true);
}

assert((targetReg == op1Reg) || (targetReg != op2Reg));
GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg,
/* canSkip */ true);
GetEmitter()->emitInsSve_R_R(ins, emitSize, targetReg, op2Reg, opt);
break;
}
Expand All @@ -2483,13 +2420,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
{
assert(isRMW);
assert(HWIntrinsicInfo::IsExplicitMaskedOperation(intrin.id));

if (targetReg != op2Reg)
{
assert(targetReg != op1Reg);
GetEmitter()->emitIns_Mov(INS_sve_mov, emitTypeSize(node), targetReg, op2Reg, /* canSkip */ true);
}

assert((targetReg == op2Reg) || (targetReg != op1Reg));
GetEmitter()->emitIns_Mov(INS_sve_mov, emitTypeSize(node), targetReg, op2Reg, /* canSkip */ true);
GetEmitter()->emitIns_R_R(ins, emitSize, targetReg, op1Reg, INS_OPTS_SCALABLE_B);
break;
}
Expand Down Expand Up @@ -2543,14 +2475,10 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)

emitSize = emitTypeSize(node);

if (targetReg != op2Reg)
{
assert(targetReg != op1Reg);
assert(targetReg != op3Reg);
GetEmitter()->emitIns_Mov(INS_mov, emitSize, targetReg, op2Reg,
/* canSkip */ true);
}

assert((targetReg == op2Reg) || (targetReg != op1Reg));
assert((targetReg == op2Reg) || (targetReg != op3Reg));
GetEmitter()->emitIns_Mov(INS_mov, emitSize, targetReg, op2Reg,
/* canSkip */ true);
GetEmitter()->emitInsSve_R_R_R(ins, emitSize, targetReg, op1Reg, op3Reg, opt,
INS_SCALABLE_OPTS_NONE);
break;
Expand All @@ -2564,14 +2492,10 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
{
assert(emitter::isFloatReg(targetReg));
assert(varTypeIsFloating(node->gtType) || varTypeIsSIMD(node->gtType));

if (targetReg != op2Reg)
{
assert(targetReg != op1Reg);
assert(targetReg != op3Reg);
GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op2Reg,
/* canSkip */ true);
}
assert((targetReg == op2Reg) || (targetReg != op1Reg));
assert((targetReg == op2Reg) || (targetReg != op3Reg));
GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op2Reg,
/* canSkip */ true);
GetEmitter()->emitInsSve_R_R_R(ins, EA_SCALABLE, targetReg, op1Reg, op3Reg, opt,
INS_SCALABLE_OPTS_WITH_SIMD_SCALAR);
break;
Expand Down

0 comments on commit eb655cf

Please sign in to comment.