def tag_com_overhead_instr(self, instr): tag_instr(instr, "communication overhead")
def process_window(self, trace_fragment): ''' Process a trace fragment. ''' # stupid hack to convert between register objects and register strings special_regs = [trace_fragment.code.north, trace_fragment.code.east,\ trace_fragment.code.south, trace_fragment.code.west, trace_fragment.code.out] name2reg = dict((str(x), x) for x in trace_fragment.code.regs + special_regs) # reinsert immediates that were cached in previous fragment # to their original register, all the cached registers that were not # overwritten yet can be found in old_register_rewrite.keys() old_targets = dict((v, k) for k, v in self.old_register_rewrite.iteritems()) immediates_to_restore = [(r, v) for v, r in self.old_cached_coeffs.iteritems() if r in old_targets] for reg, value in immediates_to_restore: orig_reg = old_targets[reg] trace_fragment.insert_instr_before(Imm(orig_reg, value)) # add the loading of the cached values trace_fragment.set_ptr(0) frequent_imm = self._get_frequent_immediates(trace_fragment) nr_free_regs = trace_fragment.nr_free_regs() nr_cached_imm = min(len(frequent_imm), nr_free_regs) cached_coeffs = dict((frequent_imm[i][1], None) for i in xrange(nr_cached_imm)) # mapping from original imm destination regs to new reg in cached_coeffs register_rewrite = {} while trace_fragment.ptr < len(trace_fragment): instr = trace_fragment.current_instr() def_, _ = VariableManager.get_def_use(instr_compact_repr(instr)) if def_: # handle None values def_ = name2reg[def_] # convert to register object if instr.opcode() == 'imm' and not instr.cond(): value = instr.value if value in cached_coeffs: if not cached_coeffs[value]: # XXX could be improved by first finding the first and last usage # and finding the register with the tightest free range fit for this interval reg = trace_fragment.alloc_local_reg() # update book keeping cached_coeffs[value] = reg register_rewrite[instr.dest] = reg # assign new reg # XXX the old register usage could be freed!!! instr.dest = reg else: # update rewrite mapping register_rewrite[instr.dest] = cached_coeffs[value] trace_fragment.remove_current_instr() trace_fragment.dec_ptr() # make sure that next op isn't skipped else: if def_ in register_rewrite: # new definition of register, value of immediate is gone # so mapping is not needed anymore del register_rewrite[def_] else: if def_ in register_rewrite: # new definition of register, value of immediate is gone # so mapping is not needed anymore del register_rewrite[def_] for reg, replacement in register_rewrite.iteritems(): replaced = self._replace_source_reg(instr, reg, replacement) if replaced: value = [k for k, v in cached_coeffs.iteritems() if v == replacement][0] tag_instr(instr, 'cache_use_imm:%s'%str(value)) trace_fragment.inc_ptr() # now determine the release time of all cached variables # note that a second run is needed to get the these line nrs last_cached_usage = dict((k, -1) for k, v in cached_coeffs.iteritems()) for i, instr in enumerate(trace_fragment.trace): cache_use = None if hasattr(instr, 'tag'): try: cache_use = [x.split(':')[1] for x in instr.tag if 'cache_use_imm' in x][0] except (IndexError): pass if cache_use: value = float(cache_use) if value in last_cached_usage: last_cached_usage[value] = i # finally release the variables at the appropriate moment for value, line in last_cached_usage.iteritems(): trace_fragment.set_ptr(line) trace_fragment.release_local_reg(cached_coeffs[value]) self.old_register_rewrite = register_rewrite self.old_cached_coeffs = cached_coeffs return trace_fragment