In integer divisible by power-of-2 check, C2 compiler generates conditional negation instructions before the actual zero check.
if ( a % 2 == 0 ) {
// bla bla bla ...
}
Below is code generated on x86_64
1. 0x00007f467d1518cc: mov %esi, %r10d
2. 0x00007f467d1518cf: and $0x1, %r10d
3. 0x00007f467d1518d3: test %esi, %esi
4. 0x00007f467d1518d5: jge 0x00007f467d1518da
5. 0x00007f467d1518d7: neg %r10d
6. 0x00007f467d1518da: test %r10d, %r10d
7. 0x00007f467d1518dd: je 0x00007f467d1518f1
We see that instructions 3 to 5 are computing the conditional negation. They are used to handle possibly negative dividend in the modulo operation, but they are redundant for the zero checks below since the negation of a zero (non-zero) is also a zero (non-zero). Below is the simplified code if the conditional negation is eliminated.
0x00007f79e912e24c: test $0x1,%esi
0x00007f79e912e252: je 0x00007f79e912e266
This optimization will also benefit other platforms such as AArch64
Before elimination
0x0000ffff6d168e54: and w10, w1, #0x1
0x0000ffff6d168e58: tbz w1, #31, 0x0000ffff6d168e60
0x0000ffff6d168e5c: neg w10, w10
0x0000ffff6d168e60: cbz w10, 0x0000ffff6d168e7c
After elimination
0x0000ffff8c6fc054: tbz w1, #0, 0x0000ffff8c6fc070
if ( a % 2 == 0 ) {
// bla bla bla ...
}
Below is code generated on x86_64
1. 0x00007f467d1518cc: mov %esi, %r10d
2. 0x00007f467d1518cf: and $0x1, %r10d
3. 0x00007f467d1518d3: test %esi, %esi
4. 0x00007f467d1518d5: jge 0x00007f467d1518da
5. 0x00007f467d1518d7: neg %r10d
6. 0x00007f467d1518da: test %r10d, %r10d
7. 0x00007f467d1518dd: je 0x00007f467d1518f1
We see that instructions 3 to 5 are computing the conditional negation. They are used to handle possibly negative dividend in the modulo operation, but they are redundant for the zero checks below since the negation of a zero (non-zero) is also a zero (non-zero). Below is the simplified code if the conditional negation is eliminated.
0x00007f79e912e24c: test $0x1,%esi
0x00007f79e912e252: je 0x00007f79e912e266
This optimization will also benefit other platforms such as AArch64
Before elimination
0x0000ffff6d168e54: and w10, w1, #0x1
0x0000ffff6d168e58: tbz w1, #31, 0x0000ffff6d168e60
0x0000ffff6d168e5c: neg w10, w10
0x0000ffff6d168e60: cbz w10, 0x0000ffff6d168e7c
After elimination
0x0000ffff8c6fc054: tbz w1, #0, 0x0000ffff8c6fc070