'Why does gcc optimize out this comparison and how can I get it to get compiled in?
unsigned char c;
int n;
int main(){
if ((c && 0xc0) == 0xc0 ) {
n=0;
}
}
When testing on godbolt, only gcc does this.
Solution 1:[1]
It's actually very simple. Since you use && as an operator, gcc can deduce that the condition always yields false.
If you use the bitwise and operator (&), gcc adds code for the if:
#include <stdio.h>
unsigned char c = 0xff;
int n = 1;
int main(){
if ((c & 0xc0) == 0xc0 ) {
n=0;
}
printf("%d\n", n);
}
yields:
ronald@oncilla:~/tmp$ cc -S x.c && cat x.s
.file "x.c"
.text
.globl c
.data
.type c, @object
.size c, 1
c:
.byte -1
.globl n
.align 4
.type n, @object
.size n, 4
n:
.long 1
.section .rodata
.LC0:
.string "%d\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movzbl c(%rip), %eax
movzbl %al, %eax
andl $192, %eax
cmpl $192, %eax
jne .L2
movl $0, n(%rip)
.L2:
movl n(%rip), %eax
movl %eax, %esi
leaq .LC0(%rip), %rdi
movl $0, %eax
call printf@PLT
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu 9.4.0-1ubuntu1~20.04) 9.4.0"
.section .note.GNU-stack,"",@progbits
.section .note.gnu.property,"a"
.align 8
.long 1f - 0f
.long 4f - 1f
.long 5
0:
.string "GNU"
1:
.align 8
.long 0xc0000002
.long 3f - 2f
2:
.long 0x3
3:
.align 8
4:
Solution 2:[2]
In C && casts operands to bool which even though its an int, it is changed to 1 meaning true, if nonzero.
& is a bitwise and, which returns the bits that are the same. If you combine this with && it returns true if there are any bits left.
If you compile with -Wall you will get a warning when something gets optimized out at compile time.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Ronald |
| Solution 2 |
