ruby-changes:50538
From: k0kubun <ko1@a...>
Date: Tue, 6 Mar 2018 21:53:26 +0900 (JST)
Subject: [ruby-changes:50538] k0kubun:r62677 (trunk): transform_mjit_header.rb: inline VM instructions
k0kubun 2018-03-06 21:53:19 +0900 (Tue, 06 Mar 2018) New Revision: 62677 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=62677 Log: transform_mjit_header.rb: inline VM instructions * Optcarrot benchmark (--jit) Before: 62.42 fps After: 65.31 fps Modified files: trunk/tool/transform_mjit_header.rb Index: tool/transform_mjit_header.rb =================================================================== --- tool/transform_mjit_header.rb (revision 62676) +++ tool/transform_mjit_header.rb (revision 62677) @@ -20,6 +20,11 @@ module MJITHeader https://github.com/ruby/ruby/blob/trunk/tool/transform_mjit_header.rb#L20 '__clang__', # clang ] + # These macros are relied on this script's transformation + PREFIXED_MACROS = [ + 'ALWAYS_INLINE', + ] + # For MinGW's ras.h. Those macros have its name in its definition and can't be preprocessed multiple times. RECURSIVE_MACROS = %w[ RASCTRYINFO @@ -31,6 +36,25 @@ module MJITHeader https://github.com/ruby/ruby/blob/trunk/tool/transform_mjit_header.rb#L36 'rb_equal_opt', # Not used from VM and not compilable ] + ALWAYS_INLINED_FUNCTIONS = [ + 'vm_opt_plus', + 'vm_opt_minus', + 'vm_opt_mult', + 'vm_opt_div', + 'vm_opt_mod', + 'vm_opt_neq', + 'vm_opt_lt', + 'vm_opt_le', + 'vm_opt_gt', + 'vm_opt_ge', + 'vm_opt_ltlt', + 'vm_opt_aref', + 'vm_opt_aset', + 'vm_opt_aref_with', + 'vm_opt_aset_with', + 'vm_opt_not', + ] + # Return start..stop of last decl in CODE ending STOP def self.find_decl(code, stop) level = 0 @@ -106,9 +130,11 @@ module MJITHeader https://github.com/ruby/ruby/blob/trunk/tool/transform_mjit_header.rb#L130 code.sub!(/\A(#define [^\n]+|\n)*(#define MJIT_HEADER 1\n)/, '\2') end - # This makes easier to process code + # Return [macro, others]. But others include PREFIXED_MACROS to be used in code. def self.separate_macro_and_code(code) - code.lines.partition { |l| l.start_with?('#') }.map! {|lines| lines.join('')} + code.lines.partition do |l| + l.start_with?('#') && PREFIXED_MACROS.all? { |m| !l.start_with?("#define #{m}") } + end.map! { |lines| lines.join('') } end def self.write(code, out) @@ -203,6 +229,11 @@ while (decl_range = MJITHeader.find_decl https://github.com/ruby/ruby/blob/trunk/tool/transform_mjit_header.rb#L229 if MJITHeader::IGNORED_FUNCTIONS.include?(decl_name) && /#{MJITHeader::FUNC_HEADER_REGEXP}{/.match(decl) puts "#{PROGRAM}: changing definition of '#{decl_name}' to declaration" code[decl_range] = decl.sub(/{.+}/m, ';') + elsif MJITHeader::ALWAYS_INLINED_FUNCTIONS.include?(decl_name) && match = /#{MJITHeader::FUNC_HEADER_REGEXP}{/.match(decl) + header = match[0].sub(/{\z/, '').strip + header = "static inline #{header.sub(/\A((static|inline) )+/, '')}" + decl[match.begin(0)...match.end(0)] = '{' # remove header + code[decl_range] = "\nALWAYS_INLINE(#{header});\n#{header} #{decl}" elsif extern_names.include?(decl_name) && (decl =~ /#{MJITHeader::FUNC_HEADER_REGEXP};/) decl.sub!(/(extern|static|inline) /, ' ') unless decl_name =~ /\Aattr_\w+_\w+\z/ # skip too-many false-positive warnings in insns_info.inc. -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/