diff options
-rwxr-xr-x | emcc | 72 | ||||
-rw-r--r-- | src/settings.js | 4 | ||||
-rwxr-xr-x | tests/runner.py | 164 | ||||
-rw-r--r-- | tools/js-optimizer.js | 4 | ||||
-rw-r--r-- | tools/shared.py | 9 | ||||
-rwxr-xr-x | tools/source-maps/sourcemapper.js | 2 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-pre-output.js | 1 | ||||
-rw-r--r-- | tools/test-js-optimizer-asm-pre.js | 1 |
8 files changed, 107 insertions, 150 deletions
@@ -127,11 +127,6 @@ Options that are modified or new in %s include: (For details on the affects of different opt levels, see apply_opt_level() in tools/shared.py and also src/settings.js.) - Note: Optimizations are only done when - compiling to JavaScript, not to intermediate - bitcode, *unless* you build with - EMCC_OPTIMIZE_NORMALLY=1 (not recommended - unless you know what you are doing!) -O2 As -O1, plus the relooper (loop recreation), LLVM -O2 optimizations, and @@ -144,7 +139,7 @@ Options that are modified or new in %s include: -s DOUBLE_MODE=0 -s PRECISE_I64_MATH=0 --closure 1 - --llvm-lto 1 + --llvm-lto 3 This is not recommended at all. A better idea is to try each of these separately on top of @@ -220,10 +215,15 @@ Options that are modified or new in %s include: 2: -O2 LLVM optimizations 3: -O3 LLVM optimizations (default in -O2+) - --llvm-lto <level> 0: No LLVM LTO (default in -O2 and below) - 1: LLVM LTO (default in -O3) + --llvm-lto <level> 0: No LLVM LTO (default) + 1: LLVM LTO is performed + 2: We combine all the bitcode and run LLVM opt -O3 + on that (which optimizes across modules, but is + not the same as normal LTO), but do not do normal + LTO + 3: We do both 2 and then 1 Note: If LLVM optimizations are not run - (see --llvm-opts), setting this to 1 has no + (see --llvm-opts), setting this has no effect. --closure <on> 0: No closure compiler (default in -O2 and below) @@ -884,10 +884,14 @@ try: newargs = newargs + [default_cxx_std] if llvm_opts is None: llvm_opts = LLVM_OPT_LEVEL[opt_level] - if llvm_lto is None: llvm_lto = opt_level >= 3 + if llvm_lto is None and opt_level >= 3: llvm_lto = 3 if opt_level == 0: debug_level = 4 if closure is None and opt_level == 3: closure = True + if llvm_lto is None and bind: + logging.debug('running lto for embind') # XXX this is a workaround for a pointer issue + llvm_lto = 1 + # TODO: support source maps with js_transform if js_transform and debug_level >= 4: logging.warning('disabling source maps because a js transform is being done') @@ -1058,6 +1062,10 @@ try: else: raise Exception('unknown llvm target: ' + str(shared.LLVM_TARGET)) + if shared.Settings.USE_TYPED_ARRAYS != 2 and llvm_opts > 0: + logging.warning('disabling LLVM optimizations, need typed arrays mode 2 for them') + llvm_opts = 0 + ## Compile source code to bitcode logging.debug('compiling to bitcode') @@ -1097,20 +1105,20 @@ try: shared.Building.llvm_as(input_file, temp_file) temp_files.append(temp_file) - if not LEAVE_INPUTS_RAW: assert len(temp_files) == len(input_files) + if not LEAVE_INPUTS_RAW: + assert len(temp_files) == len(input_files) + + # Optimize source files + if llvm_opts > 0: + for i in range(len(input_files)): + input_file = input_files[i] + if input_files[i].endswith(SOURCE_SUFFIXES): + temp_file = temp_files[i] + logging.debug('optimizing %s with -O%d' % (input_file, llvm_opts)) + shared.Building.llvm_opt(temp_file, llvm_opts) # If we were just asked to generate bitcode, stop there if final_suffix not in JS_CONTAINING_SUFFIXES: - if llvm_opts > 0: - if not os.environ.get('EMCC_OPTIMIZE_NORMALLY'): - logging.warning('-Ox flags ignored, since not generating JavaScript') - else: - for input_file in input_files: - if input_file.endswith(SOURCE_SUFFIXES): - logging.debug('optimizing %s with -O%d since EMCC_OPTIMIZE_NORMALLY defined' % (input_file, llvm_opts)) - shared.Building.llvm_opt(in_temp(unsuffixed(uniquename(input_file)) + '.o'), llvm_opts) - else: - logging.debug('not optimizing %s despite EMCC_OPTIMIZE_NORMALLY since not source code' % (input_file)) if not specified_target: for input_file in input_files: shutil.move(in_temp(unsuffixed(uniquename(input_file)) + '.o'), unsuffixed_basename(input_file) + '.' + final_suffix) @@ -1142,6 +1150,8 @@ try: symbols = filter(lambda symbol: symbol not in exclude, symbols) return set(symbols) + lib_opts = ['-O2'] + # XXX We also need to add libc symbols that use malloc, for example strdup. It's very rare to use just them and not # a normal malloc symbol (like free, after calling strdup), so we haven't hit this yet, but it is possible. libc_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libc.symbols')) @@ -1150,7 +1160,7 @@ try: libcxx_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libcxx', 'symbols'), exclude=libc_symbols) libcxxabi_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libcxxabi', 'symbols'), exclude=libc_symbols) - # XXX we should disable EMCC_DEBUG (and EMCC_OPTIMIZE_NORMALLY?) when building libs, just like in the relooper + # XXX we should disable EMCC_DEBUG when building libs, just like in the relooper def build_libc(lib_filename, files): o_s = [] @@ -1159,7 +1169,7 @@ try: musl_internal_includes = shared.path_from_root('system', 'lib', 'libc', 'musl', 'src', 'internal') for src in files: o = in_temp(os.path.basename(src) + '.o') - execute([shared.PYTHON, shared.EMCC, shared.path_from_root('system', 'lib', src), '-o', o, '-I', musl_internal_includes], stdout=stdout, stderr=stderr) + execute([shared.PYTHON, shared.EMCC, shared.path_from_root('system', 'lib', src), '-o', o, '-I', musl_internal_includes] + lib_opts, stdout=stdout, stderr=stderr) o_s.append(o) if prev_cxx: os.environ['EMMAKEN_CXX'] = prev_cxx shared.Building.link(o_s, in_temp(lib_filename)) @@ -1170,7 +1180,7 @@ try: for src in files: o = in_temp(src + '.o') srcfile = shared.path_from_root(src_dirname, src) - execute([shared.PYTHON, shared.EMXX, srcfile, '-o', o, '-std=c++11'], stdout=stdout, stderr=stderr) + execute([shared.PYTHON, shared.EMXX, srcfile, '-o', o, '-std=c++11'] + lib_opts, stdout=stdout, stderr=stderr) o_s.append(o) shared.Building.link(o_s, in_temp(lib_filename)) return in_temp(lib_filename) @@ -1418,16 +1428,14 @@ try: if not LEAVE_INPUTS_RAW: link_opts = [] if debug_level >= 4 else ['-strip-debug'] # remove LLVM debug if we are not asked for it - if llvm_opts > 0: - if not os.environ.get('EMCC_OPTIMIZE_NORMALLY'): - shared.Building.llvm_opt(in_temp(target_basename + '.bc'), llvm_opts) - if DEBUG: save_intermediate('opt', 'bc') - # Do LTO in a separate pass to work around LLVM bug XXX (see failure e.g. in cubescript) - else: - logging.debug('not running opt because EMCC_OPTIMIZE_NORMALLY was specified, opt should have been run before') + if llvm_lto >= 2: + logging.debug('running LLVM opt -O3 as pre-LTO') + shared.Building.llvm_opt(in_temp(target_basename + '.bc'), ['-O3']) + if DEBUG: save_intermediate('opt', 'bc') + if shared.Building.can_build_standalone(): # If we can LTO, do it before dce, since it opens up dce opportunities - if llvm_lto and shared.Building.can_use_unsafe_opts(): + if llvm_lto and llvm_lto != 2 and shared.Building.can_use_unsafe_opts(): if not shared.Building.can_inline(): link_opts.append('-disable-inlining') # do not internalize in std-link-opts - it ignores internalize-public-api-list - and add a manual internalize link_opts += ['-disable-internalize'] + shared.Building.get_safe_internalize() + ['-std-link-opts'] diff --git a/src/settings.js b/src/settings.js index 3a91b488..3e530c52 100644 --- a/src/settings.js +++ b/src/settings.js @@ -67,9 +67,9 @@ var RELOOP = 0; // Recreate js native loops from llvm data var RELOOPER = 'relooper.js'; // Loads the relooper from this path relative to compiler.js var USE_TYPED_ARRAYS = 2; // Use typed arrays for the heap. See https://github.com/kripken/emscripten/wiki/Code-Generation-Modes/ - // 0 means no typed arrays are used. + // 0 means no typed arrays are used. This mode disallows LLVM optimizations // 1 has two heaps, IHEAP (int32) and FHEAP (double), - // and addresses there are a match for normal addresses. This is deprecated. + // and addresses there are a match for normal addresses. This mode disallows LLVM optimizations. // 2 is a single heap, accessible through views as int8, int32, etc. This is // the recommended mode both for performance and for compatibility. var USE_FHEAP = 1; // Relevant in USE_TYPED_ARRAYS == 1. If this is disabled, only IHEAP will be used, and FHEAP diff --git a/tests/runner.py b/tests/runner.py index 46dc5e11..91e3883f 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -230,11 +230,11 @@ process(sys.argv[1]) os.remove(f + '.o') except: pass - args = [PYTHON, EMCC] + Building.COMPILER_TEST_OPTS + \ + args = [PYTHON, EMCC] + Building.COMPILER_TEST_OPTS + Settings.serialize() + \ ['-I', dirname, '-I', os.path.join(dirname, 'include')] + \ map(lambda include: '-I' + include, includes) + \ ['-c', f, '-o', f + '.o'] - output = Popen(args, stdout=PIPE, stderr=self.stderr_redirect).communicate()[0] + output = Popen(args, stdout=PIPE, stderr=self.stderr_redirect if not DEBUG else None).communicate()[0] assert os.path.exists(f + '.o'), 'Source compilation error: ' + output # Link all files @@ -435,7 +435,7 @@ process(sys.argv[1]) sys.argv = map(lambda arg: arg if not arg.startswith('test_') else 'default.' + arg, sys.argv) -test_modes = ['default', 'o1', 'o2', 'asm1', 'asm2', 'asm2g', 'asm2x86', 's_0_0', 's_0_1', 's_1_0', 's_1_1'] +test_modes = ['default', 'o1', 'o2', 'asm1', 'asm2', 'asm2g', 'asm2x86', 's_0_0', 's_0_1'] test_index = 0 @@ -2104,12 +2104,12 @@ Succeeded! } return int(&x); // both for the number, and forces x to not be nativized } - int main() + int main(int argc, char **argv) { // We should get the same value for the first and last - stack has unwound - int x1 = test(0); + int x1 = test(argc - 2); int x2 = test(100); - int x3 = test(0); + int x3 = test((argc - 2) / 4); printf("*%d,%d*\\n", x3-x1, x2 != x1); return 0; } @@ -4230,6 +4230,8 @@ def process(filename): ''', args=['34962', '26214', '35040']) def test_indirectbr(self): + Building.COMPILER_TEST_OPTS = filter(lambda x: x != '-g', Building.COMPILER_TEST_OPTS) + src = ''' #include <stdio.h> int main(void) { @@ -8217,7 +8219,7 @@ void*:16 if self.run_name == 'o2': self.emcc_args += ['--closure', '1'] # Use closure here for some additional coverage - Building.COMPILER_TEST_OPTS = [] # remove -g, so we have one test without it by default + Building.COMPILER_TEST_OPTS = filter(lambda x: x != '-g', Building.COMPILER_TEST_OPTS) # remove -g, so we have one test without it by default if self.emcc_args is None: Settings.SAFE_HEAP = 0 # Has some actual loads of unwritten-to places, in the C++ code... # Overflows happen in hash loop @@ -8249,7 +8251,7 @@ void*:16 def test_gcc_unmangler(self): Settings.NAMED_GLOBALS = 1 # test coverage for this - Building.COMPILER_TEST_OPTS = ['-I' + path_from_root('third_party')] + Building.COMPILER_TEST_OPTS += ['-I' + path_from_root('third_party')] self.do_run(open(path_from_root('third_party', 'gcc_demangler.c')).read(), '*d_demangle(char const*, int, unsigned int*)*', args=['_ZL10d_demanglePKciPj']) @@ -8472,6 +8474,8 @@ def process(filename): def test_openjpeg(self): if self.emcc_args is None: return self.skip('needs libc for getopt') + Building.COMPILER_TEST_OPTS = filter(lambda x: x != '-g', Building.COMPILER_TEST_OPTS) # remove -g, so we have one test without it by default + if Settings.USE_TYPED_ARRAYS == 2: Settings.CORRECT_SIGNS = 1 else: @@ -8692,6 +8696,7 @@ def process(filename): def test_autodebug(self): if Building.LLVM_OPTS: return self.skip('LLVM opts mess us up') + Building.COMPILER_TEST_OPTS += ['--llvm-opts', '0'] # Run a test that should work, generating some code self.test_structs() @@ -8970,13 +8975,11 @@ def process(filename): self.do_run(src, output) shutil.move(self.in_dir('src.cpp.o.js'), self.in_dir('normal.js')) - self.emcc_args.append('-s') - self.emcc_args.append('ASM_JS=0') + Settings.ASM_JS = 0 Settings.PGO = 1 self.do_run(src, output) + Settings.ASM_JS = 1 Settings.PGO = 0 - self.emcc_args.append('-s') - self.emcc_args.append('ASM_JS=1') shutil.move(self.in_dir('src.cpp.o.js'), self.in_dir('pgo.js')) pgo_output = run_js(self.in_dir('pgo.js')).split('\n')[1] @@ -10005,7 +10008,7 @@ finalizing 3 (global == 0) ''') # Generate tests for everything - def make_run(fullname, name=-1, compiler=-1, llvm_opts=0, embetter=0, quantum_size=0, typed_arrays=0, emcc_args=None, env='{}'): + def make_run(fullname, name=-1, compiler=-1, embetter=0, quantum_size=0, typed_arrays=0, emcc_args=None, env='{}'): exec(''' class %s(T): run_name = '%s' @@ -10040,9 +10043,18 @@ class %s(T): Building.LLVM_OPTS = 0 if '-O2' in self.emcc_args: Building.COMPILER_TEST_OPTS = [] # remove -g in -O2 tests, for more coverage + #Building.COMPILER_TEST_OPTS += self.emcc_args + for arg in self.emcc_args: + if arg.startswith('-O'): + Building.COMPILER_TEST_OPTS.append(arg) # so bitcode is optimized too, this is for cpp to ll + else: + try: + key, value = arg.split('=') + Settings[key] = value # forward -s K=V + except: + pass return - llvm_opts = %d # 1 is yes, 2 is yes and unsafe embetter = %d quantum_size = %d # TODO: Move much of these to a init() function in shared.py, and reuse that @@ -10052,14 +10064,13 @@ class %s(T): Settings.MICRO_OPTS = embetter Settings.QUANTUM_SIZE = quantum_size Settings.ASSERTIONS = 1-embetter - Settings.SAFE_HEAP = 1-(embetter and llvm_opts) - Building.LLVM_OPTS = llvm_opts - Settings.CHECK_OVERFLOWS = 1-(embetter or llvm_opts) - Settings.CORRECT_OVERFLOWS = 1-(embetter and llvm_opts) + Settings.SAFE_HEAP = 1-embetter + Settings.CHECK_OVERFLOWS = 1-embetter + Settings.CORRECT_OVERFLOWS = 1-embetter Settings.CORRECT_SIGNS = 0 Settings.CORRECT_ROUNDINGS = 0 Settings.CORRECT_OVERFLOWS_LINES = CORRECT_SIGNS_LINES = CORRECT_ROUNDINGS_LINES = SAFE_HEAP_LINES = [] - Settings.CHECK_SIGNS = 0 #1-(embetter or llvm_opts) + Settings.CHECK_SIGNS = 0 #1-embetter Settings.RUNTIME_TYPE_INFO = 0 Settings.DISABLE_EXCEPTION_CATCHING = 0 Settings.INCLUDE_FULL_LIBRARY = 0 @@ -10068,12 +10079,10 @@ class %s(T): Settings.EMULATE_UNALIGNED_ACCESSES = int(Settings.USE_TYPED_ARRAYS == 2 and Building.LLVM_OPTS == 2) Settings.DOUBLE_MODE = 1 if Settings.USE_TYPED_ARRAYS and Building.LLVM_OPTS == 0 else 0 Settings.PRECISE_I64_MATH = 0 - Settings.NAMED_GLOBALS = 0 if not (embetter and llvm_opts) else 1 - - Building.pick_llvm_opts(3) + Settings.NAMED_GLOBALS = 0 if not embetter else 1 TT = %s -''' % (fullname, fullname, env, fullname, fullname, compiler, str(emcc_args), llvm_opts, embetter, quantum_size, typed_arrays, fullname)) +''' % (fullname, fullname, env, fullname, fullname, compiler, str(emcc_args), embetter, quantum_size, typed_arrays, fullname)) return TT # Make one run with the defaults @@ -10092,16 +10101,14 @@ TT = %s exec('''asm2x86 = make_run("asm2x86", compiler=CLANG, emcc_args=["-O2", "-g", "-s", "CHECK_HEAP_ALIGN=1"], env='{"EMCC_LLVM_TARGET": "i386-pc-linux-gnu"}')''') # Make custom runs with various options - for compiler, quantum, embetter, typed_arrays, llvm_opts in [ - (CLANG, 4, 0, 0, 0), - (CLANG, 4, 0, 0, 1), - (CLANG, 4, 1, 1, 0), - (CLANG, 4, 1, 1, 1), + for compiler, quantum, embetter, typed_arrays in [ + (CLANG, 4, 0, 0), + (CLANG, 4, 1, 1), ]: - fullname = 's_%d_%d%s%s' % ( - llvm_opts, embetter, '' if quantum == 4 else '_q' + str(quantum), '' if typed_arrays in [0, 1] else '_t' + str(typed_arrays) + fullname = 's_0_%d%s%s' % ( + embetter, '' if quantum == 4 else '_q' + str(quantum), '' if typed_arrays in [0, 1] else '_t' + str(typed_arrays) ) - exec('%s = make_run(fullname, %r,%r,%d,%d,%d,%d)' % (fullname, fullname, compiler, llvm_opts, embetter, quantum, typed_arrays)) + exec('%s = make_run(fullname, %r,%r,%d,%d,%d)' % (fullname, fullname, compiler, embetter, quantum, typed_arrays)) del T # T is just a shape for the specific subclasses, we don't test it itself @@ -10235,23 +10242,25 @@ Options that are modified or new in %s include: (['-o', 'something.js', '-O3', '-s', 'ASM_JS=0'], 3, None, 1, 1), # and, test compiling to bitcode first (['-o', 'something.bc'], 0, [], 0, 0), - (['-o', 'something.bc'], 0, ['-O0'], 0, 0), - (['-o', 'something.bc'], 1, ['-O1'], 0, 0), - (['-o', 'something.bc'], 2, ['-O2'], 0, 0), - (['-o', 'something.bc'], 3, ['-O3', '-s', 'ASM_JS=0'], 1, 0), - (['-O1', '-o', 'something.bc'], 0, [], 0, 0), # -Ox is ignored and warned about + (['-o', 'something.bc', '-O0'], 0, [], 0, 0), + (['-o', 'something.bc', '-O1'], 1, ['-O1'], 0, 0), + (['-o', 'something.bc', '-O2'], 2, ['-O2'], 0, 0), + (['-o', 'something.bc', '-O3'], 3, ['-O3', '-s', 'ASM_JS=0'], 1, 0), + (['-O1', '-o', 'something.bc'], 1, [], 0, 0), ]: print params, opt_level, bc_params, closure, has_malloc self.clear() keep_debug = '-g' in params - output = Popen([PYTHON, compiler, path_from_root('tests', 'hello_world_loop' + ('_malloc' if has_malloc else '') + '.cpp')] + params, + args = [PYTHON, compiler, path_from_root('tests', 'hello_world_loop' + ('_malloc' if has_malloc else '') + '.cpp')] + params + print '..', args + output = Popen(args, stdout=PIPE, stderr=PIPE).communicate() assert len(output[0]) == 0, output[0] if bc_params is not None: - if '-O1' in params and 'something.bc' in params: - assert '-Ox flags ignored, since not generating JavaScript' in output[1] assert os.path.exists('something.bc'), output[1] - output = Popen([PYTHON, compiler, 'something.bc', '-o', 'something.js'] + bc_params, stdout=PIPE, stderr=PIPE).communicate() + bc_args = [PYTHON, compiler, 'something.bc', '-o', 'something.js'] + bc_params + print '....', bc_args + output = Popen(bc_args, stdout=PIPE, stderr=PIPE).communicate() assert os.path.exists('something.js'), output[1] assert ('Applying some potentially unsafe optimizations!' in output[1]) == (opt_level >= 3), 'unsafe warning should appear in opt >= 3' self.assertContained('hello, world!', run_js('something.js')) @@ -11500,64 +11509,6 @@ seeked= file. code = open('a.out.js').read() assert 'SAFE_HEAP' in code, 'valid -s option had an effect' - def test_optimize_normally(self): - assert not os.environ.get('EMCC_OPTIMIZE_NORMALLY') - assert not os.environ.get('EMCC_DEBUG') - - for optimize_normally in [0, 1]: - print optimize_normally - try: - if optimize_normally: os.environ['EMCC_OPTIMIZE_NORMALLY'] = '1' - os.environ['EMCC_DEBUG'] = '1' - - open(self.in_dir('main.cpp'), 'w').write(r''' - extern "C" { - void something(); - } - - int main() { - something(); - return 0; - } - ''') - open(self.in_dir('supp.cpp'), 'w').write(r''' - #include <stdio.h> - - extern "C" { - void something() { - printf("yello\n"); - } - } - ''') - out, err = Popen([PYTHON, EMCC, self.in_dir('main.cpp'), '-O2', '-o', 'main.o'], stdout=PIPE, stderr=PIPE).communicate() - assert ("emcc: LLVM opts: ['-O3']" in err) == optimize_normally - assert (' with -O3 since EMCC_OPTIMIZE_NORMALLY defined' in err) == optimize_normally - - out, err = Popen([PYTHON, EMCC, self.in_dir('supp.cpp'), '-O2', '-o', 'supp.o'], stdout=PIPE, stderr=PIPE).communicate() - assert ("emcc: LLVM opts: ['-O3']" in err) == optimize_normally - assert (' with -O3 since EMCC_OPTIMIZE_NORMALLY defined' in err) == optimize_normally - - out, err = Popen([PYTHON, EMCC, self.in_dir('main.o'), self.in_dir('supp.o'), '-O2', '-o', 'both.o'], stdout=PIPE, stderr=PIPE).communicate() - assert "emcc: LLVM opts: ['-O3']" not in err - assert ' with -O3 since EMCC_OPTIMIZE_NORMALLY defined' not in err - assert ('despite EMCC_OPTIMIZE_NORMALLY since not source code' in err) == optimize_normally - - out, err = Popen([PYTHON, EMCC, self.in_dir('main.cpp'), self.in_dir('supp.cpp'), '-O2', '-o', 'both2.o'], stdout=PIPE, stderr=PIPE).communicate() - assert ("emcc: LLVM opts: ['-O3']" in err) == optimize_normally - assert (' with -O3 since EMCC_OPTIMIZE_NORMALLY defined' in err) == optimize_normally - - for last in ['both.o', 'both2.o']: - out, err = Popen([PYTHON, EMCC, self.in_dir('both.o'), '-O2', '-o', last + '.js', '--memory-init-file', '0'], stdout=PIPE, stderr=PIPE).communicate() - assert ("emcc: LLVM opts: ['-O3']" not in err) == optimize_normally - assert ' with -O3 since EMCC_OPTIMIZE_NORMALLY defined' not in err - output = run_js(last + '.js') - assert 'yello' in output, 'code works ' + err - assert open('both.o.js').read() == open('both2.o.js').read() - - finally: - if optimize_normally: del os.environ['EMCC_OPTIMIZE_NORMALLY'] - del os.environ['EMCC_DEBUG'] - def test_jcache_printf(self): open(self.in_dir('src.cpp'), 'w').write(r''' #include <stdio.h> @@ -13481,9 +13432,10 @@ process(sys.argv[1]) try_delete(final_filename) output = Popen([PYTHON, EMCC, filename, #'-O3', '-O2', '-s', 'DOUBLE_MODE=0', '-s', 'PRECISE_I64_MATH=0', - '--llvm-lto', '1', '--memory-init-file', '0', '--js-transform', 'python hardcode.py', + '--llvm-lto', '3', '--memory-init-file', '0', '--js-transform', 'python hardcode.py', '-s', 'TOTAL_MEMORY=128*1024*1024', '--closure', '1', + #'-g', '-o', final_filename] + shared_args + emcc_args, stdout=PIPE, stderr=self.stderr_redirect).communicate() assert os.path.exists(final_filename), 'Failed to compile file: ' + output[0] @@ -13798,7 +13750,7 @@ process(sys.argv[1]) args = [path_from_root('tests', 'nbody-java', x) for x in os.listdir(path_from_root('tests', 'nbody-java')) if x.endswith('.c')] + \ ['-I' + path_from_root('tests', 'nbody-java')] self.do_benchmark('nbody_java', '', '''Time(s)''', - force_c=True, emcc_args=args + ['-s', 'PRECISE_I64_MATH=1', '--llvm-lto', '0'], native_args=args + ['-lgc', '-std=c99', '-target', 'x86_64-pc-linux-gnu', '-lm']) + force_c=True, emcc_args=args + ['-s', 'PRECISE_I64_MATH=1', '--llvm-lto', '2'], native_args=args + ['-lgc', '-std=c99', '-target', 'x86_64-pc-linux-gnu', '-lm']) def lua(self, benchmark, expected, output_parser=None, args_processor=None): shutil.copyfile(path_from_root('tests', 'lua', benchmark + '.lua'), benchmark + '.lua') @@ -14190,8 +14142,7 @@ fi try_delete('a.out.js') basebc_name = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-0-basebc.bc') - dcebc_name1 = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-1-linktime.bc') - dcebc_name2 = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-2-linktime.bc') + dcebc_name = os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-1-linktime.bc') ll_names = [os.path.join(TEMP_DIR, 'emscripten_temp', 'emcc-X-ll.ll').replace('X', str(x)) for x in range(2,5)] # Building a file that *does* need dlmalloc *should* trigger cache generation, but only the first time @@ -14199,7 +14150,6 @@ fi for i in range(3): print filename, libname, i self.clear() - dcebc_name = dcebc_name1 if i == 0 else dcebc_name2 try_delete(basebc_name) # we might need to check this file later try_delete(dcebc_name) # we might need to check this file later for ll_name in ll_names: try_delete(ll_name) @@ -14216,9 +14166,9 @@ fi assert os.path.exists(os.path.join(EMCC_CACHE, libname + '.bc')) if libname == 'libcxx': print os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size, os.stat(basebc_name).st_size, os.stat(dcebc_name).st_size - assert os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size > 1800000, 'libc++ is big' - assert os.stat(basebc_name).st_size > 1800000, 'libc++ is indeed big' - assert os.stat(dcebc_name).st_size < 750000, 'Dead code elimination must remove most of libc++' + assert os.stat(os.path.join(EMCC_CACHE, libname + '.bc')).st_size > 1000000, 'libc++ is big' + assert os.stat(basebc_name).st_size > 1000000, 'libc++ is indeed big' + assert os.stat(dcebc_name).st_size < 500000, 'Dead code elimination must remove most of libc++' # should only have metadata in -O0, not 1 and 2 if i > 0: for ll_name in ll_names: @@ -14305,7 +14255,7 @@ fi (['--jcache'], 'hello_malloc.cpp', False, True, False, True, False, True, []), ([], 'hello_malloc.cpp', False, False, False, False, False, False, []), # new, huge file - ([], 'hello_libcxx.cpp', False, False, False, False, False, False, ('4 chunks',)), + ([], 'hello_libcxx.cpp', False, False, False, False, False, False, ('3 chunks',)), (['--jcache'], 'hello_libcxx.cpp', True, False, True, False, True, False, []), (['--jcache'], 'hello_libcxx.cpp', False, True, False, True, False, True, []), ([], 'hello_libcxx.cpp', False, False, False, False, False, False, []), diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 151e573a..be5accbc 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -584,6 +584,8 @@ function simplifyExpressionsPre(ast) { node[3] = value[2]; } } + } else if (type == 'sub' && node[1][0] == 'name' && /^FUNCTION_TABLE.*/.exec(node[1][1])) { + return null; // do not traverse subchildren here, we should not collapse 55 & 126. TODO: optimize this into a nonvirtual call (also because we lose some other opts here)! } }); @@ -2035,7 +2037,6 @@ function eliminate(ast, memSafe) { // examine body and note locals var hasSwitch = false; traverse(func, function(node, type) { - if (debug && type) type = type.toString(); if (type === 'var') { var node1 = node[1]; for (var i = 0; i < node1.length; i++) { @@ -2645,7 +2646,6 @@ function eliminate(ast, memSafe) { var has_num = false; var fail = false; traverse(node, function(subNode, subType) { - if (debug && subType) subType = subType.toString(); if (subType === 'binary') { if (subNode[1] !== '+') { fail = true; diff --git a/tools/shared.py b/tools/shared.py index 8d235589..720b607e 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -283,7 +283,7 @@ def check_node_version(): # we re-check sanity when the settings are changed) # We also re-check sanity and clear the cache when the version changes -EMSCRIPTEN_VERSION = '1.5.1' +EMSCRIPTEN_VERSION = '1.5.2' def generate_sanity(): return EMSCRIPTEN_VERSION + '|' + get_llvm_target() @@ -312,6 +312,7 @@ def check_sanity(force=False): if reason: logging.warning('(Emscripten: %s, clearing cache)' % reason) Cache.erase() + force = False # the check actually failed, so definitely write out the sanity file, to avoid others later seeing failures too # some warning, not fatal checks - do them even if EM_IGNORE_SANITY is on check_llvm_version() @@ -932,7 +933,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e # Finish link actual_files = unique_ordered(actual_files) # tolerate people trying to link a.so a.so etc. - logging.debug('emcc: llvm-linking: %s', actual_files) + logging.debug('emcc: llvm-linking: %s to %s', actual_files, target) # check for too-long command line link_cmd = [LLVM_LINK] + actual_files + ['-o', target] @@ -1281,9 +1282,6 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e emcc_debug = os.environ.get('EMCC_DEBUG') if emcc_debug: del os.environ['EMCC_DEBUG'] - emcc_optimize_normally = os.environ.get('EMCC_OPTIMIZE_NORMALLY') - if emcc_optimize_normally: del os.environ['EMCC_OPTIMIZE_NORMALLY'] - def make(opt_level): raw = relooper + '.raw.js' Building.emcc(os.path.join('relooper', 'Relooper.cpp'), ['-I' + os.path.join('relooper'), '--post-js', @@ -1314,7 +1312,6 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)''' % { 'winfix': '' if not WINDOWS e finally: os.chdir(curr) if emcc_debug: os.environ['EMCC_DEBUG'] = emcc_debug - if emcc_optimize_normally: os.environ['EMCC_OPTIMIZE_NORMALLY'] = emcc_optimize_normally if not ok: logging.error('bootstrapping relooper failed. You may need to manually create relooper.js by compiling it, see src/relooper/emscripten') 1/0 diff --git a/tools/source-maps/sourcemapper.js b/tools/source-maps/sourcemapper.js index 0001e7c7..fa908900 100755 --- a/tools/source-maps/sourcemapper.js +++ b/tools/source-maps/sourcemapper.js @@ -110,7 +110,7 @@ function generateMap(mappings, sourceRoot, mapFileBaseName, generatedLineOffset) try { generator.setSourceContent(originalFileName, fs.readFileSync(rootedPath, 'utf-8')); } catch (e) { - console.warn("Unable to find original file for " + originalFileName + + console.warn("sourcemapper: Unable to find original file for " + originalFileName + " at " + rootedPath); } } diff --git a/tools/test-js-optimizer-asm-pre-output.js b/tools/test-js-optimizer-asm-pre-output.js index 2cd8d407..301a2ec8 100644 --- a/tools/test-js-optimizer-asm-pre-output.js +++ b/tools/test-js-optimizer-asm-pre-output.js @@ -19,6 +19,7 @@ function a() { f(g() | 0 & -1); f((g() | 0) >> 2); $56 = _fcntl() | 0 | 1; + FUNCTION_TABLE_ii[55 & 127]() | 0; } function b($this, $__n) { $this = $this | 0; diff --git a/tools/test-js-optimizer-asm-pre.js b/tools/test-js-optimizer-asm-pre.js index ca7d2894..c7c92124 100644 --- a/tools/test-js-optimizer-asm-pre.js +++ b/tools/test-js-optimizer-asm-pre.js @@ -20,6 +20,7 @@ function a() { f(g() | 0 & -1); f((g() | 0) >> 2); $56 = (_fcntl() | 0) | 1; + FUNCTION_TABLE_ii[55 & 127]() | 0; } function b($this, $__n) { $this = $this | 0; |