Почему рет исчезают с оптимизацией? - PullRequest
0 голосов
/ 24 октября 2018
int suma(int* array, int len)
{
    asm("    xor %eax, %eax           # resultado = 0   \n"
        "    xor %edx, %edx           # i = 0           \n"
        "1:  add (%rdi,%rdx,4), %eax  # res += array[i] \n"
        "    inc %edx                 # ++i             \n"
        "    cmp %edx,%esi            # i < len?        \n"
        "    jne 1b                   # repetir         \n"
//      "    ret                                        \n"
       );
}

int main()
{
    int v[100];
    return suma(v, 100);
}

Почему gcc вставляет ret в конце suma() на -O0, но я должен сам добавить его на -O3?

С gcc -v:

gcc version 8.2.1 20181011 (Red Hat 8.2.1-4) (GCC) 

1 Ответ

0 голосов
/ 24 октября 2018

Я предполагаю, что 64bit ..., массив в rdi, len в esi.

Вы используете inline asm, а не функцию __attribute__((naked,noinline)), поэтому компилятор может использовать встроенный шаблонный шаблон asm в любом контексте, который он хочет.Поскольку вам не удалось использовать какие-либо ограничения ввода / вывода, и вы закрыли регистры, не сказав компилятору, он просто полностью сломается, если вы не отключите оптимизацию.

Чтобы ответить на главный вопрос, компилятор просто вставляет suma вmain.Это неявно volatile (потому что это базовый asm-оператор), поэтому он не оптимизирован.

Но выполнение завершается не окончательной функцией (suma), котораянеопределенное поведение , поэтому современный GCC просто сдается и опускает инструкцию ret.Он предполагает, что выполнение никогда не может принять этот путь (из-за неопределенного поведения), и не беспокоится о генерации кода для него.

Если вы добавите return 0; в конец suma, то main заканчивается инструкцией ret.

Удивительно, но gcc выдает только одно предупреждение в проводнике компилятора Godbolt с -O3 -Wall :

<source>: In function 'int suma(int*, int)':
<source>:13:1: warning: no return statement in function returning non-void [-Wreturn-type]
 }
 ^

В результате получается вывод asm для main, который, конечно, полностью нарушен, потому что RDI равен argc;он никогда не зарезервировал место для int v[100], потому что он не использовался в источнике C или ничего не делал.

main:
            xor %eax, %eax           # resultado = 0   
    xor %edx, %edx           # i = 0           
1:  add (%rdi,%rdx,4), %eax  # res += array[i] 
    inc %edx                 # ++i             
    cmp %edx,%esi            # i < len?        
    jne 1b                   # repetir         

С return 0; в конце suma, он и главный конец с xorl %eax, %eax;ret, но, конечно, main все еще полностью поврежден, потому что встроенный asm не использует никаких входных ограничений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...