def transform_loop_condition(self, expr, outer_block, loop_body, merge): """Normalize loop conditions so they are just simple variables""" if self.is_simple(expr): return self.transform_expr(expr) else: loop_carried_vars = [name for name in collect_var_names(expr) if name in merge] if len(loop_carried_vars) == 0: return expr left_values = [merge[name][0] for name in loop_carried_vars] right_values = [merge[name][1] for name in loop_carried_vars] left_cond = subst.subst_expr(expr, dict(zip(loop_carried_vars, left_values))) if not self.is_simple(left_cond): left_cond = self.temp_in_block(left_cond, outer_block, name = "cond") right_cond = subst.subst_expr(expr, dict(zip(loop_carried_vars, right_values))) if not self.is_simple(right_cond): right_cond = self.temp_in_block(right_cond, loop_body, name = "cond") cond_var = self.fresh_var(left_cond.type, "cond") merge[cond_var.name] = (left_cond, right_cond) return cond_var
def transform_Assign(self, stmt): # pattern match only on statements of the form # dest[complex_indexing] = src # when: # 1) dest hasn't been used before as a value # 2) src doesn't escape # 3) src was locally allocated # ...then transform the code so instead of allocating src if stmt.lhs.__class__ is Index and stmt.lhs.value.__class__ is Var: lhs_name = stmt.lhs.value.name if lhs_name not in self.usedef.first_use and \ lhs_name not in self.may_escape and \ self.no_array_aliases(lhs_name): # why assign to an array if it never gets used? return None elif stmt.lhs.type.__class__ is ArrayT and stmt.rhs.__class__ is Var: curr_path = self.usedef.stmt_paths[id(stmt)] rhs_name = stmt.rhs.name if lhs_name not in self.usedef.first_use or \ self.usedef.first_use[lhs_name] > curr_path: if self.usedef.last_use[rhs_name] == curr_path and \ rhs_name not in self.may_escape and \ rhs_name in self.local_arrays: array_stmt = self.local_arrays[rhs_name] prev_path = self.usedef.stmt_paths[id(array_stmt)] if self.is_array_alloc(array_stmt.rhs) and \ all(self.usedef.created_on[lhs_depends_on] < prev_path for lhs_depends_on in collect_var_names(stmt.lhs)): array_stmt.rhs = stmt.lhs return None return stmt
def visit_Assign(self, stmt): lhs = stmt.lhs rhs = stmt.rhs if lhs.__class__ is Var: lhs_name = stmt.lhs.name rhs_class = rhs.__class__ if rhs_class is Var: linked_set = self.linked_arrays.get(lhs_name, set([lhs_name])) rhs_name = stmt.rhs.name linked_set.add(rhs_name) self.linked_arrays[lhs_name] = linked_set self.linked_arrays[rhs_name] = linked_set if lhs_name in self.array_values: self.array_values[rhs_name] = self.array_values[lhs_name] elif rhs_class is Range: self.array_values[lhs_name] = RangeArray(rhs.start, rhs.step, rhs.type.elt_type) """ elif rhs_class in (ConstArray, ConstArrayLike): self.array_values[lhs_name] = ConstValue(value = rhs.value, type = rhs.type) elif rhs_class is IndexMap: self.array_values[lhs_name] = IndexMapResult(fn = rhs.fn) """ else: # if not a var, might be an index expression for tainted_lhs_name in collect_var_names(lhs): for linked_name in self.linked_arrays.get(tainted_lhs_name, set([tainted_lhs_name])): self.array_values[linked_name] = unknown
def visit_Assign(self, stmt): lhs = stmt.lhs rhs = stmt.rhs if lhs.__class__ is Var: lhs_name = stmt.lhs.name rhs_class = rhs.__class__ if rhs_class is Var: linked_set = self.linked_arrays.get(lhs_name, set([lhs_name])) rhs_name = stmt.rhs.name linked_set.add(rhs_name) self.linked_arrays[lhs_name] = linked_set self.linked_arrays[rhs_name] = linked_set if lhs_name in self.array_values: self.array_values[rhs_name] = self.array_values[lhs_name] elif rhs_class is Range: self.array_values[lhs_name] = RangeArray(rhs.start, rhs.step, rhs.type.elt_type) elif rhs_class in (ConstArray, ConstArrayLike): self.array_values[lhs_name] = ConstValue(value = rhs.value, type = rhs.type) elif rhs_class is IndexMap: self.array_values[lhs_name] = IndexMapResult(fn = rhs.fn) else: # if not a var, might be an index expression for tainted_lhs_name in collect_var_names(lhs): for linked_name in self.linked_arrays.get(tainted_lhs_name, set([tainted_lhs_name])): self.array_values[linked_name] = unknown
def visit_Assign(self, stmt): if stmt.lhs.__class__ is Tuple: for elt in stmt.lhs.elts: self.visit_Assign(elt) elif stmt.lhs.__class__ is Index: for name in collect_var_names(stmt.lhs.value): self.writes.append(name) for alias_name in self.may_alias[name]: self.writes.append(alias_name)
def visit_Assign(self, stmt): consumes, reads = self.visit_expr(stmt.rhs) _, writes = self.visit_expr(stmt.lhs) for write_expr_set in writes.itervalues(): for write_expr in write_expr_set: consumes.update(collect_var_names(write_expr)) produces = collect_binding_names(stmt.lhs) return StmtNode(stmt, consumes, produces, reads, writes)
def collect_loop_vars(self, loop_vars, loop_body): """Gather the variables whose values change between loop iterations""" for stmt in loop_body: assert stmt.__class__ not in (ForLoop, While, Return) if stmt.__class__ is Assign: lhs_names = collect_binding_names(stmt.lhs) rhs_names = collect_var_names(stmt.rhs) if any(name in loop_vars for name in rhs_names): loop_vars.update(lhs_names)
def transform_Assign(self, stmt): # pattern match only on statements of the form # dest[complex_indexing] = src # when: # 1) dest hasn't been used before as a value # 2) src doesn't escape # 3) src was locally allocated # ...then transform the code so instead of allocating src if stmt.lhs.__class__ is Index and stmt.lhs.value.__class__ is Var: lhs_name = stmt.lhs.value.name if lhs_name not in self.usedef.first_use and \ lhs_name not in self.may_escape and \ self.no_array_aliases(lhs_name): # why assign to an array if it never gets used? return None elif stmt.lhs.type.__class__ is ArrayT and stmt.rhs.__class__ is Var: curr_path = self.usedef.stmt_paths[id(stmt)] rhs_name = stmt.rhs.name if lhs_name not in self.usedef.first_use or \ self.usedef.first_use[lhs_name] > curr_path: if self.usedef.last_use[rhs_name] == curr_path and \ rhs_name not in self.may_escape and \ rhs_name in self.local_arrays: array_stmt = self.local_arrays[rhs_name] prev_path = self.usedef.stmt_paths[id(array_stmt)] if array_stmt.rhs.__class__ in array_constructors and \ all(self.usedef.created_on[lhs_depends_on] < prev_path for lhs_depends_on in collect_var_names(stmt.lhs)): array_stmt.rhs = stmt.lhs return None """ elif stmt.lhs.__class__ is Var and stmt.rhs.__class__ is Alloc: lhs_name = stmt.lhs.name curr_path = self.usedef.stmt_number[id(stmt)] print stmt for prev_name in self.pointers_by_size.get(stmt.rhs.count, []): if self.type_env[prev_name] == self.type_env[lhs_name] and \ prev_name in self.local_alloc and \ lhs_name in self.local_alloc and \ self.usedef.last_use[prev_name] < curr_stmt_number: stmt.rhs = Var(prev_name, type = self.type_env[prev_name]) self.usedef.last_use[prev_name] = curr_stmt_number return stmt if lhs_name not in self.may_escape and \ len(self.may_alias.get(lhs_name, [])) <= 1: alloc_set = self.pointers_by_size.setdefault(stmt.rhs.count, set([])) alloc_set.add(lhs_name) """ return stmt
def visit_Assign(self, stmt): lhs_names = collect_binding_names(stmt.lhs) rhs_names = collect_var_names(stmt.rhs) for x in lhs_names: dependencies = self.depends_on.get(x, set([])) dependencies.update(rhs_names) self.depends_on[x] = dependencies if any(x in self.volatile_vars for x in rhs_names): self.volatile_vars.update(lhs_names) elif self.is_mutable_alloc(stmt.rhs): if len(lhs_names) == 1 and \ len(self.may_alias.get(lhs_names[0], [])) <= 1: pass else: self.volatile_vars.update(lhs_names) # mark any array writes as volatile if stmt.lhs.__class__ is Index: assert stmt.lhs.value.__class__ is Var self.volatile_vars.add(stmt.lhs.value.name)
def visit_Assign(self, stmt): lhs = stmt.lhs rhs = stmt.rhs if lhs.__class__ is Var: lhs_name = stmt.lhs.name rhs_class = rhs.__class__ if rhs_class is Var: linked_set = self.linked_arrays.get(lhs_name, set([lhs_name])) rhs_name = stmt.rhs.name linked_set.add(rhs_name) self.linked_arrays[lhs_name] = linked_set self.linked_arrays[rhs_name] = linked_set if lhs_name in self.array_values: self.array_values[rhs_name] = self.array_values[lhs_name] elif rhs_class is Range: v = RangeArray(rhs.start, rhs.step, rhs.type.elt_type) self.array_values[lhs_name] = v else: # if not a var, might be an index expression for tainted_lhs_name in collect_vars.collect_var_names(lhs): for linked_name in self.linked_arrays.get(tainted_lhs_name, set([tainted_lhs_name])): self.array_values[linked_name] = unknown