-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
[ARM64/Linux] Inefficient conditionals branching #12735
Comments
Not ARM64 specific, x64 generates: G_M55886_IG01:
4883EC28 sub rsp, 40
90 nop
G_M55886_IG02:
83FA03 cmp edx, 3
7507 jne SHORT G_M55886_IG03
B803000000 mov eax, 3
EB03 jmp SHORT G_M55886_IG04
G_M55886_IG03:
8D4201 lea eax, [rdx+1]
G_M55886_IG04:
83790802 cmp dword ptr [rcx+8], 2
760B jbe SHORT G_M55886_IG06
894118 mov dword ptr [rcx+24], eax
488BC1 mov rax, rcx
G_M55886_IG05:
4883C428 add rsp, 40
C3 ret
G_M55886_IG06:
E8169E385F call CORINFO_HELP_RNGCHKFAIL
CC int3 Here assertion propagation isn't very smart and substitutes
Because of the
Yes but it's a bit complicated because this isn't obvious in the IR until after register allocation when you'd need to figure out that the store is useless because both variables have been assigned the same register and that the block is empty otherwise. |
But the block doesn't have to be empty to remove the unconditional branch. The unconditional branch is always the last statement in the block, so if the edges were re-arranged such that the block you unconditionally branch to is the next BB after the one with the conditional you could just call through, or alternatively re-order the branch conditions, then you don't have to change the edges. Unless i'm missing something can't both of these be done before regalloc just purely from the control flow of the IR? |
I'm not sure I understand. If neither block is empty then the only flow control transform that you can do here is branch inversion and that doesn't help. Perhaps you have in mind an additional IR transform? int y;
if (n == 3)
y = n;
else
y = n + 1; could become int y = n;
if (n != 3)
y = y + 1; That would work but yes, the JIT doesn't do anything like this today. Though I happen to have an if conversion experiment that could be extended to handle this case. Maybe one day... There's a rather similar issue I opened a long time ago - #4326. |
No that's correct, In my original post I had confused the cases where it generated the You're right that if-conversion would certainly give the best code in such cases. |
With the latest HEAD, the code gets if converted, but the extra
Assertion propagation happens before the if conversion, so it makes sense that this still happens:
|
I can confirm the extra I did some hacking and got the Unfortunately, without introducing a new concept or doing Also, this pattern: if (n == 3) // including other relops
y = n;
else
y = n + 1; Can be reduced to: cmp w0, #3
cinc w0, w0, <cond> Related: #82031 |
The following
produces the following conditional (with
QuickJIT
off)so for both the if and else case it branches, it has no fall through case that doesn't
require the branch.
but also it has generated an extra mov here because it knows n is 3. However change the
condition to
and it now just re-uses the register containing n since it's dead after the if anyway
So not quite sure why the second case generates smaller code.
But again the conditional can just be re-arranged to
and remove a branch.
/CC @CarolEidt @tannergooding
category:cq
theme:basic-cq
skill-level:intermediate
cost:medium
The text was updated successfully, but these errors were encountered: