Skip to content

Difference of Codegen in JIT ASM when using Negation / if-else block code #81479

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

Closed
ShreyasJejurkar opened this issue Feb 1, 2023 · 4 comments · Fixed by #81880
Closed

Difference of Codegen in JIT ASM when using Negation / if-else block code #81479

ShreyasJejurkar opened this issue Feb 1, 2023 · 4 comments · Fixed by #81880
Assignees
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Milestone

Comments

@ShreyasJejurkar
Copy link
Contributor

Was playing with the JIT ASM code and found this interesting difference when using the Negation operator as compared to the if and else block.

public class C 
{
    public bool NegationOperator(bool input) 
    {
        return !input;
    }
    
    public bool IfElseCondition(bool input) 
    {
        if (input)
        {
            return false;
        } 
        else 
        {
            return true;
        }
    }
}

As you can see above we are doing the same thing, in both of the code-block we are just reverting the result based on the input value.
I expect to have the same code-gen generated for both of the code blocks because we are dealing with all constants values except input parameters (which is technically also a constant as it can have possible 2 values only) so JIT can see that and should fold.

But interestingly if-else block code generates a different code than the NegationOperator method.

C.NegationOperator(Boolean)
    L0000: xor eax, eax
    L0002: test dl, dl
    L0004: sete al
    L0007: ret

C.IfElseCondition(Boolean)
    L0000: test dl, dl
    L0002: je short L0007
    L0004: xor eax, eax
    L0006: ret
    L0007: mov eax, 1
    L000c: ret

Sharplab link

Why there is a difference in codegen!? Can't we generate the same ASM code for the IfElseCondition method just like we did it for NegationOperator method? I guess we can avoid je instruction in IfElseCondition.

@ghost ghost 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 Feb 1, 2023
@ghost
Copy link

ghost commented Feb 1, 2023

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

Issue Details

Was playing with the JIT ASM code and found this interesting difference when using the Negation operator as compared to the if and else block.

public class C 
{
    public bool NegationOperator(bool input) 
    {
        return !input;
    }
    
    public bool IfElseCondition(bool input) 
    {
        if (input)
        {
            return false;
        } 
        else 
        {
            return true;
        }
    }
}

As you can see above we are doing the same thing, in both of the code-block we are just reverting the result based on the input value.
I expect to have the same code-gen generated for both of the code blocks because we are dealing with all constants values except input parameters (which is technically also a constant as it can have possible 2 values only) so JIT can see that and should fold.

But interestingly if-else block code generates a different code than the NegationOperator method.

C.NegationOperator(Boolean)
    L0000: xor eax, eax
    L0002: test dl, dl
    L0004: sete al
    L0007: ret

C.IfElseCondition(Boolean)
    L0000: test dl, dl
    L0002: je short L0007
    L0004: xor eax, eax
    L0006: ret
    L0007: mov eax, 1
    L000c: ret

Sharplab link

Why there is a difference in codegen!? Can't we generate the same ASM code for the IfElseCondition method just like we did it for NegationOperator method? I guess we can avoid je instruction in IfElseCondition.

Author: ShreyasJejurkar
Assignees: -
Labels:

area-CodeGen-coreclr

Milestone: -

@EgorBo
Copy link
Member

EgorBo commented Feb 1, 2023

This is fixed in .net 8 for arm64, x64 support is coming with #81267

@kunalspathak
Copy link
Member

@jakobbotsch - can you close this once you verify after merging #81267?

@jakobbotsch
Copy link
Member

It is going to need a small follow-up to transform SELECT(cond, 1/0, 0/1) into SETCC, but I can take care of that too.

@jakobbotsch jakobbotsch self-assigned this Feb 1, 2023
@JulieLeeMSFT JulieLeeMSFT added this to the 8.0.0 milestone Feb 3, 2023
@ghost ghost removed the untriaged New issue has not been triaged by the area owner label Feb 3, 2023
jakobbotsch added a commit to jakobbotsch/runtime that referenced this issue Feb 9, 2023
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Feb 9, 2023
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Feb 9, 2023
@ghost ghost locked as resolved and limited conversation to collaborators Mar 11, 2023
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 a pull request may close this issue.

5 participants