Относительно оптимизации для "не statment" в c?
Изучая оптимизацию компилятора, я пишу коды на C
под Linux
с GCC
версия gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5.1)
Для постоянного not a statement
(нет) в C. Я сначала написал два кода y.c
второй x.c
а также generate their compiled assembly code
с помощью gcc -S
вариант.
Кулак код YC
desktop:~$ cat y.c
main()
{
int i=0;
}
desktop:~$ gcc -S y.c
desktop:~$
Второй код хс
desktop:~$ cat x.c
main()
{
int i=0;
/* Loops and if*/
while(0);
for(;0;);
if(0);
/* Arithmetic Operations */
i * i;
i / i;
i - i;
i + i;
i % i;
+i;
-i;
/* Comparison operators */
i == i;
i != i;
i < i;
i > i;
i >= i;
i <= i;
/* Bitwise Operations*/
i ^ i;
i | i;
i & i;
~i;
i << i;
i >> i;
/* Address Operatins*/
&i;
*(&i);
(&i)[i];
/* Ternary conditional operation*/
i? i : i;
/* Other Operations*/
sizeof(i);
(char)i;
/* Not-Logical Operation*/
!i;
/* Logical AND , OR Operators */
// i && i; // Commented && operation
// i || i; // Commented || operation
}
desktop:~$ gcc -S x.c
ВНИМАНИЕ: на этот раз последние две строки x.c
комментируются.
И как я ожидал. Нет разницы в их сгенерированных кодах сборки. Я сравнил x.s
а также y.s
с помощью diff
команда.
desktop:~$ diff x.s y.s
1c1
< .file "x.c"
---
> .file "y.c"
desktop:~$
Но когда я раскомментирую последний (или скажем добавить) две строки в x.c
,
i && i;
i || i;
Снова скомпилируйте xc с опцией -S и сравните с ys
desktop:~$ tail x.c
sizeof(i);
(char)i;
/* Not-Logical Operation*/
!i;
/* Logical AND , OR Operators */
i && i; // unCommented && operation
i || i; // unCommented || operation
}
desktop:~$ gcc -S x.c
desktop:~$ diff x.s y.s
1c1
< .file "x.c"
---
> .file "y.c"
10,21d9
< movl -4(%ebp), %eax
< testl %eax, %eax
< je .L3
< movl -4(%ebp), %eax
< testl %eax, %eax
< .L3:
< movl -4(%ebp), %eax
< testl %eax, %eax
< jne .L8
< movl -4(%ebp), %eax
< testl %eax, %eax
< .L8:
desktop:~$
Вопрос:
Я просто не могу понять, почему выражения i || i
а также i && i
не эквивалентны 'not a statement'
?
Зачем компилятор переносить эти два оператора в исполняемый файл (мы можем разобрать с objdump
получит такой же код). Что особенного в этих двух выражениях. они не включают =
операция.
Они меняют (устанавливают / сбрасывают) регистры флагов процессора? Я думаю, нет!
Четное /
Отказ от операции деления, которая может вызвать ошибку деления на ноль.
РЕДАКТИРОВАТЬ: Добавлен ответ
Там нет ничего особенного в i || i
а также i && i
выражения. Оба эквивалентны НЕ ЗАЯВЛЕНИЮ. И может быть удален GCC compiler
с некоторыми дополнительными усилиями.
Чтобы удалить это: -o2
а также -o3
флаги полезны:
Вот моя попытка!
desktop:~$ gcc -o2 -S y.c
desktop:~$ gcc -o2 -S x.c
desktop:~$ diff x.s y.s -y
.file "x.c" | .file "y.c"
.text .text
.p2align 4,,15 <
.globl main .globl main
.type main, @function .type main, @function
main: main:
pushl %ebp pushl %ebp
movl %esp, %ebp movl %esp, %ebp
popl %ebp | subl $16, %esp
> movl $0, -4(%ebp)
> leave
Дополнительные строки в RHS из-за несовпадения файлов.
Я также хотел бы добавить информацию, которая JAVA
а также C#
компиляторы отбрасывают это выражение без каких-либо флагов.
1 ответ
Включить оптимизацию, используя -O2
, и вы должны увидеть, что дополнительный код исчезнет.