2013-03-30 5 views
5

У меня есть следующая простая программа, которую я использую, чтобы обновить мою память о GDB (которую я не касался много лет).GCC меняется меньше или меньше

#include <stdio.h> 

int main() 
{ 
    int i; 

    for (i = 0; i < 10; i++) 
    { 
    printf("Hello World\n"); 
    } 

    return 0; 
} 

Скомпилируйте это с помощью gcc -g for-test.c -o for-test. Основываясь на странице руководства, я не ожидаю, что какие-либо оптимизации будут использованы, поскольку я не указал их.

Когда я загружаю это в GDB и запустить disassemble main, то i < 10 сравнение генерирует следующее:

cmp DWORD PTR [rbp-0x4],0x9 
jle 0x4004fe <main+10> 

Это, кажется, эффективно изменили сравнение i < 10 к i <= 9. Учитывая, что это целые сравнения, не должно быть разницы, но мне было интересно, есть ли какая-либо причина, по которой GCC выводит эту сборку, вместо сравнения с 10 и прыжками, если меньше (JL)?

Редактировать: Это на машине с 64-разрядным процессором, работающим под управлением Ubuntu с GCC 4.6.3 и GDB 7.4-2012.04.

+0

Оба способа на 100% идентичны (одинаковое поведение, одинаковый размер кода, одинаковая скорость для каждого процессора). Я не знаю о внутренних компонентах GCC, поэтому не могу догадаться, почему это произошло. Более интересно то, что я не думаю, что вы включили оптимизацию (в противном случае он будет использовать регистр вместо локальной переменной для 'i'). – Brendan

+2

Возможно, это так, как это нормализует сравнения .. – harold

+0

Если бы были какие-то шансы, что они не будут одинаковыми, это не сделает это без оптимизации. например 'if (a + 1> 1)' будет упрощен до 'if (a> 0)' с оптимизацией, но это потенциально небезопасно, поэтому не будет сделано иначе. – teppic

ответ

5

Не должно быть разницы в скорости выполнения. Я думаю, что gcc обычно испускает jle для таких сравнений и делает это для согласованности в сгенерированной сборке.

+0

Это похоже на случай. Интересно, что я пробовал один и тот же код в clang, и результат был обратным - он бы преобразовал «цикл продолжения, если меньше, чем« to »break, если он больше или равен». Я не уверен, почему два компилятора выбрали разные маршруты, или если они изначально более эффективны, чем другие. – pwaring

0

Это не эффективная оптимизация, просто другой способ написать то же самое. Компиляция с флагом -O генерирует гораздо более сложные оптимизации.

2

Составители могут выполнять оптимизации, если наблюдаемое поведение одинаково. Это известно как As-If rule. Поскольку наблюдаемое поведение для обоих случаев одинаково, компилятору разрешено генерировать код сборки в любом из двух. Это верно, даже если у вас нет оптимизаций.

+0

+1. Он мог бы даже развернуть цикл (это на самом деле делает это с '-O3'). И, возможно, даже напечатайте одну строку, которая составляет 10 копий оригинала. –

+0

Это не настоящая оптимизация, если только не сравнивать с 9 и прыгать, если меньше или равно быстрее (или больше эффективности памяти или какой-либо другой меры), чем сравнивать с 10 и прыгать, если меньше. – pwaring

Смежные вопросы