Пример #1
0
  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
Пример #2
0
  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
Пример #3
0
 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 
Пример #4
0
 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 
Пример #5
0
 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)
Пример #6
0
 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)
Пример #7
0
  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)
Пример #8
0
  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)
Пример #9
0
  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
Пример #10
0
  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)
Пример #11
0
 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