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
9f17a19e
Commit
9f17a19e
authored
May 28, 2016
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Switch PhiAnalysis to use VRegSets
parent
84b05dab
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
123 additions
and
87 deletions
+123
-87
src/analysis/function_analysis.cpp
src/analysis/function_analysis.cpp
+51
-48
src/analysis/function_analysis.h
src/analysis/function_analysis.h
+21
-13
src/codegen/ast_interpreter.cpp
src/codegen/ast_interpreter.cpp
+2
-2
src/codegen/irgen.cpp
src/codegen/irgen.cpp
+16
-14
src/codegen/irgen/irgenerator.cpp
src/codegen/irgen/irgenerator.cpp
+3
-2
src/codegen/irgen/irgenerator.h
src/codegen/irgen/irgenerator.h
+2
-0
src/core/cfg.cpp
src/core/cfg.cpp
+2
-4
src/core/cfg.h
src/core/cfg.h
+26
-4
No files found.
src/analysis/function_analysis.cpp
View file @
9f17a19e
...
@@ -378,32 +378,26 @@ void DefinednessBBAnalyzer::processBB(Map& starting, CFGBlock* block) const {
...
@@ -378,32 +378,26 @@ void DefinednessBBAnalyzer::processBB(Map& starting, CFGBlock* block) const {
}
}
}
}
void
DefinednessAnalysis
::
run
(
llvm
::
DenseMap
<
InternedString
,
DefinednessAnalysis
::
DefinitionLevel
>
initial_map
,
void
DefinednessAnalysis
::
run
(
VRegMap
<
DefinednessAnalysis
::
DefinitionLevel
>
initial_map
,
CFGBlock
*
initial_block
,
CFGBlock
*
initial_block
,
ScopeInfo
*
scope_info
)
{
ScopeInfo
*
scope_info
)
{
Timer
_t
(
"DefinednessAnalysis()"
,
10
);
Timer
_t
(
"DefinednessAnalysis()"
,
10
);
// Don't run this twice:
// Don't run this twice:
assert
(
!
defined_at_end
.
size
());
assert
(
!
defined_at_end
.
size
());
auto
cfg
=
initial_block
->
cfg
;
auto
cfg
=
initial_block
->
cfg
;
int
nvregs
=
cfg
->
getVRegInfo
().
getTotalNumOfVRegs
();
assert
(
initial_map
.
numVregs
()
==
nvregs
);
auto
&&
vreg_info
=
cfg
->
getVRegInfo
();
auto
&&
vreg_info
=
cfg
->
getVRegInfo
();
int
nvregs
=
vreg_info
.
getTotalNumOfVRegs
();
computeFixedPoint
(
std
::
move
(
initial_map
),
initial_block
,
DefinednessBBAnalyzer
(
scope_info
),
false
,
ASSERT
(
nvregs
==
initial_map
.
size
(),
"%d %d"
,
nvregs
,
initial_map
.
size
());
VRegMap
<
DefinednessAnalysis
::
DefinitionLevel
>
real_initial_map
(
nvregs
);
for
(
auto
&&
p
:
initial_map
)
{
real_initial_map
[
vreg_info
.
getVReg
(
p
.
first
)]
=
p
.
second
;
}
computeFixedPoint
(
std
::
move
(
real_initial_map
),
initial_block
,
DefinednessBBAnalyzer
(
scope_info
),
false
,
defined_at_beginning
,
defined_at_end
);
defined_at_beginning
,
defined_at_end
);
for
(
const
auto
&
p
:
defined_at_end
)
{
for
(
const
auto
&
p
:
defined_at_end
)
{
assert
(
p
.
second
.
numVregs
()
==
nvregs
);
assert
(
p
.
second
.
numVregs
()
==
nvregs
);
assert
(
!
defined_at_end_sets
.
count
(
p
.
first
));
assert
(
!
defined_at_end_sets
.
count
(
p
.
first
));
RequiredSet
&
required
=
defined_at_end_sets
.
insert
(
std
::
make_pair
(
p
.
first
,
Required
Set
(
nvregs
))).
first
->
second
;
VRegSet
&
required
=
defined_at_end_sets
.
insert
(
std
::
make_pair
(
p
.
first
,
VReg
Set
(
nvregs
))).
first
->
second
;
// required.resize(nvregs, /* value= */ false);
// required.resize(nvregs, /* value= */ false);
...
@@ -434,15 +428,14 @@ DefinednessAnalysis::DefinitionLevel DefinednessAnalysis::isDefinedAtEnd(Interne
...
@@ -434,15 +428,14 @@ DefinednessAnalysis::DefinitionLevel DefinednessAnalysis::isDefinedAtEnd(Interne
return
map
[
cfg
->
getVRegInfo
().
getVReg
(
name
)];
return
map
[
cfg
->
getVRegInfo
().
getVReg
(
name
)];
}
}
const
DefinednessAnalysis
::
RequiredSet
&
DefinednessAnalysis
::
getDefinedName
sAtEnd
(
CFGBlock
*
block
)
{
const
VRegSet
&
DefinednessAnalysis
::
getDefinedVreg
sAtEnd
(
CFGBlock
*
block
)
{
assert
(
defined_at_end_sets
.
count
(
block
));
assert
(
defined_at_end_sets
.
count
(
block
));
return
defined_at_end_sets
.
find
(
block
)
->
second
;
return
defined_at_end_sets
.
find
(
block
)
->
second
;
}
}
PhiAnalysis
::
PhiAnalysis
(
llvm
::
DenseMap
<
InternedString
,
DefinednessAnalysis
::
DefinitionLevel
>
initial_map
,
PhiAnalysis
::
PhiAnalysis
(
VRegMap
<
DefinednessAnalysis
::
DefinitionLevel
>
initial_map
,
CFGBlock
*
initial_block
,
CFGBlock
*
initial_block
,
bool
initials_need_phis
,
LivenessAnalysis
*
liveness
,
bool
initials_need_phis
,
LivenessAnalysis
*
liveness
,
ScopeInfo
*
scope_info
)
ScopeInfo
*
scope_info
)
:
definedness
(),
empty_set
(
initial_map
.
numVregs
()),
liveness
(
liveness
)
{
:
definedness
(),
liveness
(
liveness
)
{
auto
cfg
=
initial_block
->
cfg
;
auto
cfg
=
initial_block
->
cfg
;
auto
&&
vreg_info
=
cfg
->
getVRegInfo
();
auto
&&
vreg_info
=
cfg
->
getVRegInfo
();
...
@@ -450,13 +443,17 @@ PhiAnalysis::PhiAnalysis(llvm::DenseMap<InternedString, DefinednessAnalysis::Def
...
@@ -450,13 +443,17 @@ PhiAnalysis::PhiAnalysis(llvm::DenseMap<InternedString, DefinednessAnalysis::Def
// then we should include the initial arguments as an extra entry point.
// then we should include the initial arguments as an extra entry point.
assert
(
initials_need_phis
==
(
initial_block
->
predecessors
.
size
()
>
0
));
assert
(
initials_need_phis
==
(
initial_block
->
predecessors
.
size
()
>
0
));
int
num_vregs
=
initial_map
.
numVregs
();
assert
(
num_vregs
==
vreg_info
.
getTotalNumOfVRegs
());
definedness
.
run
(
std
::
move
(
initial_map
),
initial_block
,
scope_info
);
definedness
.
run
(
std
::
move
(
initial_map
),
initial_block
,
scope_info
);
Timer
_t
(
"PhiAnalysis()"
,
10
);
Timer
_t
(
"PhiAnalysis()"
,
10
);
for
(
const
auto
&
p
:
definedness
.
defined_at_end
)
{
for
(
const
auto
&
p
:
definedness
.
defined_at_end
)
{
CFGBlock
*
block
=
p
.
first
;
CFGBlock
*
block
=
p
.
first
;
RequiredSet
&
required
=
required_phis
[
block
];
assert
(
!
required_phis
.
count
(
block
));
VRegSet
&
required
=
required_phis
.
insert
(
std
::
make_pair
(
block
,
VRegSet
(
num_vregs
))).
first
->
second
;
int
npred
=
0
;
int
npred
=
0
;
for
(
CFGBlock
*
pred
:
block
->
predecessors
)
{
for
(
CFGBlock
*
pred
:
block
->
predecessors
)
{
...
@@ -469,13 +466,13 @@ PhiAnalysis::PhiAnalysis(llvm::DenseMap<InternedString, DefinednessAnalysis::Def
...
@@ -469,13 +466,13 @@ PhiAnalysis::PhiAnalysis(llvm::DenseMap<InternedString, DefinednessAnalysis::Def
if
(
!
definedness
.
defined_at_end
.
count
(
pred
))
if
(
!
definedness
.
defined_at_end
.
count
(
pred
))
continue
;
continue
;
const
VRegSet
&
defined
=
definedness
.
getDefined
Name
sAtEnd
(
pred
);
const
VRegSet
&
defined
=
definedness
.
getDefined
Vreg
sAtEnd
(
pred
);
for
(
int
vreg
:
defined
)
{
for
(
int
vreg
:
defined
)
{
auto
s
=
vreg_info
.
getName
(
vreg
);
auto
s
=
vreg_info
.
getName
(
vreg
);
if
(
required
.
count
(
s
)
==
0
&&
liveness
->
isLiveAtEnd
(
s
,
pred
))
{
if
(
!
required
[
vreg
]
&&
liveness
->
isLiveAtEnd
(
s
,
pred
))
{
// printf("%d-%d %s\n", pred->idx, block->idx, s.c_str());
// printf("%d-%d %s\n", pred->idx, block->idx, s.c_str());
required
.
insert
(
s
);
required
.
set
(
vreg
);
}
}
}
}
}
}
...
@@ -486,23 +483,23 @@ PhiAnalysis::PhiAnalysis(llvm::DenseMap<InternedString, DefinednessAnalysis::Def
...
@@ -486,23 +483,23 @@ PhiAnalysis::PhiAnalysis(llvm::DenseMap<InternedString, DefinednessAnalysis::Def
us_phis
.
log
(
_t
.
end
());
us_phis
.
log
(
_t
.
end
());
}
}
const
PhiAnalysis
::
RequiredSet
&
PhiAnalysis
::
getAllRequiredAfter
(
CFGBlock
*
block
)
{
const
VRegSet
&
PhiAnalysis
::
getAllRequiredAfter
(
CFGBlock
*
block
)
{
static
RequiredSet
empty
;
if
(
block
->
successors
.
size
()
==
0
)
if
(
block
->
successors
.
size
()
==
0
)
return
empty
;
return
empty
_set
;
assert
(
required_phis
.
count
(
block
->
successors
[
0
]));
assert
(
required_phis
.
count
(
block
->
successors
[
0
]));
return
required_phis
[
block
->
successors
[
0
]]
;
return
required_phis
.
find
(
block
->
successors
[
0
])
->
second
;
}
}
const
PhiAnalysis
::
Required
Set
&
PhiAnalysis
::
getAllRequiredFor
(
CFGBlock
*
block
)
{
const
VReg
Set
&
PhiAnalysis
::
getAllRequiredFor
(
CFGBlock
*
block
)
{
assert
(
required_phis
.
count
(
block
));
assert
(
required_phis
.
count
(
block
));
return
required_phis
[
block
]
;
return
required_phis
.
find
(
block
)
->
second
;
}
}
// TODO: switch this to taking a vreg
bool
PhiAnalysis
::
isRequired
(
InternedString
name
,
CFGBlock
*
block
)
{
bool
PhiAnalysis
::
isRequired
(
InternedString
name
,
CFGBlock
*
block
)
{
assert
(
!
startswith
(
name
.
s
(),
"!"
));
assert
(
!
startswith
(
name
.
s
(),
"!"
));
assert
(
required_phis
.
count
(
block
));
assert
(
required_phis
.
count
(
block
));
return
required_phis
[
block
].
count
(
name
)
!=
0
;
return
required_phis
.
find
(
block
)
->
second
[
block
->
cfg
->
getVRegInfo
().
getVReg
(
name
)]
;
}
}
bool
PhiAnalysis
::
isRequiredAfter
(
InternedString
name
,
CFGBlock
*
block
)
{
bool
PhiAnalysis
::
isRequiredAfter
(
InternedString
name
,
CFGBlock
*
block
)
{
...
@@ -548,31 +545,34 @@ std::unique_ptr<PhiAnalysis> computeRequiredPhis(const ParamNames& args, CFG* cf
...
@@ -548,31 +545,34 @@ std::unique_ptr<PhiAnalysis> computeRequiredPhis(const ParamNames& args, CFG* cf
static
StatCounter
counter
(
"num_phi_analysis"
);
static
StatCounter
counter
(
"num_phi_analysis"
);
counter
.
log
();
counter
.
log
();
llvm
::
DenseMap
<
InternedString
,
DefinednessAnalysis
::
DefinitionLevel
>
initial_map
;
auto
&&
vreg_info
=
cfg
->
getVRegInfo
();
auto
&&
vreg_info
=
cfg
->
getVRegInfo
();
int
num_vregs
=
vreg_info
.
getTotalNumOfVRegs
();
VRegMap
<
DefinednessAnalysis
::
DefinitionLevel
>
initial_map
(
num_vregs
);
assert
(
vreg_info
.
hasVRegsAssigned
());
assert
(
vreg_info
.
hasVRegsAssigned
());
for
(
auto
p
:
vreg_info
.
getSymVRegMap
())
for
(
int
vreg
=
0
;
vreg
<
num_vregs
;
vreg
++
)
{
initial_map
[
p
.
first
]
=
DefinednessAnalysis
::
Undefined
;
initial_map
[
vreg
]
=
DefinednessAnalysis
::
Undefined
;
}
auto
maybe_add
=
[
&
](
llvm
::
StringRef
s
)
{
auto
maybe_add
=
[
&
](
AST_Name
*
n
)
{
InternedString
e
=
scope_info
->
internString
(
s
)
;
ScopeInfo
::
VarScopeType
vst
=
n
->
lookup_type
;
ScopeInfo
::
VarScopeType
vst
=
scope_info
->
getScopeTypeOfName
(
e
);
assert
(
vst
!=
ScopeInfo
::
VarScopeType
::
UNKNOWN
);
assert
(
vst
!=
ScopeInfo
::
VarScopeType
::
GLOBAL
);
assert
(
vst
!=
ScopeInfo
::
VarScopeType
::
GLOBAL
);
if
(
vst
==
ScopeInfo
::
VarScopeType
::
NAME
)
if
(
vst
==
ScopeInfo
::
VarScopeType
::
NAME
)
return
;
return
;
assert
(
vreg_info
.
getVReg
(
e
)
>=
0
);
// just run it through for the assertions
assert
(
n
->
vreg
>=
0
);
initial_map
[
e
]
=
DefinednessAnalysis
::
Defined
;
initial_map
[
n
->
vreg
]
=
DefinednessAnalysis
::
Defined
;
};
};
for
(
auto
e
:
args
.
args
)
for
(
auto
e
:
args
.
arg
_name
s
)
maybe_add
(
e
);
maybe_add
(
e
);
if
(
args
.
vararg
.
size
()
)
if
(
args
.
vararg
_name
)
maybe_add
(
args
.
vararg
);
maybe_add
(
args
.
vararg
_name
);
if
(
args
.
kwarg
.
size
()
)
if
(
args
.
kwarg
_name
)
maybe_add
(
args
.
kwarg
);
maybe_add
(
args
.
kwarg
_name
);
assert
(
initial_map
.
size
()
==
vreg_info
.
getTotalNumOfVRegs
());
assert
(
initial_map
.
numVregs
()
==
vreg_info
.
getTotalNumOfVRegs
());
return
std
::
unique_ptr
<
PhiAnalysis
>
(
return
std
::
unique_ptr
<
PhiAnalysis
>
(
new
PhiAnalysis
(
std
::
move
(
initial_map
),
cfg
->
getStartingBlock
(),
false
,
liveness
,
scope_info
));
new
PhiAnalysis
(
std
::
move
(
initial_map
),
cfg
->
getStartingBlock
(),
false
,
liveness
,
scope_info
));
...
@@ -583,10 +583,12 @@ std::unique_ptr<PhiAnalysis> computeRequiredPhis(const OSREntryDescriptor* entry
...
@@ -583,10 +583,12 @@ std::unique_ptr<PhiAnalysis> computeRequiredPhis(const OSREntryDescriptor* entry
static
StatCounter
counter
(
"num_phi_analysis"
);
static
StatCounter
counter
(
"num_phi_analysis"
);
counter
.
log
();
counter
.
log
();
llvm
::
DenseMap
<
InternedString
,
DefinednessAnalysis
::
DefinitionLevel
>
initial_map
;
auto
cfg
=
entry_descriptor
->
md
->
source
->
cfg
;
int
num_vregs
=
cfg
->
getVRegInfo
().
getTotalNumOfVRegs
();
VRegMap
<
DefinednessAnalysis
::
DefinitionLevel
>
initial_map
(
num_vregs
);
for
(
auto
p
:
entry_descriptor
->
md
->
source
->
cfg
->
getVRegInfo
().
getSymVRegMap
()
)
{
for
(
int
vreg
=
0
;
vreg
<
num_vregs
;
vreg
++
)
{
initial_map
[
p
.
first
]
=
DefinednessAnalysis
::
Undefined
;
initial_map
[
vreg
]
=
DefinednessAnalysis
::
Undefined
;
}
}
llvm
::
StringSet
<>
potentially_undefined
;
llvm
::
StringSet
<>
potentially_undefined
;
...
@@ -602,11 +604,12 @@ std::unique_ptr<PhiAnalysis> computeRequiredPhis(const OSREntryDescriptor* entry
...
@@ -602,11 +604,12 @@ std::unique_ptr<PhiAnalysis> computeRequiredPhis(const OSREntryDescriptor* entry
if
(
p
.
first
.
s
()
==
PASSED_CLOSURE_NAME
||
p
.
first
.
s
()
==
FRAME_INFO_PTR_NAME
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
)
||
p
.
first
.
s
()
==
PASSED_GENERATOR_NAME
||
p
.
first
.
s
()
==
CREATED_CLOSURE_NAME
)
continue
;
continue
;
ASSERT
(
initial_map
.
count
(
p
.
first
),
"%s"
,
p
.
first
.
c_str
());
int
vreg
=
cfg
->
getVRegInfo
().
getVReg
(
p
.
first
);
ASSERT
(
initial_map
[
vreg
]
==
DefinednessAnalysis
::
Undefined
,
"%s %d"
,
p
.
first
.
c_str
(),
initial_map
[
vreg
]);
if
(
potentially_undefined
.
count
(
p
.
first
.
s
()))
if
(
potentially_undefined
.
count
(
p
.
first
.
s
()))
initial_map
[
p
.
first
]
=
DefinednessAnalysis
::
PotentiallyDefined
;
initial_map
[
vreg
]
=
DefinednessAnalysis
::
PotentiallyDefined
;
else
else
initial_map
[
p
.
first
]
=
DefinednessAnalysis
::
Defined
;
initial_map
[
vreg
]
=
DefinednessAnalysis
::
Defined
;
}
}
return
std
::
unique_ptr
<
PhiAnalysis
>
(
return
std
::
unique_ptr
<
PhiAnalysis
>
(
...
...
src/analysis/function_analysis.h
View file @
9f17a19e
...
@@ -63,7 +63,15 @@ private:
...
@@ -63,7 +63,15 @@ private:
public:
public:
VRegSet
(
int
num_vregs
)
:
v
(
num_vregs
,
false
)
{}
VRegSet
(
int
num_vregs
)
:
v
(
num_vregs
,
false
)
{}
void
set
(
int
vreg
)
{
v
[
vreg
]
=
true
;
}
// TODO: what is the referenc type here?
bool
operator
[](
int
vreg
)
{
assert
(
vreg
>=
0
&&
vreg
<
v
.
size
());
return
v
[
vreg
];
}
void
set
(
int
vreg
)
{
assert
(
vreg
>=
0
&&
vreg
<
v
.
size
());
v
[
vreg
]
=
true
;
}
class
iterator
{
class
iterator
{
public:
public:
...
@@ -145,44 +153,44 @@ public:
...
@@ -145,44 +153,44 @@ public:
PotentiallyDefined
,
PotentiallyDefined
,
Defined
,
Defined
,
};
};
typedef
VRegSet
RequiredSet
;
private:
private:
llvm
::
DenseMap
<
CFGBlock
*
,
VRegMap
<
DefinitionLevel
>>
defined_at_beginning
,
defined_at_end
;
llvm
::
DenseMap
<
CFGBlock
*
,
VRegMap
<
DefinitionLevel
>>
defined_at_beginning
,
defined_at_end
;
llvm
::
DenseMap
<
CFGBlock
*
,
Required
Set
>
defined_at_end_sets
;
llvm
::
DenseMap
<
CFGBlock
*
,
VReg
Set
>
defined_at_end_sets
;
public:
public:
DefinednessAnalysis
()
{}
DefinednessAnalysis
()
{}
void
run
(
llvm
::
DenseMap
<
InternedString
,
DefinitionLevel
>
initial_map
,
CFGBlock
*
initial_block
,
void
run
(
VRegMap
<
DefinitionLevel
>
initial_map
,
CFGBlock
*
initial_block
,
ScopeInfo
*
scope_info
);
ScopeInfo
*
scope_info
);
DefinitionLevel
isDefinedAtEnd
(
InternedString
name
,
CFGBlock
*
block
);
DefinitionLevel
isDefinedAtEnd
(
InternedString
name
,
CFGBlock
*
block
);
const
RequiredSet
&
getDefinedName
sAtEnd
(
CFGBlock
*
block
);
const
VRegSet
&
getDefinedVreg
sAtEnd
(
CFGBlock
*
block
);
friend
class
PhiAnalysis
;
friend
class
PhiAnalysis
;
};
};
class
PhiAnalysis
{
class
PhiAnalysis
{
public:
public:
typedef
llvm
::
DenseSet
<
InternedString
>
RequiredSet
;
DefinednessAnalysis
definedness
;
DefinednessAnalysis
definedness
;
VRegSet
empty_set
;
private:
private:
LivenessAnalysis
*
liveness
;
LivenessAnalysis
*
liveness
;
llvm
::
DenseMap
<
CFGBlock
*
,
Required
Set
>
required_phis
;
llvm
::
DenseMap
<
CFGBlock
*
,
VReg
Set
>
required_phis
;
public:
public:
// Initials_need_phis specifies that initial_map should count as an additional entry point
// Initials_need_phis specifies that initial_map should count as an additional entry point
// that may require phis.
// that may require phis.
PhiAnalysis
(
llvm
::
DenseMap
<
InternedString
,
DefinednessAnalysis
::
DefinitionLevel
>
initial_map
,
PhiAnalysis
(
VRegMap
<
DefinednessAnalysis
::
DefinitionLevel
>
initial_map
,
CFGBlock
*
initial_block
,
CFGBlock
*
initial_block
,
bool
initials_need_phis
,
LivenessAnalysis
*
liveness
,
ScopeInfo
*
scope_info
);
bool
initials_need_phis
,
LivenessAnalysis
*
liveness
,
ScopeInfo
*
scope_info
);
// TODO: convert these to taking vregs
bool
isRequired
(
InternedString
name
,
CFGBlock
*
block
);
bool
isRequired
(
InternedString
name
,
CFGBlock
*
block
);
bool
isRequiredAfter
(
InternedString
name
,
CFGBlock
*
block
);
bool
isRequiredAfter
(
InternedString
name
,
CFGBlock
*
block
);
const
RequiredSet
&
getAllRequiredAfter
(
CFGBlock
*
block
);
const
VRegSet
&
getAllRequiredAfter
(
CFGBlock
*
block
);
const
RequiredSet
&
getAllRequiredFor
(
CFGBlock
*
block
);
const
VRegSet
&
getAllRequiredFor
(
CFGBlock
*
block
);
// TODO: convert these to taking vregs
// If "name" may be undefined at the beginning of any immediate successor block of "block":
// If "name" may be undefined at the beginning of any immediate successor block of "block":
bool
isPotentiallyUndefinedAfter
(
InternedString
name
,
CFGBlock
*
block
);
bool
isPotentiallyUndefinedAfter
(
InternedString
name
,
CFGBlock
*
block
);
// If "name" may be undefined at the beginning of "block"
// If "name" may be undefined at the beginning of "block"
...
...
src/codegen/ast_interpreter.cpp
View file @
9f17a19e
...
@@ -155,7 +155,7 @@ public:
...
@@ -155,7 +155,7 @@ public:
~
ASTInterpreter
()
{
Py_XDECREF
(
this
->
created_closure
);
}
~
ASTInterpreter
()
{
Py_XDECREF
(
this
->
created_closure
);
}
const
VRegInfo
&
getVRegInfo
()
const
{
return
source_info
->
cfg
->
getVRegInfo
();
}
const
VRegInfo
&
getVRegInfo
()
const
{
return
source_info
->
cfg
->
getVRegInfo
();
}
const
llvm
::
DenseMap
<
InternedString
,
int
>&
getSymVRegMap
()
const
{
const
llvm
::
DenseMap
<
InternedString
,
DefaultedInt
<-
1
>
>&
getSymVRegMap
()
const
{
return
source_info
->
cfg
->
getVRegInfo
().
getSymVRegMap
();
return
source_info
->
cfg
->
getVRegInfo
().
getSymVRegMap
();
}
}
...
@@ -745,7 +745,7 @@ Box* ASTInterpreter::doOSR(AST_Jump* node) {
...
@@ -745,7 +745,7 @@ 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.
// 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
;
static
Box
*
const
VAL_UNDEFINED
=
(
Box
*
)
None
;
const
VRegSet
&
defined
=
phis
->
definedness
.
getDefined
Name
sAtEnd
(
current_block
);
const
VRegSet
&
defined
=
phis
->
definedness
.
getDefined
Vreg
sAtEnd
(
current_block
);
for
(
int
vreg
:
defined
)
{
for
(
int
vreg
:
defined
)
{
InternedString
name
=
source_info
->
cfg
->
getVRegInfo
().
getName
(
vreg
);
InternedString
name
=
source_info
->
cfg
->
getVRegInfo
().
getName
(
vreg
);
...
...
src/codegen/irgen.cpp
View file @
9f17a19e
...
@@ -361,12 +361,14 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
...
@@ -361,12 +361,14 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
PhiAnalysis
*
phi_analysis
=
irstate
->
getPhis
();
PhiAnalysis
*
phi_analysis
=
irstate
->
getPhis
();
assert
(
phi_analysis
);
assert
(
phi_analysis
);
CFG
*
cfg
=
source
->
cfg
;
if
(
entry_descriptor
!=
NULL
)
if
(
entry_descriptor
!=
NULL
)
assert
(
blocks
.
count
(
source
->
cfg
->
getStartingBlock
())
==
0
);
assert
(
blocks
.
count
(
cfg
->
getStartingBlock
())
==
0
);
// We need the entry blocks pre-allocated so that we can jump forward to them.
// We need the entry blocks pre-allocated so that we can jump forward to them.
std
::
unordered_map
<
CFGBlock
*
,
llvm
::
BasicBlock
*>
llvm_entry_blocks
;
std
::
unordered_map
<
CFGBlock
*
,
llvm
::
BasicBlock
*>
llvm_entry_blocks
;
for
(
CFGBlock
*
block
:
source
->
cfg
->
blocks
)
{
for
(
CFGBlock
*
block
:
cfg
->
blocks
)
{
if
(
blocks
.
count
(
block
)
==
0
)
{
if
(
blocks
.
count
(
block
)
==
0
)
{
llvm_entry_blocks
[
block
]
=
NULL
;
llvm_entry_blocks
[
block
]
=
NULL
;
continue
;
continue
;
...
@@ -514,8 +516,8 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
...
@@ -514,8 +516,8 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
CFGBlock
*
initial_block
=
NULL
;
CFGBlock
*
initial_block
=
NULL
;
if
(
entry_descriptor
)
{
if
(
entry_descriptor
)
{
initial_block
=
entry_descriptor
->
backedge
->
target
;
initial_block
=
entry_descriptor
->
backedge
->
target
;
}
else
if
(
blocks
.
count
(
source
->
cfg
->
getStartingBlock
()))
{
}
else
if
(
blocks
.
count
(
cfg
->
getStartingBlock
()))
{
initial_block
=
source
->
cfg
->
getStartingBlock
();
initial_block
=
cfg
->
getStartingBlock
();
}
}
// The rest of this code assumes that for each non-entry block that gets evaluated,
// The rest of this code assumes that for each non-entry block that gets evaluated,
...
@@ -548,14 +550,13 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
...
@@ -548,14 +550,13 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
// Set initial symbol table:
// Set initial symbol table:
// If we're in the starting block, no phis or symbol table changes for us.
// If we're in the starting block, no phis or symbol table changes for us.
// Generate function entry code instead.
// Generate function entry code instead.
if
(
block
==
source
->
cfg
->
getStartingBlock
())
{
if
(
block
==
cfg
->
getStartingBlock
())
{
assert
(
entry_descriptor
==
NULL
);
assert
(
entry_descriptor
==
NULL
);
if
(
ENABLE_REOPT
&&
effort
<
EffortLevel
::
MAXIMAL
&&
source
->
ast
!=
NULL
if
(
ENABLE_REOPT
&&
effort
<
EffortLevel
::
MAXIMAL
&&
source
->
ast
!=
NULL
&&
source
->
ast
->
type
!=
AST_TYPE
::
Module
)
{
&&
source
->
ast
->
type
!=
AST_TYPE
::
Module
)
{
llvm
::
BasicBlock
*
preentry_bb
llvm
::
BasicBlock
*
preentry_bb
=
llvm
::
BasicBlock
::
Create
(
=
llvm
::
BasicBlock
::
Create
(
g
.
context
,
"pre_entry"
,
irstate
->
getLLVMFunction
(),
g
.
context
,
"pre_entry"
,
irstate
->
getLLVMFunction
(),
llvm_entry_blocks
[
cfg
->
getStartingBlock
()]);
llvm_entry_blocks
[
source
->
cfg
->
getStartingBlock
()]);
llvm
::
BasicBlock
*
reopt_bb
=
llvm
::
BasicBlock
::
Create
(
g
.
context
,
"reopt"
,
irstate
->
getLLVMFunction
());
llvm
::
BasicBlock
*
reopt_bb
=
llvm
::
BasicBlock
::
Create
(
g
.
context
,
"reopt"
,
irstate
->
getLLVMFunction
());
emitter
->
getBuilder
()
->
SetInsertPoint
(
preentry_bb
);
emitter
->
getBuilder
()
->
SetInsertPoint
(
preentry_bb
);
...
@@ -580,7 +581,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
...
@@ -580,7 +581,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
llvm
::
MDNode
*
branch_weights
=
llvm
::
MDNode
::
get
(
g
.
context
,
llvm
::
ArrayRef
<
llvm
::
Metadata
*>
(
md_vals
));
llvm
::
MDNode
*
branch_weights
=
llvm
::
MDNode
::
get
(
g
.
context
,
llvm
::
ArrayRef
<
llvm
::
Metadata
*>
(
md_vals
));
llvm
::
BranchInst
*
guard
=
emitter
->
getBuilder
()
->
CreateCondBr
(
llvm
::
BranchInst
*
guard
=
emitter
->
getBuilder
()
->
CreateCondBr
(
reopt_test
,
reopt_bb
,
llvm_entry_blocks
[
source
->
cfg
->
getStartingBlock
()],
branch_weights
);
reopt_test
,
reopt_bb
,
llvm_entry_blocks
[
cfg
->
getStartingBlock
()],
branch_weights
);
emitter
->
getBuilder
()
->
SetInsertPoint
(
reopt_bb
);
emitter
->
getBuilder
()
->
SetInsertPoint
(
reopt_bb
);
// emitter->getBuilder()->CreateCall(g.funcs.my_assert, getConstantInt(0, g.i1));
// emitter->getBuilder()->CreateCall(g.funcs.my_assert, getConstantInt(0, g.i1));
...
@@ -603,7 +604,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
...
@@ -603,7 +604,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
postcall
->
setTailCall
(
true
);
postcall
->
setTailCall
(
true
);
emitter
->
getBuilder
()
->
CreateRet
(
postcall
);
emitter
->
getBuilder
()
->
CreateRet
(
postcall
);
emitter
->
getBuilder
()
->
SetInsertPoint
(
llvm_entry_blocks
[
source
->
cfg
->
getStartingBlock
()]);
emitter
->
getBuilder
()
->
SetInsertPoint
(
llvm_entry_blocks
[
cfg
->
getStartingBlock
()]);
}
}
generator
->
doFunctionEntry
(
*
irstate
->
getParamNames
(),
cf
->
spec
->
arg_types
);
generator
->
doFunctionEntry
(
*
irstate
->
getParamNames
(),
cf
->
spec
->
arg_types
);
...
@@ -640,7 +641,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
...
@@ -640,7 +641,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
(
*
phis
)[
p
.
first
]
=
std
::
make_pair
(
analyzed_type
,
phi
);
(
*
phis
)[
p
.
first
]
=
std
::
make_pair
(
analyzed_type
,
phi
);
}
}
}
else
if
(
pred
==
NULL
)
{
}
else
if
(
pred
==
NULL
)
{
assert
(
traversal_order
.
size
()
<
source
->
cfg
->
blocks
.
size
());
assert
(
traversal_order
.
size
()
<
cfg
->
blocks
.
size
());
assert
(
phis
);
assert
(
phis
);
assert
(
block
->
predecessors
.
size
());
assert
(
block
->
predecessors
.
size
());
for
(
int
i
=
0
;
i
<
block
->
predecessors
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
block
->
predecessors
.
size
();
i
++
)
{
...
@@ -651,7 +652,8 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
...
@@ -651,7 +652,8 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
std
::
set
<
InternedString
>
names
;
std
::
set
<
InternedString
>
names
;
for
(
const
auto
&
s
:
phi_analysis
->
getAllRequiredFor
(
block
))
{
for
(
const
int
vreg
:
phi_analysis
->
getAllRequiredFor
(
block
))
{
auto
s
=
cfg
->
getVRegInfo
().
getName
(
vreg
);
names
.
insert
(
s
);
names
.
insert
(
s
);
if
(
phi_analysis
->
isPotentiallyUndefinedAfter
(
s
,
block
->
predecessors
[
0
]))
{
if
(
phi_analysis
->
isPotentiallyUndefinedAfter
(
s
,
block
->
predecessors
[
0
]))
{
names
.
insert
(
getIsDefinedName
(
s
,
source
->
getInternedStrings
()));
names
.
insert
(
getIsDefinedName
(
s
,
source
->
getInternedStrings
()));
...
@@ -832,7 +834,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
...
@@ -832,7 +834,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
// the relevant IR, so after we have done all of it, go back through and populate the phi nodes.
// the relevant IR, so after we have done all of it, go back through and populate the phi nodes.
// Also, do some checking to make sure that the phi analysis stuff worked out, and that all blocks
// Also, do some checking to make sure that the phi analysis stuff worked out, and that all blocks
// agreed on what symbols + types they should be propagating for the phis.
// agreed on what symbols + types they should be propagating for the phis.
for
(
CFGBlock
*
b
:
source
->
cfg
->
blocks
)
{
for
(
CFGBlock
*
b
:
cfg
->
blocks
)
{
PHITable
*
phis
=
created_phis
[
b
];
PHITable
*
phis
=
created_phis
[
b
];
if
(
phis
==
NULL
)
if
(
phis
==
NULL
)
continue
;
continue
;
...
@@ -910,7 +912,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
...
@@ -910,7 +912,7 @@ static void emitBBs(IRGenState* irstate, TypeAnalysis* types, const OSREntryDesc
}
}
// deallocate/dereference memory
// deallocate/dereference memory
for
(
CFGBlock
*
b
:
source
->
cfg
->
blocks
)
{
for
(
CFGBlock
*
b
:
cfg
->
blocks
)
{
if
(
ending_symbol_tables
[
b
]
==
NULL
)
if
(
ending_symbol_tables
[
b
]
==
NULL
)
continue
;
continue
;
...
...
src/codegen/irgen/irgenerator.cpp
View file @
9f17a19e
...
@@ -2682,8 +2682,9 @@ private:
...
@@ -2682,8 +2682,9 @@ private:
}
}
}
}
const
PhiAnalysis
::
RequiredSet
&
all_phis
=
irstate
->
getPhis
()
->
getAllRequiredAfter
(
myblock
);
for
(
int
vreg
:
irstate
->
getPhis
()
->
getAllRequiredAfter
(
myblock
))
{
for
(
PhiAnalysis
::
RequiredSet
::
const_iterator
it
=
all_phis
.
begin
(),
end
=
all_phis
.
end
();
it
!=
end
;
++
it
)
{
auto
name
=
irstate
->
getCFG
()
->
getVRegInfo
().
getName
(
vreg
);
auto
it
=
&
name
;
// hack, remove
if
(
VERBOSITY
()
>=
3
)
if
(
VERBOSITY
()
>=
3
)
printf
(
"phi will be required for %s
\n
"
,
it
->
c_str
());
printf
(
"phi will be required for %s
\n
"
,
it
->
c_str
());
assert
(
scope_info
->
getScopeTypeOfName
(
*
it
)
!=
ScopeInfo
::
VarScopeType
::
GLOBAL
);
assert
(
scope_info
->
getScopeTypeOfName
(
*
it
)
!=
ScopeInfo
::
VarScopeType
::
GLOBAL
);
...
...
src/codegen/irgen/irgenerator.h
View file @
9f17a19e
...
@@ -82,6 +82,8 @@ public:
...
@@ -82,6 +82,8 @@ public:
ParamNames
*
param_names
,
GCBuilder
*
gc
,
llvm
::
MDNode
*
func_dbg_info
,
RefcountTracker
*
refcount_tracker
);
ParamNames
*
param_names
,
GCBuilder
*
gc
,
llvm
::
MDNode
*
func_dbg_info
,
RefcountTracker
*
refcount_tracker
);
~
IRGenState
();
~
IRGenState
();
CFG
*
getCFG
()
{
return
getSourceInfo
()
->
cfg
;
}
CompiledFunction
*
getCurFunction
()
{
return
cf
;
}
CompiledFunction
*
getCurFunction
()
{
return
cf
;
}
FunctionMetadata
*
getMD
()
{
return
md
;
}
FunctionMetadata
*
getMD
()
{
return
md
;
}
...
...
src/core/cfg.cpp
View file @
9f17a19e
...
@@ -2677,7 +2677,7 @@ public:
...
@@ -2677,7 +2677,7 @@ public:
ScopeInfo
*
scope_info
;
ScopeInfo
*
scope_info
;
CFGBlock
*
current_block
;
CFGBlock
*
current_block
;
int
next_vreg
;
int
next_vreg
;
llvm
::
DenseMap
<
InternedString
,
int
>
sym_vreg_map
;
llvm
::
DenseMap
<
InternedString
,
DefaultedInt
<-
1
>
>
sym_vreg_map
;
llvm
::
DenseMap
<
InternedString
,
std
::
unordered_set
<
CFGBlock
*>>
sym_blocks_map
;
llvm
::
DenseMap
<
InternedString
,
std
::
unordered_set
<
CFGBlock
*>>
sym_blocks_map
;
std
::
vector
<
InternedString
>
vreg_sym_map
;
std
::
vector
<
InternedString
>
vreg_sym_map
;
...
@@ -2685,9 +2685,7 @@ public:
...
@@ -2685,9 +2685,7 @@ public:
AssignVRegsVisitor
(
ScopeInfo
*
scope_info
)
:
scope_info
(
scope_info
),
current_block
(
0
),
next_vreg
(
0
)
{}
AssignVRegsVisitor
(
ScopeInfo
*
scope_info
)
:
scope_info
(
scope_info
),
current_block
(
0
),
next_vreg
(
0
)
{}
bool
visit_alias
(
AST_alias
*
node
)
override
{
bool
visit_alias
(
AST_alias
*
node
)
override
{
RELEASE_ASSERT
(
0
,
"these should be removed by the cfg"
);
}
RELEASE_ASSERT
(
0
,
"these should be removed by the cfg"
);
}
bool
visit_arguments
(
AST_arguments
*
node
)
override
{
bool
visit_arguments
(
AST_arguments
*
node
)
override
{
for
(
AST_expr
*
d
:
node
->
defaults
)
for
(
AST_expr
*
d
:
node
->
defaults
)
...
...
src/core/cfg.h
View file @
9f17a19e
...
@@ -42,6 +42,26 @@ class CFG;
...
@@ -42,6 +42,26 @@ class CFG;
class
ParamNames
;
class
ParamNames
;
class
ScopeInfo
;
class
ScopeInfo
;
// Simple class to override the default value of an int.
template
<
int
D
=
-
1
>
class
DefaultedInt
{
private:
int
x
;
public:
DefaultedInt
()
:
x
(
D
)
{}
DefaultedInt
(
int
x
)
:
x
(
x
)
{}
DefaultedInt
(
const
DefaultedInt
&
rhs
)
:
x
(
rhs
.
x
)
{}
DefaultedInt
(
DefaultedInt
&&
rhs
)
:
x
(
rhs
.
x
)
{}
void
operator
=
(
const
DefaultedInt
&
rhs
)
{
x
=
rhs
.
x
;
}
void
operator
=
(
DefaultedInt
&&
rhs
)
{
x
=
rhs
.
x
;
}
template
<
typename
T
>
bool
operator
<
(
T
rhs
)
const
{
return
x
<
rhs
;
}
template
<
typename
T
>
bool
operator
>
(
T
rhs
)
const
{
return
x
>
rhs
;
}
template
<
typename
T
>
bool
operator
<=
(
T
rhs
)
const
{
return
x
<=
rhs
;
}
template
<
typename
T
>
bool
operator
>=
(
T
rhs
)
const
{
return
x
>=
rhs
;
}
operator
int
()
const
{
return
x
;
}
};
class
CFGBlock
{
class
CFGBlock
{
public:
public:
CFG
*
cfg
;
CFG
*
cfg
;
...
@@ -85,8 +105,8 @@ public:
...
@@ -85,8 +105,8 @@ public:
// llvm jit : [user visible]
// llvm jit : [user visible]
class
VRegInfo
{
class
VRegInfo
{
private:
private:
llvm
::
DenseMap
<
InternedString
,
int
>
sym_vreg_map_user_visible
;
llvm
::
DenseMap
<
InternedString
,
DefaultedInt
<-
1
>
>
sym_vreg_map_user_visible
;
llvm
::
DenseMap
<
InternedString
,
int
>
sym_vreg_map
;
llvm
::
DenseMap
<
InternedString
,
DefaultedInt
<-
1
>
>
sym_vreg_map
;
// Reverse map, from vreg->symbol name.
// Reverse map, from vreg->symbol name.
std
::
vector
<
InternedString
>
vreg_sym_map
;
std
::
vector
<
InternedString
>
vreg_sym_map
;
...
@@ -97,8 +117,10 @@ private:
...
@@ -97,8 +117,10 @@ private:
public:
public:
// map of all assigned names. if the name is block local the vreg number is not unique because this vregs get reused
// map of all assigned names. if the name is block local the vreg number is not unique because this vregs get reused
// between blocks.
// between blocks.
const
llvm
::
DenseMap
<
InternedString
,
int
>&
getSymVRegMap
()
{
return
sym_vreg_map
;
}
const
llvm
::
DenseMap
<
InternedString
,
DefaultedInt
<-
1
>>&
getSymVRegMap
()
{
return
sym_vreg_map
;
}
const
llvm
::
DenseMap
<
InternedString
,
int
>&
getUserVisibleSymVRegMap
()
{
return
sym_vreg_map_user_visible
;
}
const
llvm
::
DenseMap
<
InternedString
,
DefaultedInt
<-
1
>>&
getUserVisibleSymVRegMap
()
{
return
sym_vreg_map_user_visible
;
}
int
getVReg
(
InternedString
name
)
const
{
int
getVReg
(
InternedString
name
)
const
{
assert
(
hasVRegsAssigned
());
assert
(
hasVRegsAssigned
());
...
...
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