-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathemireduce.py
91 lines (81 loc) · 2.63 KB
/
emireduce.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#!/usr/bin/env python3
import os
import sys
import subprocess
import shutil
# python3 emireduce.py <path to opt> <llbui build dir> <src ir> <reduced ir>
# TODO: pass sequence reduction
opt_bin = sys.argv[1]
ubi_path = sys.argv[2]
llubi_bin = os.path.join(ubi_path, "llubi")
if not os.path.exists(llubi_bin):
print("llubi not found")
sys.exit(1)
emireduce_bin = os.path.join(ubi_path, "emireduce")
if not os.path.exists(emireduce_bin):
print("emireduce not found")
sys.exit(1)
src_ir = sys.argv[3]
reduced_ir = sys.argv[4]
reduced_tmp_ir = reduced_ir.removesuffix(".ll") + ".tmp.ll"
reduced_opt_ir = reduced_ir.removesuffix(".ll") + ".opt.ll"
max_retrial = 100
def exec_ir(path):
try:
return subprocess.check_output([llubi_bin, path, "--max-steps", "100000000"], stderr=subprocess.DEVNULL).decode("utf-8")
except Exception:
return None
def reduce_ir(path, output_path):
try:
out = subprocess.check_output([emireduce_bin, path, output_path]).decode("utf-8")
if "No changes" in out:
return None
return out
except Exception:
print("Internal bug")
exit(-1)
def opt_ir(path, output_path):
try:
subprocess.check_output([opt_bin, "-S", "-O3", path, "-o", output_path])
return True
except Exception:
return False
shutil.copyfile(src_ir, reduced_ir)
ref_output = exec_ir(reduced_ir)
orig_size = os.path.getsize(reduced_ir)
if not opt_ir(reduced_ir, reduced_opt_ir):
print("Failed to optimize")
sys.exit(1)
wrong_output = exec_ir(reduced_opt_ir)
if ref_output == wrong_output:
print("Test case is not interesting")
sys.exit(0)
def reduce_once():
ref_output = reduce_ir(reduced_ir, reduced_tmp_ir)
if ref_output is None:
return False
if not opt_ir(reduced_tmp_ir, reduced_opt_ir):
os.remove(reduced_tmp_ir)
return False
cur_output = exec_ir(reduced_opt_ir)
if cur_output == ref_output:
os.remove(reduced_tmp_ir)
os.remove(reduced_opt_ir)
return False
shutil.move(reduced_tmp_ir, reduced_ir)
os.remove(reduced_opt_ir)
return True
reduce_iter = 0
reduce_fail_count = 0
while True:
reduce_iter += 1
current_size = os.path.getsize(reduced_ir)
print(f"Iteration {reduce_iter} {current_size} bytes ({current_size/orig_size*100:.2f}%) fail count {reduce_fail_count}")
if reduce_once():
reduce_fail_count = 0
else:
reduce_fail_count += 1
if reduce_fail_count >= max_retrial:
break
opt_ir(reduced_ir, reduced_opt_ir)
print(f"Final size {os.path.getsize(reduced_ir)} bytes ({os.path.getsize(reduced_ir)/orig_size*100:.2f}%)")