Генерация высококачественного кода для программ, написанных на СИ | страница 4
>x = 2;
> if( a < x && b < x)
> c = x;s
переводится в
>x = 2;
>if(a < 2 && b < 2)
> c = 2;
Целиком связано с размножением констант "размножение копий". В этом методе копируются переменные вместо константных значений. Например,
>x = y;
>if(a < x && b < x)
> c = x;
переводится в
>x = y;
>if(a < y && b < y)
> c = y;
Размножение констант и копий также может удалить излишние присваивания (x = 2 и x = y в примерах). Среди описываемых компиляторов только Microsoft C 5.0 и WATCOM C 6.0 применяют размножение констант.
Метод "свертки констант" (константная арифметика) сводит выражения, которые содержат константные данные, к возможно простейшей форме. Константные данные обычно используются в программе либо непосредственно (как в случае чисел или цифр), либо косвенно (как в случае объявленных манифестных констант). Свертка констант сводит следующий оператор:
>#define TWO 2
>a = 1 + TWO;
к его эквивалентной форме,
>a = 3;
во время компиляции, благодаря чему удаляются ненужные арифметические операции из стадии выполнения программы. В Си сворачивание констант применяют как к целым константам, так и к константам с плавающей точкой.
"Алгебраические упрощения" есть вид свертки констант, который удаляет арифметические тождества. Код, сгенерированный для таких операторов, как
>x = y + 0;
>x = y * 0;
>x = y / 1.0;
>x = y / 0;
должен быть простым константным присваиванием и не должен содержать команд для выполнения арифметических операций. Бдительный компилятор должен пометить последний оператор как ошибочный и не генерировать код для него.
"Извлечение общих подвыражений" - это процесс удаления лишних вычислений. Вместо того, чтобы генерировать код для вычисления значения каждый раз, когда оно используется, оптимизирующий компилятор пытается выделить выражение таким образом, чтобы его значение вычислялось только однажды. Там, где это возможно, последующие ссылки на такое же выражение используют ранее вычисленное значение. Выражения y * 3 и a[y*3] являются общими подвыражениями в следующем тексте:
>if( a[y*3] < 0 || b[y*3] > 10)
> a[y*3] = 0;
Выделение этих выражений приводит к логически эквивалентному тексту:
>T1 = y*3;
>A1 = &a[T1];
>A2 = &b[T1];
>if( *A1 < 0 || *A2 > 10)
> *A1 = 0;
Выделение общих подвыражений обычно происходит внутри оператора или блока. "Глубокое выделение общих подвыражений" является более сложным и перекрывает базовые блоки. Выделение общего подвыражения, y*3, в операторе
>if(a == 0)
> a = y * 3;
>else
> b = y * 3;