Skip to content

Commit 92ad3c3

Browse files
authored
Fold some HW nodes for constant input (#78929)
1 parent 69cdbf1 commit 92ad3c3

File tree

5 files changed

+130
-12
lines changed

5 files changed

+130
-12
lines changed

src/coreclr/jit/assertionprop.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6119,6 +6119,9 @@ Compiler::fgWalkResult Compiler::optVNConstantPropCurStmt(BasicBlock* block, Sta
61196119
case GT_NEG:
61206120
case GT_CAST:
61216121
case GT_INTRINSIC:
6122+
#ifdef FEATURE_HW_INTRINSICS
6123+
case GT_HWINTRINSIC:
6124+
#endif
61226125
case GT_ARR_LENGTH:
61236126
break;
61246127

src/coreclr/jit/valuenum.cpp

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6001,6 +6001,59 @@ void ValueNumStore::SetVNIsCheckedBound(ValueNum vn)
60016001
m_checkedBoundVNs.AddOrUpdate(vn, true);
60026002
}
60036003

6004+
#ifdef FEATURE_HW_INTRINSICS
6005+
ValueNum ValueNumStore::EvalHWIntrinsicFunUnary(
6006+
var_types type, NamedIntrinsic ni, VNFunc func, ValueNum arg0VN, bool encodeResultType, ValueNum resultTypeVN)
6007+
{
6008+
if (IsVNConstant(arg0VN))
6009+
{
6010+
switch (ni)
6011+
{
6012+
#ifdef TARGET_ARM64
6013+
case NI_ArmBase_LeadingZeroCount:
6014+
#else
6015+
case NI_LZCNT_LeadingZeroCount:
6016+
#endif
6017+
{
6018+
UINT32 cns = (UINT32)GetConstantInt32(arg0VN);
6019+
int lzc = 0;
6020+
while (cns != 0)
6021+
{
6022+
cns = cns >> 1;
6023+
lzc++;
6024+
}
6025+
return VNForIntCon(32 - lzc);
6026+
}
6027+
6028+
#ifdef TARGET_ARM64
6029+
case NI_ArmBase_Arm64_LeadingZeroCount:
6030+
#else
6031+
case NI_LZCNT_X64_LeadingZeroCount:
6032+
#endif
6033+
{
6034+
UINT64 cns = (UINT64)GetConstantInt64(arg0VN);
6035+
int lzc = 0;
6036+
while (cns != 0)
6037+
{
6038+
cns = cns >> 1;
6039+
lzc++;
6040+
}
6041+
return VNForIntCon(64 - lzc);
6042+
}
6043+
6044+
default:
6045+
break;
6046+
}
6047+
}
6048+
6049+
if (encodeResultType)
6050+
{
6051+
return VNForFunc(type, func, arg0VN, resultTypeVN);
6052+
}
6053+
return VNForFunc(type, func, arg0VN);
6054+
}
6055+
#endif
6056+
60046057
ValueNum ValueNumStore::EvalMathFuncUnary(var_types typ, NamedIntrinsic gtMathFN, ValueNum arg0VN)
60056058
{
60066059
assert(arg0VN == VNNormalValue(arg0VN));
@@ -9769,25 +9822,21 @@ void Compiler::fgValueNumberHWIntrinsic(GenTreeHWIntrinsic* tree)
97699822

97709823
if (tree->GetOperandCount() == 1)
97719824
{
9772-
excSetPair = op1Xvnp;
9825+
ValueNum normalLVN =
9826+
vnStore->EvalHWIntrinsicFunUnary(tree->TypeGet(), intrinsicId, func, op1vnp.GetLiberal(),
9827+
encodeResultType, resultTypeVNPair.GetLiberal());
9828+
ValueNum normalCVN =
9829+
vnStore->EvalHWIntrinsicFunUnary(tree->TypeGet(), intrinsicId, func, op1vnp.GetConservative(),
9830+
encodeResultType, resultTypeVNPair.GetConservative());
97739831

9774-
if (encodeResultType)
9775-
{
9776-
normalPair = vnStore->VNPairForFunc(tree->TypeGet(), func, op1vnp, resultTypeVNPair);
9777-
assert((vnStore->VNFuncArity(func) == 2) || isVariableNumArgs);
9778-
}
9779-
else
9780-
{
9781-
normalPair = vnStore->VNPairForFunc(tree->TypeGet(), func, op1vnp);
9782-
assert((vnStore->VNFuncArity(func) == 1) || isVariableNumArgs);
9783-
}
9832+
normalPair = ValueNumPair(normalLVN, normalCVN);
9833+
excSetPair = op1Xvnp;
97849834
}
97859835
else
97869836
{
97879837
ValueNumPair op2vnp;
97889838
ValueNumPair op2Xvnp;
97899839
getOperandVNs(tree->Op(2), &op2vnp, &op2Xvnp);
9790-
97919840
excSetPair = vnStore->VNPExcSetUnion(op1Xvnp, op2Xvnp);
97929841
if (encodeResultType)
97939842
{

src/coreclr/jit/valuenum.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,6 +1108,9 @@ class ValueNumStore
11081108
EvalMathFuncBinary(typ, mthFunc, arg0VNP.GetConservative(), arg1VNP.GetConservative()));
11091109
}
11101110

1111+
ValueNum EvalHWIntrinsicFunUnary(
1112+
var_types type, NamedIntrinsic ni, VNFunc func, ValueNum arg0VN, bool encodeResultType, ValueNum resultTypeVN);
1113+
11111114
// Returns "true" iff "vn" represents a function application.
11121115
bool IsVNFunc(ValueNum vn);
11131116

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Runtime.CompilerServices;
6+
using System.Runtime.Intrinsics.Arm;
7+
using System.Runtime.Intrinsics.X86;
8+
using Xunit;
9+
10+
public class ScalarConstantFoldings
11+
{
12+
[Fact]
13+
public static void LeadingZeroCountTests()
14+
{
15+
if (Lzcnt.IsSupported)
16+
{
17+
Assert.Equal(32U, Lzcnt.LeadingZeroCount(0));
18+
Assert.Equal(31U, Lzcnt.LeadingZeroCount(1));
19+
Assert.Equal(17U, Lzcnt.LeadingZeroCount(31400));
20+
Assert.Equal(0U, Lzcnt.LeadingZeroCount(1U << 31));
21+
Assert.Equal(0U, Lzcnt.LeadingZeroCount(uint.MaxValue));
22+
Assert.Equal(0U, Lzcnt.LeadingZeroCount(uint.MaxValue - 1));
23+
}
24+
if (Lzcnt.X64.IsSupported)
25+
{
26+
Assert.Equal(64UL, Lzcnt.X64.LeadingZeroCount(0));
27+
Assert.Equal(63UL, Lzcnt.X64.LeadingZeroCount(1));
28+
Assert.Equal(49UL, Lzcnt.X64.LeadingZeroCount(31400));
29+
Assert.Equal(32UL, Lzcnt.X64.LeadingZeroCount(1UL << 31));
30+
Assert.Equal(0UL, Lzcnt.X64.LeadingZeroCount(1UL << 63));
31+
Assert.Equal(0UL, Lzcnt.X64.LeadingZeroCount(ulong.MaxValue));
32+
Assert.Equal(0UL, Lzcnt.X64.LeadingZeroCount(ulong.MaxValue - 1));
33+
}
34+
if (ArmBase.IsSupported)
35+
{
36+
Assert.Equal(32, ArmBase.LeadingZeroCount(0));
37+
Assert.Equal(31, ArmBase.LeadingZeroCount(1));
38+
Assert.Equal(17, ArmBase.LeadingZeroCount(31400));
39+
Assert.Equal(0, ArmBase.LeadingZeroCount(1U << 31));
40+
Assert.Equal(0, ArmBase.LeadingZeroCount(uint.MaxValue));
41+
Assert.Equal(0, ArmBase.LeadingZeroCount(uint.MaxValue - 1));
42+
}
43+
if (ArmBase.Arm64.IsSupported)
44+
{
45+
Assert.Equal(64, ArmBase.Arm64.LeadingZeroCount(0));
46+
Assert.Equal(63, ArmBase.Arm64.LeadingZeroCount(1));
47+
Assert.Equal(49, ArmBase.Arm64.LeadingZeroCount(31400));
48+
Assert.Equal(32, ArmBase.Arm64.LeadingZeroCount(1UL << 31));
49+
Assert.Equal(0, ArmBase.Arm64.LeadingZeroCount(1UL << 63));
50+
Assert.Equal(0, ArmBase.Arm64.LeadingZeroCount(ulong.MaxValue));
51+
Assert.Equal(0, ArmBase.Arm64.LeadingZeroCount(ulong.MaxValue - 1));
52+
}
53+
}
54+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<BuildAsStandalone>false</BuildAsStandalone>
4+
<Optimize>True</Optimize>
5+
</PropertyGroup>
6+
<ItemGroup>
7+
<Compile Include="$(MSBuildProjectName).cs" />
8+
</ItemGroup>
9+
</Project>

0 commit comments

Comments
 (0)