Trình biên dịch lấy mã của bạn, chia nó thành các hướng dẫn rất đơn giản, sau đó kết hợp lại và sắp xếp chúng theo cách mà nó cho là tối ưu.
Mật mã
int i = 1;
int x = ++i + ++i;
bao gồm các hướng dẫn sau:
1. store 1 in i
2. read i as tmp1
3. add 1 to tmp1
4. store tmp1 in i
5. read i as tmp2
6. read i as tmp3
7. add 1 to tmp3
8. store tmp3 in i
9. read i as tmp4
10. add tmp2 and tmp4, as tmp5
11. store tmp5 in x
Nhưng mặc dù đây là một danh sách được đánh số theo cách tôi đã viết, chỉ có một số phụ thuộc theo thứ tự ở đây: 1-> 2-> 3-> 4-> 5-> 10-> 11 và 1-> 6-> 7- > 8-> 9-> 10-> 11 phải theo thứ tự tương đối của chúng. Ngoài ra, trình biên dịch có thể tự do sắp xếp lại và có lẽ loại bỏ sự dư thừa.
Ví dụ: bạn có thể sắp xếp danh sách như sau:
1. store 1 in i
2. read i as tmp1
6. read i as tmp3
3. add 1 to tmp1
7. add 1 to tmp3
4. store tmp1 in i
8. store tmp3 in i
5. read i as tmp2
9. read i as tmp4
10. add tmp2 and tmp4, as tmp5
11. store tmp5 in x
Tại sao trình biên dịch có thể làm được điều này? Bởi vì không có trình tự cho các tác dụng phụ của sự gia tăng. Nhưng bây giờ trình biên dịch có thể đơn giản hóa: ví dụ, có một cửa hàng chết trong 4: giá trị ngay lập tức bị ghi đè. Ngoài ra, tmp2 và tmp4 thực sự giống nhau.
1. store 1 in i
2. read i as tmp1
6. read i as tmp3
3. add 1 to tmp1
7. add 1 to tmp3
8. store tmp3 in i
5. read i as tmp2
10. add tmp2 and tmp2, as tmp5
11. store tmp5 in x
Và bây giờ mọi thứ cần làm với tmp1 là mã chết: nó không bao giờ được sử dụng. Và việc đọc lại tôi cũng có thể bị loại bỏ:
1. store 1 in i
6. read i as tmp3
7. add 1 to tmp3
8. store tmp3 in i
10. add tmp3 and tmp3, as tmp5
11. store tmp5 in x
Hãy nhìn xem, đoạn mã này ngắn hơn nhiều. Trình tối ưu hóa rất vui. Lập trình viên thì không, vì tôi chỉ được tăng một lần. Giáo sư.
Thay vào đó, hãy xem xét một thứ khác mà trình biên dịch có thể làm: hãy quay lại phiên bản gốc.
1. store 1 in i
2. read i as tmp1
3. add 1 to tmp1
4. store tmp1 in i
5. read i as tmp2
6. read i as tmp3
7. add 1 to tmp3
8. store tmp3 in i
9. read i as tmp4
10. add tmp2 and tmp4, as tmp5
11. store tmp5 in x
Trình biên dịch có thể sắp xếp lại nó như thế này:
1. store 1 in i
2. read i as tmp1
3. add 1 to tmp1
4. store tmp1 in i
6. read i as tmp3
7. add 1 to tmp3
8. store tmp3 in i
5. read i as tmp2
9. read i as tmp4
10. add tmp2 and tmp4, as tmp5
11. store tmp5 in x
và sau đó thông báo lại rằng tôi được đọc hai lần, vì vậy hãy loại bỏ một trong số chúng:
1. store 1 in i
2. read i as tmp1
3. add 1 to tmp1
4. store tmp1 in i
6. read i as tmp3
7. add 1 to tmp3
8. store tmp3 in i
5. read i as tmp2
10. add tmp2 and tmp2, as tmp5
11. store tmp5 in x
Điều đó thật tuyệt, nhưng nó có thể đi xa hơn: nó có thể sử dụng lại tmp1:
1. store 1 in i
2. read i as tmp1
3. add 1 to tmp1
4. store tmp1 in i
6. read i as tmp1
7. add 1 to tmp1
8. store tmp1 in i
5. read i as tmp2
10. add tmp2 and tmp2, as tmp5
11. store tmp5 in x
Sau đó, nó có thể loại bỏ việc đọc lại i trong 6:
1. store 1 in i
2. read i as tmp1
3. add 1 to tmp1
4. store tmp1 in i
7. add 1 to tmp1
8. store tmp1 in i
5. read i as tmp2
10. add tmp2 and tmp2, as tmp5
11. store tmp5 in x
Bây giờ 4 là một cửa hàng chết:
1. store 1 in i
2. read i as tmp1
3. add 1 to tmp1
7. add 1 to tmp1
8. store tmp1 in i
5. read i as tmp2
10. add tmp2 and tmp2, as tmp5
11. store tmp5 in x
và bây giờ 3 và 7 có thể được hợp nhất thành một lệnh:
1. store 1 in i
2. read i as tmp1
3+7. add 2 to tmp1
8. store tmp1 in i
5. read i as tmp2
10. add tmp2 and tmp2, as tmp5
11. store tmp5 in x
Loại bỏ tạm thời cuối cùng:
1. store 1 in i
2. read i as tmp1
3+7. add 2 to tmp1
8. store tmp1 in i
10. add tmp1 and tmp1, as tmp5
11. store tmp5 in x
Và bây giờ bạn sẽ nhận được kết quả mà Visual C ++ mang lại cho bạn.
Lưu ý rằng trong cả hai đường dẫn tối ưu hóa, các phụ thuộc thứ tự quan trọng được giữ nguyên, miễn là các hướng dẫn không bị xóa mà không làm gì cả.