Skip to content

Commit 034171b

Browse files
authored
Merge pull request #1 from microsoft/rama/initial
Initial version
2 parents 5e4f156 + d2b8020 commit 034171b

21 files changed

Lines changed: 1339 additions & 0 deletions

onnxscript/__init__.py

Whitespace-only changes.

onnxscript/analysis.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import ast
2+
3+
4+
def used_vars(expr):
5+
''' Return set of all variables used with an expression.'''
6+
if (isinstance(expr, ast.Name)):
7+
return set([expr.id])
8+
result = set()
9+
for c in ast.iter_child_nodes(expr):
10+
result = result | used_vars(c)
11+
return result
12+
13+
14+
def local_defs(lhs):
15+
'''Utility function to return set of assigned/defined variables in the lhs of an assignment statement.'''
16+
def get_id(e):
17+
assert isinstance(e, ast.Name), "Only simple assignments supported."
18+
return e.id
19+
if (isinstance(lhs, ast.Tuple)):
20+
return set([get_id(x) for x in lhs.elts])
21+
else:
22+
return set([get_id(lhs)])
23+
24+
25+
def defs(stmt):
26+
'''
27+
Return the set of all variables that may be defined (assigned to) in an
28+
execution of input stmt.
29+
'''
30+
def block_defs(block):
31+
result = set()
32+
for s in block:
33+
result = result | defs(s)
34+
return result
35+
if (isinstance(stmt, ast.Assign)):
36+
return local_defs(stmt.targets[0])
37+
elif (isinstance(stmt, ast.Return)):
38+
return set()
39+
elif (isinstance(stmt, ast.If)):
40+
return block_defs(stmt.body) | block_defs(stmt.orelse)
41+
elif isinstance(stmt, list):
42+
return block_defs(stmt)
43+
else:
44+
raise ValueError("Unsupported statement type: " + type(stmt).__name__)
45+
46+
47+
def do_liveness_analysis(fun):
48+
'''
49+
Perform liveness analysis of the given function-ast. The results of the
50+
analysis are stored directly with each statement-ast `s` as attributes `s.live_in`
51+
and `s.live_out`.
52+
'''
53+
def visit(stmt, live_out):
54+
def visitBlock(block, live_out):
55+
for s in reversed(block):
56+
live_out = visit(s, live_out)
57+
return live_out
58+
if (isinstance(stmt, ast.Assign)):
59+
return (live_out.difference(local_defs(stmt.targets[0]))) | used_vars(stmt.value)
60+
elif (isinstance(stmt, ast.Return)):
61+
return used_vars(stmt.value)
62+
elif (isinstance(stmt, ast.If)):
63+
live1 = visitBlock(stmt.body, live_out)
64+
live2 = visitBlock(stmt.orelse, live_out)
65+
return (live1 | live2) | used_vars(stmt.test)
66+
elif isinstance(stmt, ast.For):
67+
return live_out # TODO
68+
else:
69+
raise ValueError("Unsupported statement type: " + type(stmt).__name__)
70+
assert type(fun) == ast.FunctionDef
71+
live = set()
72+
for s in reversed(fun.body):
73+
s.live_out = live
74+
live = visit(s, live)
75+
s.live_in = live
76+
# print(ast.dump(s))
77+
# print("Live-In = ", live)
78+
79+
80+
def exposed_uses(stmts):
81+
'''
82+
Return the set of variables that are used before being defined by given block.
83+
'''
84+
def visitBlock(block, live_out):
85+
for stmt in reversed(block):
86+
live_out = visit(stmt, live_out)
87+
return live_out
88+
89+
def visit(stmt, live_out):
90+
if (isinstance(stmt, ast.Assign)):
91+
return (live_out.difference(local_defs(stmt.targets[0]))) | used_vars(stmt.value)
92+
elif (isinstance(stmt, ast.Return)):
93+
return used_vars(stmt.value)
94+
elif (isinstance(stmt, ast.If)):
95+
live1 = visitBlock(stmt.body, live_out)
96+
live2 = visitBlock(stmt.orelse, live_out)
97+
return (live1 | live2) | used_vars(stmt.test)
98+
else:
99+
raise ValueError("Unsupported statement type: " + type(stmt).__name__)
100+
101+
return visitBlock(stmts, set())

onnxscript/convert.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import sys
2+
from converter import convert
3+
4+
# command-line utility to invoke converter on a python file
5+
6+
if __name__ == '__main__':
7+
for i in range(1, len(sys.argv)):
8+
convert(sys.argv[i])

0 commit comments

Comments
 (0)