Ở hướng dẫn trước, bạn đã tìm hiểu vì sao cần phải tạo mã trung gian? Cách tạo mã trung gian trong thiết kế trình biên dịch. Nếu bỏ lỡ thì bạn có thể xem ở đây:
Trong hướng dẫn này bạn sẽ tìm hiểu cách tạo mã của trình biên dịch.
Tạo mã (code generation) có thể được coi là giai đoạn cuối cùng của quá trình biên dịch. Thông qua quá trình tạo mã, quá trình tối ưu hóa có thể được áp dụng trên mã, nhưng đó có thể được coi là một phần của giai đoạn tạo mã.
Mã do trình biên dịch tạo ra là mã đối tượng của một số ngôn ngữ lập trình cấp thấp hơn, ví dụ, hợp ngữ.
Chúng tôi đã thấy rằng mã nguồn được viết bằng ngôn ngữ cấp cao hơn được chuyển đổi thành ngôn ngữ cấp thấp hơn tạo ra mã đối tượng cấp thấp hơn, mã này phải có các thuộc tính tối thiểu sau:
Bây giờ chúng ta sẽ xem cách mã trung gian được chuyển đổi thành mã đối tượng đích (mã hợp ngữ, trong trường hợp này).
Directed Acyclic Graph (DAG) là một công cụ mô tả cấu trúc của các khối cơ bản, giúp xem luồng giá trị chảy giữa các khối cơ bản và cũng cung cấp tối ưu hóa. DAG cung cấp sự chuyển đổi dễ dàng trên các khối cơ bản. DAG có thể được hiểu ở đây:
Ví dụ:
t0 = a + b
t1 = t0 + c
d = t0 + t1
Kỹ thuật tối ưu hóa này hoạt động cục bộ trên mã nguồn để biến nó thành mã tối ưu hóa. Theo cục bộ, chúng tôi muốn nói đến một phần nhỏ của khối mã đang xử lý.
Các phương pháp này có thể được áp dụng trên các mã trung gian cũng như trên các mã đích. Một loạt các câu lệnh được phân tích và được kiểm tra để đảm bảo khả năng tối ưu hóa sau đây:
Ở cấp độ mã nguồn, người dùng có thể thực hiện những điều sau:
int add_ten(int x)
{
int y, z;
y = 10;
z = x + y;
return z;
}
// or
int add_ten(int x)
{
int y;
y = 10;
y = x + y;
return y;
}
// or
int add_ten(int x)
{
int y = 10;
return x + y;
}
// or
int add_ten(int x)
{
return x + 10;
}
Ở cấp độ biên dịch, trình biên dịch tìm kiếm các hướng dẫn dư thừa trong tự nhiên. Việc tải và lưu trữ nhiều hướng dẫn có thể mang cùng một ý nghĩa ngay cả khi một số trong số chúng bị loại bỏ. Ví dụ:
MOV x, R0
MOV R0, R1
Chúng ta có thể xóa lệnh đầu tiên và viết lại câu dưới dạng:
MOV x, R1
Mã không thể truy cập là một phần của mã chương trình không bao giờ được truy cập do cấu trúc lập trình. Các lập trình viên có thể đã vô tình viết một đoạn mã không bao giờ có thể tiếp cận được.
Thí dụ:
void add_ten(int x)
{
return x + 10;
printf(“value of x is %d”, x);
}
Trong đoạn mã này, câu lệnh printf sẽ không bao giờ được thực thi vì điều khiển chương trình quay trở lại trước khi nó có thể thực thi, do đó printf có thể bị loại bỏ.
Có những trường hợp trong mã mà điều khiển chương trình nhảy qua lại mà không thực hiện bất kỳ tác vụ quan trọng nào. Các bước nhảy này có thể được loại bỏ. Hãy xem xét đoạn mã sau:
#...
MOV R1, R2
GOTO L1
#...
L1 : GOTO L2
L2 : INC R1
Trong mã này, nhãn L1 có thể được loại bỏ khi nó chuyển điều khiển đến L2. Vì vậy, thay vì nhảy đến L1 và sau đó đến L2, điều khiển có thể trực tiếp đến L2, như hình dưới đây:
#...
MOV R1, R2
GOTO L2
#...
L2 : INC R1
Có những trường hợp mà các biểu thức đại số có thể trở nên đơn giản. Ví dụ, khái niệm a = a + 0 có thể được thay thế bằng a và biểu thức a = a + 1 chỉ có thể được thay thế bằng INC a.
Có những thao tác tiêu tốn nhiều thời gian và không gian hơn. 'Chi phí' của chúng có thể được giảm bớt bằng cách thay thế chúng bằng các hoạt động khác tiêu tốn ít thời gian và không gian hơn, nhưng cho kết quả tương tự.
Ví dụ: x * 2 có thể được thay thế bằng x << 1 , chỉ liên quan đến một lần dịch sang trái. Mặc dù đầu ra của a * a và a2 là như nhau, nhưng a2 sẽ hiệu quả hơn nhiều để triển khai.
Máy mục tiêu có thể triển khai các lệnh phức tạp hơn, có thể có khả năng thực hiện các hoạt động cụ thể một cách hiệu quả hơn nhiều.
Nếu mã đích có thể đáp ứng các chỉ dẫn đó một cách trực tiếp, điều đó sẽ không chỉ cải thiện chất lượng của mã mà còn mang lại kết quả hiệu quả hơn.
Một trình tạo mã được mong đợi có sự hiểu biết về môi trường thời gian chạy của máy mục tiêu và tập lệnh của nó. Trình tạo mã nên xem xét những điều sau để tạo mã:
Trình tạo mã phải theo dõi cả thanh ghi (tính khả dụng) và địa chỉ (vị trí của các giá trị) trong khi tạo mã. Đối với cả hai, hai trình mô tả sau được sử dụng:
Trình tạo mã giữ cho cả hai trình mô tả được cập nhật trong thời gian thực. Đối với câu lệnh tải, LD R1, x, trình tạo mã:
Các khối cơ bản bao gồm một chuỗi các lệnh ba địa chỉ. Trình tạo mã lấy chuỗi các lệnh này làm đầu vào.
Lưu ý: Nếu giá trị của tên được tìm thấy ở nhiều nơi (thanh ghi, bộ đệm hoặc bộ nhớ), giá trị của thanh ghi sẽ được ưu tiên hơn bộ nhớ đệm và bộ nhớ chính. Tương tự như vậy, giá trị của bộ nhớ đệm sẽ được ưu tiên hơn bộ nhớ chính. Bộ nhớ chính hầu như không được ưu tiên.
getReg: Trình tạo mã sử dụng hàm getReg để xác định trạng thái của các thanh ghi có sẵn và vị trí của các giá trị tên. getReg hoạt động như sau:
Đối với lệnh x = y OP z, trình tạo mã có thể thực hiện các hành động sau. Giả sử rằng L là vị trí (tốt nhất là thanh ghi) nơi lưu đầu ra của y OP z:
Xác định vị trí hiện tại (thanh ghi hoặc bộ nhớ) của y bằng cách tham khảo Trình mô tả địa chỉ của y . Nếu y hiện không có trong thanh ghi L , thì tạo lệnh sau để sao chép giá trị của y vào L :
MOV y', L
trong đó y ' đại diện cho giá trị được sao chép của y.
Xác định vị trí hiện tại của z bằng cách sử dụng cùng một phương pháp được sử dụng trong bước 2 cho y và tạo ra lệnh sau:
OP z', L
trong đó z ' đại diện cho giá trị được sao chép của z .
Các cấu trúc mã khác như vòng lặp và câu lệnh điều kiện được chuyển đổi thành ngôn ngữ hợp ngữ theo hợp ngữ chung.
Trong hướng dẫn tiếp theo, bạn sẽ tìm hiểu chi tiết các phương pháp để tối ưu mã trong thiết kế trình biên dịch.
Bạn có thể vui lòng tắt trình chặn quảng cáo ❤️ để hỗ trợ chúng tôi duy trì hoạt động của trang web.
Trong hướng dẫn này, bạn sẽ tìm hiểu chi tiết về môi trường thực thi, nơi chương trình sau khi biên dịch sẽ được thực thi.
Trong hướng dẫn này, bạn sẽ tìm hiểu bảng ký hiệu là gì? Cách trình biên dịch sử dụng bảng ký hiệu trong thiết kế trình biên dịch.
Trong hướng dẫn này, bạn sẽ tìm hiểu chi tiết các phương pháp để tối ưu mã trong thiết kế trình biên dịch.
Trong hướng dẫn này, bạn sẽ tìm hiểu vì sao cần phải tạo mã trung gian? Cách tạo mã trung gian trong thiết kế trình biên dịch.