gcc не объединяет последовательные ограждения

#c #optimization #memory-barriers #memory-model

#c #оптимизация #барьеры памяти #модель памяти

Вопрос:

Для этого простого фрагмента кода

 std::atomic_int i;
void foo() {
    i.store(1);
    i.store(2);
}
  

gcc генерирует следующую сборку для ARM:

 movw    r3, #:lower16:.LANCHOR0
movt    r3, #:upper16:.LANCHOR0
dmb ish
mov r1, #1
mov r2, #2
str r1, [r3]
dmb ish
dmb ish               ; why is this not eliminated?
str r2, [r3]
dmb ish
bx  lr
  

Вы можете заметить, что в середине создается повторяющееся ограждение, которое кажется излишним. Проблема в том, что оптимизатор gcc не может перехватить и устранить дополнительные ограждения, или я что-то упускаю?

Кстати, clang, похоже, обрабатывает соседние ограждения.

Комментарии:

1. Можете ли вы подтвердить, какая архитектура и версия ARM (и GCC)? Godbolt выдает приличный результат для ARM64, но я не уверен, что это то, что вы хотите.

2. Это ARM32. Смотрите здесь: godbolt.org/z/BSPOKN

Ответ №1:

Да, это не так, и я некоторое время обсуждал это с разными людьми. Для внешнего наблюдателя, такого как я, эффект заключается в том, что он обрабатывает atomic as volatile , в то время как стандарт этого не требует. Я не смог найти требование для этого в стандарте.

Однако это также может быть простым случаем отсутствия оптимизации.