При рассмотрении выполнения инструкций необходимо соблюдать семантику программы . Любой порядок правильный, если это соблюдается. Конкретно, это описывается «зависимостями», которые указывают, требуют ли некоторые инструкции заданного порядка относительно правильного поведения программы. Например, рассмотрим следующую программу
1 x <= y+3
2 z <= 2*x
3 w = 5*y
4 y = 2*a
Инструкции 1 и 2 являются зависимыми. Если их относительный порядок изменяется, программа не соответствует желаемому программисту, и любое изменение порядка запрещено. По разным причинам 4 нельзя выполнить без изменений, пока y не будет использоваться 1 и 3. Существуют различные виды зависимостей, в том числе при рассмотрении потока управления.
Компилятор и оборудование пытаются переупорядочить программы, чтобы повысить их эффективность при соблюдении зависимостей. Действительно, их действия дополняют друг друга.
Компилятор может учитывать большие преобразования, чем процессор, и использует для этого более сложную эвристику. Компилятор может иметь большое представление о программе и переупорядочивать большую часть кода. Теоретически, инструкция на расстоянии, скажем, 1000, может быть смещена, если нет нарушения зависимости, и компилятор считает, что это может улучшить выполнение программы. Он может полностью реорганизовать код, развернуть циклы и т. Д. Напротив, процессор имеет относительно ограниченное окно предварительно выбранных инструкций, которые можно рассматривать для переупорядочения, и любая перестановка может касаться только близких инструкций и основана на простых методах, выполнимых в цикле.
Но процессор имеет большое преимущество. Он может выполнять динамическое переупорядочение и реагировать на случайные события. В данный момент он учитывает, какая инструкция может быть выполнена в отношении зависимостей и доступности данных, и соответственно переупорядочивает код. Это основано на динамических зависимостях, и, например, если результат предыдущей зависимой инструкции недоступен из-за отсутствия кэша, он выполнит другие инструкции, которые уважают зависимости. Последовательные запуски одной и той же программы с одними и теми же входными данными могут приводить к разному упорядочению в зависимости от неправильных прогнозов веток, ошибок кэша и т. Д.
Таким образом, нет конкуренции между компилятором и процессором, но есть эффективное сотрудничество.