Các lượt nộp
    Danh sách bài
    Trang chủ
    Báo lỗi

    solution

    Đề bài: [Trình biên dịch] Loại bỏ mã chết bằng phân tích sống lùi

    Một tối ưu hoá kinh điển trong pha sinh mã trung gian là loại bỏ mã chết (dead code elimination) dựa trên phân tích biến sống (liveness analysis): một lệnh gán là mã chết nếu giá trị nó tạo ra không bao giờ được dùng.

    Cho một khối lệnh ba địa chỉ (three-address code) tuyến tính gồm nnn lệnh đánh số 1..n1..n1..n theo thứ tự xuất hiện, không có nhãn, không có lệnh nhảy. Lệnh thứ iii có một trong hai dạng:

    • x = y op z (với op ∈{+,−,∗}\in \{+, -, *\}∈{+,−,∗}), hoặc
    • x = y (phép gán trực tiếp),

    trong đó x luôn là tên biến, còn y, z mỗi cái có thể là tên biến hoặc một hằng số nguyên. Tên biến là chuỗi chữ cái thường độ dài từ 1 đến 10.

    Cho tập hợp LLL các biến sống ngay sau lệnh cuối cùng (live-out của toàn khối — ví dụ các biến còn được dùng ở phần chương trình phía sau khối này). Áp dụng một lượt duyệt lùi (từ lệnh nnn về lệnh 111) theo đúng quy tắc phân tích sống chuẩn sau, với livelivelive ban đầu =L= L=L:

    • Xét lệnh iii theo thứ tự lùi: nếu biến x (vế trái) của lệnh iii đang sống (thuộc livelivelive) thì lệnh iii được giữ lại; loại x khỏi livelivelive, sau đó thêm vào livelivelive các biến xuất hiện ở vế phải (y, và z nếu có — bỏ qua nếu chúng là hằng số).
    • Nếu x không sống (không thuộc livelivelive) thì lệnh iii là mã chết, bị loại bỏ hoàn toàn — vế phải của nó không đóng góp thêm biến nào vào livelivelive, và livelivelive giữ nguyên.

    Vì lượt duyệt là từ cuối lên đầu, việc loại một lệnh có thể khiến biến ở vế phải của nó không còn được dùng nữa, kéo theo lệnh sinh ra biến đó (nếu đứng trước) cũng bị phát hiện là mã chết ngay trong cùng lượt duyệt.

    Ví dụ: với 3 lệnh a = x + y, b = a * 2, c = 5 và live-out ={c}=\{c\}={c}: lệnh 3 giữ lại (sinh c); lệnh 2 bị loại vì b không sống; do đó lệnh 1 cũng bị loại vì a (chỉ được dùng bởi lệnh 2, đã chết) không còn sống. Kết quả: chỉ giữ lại lệnh số 3.

    • Định dạng đầu vào:
      • Dòng 1: số nguyên nnn (0≤n≤20000 \le n \le 20000≤n≤2000).
      • nnn dòng tiếp theo: lệnh thứ iii, dạng x = y op z hoặc x = y (các thành phần cách nhau đúng một khoảng trắng, có đúng một dấu =).
      • Dòng cuối cùng: m v1 v2 ... vm với mmm (0≤m≤500 \le m \le 500≤m≤50) là số biến live-out, tiếp theo là mmm tên biến (nếu m=0m=0m=0 thì dòng chỉ có số 000).
    • Định dạng đầu ra:

      In ra chỉ số (đánh số từ 1 theo thứ tự xuất hiện ban đầu) của các lệnh còn được giữ lại, mỗi chỉ số một dòng, theo thứ tự tăng dần. Nếu không còn lệnh nào được giữ lại, in ra đúng một dòng EMPTY.

    Ví dụ:

    Đầu vào:

    2
    t1 = a + b
    t2 = t1 * c
    1 t2
    

    Đầu ra:

    1
    2
    

    Đầu vào:

    3
    a = x + y
    b = a * 2
    c = 5
    1 c
    

    Đầu ra:

    3
    

    Đang tải editor...