Một backend trình biên dịch mới có tên TPDE-LLVM đã được mở mã nguồn, hứa hẹn cải thiện đáng kể thời gian biên dịch trong khi vẫn duy trì hiệu suất runtime tương tự như backend -O0 tiêu chuẩn của LLVM . Dự án này giải quyết một trong những khiếu nại dai dẳng nhất về LLVM : tốc độ biên dịch chậm, đặc biệt là đối với các bản build debug.
Tăng Tốc Ấn Tượng Với Những Đánh Đổi
TPDE-LLVM mang lại tốc độ biên dịch nhanh hơn 10-20 lần so với backend -O0 của LLVM trên các benchmark khác nhau. Kiểm thử trên SPEC CPU 2017 cho thấy những cải thiện nhất quán, với một số chương trình như omnetpp và xalanc có tốc độ biên dịch nhanh hơn 20 lần. Tuy nhiên, tốc độ này đi kèm với chi phí là kích thước code lớn hơn một chút, thường lớn hơn 10-30% so với đầu ra LLVM tiêu chuẩn.
Cộng đồng đã có phản ứng trái chiều với những kết quả này. Trong khi một số nhà phát triển hào hứng với việc build debug nhanh hơn, những người khác chỉ ra các hạn chế quan trọng. Backend hiện tại chỉ hỗ trợ một tập con của intermediate representation ( IR ) của LLVM và chỉ nhắm đến các bộ xử lý x86-64 và AArch64 .
IR (Intermediate Representation): Một ngôn ngữ lập trình cấp thấp được sử dụng nội bộ bởi các trình biên dịch để biểu diễn mã nguồn trước khi chuyển đổi thành mã máy.
Kết quả hiệu suất SPEC CPU 2017 (x86-64)
Benchmark | Tăng tốc thời gian biên dịch (-O0) | Tỷ lệ kích thước mã (-O0) | Tăng tốc thời gian biên dịch (-O1) | Tỷ lệ kích thước mã (-O1) |
---|---|---|---|---|
600.perl | 11.39x | 1.27x | 15.00x | 0.97x |
602.gcc | 12.54x | 1.32x | 17.55x | 1.01x |
605.mcf | 9.72x | 1.27x | 12.47x | 0.92x |
620.omnetpp | 21.46x | 1.24x | 26.49x | 1.03x |
623.xalanc | 18.99x | 1.24x | 24.80x | 0.98x |
625.x264 | 10.52x | 1.26x | 15.19x | 0.97x |
631.deepsjeng | 9.60x | 1.25x | 17.56x | 0.97x |
641.jeela | 21.44x | 1.24x | 18.36x | 0.95x |
657.x2 | 10.95x | 1.30x | 15.15x | 0.92x |
Trung bình nhân | 13.34x | 1.27x | 17.58x | 0.97x |
Đổi Mới Kỹ Thuật Đằng Sau Tốc Độ
Bí mật của tốc độ TPDE-LLVM nằm ở cách tiếp cận được tối ưu hóa. Thay vì hệ thống tối ưu hóa đa pass phức tạp của LLVM , TPDE chỉ sử dụng ba pass: dọn dẹp IR , phân tích cho vòng lặp và thời gian sống của biến, và tạo mã kết hợp. Quy trình đơn giản này xử lý lowering, phân bổ thanh ghi và tạo mã máy tất cả cùng một lúc.
Các cuộc thảo luận cộng đồng tiết lộ rằng cách tiếp cận này hoạt động tốt cho mã được tạo bởi trình biên dịch điển hình từ Clang , với hỗ trợ tốt cho Rust và Flang . Tuy nhiên, một số thư viện Rust phổ biến sử dụng các kiểu vector chuyên biệt chưa được hỗ trợ, hạn chế tính hữu dụng tức thì cho tất cả các dự án.
Tổng quan Kiến trúc TPDE-LLVM
- Thiết kế Ba Lần Xử lý: Dọn dẹp/chuẩn bị IR → Phân tích (vòng lặp + liveness) → Sinh mã kết hợp
- Các Nền tảng Được Hỗ trợ: Chỉ x86-64 và AArch64
- Hỗ trợ LLVM-IR: Tập con điển hình được tạo bởi Clang -O0/-O1
- Tùy chọn Tích hợp: Thư viện (biên dịch JIT), công cụ độc lập, tích hợp Clang (yêu cầu patch)
- Hạn chế Hiện tại: Không hỗ trợ DWARF, phân bổ thanh ghi cơ bản, chỉ các nền tảng ELF
Tác Động Thực Tế Và Hạn Chế
Việc tăng hiệu suất chủ yếu có lợi cho phần backend của quá trình biên dịch. Trong các dự án C/C++ điển hình sử dụng Clang , frontend (phân tích mã nguồn) chiếm 50-80% thời gian biên dịch. Với TPDE-LLVM , con số này tăng lên hơn 98%, có nghĩa là tốc độ tổng thể ít ấn tượng hơn so với những con số backend gợi ý.
Cải thiện 10-20 lần được mô tả ở đây chưa hoạt động cho clang hoặc rustc, và khi nó hoạt động, nó sẽ chỉ tăng tốc phần backend. Tuy nhiên, đây vẫn là một chiến thắng đáng kinh ngạc cho thời gian biên dịch vì hai bước còn lại có thể được tối ưu hóa độc lập.
Một số thách thức kỹ thuật vẫn còn. Hệ thống chưa hỗ trợ thông tin debug DWARF , sử dụng phân bổ thanh ghi cơ bản mà spill mọi thứ, và thiếu hỗ trợ cho các nền tảng không phải ELF . Các nhà phát triển đã xác định các tính năng LLVM-IR cụ thể làm chậm quá trình biên dịch, bao gồm các biểu thức hằng số trong hàm và cấu trúc dữ liệu có kích thước tùy ý.
Các Điểm Nghẽn Hiệu Suất Đã Xác Định Trong LLVM-IR
Tác Động Hiệu Suất:
- ConstantExpr bên trong các hàm (yêu cầu viết lại thành các lệnh)
- Các giá trị struct/array có kích thước tùy ý (độ phức tạp thời gian chạy bậc hai)
- PHINode::getIncomingValForBlock gây ra thời gian biên dịch bậc hai cho các khối có >1k tiền nhiệm
Thách Thức Triển Khai:
- Truy cập trực tiếp đến các biến toàn cục thread-local (yêu cầu tạo lời gọi hàm)
- Phép toán số học với độ rộng bit tùy ý (i268 và các độ rộng không chuẩn tương tự)
- Vấn đề hiệu suất Live::successors yêu cầu bộ nhớ đệm
Nhìn Về Tương Lai
Dự án đại diện cho một bước quan trọng hướng tới biên dịch nhanh hơn, đặc biệt có giá trị cho quy trình phát triển nơi mà việc lặp lại nhanh quan trọng hơn hiệu suất runtime tối ưu. Mặc dù nó sẽ không thay thế các backend tối ưu hóa của LLVM cho các bản build phát hành, TPDE-LLVM có thể trở thành một công cụ quan trọng cho các nhà phát triển dành nhiều thời gian chờ đợi các bản build debug biên dịch.
Việc phát hành mã nguồn mở cho phép cộng đồng rộng lớn hơn thử nghiệm với những kỹ thuật này và có khả năng tích hợp chúng vào các toolchain hiện có. Liệu điều này dẫn đến việc áp dụng rộng rãi hay ảnh hưởng đến các cải tiến trong chính LLVM vẫn còn phải xem, nhưng nó chắc chắn chứng minh rằng những cải thiện tốc độ biên dịch đáng kể là có thể với những lựa chọn kiến trúc phù hợp.
Tham khảo: TPDE-LLVM: 10-20x Faster LLVM -00 Back-End