Cho một đoạn mã ba địa chỉ (TAC) tuyến tính (không nhãn, không rẽ nhánh) gồm n lệnh liên tiếp, lệnh thứ i luôn có đích là ti (i=1,…,n). Mỗi lệnh có dạng tK = A op B (op ∈{+,−,∗,/}) hoặc dạng sao chép tK = A, trong đó A, B là biến gốc, hằng số, hoặc một tJ (J<K).
Hãy tối ưu đoạn mã bằng kỹ thuật đánh số giá trị cục bộ (local value numbering) để loại bỏ các phép tính trùng lặp, theo đúng quy tắc sau. Gọi canon(x) là "giá trị canonical hiện tại" của x: với biến gốc/hằng số chưa từng được định nghĩa, canon(x)=x; với ti đã xử lý, canon(ti) được xác định như dưới đây. Xử lý các lệnh theo thứ tự i=1,…,n:
tK = A: đặt canon(tK)=canon(A); dòng xuất ra là tK = canon(A).tK = A op B: gọi a=canon(A), b=canon(B). Nếu op là + hoặc * (giao hoán), khóa biểu thức là (op, a, b đã sắp xếp theo thứ tự từ điển); nếu op là - hoặc / (không giao hoán), khóa là (op, a, b) giữ nguyên thứ tự.
tP (P<K) đã xử lý trước đó: đặt canon(tK)=canon(tP), dòng xuất ra thay bằng tK = canon(t_P), và tính là 1 lệnh bị loại bỏ.tK = a op b.Lưu ý canon(tP) luôn chính bằng tP (vì lần đầu một khóa mới xuất hiện, canon của đích được đặt bằng chính tên đích đó).
Dòng 1: số nguyên n (1≤n≤100).
n dòng tiếp theo: lệnh thứ i theo đúng định dạng tK = A op B hoặc tK = A như mô tả (các token cách nhau một khoảng trắng, dấu = có khoảng trắng hai bên).
Dòng đầu tiên: số nguyên là tổng số lệnh bị loại bỏ (thay bằng lệnh sao chép). n dòng tiếp theo: đoạn mã đã được tối ưu, theo đúng thứ tự t1,…,tn và đúng định dạng nêu trên.
Ví dụ:
Đầu vào:
5
t1 = a + b
t2 = c - d
t3 = b + a
t4 = d - c
t5 = t1 + t3
Đầu ra:
1
t1 = a + b
t2 = c - d
t3 = t1
t4 = d - c
t5 = t1 + t1
Đầu vào:
1
t1 = x + y
Đầu ra:
0
t1 = x + y
Đang tải editor...