analysis: add an optimization to remove 'getter' tests when called outside an init
authorJean-Sebastien Gelinas <calestar@gmail.com>
Wed, 21 Oct 2009 21:20:18 +0000 (17:20 -0400)
committerJean Privat <jean@pryen.org>
Mon, 11 Jan 2010 21:52:31 +0000 (16:52 -0500)
Signed-off-by: Jean-Sebastien Gelinas <calestar@gmail.com>
Signed-off-by: Jean Privat <jean@pryen.org>

src/analysis/analysis.nit
src/analysis/remove_out_of_init_get_test.nit [new file with mode: 0644]
src/nitc.nit

index 533175e..91e9a9d 100644 (file)
@@ -42,12 +42,14 @@ import reachable_from_init_method_analysis_impl
 # Global Optimizations
 import dead_method_removal
 import inline_get_and_set
+import remove_out_of_init_get_test
 
 redef class ToolContext
        readable writable var _global_callgraph: String = "rta"
        readable writable var _no_dead_method_removal: Bool = false
        readable writable var _no_inline_get_set: Bool = false
        readable writable var _no_callgraph_from_init: Bool = false
+       readable writable var _no_out_of_init_get_test_removal: Bool = false
 end
 
 redef class Program
@@ -95,6 +97,7 @@ redef class Program
        fun do_global_post_analysis_optimizations do
                assert tc.global
                if not tc.no_dead_method_removal then optimize_dead_methods
+               if not tc.no_out_of_init_get_test_removal then optimize_out_of_init_getters
        end
 
        # This method will create log files storing analysis information
diff --git a/src/analysis/remove_out_of_init_get_test.nit b/src/analysis/remove_out_of_init_get_test.nit
new file mode 100644 (file)
index 0000000..0e8b46d
--- /dev/null
@@ -0,0 +1,54 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2009 Jean-Sebastien Gelinas <calestar@gmail.com>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This package introduces an optimization that removes 'get' tests when
+# not reachable from an initializer
+package remove_out_of_init_get_test
+
+import reachable_from_init_method_analysis
+
+redef class Program
+       # Calling this method will remove all 'isset' that were generated automaticaly
+       # before a attribute read if this attribute read is done in a method that
+       # cannot be reached by a initializer
+       fun optimize_out_of_init_getters do
+               with_each_iroutines !action(i,m) do
+                       if not rfima.is_iroutine_reachable_from_init(i) then
+                               var remover = new GetterTestRemover
+                               remover.visit_iroutine(i)
+                       end
+               end
+       end
+end
+
+class GetterTestRemover
+special ICodeVisitor
+       redef fun visit_icode(ic)
+       do
+               # Replace 'x = isset(y)' by 'x = true'
+               if ic isa IAttrIsset then
+                       var result = ic.result
+                       assert result != null
+                       var e =  new INative("TAG_Bool(true)", null)
+                       e.is_pure = true
+                       e.result = result
+                       current_icode.insert_before(e)
+                       current_icode.delete
+               end
+
+               super
+       end
+end
index 8a3ca9d..46fbf1a 100644 (file)
@@ -33,6 +33,7 @@ special AbstractCompiler
        readable var _opt_global_no_STF_opt: OptionBool = new OptionBool("Do not use SFT optimization", "--no-global-SFT-optimization")
        readable var _opt_global_no_DMR_opt: OptionBool = new OptionBool("Do not use dead method removal optimization", "--no-global-DMR-optimization")
        readable var _opt_global_no_inline_get_set: OptionBool = new OptionBool("Do not automatically inline getters/setters", "--no-global-get-set-inlining")
+       readable var _opt_global_no_out_of_init_get_test_opt: OptionBool = new OptionBool("Do not remove get tests outside object initialization", "--no-global-OOIT-optimization")
        readable var _opt_global_no_RFIMA: OptionBool = new OptionBool("Do not use a specialized algorithm to find reachable methods from initializers", "--no-global-RFIM-analysis")
        readable var _opt_global_callgraph: OptionEnum = new OptionEnum(["none", "cha", "rta"], "The algorithm to use to build the callgraph", 2, "--global-callgraph")
        readable var _opt_clibdir: OptionString = new OptionString("NIT C library directory", "--clibdir")
@@ -44,7 +45,7 @@ special AbstractCompiler
        init
        do
                super("nitc")
-               option_context.add_option(opt_output, opt_boost, opt_no_cc, opt_global, opt_clibdir, opt_bindir, opt_compdir, opt_extension_prefix, opt_dump, opt_global_no_STF_opt, opt_global_no_DMR_opt, opt_global_callgraph, opt_global_no_inline_get_set, opt_global_no_RFIMA)
+               option_context.add_option(opt_output, opt_boost, opt_no_cc, opt_global, opt_clibdir, opt_bindir, opt_compdir, opt_extension_prefix, opt_dump, opt_global_no_STF_opt, opt_global_no_DMR_opt, opt_global_callgraph, opt_global_no_inline_get_set, opt_global_no_RFIMA, opt_global_no_out_of_init_get_test_opt)
        end
 
        redef fun process_options
@@ -60,6 +61,7 @@ special AbstractCompiler
                no_dead_method_removal = opt_global_no_DMR_opt.value
                no_inline_get_set = opt_global_no_inline_get_set.value
                no_callgraph_from_init = opt_global_no_RFIMA.value
+               no_out_of_init_get_test_removal = opt_global_no_out_of_init_get_test_opt.value
                global_callgraph = opt_global_callgraph.value_name
                compdir = opt_compdir.value
                if compdir == null then