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

VN does not number some HWI loads properly #63499

Closed
SingleAccretion opened this issue Jan 7, 2022 · 4 comments · Fixed by #70621
Closed

VN does not number some HWI loads properly #63499

SingleAccretion opened this issue Jan 7, 2022 · 4 comments · Fixed by #70621
Assignees
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI bug
Milestone

Comments

@SingleAccretion
Copy link
Contributor

Reproduction:

using System;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;

unsafe
{
    var dbls = stackalloc double[] { 1, 1 };
    Console.WriteLine(Problem(dbls));
}

[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
static unsafe bool Problem(double* a)
{
    const double Mask = -0.0;

    var v1 = Avx.MaskLoad(a, Vector128.Create(0, Mask));
    if (v1.GetElement(0) == 0)
    {
        var v2 = Avx.MaskLoad(a, Vector128.Create(Mask, 0));
        if (v2.GetElement(0) == 0)
        {
            return true;
        }
    }

    return false;
}

Expected result: false.
Actual result: true.

Cause: in the below VN code we only encode the value of the address operand:

if (isMemoryLoad)
{
ValueNumPair op1vnp;
ValueNumPair op1Xvnp;
vnStore->VNPUnpackExc(tree->Op(1)->gtVNPair, &op1vnp, &op1Xvnp);
// The addrVN incorporates both op1's ValueNumber and the func operation
// The func is used because operations such as LoadLow and LoadHigh perform
// different operations, thus need to compute different ValueNumbers
// We don't need to encode the result type as it will be encoded by the opcode in 'func'
//
ValueNum addrVN = vnStore->VNForFunc(TYP_BYREF, func, op1vnp.GetLiberal());
// The address could point anywhere, so it is an ByrefExposed load.
//
ValueNum loadVN = fgValueNumberByrefExposedLoad(tree->TypeGet(), addrVN);
tree->gtVNPair.SetLiberal(loadVN);
tree->gtVNPair.SetConservative(vnStore->VNForExpr(compCurBB, tree->TypeGet()));
tree->gtVNPair = vnStore->VNPWithExc(tree->gtVNPair, op1Xvnp);
fgValueNumberAddExceptionSetForIndirection(tree, tree->Op(1));
return;
}

We need to encode the value of the second parameter (if it is present) as well.

FYI @tannergooding

@dotnet-issue-labeler dotnet-issue-labeler bot added area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI untriaged New issue has not been triaged by the area owner labels Jan 7, 2022
@ghost
Copy link

ghost commented Jan 7, 2022

Tagging subscribers to this area: @JulieLeeMSFT
See info in area-owners.md if you want to be subscribed.

Issue Details

Reproduction:

using System;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;

unsafe
{
    var dbls = stackalloc double[] { 1, 1 };
    Console.WriteLine(Problem(dbls));
}

[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
static unsafe bool Problem(double* a)
{
    const double Mask = -0.0;

    var v1 = Avx.MaskLoad(a, Vector128.Create(0, Mask));
    if (v1.GetElement(0) == 0)
    {
        var v2 = Avx.MaskLoad(a, Vector128.Create(Mask, 0));
        if (v2.GetElement(0) == 0)
        {
            return true;
        }
    }

    return false;
}

Expected result: false.
Actual result: true.

Cause: in the below VN code we only encode the value of the address operand:

if (isMemoryLoad)
{
ValueNumPair op1vnp;
ValueNumPair op1Xvnp;
vnStore->VNPUnpackExc(tree->Op(1)->gtVNPair, &op1vnp, &op1Xvnp);
// The addrVN incorporates both op1's ValueNumber and the func operation
// The func is used because operations such as LoadLow and LoadHigh perform
// different operations, thus need to compute different ValueNumbers
// We don't need to encode the result type as it will be encoded by the opcode in 'func'
//
ValueNum addrVN = vnStore->VNForFunc(TYP_BYREF, func, op1vnp.GetLiberal());
// The address could point anywhere, so it is an ByrefExposed load.
//
ValueNum loadVN = fgValueNumberByrefExposedLoad(tree->TypeGet(), addrVN);
tree->gtVNPair.SetLiberal(loadVN);
tree->gtVNPair.SetConservative(vnStore->VNForExpr(compCurBB, tree->TypeGet()));
tree->gtVNPair = vnStore->VNPWithExc(tree->gtVNPair, op1Xvnp);
fgValueNumberAddExceptionSetForIndirection(tree, tree->Op(1));
return;
}

We need to encode the value of the second parameter (if it is present) as well.

FYI @tannergooding

Author: SingleAccretion
Assignees: -
Labels:

area-CodeGen-coreclr, untriaged

Milestone: -

@SingleAccretion SingleAccretion added this to the 7.0.0 milestone Jan 7, 2022
@SingleAccretion SingleAccretion removed the untriaged New issue has not been triaged by the area owner label Jan 7, 2022
@SingleAccretion SingleAccretion self-assigned this Jan 7, 2022
@SingleAccretion
Copy link
Contributor Author

VN also doesn't account for the fact LoadHigh-family of intrinsics have the address as the second operand, not the first.

@SingleAccretion
Copy link
Contributor Author

Another issue: "helper" intrinsics, i. e. the recently added V128 ones, aren't accounted as a memory load for at all.

@tannergooding
Copy link
Member

Another issue: "helper" intrinsics, i. e. the recently added V128 ones, aren't accounted as a memory load for at all.

These ones should be handled on import by converting them to the relevant actual intrinsics.

@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Jun 11, 2022
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Jun 15, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Jul 15, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants