Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add constant propagation pass.

  • Loading branch information...
commit 432e8c17031221d9bd0bb4b31856aecec2c46190 1 parent 02968b9
@whitequark authored
View
6 lib/furnace-avm2/abc/metadata/method_body_info.rb
@@ -33,11 +33,17 @@ def code_to_cfg(options={})
Furnace::AVM2::Transform::DataflowInvariantCodeMotion.new,
Furnace::AVM2::Transform::PartialEvaluation.new,
Furnace::AVM2::Transform::SSAOptimize.new,
+
+ Furnace::AVM2::Transform::LivenessAnalysis.new,
Furnace::AVM2::Transform::FoldBooleanShortcuts.new,
Furnace::AVM2::Transform::FoldTernaryOperators.new,
Furnace::AVM2::Transform::FoldIncrementDecrement.new,
+ Furnace::AVM2::Transform::SSAOptimize.new,
]),
+ Furnace::AVM2::Transform::LivenessAnalysis.new(idempotent: true),
+ Furnace::AVM2::Transform::PropagateConstants.new,
+
Furnace::AVM2::Transform::UpdateExceptionVariables.new,
Furnace::AVM2::Transform::FoldPassthroughAssignments.new,
])
View
1  lib/furnace-avm2/transform.rb
@@ -13,6 +13,7 @@ module Furnace::AVM2::Transform
require_relative "transform/liveness_analysis"
require_relative "transform/dataflow_invariant_code_motion"
require_relative "transform/partial_evaluation"
+require_relative "transform/propagate_constants"
require_relative "transform/fold_ternary_operators"
require_relative "transform/fold_boolean_shortcuts"
require_relative "transform/fold_passthrough_assignments"
View
6 lib/furnace-avm2/transform/liveness_analysis.rb
@@ -4,6 +4,10 @@ class LivenessAnalysis
# Avoid creating too much literals.
EMPTY_SET = Set[]
+ def initialize(options={})
+ @idempotent = options[:idempotent] || false
+ end
+
def transform(cfg)
dom = cfg.dominators
loops = cfg.identify_loops
@@ -83,7 +87,7 @@ def transform(cfg)
# This transform does not change CFG in any way,
# it just rebuilds the metadata.
- nil
+ cfg if @idempotent
end
end
end
View
29 lib/furnace-avm2/transform/phi_node_reduction.rb
@@ -1,29 +0,0 @@
-module Furnace::AVM2
- module Transform
- module PhiNodeReduction
- def reduce_phi_nodes(cfg, root, target_id, supplementary_id)
- worklist = Set[ root ]
- visited = Set[]
-
- while worklist.any?
- block = worklist.first
- worklist.delete block
- visited.add block
-
- gets = block.metadata.gets_map[target_id]
- gets.each do |get|
- if get.children.include? supplementary_id
- block.metadata.remove_get target_id
- end
- end
-
- block.targets.each do |target|
- if target.metadata.live.include? target_id
- worklist.add target unless visited.include? target
- end
- end
- end
- end
- end
- end
-end
View
20 lib/furnace-avm2/transform/propagate_constants.rb
@@ -4,6 +4,26 @@ class PropagateConstants
include SubgraphOperations
def transform(cfg)
+ changed = false
+
+ evaluator = Evaluator.new
+
+ cfg.nodes.each do |block|
+ block.metadata.sets.each do |id|
+ set = block.metadata.set_map[id]
+ _, set_value = set.children
+
+ # TODO add options for folding complex constants
+ if evaluator.immediate?(set_value)
+ replace_r_nodes(cfg, block, id, set_value)
+ block.metadata.remove_set(id)
+ block.insns.delete set
+
+ changed = true
+ end
+ end
+ end
+
cfg
end
end
View
8 lib/furnace-avm2/transform/subgraph_operations.rb
@@ -1,7 +1,7 @@
module Furnace::AVM2
module Transform
module SubgraphOperations
- def walk_live_nodes(cfg, root)
+ def walk_live_nodes(cfg, root, id)
worklist = Set[ root ]
visited = Set[]
@@ -13,7 +13,7 @@ def walk_live_nodes(cfg, root)
yield block
block.targets.each do |target|
- if target.metadata.live.include? target_id
+ if target.metadata.live.include? id
worklist.add target unless visited.include? target
end
end
@@ -21,7 +21,7 @@ def walk_live_nodes(cfg, root)
end
def reduce_phi_nodes(cfg, root, target_id, supplementary_id)
- walk_live_nodes(cfg, root) do |block|
+ walk_live_nodes(cfg, root, target_id) do |block|
gets = block.metadata.gets_map[target_id]
gets.each do |get|
if get.children.include? supplementary_id
@@ -32,7 +32,7 @@ def reduce_phi_nodes(cfg, root, target_id, supplementary_id)
end
def replace_r_nodes(cfg, root, target_id, replacement)
- walk_live_nodes(cfg, root) do |block|
+ walk_live_nodes(cfg, root, target_id) do |block|
gets = block.metadata.gets_map[target_id]
gets.each do |get|
get.update(replacement.type,
Please sign in to comment.
Something went wrong with that request. Please try again.