PageRenderTime 45ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/translator/backendopt/storesink.py

https://bitbucket.org/halgari/pypy
Python | 97 lines | 81 code | 12 blank | 4 comment | 31 complexity | e962101292b6539aeb33c1a425ed6745 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, AGPL-3.0
  1. from rpython.rtyper.lltypesystem.lloperation import llop
  2. from rpython.flowspace.model import mkentrymap, Variable
  3. from rpython.translator.backendopt import removenoops
  4. from rpython.translator import simplify
  5. def has_side_effects(op):
  6. if op.opname == 'debug_assert':
  7. return False
  8. try:
  9. return getattr(llop, op.opname).sideeffects
  10. except AttributeError:
  11. return True
  12. def storesink_graph(graph):
  13. """ remove superfluous getfields. use a super-local method: all non-join
  14. blocks inherit the heap information from their (single) predecessor
  15. """
  16. added_some_same_as = False
  17. entrymap = mkentrymap(graph)
  18. # all merge blocks are starting points
  19. todo = [(block, None, None) for (block, prev_blocks) in entrymap.iteritems()
  20. if len(prev_blocks) > 1 or block is graph.startblock]
  21. visited = 0
  22. while todo:
  23. block, cache, inputlink = todo.pop()
  24. visited += 1
  25. if cache is None:
  26. cache = {}
  27. if block.operations:
  28. changed_block = _storesink_block(block, cache, inputlink)
  29. added_some_same_as = changed_block or added_some_same_as
  30. for link in block.exits:
  31. if len(entrymap[link.target]) == 1:
  32. new_cache = _translate_cache(cache, link)
  33. todo.append((link.target, new_cache, link))
  34. assert visited == len(entrymap)
  35. if added_some_same_as:
  36. removenoops.remove_same_as(graph)
  37. simplify.transform_dead_op_vars(graph)
  38. def _translate_cache(cache, link):
  39. if link.target.operations == (): # exit or except block:
  40. return {}
  41. block = link.target
  42. local_versions = {var1: var2 for var1, var2 in zip(link.args, block.inputargs)}
  43. def _translate_arg(arg):
  44. if isinstance(arg, Variable):
  45. res = local_versions.get(arg, None)
  46. if res is None:
  47. res = Variable(arg)
  48. res.concretetype = arg.concretetype
  49. link.args.append(arg)
  50. block.inputargs.append(res)
  51. local_versions[arg] = res
  52. return res
  53. else:
  54. return arg
  55. new_cache = {}
  56. for (var, field), res in cache.iteritems():
  57. if var in local_versions or not isinstance(var, Variable):
  58. new_cache[_translate_arg(var), field] = _translate_arg(res)
  59. return new_cache
  60. def _storesink_block(block, cache, inputlink):
  61. def clear_cache_for(cache, concretetype, fieldname):
  62. for k in cache.keys():
  63. if k[0].concretetype == concretetype and k[1] == fieldname:
  64. del cache[k]
  65. added_some_same_as = False
  66. for op in block.operations:
  67. if op.opname == 'getfield':
  68. tup = (op.args[0], op.args[1].value)
  69. res = cache.get(tup, None)
  70. if res is not None:
  71. op.opname = 'same_as'
  72. op.args = [res]
  73. added_some_same_as = True
  74. else:
  75. cache[tup] = op.result
  76. elif op.opname in ('setarrayitem', 'setinteriorfield', "malloc", "malloc_varsize"):
  77. pass
  78. elif op.opname == 'setfield':
  79. target = op.args[0]
  80. field = op.args[1].value
  81. clear_cache_for(cache, target.concretetype, field)
  82. cache[target, field] = op.args[2]
  83. elif has_side_effects(op):
  84. cache.clear()
  85. return added_some_same_as