memory_order изменяется на значение по умолчанию при передаче неконстантным lvalue

#include <atomic>

std::atomic<int> val{1};

const auto my_order = std::memory_order_relaxed; // const lvalue

int main()
{
val.store(42, my_order);
}

Этот код не имеет отношения, но я заметил нечто странное в отношении упорядочения памяти. Компилятор создает следующую сборку для main (x86_64, g ++ 6.2.1, скомпилированную с -O3):

0x00000000004004c0 <+0>:     movl   $0x2a,0x200b5a(%rip)        # 0x601024 <val>
0x00000000004004ca <+10>:    xor    %eax,%eax
0x00000000004004cc <+12>:    retq

Не существует специальных инструкций процессора для атомарного режима, который ожидается на x86 с std::memory_order_relaxed упорядоченность.
Тем не менее, когда const квалификатор удален из my_order

auto my_order = std::memory_order_relaxed; // non-const lvalue

сгенерированная компилятором сборка становится:

0x00000000004004c0 <+0>:     movl   $0x2a,0x200b5a(%rip)        # 0x601024 <val>
0x00000000004004ca <+10>:    xor    %eax,%eax
0x00000000004004cc <+12>:    mfence
0x00000000004004cf <+15>:    retq

mfence Инструкция, кажется, указывает на то, что std::memory_order_seq_cst теперь используется порядок (по умолчанию). Это немного удивительно для меня. Даже если my_order является lvalue (нетрадиционно для указания порядка памяти), оно передается по значению (все еще std::memory_order_relaxed) и я не вижу, какconst изменил бы результат. Я не мог найти конкретную перегрузку в заголовочных файлах библиотеки для этого.
С Clang я вижу аналогичные результаты, за исключением того, что он использует xchg, который является лягушатным способом выражения последовательной последовательности.
Чем можно объяснить разницу?

1

Решение

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

В случае my_order это неconst глобальная переменная, компилятор не может знать, каким будет фактическое значение, когда store выполняется и поэтому он собирается использовать std::memory_order_seq_cst,
Если переменная объявлена const, параметр порядка вступит в силу и mfence инструкция ушла.

0

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

Других решений пока нет …

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