https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89506
--- Comment #6 from Jakub Jelinek <jakub at gcc dot gnu.org> --- int main () { for (long long j = -__INT_MAX__ - 1; j <= __INT_MAX__; j++) { int t, t2, c, c2; int i = j; asm volatile ("adds %0, %2, #1; mrs %1, apsr" : "=r" (t), "=r" (c) : "r" (i) : "cc"); asm volatile ("subs %0, %2, %3; mrs %1, apsr" : "=r" (t2), "=r" (c2) : "r" (i), "r" (-1) : "cc"); if (t != t2 || c != c2) __builtin_printf ("%d %d %d %d %d\n", i, t, t2, c, c2); } return 0; } suggests though (unless I've screwed up something) that at least for the adds r0, r0, #1 vs mvn r3, #0; subs r0, r0, r3 it doesn't make a difference. On the other side, int main () { for (long long j = -__INT_MAX__ - 1; j <= __INT_MAX__; j++) { int t, t2, c, c2; int i = j; asm volatile ("adds %0, %2, #2147483648; mrs %1, apsr" : "=r" (t), "=r" (c) : "r" (i) : "cc"); asm volatile ("subs %0, %2, #2147483648; mrs %1, apsr" : "=r" (t2), "=r" (c2) : "r" (i) : "cc"); if (t != t2 || c != c2) __builtin_printf ("%d %d %d %d %d\n", i, t, t2, c, c2); } return 0; } triggers on lots of values. If INT_MIN is the only problematic value, we could tweak the patch to only handle that value carefully, or always emit subs instead of adds for that case (e.g. by swapping the two alternatives).