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

x64Emitter: Emit shorter MOVs for 32-bit immediates #8133

Merged
merged 2 commits into from
Jan 6, 2020

Conversation

Sintendo
Copy link
Member

Expands what we did in #7414 so it works for 32-bit immediates as well. We can emit a shorter 32-bit instruction for 32-bit immediates in [0, 0x7FFFFFFF].
We hit this in cmpXX, and possibly some other places too.

Before:

0:  48 c7 c0 ff ff ff 7f    mov    rax,0x7fffffff

After:

0:  b8 ff ff ff 7f          mov    eax,0x7fffffff

Sintendo added 2 commits May 29, 2019 01:04
Prior to this commit, the emitter would emit a 7-byte instruction when
loading a 32-bit immediate to a 64-bit register.

0:  48 c7 c0 ff ff ff 7f    mov    rax,0x7fffffff

With this change, it will check if it can instead emit a load to a
32-bit register, which takes only 5 or 6 bytes.

0:  b8 ff ff ff 7f          mov    eax,0x7fffffff
@Tilka
Copy link
Member

Tilka commented Jun 2, 2019

This should work for the full 32-bit range since sign-extension only happens when the operand size is 64 bits, I think?

@Sintendo
Copy link
Member Author

Sintendo commented Jun 3, 2019

32-bit immediates are always sign extended when the destination is 64-bit, so we can only apply this when the immediate's highest bit is zero. Or perhaps I'm misunderstanding and you're actually referring to something else entirely?

@Tilka
Copy link
Member

Tilka commented Jun 3, 2019

That's the thing though, the destination isn't 64-bit.

@Sintendo
Copy link
Member Author

Sintendo commented Jun 3, 2019

Doesn't bits == 64 && a1.IsSimpleReg() ensure the destination is a 64-bit register?

@Tilka
Copy link
Member

Tilka commented Jun 3, 2019

But that's not what is actually emitted inside the if.

@Sintendo
Copy link
Member Author

Sintendo commented Jun 3, 2019

Well yes, that's the point of the optimization; we take advantage of x86-64 zero-extending values written to 32-bit registers when the immediate values allow for this.

There's three similar optimizations:

  1. transforming MOV(64, R(x), Imm64([0, 0xFFFFFFFF])) to MOV(32, R(x), Imm32([0, 0xFFFFFFFF]))
    This one applies to the whole 32-bit range and was implemented as part of x64Emitter: emit shorter MOVs for 64-bit immediates #7414 (53a9477).

  2. transforming MOV(64, R(x), Imm64([0xFFFFFFFF80000000, 0xFFFFFFFFFFFFFFFF])) to MOV(64, R(x), Imm32([0x80000000, 0xFFFFFFFF]))
    This one was also implemented as part of x64Emitter: emit shorter MOVs for 64-bit immediates #7414 (575f1b3). It technically also handles [0, 0x7FFFFFFF], but those are already covered by 1 anyway. It was done inside OpArg::WriteNormalOp, but in retrospect I should've probably just done that in XEmitter::MOV like the other two.

  3. transforming MOV(64, R(x), Imm32([0, 0x7FFFFFFF])) to MOV(32, R(x), Imm32([0, 0x7FFFFFFF]))
    This is what this pull request adds.

@Tilka
Copy link
Member

Tilka commented Jun 3, 2019

What I'm saying is the optimization replaces a 64-bit MOV with a 32-bit MOV that moves into a 32-bit register, so there is no 64-bit operand, so there is no sign-extension: https://godbolt.org/z/XZ42cy

@Sintendo
Copy link
Member Author

Sintendo commented Jun 3, 2019

Yes, which is why we can only apply this optimization when the sign-extension (64-bit instruction before optimization) and the zero-extension (32-bit instruction after optimization) give the same result.

MOV(64, R(x), Imm32(0xFFFFFFFF)); is equivalent to MOV(64, R(x), Imm64(0xFFFFFFFFFFFFFFFF));, not to MOV(32, R(x), Imm32(0xFFFFFFFF));.

I'd be happy to discuss this on IRC or something, because I think we're talking past each other here. :/

@Tilka
Copy link
Member

Tilka commented Jun 3, 2019

Oh, I see what you mean now.

@Tilka Tilka merged commit 6e18dfb into dolphin-emu:master Jan 6, 2020
@Sintendo Sintendo deleted the mov64imm32 branch June 8, 2021 13:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants