Беспредельный copy elision

yndx-antoshkka
yndx-antoshkka

Правила copy elision в секции [class.copy.elision] отлично работают!

Однако они подразумевают, что функция в исходном коде будет являться функцией и в бинарнике. Что не верно, для оптимизирующих компиляторов, умеющих встраивать тела функций и делать link-time оптимизации.

Для таких компиляторов в ассемблерном коде программы зачастую можно встретить цепочки копирования+удаления объекта. Другими словами можно увидеть нечто подобное после встраивания функций:

int caller() {
    A a;
    // ...

    A b = a;
    a.~A();
    // ...

    A c = b;
    b.~A();
    // ...
}

Подобные цепочки всегда генерируются при:

  • возврате субобъекта
  • возврате элемента из structured binding
  • std::move возвращаемого объекта
  • возврате локального объекта используя ссылку
  • возврате активного элемента union
  • передаче параметра по копии в функцию в конце блока
  • возврате объекта расположенного в std::aligned_storage
  • возврате параметра функции, принятого по копии

В https://apolukhin.github.io/papers/ultimate_copy_elision.html предлагаю убрать существующие ограничения на copy elision и всегда позволять его делать если: копируемый локальный не volatile объект или его не volatile субобъект не используются после копирования.

Такая формулировка не влияет на совместный scope объектов: Если код после inline выглядел как

int caller() {
    A a;
    // ... #1

    A b = a;
    a.~A();
    // ... #2

    A c = b;
    b.~A();
    // ... #3

    c.~A();
}

То с убранными ограничениями для copy elision код превратится в

int caller() {
    A a;
    // ... #1
    // ... #2
    // ... #3

    a.~A(); // бывший c.~A();
}

Подобная оптимизация может положительно сказаться на времени компиляции и на время link-time оптимизации: в данный момент компиляторы пытаются встраивать вызов copy конструктора и деструктора и оптимизировать всё их содержимое в контексте текущей функции. Это ведёт к тому, что оптимизатор вынужден оптимизировать несколько мегабайт низкоуровнего кода, вместо того, чтобы просто выкинуть эти два вызова функций и работать с намного меньшими объёмами низкоуровневых команд.

26
рейтинг
в разработке
Нет комментариев
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).
Все предложения