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

Improve morphing of bit comparisons to constant 0/1 #73120

Merged
merged 12 commits into from
Sep 6, 2022

Conversation

dubiousconst282
Copy link
Contributor

@dubiousconst282 dubiousconst282 commented Jul 31, 2022

This PR does the following:

  • Allow morphing ((x >> CNS(y)) & 1) EQ/NE 0/1 -> (x & CNS(1 << y)) EQ/NE 0 with non-constant y, but only in some cases (if it's comparing the result to non-zero, or if the node is being used by a branch). This allows the lowering pass to create BT nodes for the latter pattern.
  • Lower EQ(AND(x, 1), 1) into AND(x, 1) by checking for TEST_NE instead of EQ/NE nodes. This should remove the need to identify variations such as (x & 1) != 0, while also avoiding interferences with later transforms based on EQ/NE nodes.
  • Lower NE/EQ(AND(x, 1), 0/1) into AND(x, 1)

I wasn't able to get the morph heuristic to work with (x >> y & 1) != 1, because the IR looks like EQ(EQ(..., 1), 0), but there are no diffs in this case.

Fixes #72986.

Diffs
    public static string BitTest_If_Ne0(int x, int y) => (x >> y & 1) != 0 ? "X" : " ";
    public static bool BitTest_Eq0(int x, int y) => (x >> y & 1) == 0;
    public static bool BitTest_Eq1(int x, int y) => (x >> y & 1) == 1;
    public static bool BitTest_Ne0(int x, int y) => (x >> y & 1) != 0;
    public static bool BitTest_Ne1(int x, int y) => (x >> y & 1) != 1;
    public static bool And1_Eq0(int x) => (x & 1) == 0;
    public static bool And1_Eq1(int x) => (x & 1) == 1;
    public static bool And1_Ne0(int x) => (x & 1) != 0;
    public static bool And1_Ne1(int x) => (x & 1) != 1;
 ; Assembly listing for method Program:BitTest_If_Ne0(int,int):System.String
-       sarx     eax, ecx, edx
-       test     al, 1
-       jne      SHORT G_M39616_IG05
+       bt       ecx, edx
+       jb       SHORT G_M39616_IG05
        mov      rax, 0xD1FFAB1E      ; " "
        mov      rax, gword ptr [rax]
        ret
        mov      rax, 0xD1FFAB1E      ; "X"
        mov      rax, gword ptr [rax]
        ret
 ; Assembly listing for method Program:BitTest_Eq0(int,int):bool
-       sarx     eax, ecx, edx
-       test     al, 1
-       sete     al
+       bt       ecx, edx
+       setae    al
        movzx    rax, al
        ret
 ; Assembly listing for method Program:BitTest_Eq1(int,int):bool
        sarx     eax, ecx, edx
        and      eax, 1
        ret
 ; Assembly listing for method Program:BitTest_Ne0(int,int):bool
        sarx     eax, ecx, edx
-       test     al, 1
-       setne    al
-       movzx    rax, al
+       and      eax, 1
        ret
 ; Assembly listing for method Program:BitTest_Ne1(int,int):bool
        sarx     eax, ecx, edx
        test     al, 1
        sete     al
        movzx    rax, al
        ret
 ; Assembly listing for method Program:And1_Eq0(int):bool
        xor      eax, eax
        test     cl, 1
        sete     al
        ret
 ; Assembly listing for method Program:And1_Eq1(int):bool
        mov      eax, ecx
        and      eax, 1
        ret
 ; Assembly listing for method Program:And1_Ne0(int):bool
-       xor      eax, eax
-       test     cl, 1
-       setne    al
+       mov      eax, ecx
+       and      eax, 1
        ret
 ; Assembly listing for method Program:And1_Ne1(int):bool
        xor      eax, eax
        test     cl, 1
        sete     al
        ret

SPMI diffs

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jul 31, 2022
@ghost ghost added the community-contribution Indicates that the PR has been added by a community member label Jul 31, 2022
@dnfadmin
Copy link

dnfadmin commented Jul 31, 2022

CLA assistant check
All CLA requirements met.

@ghost
Copy link

ghost commented Jul 31, 2022

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

Issue Details

This PR does the following:

  • Allow morphing ((x >> CNS(y)) & 1) EQ/NE 0/1 -> (x & CNS(1 << y)) EQ/NE 0 with non-constant y. This allows the lowering pass to create BT nodes for the latter pattern.
  • Lower EQ(AND(x, 1), 1) into AND(x, 1) by checking for TEST_NE instead of EQ/NE nodes. This should remove the need to identify variations such as (x & 1) != 0, while also avoiding interferences with later transforms based on EQ/NE nodes.

Fixes #72986.

Diffs
public static bool BitTest_Eq0(int x, int y) => (x >> y & 1) == 0;
public static bool BitTest_Eq1(int x, int y) => (x >> y & 1) == 1;
public static bool BitTest_Ne0(int x, int y) => (x >> y & 1) != 0;
public static bool BitTest_Ne1(int x, int y) => (x >> y & 1) != 1;
public static bool And1_Eq0(int x) => (x & 1) == 0;
public static bool And1_Eq1(int x) => (x & 1) == 1;
public static bool And1_Ne0(int x) => (x & 1) != 0;
public static bool And1_Ne1(int x) => (x & 1) != 1;
 ; Assembly listing for method Program:BitTest_Eq0(int,int):bool
-       8BC1                 mov      eax, ecx
-       8BCA                 mov      ecx, edx
-       D3F8                 sar      eax, cl
-       A801                 test     al, 1
-       0F94C0               sete     al
+       0FA3D1               bt       ecx, edx
+       0F93C0               setae    al
        0FB6C0               movzx    rax, al
        C3                   ret
 ; Assembly listing for method Program:BitTest_Eq1(int,int):bool
-       8BC1                 mov      eax, ecx
-       8BCA                 mov      ecx, edx
-       D3F8                 sar      eax, cl
-       83E001               and      eax, 1
+       0FA3D1               bt       ecx, edx
+       0F92C0               setb     al
+       0FB6C0               movzx    rax, al
        C3                   ret
 ; Assembly listing for method Program:BitTest_Ne0(int,int):bool
-       8BC1                 mov      eax, ecx
-       8BCA                 mov      ecx, edx
-       D3F8                 sar      eax, cl
-       A801                 test     al, 1
-       0F95C0               setne    al
+       0FA3D1               bt       ecx, edx
+       0F92C0               setb     al
        0FB6C0               movzx    rax, al
        C3                   ret
 ; Assembly listing for method Program:BitTest_Ne1(int,int):bool
-       8BC1                 mov      eax, ecx
-       8BCA                 mov      ecx, edx
-       D3F8                 sar      eax, cl
-       A801                 test     al, 1
-       0F94C0               sete     al
+       0FA3D1               bt       ecx, edx
+       0F93C0               setae    al
        0FB6C0               movzx    rax, al
        C3                   ret
 ; Assembly listing for method Program:And1_Eq0(int):bool
        33C0                 xor      eax, eax
        F6C101               test     cl, 1
        0F94C0               sete     al
        C3                   ret
 ; Assembly listing for method Program:And1_Eq1(int):bool
-       8BC1                 mov      eax, ecx
-       83E001               and      eax, 1
+       B801000000           mov      eax, 1
+       23C1                 and      eax, ecx
        C3                   ret
 ; Assembly listing for method Program:And1_Ne0(int):bool
-       33C0                 xor      eax, eax
-       F6C101               test     cl, 1
-       0F95C0               setne    al
+       B801000000           mov      eax, 1
+       23C1                 and      eax, ecx
        C3                   ret
 ; Assembly listing for method Program:And1_Ne1(int):bool
        33C0                 xor      eax, eax
        F6C101               test     cl, 1
        0F94C0               sete     al
        C3                   ret
Author: dubiousconst282
Assignees: -
Labels:

area-CodeGen-coreclr

Milestone: -

@EgorBo EgorBo added this to the 8.0.0 milestone Jul 31, 2022
@AndyAyersMS
Copy link
Member

/azp run fuzzlyn

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

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.

Changes LGTM. Thanks!

We will hold off on merging until the 7.0 release branches off from main (see #72297 for schedule).

@jakobbotsch
Copy link
Member

The Fuzzlyn failures look like the ones fixed by #73146. I'm not really sure what happened here, normally jobs triggered via the bot run on a merge of the PR head commit and current main, but in this case it ran directly on the head commit 991ff69 that does not have c4ea81d.

I would retrigger it but since this is still a draft I'll wait.

@dubiousconst282
Copy link
Contributor Author

Thanks! I was holding on draft to investigate regressions from the CI diffs, but there aren't many. I think it's ready now.

@dubiousconst282 dubiousconst282 marked this pull request as ready for review August 3, 2022 04:51
@AndyAyersMS
Copy link
Member

@dubiousconst282 we are ready to take in new changes once more.

Can you fix the merge conflicts?

@AndyAyersMS AndyAyersMS added the needs-author-action An issue or pull request that requires more info or actions from the author. label Aug 26, 2022
@ghost ghost removed the needs-author-action An issue or pull request that requires more info or actions from the author. label Aug 27, 2022
@dubiousconst282
Copy link
Contributor Author

@AndyAyersMS Done

@AndyAyersMS
Copy link
Member

/azp run fuzzlyn

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@AndyAyersMS
Copy link
Member

Interesting and almost certainly unrelated Fuzzlyn failure. No core dump so not sure this is actionable.

FYI @janvorli in case we start seeing this more often.

OSX arm64 checked

Assert failure(PID 24175 [0x00005e6f], Thread: 2129739 [0x207f4b]): !"Unable to commit a loaderheap code page"
    File: /Users/runner/work/1/s/src/coreclr/utilcode/loaderheap.cpp Line: 1173
    Image: /private/tmp/helix/working/A4B6094A/p/CoreRoot/corerun

@AndyAyersMS AndyAyersMS merged commit 1b4ed22 into dotnet:main Sep 6, 2022
@AndyAyersMS
Copy link
Member

@dubiousconst282 thank you for your contribution!

@dubiousconst282 dubiousconst282 deleted the bt-shift-morph branch September 6, 2022 20:24
@ghost ghost locked as resolved and limited conversation to collaborators Oct 9, 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 community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

JIT: Recognize 'bt' bit test idiom
5 participants