Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
6a4033c
Better Add Loop Type unrolling
startwarfields Jun 25, 2019
e5e74ee
Better handling of relops for single add use case
startwarfields Jun 25, 2019
4f26a7d
Added simple multiple loop unroll.
startwarfields Jun 25, 2019
c1cdd50
Refactored Execute Phase of Loop Unrolling, Next Steps: Cleaner Ident…
startwarfields Jun 26, 2019
122a7fd
Induction Method added to determine if loop is finite
startwarfields Jun 26, 2019
9fe77d7
Loop Unroll correctly resets the instructions of an unrollable loop
startwarfields Jun 26, 2019
cdd9b3a
Bad Loops and Unrollable Loops both handled correctly, small optimiza…
startwarfields Jun 26, 2019
dc7db84
Conditionals Work Correctly, however nested conditionals imply a cont…
startwarfields Jun 26, 2019
f9af31e
Added Crash Prevention for Nested While Loops. Nested Loops do not un…
startwarfields Jun 26, 2019
38ef344
Pre-Demo Milestone 1 Commit
startwarfields Jun 26, 2019
eb6e9f0
Planning Steps for Upgrading Identify stage to correctly identify all…
startwarfields Jul 1, 2019
b7ca83c
Fixed Flow from Header to body in unrolled loops in the clean-up stage
startwarfields Jul 3, 2019
16e4887
Loop Identification via dominators completed. Nested While Loops Work…
startwarfields Jul 3, 2019
59177cf
Minor Edits. Removed Herobrine
startwarfields Jul 3, 2019
9fc57b6
Fixed While Loop Labels, Updated Loop Unrolling
startwarfields Jul 8, 2019
8acfa61
Fixed Nested Loop Multipliers
startwarfields Jul 8, 2019
715761c
Refactored Jump handling in loops
startwarfields Jul 8, 2019
5982ed9
Pre-Pull Request Code Cleanup
startwarfields Jul 8, 2019
2cd0163
Revert exp2 change in visit_while
startwarfields Jul 8, 2019
e66f951
Basic Hardcoded Loop Unrollling DONE. Split Edges changed return pass…
startwarfields Jun 18, 2019
d14ed57
Loop Unroll Improvements: Jump, Label
startwarfields Jun 18, 2019
0e8589c
CHECKPOINT: Basic Loop Unravel Complete. Next Step: Edge Cases, refactor
startwarfields Jun 18, 2019
1bbc161
Add and Subtract Unrolls working. Jump, Label, Binary OP detection wo…
startwarfields Jun 19, 2019
6d73552
Pre-Number Promotion final loop unroll
startwarfields Jun 19, 2019
5b4c29c
Final Pre-Math Implementation
startwarfields Jun 20, 2019
bdd1f8f
Unnested Loop unrolling partially working
startwarfields Jun 21, 2019
5b4cd07
Better Loop Algorithm. Using Simple_Cycles to correctly attempt each …
startwarfields Jun 24, 2019
b72ead0
Better Add Loop Type unrolling
startwarfields Jun 25, 2019
7707a48
Better handling of relops for single add use case
startwarfields Jun 25, 2019
d78194b
Added simple multiple loop unroll.
startwarfields Jun 25, 2019
c5ba18e
Refactored Execute Phase of Loop Unrolling, Next Steps: Cleaner Ident…
startwarfields Jun 26, 2019
cb45a54
Induction Method added to determine if loop is finite
startwarfields Jun 26, 2019
51a9ff1
Loop Unroll correctly resets the instructions of an unrollable loop
startwarfields Jun 26, 2019
8f8a0e2
Bad Loops and Unrollable Loops both handled correctly, small optimiza…
startwarfields Jun 26, 2019
2eabc32
Conditionals Work Correctly, however nested conditionals imply a cont…
startwarfields Jun 26, 2019
ef68fca
Added Crash Prevention for Nested While Loops. Nested Loops do not un…
startwarfields Jun 26, 2019
df45fc3
Pre-Demo Milestone 1 Commit
startwarfields Jun 26, 2019
93f7f76
Planning Steps for Upgrading Identify stage to correctly identify all…
startwarfields Jul 1, 2019
74198c1
Fixed Flow from Header to body in unrolled loops in the clean-up stage
startwarfields Jul 3, 2019
8fab505
Loop Identification via dominators completed. Nested While Loops Work…
startwarfields Jul 3, 2019
03e0605
Minor Edits. Removed Herobrine
startwarfields Jul 3, 2019
79b4e00
Fixed While Loop Labels, Updated Loop Unrolling
startwarfields Jul 8, 2019
14ae210
Fixed Nested Loop Multipliers
startwarfields Jul 8, 2019
1af7027
Refactored Jump handling in loops
startwarfields Jul 8, 2019
dce5272
Pre-Pull Request Code Cleanup
startwarfields Jul 8, 2019
5598821
Revert exp2 change in visit_while
startwarfields Jul 8, 2019
3ab8020
Merge branch 'startwarfields/loop_unrolling' of https://github.com/li…
startwarfields Jul 11, 2019
5bc3f39
Fixed Merge Conflict with ir_visitor.p
startwarfields Jul 11, 2019
dcaed8a
Confirming Muffin Man Contact
startwarfields Jul 12, 2019
aac4705
Testing mfsim reimplementation
startwarfields Jul 12, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/passes/pass_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from compiler.passes.analyses.call_graph import CallGraph
from compiler.passes.analyses.def_use import DefUseChains
from compiler.passes.transforms.inline import Inline
from compiler.passes.transforms.loop_unroll import LoopUnroll
from compiler.passes.transforms.split_edges import SplitEdges
from compiler.passes.transforms.ssa import SSA
from shared.bs_exceptions import UnInitializedError
Expand Down Expand Up @@ -39,8 +40,6 @@ def run_transformations(self):
# TODO: This should be handled through decorator.
# TODO: Make this handle dependencies correctly.
for key, value in self.transforms.items():
if key is 'loop_unroll' and not self.config.loopunroll:
continue
self.program = value.transform(self.program)

def run_analysis(self):
Expand All @@ -60,4 +59,5 @@ def init_transforms(self):
if self.config.inline:
self.transforms['inline'] = Inline()
self.transforms['split_edges'] = SplitEdges()
self.transforms['loop_unroll'] = LoopUnroll()
self.dependencies['transforms'].add_node('split_edges')
167 changes: 167 additions & 0 deletions compiler/passes/transforms/loop_unroll.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
from compiler.data_structures import *
from compiler.data_structures.program import Program
from compiler.passes.transforms.bs_transform import BSTransform
import networkx as nx
import copy



class LoopUnroll(BSTransform):

def __init__(self):
super().__init__("LoopUnravel")
self.log.warn("Starting Loop Unrolling.....")

def loop_condition(self, RelOp, left, right):
if RelOp == RelationalOps.EQUALITY:
return True if left == right else False
elif RelOp == RelationalOps.NE:
return True if left != right else False
elif RelOp == RelationalOps.LT:
return True if left < right else False
elif RelOp == RelationalOps.LTE:
return True if left <= right else False
elif RelOp == RelationalOps.GT:
return True if left > right else False
elif RelOp == RelationalOps.GTE:
return True if left >= right else False
else:
return False

def reevaluate(self, BinOp: BinaryOp, left, right):
if BinOp.op == BinaryOps.SUBTRACT:
left = left - right
elif BinOp.op == BinaryOps.ADD:
left = left + right
elif BinOp.op == BinaryOps.MULTIPLE:
left = left * right
elif BinOp.op == BinaryOps.DIVIDE:
left = left / right
elif BinOp.op == BinaryOps.AND:
left = left & right
elif BinOp.op == BinaryOps.OR:
left = left | right
return left

def finite_loop(self, bin_op, left: int, modifier: int, right: int, inductive_step=True):
left_modified = self.reevaluate(bin_op, left, modifier)
left_modified_right_delta = left_modified - right
left_right_delta = left - right
lmrd_lrd_delta = left_right_delta - left_modified_right_delta
if inductive_step: i_step = self.finite_loop(bin_op, left_modified, modifier, right, False)
else: i_step = True

return True if abs(lmrd_lrd_delta) > 0 and i_step else False

def unroll(self, program: Program) -> Program:
global jump_from_loop_body
for root in program.functions:
self.log.warn("Test")
loop_list = []
dominators = (nx.immediate_dominators(program.functions[root]['graph'],1))
sorted_doms = sorted(dominators.items())
for loop in dominators:
edge_list = list(program.functions[root]['graph'].out_edges(loop))
if len(edge_list) > 0:
for edge in edge_list:
if edge in sorted_doms:
loop_list.append(edge)

for loop in loop_list:
if len(loop) > 2:
continue
loop_body = loop[0]
head = loop[1]

pure_child_ins = copy.deepcopy(program.functions[root]['blocks'][loop_body].instructions)
pure_parent_ins = copy.deepcopy(program.functions[root]['blocks'][head].instructions)
c_label = program.functions[root]['blocks'][loop_body].label

label = None
binary_operation = None
jump_from_loop_body = None
labels = []
# IDENTIFY
nested_multiplier = 0
# Head Instructions
l_left = l_right = None
for p_instructions in program.functions[root]['blocks'][head].instructions:
if type(p_instructions) == Conditional:
if c_label.label == p_instructions.true_branch.label:
label = program.functions[root]['blocks'][head].instructions.pop(
program.functions[root]['blocks'][head].instructions.index(p_instructions))
nested_multiplier +=1
labels.append(label)
l_left = label.left

l_right = label.right

else:
pass
bad_loop = True

if program.functions[root]['blocks'][loop_body].instructions[-1] == Jump:
jump_from_loop_body = program.functions[root]['blocks'][loop_body].instructions.pop(-1)
else:
jump_from_loop_body = None
for c_instructions in program.functions[root]['blocks'][loop_body].instructions:
if type(c_instructions) == BinaryOp:
binary_operation = c_instructions
if l_left != None and binary_operation.defs.name[:-1] == l_left.name:
program.functions[root]['blocks'][loop_body].instructions.pop(program.functions[root]['blocks'][loop_body].instructions.index(c_instructions))
bad_loop = False
elif l_right != None and binary_operation.defs.name[:-1] == l_right.name:
program.functions[root]['blocks'][loop_body].instructions.pop(program.functions[root]['blocks'][loop_body].instructions.index(c_instructions))
bad_loop = False
else:
pass
if label is None or binary_operation is None:
bad_loop = True

# EXECUTE
# TODO: Refactor when Numbers are fixed
is_finite = False
if bad_loop is False:
constant = 1

base_instructions_unf = program.functions[root]['blocks'][loop_body].instructions.copy()
base_instructions = list(filter(lambda i : not(type(i) is Jump), base_instructions_unf))
program.functions[root]['blocks'][loop_body].instructions = base_instructions.copy()
is_finite = self.finite_loop(binary_operation, constant, int(binary_operation.right),
label.right.value)
if is_finite:
while self.loop_condition(label.relop.value, constant, label.right.value*nested_multiplier):
program.functions[root]['blocks'][loop_body].instructions +=base_instructions
constant = self.reevaluate(binary_operation, constant, int(binary_operation.right))
# CLEANUP: Adds the correct jump paths
if jump_from_loop_body is not None:
jump_from_loop_body.jumps = label.false_branch
program.functions[root]['blocks'][loop_body].instructions.extend(jump_from_loop_body)

jump_from_head = Jump(label.true_branch)
program.functions[root]['blocks'][head].instructions.append(jump_from_head)
program.functions[root]['blocks'][loop_body].label = label.true_branch

program.functions[root]['blocks'][loop_body].jumps.pop()
program.functions[root]['blocks'][loop_body].instructions.append(Jump(program.functions[root]['blocks'][loop_body+1].label))
else:
bad_loop = True

if bad_loop:
program.functions[root]['blocks'][head].instructions = pure_parent_ins
program.functions[root]['blocks'][loop_body].instructions = pure_child_ins
self.log.warn("Found Unrollable Loop... resetting instructions..")
for root in program.functions:
for block in program.functions[root]['blocks']:
self.log.warn(program.functions[root]['blocks'][block])
self.log.warn("Loop Unrolling Completed")
return program

# Entry Point
def transform(self, program: Program) -> Program:
for root in program.functions:
for block in program.functions[root]['blocks']:
self.log.warn("I exist! i matter! ")
self.log.warn(program.functions[root]['blocks'][block])
self.log.warn("Loop Unrolling Completed")
return self.unroll(program)
9 changes: 7 additions & 2 deletions compiler/semantics/ir_visitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,10 @@ def visitWhileStatement(self, ctx: BSParser.WhileStatementContext):

# set up true block
true_block = BasicBlock()
true_label = Label("bsbbw_{}_t".format(true_block.nid))

self.graph.add_node(true_block.nid, function=self.scope_stack[-1])
true_label = Label("bsbbw_{}_l".format(true_block.nid))

self.labels[true_label.name] = true_block.nid
true_block.add(true_label)
self.graph.add_node(true_block.nid, function=self.scope_stack[-1])
Expand Down Expand Up @@ -366,7 +369,9 @@ def visitRepeat(self, ctx: BSParser.RepeatContext):

# set up the true block
true_block = BasicBlock()
true_label = Label("bsbbr_{}_t".format(true_block.nid))
self.graph.add_node(true_block.nid, function=self.scope_stack[-1])
true_label = Label("bsbbw_{}_l".format(true_block.nid))

self.labels[true_label.name] = true_block.nid
true_block.add(true_label)
self.graph.add_node(true_block.nid, function=self.scope_stack[-1])
Expand Down