optdeadstore.pas 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. {
  2. Dead store elimination
  3. Copyright (c) 2005-2012 by Jeppe Johansen and Florian Klaempfl
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit optdeadstore;
  18. {$i fpcdefs.inc}
  19. { $define DEBUG_DEADSTORE}
  20. { $define EXTDEBUG_DEADSTORE}
  21. interface
  22. uses
  23. node;
  24. function do_optdeadstoreelim(var rootnode : tnode) : tnode;
  25. implementation
  26. uses
  27. verbose,globtype,globals,
  28. procinfo,pass_1,
  29. nutils,
  30. nbas,nld,
  31. optbase,
  32. symsym,symconst;
  33. function deadstoreelim(var n: tnode; arg: pointer): foreachnoderesult;
  34. var
  35. a: tassignmentnode;
  36. redundant: boolean;
  37. begin
  38. result:=fen_true;
  39. if (n.nodetype=statementn) and
  40. assigned(tstatementnode(n).statement) then
  41. begin
  42. if tstatementnode(n).statement.nodetype=assignn then
  43. begin
  44. a:=tassignmentnode(tstatementnode(n).statement);
  45. { we need to have dfa for the node }
  46. if assigned(a.left.optinfo) and
  47. (a.left.optinfo^.index<>aword(-1)) and
  48. { node must be either a local or parameter load node }
  49. (a.left.nodetype=loadn) and
  50. { its address cannot have escaped the current routine }
  51. not(tabstractvarsym(tloadnode(a.left).symtableentry).addr_taken) and
  52. ((
  53. (tloadnode(a.left).symtableentry.typ=localvarsym) and
  54. (tloadnode(a.left).symtable=current_procinfo.procdef.localst)) or
  55. ((tloadnode(a.left).symtableentry.typ=paravarsym) and
  56. (tloadnode(a.left).symtable=current_procinfo.procdef.parast) and
  57. (tparavarsym(tloadnode(a.left).symtableentry).varspez in [vs_const,vs_value])) or
  58. ((tloadnode(a.left).symtableentry.typ=staticvarsym) and
  59. (tloadnode(a.left).symtable.symtabletype=staticsymtable) and
  60. (current_procinfo.procdef.proctypeoption<>potype_unitinit) and
  61. not(vsa_different_scope in tstaticvarsym(tloadnode(a.left).symtableentry).varsymaccess)
  62. )
  63. ) and
  64. ((a.right.nodetype in [niln,stringconstn,pointerconstn,setconstn,guidconstn]) or
  65. ((a.right.nodetype=ordconstn) and not(cs_check_range in current_settings.localswitches)) or
  66. ((a.right.nodetype=realconstn) and not(cs_ieee_errors in current_settings.localswitches)) or
  67. ((cs_opt_dead_values in current_settings.optimizerswitches) and not(might_have_sideeffects(a.right)))
  68. ) then
  69. begin
  70. redundant:=not(assigned(a.successor)) or not(DFASetIn(a.successor.optinfo^.life,a.left.optinfo^.index));
  71. if redundant then
  72. begin
  73. {$ifdef DEBUG_DEADSTORE}
  74. writeln('************************** Redundant write *********************************');
  75. printnode(a);
  76. writeln('****************************************************************************');
  77. {$endif DEBUG_DEADSTORE}
  78. pboolean(arg)^:=true;
  79. tstatementnode(n).statement.free;
  80. tstatementnode(n).statement:=cnothingnode.create;
  81. { do not run firstpass on n here, as it will remove the statement node
  82. and this will make foreachnodestatic process the wrong nodes as the current statement
  83. node will disappear }
  84. end
  85. end;
  86. end;
  87. end;
  88. end;
  89. function do_optdeadstoreelim(var rootnode: tnode): tnode;
  90. var
  91. changed: boolean;
  92. begin
  93. {$ifdef EXTDEBUG_DEADSTORE}
  94. writeln('******************* Tree before deadstore elimination **********************');
  95. printnode(rootnode);
  96. writeln('****************************************************************************');
  97. {$endif EXTDEBUG_DEADSTORE}
  98. if not(pi_dfaavailable in current_procinfo.flags) then
  99. internalerror(2013110201);
  100. changed:=false;
  101. if not current_procinfo.has_nestedprocs then
  102. foreachnodestatic(pm_postprocess, rootnode, @deadstoreelim, @changed);
  103. {$ifdef DEBUG_DEADSTORE}
  104. if changed then
  105. begin
  106. writeln('******************** Tree after deadstore elimination **********************');
  107. printnode(rootnode);
  108. writeln('****************************************************************************');
  109. end;
  110. {$endif DEBUG_DEADSTORE}
  111. result:=rootnode;
  112. end;
  113. end.