Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Gwenaël Samain
cython
Commits
31376840
Commit
31376840
authored
May 25, 2011
by
Vitja Makarov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Speedup flow-control by using big-integer bitsets instead of native python sets
parent
4c644da3
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
121 additions
and
54 deletions
+121
-54
Cython/Compiler/FlowControl.pxd
Cython/Compiler/FlowControl.pxd
+33
-0
Cython/Compiler/FlowControl.py
Cython/Compiler/FlowControl.py
+88
-54
No files found.
Cython/Compiler/FlowControl.pxd
View file @
31376840
...
...
@@ -10,6 +10,13 @@ cdef class ControlBlock:
cdef
public
dict
input
cdef
public
dict
output
# Big integer it bitsets
cdef
public
object
i_input
cdef
public
object
i_output
cdef
public
object
i_gen
cdef
public
object
i_kill
cdef
public
object
i_state
cpdef
bint
empty
(
self
)
cpdef
detach
(
self
)
cpdef
add_child
(
self
,
block
)
...
...
@@ -17,6 +24,20 @@ cdef class ControlBlock:
cdef
class
ExitBlock
(
ControlBlock
):
cpdef
bint
empty
(
self
)
cdef
class
NameAssignment
:
cdef
public
bint
is_arg
cdef
public
object
lhs
cdef
public
object
rhs
cdef
public
object
entry
cdef
public
object
pos
cdef
public
set
refs
cdef
public
object
bit
cdef
class
AssignmentList
:
cdef
public
object
bit
cdef
public
object
mask
cdef
public
list
stats
cdef
class
ControlFlow
:
cdef
public
set
blocks
cdef
public
set
entries
...
...
@@ -27,6 +48,8 @@ cdef class ControlFlow:
cdef
public
ExitBlock
exit_point
cdef
public
ControlBlock
block
cdef
public
dict
assmts
cpdef
newblock
(
self
,
parent
=*
)
cpdef
nextblock
(
self
,
parent
=*
)
cpdef
bint
is_tracked
(
self
,
entry
)
...
...
@@ -37,6 +60,16 @@ cdef class ControlFlow:
cpdef
mark_reference
(
self
,
node
,
entry
)
cpdef
normalize
(
self
)
@
cython
.
locals
(
offset
=
object
,
assmts
=
AssignmentList
,
block
=
ControlBlock
)
cpdef
initialize
(
self
)
@
cython
.
locals
(
assmts
=
AssignmentList
,
assmt
=
NameAssignment
)
cpdef
set
map_one
(
self
,
istate
,
entry
)
@
cython
.
locals
(
block
=
ControlBlock
,
parent
=
ControlBlock
)
cdef
reaching_definitions
(
self
)
cdef
class
Uninitialized
:
pass
...
...
Cython/Compiler/FlowControl.py
View file @
31376840
...
...
@@ -55,6 +55,12 @@ class ControlBlock(object):
self
.
gen
=
{}
self
.
bounded
=
set
()
self
.
i_input
=
0
self
.
i_output
=
0
self
.
i_gen
=
0
self
.
i_kill
=
0
self
.
i_state
=
0
def
empty
(
self
):
return
(
not
self
.
stats
and
not
self
.
positions
)
...
...
@@ -79,6 +85,11 @@ class ExitBlock(ControlBlock):
return
False
class
AssignmentList
:
def
__init__
(
self
):
self
.
stats
=
[]
class
ControlFlow
(
object
):
"""Control-flow graph.
...
...
@@ -196,6 +207,68 @@ class ControlFlow(object):
unreachable
.
add
(
block
)
self
.
blocks
-=
unreachable
def
initialize
(
self
):
"""Set initial state, map assignments to bits."""
self
.
assmts
=
{}
offset
=
0
for
entry
in
self
.
entries
:
assmts
=
AssignmentList
()
assmts
.
bit
=
1
<<
offset
assmts
.
mask
=
assmts
.
bit
self
.
assmts
[
entry
]
=
assmts
offset
+=
1
for
block
in
self
.
blocks
:
for
stat
in
block
.
stats
:
if
isinstance
(
stat
,
NameAssignment
):
stat
.
bit
=
1
<<
offset
assmts
=
self
.
assmts
[
stat
.
entry
]
assmts
.
stats
.
append
(
stat
)
assmts
.
mask
|=
stat
.
bit
offset
+=
1
for
block
in
self
.
blocks
:
for
entry
,
stat
in
block
.
gen
.
items
():
assmts
=
self
.
assmts
[
entry
]
if
stat
is
Uninitialized
:
block
.
i_gen
|=
assmts
.
bit
else
:
block
.
i_gen
|=
stat
.
bit
block
.
i_kill
|=
assmts
.
mask
block
.
i_output
=
block
.
i_gen
for
entry
in
block
.
bounded
:
block
.
i_kill
|=
self
.
assmts
[
entry
].
bit
for
assmts
in
self
.
assmts
.
itervalues
():
self
.
entry_point
.
i_gen
|=
assmts
.
bit
self
.
entry_point
.
i_output
=
self
.
entry_point
.
i_gen
def
map_one
(
self
,
istate
,
entry
):
ret
=
set
()
assmts
=
self
.
assmts
[
entry
]
if
istate
&
assmts
.
bit
:
ret
.
add
(
Uninitialized
)
for
assmt
in
assmts
.
stats
:
if
istate
&
assmt
.
bit
:
ret
.
add
(
assmt
)
return
ret
def
reaching_definitions
(
self
):
"""Per-block reaching definitions analysis."""
dirty
=
True
while
dirty
:
dirty
=
False
for
block
in
self
.
blocks
:
i_input
=
0
for
parent
in
block
.
parents
:
i_input
|=
parent
.
i_output
i_output
=
(
i_input
&
~
block
.
i_kill
)
|
block
.
i_gen
if
i_output
!=
block
.
i_output
:
dirty
=
True
block
.
i_input
=
i_input
block
.
i_output
=
i_output
class
LoopDescr
(
object
):
def
__init__
(
self
,
next_block
,
loop_block
):
...
...
@@ -218,8 +291,6 @@ class ExceptionDescr(object):
self
.
finally_exit
=
finally_exit
class
NameAssignment
(
object
):
is_arg
=
False
def
__init__
(
self
,
lhs
,
rhs
,
entry
):
if
lhs
.
cf_state
is
None
:
lhs
.
cf_state
=
set
()
...
...
@@ -228,6 +299,7 @@ class NameAssignment(object):
self
.
entry
=
entry
self
.
pos
=
lhs
.
pos
self
.
refs
=
set
()
self
.
is_arg
=
False
def
__repr__
(
self
):
return
'%s(entry=%r)'
%
(
self
.
__class__
.
__name__
,
self
.
entry
)
...
...
@@ -337,47 +409,8 @@ class MessageCollection(list):
def
check_definitions
(
flow
,
compiler_directives
):
"""Based on algo 9.11 from Dragon Book."""
# Initialize
for
block
in
flow
.
blocks
:
block
.
input
=
{}
block
.
output
=
{}
for
entry
,
item
in
block
.
gen
.
items
():
block
.
output
[
entry
]
=
set
([
item
])
entry_point
=
flow
.
entry_point
entry_point
.
input
=
{}
entry_point
.
output
=
{}
for
entry
in
flow
.
entries
:
entry_point
.
gen
[
entry
]
=
Uninitialized
entry_point
.
output
[
entry
]
=
set
([
Uninitialized
])
# Per-block reaching definitons
dirty
=
True
while
dirty
:
dirty
=
False
for
block
in
flow
.
blocks
:
input
=
{}
for
parent
in
block
.
parents
:
for
entry
,
items
in
parent
.
output
.
iteritems
():
if
entry
in
input
:
input
[
entry
].
update
(
items
)
else
:
input
[
entry
]
=
set
(
items
)
output
=
{}
for
entry
,
items
in
input
.
iteritems
():
if
entry
in
block
.
gen
:
continue
output
[
entry
]
=
set
(
items
)
if
entry
in
block
.
bounded
:
output
[
entry
].
discard
(
Uninitialized
)
for
entry
,
item
in
block
.
gen
.
iteritems
():
output
[
entry
]
=
set
([
item
])
if
not
dirty
:
if
output
!=
block
.
output
:
dirty
=
True
block
.
input
=
input
block
.
output
=
output
flow
.
initialize
()
flow
.
reaching_definitions
()
# Track down state
assignments
=
set
()
...
...
@@ -386,28 +419,29 @@ def check_definitions(flow, compiler_directives):
assmt_nodes
=
set
()
for
block
in
flow
.
blocks
:
state
=
{}
for
entry
,
items
in
block
.
input
.
iteritems
():
state
[
entry
]
=
set
(
items
)
i_state
=
block
.
i_input
for
stat
in
block
.
stats
:
i_assmts
=
flow
.
assmts
[
stat
.
entry
]
state
=
flow
.
map_one
(
i_state
,
stat
.
entry
)
if
isinstance
(
stat
,
NameAssignment
):
stat
.
lhs
.
cf_state
.
update
(
state
[
stat
.
entry
]
)
stat
.
lhs
.
cf_state
.
update
(
state
)
assmt_nodes
.
add
(
stat
.
lhs
)
i_state
=
i_state
&
~
i_assmts
.
mask
if
stat
.
rhs
:
state
[
stat
.
entry
]
=
set
([
stat
])
i_state
|=
stat
.
bit
else
:
state
[
stat
.
entry
]
=
set
([
Uninitialized
])
i_state
|=
i_assmts
.
bit
assignments
.
add
(
stat
)
stat
.
entry
.
cf_assignments
.
append
(
stat
)
elif
isinstance
(
stat
,
NameReference
):
references
[
stat
.
node
]
=
stat
.
entry
stat
.
entry
.
cf_references
.
append
(
stat
)
stat
.
node
.
cf_state
.
update
(
state
[
stat
.
entry
]
)
stat
.
node
.
cf_state
.
update
(
state
)
if
not
stat
.
node
.
allow_null
:
state
[
stat
.
entry
].
discard
(
Uninitialized
)
for
assmt
in
state
[
stat
.
entry
]:
if
assmt
is
not
Uninitialized
:
assmt
.
refs
.
add
(
stat
)
i_state
&=
~
i_assmts
.
bit
state
.
discard
(
Uninitialized
)
for
assmt
in
state
:
assmt
.
refs
.
add
(
stat
)
# Check variable usage
warn_maybe_uninitialized
=
compiler_directives
[
'warn.maybe_uninitialized'
]
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment