Как _ReadWriteBarrier распространяется вверх по дереву вызовов?

Я просматриваю этот фрагмент текста в документации для встроенного _ReadWriteBarrier Visual C++:

В прошлых версиях компилятора Visual C++ функции _ReadWriteBarrier и _WriteBarrier применялись только локально и не влияли на функции выше по дереву вызовов. В Visual C++ 2005 и более поздних версиях эти функции применяются на всем пути вверх по дереву вызовов.

Я понимаю, что барьер делает внутри функции, но «вверх по дереву вызовов», похоже, подразумевает, что функция foo(), вызывающая функцию bar(), может знать, содержит ли bar() барьер или нет. Что на самом деле изменилось в VC2005, чтобы включить это... соглашение о вызовах/ABI, какой-то глобальный анализ, выполненный компилятором, или что?


person timday    schedule 28.01.2010    source источник


Ответы (1)


Документы MS никогда не бывают отличными, и этот — хороший тому пример. В _ReadWriteBarrier есть 2 части:

  1. указание ЦП создать барьер памяти (т.е. mfence),
  2. говоря компилятору не оптимизировать вокруг барьера.

Я подозреваю, что часть дерева вызовов относится к № 2. то есть:

int x = 0;

void foo()
{
   x = 7;
   _ReadWriteBarrier();
   x = 8;
}

Без барьера x=7 может быть полностью удален компилятором. С барьером он остается. А как насчет функции, которая вызывает foo?

void bar()
{
   x = 3;  // optimized away?
   foo();
   x = 4;
}

Я думаю, что в прошлом x=3, возможно, был оптимизирован (компилятору может быть трудно определить, разрешено это или нет), но теперь он будет правильно сохранять инструкции x=3.

Я думаю.

person tony    schedule 29.01.2010
comment
Это также то, как я понимаю документы MS. Но как компилятор может реализовать такое поведение? Если ответ будет заключаться просто в том, что все вызовы невстроенных функций являются ограничениями переупорядочивания компилятора, то почему ссылка на более ранние версии VC не реализует это? - person shojtsy; 23.04.2010
comment
Я действительно не знаю. Он может пометить каждую функцию атрибутами, которые затем интерпретирует компоновщик. Это может быть так же просто, как изменение имени или сложная база данных внутри библиотеки или, по крайней мере, в словаре объектов во время компиляции... Однако, как правило, в прошлом компиляторы всегда предполагали самое худшее о функциях, которые они не могли видеть. , таким образом, не оптимизируя его. Возможно, по мере того, как они становятся умнее, им нужно раскрывать больше информации. - person tony; 24.04.2010