Межпроцедурный анализ (Interprocedural Analysis, IPA) представляет собой более "агрессивную" методику оптимизации кода, обрамляющего вызов подпрограммы. При этом используется технология, похожая на анализ алиасов и позволяющая компилятору максимально "быть в курсе" того, какие переменные и регистры модифицируется в конкретном участке кода. Если анализ алиасов предоставляет сведения, касающиеся возможной адресации указателем на ту или иную области памяти, IPA анализирует возможность модификации регистра или переменной в результате вызова функции.
int a[10], b[10], c;
void bar()
{
c++;
}
void foo()
{
int i;
for (i=1; i<10; i++)
{
b[0] =b[0] + a[i];
bar();
}
}
Результат компиляции цикла без IPA-оптимизации (на промежуточном языке):
…
r5 = 1
loop_start:
r6 = r5 * 2
load r1, b
load r2, a[r6]
r1 = r1 + r2
save b, r1
call bar
r5 = r5 + 1
cmp r5, 10
if less jump loop_start
…
Результат компиляции цикла с IPA-оптимизацией (на промежуточном языке):
…
load r1, b
r5 = 1
loop_start:
r6 = r5 * 2
load r2, a[r6]
r1 = r1 + r2
call bar
r5 = r5 + 1
cmp r5, 10
if less jump loop_start
save b, r1
…
Использование IPA-анализа позволило отказаться от постоянного сохранения значения b[0] в память, поскольку компилятор имеет информацию о том, что функция bar() использует только глобальную переменную c и не работает с b[0]. Это привело к повышению производительности программы и сокращению программного кода.
|
|
Залогом эффективности IPA является способность просматривать содержимое всех файлов проекта и библиотек, поскольку зачастую вызов функции и ее описание может находиться в различных файлах.
В компиляторах различных разработчиков "акценты" IPA-оптимизации могут различаться. Например, для рассматриваемого ниже компилятора cc21k одними из основных задач IPA-оптимизации являются исключение из программы операций работы с неиспользуемыми переменными, а также анализ возможностей генерации кода с аппаратной поддержкой циклов.