Оптимизация — Как не указать точный порядок вычисления аргумента функции помогает C & amp; Компилятор C ++ для генерации оптимизированного кода?

#include <iostream>
int foo() {
std::cout<<"foo() is called\n";
return 9;
}
int bar() {
std::cout<<"bar() is called\n";
return 18;
}
int main() {
std::cout<<foo()<<' '<<bar()<<' '<<'\n';
}
// Above program's behaviour is unspecified
// clang++ evaluates function arguments from left to right: http://melpon.org/wandbox/permlink/STnvMm1YVrrSRSsB
// g++ & MSVC++ evaluates function arguments from right to left
// so either foo() or bar() can be called first depending upon compiler.

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

AFAIK, порядок оценки строго указан в таких языках, как Java, C #, D и т. Д.

3

Решение

Я думаю, что вся предпосылка вопроса неверна:

Как не указан точный порядок вычисления аргумента функции C & Компилятор C ++ для генерации оптимизированного кода?

Речь идет не об оптимизации кода (хотя это позволяет). Речь идет о том, чтобы не наказывать компиляторы, потому что базовое оборудование имеет определенные ограничения ABI.

Некоторые системы зависят от параметров, помещаемых в стек в обратном порядке, в то время как другие зависят от прямого порядка. C ++ работает на всех видах систем со всеми видами ограничений. Если вы выполняете заказ на уровне языка, вам потребуется, чтобы некоторые системы платили штраф за исполнение этого заказа.

Первое правило C ++ — «Если вы его не используете, вам не нужно платить за это». Таким образом, соблюдение порядка было бы нарушением основной директивы C ++.

9

Другие решения

Это не. По крайней мере, сегодня нет. Может быть, это было в прошлом.

Предложение для C ++ 17 предлагает определить порядок вычисления слева-справа для вызовов функций, operator<< и так далее.

Как описано в Разделе 7 этого документа, это предложение было протестировано путем компиляции ядра Windows NT, и оно фактически привело к ускорению увеличение в некоторых тестах. Комментарий авторов:

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

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

7

Порядок оценки связан с тем, как передаются аргументы. Если для передачи аргументов используется стек, вычисление справа налево помогает повысить производительность, поскольку именно так аргументы помещаются в стек.

Например, с помощью следующего кода:

void foo(bar(), baz());

Предполагая, что соглашение о вызовах — это «передача аргументов через стек», соглашение о вызовах C требует, чтобы аргументы помещались в стек, начиная с последнего, — так, чтобы при вызове функции вызываемого объекта она сначала получала первый аргумент и была способна поддерживать функции с переменными числами. , Если порядок оценки был слева направо, результат bar() должен был быть сохранен во временном, чем baz() вызывается, это результат push, сопровождаемый временным push. Тем не менее, оценка справа налево позволяет компилятору избежать временного.

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

5

Первоначальная причина, по которой стандарты C и C ++ не указали, и порядок оценки аргументов функции заключается в том, чтобы предоставить больше возможностей оптимизации для компилятора. К сожалению, это обоснование не было подкреплено обширными экспериментами в то время, когда эти языки были изначально разработаны. Но это имело смысл.

Эта проблема была поднята в последние несколько лет. Увидеть этот сообщение в блоге Хербом Саттером и не забудьте просмотреть комментарии.

Предложение P0145R1 предполагает, что лучше указать порядок вычисления для аргументов функции и для других операторов. Это говорит:

Порядок вычисления выражения, как
в настоящее время это указано в стандарте, подрывает советы,
популярные идиомы программирования, или относительная безопасность стандартной библиотеки
объекты. Ловушки предназначены не только для новичков или небрежных
программист. Они влияют на всех нас без разбора, даже когда мы знаем
правила.

Вы можете найти больше информации о том, как это влияет на возможности оптимизации в этом документе.

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

2
По вопросам рекламы [email protected]