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

Allow constant propagation of Vector.Zero. #65028

Merged
merged 96 commits into from
Feb 18, 2022
Merged
Show file tree
Hide file tree
Changes from 90 commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
7aca5dc
Initial work
TIHan Dec 16, 2021
2752913
Added a comma to display
TIHan Dec 16, 2021
526e6c8
Cleanup
TIHan Dec 16, 2021
d850426
Fixing build
TIHan Dec 17, 2021
0ee6450
More cleanup
TIHan Dec 17, 2021
cb5a82e
Update comment
TIHan Dec 17, 2021
6ae9a94
Update comment
TIHan Dec 17, 2021
5c1997f
Added CompareEqual Vector64/128 with Zero tests
TIHan Jan 4, 2022
b33c72c
Merge remote-tracking branch 'upstream/main' into vector-64-128-zero-…
TIHan Jan 4, 2022
fd19fdc
Do not contain op1 for now
TIHan Jan 4, 2022
178ff52
Wrong intrinsic id used
TIHan Jan 5, 2022
c0a23c0
Removing generated tests
TIHan Jan 6, 2022
ad780ea
Removing generated tests
TIHan Jan 6, 2022
83c26ab
Added CompareEqual tests
TIHan Jan 6, 2022
9f7e7da
Supporting containment for first operand
TIHan Jan 6, 2022
1e67415
Fix test build
TIHan Jan 6, 2022
25b9d92
Passing correct register
TIHan Jan 6, 2022
c0dc7e4
Check IsVectorZero before not allocing a register
TIHan Jan 7, 2022
a718944
Update comment
TIHan Jan 7, 2022
1f45fa2
Fixing test
TIHan Jan 7, 2022
cb872da
Minor format change
TIHan Jan 7, 2022
c0708d7
Fixed formatting
TIHan Jan 7, 2022
bf49d11
Renamed test
TIHan Jan 8, 2022
bc7a557
Adding AdvSimd_Arm64 tests:
TIHan Jan 10, 2022
5939f36
Adding support for rest of 'cmeq' and 'fcmeq' instructions
TIHan Jan 10, 2022
6cd0ea8
Removing github csproj
TIHan Jan 10, 2022
2b30421
Minor test fix
TIHan Jan 10, 2022
0828de6
Fixed tests
TIHan Jan 10, 2022
fa43d19
Fix print
TIHan Jan 10, 2022
911f929
Minor format change
TIHan Jan 10, 2022
b91be1e
Fixing test
TIHan Jan 11, 2022
760a08c
Initial commit for Vector.Create to Vector.Zero normalization
TIHan Jan 14, 2022
c1a90b4
Added some emitter tests
TIHan Jan 18, 2022
32f86c1
Feedback
TIHan Jan 19, 2022
b08f552
Update emitarm64.cpp
TIHan Jan 19, 2022
c89e47b
Feedback
TIHan Jan 19, 2022
956e50a
Merge branch 'vector-64-128-zero-arm64-opts1' of github.com:TIHan/run…
TIHan Jan 19, 2022
2b526c9
Merge remote-tracking branch 'upstream' into vector-64-128-zero-arm64…
TIHan Jan 19, 2022
d51a988
Merge branch 'vector-64-128-zero-arm64-opts1' into vector-64-128-256-…
TIHan Jan 19, 2022
77c3d25
Merge remote-tracking branch 'upstream' into vector-64-128-256-Create…
TIHan Jan 20, 2022
b1065e8
Handling variations of Vector.Create
TIHan Jan 20, 2022
451f8e3
Use Operands iterator instead of edges
TIHan Jan 20, 2022
e231131
Fix condition
TIHan Jan 20, 2022
64ad95f
Simplify
TIHan Jan 20, 2022
333fc67
format
TIHan Jan 20, 2022
bc02904
Fixed IsFloatPositiveZero
TIHan Jan 21, 2022
d8c39e3
Uncomment
TIHan Jan 21, 2022
a5e51d5
Merging
TIHan Jan 21, 2022
38d9e7e
Updated tests to include Vector64.Create/Vector128.Create for ARM64
TIHan Jan 21, 2022
fb6047c
Making implementation of IsFloatPositiveZero explicit
TIHan Jan 21, 2022
bc1b9f4
Update src/coreclr/jit/gentree.cpp
TIHan Jan 24, 2022
d7904b6
Feedback
TIHan Jan 24, 2022
dbe1990
Merged
TIHan Jan 24, 2022
5b7d991
Update comment
TIHan Jan 24, 2022
5a7f674
Update comment
TIHan Jan 24, 2022
377b794
Do not perform optimization when VN CSE phase
TIHan Jan 24, 2022
1cf0b32
use ResetHWIntrinsicId
TIHan Jan 25, 2022
84f51cd
Assert !optValnumCSE_phase
TIHan Jan 25, 2022
31cd50d
Simplify IsVectorZero
TIHan Jan 25, 2022
383f147
Simplify IsVectorZero
TIHan Jan 25, 2022
29fb977
Simplify some uses of Vector*_get_Zero
TIHan Jan 25, 2022
51eae5a
Added another test
TIHan Jan 25, 2022
7d06ebf
Fixed formatting
TIHan Jan 25, 2022
177cd53
Revert lowering removal
TIHan Jan 25, 2022
32ac1fc
Merge remote-tracking branch 'upstream/main' into vector-64-128-256-C…
TIHan Feb 7, 2022
feed738
Initial work for optimizations on VectorZero value numbering
TIHan Feb 8, 2022
9840c5b
Allowing all Vector.Zero to be constant prop'ed. Added VNFuncSimdType…
TIHan Feb 8, 2022
36c4001
Update gentree.h
TIHan Feb 8, 2022
fc28677
Merge branch 'vector-64-128-256-Create-to-get_Zero' into vec-zero-vn
TIHan Feb 8, 2022
b074f09
Quick rename
TIHan Feb 8, 2022
2331a6e
Removed extra variable
TIHan Feb 8, 2022
f0d1ecc
Added default case
TIHan Feb 8, 2022
b15036f
Format
TIHan Feb 8, 2022
d27d877
Fixed vnDumpSimdType to take into account CorInfoType
TIHan Feb 9, 2022
e48ad65
Fixed gtNewSimdZeroNode to produce the right Vector*_get_Zero based o…
TIHan Feb 9, 2022
da48e4e
Formatting
TIHan Feb 10, 2022
3785e34
Feedback and a loop test
TIHan Feb 11, 2022
2b108d2
Added another test. Formatting fixes
TIHan Feb 11, 2022
b1c44cf
Added GetSimdBaseJitPreciseType
TIHan Feb 11, 2022
014b09f
Feedback
TIHan Feb 11, 2022
bb58117
Minor fix
TIHan Feb 11, 2022
7aae73b
Minor comment update
TIHan Feb 11, 2022
423d25a
Added another comment
TIHan Feb 11, 2022
616bb9b
Added another comment
TIHan Feb 11, 2022
84d3a94
Added another comment
TIHan Feb 11, 2022
ac3b474
Update comment
TIHan Feb 11, 2022
2769740
Formatting
TIHan Feb 11, 2022
92df1fd
Merge remote-tracking branch 'upstream/main' into vec-zero-vn
TIHan Feb 13, 2022
4a6d9a2
Feedback
TIHan Feb 14, 2022
2d6f367
Fixing build
TIHan Feb 14, 2022
759e8c0
Feedback
TIHan Feb 16, 2022
4c0f768
Merge remote-tracking branch 'upstream/main' into vector-64-128-256-C…
TIHan Feb 17, 2022
1d7e408
Merge branch 'vector-64-128-256-Create-to-get_Zero' into vec-zero-vn
TIHan Feb 17, 2022
0bdb08d
Merging
TIHan Feb 17, 2022
4bd81c7
Update assertionprop.cpp
TIHan Feb 18, 2022
396e8a1
Formatting
TIHan Feb 18, 2022
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
26 changes: 23 additions & 3 deletions src/coreclr/jit/assertionprop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2882,8 +2882,8 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree)
ValueNumPair vnPair = tree->gtVNPair;
ValueNum vnCns = vnStore->VNConservativeNormalValue(vnPair);

// Check if node evaluates to a constant.
if (!vnStore->IsVNConstant(vnCns))
// Check if node evaluates to a constant or Vector.Zero.
if (!vnStore->IsVNConstant(vnCns) && !vnStore->IsVNVectorZero(vnCns))
{
return nullptr;
}
Expand Down Expand Up @@ -3042,6 +3042,25 @@ GenTree* Compiler::optVNConstantPropOnTree(BasicBlock* block, GenTree* tree)
}
break;

#if FEATURE_HW_INTRINSICS
case TYP_SIMD8:
case TYP_SIMD12:
case TYP_SIMD16:
case TYP_SIMD32:
{
assert(vnStore->IsVNVectorZero(vnCns));

VNSimdTypeInfo vnInfo = vnStore->GetVectorZeroSimdTypeOfVN(vnCns);

assert(vnInfo.m_simdBaseJitType != CORINFO_TYPE_UNDEF);
assert(vnInfo.m_simdSize != 0);
assert(getSIMDTypeForSize(vnInfo.m_simdSize) == vnStore->TypeOfVN(vnCns));

conValTree = gtNewSimdZeroNode(tree->TypeGet(), vnInfo.m_simdBaseJitType, vnInfo.m_simdSize, true);
}
break;
#endif

case TYP_BYREF:
// Do not support const byref optimization.
break;
Expand Down Expand Up @@ -5449,7 +5468,8 @@ struct VNAssertionPropVisitorInfo
//
GenTree* Compiler::optExtractSideEffListFromConst(GenTree* tree)
{
assert(vnStore->IsVNConstant(vnStore->VNConservativeNormalValue(tree->gtVNPair)));
assert(vnStore->IsVNConstant(vnStore->VNConservativeNormalValue(tree->gtVNPair)) ||
vnStore->IsVNVectorZero(vnStore->VNConservativeNormalValue(tree->gtVNPair)));

GenTree* sideEffList = nullptr;

Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -6421,6 +6421,9 @@ class Compiler
GenTree* fgOptimizeCast(GenTreeCast* cast);
GenTree* fgOptimizeEqualityComparisonWithConst(GenTreeOp* cmp);
GenTree* fgOptimizeRelationalComparisonWithConst(GenTreeOp* cmp);
#ifdef FEATURE_HW_INTRINSICS
GenTree* fgOptimizeHWIntrinsic(GenTreeHWIntrinsic* node);
#endif
GenTree* fgOptimizeCommutativeArithmetic(GenTreeOp* tree);
GenTree* fgOptimizeAddition(GenTreeOp* add);
GenTree* fgOptimizeMultiply(GenTreeOp* mul);
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/jit/gentree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21496,7 +21496,7 @@ GenTree* Compiler::gtNewSimdZeroNode(var_types type,
#if defined(TARGET_XARCH)
intrinsic = (simdSize == 32) ? NI_Vector256_get_Zero : NI_Vector128_get_Zero;
#elif defined(TARGET_ARM64)
intrinsic = (simdSize == 16) ? NI_Vector128_get_Zero : NI_Vector64_get_Zero;
intrinsic = (simdSize > 8) ? NI_Vector128_get_Zero : NI_Vector64_get_Zero;
TIHan marked this conversation as resolved.
Show resolved Hide resolved
#else
#error Unsupported platform
#endif // !TARGET_XARCH && !TARGET_ARM64
Expand Down
78 changes: 42 additions & 36 deletions src/coreclr/jit/gentree.h
Original file line number Diff line number Diff line change
Expand Up @@ -5323,6 +5323,34 @@ struct GenTreeJitIntrinsic : public GenTreeMultiOp
return (CorInfoType)gtSimdBaseJitType;
}

CorInfoType GetNormalizedSimdBaseJitType() const
{
CorInfoType simdBaseJitType = GetSimdBaseJitType();
switch (simdBaseJitType)
{
case CORINFO_TYPE_NATIVEINT:
{
#ifdef TARGET_64BIT
return CORINFO_TYPE_LONG;
#else
return CORINFO_TYPE_INT;
#endif
}

case CORINFO_TYPE_NATIVEUINT:
{
#ifdef TARGET_64BIT
return CORINFO_TYPE_ULONG;
#else
return CORINFO_TYPE_UINT;
#endif
}

default:
return simdBaseJitType;
}
}

void SetSimdBaseJitType(CorInfoType simdBaseJitType)
{
gtSimdBaseJitType = (unsigned char)simdBaseJitType;
Expand Down Expand Up @@ -7702,16 +7730,20 @@ inline bool GenTree::IsSIMDZero() const
//
inline bool GenTree::IsFloatPositiveZero() const
{
return IsCnsFltOrDbl() && !IsCnsNonZeroFltOrDbl();
if (IsCnsFltOrDbl())
{
double constValue = AsDblCon()->gtDconVal;
return *(__int64*)&constValue == 0;
}

return false;
}

//-------------------------------------------------------------------
// IsVectorZero: returns true if this is an integral or floating-point (SIMD or HW intrinsic) vector
// with all its elements equal to zero.
// IsVectorZero: returns true if this node is a HWIntrinsic that is Vector*_get_Zero.
//
// Returns:
// True if this represents an integral or floating-point const (SIMD or HW intrinsic) vector with all its elements
// equal to zero.
// True if this represents a HWIntrinsic node that is Vector*_get_Zero.
//
// TODO: We already have IsSIMDZero() and IsIntegralConstVector(0),
// however, IsSIMDZero() does not cover hardware intrinsics, and IsIntegralConstVector(0) does not cover floating
Expand All @@ -7720,45 +7752,19 @@ inline bool GenTree::IsFloatPositiveZero() const
// separate ones; preferably this one.
inline bool GenTree::IsVectorZero() const
{
#ifdef FEATURE_SIMD
if (gtOper == GT_SIMD)
{
const GenTreeSIMD* node = AsSIMD();

if (node->GetSIMDIntrinsicId() == SIMDIntrinsicInit)
{
return (node->Op(1)->IsIntegralConst(0) || node->Op(1)->IsFloatPositiveZero());
}
}
#endif

#ifdef FEATURE_HW_INTRINSICS
if (gtOper == GT_HWINTRINSIC)
{
const GenTreeHWIntrinsic* node = AsHWIntrinsic();
const var_types simdBaseType = node->GetSimdBaseType();
const GenTreeHWIntrinsic* node = AsHWIntrinsic();
const NamedIntrinsic intrinsicId = node->GetHWIntrinsicId();

if (varTypeIsIntegral(simdBaseType) || varTypeIsFloating(simdBaseType))
if (node->GetOperandCount() == 0)
{
const NamedIntrinsic intrinsicId = node->GetHWIntrinsicId();

if (node->GetOperandCount() == 0)
{
#if defined(TARGET_XARCH)
return (intrinsicId == NI_Vector128_get_Zero) || (intrinsicId == NI_Vector256_get_Zero);
#elif defined(TARGET_ARM64)
return (intrinsicId == NI_Vector64_get_Zero) || (intrinsicId == NI_Vector128_get_Zero);
#endif // !TARGET_XARCH && !TARGET_ARM64
}
else if ((node->GetOperandCount() == 1) &&
(node->Op(1)->IsIntegralConst(0) || node->Op(1)->IsFloatPositiveZero()))
{
#if defined(TARGET_XARCH)
return (intrinsicId == NI_Vector128_Create) || (intrinsicId == NI_Vector256_Create);
return (intrinsicId == NI_Vector128_get_Zero) || (intrinsicId == NI_Vector256_get_Zero);
#elif defined(TARGET_ARM64)
return (intrinsicId == NI_Vector64_Create) || (intrinsicId == NI_Vector128_Create);
return (intrinsicId == NI_Vector64_get_Zero) || (intrinsicId == NI_Vector128_get_Zero);
#endif // !TARGET_XARCH && !TARGET_ARM64
}
}
}
#endif // FEATURE_HW_INTRINSICS
Expand Down
13 changes: 10 additions & 3 deletions src/coreclr/jit/liveness.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2066,16 +2066,23 @@ void Compiler::fgComputeLifeLIR(VARSET_TP& life, BasicBlock* block, VARSET_VALAR
case GT_PUTARG_STK:
case GT_IL_OFFSET:
case GT_KEEPALIVE:
#ifdef FEATURE_HW_INTRINSICS
case GT_HWINTRINSIC:
#endif // FEATURE_HW_INTRINSICS
// Never remove these nodes, as they are always side-effecting.
//
// NOTE: the only side-effect of some of these nodes (GT_CMP, GT_SUB_HI) is a write to the flags
// register.
// Properly modeling this would allow these nodes to be removed.
break;

#ifdef FEATURE_HW_INTRINSICS
case GT_HWINTRINSIC:
// Conservative: This only removes Vector.Zero nodes, but could be expanded.
if (node->IsVectorZero())
{
fgTryRemoveNonLocal(node, &blockRange);
}
break;
#endif // FEATURE_HW_INTRINSICS

case GT_NOP:
{
// NOTE: we need to keep some NOPs around because they are referenced by calls. See the dead store
Expand Down
90 changes: 90 additions & 0 deletions src/coreclr/jit/morph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13516,6 +13516,89 @@ GenTree* Compiler::fgOptimizeRelationalComparisonWithConst(GenTreeOp* cmp)
return cmp;
}

#ifdef FEATURE_HW_INTRINSICS

//------------------------------------------------------------------------
// fgOptimizeHWIntrinsic: optimize a HW intrinsic node
//
// Arguments:
// node - HWIntrinsic node to examine
//
// Returns:
// The original node if no optimization happened or if tree bashing occured.
// An alternative tree if an optimization happened.
//
// Notes:
// Checks for HWIntrinsic nodes: Vector64.Create/Vector128.Create/Vector256.Create,
// and if the call is one of these, attempt to optimize.
// This is post-order, meaning that it will not morph the children.
//
GenTree* Compiler::fgOptimizeHWIntrinsic(GenTreeHWIntrinsic* node)
{
assert(!optValnumCSE_phase);

if (opts.OptimizationDisabled())
{
return node;
}

switch (node->GetHWIntrinsicId())
{
case NI_Vector128_Create:
#if defined(TARGET_XARCH)
case NI_Vector256_Create:
#elif defined(TARGET_ARM64)
case NI_Vector64_Create:
#endif
{
bool hwAllArgsAreConstZero = true;
for (GenTree* arg : node->Operands())
{
if (!arg->IsIntegralConst(0) && !arg->IsFloatPositiveZero())
{
hwAllArgsAreConstZero = false;
break;
}
}

if (hwAllArgsAreConstZero)
{
switch (node->GetHWIntrinsicId())
{
case NI_Vector128_Create:
{
node->ResetHWIntrinsicId(NI_Vector128_get_Zero);
break;
}
#if defined(TARGET_XARCH)
case NI_Vector256_Create:
{
node->ResetHWIntrinsicId(NI_Vector256_get_Zero);
break;
}
#elif defined(TARGET_ARM64)
case NI_Vector64_Create:
{
node->ResetHWIntrinsicId(NI_Vector64_get_Zero);
break;
}
#endif
default:
unreached();
}
}
break;
}

default:
break;
}

return node;
}

#endif

//------------------------------------------------------------------------
// fgOptimizeCommutativeArithmetic: Optimizes commutative operations.
//
Expand Down Expand Up @@ -14447,6 +14530,13 @@ GenTree* Compiler::fgMorphMultiOp(GenTreeMultiOp* multiOp)
}
#endif // defined(FEATURE_HW_INTRINSICS) && defined(TARGET_XARCH)

#ifdef FEATURE_HW_INTRINSICS
if (multiOp->OperIsHWIntrinsic() && !optValnumCSE_phase)
{
return fgOptimizeHWIntrinsic(multiOp->AsHWIntrinsic());
}
#endif

return multiOp;
}
#endif // defined(FEATURE_SIMD) || defined(FEATURE_HW_INTRINSICS)
Expand Down
Loading