Skip to content

Conversation

@tannergooding
Copy link
Member

This resolves #54956

@ghost ghost added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 31, 2022
@ghost ghost assigned tannergooding May 31, 2022
@ghost
Copy link

ghost commented May 31, 2022

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

Issue Details

This resolves #54956

Author: tannergooding
Assignees: -
Labels:

area-CodeGen-coreclr

Milestone: -

@SingleAccretion
Copy link
Contributor

SingleAccretion commented May 31, 2022

I remember there was some number of std::swaps in gentree.cpp that were responsible for the reordering, e. g.:

// GT_AND_NOT expects `op1 & ~op2`, but xarch does `~op1 & op2`
std::swap(op1, op2);
break;

They need to be dealt with in some way, as it is very surprising (-- prone to creating subtle bugs) for a gtNewXYZ function to potentially silently reorder operands (at a minimum, it needs to assert that it can do that safely, with gtCanSwapOrder(op1, op2)).

Additionally, it would be nice to add tests for all affected intrinsics (not just AndNot).

@tannergooding
Copy link
Member Author

@fanyang-mono, could you point me to where Mono makes decisions about side effects?

It looks like it has the same issue where its incorrectly re-ordering parameters for some intrinsics.

@fanyang-mono
Copy link
Member

@fanyang-mono, could you point me to where Mono makes decisions about side effects?

It looks like it has the same issue where its incorrectly re-ordering parameters for some intrinsics.

I was able to reproduce the issue locally with fullaot. I need some time to investigate and will get back to you tmr.

@vargaz
Copy link
Contributor

vargaz commented Jun 6, 2022

This will fix the mono failure:
#70308

@SamMonoRT
Copy link
Member

#70308 has merged, we should try re-running failing mono lanes

@fanyang-mono
Copy link
Member

/azp run runtime

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@tannergooding
Copy link
Member Author

They need to be dealt with in some way, as it is very surprising (-- prone to creating subtle bugs) for a gtNewXYZ function to potentially silently reorder operands (at a minimum, it needs to assert that it can do that safely, with gtCanSwapOrder(op1, op2)).

I agree, I'll log a new issue to track them since they are impacted a different way and will require different handling.

Additionally, it would be nice to add tests for all affected intrinsics (not just AndNot).

I'll work on adding these.

@tannergooding
Copy link
Member Author

CC. @dotnet/jit-contrib

@tannergooding
Copy link
Member Author

Ping @dotnet/jit-contrib

Would be good to get this in for 7 to help ensure code works as users expect without accidental side effect re-ordering.

Copy link
Member

@AndyAyersMS AndyAyersMS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems risky to selectively spill like this. If you have a bigger tree of intrinsics where many leaf operands can throw it seems like you could still reorder exceptions between operands at different levels.

@tannergooding
Copy link
Member Author

@AndyAyersMS do you have an example? Shouldn't impSpillSideEffect detect when a nested node also has side effects considering we rely on it for other phases of import?

@AndyAyersMS
Copy link
Member

We don't generally rely on it elsewhere; it is mainly called from impSpillSideEffects which is typically called with either NONE or ALL.

Test case would be something along these lines (might need to fiddle a bit to get it right). Call with d == 0.

    [MethodImpl(MethodImplOptions.NoInlining)]
    static Vector128<int> SideEffectsTree_Sse2_ShiftLeftLogical(Vector128<int>[] left, byte* right, int d)
    {
        if (Sse2.IsSupported)
        {
            return Sse2.ShiftLeftLogical(Sse2.ShiftLeftLogical(left[0], *right), 5 / d));

@tannergooding
Copy link
Member Author

tannergooding commented Jul 6, 2022

@AndyAyersMS, not sure I understand.

impSpillSideEffects effectively just does impSpillSideEffect for each stack argument from 0 (bottom) to chkLevel (which is frequently CHECK_SPILL_ALL).

So for CHECK_SPILL_ALL with 2 operands, it will spill op1, then op2; and only spill if that stack entry is marked as GTF_GLOB_EFFECT or GTF_SIDE_EFFECT -or- we're spilling global effects and its an address exposed local.


For most of these intrinsics we have a binary case where we need to swap operand 1 and 2. So we only check if op1 needs to be spilled. We shouldn't also need to check if op2 needs to be spilled because it will be evaluated after op1 if op1 is spilled first.

impSpillSideEffects itself wouldn't catch anything else since it doesn't do any additional checks on top outside impSpillSpecialSideEff() which we should never have since that only applies to exception objects. It would only potentially spill op2 when its unnecessary since it will always be the "next" operand in the evaluation order.

@tannergooding
Copy link
Member Author

Hmmm. I guess, if the stack had 3 operands and the unrelated operand had side effects that could be problematic. In which case we'd want impSpillSideEffects(true, verCurrentState.esStackDepth - 2, "Reason")....

Is that a concern here? The stack should normally be balanced, right?

@AndyAyersMS
Copy link
Member

Looking at it some more I think what you have will be ok, if there are more levels to the tree, you'll just accumulate more op1 spills along the way.

Eg if abstractly there is some tree like (% (% a b) c) where the expansion of % wants to reverse operand order (call this %r), you'll emit

t0  = a;
t1  = (%r b, t0);
... = (%r c, t1);

@tannergooding tannergooding merged commit bcb18f0 into dotnet:main Jul 7, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Aug 6, 2022
@tannergooding tannergooding deleted the fix-54956 branch November 11, 2022 15:27
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Some hardware intrinsic nodes can reorder side effects

6 participants