Будет ли G CC оптимизировать встроенный аксессор? - PullRequest
3 голосов
/ 05 февраля 2020

Допустим, у меня есть этот класс

class Point 
{
  inline float x() const { return v[0]; }
  inline float y() const { return v[1]; }
  inline float z() const { return v[2]; }

  float v[3];
};

И я делаю:

Point myPoint;
myPoint[0] = 5;

// unrelated code goes here

float myVal = myPoint.x() + 5;

Будет ли G CC на -O2 или -O3 оптимизировать любые вызовы на x() только с получением v[0]? IE:

float myVal = myPoint.v[0] + 5;

Или есть причина, по которой это невозможно?

Обновление: стоит упомянуть, я понимаю, что inline - это скорее предложение для компилятора, чем что-либо еще , но все равно задавался вопросом.

В качестве дополнительного вопроса, повлияет ли использование шаблонов на этот класс на оптимизацию, которую можно выполнить?

Ответы [ 3 ]

6 голосов
/ 05 февраля 2020

Оптимизирует ли G CC встроенный метод доступа?

Все оптимизирующие компиляторы сделают это. Это тривиальная оптимизация по сравнению с другими.

Или есть причина, почему это невозможно?

Нет причины, которая делает это невозможной, но есть Также нет гарантии.

В качестве дополнительного вопроса, повлияет ли шаблонирование этого класса на оптимизацию, которую можно выполнить?

Нет. Но, разумеется, компилятор может иметь разные пороговые значения для шаблонов.

2 голосов
/ 05 февраля 2020

Может быть или не быть встроенным. Никаких гарантий там нет. Но если вы хотите, чтобы он всегда был встроенным, используйте атрибут [[gnu::always_inline]]. Смотри документы здесь . Используйте этот атрибут, только если вы знаете, что делаете. В большинстве случаев лучше позволить компилятору решить, какие оптимизации подходят.

2 голосов
/ 05 февраля 2020

Здесь вы можете увидеть разницу: https://godbolt.org/

Допустим, у вас есть этот код (ваш не компилируется: отсутствует ;, а Point не имеет [] ):

struct Point 
{
  inline float x() const { return v[0]; }
  inline float y() const { return v[1]; }
  inline float z() const { return v[2]; }

  float v[3];
};

int main() {
    Point myPoint;
    myPoint.v[0] = 5;

    float myVal = myPoint.x() + 5;
    return myVal;
}

Тогда g cc 9.2 испускает :

Point::x() const:
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-8], rdi
        mov     rax, QWORD PTR [rbp-8]
        movss   xmm0, DWORD PTR [rax]
        pop     rbp
        ret
main:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        movss   xmm0, DWORD PTR .LC0[rip]
        movss   DWORD PTR [rbp-16], xmm0
        lea     rax, [rbp-16]
        mov     rdi, rax
        call    Point::x() const
        movss   xmm1, DWORD PTR .LC0[rip]
        addss   xmm0, xmm1
        movss   DWORD PTR [rbp-4], xmm0
        movss   xmm0, DWORD PTR [rbp-4]
        cvttss2si       eax, xmm0
        leave
        ret
.LC0:
        .long   1084227584

Я не настолько опытен в чтении ассемблера, но я сравниваю вышеизложенное с вывод с -O3 достаточно убедителен:

main:
        mov     eax, 10
        ret

Сгенерированный код может сильно различаться в зависимости от контекста, я просто хотел узнать, есть ли фундаментальные причины это может никогда или не произойдет.

Приведенный выше пример уже опровергает «никогда». «Всегда», однако трудно получить. Гарантия, которую вы получаете, заключается в том, что полученный код ведет себя так, как если бы компилятор перевел ваш код без примененной оптимизации. За некоторыми исключениями, оптимизация обычно не гарантируется. Чтобы быть уверенным, я бы полагался только на результаты компиляции в сценарии realisti c.

...