У меня есть компилятор, который нацелен на LLVM, и я предоставляю два способа запуска кода:
- Запустить его автоматически. Этот режим компилирует код в LLVM и использует JIT ExecutionEngine для компиляции его в машинный код "на лету" и запускает его без создания выходного файла.
- Скомпилируйте его и запустите отдельно. В этом режиме выводится LLVM.bc файл, который я вручную оптимизирую (с помощью
opt
), скомпилируйте для собственной сборки (сllc
) компиляцию в машинный код и ссылку (с помощьюgcc
) и запустите.
Я ожидал, что подход № 2 будет быстрее, чем подход №1, или, по крайней мере, с той же скоростью, но, пройдя несколько тестов скорости, я с удивлением обнаруживаю, что # 2 последовательно работает примерно в два раза медленнее. Это огромная разница в скорости.
В обоих случаях работает тот же исходный код LLVM. С подходом № 1 я еще не потрудился запускать любые пропуски оптимизации LLVM (именно поэтому я ожидал, что это будет медленнее). При подходе # 2 я запускаю opt
с -std-compile-opts
и llc
с помощью -O3
, чтобы максимизировать оптимизацию, но она не приближается к № 1. Вот пример запуска той же программы:
- # 1 без оптимизации: 11.833s
- # 2 без оптимизации: 22.262s
- # 2 с оптимизацией (
-std-compile-opts
и-O3
): 18.823s
Выполняет ли ExecutionEngine что-то особенное, о котором я не знаю? Есть ли способ оптимизировать скомпилированный код для достижения той же производительности, что и ExecutionEngine JIT?