Różnica między pamięcią asm, asm i clobbering

Podczas implementacji bez blokady struktur danych i kodu czasowego często konieczne jest powstrzymanie optymalizacji kompilatora. Zwykle ludzie robią to używając asm volatile z {[2] } na liście clobber, ale czasami widzisz tylko asm volatile lub po prostu zwykłą asm clobbering memory.

Jaki wpływ mają te różne stwierdzenia na generowanie kodu (szczególnie w GCC, ponieważ jest mało prawdopodobne, aby był przenośny)?

Dla odniesienia, są to ciekawe odmiany:

asm ("");   // presumably this has no effect on code generation
asm volatile ("");
asm ("" ::: "memory");
asm volatile ("" ::: "memory");
Author: jleahy, 2013-01-22

3 answers

Zobacz stronę "Rozszerzony Asm" w dokumentacji GCC .

Możesz zapobiec usunięciu instrukcji asm, wpisując słowo kluczowe volatile Po asm. [...] Słowo kluczowe volatile wskazuje, że instrukcja ma ważne skutki uboczne. GCC nie usunie volatile asm, jeśli jest osiągalny.

I

Instrukcja asm bez operandów wyjściowych będzie traktowana identycznie jak lotna asm Instrukcja.

Żaden z Twoich przykładów nie ma podanych operandów wyjściowych, więc formularze asm i asm volatile zachowują się identycznie: tworzą punkt w kodzie, który nie może zostać usunięty (chyba że okaże się nieosiągalny).

To nie to samo, co nic nie Robienie. Zobacz to pytanie dla przykładu atrapy asm, która zmienia generowanie kodu - w tym przykładzie kod, który okrąża pętlę 1000 razy, zostaje wektoryzowany do kodu, który oblicza 16 iteracji pętli na raz; ale obecność asm wewnątrz pętli hamuje optymalizację (asm musi być osiągnięta 1000 razy).

Clobber "memory" sprawia, że GCC zakłada, że dowolna pamięć może być dowolnie odczytywana lub zapisywana przez asm blok, więc uniemożliwi kompilatorowi zmianę kolejności załadowań lub Przechowywanie w nim:

Spowoduje to, że GCC nie będzie przechowywać wartości pamięci w pamięci podręcznej w rejestrach w całej instrukcji asemblera i nie będzie optymalizować magazynów ani ładowania do tego pamięć.

(nie uniemożliwia to procesorowi zmiany kolejności obciążeń i przechowywania w odniesieniu do innego procesora; do tego potrzebne są prawdziwe instrukcje barierze pamięci.)

 45
Author: Matthew Slattery,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:19

asm ("") nic nie robi (a przynajmniej nie ma nic robić.

asm volatile ("") i nic nie robi.

asm ("" ::: "memory") jest prostym kompilatorem.

asm volatile ("" ::: "memory") AFAIK jest taki sam jak poprzedni. Słowo kluczowe volatile mówi kompilatorowi, że nie wolno przenosić tego bloku złożenia. Na przykład, może zostać wyciągnięta z pętli, jeśli kompilator zdecyduje, że wartości wejściowe są takie same w każdym wywołaniu. Nie jestem do końca pewien na jakich warunkach kompilator zdecyduje, że to rozumie na tyle o złożeniu, aby spróbować zoptymalizować jego rozmieszczenie, ale słowo kluczowe volatile CAŁKOWICIE to tłumi. To powiedziawszy, byłbym bardzo zaskoczony, gdyby kompilator spróbował przenieść asm oświadczenie, które nie miało zadeklarowanych wejść ani wyjść.

Nawiasem mówiąc, volatile zapobiega również usunięciu wyrażenia przez kompilator, jeśli zdecyduje, że wartości wyjściowe są nieużywane. Może się to zdarzyć tylko wtedy, gdy istnieją wartości wyjściowe, więc nie dotyczy to asm ("" ::: "memory").

 7
Author: Kevin Ballard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-21 23:41:58

Tylko dla kompletności odpowiedzi Kevina Ballarda, Visual Studio 2010 oferuje _ReadBarrier (), _writebarrier() i _readwritebarrier (), aby zrobić to samo (VS2010 nie pozwala na montaż inline dla aplikacji 64-bitowych).

Nie generują one żadnych instrukcji, lecz wpływają na zachowanie kompilatora. Dobrym przykładem jest tutaj

MemoryBarrier () generuje lock or DWORD PTR [rsp], 0

 1
Author: James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-22 00:55:41