Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JIT: Enable CSE for VectorX.Create #50644

Merged
merged 4 commits into from
Apr 7, 2021
Merged
Changes from all commits
Commits
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
35 changes: 20 additions & 15 deletions src/coreclr/jit/valuenum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1900,7 +1900,9 @@ ValueNum ValueNumStore::VNForFunc(var_types typ, VNFunc func, ValueNum arg0VN, V
assert(arg0VN != NoVN && arg1VN != NoVN);
assert(arg0VN == VNNormalValue(arg0VN)); // Arguments carry no exceptions.
assert(arg1VN == VNNormalValue(arg1VN)); // Arguments carry no exceptions.
assert(VNFuncArity(func) == 2);

// Some SIMD functions with variable number of arguments are defined with zero arity
assert((VNFuncArity(func) == 0) || (VNFuncArity(func) == 2));
assert(func != VNF_MapSelect); // Precondition: use the special function VNForMapSelect defined for that.

ValueNum resultVN;
Expand Down Expand Up @@ -8918,26 +8920,24 @@ void Compiler::fgValueNumberHWIntrinsic(GenTree* tree)
assert(hwIntrinsicNode != nullptr);

// For safety/correctness we must mutate the global heap valuenumber
// for any HW intrinsic that performs a memory store operation
// for any HW intrinsic that performs a memory store operation
if (hwIntrinsicNode->OperIsMemoryStore())
{
fgMutateGcHeap(tree DEBUGARG("HWIntrinsic - MemoryStore"));
}

// Check for any intrintics that have variable number of args or more than 2 args
// For now we will generate a unique value number for these cases.
//
if ((HWIntrinsicInfo::lookupNumArgs(hwIntrinsicNode->gtHWIntrinsicId) == -1) ||
((tree->AsOp()->gtOp1 != nullptr) && (tree->AsOp()->gtOp1->OperIs(GT_LIST))))
if ((tree->AsOp()->gtOp1 != nullptr) && tree->gtGetOp1()->OperIs(GT_LIST))
{
// We have a HWINTRINSIC node in the GT_LIST form with 3 or more args
// Or the numArgs was specified as -1 in the numArgs column

// Generate unique VN
// TODO-CQ: allow intrinsics with GT_LIST to be properly VN'ed, it will
// allow use to process things like Vector128.Create(1,2,3,4) etc.
// Generate unique VN for now.
tree->gtVNPair.SetBoth(vnStore->VNForExpr(compCurBB, tree->TypeGet()));
return;
}

// We don't expect GT_LIST to be in the second op
assert((tree->AsOp()->gtOp2 == nullptr) || !tree->gtGetOp2()->OperIs(GT_LIST));

VNFunc func = GetVNFuncForNode(tree);
bool isMemoryLoad = hwIntrinsicNode->OperIsMemoryLoad();

Expand Down Expand Up @@ -8990,9 +8990,14 @@ void Compiler::fgValueNumberHWIntrinsic(GenTree* tree)
#endif
}

const bool isVariableNumArgs = HWIntrinsicInfo::lookupNumArgs(hwIntrinsicNode->gtHWIntrinsicId) == -1;

// There are some HWINTRINSICS operations that have zero args, i.e. NI_Vector128_Zero
if (tree->AsOp()->gtOp1 == nullptr)
{
// Currently we don't have intrinsics with variable number of args with a parameter-less option.
assert(!isVariableNumArgs);

if (encodeResultType)
{
// There are zero arg HWINTRINSICS operations that encode the result type, i.e. Vector128_AllBitSet
Expand All @@ -9018,12 +9023,12 @@ void Compiler::fgValueNumberHWIntrinsic(GenTree* tree)
if (encodeResultType)
{
normalPair = vnStore->VNPairForFunc(tree->TypeGet(), func, op1vnp, resvnp);
assert(vnStore->VNFuncArity(func) == 2);
assert((vnStore->VNFuncArity(func) == 2) || isVariableNumArgs);
}
else
{
normalPair = vnStore->VNPairForFunc(tree->TypeGet(), func, op1vnp);
assert(vnStore->VNFuncArity(func) == 1);
assert((vnStore->VNFuncArity(func) == 1) || isVariableNumArgs);
}
}
else
Expand All @@ -9036,12 +9041,12 @@ void Compiler::fgValueNumberHWIntrinsic(GenTree* tree)
if (encodeResultType)
{
normalPair = vnStore->VNPairForFunc(tree->TypeGet(), func, op1vnp, op2vnp, resvnp);
assert(vnStore->VNFuncArity(func) == 3);
assert((vnStore->VNFuncArity(func) == 3) || isVariableNumArgs);
}
else
{
normalPair = vnStore->VNPairForFunc(tree->TypeGet(), func, op1vnp, op2vnp);
assert(vnStore->VNFuncArity(func) == 2);
assert((vnStore->VNFuncArity(func) == 2) || isVariableNumArgs);
}
}
}
Expand Down