aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2011-12-13 12:20:45 -0800
committerAlon Zakai <alonzakai@gmail.com>2011-12-13 12:20:45 -0800
commit9071942043abc0000a3fa1a68f34887657275a2c (patch)
tree605bfa623e8293341b5102a2ef6020c50d542d87
parent09f3e4c41358e74b34b06a755372847577dce34f (diff)
llvm opts in emcc (untested)
-rwxr-xr-xemcc69
-rw-r--r--tests/runner.py6
-rw-r--r--tools/shared.py12
3 files changed, 52 insertions, 35 deletions
diff --git a/emcc b/emcc
index b75a68e2..11748bbb 100755
--- a/emcc
+++ b/emcc
@@ -8,12 +8,9 @@ emcc is a drop-in replacement for a compiler like gcc or clang.
Tell your build system to use this instead of the compiler, linker, ar and
ranlib. All the normal build commands will be sent to this script, which
-will proxy them to the appropriate LLVM build commands, in order to
-generate proper code for Emscripten to later process.
-
-For example, compilation will be translated into calls to clang
-with -emit-llvm, and linking will be translated into calls to llvm-link,
-and so forth.
+will proxy them to the appropriate build commands. For example, compilation
+will be translated into calls to clang with -emit-llvm, and linking will
+be translated into calls to llvm-link, and so forth.
Example uses:
@@ -77,7 +74,6 @@ emcc can be influenced by a few environment variables:
your system headers will be used.
EMMAKEN_COMPILER - The compiler to be used, if you don't want the default clang.
-
'''
import os, sys, shutil
@@ -117,16 +113,24 @@ Most normal gcc/g++ options will work, for example:
Options that are modified or new in %s include:
-O0 No optimizations (default)
- -O1 Simple optimizations and no runtime assertions
+ -O1 Simple optimizations, including safe LLVM
+ optimizations, and no runtime assertions
-O2 As -O1, plus code flow optimization (relooper)
Warning: Compiling with this takes a long time!
-O3 As -O2, plus dangerous optimizations that may
- break things
- -s OPTION=VALUE JavaScript code generation option
- passed into the emscripten compiler
- --typed-arrays <mode> 0: no typed arrays
- 1: parallel typed arrays
- 2: shared (C-like) typed arrays (default)
+ break the generated code! If that happens, try
+ -O2 and then adding dangerous optimizations one
+ by one.
+ -s OPTION=VALUE JavaScript code generation option passed
+ into the emscripten compiler
+ --typed-arrays <mode> 0: No typed arrays
+ 1: Parallel typed arrays
+ 2: Shared (C-like) typed arrays (default)
+ --llvm-opts <level> 0: No LLVM optimizations
+ 1: Safe/portable LLVM optimizations
+ 2: Full, unsafe/unportable LLVM optimizations;
+ this will almost certainly break the
+ generated code!
The target file, if specified (-o <target>), defines what will
be generated:
@@ -248,6 +252,7 @@ elif use_compiler:
newargs = sys.argv[1:]
opt_level = 0
+ llvm_opt_level = 0
for i in range(len(newargs)):
if newargs[i].startswith('-O'):
@@ -256,6 +261,8 @@ elif use_compiler:
assert 0 <= opt_level <= 3
except:
raise Exception('Invalid optimization level: ' + newargs[i])
+ if opt_level >= 1:
+ llvm_opt_level = 1
newargs[i] = ''
newargs = [ arg for arg in newargs if arg is not '' ]
@@ -284,6 +291,21 @@ elif use_compiler:
final_suffix = target.split('.')[-1]
+ # Apply optimization level settings
+ if opt_level >= 1:
+ shared.Settings.ASSERTIONS = 0
+ if opt_level >= 2:
+ shared.Settings.RELOOP = 1
+ print >> sys.stderr, 'Warning: The relooper optimization can be very slow.'
+ if opt_level >= 3:
+ shared.Settings.CORRECT_SIGNS = 0
+ shared.Settings.CORRECT_OVERFLOWS = 0
+ shared.Settings.CORRECT_ROUNDINGS = 0
+ shared.Settings.I64_MODE = 0
+ shared.Settings.DOUBLE_MODE = 0
+ shared.Settings.DISABLE_EXCEPTION_CATCHING = 1
+ print >> sys.stderr, 'Warning: Applying some potentially unsafe optimizations! (Use -O2 if this fails.)'
+
## Compile
# First, generate LLVM bitcode TODO: handle |emcc a.cpp b.cpp -c| which generate *two* bitcode files
@@ -292,6 +314,10 @@ elif use_compiler:
if DEBUG: print >> sys.stderr, "Running:", call, ' '.join(newargs)
Popen([call] + newargs).communicate()
+ # Optimize, if asked to
+ if llvm_opt_level > 0:
+ shared.Building.llvm_opt(target_basename + '.bc', 2, safe=llvm_opt_level < 2)
+
# If we were just asked to generate bitcode, stop there
if final_suffix in ['o', 'bc']:
if final_suffix == 'o':
@@ -300,21 +326,6 @@ elif use_compiler:
## Continue on to create JavaScript
- # Apply optimization level settings
- if opt_level >= 1:
- shared.Settings.ASSERTIONS = 0
- if opt_level >= 2:
- shared.Settings.RELOOP = 1
- print >> sys.stderr, 'Warning: The relooper optimization can be very slow.'
- if opt_level >= 3:
- shared.Settings.CORRECT_SIGNS = 0
- shared.Settings.CORRECT_OVERFLOWS = 0
- shared.Settings.CORRECT_ROUNDINGS = 0
- shared.Settings.I64_MODE = 0
- shared.Settings.DOUBLE_MODE = 0
- shared.Settings.DISABLE_EXCEPTION_CATCHING = 1
- print >> sys.stderr, 'Warning: Applying some potentially unsafe optimizations! (Use -O2 if this fails.)'
-
# Apply -s settings in newargs here (after -Ox, so they can override it)
for change in settings_changes:
diff --git a/tests/runner.py b/tests/runner.py
index 67684470..b0125f12 100644
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -81,7 +81,8 @@ class RunnerCore(unittest.TestCase):
need_post = build_ll_hook(filename)
Building.llvm_as(filename)
shutil.move(filename + '.o.ll', filename + '.o.ll.pre') # for comparisons later
- Building.llvm_opts(filename)
+ if Building.LLVM_OPTS:
+ Building.llvm_opts(filename)
Building.llvm_dis(filename)
if build_ll_hook and need_post:
build_ll_hook(filename)
@@ -4958,8 +4959,7 @@ Options that are modified or new in %s include:
# emcc --llvm-opts=x .. ==> pick level of LLVM optimizations (default is 0, to be safe?)
- # When doing unsafe opts, can we run -Ox on the source, not just at the very end?
- # In fact we can run safe opts at that time too, now we are a gcc replacement. Removes the entire need for llvm opts only at the end.
+ # We can run safe opts at each emcc invocation, now we are a gcc replacement. Removes the entire need for llvm opts only at the end.
# linking - TODO. in particular, test normal project linking, static and dynamic: get_library should not need to be told what to link!
# emcc a.cpp b.cpp => one .js
# emcc a.cpp b.cpp -c => two .o files
diff --git a/tools/shared.py b/tools/shared.py
index dcca2707..8cf6e1fd 100644
--- a/tools/shared.py
+++ b/tools/shared.py
@@ -196,6 +196,7 @@ class Settings:
class Settings2:
reset = Settings.reset
load_defaults = Settings.load_defaults
+ QUANTUM_SIZE = 4
Settings = Settings2
@classmethod
@@ -203,6 +204,7 @@ class Settings:
''' Load the JS settings into Python '''
settings = open(path_from_root('src', 'settings.js')).read().replace('var ', 'Settings.').replace('//', '#')
exec(settings)
+Settings.reset()
# Building
@@ -296,7 +298,13 @@ class Building:
# Optional LLVM optimizations
@staticmethod
- def llvm_opts(filename):
+ def llvm_opt(filename, level, safe=True):
+ output = Popen([LLVM_OPT, filename] + Building.pick_llvm_opts(level, safe) + ['-o=' + filename + '.opt.bc'], stdout=PIPE).communicate()[0]
+ assert os.path.exists(filename + '.opt.bc'), 'Failed to run llvm optimizations: ' + output
+ shutil.move(filename + '.opt.bc', filename)
+
+ @staticmethod
+ def llvm_opts(filename): # deprecated version, only for test runner. TODO: remove
if Building.LLVM_OPTS:
shutil.move(filename + '.o', filename + '.o.pre')
output = Popen([LLVM_OPT, filename + '.o.pre'] + Building.LLVM_OPT_OPTS + ['-o=' + filename + '.o'], stdout=PIPE).communicate()[0]
@@ -371,8 +379,6 @@ class Building:
into i64s. In any case, the handpicked ones here should be safe and portable. They are also tuned for
things that look useful.
'''
- if not Building.LLVM_OPTS: return # XXX this makes using this independently from the test runner very unpleasant
-
opts = []
if optimization_level > 0:
#opts.append('-disable-inlining') # we prefer to let closure compiler do our inlining