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

[AArch64] Suboptimal comparison against certain immediates #76460

Open
Kmeakin opened this issue Dec 27, 2023 · 2 comments
Open

[AArch64] Suboptimal comparison against certain immediates #76460

Kmeakin opened this issue Dec 27, 2023 · 2 comments

Comments

@Kmeakin
Copy link
Contributor

Kmeakin commented Dec 27, 2023

LLVM canonicalizes non-strict comparisons against constants to strict comparisons (eg ule x, c => ult x, c+1). This results in less optimal AArch64 assembly if c can be encoded in a single mov instruction but c+1 or c-1 takes a mov+movk pair to encode:

godbolt

#include <stdbool.h>
#include <stdint.h>

#define u32 uint32_t
#define s32 int32_t

bool ule_11111111(u32 x) { return x <= 0x11111111; }
bool ule_22222222(u32 x) { return x <= 0x22222222; }
bool ule_33333333(u32 x) { return x <= 0x33333333; }
bool ule_44444444(u32 x) { return x <= 0x44444444; }
bool ule_55555555(u32 x) { return x <= 0x55555555; }
bool ule_66666666(u32 x) { return x <= 0x66666666; }
bool ule_77777777(u32 x) { return x <= 0x77777777; }
bool ule_88888888(u32 x) { return x <= 0x88888888; }
bool ule_99999999(u32 x) { return x <= 0x99999999; }

bool uge_11111111(u32 x) { return x >= 0x11111111; }
bool uge_22222222(u32 x) { return x >= 0x22222222; }
bool uge_33333333(u32 x) { return x >= 0x33333333; }
bool uge_44444444(u32 x) { return x >= 0x44444444; }
bool uge_55555555(u32 x) { return x >= 0x55555555; }
bool uge_66666666(u32 x) { return x >= 0x66666666; }
bool uge_77777777(u32 x) { return x >= 0x77777777; }
bool uge_88888888(u32 x) { return x >= 0x88888888; }
bool uge_99999999(u32 x) { return x >= 0x99999999; }

bool sle_11111111(s32 x) { return x <= 0x11111111; }
bool sle_22222222(s32 x) { return x <= 0x22222222; }
bool sle_33333333(s32 x) { return x <= 0x33333333; }
bool sle_44444444(s32 x) { return x <= 0x44444444; }
bool sle_55555555(s32 x) { return x <= 0x55555555; }
bool sle_66666666(s32 x) { return x <= 0x66666666; }
bool sle_77777777(s32 x) { return x <= 0x77777777; }
bool sle_88888888(s32 x) { return x <= 0x88888888; }
bool sle_99999999(s32 x) { return x <= 0x99999999; }

bool sge_11111111(s32 x) { return x >= 0x11111111; }
bool sge_22222222(s32 x) { return x >= 0x22222222; }
bool sge_33333333(s32 x) { return x >= 0x33333333; }
bool sge_44444444(s32 x) { return x >= 0x44444444; }
bool sge_55555555(s32 x) { return x >= 0x55555555; }
bool sge_66666666(s32 x) { return x >= 0x66666666; }
bool sge_77777777(s32 x) { return x >= 0x77777777; }
bool sge_88888888(s32 x) { return x >= 0x88888888; }
bool sge_99999999(s32 x) { return x >= 0x99999999; }
@llvmbot
Copy link
Collaborator

llvmbot commented Dec 27, 2023

@llvm/issue-subscribers-backend-aarch64

Author: Karl Meakin (Kmeakin)

LLVM canonicalizes non-strict comparisons against constants to strict comparisons (eg `ule x, c` => `ult x, c+1`. This results in less optimal AArch64 assembly if `c` can be encoded in a single `mov` instruction but `c+1` or `c-1` takes a `mov+movk` pair to encode:

godbolt

#include &lt;stdbool.h&gt;
#include &lt;stdint.h&gt;

#define u32 uint32_t
#define s32 int32_t

bool ule_11111111(u32 x) { return x &lt;= 0x11111111; }
bool ule_22222222(u32 x) { return x &lt;= 0x22222222; }
bool ule_33333333(u32 x) { return x &lt;= 0x33333333; }
bool ule_44444444(u32 x) { return x &lt;= 0x44444444; }
bool ule_55555555(u32 x) { return x &lt;= 0x55555555; }
bool ule_66666666(u32 x) { return x &lt;= 0x66666666; }
bool ule_77777777(u32 x) { return x &lt;= 0x77777777; }
bool ule_88888888(u32 x) { return x &lt;= 0x88888888; }
bool ule_99999999(u32 x) { return x &lt;= 0x99999999; }

bool uge_11111111(u32 x) { return x &gt;= 0x11111111; }
bool uge_22222222(u32 x) { return x &gt;= 0x22222222; }
bool uge_33333333(u32 x) { return x &gt;= 0x33333333; }
bool uge_44444444(u32 x) { return x &gt;= 0x44444444; }
bool uge_55555555(u32 x) { return x &gt;= 0x55555555; }
bool uge_66666666(u32 x) { return x &gt;= 0x66666666; }
bool uge_77777777(u32 x) { return x &gt;= 0x77777777; }
bool uge_88888888(u32 x) { return x &gt;= 0x88888888; }
bool uge_99999999(u32 x) { return x &gt;= 0x99999999; }

bool sle_11111111(s32 x) { return x &lt;= 0x11111111; }
bool sle_22222222(s32 x) { return x &lt;= 0x22222222; }
bool sle_33333333(s32 x) { return x &lt;= 0x33333333; }
bool sle_44444444(s32 x) { return x &lt;= 0x44444444; }
bool sle_55555555(s32 x) { return x &lt;= 0x55555555; }
bool sle_66666666(s32 x) { return x &lt;= 0x66666666; }
bool sle_77777777(s32 x) { return x &lt;= 0x77777777; }
bool sle_88888888(s32 x) { return x &lt;= 0x88888888; }
bool sle_99999999(s32 x) { return x &lt;= 0x99999999; }

bool sge_11111111(s32 x) { return x &gt;= 0x11111111; }
bool sge_22222222(s32 x) { return x &gt;= 0x22222222; }
bool sge_33333333(s32 x) { return x &gt;= 0x33333333; }
bool sge_44444444(s32 x) { return x &gt;= 0x44444444; }
bool sge_55555555(s32 x) { return x &gt;= 0x55555555; }
bool sge_66666666(s32 x) { return x &gt;= 0x66666666; }
bool sge_77777777(s32 x) { return x &gt;= 0x77777777; }
bool sge_88888888(s32 x) { return x &gt;= 0x88888888; }
bool sge_99999999(s32 x) { return x &gt;= 0x99999999; }

@resistor
Copy link
Collaborator

Done for GlobalISel

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants