Задача оценки качества кодогенерации намного сложнее, чем может показаться на первый взгляд. Прежде всего, следует разделять, собственно, сам компилятор и его окружение (среду, библиотеки и т.д.). В частности совершенно некорректно сравнивать размер откомпилированного примера "Hello, World" с его ассемблерной реализацией. Вызов 'printf("xxx");' компилятор транслирует приблизительно в следующий код: "push offset xxx\call printf\pop eax" – круче уже не оптимизируешь!
Обратите внимание на размер объективного файла, сформированного компилятором. Не правда ли, он мало в чем не уступает объективному файлу ассемблерной реализации? Конечно, после подключения всех необходимых библиотек, размер откомпилированного файла увеличивается в десятки раз, в то время как объем ассемблерного модуля практически не изменяется. Да, это так, но при чем здесь компилятор?! Ему встретился вызов printf, – он и включил его в объективный файл. Если бы программист захотел вывести строку напрямую, – через соответствующую API функцию операционной системы (как он поступил в ассемблерной реализации), исполняемый файл сразу бы похудел на десяток-другой килобайт. Что еще остается? Ах да, среда, называемая так же RTL (Run Time Library
– библиотека времени исполнения), – служебные функции, вызываемые самим компилятором. Несмотря на то, что библиотеки времени исполнения являются неотъемлемым компонентом компилятора, к качеству кодогенерации они не имеют никакого отношения, т.к. с точки зрения компилятора функции RTL ничем не отличаются от обычных библиотечных функций.
Избыточность штатных библиотечных функций и библиотеки времени исполнения на крохотных проектах очевидна, – вывод строки "Hello, World" не использует и сотой доли возможностей функции printf, но в программе, состоящей из нескольких тысяч строк, соотношение между полезными и служебными функциями нормализуется и коэффициент полезного действия библиотек практически вплотную приближается к единице.