"почему бы не скомпилировать для x86"
Потому что тогда вы не сможете воспользоваться специфическими особенностями конкретного процессора, на котором он запускается. В частности, если мы будем читать «compile for x86» как «производить нативный код, который может работать на 386 и его потомках», то результирующий код не может полагаться даже на что-то более старое, чем инструкции mmx.
Таким образом, конечный результат заключается в том, что вам нужно скомпилировать для каждой конкретной архитектуры, на которой он будет работать (как насчет тех, которые еще не существуют), и попросить установщика выбрать, какой исполняемый файл поместить на место. Или я слышал, что компилятор intel C ++ создаст несколько версий одной и той же функции, отличающихся только используемыми функциями процессора, и выберет правильную во время выполнения в зависимости от того, что процессор сообщает о доступности.
С другой стороны, вы можете просматривать байт-код как «полускомпилированный» источник, подобный промежуточному формату, в котором собственный компилятор (если не будет задан вопрос) фактически не будет записывать на диск. Затем среда выполнения может выполнить окончательную компиляцию, точно зная, какая архитектура будет использоваться. Именно по этой причине некоторое время назад некоторый код на C # /. Net мог немного превзойти код на C ++ в некоторых ресурсоемких задачах в некоторых тестах.
«Окончательная компиляция» байт-кода может также сделать дополнительные предположения по оптимизации, которые (с точки зрения статической компиляции) явно небезопасными *, и просто перекомпилировать, если эти предположения будут позже ошибочными.