Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
H
Hercules
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
llvm
Hercules
Commits
8fbc8990
Commit
8fbc8990
authored
3 months ago
by
Russel Arbore
Browse files
Options
Downloads
Patches
Plain Diff
More fixes to outline
parent
0012148d
No related branches found
No related tags found
1 merge request
!79
More fixes to outline
Pipeline
#200654
passed
3 months ago
Stage: build
Stage: test
Changes
3
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
hercules_opt/src/outline.rs
+24
-22
24 additions, 22 deletions
hercules_opt/src/outline.rs
hercules_opt/src/pass.rs
+48
-4
48 additions, 4 deletions
hercules_opt/src/pass.rs
hercules_opt/src/utils.rs
+46
-0
46 additions, 0 deletions
hercules_opt/src/utils.rs
with
118 additions
and
26 deletions
hercules_opt/src/outline.rs
+
24
−
22
View file @
8fbc8990
...
...
@@ -228,27 +228,27 @@ pub fn outline(
outlined
.nodes
.push
(
Node
::
Parameter
{
index
});
}
let
convert_id
=
|
old
|
{
if
let
Some
(
new
)
=
old_to_new_id
.get
(
&
old
)
{
// Map a use inside the partition to its new ID in the
// outlined function.
*
new
}
else
if
let
Some
(
idx
)
=
outside_id_to_param_idx
.get
(
&
old
)
{
// Map a data use outside the partition to the ID of the
// corresponding parameter node.
NodeID
::
new
(
idx
+
1
)
}
else
{
// Map a control use outside the partition to the start
// node. This corresponds to the outside predecessors of the
// top node and the use of the old start by constant,
// dynamic constant, parameter, and undef nodes.
NodeID
::
new
(
0
)
}
};
// Add the nodes from the partition.
let
mut
select_top_phi_inputs
=
vec!
[];
for
id
in
partition
.iter
()
{
let
convert_id
=
|
old
|
{
if
let
Some
(
new
)
=
old_to_new_id
.get
(
&
old
)
{
// Map a use inside the partition to its new ID in the
// outlined function.
*
new
}
else
if
let
Some
(
idx
)
=
outside_id_to_param_idx
.get
(
&
old
)
{
// Map a data use outside the partition to the ID of the
// corresponding parameter node.
NodeID
::
new
(
idx
+
1
)
}
else
{
// Map a control use outside the partition to the start
// node. This corresponds to the outside predecessors of the
// top node and the use of the old start by constant,
// dynamic constant, parameter, and undef nodes.
NodeID
::
new
(
0
)
}
};
let
mut
node
=
edit
.get_node
(
*
id
)
.clone
();
if
let
Node
::
Phi
{
control
,
data
}
=
&
mut
node
&&
*
control
==
top_node
...
...
@@ -372,7 +372,7 @@ pub fn outline(
if
dom_return_values
.contains
(
inside_id
)
{
// If this outside used value dominates this return,
// then return the value itself.
*
inside_id
convert_id
(
*
inside_id
)
}
else
{
// If not, then return an Undef. Since this value
// doesn't dominate this return, it can't be used on
...
...
@@ -408,7 +408,7 @@ pub fn outline(
// Return the return product.
outlined
.nodes
.push
(
Node
::
Return
{
control
:
*
exit
,
control
:
convert_id
(
*
exit
)
,
data
:
construct_id
,
});
}
...
...
@@ -558,7 +558,7 @@ pub fn outline(
}
/*
* Just outlines all of a function
ac
cept the entry and return. Minimum work
* Just outlines all of a function
ex
cept the entry and return. Minimum work
* needed to cause runtime Rust code to be generated as necessary.
*/
pub
fn
dumb_outline
(
...
...
@@ -568,7 +568,9 @@ pub fn dumb_outline(
dom
:
&
DomTree
,
to_be_function_id
:
FunctionID
,
)
->
Option
<
Function
>
{
collapse_returns
(
editor
);
if
!
contains_between_control_flow
(
editor
.func
())
{
return
None
;
}
let
partition
=
editor
.node_ids
()
.filter
(|
id
|
{
...
...
This diff is collapsed.
Click to expand it.
hercules_opt/src/pass.rs
+
48
−
4
View file @
8fbc8990
...
...
@@ -659,6 +659,39 @@ impl PassManager {
self
.clear_analyses
();
}
Pass
::
Outline
=>
{
self
.make_def_uses
();
let
def_uses
=
self
.def_uses
.as_ref
()
.unwrap
();
let
constants_ref
=
RefCell
::
new
(
std
::
mem
::
take
(
&
mut
self
.module.constants
));
let
dynamic_constants_ref
=
RefCell
::
new
(
std
::
mem
::
take
(
&
mut
self
.module.dynamic_constants
));
let
types_ref
=
RefCell
::
new
(
std
::
mem
::
take
(
&
mut
self
.module.types
));
let
old_num_funcs
=
self
.module.functions
.len
();
let
mut
editors
:
Vec
<
_
>
=
zip
(
self
.module.functions
.iter_mut
(),
def_uses
.iter
())
.map
(|(
func
,
def_use
)|
{
FunctionEditor
::
new
(
func
,
&
constants_ref
,
&
dynamic_constants_ref
,
&
types_ref
,
def_use
,
)
})
.collect
();
for
editor
in
editors
.iter_mut
()
{
collapse_returns
(
editor
);
ensure_between_control_flow
(
editor
);
}
let
mut
edits
:
Vec
<
_
>
=
editors
.into_iter
()
.enumerate
()
.map
(|(
idx
,
editor
)|
(
idx
,
editor
.edits
()))
.collect
();
self
.module.constants
=
constants_ref
.take
();
self
.module.dynamic_constants
=
dynamic_constants_ref
.take
();
self
.module.types
=
types_ref
.take
();
self
.clear_analyses
();
self
.make_def_uses
();
self
.make_typing
();
self
.make_control_subgraphs
();
...
...
@@ -671,7 +704,6 @@ impl PassManager {
let
dynamic_constants_ref
=
RefCell
::
new
(
std
::
mem
::
take
(
&
mut
self
.module.dynamic_constants
));
let
types_ref
=
RefCell
::
new
(
std
::
mem
::
take
(
&
mut
self
.module.types
));
let
old_num_funcs
=
self
.module.functions
.len
();
let
mut
editors
:
Vec
<
_
>
=
zip
(
self
.module.functions
.iter_mut
(),
def_uses
.iter
())
.map
(|(
func
,
def_use
)|
{
...
...
@@ -701,11 +733,23 @@ impl PassManager {
self
.module.constants
=
constants_ref
.take
();
self
.module.dynamic_constants
=
dynamic_constants_ref
.take
();
self
.module.types
=
types_ref
.take
();
let
edits
:
Vec
<
_
>
=
editors
.into_iter
()
.map
(|
editor
|
editor
.edits
())
.collect
();
for
idx
in
0
..
edits
.len
()
{
edits
.extend
(
editors
.into_iter
()
.enumerate
()
.map
(|(
idx
,
editor
)|
(
idx
,
editor
.edits
())),
);
for
(
func_idx
,
edit
)
in
edits
{
if
let
Some
(
plans
)
=
self
.plans
.as_mut
()
{
repair_plan
(
&
mut
plans
[
idx
],
&
self
.module.functions
[
idx
],
&
edits
[
idx
]);
repair_plan
(
&
mut
plans
[
func_idx
],
&
self
.module.functions
[
func_idx
],
&
edit
,
);
}
}
for
idx
in
0
..
self
.module.functions
.len
()
{
let
grave_mapping
=
self
.module.functions
[
idx
]
.delete_gravestones
();
if
let
Some
(
plans
)
=
self
.plans
.as_mut
()
{
plans
[
idx
]
.fix_gravestones
(
&
grave_mapping
);
...
...
This diff is collapsed.
Click to expand it.
hercules_opt/src/utils.rs
+
46
−
0
View file @
8fbc8990
...
...
@@ -264,3 +264,49 @@ pub fn collapse_returns(editor: &mut FunctionEditor) -> Option<NodeID> {
});
new_return
}
pub
fn
contains_between_control_flow
(
func
:
&
Function
)
->
bool
{
let
num_control
=
func
.nodes
.iter
()
.filter
(|
node
|
node
.is_control
())
.count
();
assert!
(
num_control
>=
2
,
"PANIC: A Hercules function must have at least two control nodes: a start node and at least one return node."
);
num_control
>
2
}
/*
* Top level function to ensure a Hercules function contains at least one
* control node that isn't the start or return nodes.
*/
pub
fn
ensure_between_control_flow
(
editor
:
&
mut
FunctionEditor
)
->
Option
<
NodeID
>
{
if
!
contains_between_control_flow
(
editor
.func
())
{
let
ret
=
editor
.node_ids
()
.skip
(
1
)
.filter
(|
id
|
editor
.func
()
.nodes
[
id
.idx
()]
.is_control
())
.next
()
.unwrap
();
let
Node
::
Return
{
control
,
data
}
=
editor
.func
()
.nodes
[
ret
.idx
()]
else
{
panic!
(
"PANIC: A Hercules function with only two control nodes must have a return node be the other control node, other than the start node."
)
};
assert_eq!
(
control
,
NodeID
::
new
(
0
),
"PANIC: The only other control node in a Hercules function, the return node, is not using the start node."
);
let
mut
region_id
=
None
;
editor
.edit
(|
mut
edit
|
{
edit
=
edit
.delete_node
(
ret
)
?
;
region_id
=
Some
(
edit
.add_node
(
Node
::
Region
{
preds
:
Box
::
new
([
NodeID
::
new
(
0
)]),
}));
edit
.add_node
(
Node
::
Return
{
control
:
region_id
.unwrap
(),
data
,
});
Ok
(
edit
)
});
region_id
}
else
{
Some
(
editor
.get_users
(
NodeID
::
new
(
0
))
.filter
(|
id
|
editor
.func
()
.nodes
[
id
.idx
()]
.is_control
())
.next
()
.unwrap
(),
)
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment