refactor PGO code
This commit is contained in:
Родитель
bcf1a4f0e9
Коммит
acccc5e85a
|
@ -47,6 +47,12 @@ if (SAFE_HEAP >= 2) {
|
|||
SAFE_HEAP_LINES = set(SAFE_HEAP_LINES); // for fast checking
|
||||
}
|
||||
|
||||
if (PGO) { // by default, correct everything during PGO
|
||||
CORRECT_SIGNS = CORRECT_SIGNS || 1;
|
||||
CORRECT_OVERFLOWS = CORRECT_OVERFLOWS || 1;
|
||||
CORRECT_ROUNDINGS = CORRECT_ROUNDINGS || 1;
|
||||
}
|
||||
|
||||
EXPORTED_FUNCTIONS = set(EXPORTED_FUNCTIONS);
|
||||
EXPORTED_GLOBALS = set(EXPORTED_GLOBALS);
|
||||
|
||||
|
@ -57,7 +63,7 @@ assert(!(USE_TYPED_ARRAYS === 2 && QUANTUM_SIZE !== 4), 'For USE_TYPED_ARRAYS ==
|
|||
// Output some info and warnings based on settings
|
||||
|
||||
if (!OPTIMIZE || !RELOOP || ASSERTIONS || CHECK_SIGNS || CHECK_OVERFLOWS || INIT_STACK || INIT_HEAP ||
|
||||
!SKIP_STACK_IN_SMALL || SAFE_HEAP || AUTO_OPTIMIZE || PROFILE || !DISABLE_EXCEPTION_CATCHING) {
|
||||
!SKIP_STACK_IN_SMALL || SAFE_HEAP || PGO || PROFILE || !DISABLE_EXCEPTION_CATCHING) {
|
||||
print('// Note: Some Emscripten settings will significantly limit the speed of the generated code.');
|
||||
} else {
|
||||
print('// Note: For maximum-speed code, see "Optimizing Code" on the Emscripten wiki, https://github.com/kripken/emscripten/wiki/Optimizing-Code');
|
||||
|
|
|
@ -1342,8 +1342,8 @@ function handleOverflow(text, bits) {
|
|||
if (!bits) return text;
|
||||
var correct = correctOverflows();
|
||||
warn(!correct || bits <= 32, 'Cannot correct overflows of this many bits: ' + bits + ' at line ' + Framework.currItem.lineNum);
|
||||
if (CHECK_OVERFLOWS) return 'CHECK_OVERFLOW(' + text + ', ' + bits + ', ' + Math.floor(correctSpecificOverflow() && !AUTO_OPTIMIZE) + (
|
||||
AUTO_OPTIMIZE ? ', "' + Debugging.getIdentifier() + '"' : ''
|
||||
if (CHECK_OVERFLOWS) return 'CHECK_OVERFLOW(' + text + ', ' + bits + ', ' + Math.floor(correctSpecificOverflow() && !PGO) + (
|
||||
PGO ? ', "' + Debugging.getIdentifier() + '"' : ''
|
||||
) + ')';
|
||||
if (!correct) return text;
|
||||
if (bits <= 32) {
|
||||
|
@ -1398,8 +1398,8 @@ function makeSignOp(value, type, op, force) {
|
|||
var bits, full;
|
||||
if (type in Runtime.INT_TYPES) {
|
||||
bits = parseInt(type.substr(1));
|
||||
full = op + 'Sign(' + value + ', ' + bits + ', ' + Math.floor(correctSpecificSign() && !AUTO_OPTIMIZE) + (
|
||||
AUTO_OPTIMIZE ? ', "' + Debugging.getIdentifier() + '"' : ''
|
||||
full = op + 'Sign(' + value + ', ' + bits + ', ' + Math.floor(correctSpecificSign() && !PGO) + (
|
||||
PGO ? ', "' + Debugging.getIdentifier() + '"' : ''
|
||||
) + ')';
|
||||
// Always sign/unsign constants at compile time, regardless of CHECK/CORRECT
|
||||
if (isNumber(value)) {
|
||||
|
|
|
@ -187,7 +187,7 @@ function SAFE_HEAP_COPY_HISTORY(dest, src) {
|
|||
#endif
|
||||
|
||||
var CorrectionsMonitor = {
|
||||
#if AUTO_OPTIMIZE
|
||||
#if PGO
|
||||
MAX_ALLOWED: Infinity,
|
||||
#else
|
||||
MAX_ALLOWED: 0, // XXX
|
||||
|
@ -200,7 +200,7 @@ var CorrectionsMonitor = {
|
|||
this.corrections++;
|
||||
if (this.corrections >= this.MAX_ALLOWED) abort('\n\nToo many corrections!');
|
||||
}
|
||||
#if AUTO_OPTIMIZE
|
||||
#if PGO
|
||||
if (!sig)
|
||||
sig = (new Error().stack).toString().split('\n')[2].split(':').slice(-1)[0]; // Spidermonkey-specific FIXME
|
||||
sig = type + '|' + sig;
|
||||
|
|
|
@ -125,11 +125,14 @@ CORRECT_ROUNDINGS = 1; // C rounds to 0 (-5.5 to -5, +5.5 to 5), while JS has no
|
|||
// Math.floor is to negative, ceil to positive. With CORRECT_ROUNDINGS,
|
||||
// we will do slow but correct C rounding operations.
|
||||
|
||||
AUTO_OPTIMIZE = 0; // When run with the CHECK_* options, will not fail on errors. Instead, will
|
||||
// keep a record of which checks succeeded and which failed. On shutdown, will
|
||||
// print out that information. This is useful for knowing which lines need
|
||||
// checking enabled and which do not, that is, this is a way to automate the
|
||||
// generation of line data for CORRECT_*_LINES options
|
||||
PGO = 0; // Profile-guided optimization.
|
||||
// When run with the CHECK_* options, will not fail on errors. Instead, will
|
||||
// keep a record of which checks succeeded and which failed. On shutdown, will
|
||||
// print out that information. This is useful for knowing which lines need
|
||||
// checking enabled and which do not, that is, this is a way to automate the
|
||||
// generation of line data for CORRECT_*_LINES options.
|
||||
// All CORRECT_* options default to 1 with PGO builds.
|
||||
// See https://github.com/kripken/emscripten/wiki/Optimizing-Code for more info
|
||||
|
||||
PROFILE = 0; // Enables runtime profiling. See test_profiling for a usage example.
|
||||
|
||||
|
|
|
@ -59,7 +59,9 @@ class RunnerCore(unittest.TestCase):
|
|||
def get_dir(self):
|
||||
return self.working_dir
|
||||
|
||||
# Similar to LLVM::createStandardModulePasses()
|
||||
def get_stdout_path(self):
|
||||
return os.path.join(self.get_dir(), 'stdout')
|
||||
|
||||
def pick_llvm_opts(self, optimization_level, safe=True):
|
||||
global LLVM_OPT_OPTS
|
||||
|
||||
|
@ -3302,10 +3304,10 @@ if 'benchmark' not in str(sys.argv):
|
|||
if Settings.QUANTUM_SIZE == 1: return self.skip('TODO FIXME')
|
||||
Settings.RELOOP = 0 # too slow
|
||||
|
||||
auto_optimize_data = read_auto_optimize_data(path_from_root('tests', 'sqlite', 'sqlite-autooptimize.fails.txt'))
|
||||
pgo_data = read_pgo_data(path_from_root('tests', 'sqlite', 'sqlite-autooptimize.fails.txt'))
|
||||
|
||||
Settings.CORRECT_SIGNS = 2
|
||||
Settings.CORRECT_SIGNS_LINES = auto_optimize_data['signs_lines']
|
||||
Settings.CORRECT_SIGNS_LINES = pgo_data['signs_lines']
|
||||
Settings.CORRECT_OVERFLOWS = 0
|
||||
Settings.CORRECT_ROUNDINGS = 0
|
||||
Settings.SAFE_HEAP = 0 # uses time.h to set random bytes, other stuff
|
||||
|
@ -4303,10 +4305,10 @@ Child2:9
|
|||
self.do_run(src.replace('TYPE', 'long long'), '*-2**2**-5**5*')
|
||||
self.do_run(src.replace('TYPE', 'int'), '*-2**2**-5**5*')
|
||||
|
||||
def test_autooptimize(self):
|
||||
def test_pgo(self):
|
||||
if Settings.USE_TYPED_ARRAYS == 2: return self.skip('LLVM opts optimize out the things we check')
|
||||
|
||||
Settings.AUTO_OPTIMIZE = Settings.CHECK_OVERFLOWS = Settings.CORRECT_OVERFLOWS = Settings.CHECK_SIGNS = Settings.CORRECT_SIGNS = 1
|
||||
Settings.PGO = Settings.CHECK_OVERFLOWS = Settings.CORRECT_OVERFLOWS = Settings.CHECK_SIGNS = Settings.CORRECT_SIGNS = 1
|
||||
|
||||
src = '''
|
||||
#include<stdio.h>
|
||||
|
@ -4335,6 +4337,26 @@ Child2:9
|
|||
|
||||
self.do_run(src, '*186854335,63*\n', output_nicerizer=check)
|
||||
|
||||
Settings.PGO = Settings.CHECK_OVERFLOWS = Settings.CORRECT_OVERFLOWS = Settings.CHECK_SIGNS = Settings.CORRECT_SIGNS = 0
|
||||
|
||||
# Now, recompile with the PGO data, and it should work
|
||||
|
||||
pgo_data = read_pgo_data(self.get_stdout_path())
|
||||
|
||||
Settings.CORRECT_SIGNS = 2
|
||||
Settings.CORRECT_SIGNS_LINES = pgo_data['signs_lines']
|
||||
Settings.CORRECT_OVERFLOWS = 2
|
||||
Settings.CORRECT_OVERFLOWS_LINES = pgo_data['overflows_lines']
|
||||
|
||||
self.do_run(src, '*186854335,63*\n')
|
||||
|
||||
# Sanity check: Without PGO, we will fail
|
||||
|
||||
try:
|
||||
self.do_run(src, '*186854335,63*\n')
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
# Generate tests for all our compilers
|
||||
def make_run(name, compiler, llvm_opts, embetter, quantum_size, typed_arrays):
|
||||
|
@ -4357,7 +4379,7 @@ class %s(T):
|
|||
Settings.ASSERTIONS = 1-embetter
|
||||
Settings.SAFE_HEAP = 1-(embetter and llvm_opts)
|
||||
Building.LLVM_OPTS = llvm_opts
|
||||
Settings.AUTO_OPTIMIZE = 0
|
||||
Settings.PGO = 0
|
||||
Settings.CHECK_OVERFLOWS = 1-(embetter or llvm_opts)
|
||||
Settings.CORRECT_OVERFLOWS = 1-(embetter and llvm_opts)
|
||||
Settings.CORRECT_SIGNS = 0
|
||||
|
@ -4465,7 +4487,7 @@ else:
|
|||
Settings.USE_TYPED_ARRAYS = 1
|
||||
Settings.QUANTUM_SIZE = 1
|
||||
Settings.I64_MODE = 0
|
||||
Settings.ASSERTIONS = Settings.SAFE_HEAP = Settings.CHECK_OVERFLOWS = Settings.CORRECT_OVERFLOWS = Settings.CHECK_SIGNS = Settings.INIT_STACK = Settings.AUTO_OPTIMIZE = Settings.RUNTIME_TYPE_INFO = 0
|
||||
Settings.ASSERTIONS = Settings.SAFE_HEAP = Settings.CHECK_OVERFLOWS = Settings.CORRECT_OVERFLOWS = Settings.CHECK_SIGNS = Settings.INIT_STACK = Settings.PGO = Settings.RUNTIME_TYPE_INFO = 0
|
||||
Settings.INVOKE_RUN = 1
|
||||
Settings.CORRECT_SIGNS = 0
|
||||
Settings.CORRECT_ROUNDINGS = 0
|
||||
|
|
|
@ -186,22 +186,25 @@ def pick_llvm_opts(optimization_level, safe=True):
|
|||
|
||||
return opts
|
||||
|
||||
def read_auto_optimize_data(filename):
|
||||
def read_pgo_data(filename):
|
||||
'''
|
||||
Reads the output of AUTO_OPTIMIZE and generates proper information for CORRECT_* == 2 's *_LINES options
|
||||
Reads the output of PGO and generates proper information for CORRECT_* == 2 's *_LINES options
|
||||
'''
|
||||
signs_lines = []
|
||||
overflows_lines = []
|
||||
|
||||
for line in open(filename, 'r'):
|
||||
if line.rstrip() == '': continue
|
||||
if '%0 failures' in line: continue
|
||||
left, right = line.split(' : ')
|
||||
signature = left.split('|')[1]
|
||||
if 'Sign' in left:
|
||||
signs_lines.append(signature)
|
||||
elif 'Overflow' in left:
|
||||
overflows_lines.append(signature)
|
||||
try:
|
||||
if line.rstrip() == '': continue
|
||||
if '%0 failures' in line: continue
|
||||
left, right = line.split(' : ')
|
||||
signature = left.split('|')[1]
|
||||
if 'Sign' in left:
|
||||
signs_lines.append(signature)
|
||||
elif 'Overflow' in left:
|
||||
overflows_lines.append(signature)
|
||||
except:
|
||||
pass
|
||||
|
||||
return {
|
||||
'signs_lines': signs_lines,
|
||||
|
@ -340,7 +343,7 @@ class Building:
|
|||
|
||||
# Run Emscripten
|
||||
exported_settings = {}
|
||||
for setting in ['QUANTUM_SIZE', 'RELOOP', 'OPTIMIZE', 'ASSERTIONS', 'USE_TYPED_ARRAYS', 'SAFE_HEAP', 'CHECK_OVERFLOWS', 'CORRECT_OVERFLOWS', 'CORRECT_SIGNS', 'CHECK_SIGNS', 'CORRECT_OVERFLOWS_LINES', 'CORRECT_SIGNS_LINES', 'CORRECT_ROUNDINGS', 'CORRECT_ROUNDINGS_LINES', 'INVOKE_RUN', 'SAFE_HEAP_LINES', 'INIT_STACK', 'AUTO_OPTIMIZE', 'EXPORTED_FUNCTIONS', 'EXPORTED_GLOBALS', 'BUILD_AS_SHARED_LIB', 'INCLUDE_FULL_LIBRARY', 'RUNTIME_TYPE_INFO', 'DISABLE_EXCEPTION_CATCHING', 'TOTAL_MEMORY', 'FAST_MEMORY', 'EXCEPTION_DEBUG', 'PROFILE', 'I64_MODE', 'EMULATE_UNALIGNED_ACCESSES']:
|
||||
for setting in ['QUANTUM_SIZE', 'RELOOP', 'OPTIMIZE', 'ASSERTIONS', 'USE_TYPED_ARRAYS', 'SAFE_HEAP', 'CHECK_OVERFLOWS', 'CORRECT_OVERFLOWS', 'CORRECT_SIGNS', 'CHECK_SIGNS', 'CORRECT_OVERFLOWS_LINES', 'CORRECT_SIGNS_LINES', 'CORRECT_ROUNDINGS', 'CORRECT_ROUNDINGS_LINES', 'INVOKE_RUN', 'SAFE_HEAP_LINES', 'INIT_STACK', 'PGO', 'EXPORTED_FUNCTIONS', 'EXPORTED_GLOBALS', 'BUILD_AS_SHARED_LIB', 'INCLUDE_FULL_LIBRARY', 'RUNTIME_TYPE_INFO', 'DISABLE_EXCEPTION_CATCHING', 'TOTAL_MEMORY', 'FAST_MEMORY', 'EXCEPTION_DEBUG', 'PROFILE', 'I64_MODE', 'EMULATE_UNALIGNED_ACCESSES']:
|
||||
try:
|
||||
value = eval('Settings.' + setting)
|
||||
if value is not None:
|
||||
|
|
Загрузка…
Ссылка в новой задаче