Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
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
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
Pyston
Commits
742dc66c
Commit
742dc66c
authored
May 26, 2016
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make DefinednessAnalysis return a bitset
Maybe not the best place to start
parent
3fe4964c
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
117 additions
and
18 deletions
+117
-18
src/analysis/function_analysis.cpp
src/analysis/function_analysis.cpp
+45
-15
src/analysis/function_analysis.h
src/analysis/function_analysis.h
+45
-1
src/codegen/ast_interpreter.cpp
src/codegen/ast_interpreter.cpp
+5
-2
src/core/cfg.cpp
src/core/cfg.cpp
+12
-0
src/core/cfg.h
src/core/cfg.h
+10
-0
No files found.
src/analysis/function_analysis.cpp
View file @
742dc66c
...
...
@@ -26,6 +26,7 @@
#include "analysis/fpc.h"
#include "analysis/scoping_analysis.h"
#include "codegen/osrentry.h"
#include "codegen/irgen/irgenerator.h"
#include "core/ast.h"
#include "core/cfg.h"
#include "core/common.h"
...
...
@@ -382,21 +383,41 @@ void DefinednessAnalysis::run(llvm::DenseMap<InternedString, DefinednessAnalysis
// Don't run this twice:
assert
(
!
defined_at_end
.
size
());
auto
cfg
=
initial_block
->
cfg
;
auto
&&
vreg_info
=
cfg
->
getVRegInfo
();
int
nvregs
=
vreg_info
.
getTotalNumOfVRegs
();
ASSERT
(
nvregs
==
initial_map
.
size
(),
"%d %d"
,
nvregs
,
initial_map
.
size
());
for
(
auto
&&
p
:
initial_map
)
{
// Run it through getVReg to make sure that the vreg exists
ASSERT
(
vreg_info
.
getVReg
(
p
.
first
)
>=
0
,
"%s"
,
p
.
first
.
c_str
());
}
computeFixedPoint
(
std
::
move
(
initial_map
),
initial_block
,
DefinednessBBAnalyzer
(
scope_info
),
false
,
defined_at_beginning
,
defined_at_end
);
for
(
const
auto
&
p
:
defined_at_end
)
{
RequiredSet
&
required
=
defined_at_end_sets
[
p
.
first
];
for
(
const
auto
&
p2
:
p
.
second
)
{
assert
(
p
.
second
.
size
()
==
nvregs
);
assert
(
!
defined_at_end_sets
.
count
(
p
.
first
));
RequiredSet
&
required
=
defined_at_end_sets
.
insert
(
std
::
make_pair
(
p
.
first
,
RequiredSet
(
nvregs
))).
first
->
second
;
//required.resize(nvregs, /* value= */ false);
for
(
int
vreg
=
0
;
vreg
<
nvregs
;
vreg
++
)
{
// TODO shouldn't have to use name at all
InternedString
name
=
vreg_info
.
getName
(
vreg
);
#ifndef NDEBUG
ScopeInfo
::
VarScopeType
vst
=
scope_info
->
getScopeTypeOfName
(
p2
.
first
);
ScopeInfo
::
VarScopeType
vst
=
scope_info
->
getScopeTypeOfName
(
name
);
assert
(
vst
!=
ScopeInfo
::
VarScopeType
::
GLOBAL
&&
vst
!=
ScopeInfo
::
VarScopeType
::
NAME
);
#endif
// TODO: don't returned a RequiredSet here, just use a bitset
assert
(
p2
.
second
!=
DefinednessAnalysis
::
Unknown
);
if
(
p2
.
second
!=
DefinednessAnalysis
::
Undefined
)
required
.
insert
(
p2
.
first
);
assert
(
p
.
second
.
count
(
name
));
auto
status
=
p
.
second
.
find
(
name
)
->
second
;
assert
(
status
!=
DefinednessAnalysis
::
Unknown
);
if
(
status
!=
DefinednessAnalysis
::
Undefined
)
required
.
set
(
vreg
);
}
}
...
...
@@ -414,13 +435,16 @@ DefinednessAnalysis::DefinitionLevel DefinednessAnalysis::isDefinedAtEnd(Interne
const
DefinednessAnalysis
::
RequiredSet
&
DefinednessAnalysis
::
getDefinedNamesAtEnd
(
CFGBlock
*
block
)
{
assert
(
defined_at_end_sets
.
count
(
block
));
return
defined_at_end_sets
[
block
]
;
return
defined_at_end_sets
.
find
(
block
)
->
second
;
}
PhiAnalysis
::
PhiAnalysis
(
llvm
::
DenseMap
<
InternedString
,
DefinednessAnalysis
::
DefinitionLevel
>
initial_map
,
CFGBlock
*
initial_block
,
bool
initials_need_phis
,
LivenessAnalysis
*
liveness
,
ScopeInfo
*
scope_info
)
:
definedness
(),
liveness
(
liveness
)
{
auto
cfg
=
initial_block
->
cfg
;
auto
&&
vreg_info
=
cfg
->
getVRegInfo
();
// I think this should always be the case -- if we're going to generate phis for the initial block,
// then we should include the initial arguments as an extra entry point.
assert
(
initials_need_phis
==
(
initial_block
->
predecessors
.
size
()
>
0
));
...
...
@@ -444,8 +468,9 @@ PhiAnalysis::PhiAnalysis(llvm::DenseMap<InternedString, DefinednessAnalysis::Def
if
(
!
definedness
.
defined_at_end
.
count
(
pred
))
continue
;
const
RequiredSet
&
defined
=
definedness
.
getDefinedNamesAtEnd
(
pred
);
for
(
const
auto
&
s
:
defined
)
{
const
VRegSet
&
defined
=
definedness
.
getDefinedNamesAtEnd
(
pred
);
for
(
int
vreg
:
defined
)
{
auto
s
=
vreg_info
.
getName
(
vreg
);
if
(
required
.
count
(
s
)
==
0
&&
liveness
->
isLiveAtEnd
(
s
,
pred
))
{
// printf("%d-%d %s\n", pred->idx, block->idx, s.c_str());
...
...
@@ -520,9 +545,10 @@ std::unique_ptr<PhiAnalysis> computeRequiredPhis(const ParamNames& args, CFG* cf
counter
.
log
();
llvm
::
DenseMap
<
InternedString
,
DefinednessAnalysis
::
DefinitionLevel
>
initial_map
;
auto
&&
vreg_info
=
cfg
->
getVRegInfo
();
assert
(
cfg
->
hasVr
egsAssigned
());
for
(
auto
p
:
cfg
->
sym_vreg_map
)
assert
(
vreg_info
.
hasVR
egsAssigned
());
for
(
auto
p
:
vreg_info
.
getSymVRegMap
()
)
initial_map
[
p
.
first
]
=
DefinednessAnalysis
::
Undefined
;
auto
maybe_add
=
[
&
](
llvm
::
StringRef
s
)
{
...
...
@@ -531,7 +557,7 @@ std::unique_ptr<PhiAnalysis> computeRequiredPhis(const ParamNames& args, CFG* cf
assert
(
vst
!=
ScopeInfo
::
VarScopeType
::
GLOBAL
);
if
(
vst
==
ScopeInfo
::
VarScopeType
::
NAME
)
return
;
assert
(
cfg
->
sym_vreg_map
.
count
(
e
));
assert
(
vreg_info
.
getVReg
(
e
)
>=
0
);
// just run it through for the assertions
initial_map
[
e
]
=
DefinednessAnalysis
::
Defined
;
};
...
...
@@ -542,7 +568,7 @@ std::unique_ptr<PhiAnalysis> computeRequiredPhis(const ParamNames& args, CFG* cf
if
(
args
.
kwarg
.
size
())
maybe_add
(
args
.
kwarg
);
assert
(
initial_map
.
size
()
==
cfg
->
sym_vreg_map
.
size
());
assert
(
initial_map
.
size
()
==
vreg_info
.
getTotalNumOfVRegs
());
return
std
::
unique_ptr
<
PhiAnalysis
>
(
new
PhiAnalysis
(
std
::
move
(
initial_map
),
cfg
->
getStartingBlock
(),
false
,
liveness
,
scope_info
));
...
...
@@ -555,7 +581,7 @@ std::unique_ptr<PhiAnalysis> computeRequiredPhis(const OSREntryDescriptor* entry
llvm
::
DenseMap
<
InternedString
,
DefinednessAnalysis
::
DefinitionLevel
>
initial_map
;
for
(
auto
p
:
entry_descriptor
->
md
->
source
->
cfg
->
sym_vreg_map
)
{
for
(
auto
p
:
entry_descriptor
->
md
->
source
->
cfg
->
getVRegInfo
().
getSymVRegMap
()
)
{
initial_map
[
p
.
first
]
=
DefinednessAnalysis
::
Undefined
;
}
...
...
@@ -569,6 +595,10 @@ std::unique_ptr<PhiAnalysis> computeRequiredPhis(const OSREntryDescriptor* entry
for
(
const
auto
&
p
:
entry_descriptor
->
args
)
{
if
(
p
.
first
.
s
()[
0
]
==
'!'
)
continue
;
if
(
p
.
first
.
s
()
==
PASSED_CLOSURE_NAME
||
p
.
first
.
s
()
==
FRAME_INFO_PTR_NAME
||
p
.
first
.
s
()
==
PASSED_GENERATOR_NAME
||
p
.
first
.
s
()
==
CREATED_CLOSURE_NAME
)
continue
;
ASSERT
(
initial_map
.
count
(
p
.
first
),
"%s"
,
p
.
first
.
c_str
());
if
(
potentially_undefined
.
count
(
p
.
first
.
s
()))
initial_map
[
p
.
first
]
=
DefinednessAnalysis
::
PotentiallyDefined
;
else
...
...
src/analysis/function_analysis.h
View file @
742dc66c
...
...
@@ -55,6 +55,50 @@ public:
class
PhiAnalysis
;
class
VRegSet
{
private:
// TODO: switch just to a bool*
std
::
vector
<
bool
>
v
;
public:
VRegSet
(
int
num_vregs
)
:
v
(
num_vregs
,
false
)
{}
void
set
(
int
vreg
)
{
v
[
vreg
]
=
true
;
}
class
iterator
{
public:
const
VRegSet
&
set
;
int
i
;
iterator
(
const
VRegSet
&
set
,
int
i
)
:
set
(
set
),
i
(
i
)
{}
iterator
&
operator
++
()
{
do
{
i
++
;
}
while
(
i
<
set
.
v
.
size
()
&&
!
set
.
v
[
i
]);
return
*
this
;
}
bool
operator
==
(
const
iterator
&
rhs
)
const
{
return
i
==
rhs
.
i
;
}
bool
operator
!=
(
const
iterator
&
rhs
)
const
{
return
!
(
*
this
==
rhs
);
}
int
operator
*
()
{
return
i
;
}
};
iterator
begin
()
const
{
for
(
int
i
=
0
;
i
<
v
.
size
();
i
++
)
{
if
(
v
[
i
])
return
iterator
(
*
this
,
i
);
}
return
iterator
(
*
this
,
this
->
v
.
size
());
}
iterator
end
()
const
{
return
iterator
(
*
this
,
this
->
v
.
size
());
}
};
class
DefinednessAnalysis
{
public:
enum
DefinitionLevel
{
...
...
@@ -63,7 +107,7 @@ public:
PotentiallyDefined
,
Defined
,
};
typedef
llvm
::
DenseSet
<
InternedString
>
RequiredSet
;
typedef
VRegSet
RequiredSet
;
private:
llvm
::
DenseMap
<
CFGBlock
*
,
llvm
::
DenseMap
<
InternedString
,
DefinitionLevel
>>
defined_at_beginning
,
defined_at_end
;
...
...
src/codegen/ast_interpreter.cpp
View file @
742dc66c
...
...
@@ -745,8 +745,11 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
// Currently we pass None because the LLVM jit will decref this value even though it may not be set.
static
Box
*
const
VAL_UNDEFINED
=
(
Box
*
)
None
;
for
(
auto
&
name
:
phis
->
definedness
.
getDefinedNamesAtEnd
(
current_block
))
{
Box
*
val
=
vregs
[
getVRegInfo
().
getVReg
(
name
)];
const
VRegSet
&
defined
=
phis
->
definedness
.
getDefinedNamesAtEnd
(
current_block
);
for
(
int
vreg
:
defined
)
{
InternedString
name
=
source_info
->
cfg
->
getVRegInfo
().
getName
(
vreg
);
Box
*
val
=
vregs
[
vreg
];
if
(
!
liveness
->
isLiveAtEnd
(
name
,
current_block
))
continue
;
...
...
src/core/cfg.cpp
View file @
742dc66c
...
...
@@ -2681,6 +2681,7 @@ public:
int
next_vreg
;
llvm
::
DenseMap
<
InternedString
,
int
>
sym_vreg_map
;
llvm
::
DenseMap
<
InternedString
,
std
::
unordered_set
<
CFGBlock
*>>
sym_blocks_map
;
std
::
vector
<
InternedString
>
vreg_sym_map
;
enum
Step
{
TrackBlockUsage
=
0
,
UserVisible
,
CrossBlock
,
SingleBlockUse
}
step
;
...
...
@@ -2750,13 +2751,21 @@ public:
int
assignVReg
(
InternedString
id
)
{
auto
it
=
sym_vreg_map
.
find
(
id
);
if
(
sym_vreg_map
.
end
()
==
it
)
{
ASSERT
(
next_vreg
==
sym_vreg_map
.
size
(),
"%d %d"
,
next_vreg
,
sym_vreg_map
.
size
());
assert
(
next_vreg
==
vreg_sym_map
.
size
());
sym_vreg_map
[
id
]
=
next_vreg
;
vreg_sym_map
.
push_back
(
id
);
return
next_vreg
++
;
}
return
it
->
second
;
}
};
// XXX temporarily disable vreg reuse, since for the transition we want to make it very
// easy to convert between vregs and names.
#define REUSE_VREGS 0
void
VRegInfo
::
assignVRegs
(
CFG
*
cfg
,
const
ParamNames
&
param_names
,
ScopeInfo
*
scope_info
)
{
assert
(
!
hasVRegsAssigned
());
...
...
@@ -2768,8 +2777,10 @@ void VRegInfo::assignVRegs(CFG* cfg, const ParamNames& param_names, ScopeInfo* s
for
(
CFGBlock
*
b
:
cfg
->
blocks
)
{
visitor
.
current_block
=
b
;
#if REUSE_VREGS
if
(
step
==
AssignVRegsVisitor
::
SingleBlockUse
)
visitor
.
next_vreg
=
num_vregs_cross_block
;
#endif
if
(
b
==
cfg
->
getStartingBlock
())
{
for
(
auto
*
name
:
param_names
.
arg_names
)
{
...
...
@@ -2796,6 +2807,7 @@ void VRegInfo::assignVRegs(CFG* cfg, const ParamNames& param_names, ScopeInfo* s
num_vregs
=
num_vregs_cross_block
=
visitor
.
next_vreg
;
}
sym_vreg_map
=
std
::
move
(
visitor
.
sym_vreg_map
);
vreg_sym_map
=
std
::
move
(
visitor
.
vreg_sym_map
);
assert
(
hasVRegsAssigned
());
}
...
...
src/core/cfg.h
View file @
742dc66c
...
...
@@ -87,6 +87,10 @@ class VRegInfo {
private:
llvm
::
DenseMap
<
InternedString
,
int
>
sym_vreg_map_user_visible
;
llvm
::
DenseMap
<
InternedString
,
int
>
sym_vreg_map
;
// Reverse map, from vreg->symbol name.
std
::
vector
<
InternedString
>
vreg_sym_map
;
int
num_vregs_cross_block
=
-
1
;
int
num_vregs
=
-
1
;
...
...
@@ -105,6 +109,12 @@ public:
return
it
->
second
;
}
InternedString
getName
(
int
vreg
)
const
{
assert
(
hasVRegsAssigned
());
assert
(
vreg
>=
0
&&
vreg
<
num_vregs
);
return
vreg_sym_map
[
vreg
];
}
bool
isUserVisibleVReg
(
int
vreg
)
const
{
return
vreg
<
sym_vreg_map_user_visible
.
size
();
}
bool
isCrossBlockVReg
(
int
vreg
)
const
{
return
!
isUserVisibleVReg
(
vreg
)
&&
vreg
<
num_vregs_cross_block
;
}
bool
isBlockLocalVReg
(
int
vreg
)
const
{
return
vreg
>=
num_vregs_cross_block
;
}
...
...
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