Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a1cd1f8
Implement Wasm codegen for Vector128.Create with const operands
adamperlin Jun 17, 2026
2921181
Merge branch 'main' of github.com:dotnet/runtime into adamperlin/wasm…
adamperlin Jun 18, 2026
f4fd2fe
Fix categories and flags for some Vector128 Wasm hardware intrinsics
adamperlin Jun 18, 2026
48e0731
Checkpoint: PackedSimd.Add now compiles as an intrinsic (with const v…
adamperlin Jun 19, 2026
7bf550b
Add a few more PackedSimd intrinsics
adamperlin Jun 19, 2026
50f2359
Add table-driven codegen entries for (simd), (simd, simd) and (simd, …
adamperlin Jun 20, 2026
250aa59
Add ifdefs and remove not fully implemented opcode
adamperlin Jun 22, 2026
3766e1b
Cleanup (for now) unused code
adamperlin Jun 22, 2026
46ae244
Add #if FEATURE_SIMD
adamperlin Jun 22, 2026
cb5a7e9
jit-format
adamperlin Jun 22, 2026
c0f347d
Fix ifdef condition syntax
adamperlin Jun 22, 2026
3d4abae
Apply suggestions from code review
adamperlin Jun 22, 2026
628c47a
Fix unconditional NYI_WASM_SIMD lower bailout, handle no disasm file …
adamperlin Jun 22, 2026
4c056e3
Remove TODO
adamperlin Jun 23, 2026
10ff35c
Potential fix for pull request finding
adamperlin Jun 23, 2026
6ecc662
Copilot feedback: remove unconditional import NYI on non-constant vec…
adamperlin Jun 23, 2026
292bcaf
Format hwintrinsiclistwasm.h
adamperlin Jun 23, 2026
e7cef58
More copilot feedback
adamperlin Jun 23, 2026
5a93f14
Potential fix for pull request finding
adamperlin Jun 23, 2026
3b52445
Merge branch 'main' of github.com:dotnet/runtime into adamperlin/wasm…
adamperlin Jun 24, 2026
01e61c6
Address more review feedback: Ensure Vector128.GetElement can fall ba…
adamperlin Jun 25, 2026
ef9b870
Merge branch 'adamperlin/wasm-basic-simd' of github.com:adamperlin/ru…
adamperlin Jun 25, 2026
aff1238
Update src/coreclr/jit/hwintrinsic.cpp
adamperlin Jun 25, 2026
79f9b4d
Additional review feedback: handle PackedSimd.LoadVector128, Store to…
adamperlin Jun 26, 2026
132760a
Add impSimdCreate helper shared across targets
adamperlin Jun 26, 2026
6eaf553
Merge branch 'adamperlin/wasm-basic-simd' of github.com:adamperlin/ru…
adamperlin Jun 26, 2026
b868b58
Fix op reversal assert
adamperlin Jun 26, 2026
3a54c5a
Potential fix for pull request finding
adamperlin Jun 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/coreclr/jit/codegen.h
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,9 @@ class CodeGen final : public CodeGenInterface

#if defined(TARGET_WASM)
void genCodeForConstant(GenTree* treeNode);
#if defined(FEATURE_SIMD)
void genCodeForVectorConstant(GenTree* treeNode);
#endif
void genCatchArg(GenTree* treeNode);
#endif

Expand Down
29 changes: 25 additions & 4 deletions src/coreclr/jit/codegenwasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -746,6 +746,12 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
return;
}

if (treeNode->OperIsHWIntrinsic())
{
genHWIntrinsic(treeNode->AsHWIntrinsic());
return;
}
Comment thread
adamperlin marked this conversation as resolved.

switch (treeNode->OperGet())
{
case GT_ADD:
Expand Down Expand Up @@ -922,6 +928,12 @@ void CodeGen::genCodeForTreeNode(GenTree* treeNode)
genCkfinite(treeNode);
break;

#if defined(FEATURE_SIMD)
case GT_CNS_VEC:
genCodeForVectorConstant(treeNode);
break;
#endif // FEATURE_SIMD

default:
#ifdef DEBUG
if (JitConfig.JitWasmNyiToR2RUnsupported())
Expand Down Expand Up @@ -1801,6 +1813,19 @@ void CodeGen::genCodeForConstant(GenTree* treeNode)
WasmProduceReg(treeNode);
}

#ifdef FEATURE_SIMD
void CodeGen::genCodeForVectorConstant(GenTree* treeNode)
{
assert(treeNode->IsCnsVec());
GenTreeVecCon* vecCon = treeNode->AsVecCon();

// There is only one type variant for v128.const, v128.const <byte[16]>
// and the bytes are reinterpreted according to whichever operation consumes the value.
GetEmitter()->emitIns_V128Imm(INS_v128_const, vecCon->gtSimd16Val.u8);
WasmProduceReg(treeNode);
}
Comment thread
adamperlin marked this conversation as resolved.
#endif

//------------------------------------------------------------------------
// genCodeForShift: Generate code for a shift or rotate operator
//
Expand Down Expand Up @@ -2471,10 +2496,6 @@ void CodeGen::genCodeForLclVar(GenTreeLclVar* tree)
if (!varDsc->lvIsRegCandidate())
{
var_types type = varDsc->GetRegisterType(tree);
if (type == TYP_SIMD16)
{
NYI_WASM_SIMD("SIMD16 local load");
}

GetEmitter()->emitIns_I(INS_local_get, EA_PTRSIZE, GetFramePointerRegIndex());
GetEmitter()->emitIns_S(ins_Load(type), emitTypeSize(type), tree->GetLclNum(), 0);
Expand Down
7 changes: 7 additions & 0 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2024,6 +2024,13 @@ void Compiler::compSetProcessor()
// Add virtual vector ISAs. These are both supported as part of the required baseline.
instructionSetFlags.AddInstructionSet(InstructionSet_Vector64);
instructionSetFlags.AddInstructionSet(InstructionSet_Vector128);
#elif defined(TARGET_WASM)
// Ensure required baseline ISAs are supported in JIT code, even if not passed in by the VM.
instructionSetFlags.AddInstructionSet(InstructionSet_WasmBase);
instructionSetFlags.AddInstructionSet(InstructionSet_PackedSimd);

// Add virtual vector ISA. Vector128 is part of the required Wasm SIMD baseline.
instructionSetFlags.AddInstructionSet(InstructionSet_Vector128);
#endif // TARGET_ARM64

assert(instructionSetFlags.Equals(EnsureInstructionSetFlagsAreValid(instructionSetFlags)));
Expand Down
6 changes: 4 additions & 2 deletions src/coreclr/jit/hwintrinsic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1048,8 +1048,8 @@ static const HWIntrinsicIsaRange hwintrinsicIsaRangeArray[] = {
{ NI_Illegal, NI_Illegal }, // SveSm4_Arm64
#elif defined(TARGET_WASM)
{ NI_Illegal, NI_Illegal }, // WasmBase
{ NI_Illegal, NI_Illegal }, // PackedSimd
{ FIRST_NI_Vector128, LAST_NI_Vector128 }, // Vector128
{ FIRST_NI_PackedSimd, LAST_NI_PackedSimd }, // PackedSimd
{ FIRST_NI_Vector128, LAST_NI_Vector128 }, // Vector128
Comment thread
adamperlin marked this conversation as resolved.
Outdated
// TODO-WASM: Add PackedSimd intrinsic ranges
Comment thread
adamperlin marked this conversation as resolved.
Outdated
Comment thread
adamperlin marked this conversation as resolved.
Outdated
Comment thread
adamperlin marked this conversation as resolved.
Outdated
#else
#error Unsupported platform
Expand Down Expand Up @@ -2275,6 +2275,8 @@ GenTree* Compiler::impHWIntrinsic(NamedIntrinsic intrinsic,
if ((simdSize != 8) && (simdSize != 16) && (simdSize != SIZE_UNKNOWN))
#elif defined(TARGET_XARCH)
if ((simdSize != 16) && (simdSize != 32) && (simdSize != 64))
#elif defined(TARGET_WASM)
if (simdSize != 16)
#endif // TARGET_*
{
assert(!"Unexpected SIMD size");
Expand Down
94 changes: 93 additions & 1 deletion src/coreclr/jit/hwintrinsic.h
Original file line number Diff line number Diff line change
Expand Up @@ -1463,8 +1463,100 @@ struct HWIntrinsic final
}
}
};
#else if defined(TARGET_WASM)
Comment thread
adamperlin marked this conversation as resolved.
Outdated
struct HWIntrinsic final
{
HWIntrinsic(const GenTreeHWIntrinsic* node)
: op1(nullptr)
, op2(nullptr)
, op3(nullptr)
, numOperands(0)
, baseType(TYP_UNDEF)
{
assert(node != nullptr);

#endif // TARGET_ARM64
id = node->GetHWIntrinsicId();
category = HWIntrinsicInfo::lookupCategory(id);

assert(HWIntrinsicInfo::RequiresCodegen(id));

InitializeOperands(node);
InitializeBaseType(node);
}

bool codeGenIsTableDriven() const
{
bool isTableDrivenCategory = category != HW_Category_Helper;
bool isTableDrivenFlag = !HWIntrinsicInfo::HasSpecialCodegen(id);

return isTableDrivenCategory && isTableDrivenFlag;
}

NamedIntrinsic id;
HWIntrinsicCategory category;
GenTree* op1;
GenTree* op2;
GenTree* op3;
size_t numOperands;
var_types baseType;

private:
void InitializeOperands(const GenTreeHWIntrinsic* node)
{
numOperands = node->GetOperandCount();

switch (numOperands)
{
case 3:
op3 = node->Op(3);
FALLTHROUGH;
case 2:
op2 = node->Op(2);
FALLTHROUGH;
case 1:
op1 = node->Op(1);
FALLTHROUGH;
case 0:
break;

default:
unreached();
}
}

void InitializeBaseType(const GenTreeHWIntrinsic* node)
{
baseType = node->GetSimdBaseType();

if (baseType == TYP_UNKNOWN)
{
assert((category == HW_Category_Scalar) || (category == HW_Category_Special));

if (HWIntrinsicInfo::BaseTypeFromFirstArg(id))
{
assert(op1 != nullptr);
baseType = op1->TypeGet();
}
else if (HWIntrinsicInfo::BaseTypeFromSecondArg(id))
{
// TODO-WASM: This case can likely be dropped
assert(op2 != nullptr);
baseType = op2->TypeGet();
}
else
{
baseType = node->TypeGet();
}

if (category == HW_Category_Scalar)
{
baseType = genActualType(baseType);
}
}
}
};

#endif // TARGET_WASM

#endif // FEATURE_HW_INTRINSICS

Expand Down
27 changes: 26 additions & 1 deletion src/coreclr/jit/hwintrinsiccodegenwasm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,32 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//
void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
{
NYI_WASM_SIMD("genHWIntrinsic");
// emitIns_v128_Imm
// emitIns_Lane
// emitIns_Memarg_Lane

const HWIntrinsic info(node);
genConsumeMultiOpOperands(node);

if (info.codeGenIsTableDriven())
{
instruction const ins = HWIntrinsicInfo::lookupIns(info.id, info.baseType, m_compiler);
assert(ins != INS_invalid);
if (info.category == HW_Category_SIMD)
{
GetEmitter()->emitIns(ins);
}
else
{
NYI_WASM_SIMD("!HW_Category_SIMD");
}
}
else
{
NYI_WASM_SIMD("!codeGenIsTableDriven");
}

WasmProduceReg(node);
}
Comment thread
adamperlin marked this conversation as resolved.

#endif // FEATURE_HW_INTRINSICS
Loading
Loading