Часто приходится сталкиваться с непониманием термина
RISC, общепринятая расшифровка которого — Reduced Instruction Set Computer
(компьютер с уменьшенной системой команд). Какой же, говорят, SPARC или
PowerPC -RISC, если у него количество кодов команд не уступает или почти
не уступает количеству команд в х8б? Почему тогда х86 не RISC, ведь у
него команд гораздо меньше и они гораздо проще, чем у VAX 11/780, считающегося
классическим примером CISC-архитектуры. Да и технологии повышения производительности
у современных х86 и RISC-процессоров используются примерно те же, что
и у больших компьютеров 70-х: множественные АЛУ, виртуальные регистры,
динамическая перепланировка команд.
В действительности, исходно аббревиатура RISC расшифровывалась несколько
иначе, а именно как Rational Instruction Set Computer (RISC, компьютер
с рациональной системой команд). RISC-процессоры, таким образом противопоставлялись
процессорам с необязательно сложной (CISC - Complex Instruction Set Computer,
компьютер со сложной системой команд), но "иррациональной",
исторически сложившейся архитектурой, в которой, в силу требований бинарной
и ассемблерной совместимости с предыдущими поколениями, накоплено множество
Пример 2.6. Эквивалентные преобразования программы
/* Пример возможной стратегии оптимизации.
* Код, вставляемый компилятором для проверки границ индекса,
* выделен при помощи нестандартного выравнивания. */
int array[100];
int bubblesort(int size) ) int count; do {
count=0;
for(i=l; i<100; i++) {
if (i<0 || i>100) raise(IndexOverflow); if (i-l<0 || i-l>100)
raise(IndexOverflow); if (array[i-1]<array[i]) { if (i<0 || i>100)
raise(IndexOverflow);
int t=array[i];
if (i<0 || i>100) raise(IndexOverflow); if (i-l<0 || i-l>100)
raise(IndexOverflow);
array[i]=array[i-1];
if (i-l<0 II i-l>100) raise(IndexOverflow); array[i-1]=t; count++;
I
while (count != 0) ;
// оптимизированный внутренний цикл может выглядеть так: register int
*ptr=array; register int *limit=ptr; register int t=*ptr++;
if (size<100) limit+=size; else limit+=100;
while (ptr<limit) { if (t<*ptr) { ptr[-l]=*ptr;
*ptr++=t; count++; ) else t=*ptr++;
}
if (size>100) raise (IndexOverf low) ;
По мере распространения в мини- и микрокомпьютерах кэшей
команд и данных, а также конвейерного исполнения команд, объединение множества
действий в один код операции стало менее выгодным с точки зрения производительности.
Это привело к радикальному изменению взглядов на то, каким должен быть
идеальный процессор, ориентированный на исполнение откомпилированного
кода. Во-первых, компилятору не нужна ни бинарная, ни даже ассемблерная
совместимость с чем бы то ни было (отсюда "рациональность").
Во-вторых, ему требуется много взаимозаменяемых регистров — минимум тридцать
два, а на самом деле чем больше, тем лучше. В-третьих, сложные комбинированные
команды усложняют аппаратуру процессора, а толку от них все равно нет,
или мало.
Коммерческий успех процессоров, построенных в соответствии с этими взглядами
(SPARC, MIPS, PA-RISC) привел к тому, что аббревиатура
USC стала употребляться к месту и не к месту — например, уже упоминавшийся
Transputer (имевший регистровый стек и реализованный на Уровне системы
команд планировщик, т. е. являющийся живым воплощением описанного ранее
CISC-подхода) в документации называли RISC-процессором, фирма Intel хвасталась,
что ее новый процессор Pentium построен на RISC-ядре (что под этим ни
подразумевалось?) и т. д.