def isolate_phi_nodes_block(self): """ Init structures and virtually insert parallel copy before/after each phi node """ ircfg = self.ssa.graph for irblock in viewvalues(ircfg.blocks): if not irblock_has_phi(irblock): continue for dst, sources in viewitems(irblock[0]): assert sources.is_op('Phi') new_var = self.create_copy_var(dst) self.phi_new_var[dst] = new_var var_to_parents = get_phi_sources_parent_block( self.ssa.graph, irblock.loc_key, sources.args) for src in sources.args: parents = var_to_parents[src] self.new_var_to_srcs_parents.setdefault( new_var, set()).update(parents) for parent in parents: self.phi_parent_sources.setdefault(dst, set()).add( (parent, src)) self.phi_destinations[irblock.loc_key] = set(irblock[0])
def aggressive_coalesce_block(self): """Try to coalesce phi var with their pre/post variables""" ircfg = self.ssa.graph # Run coalesce on the post phi parallel copy for irblock in viewvalues(ircfg.blocks): if not irblock_has_phi(irblock): continue parallel_copies = {} for dst in self.phi_destinations[irblock.loc_key]: parallel_copies[dst] = self.phi_new_var[dst] self.aggressive_coalesce_parallel_copy(parallel_copies, None) # Run coalesce on the pre phi parallel copy # Stand for the virtual parallel copies at the end of Phi's block # parents parent_to_parallel_copies = {} for dst in irblock[0]: new_var = self.phi_new_var[dst] for parent, src in self.phi_parent_sources[dst]: parent_to_parallel_copies.setdefault(parent, {})[new_var] = src for parent, parallel_copies in viewitems( parent_to_parallel_copies): self.aggressive_coalesce_parallel_copy(parallel_copies, parent)
def aggressive_coalesce_block(self): """Try to coalesce phi var with their pre/post variables""" ircfg = self.ssa.graph # Run coalesce on the post phi parallel copy for irblock in viewvalues(ircfg.blocks): if not irblock_has_phi(irblock): continue parallel_copies = {} for dst in self.phi_destinations[irblock.loc_key]: parallel_copies[dst] = self.phi_new_var[dst] self.aggressive_coalesce_parallel_copy(parallel_copies, None) # Run coalesce on the pre phi parallel copy # Stand for the virtual parallel copies at the end of Phi's block # parents parent_to_parallel_copies = {} for dst in irblock[0]: new_var = self.phi_new_var[dst] for parent, src in self.phi_parent_sources[dst]: parent_to_parallel_copies.setdefault(parent, {})[new_var] = src for parent, parallel_copies in viewitems(parent_to_parallel_copies): self.aggressive_coalesce_parallel_copy(parallel_copies, parent)
def isolate_phi_nodes_block(self): """ Init structures and virtually insert parallel copy before/after each phi node """ ircfg = self.ssa.graph for irblock in viewvalues(ircfg.blocks): if not irblock_has_phi(irblock): continue for dst, sources in viewitems(irblock[0]): assert sources.is_op('Phi') new_var = self.create_copy_var(dst) self.phi_new_var[dst] = new_var var_to_parents = get_phi_sources_parent_block( self.ssa.graph, irblock.loc_key, sources.args ) for src in sources.args: parents = var_to_parents[src] self.new_var_to_srcs_parents.setdefault(new_var, set()).update(parents) for parent in parents: self.phi_parent_sources.setdefault(dst, set()).add((parent, src)) self.phi_destinations[irblock.loc_key] = set(irblock[0])
def order_ssa_var_dom(self): """Compute dominance order of each ssa variable""" ircfg = self.ssa.graph # compute dominator tree dominator_tree = ircfg.compute_dominator_tree(self.head) # variable -> Varinfo self.var_to_varinfo = {} # live_index can later be used to compare dominance of AssignBlocks live_index = 0 # walk in DFS over the dominator tree for loc_key in dominator_tree.walk_depth_first_forward(self.head): irblock = ircfg.blocks.get(loc_key, None) if irblock is None: continue # Create live index for phi new vars # They do not exist in the graph yet, so index is set to None if irblock_has_phi(irblock): for dst in irblock[0]: if not dst.is_id(): continue new_var = self.phi_new_var[dst] self.var_to_varinfo[new_var] = Varinfo( live_index, loc_key, None) live_index += 1 # Create live index for remaining assignments for index, assignblk in enumerate(irblock): used = False for dst in assignblk: if not dst.is_id(): continue if dst in self.ssa.immutable_ids: # Will not be considered by the current algo, ignore it # (for instance, IRDst) continue assert dst not in self.var_to_varinfo self.var_to_varinfo[dst] = Varinfo(live_index, loc_key, index) used = True if used: live_index += 1
def order_ssa_var_dom(self): """Compute dominance order of each ssa variable""" ircfg = self.ssa.graph # compute dominator tree dominator_tree = ircfg.compute_dominator_tree(self.head) # variable -> Varinfo self.var_to_varinfo = {} # live_index can later be used to compare dominance of AssignBlocks live_index = 0 # walk in DFS over the dominator tree for loc_key in dominator_tree.walk_depth_first_forward(self.head): irblock = ircfg.blocks[loc_key] # Create live index for phi new vars # They do not exist in the graph yet, so index is set to None if irblock_has_phi(irblock): for dst in irblock[0]: if not dst.is_id(): continue new_var = self.phi_new_var[dst] self.var_to_varinfo[new_var] = Varinfo(live_index, loc_key, None) live_index += 1 # Create live index for remaining assignments for index, assignblk in enumerate(irblock): used = False for dst in assignblk: if not dst.is_id(): continue if dst in self.ssa.immutable_ids: # Will not be considered by the current algo, ignore it # (for instance, IRDst) continue assert dst not in self.var_to_varinfo self.var_to_varinfo[dst] = Varinfo(live_index, loc_key, index) used = True if used: live_index += 1
def insert_parallel_copy(self): """ Naive Out-of-SSA from CSSA (without coalescing for now) - Replace Phi - Create room for parallel copies in Phi's parents """ ircfg = self.ssa.graph for irblock in list(viewvalues(ircfg.blocks)): if not irblock_has_phi(irblock): continue # Replace Phi with Phi's dst = new_var parallel_copies = {} for dst in self.phi_destinations[irblock.loc_key]: new_var = self.phi_new_var[dst] parallel_copies[dst] = new_var assignblks = list(irblock) assignblks[0] = AssignBlock(parallel_copies, irblock[0].instr) new_irblock = IRBlock(irblock.loc_db, irblock.loc_key, assignblks) ircfg.blocks[irblock.loc_key] = new_irblock # Insert new_var = src in each Phi's parent, at the end of the block parent_to_parallel_copies = {} parallel_copies = {} for dst in irblock[0]: new_var = self.phi_new_var[dst] for parent, src in self.phi_parent_sources[dst]: parent_to_parallel_copies.setdefault(parent, {})[new_var] = src for parent, parallel_copies in viewitems( parent_to_parallel_copies): parent = ircfg.blocks[parent] assignblks = list(parent) assignblks.append( AssignBlock(parallel_copies, parent[-1].instr)) new_irblock = IRBlock(parent.loc_db, parent.loc_key, assignblks) ircfg.blocks[parent.loc_key] = new_irblock
def insert_parallel_copy(self): """ Naive Out-of-SSA from CSSA (without coalescing for now) - Replace Phi - Create room for parallel copies in Phi's parents """ ircfg = self.ssa.graph for irblock in list(viewvalues(ircfg.blocks)): if not irblock_has_phi(irblock): continue # Replace Phi with Phi's dst = new_var parallel_copies = {} for dst in self.phi_destinations[irblock.loc_key]: new_var = self.phi_new_var[dst] parallel_copies[dst] = new_var assignblks = list(irblock) assignblks[0] = AssignBlock(parallel_copies, irblock[0].instr) new_irblock = IRBlock(irblock.loc_key, assignblks) ircfg.blocks[irblock.loc_key] = new_irblock # Insert new_var = src in each Phi's parent, at the end of the block parent_to_parallel_copies = {} parallel_copies = {} for dst in irblock[0]: new_var = self.phi_new_var[dst] for parent, src in self.phi_parent_sources[dst]: parent_to_parallel_copies.setdefault(parent, {})[new_var] = src for parent, parallel_copies in viewitems(parent_to_parallel_copies): parent = ircfg.blocks[parent] assignblks = list(parent) assignblks.append(AssignBlock(parallel_copies, parent[-1].instr)) new_irblock = IRBlock(parent.loc_key, assignblks) ircfg.blocks[parent.loc_key] = new_irblock