Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 1496376

Browse files
committed
Sea of nodes optimizations and convenience functions
1 parent b7e0044 commit 1496376

File tree

3 files changed

+90
-13
lines changed

3 files changed

+90
-13
lines changed

lib/syntax_tree/yarv/control_flow_graph.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,10 @@ def to_dfg
203203
DataFlowGraph.compile(self)
204204
end
205205

206+
def to_son
207+
to_dfg.to_son
208+
end
209+
206210
def to_mermaid
207211
output = StringIO.new
208212
output.puts("flowchart TD")

lib/syntax_tree/yarv/instruction_sequence.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,14 @@ def to_cfg
273273
ControlFlowGraph.compile(self)
274274
end
275275

276+
def to_dfg
277+
to_cfg.to_dfg
278+
end
279+
280+
def to_son
281+
to_dfg.to_son
282+
end
283+
276284
def disasm
277285
fmt = Disassembler.new
278286
fmt.enqueue(self)

lib/syntax_tree/yarv/sea_of_nodes.rb

Lines changed: 78 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ def compile
118118

119119
connect_local_graphs_control(local_graphs)
120120
connect_local_graphs_data(local_graphs)
121-
cleanup
121+
cleanup_phi_nodes
122+
cleanup_insn_nodes
122123

123124
SeaOfNodes.new(dfg, nodes, local_graphs).tap(&:verify)
124125
end
@@ -311,23 +312,13 @@ def connect_local_graphs_data(local_graphs)
311312
# We don't always build things in an optimal way. Go back and fix up
312313
# some mess we left. Ideally we wouldn't create these problems in the
313314
# first place.
314-
def cleanup
315+
def cleanup_phi_nodes
315316
nodes.dup.each do |node| # dup because we're mutating
316317
next unless node.is_a?(PhiNode)
317318

318319
if node.inputs.size == 1
319320
# Remove phi nodes with a single input.
320-
node.inputs.each do |producer_edge|
321-
node.outputs.each do |consumer_edge|
322-
connect(
323-
producer_edge.from,
324-
consumer_edge.to,
325-
producer_edge.type,
326-
consumer_edge.label
327-
)
328-
end
329-
end
330-
321+
connect_over(node)
331322
remove(node)
332323
elsif node.inputs.map(&:from).uniq.size == 1
333324
# Remove phi nodes where all inputs are the same.
@@ -344,6 +335,66 @@ def cleanup
344335
end
345336
end
346337

338+
# Eliminate as many unnecessary nodes as we can.
339+
def cleanup_insn_nodes
340+
nodes.dup.each do |node|
341+
next unless node.is_a?(InsnNode)
342+
343+
case node.insn
344+
when AdjustStack
345+
# If there are any inputs to the adjust stack that are immediately
346+
# discarded, we can remove them from the input list.
347+
number = node.insn.number
348+
349+
node.inputs.dup.each do |input_edge|
350+
next if input_edge.type != :data
351+
352+
from = input_edge.from
353+
next unless from.is_a?(InsnNode)
354+
355+
if from.inputs.empty? && from.outputs.size == 1
356+
number -= 1
357+
remove(input_edge.from)
358+
elsif from.insn.is_a?(Dup)
359+
number -= 1
360+
connect_over(from)
361+
remove(from)
362+
363+
new_edge = node.inputs.last
364+
new_edge.from.outputs.delete(new_edge)
365+
node.inputs.delete(new_edge)
366+
end
367+
end
368+
369+
if number == 0
370+
connect_over(node)
371+
remove(node)
372+
else
373+
next_node =
374+
if number == 1
375+
InsnNode.new(Pop.new, node.offset)
376+
else
377+
InsnNode.new(AdjustStack.new(number), node.offset)
378+
end
379+
380+
next_node.inputs.concat(node.inputs)
381+
next_node.outputs.concat(node.outputs)
382+
383+
# Dynamically finding the index of the node in the nodes array
384+
# because we're mutating the array as we go.
385+
nodes[nodes.index(node)] = next_node
386+
end
387+
when Jump
388+
# When you have a jump instruction that only has one input and one
389+
# output, you can just connect over top of it and remove it.
390+
if node.inputs.size == 1 && node.outputs.size == 1
391+
connect_over(node)
392+
remove(node)
393+
end
394+
end
395+
end
396+
end
397+
347398
# Connect one node to another.
348399
def connect(from, to, type, label = nil)
349400
raise if from == to
@@ -354,6 +405,20 @@ def connect(from, to, type, label = nil)
354405
to.inputs << edge
355406
end
356407

408+
# Connect all of the inputs to all of the outputs of a node.
409+
def connect_over(node)
410+
node.inputs.each do |producer_edge|
411+
node.outputs.each do |consumer_edge|
412+
connect(
413+
producer_edge.from,
414+
consumer_edge.to,
415+
producer_edge.type,
416+
consumer_edge.label
417+
)
418+
end
419+
end
420+
end
421+
357422
# Remove a node from the graph.
358423
def remove(node)
359424
node.inputs.each do |producer_edge|

0 commit comments

Comments
 (0)