diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/cases/caall.ll | 12 | ||||
-rw-r--r-- | tests/cases/i24_mem_ta2.ll | 10 | ||||
-rw-r--r-- | tests/cases/i64toi8star.ll | 6 | ||||
-rw-r--r-- | tests/cases/inttoptr.ll | 8 | ||||
-rw-r--r-- | tests/cases/invokebitcast.ll | 7 | ||||
-rw-r--r-- | tests/cases/phicubed.ll | 2 | ||||
-rw-r--r-- | tests/cases/phientryimplicit.ll | 36 | ||||
-rw-r--r-- | tests/cases/phiself.ll | 4 | ||||
-rw-r--r-- | tests/cases/ptrtoi64.ll | 14 | ||||
-rw-r--r-- | tests/cases/sillybitcast.ll | 4 | ||||
-rw-r--r-- | tests/cases/sillybitcast2.ll | 35 | ||||
-rw-r--r-- | tests/cases/unaligneddouble.ll | 2 | ||||
-rwxr-xr-x | tests/runner.py | 5 | ||||
-rw-r--r-- | tests/test_benchmark.py | 208 | ||||
-rw-r--r-- | tests/test_core.py | 75 | ||||
-rw-r--r-- | tests/test_other.py | 5 |
16 files changed, 275 insertions, 158 deletions
diff --git a/tests/cases/caall.ll b/tests/cases/caall.ll index 5b8f7f29..2cc231ec 100644 --- a/tests/cases/caall.ll +++ b/tests/cases/caall.ll @@ -1,6 +1,6 @@ ; ModuleID = 'tests/hello_world.bc' -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" -target triple = "i386-pc-linux-gnu" +target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32" +target triple = "le32-unknown-nacl" @.str = private unnamed_addr constant [15 x i8] c"hello, world!\0A\00", align 1 ; [#uses=1 type=[15 x i8]*] @@ -11,14 +11,14 @@ entry: store i32 0, i32* %retval %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0 type=i32] %call12 = call void (i32*)** @_ZNSt3__13mapINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPFvP6ObjectENS_4lessIS6_EENS4_INS_4pairIKS6_SA_EEEEEixERSE_(i32 10) - %26 = load void (%class.Object*)** %call12 + %l26 = load void (i32*)** %call12 ret i32 1 } -define (i32*)** @_ZNSt3__13mapINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPFvP6ObjectENS_4lessIS6_EENS4_INS_4pairIKS6_SA_EEEEEixERSE_(i32 %x) { +define void (i32*)** @_ZNSt3__13mapINS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEEPFvP6ObjectENS_4lessIS6_EENS4_INS_4pairIKS6_SA_EEEEEixERSE_(i32 %x) { entry: - %ret = inttoptr i32 0 to (i32*)** - ret (i32*)** %ret + %ret = inttoptr i32 0 to void (i32*)** + ret void (i32*)** %ret } ; [#uses=1] diff --git a/tests/cases/i24_mem_ta2.ll b/tests/cases/i24_mem_ta2.ll index e50014ca..550389fe 100644 --- a/tests/cases/i24_mem_ta2.ll +++ b/tests/cases/i24_mem_ta2.ll @@ -1,8 +1,8 @@ ; ModuleID = 'tests/hello_world.bc' -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" -target triple = "i386-pc-linux-gnu" +target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32" +target triple = "le32-unknown-nacl" -@.str = private unnamed_addr constant [15 x i8] c".%x.\0A\00", align 1 ; [#uses=1 type=[5 x i8]*] +@.str = private unnamed_addr constant [6 x i8] c".%x.\0A\00", align 1 ; [#uses=1 type=[5 x i8]*] define i32 @main() { entry: @@ -11,11 +11,11 @@ entry: %i24 = bitcast i32* %mem to i24* %load = load i24* %i24, align 4 %load32 = zext i24 %load to i32 - %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([5 x i8]* @.str, i32 0, i32 0), i32 %load32) + %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0), i32 %load32) %val_24 = trunc i32 4041265344 to i24 store i24 %val_24, i24* %i24, align 4 %load32b = load i32* %mem, align 4 - %call2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([5 x i8]* @.str, i32 0, i32 0), i32 %load32b) + %call2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([6 x i8]* @.str, i32 0, i32 0), i32 %load32b) ret i32 1 } diff --git a/tests/cases/i64toi8star.ll b/tests/cases/i64toi8star.ll index d4a39340..b2307449 100644 --- a/tests/cases/i64toi8star.ll +++ b/tests/cases/i64toi8star.ll @@ -25,8 +25,8 @@ entry: %retval = alloca i32 ; [#uses=2] %0 = alloca i32 ; [#uses=2] %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] - %5 = call i32 @PyLong_FromVoidPtr(i8* null) nounwind ; [#uses=0] - %13 = call i32 @PyLong_FromVoidPtr(i8* inttoptr (i64 1 to i8*)) nounwind ; [#uses=0] - %1 = call i32 bitcast (i32 (i8*)* @puts to i32 (i32*)*)(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ; [#uses=0] + %a5 = call i32 @PyLong_FromVoidPtr(i8* null) nounwind ; [#uses=0] + %a13 = call i32 @PyLong_FromVoidPtr(i8* inttoptr (i64 1 to i8*)) nounwind ; [#uses=0] + %a1 = call i32 @puts(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ; [#uses=0] ret i32 0 } diff --git a/tests/cases/inttoptr.ll b/tests/cases/inttoptr.ll index b0711672..c1b40a74 100644 --- a/tests/cases/inttoptr.ll +++ b/tests/cases/inttoptr.ll @@ -1,6 +1,6 @@ ; ModuleID = '/tmp/emscripten/tmp/src.cpp.o' -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" -target triple = "i386-pc-linux-gnu" +target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32" +target triple = "le32-unknown-nacl" @.str = private constant [14 x i8] c"hello, world!\00", align 1 ; [#uses=1] @@ -14,7 +14,7 @@ entry: %0 = alloca i32 ; [#uses=2] %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] %sz.i7 = inttoptr i32 64 to i32* ; [#uses=1 type=i32*] - store i32 184, i32* %sz.i7, align 8, !tbaa !1610 - %1 = call i32 bitcast (i32 (i8*)* @puts to i32 (i32*)*)(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ; [#uses=0] + store i32 184, i32* %sz.i7, align 8 + %1 = call i32 @puts(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ; [#uses=0] ret i32 0 } diff --git a/tests/cases/invokebitcast.ll b/tests/cases/invokebitcast.ll index ffb5803f..ec090b0d 100644 --- a/tests/cases/invokebitcast.ll +++ b/tests/cases/invokebitcast.ll @@ -1,7 +1,7 @@ ; ModuleID = '/dev/shm/tmp/src.cpp.o' ; Just test for compilation here -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-f128:128:128-n8:16:32" -target triple = "i386-pc-linux-gnu" +target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32" +target triple = "le32-unknown-nacl" %struct.CPU_Regs = type { [8 x %union.GenReg32] } %union.GenReg32 = type { [1 x i32] } @@ -16,7 +16,8 @@ entry: %0 = alloca i32 ; [#uses=2] %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] %1 = load i32* bitcast (i32* getelementptr inbounds (%struct.CPU_Regs* @cpu_regs, i32 0, i32 0, i32 1, i32 0, i32 0) to i32*), align 2 ; [#uses=1] - store i16 %1, i16* bitcast (%struct.CPU_Regs* @cpu_regs to i16*), align 2 + %s = trunc i32 %1 to i16 + store i16 %s, i16* bitcast (%struct.CPU_Regs* @cpu_regs to i16*), align 2 %2 = call i32 @puts(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ; [#uses=0] store i32 0, i32* %0, align 4 %3 = load i32* %0, align 4 ; [#uses=1] diff --git a/tests/cases/phicubed.ll b/tests/cases/phicubed.ll index a0799997..5fc3208b 100644 --- a/tests/cases/phicubed.ll +++ b/tests/cases/phicubed.ll @@ -1,4 +1,6 @@ ; ModuleID = '/dev/shm/tmp/src.cpp.o' +target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32" +target triple = "le32-unknown-nacl" %struct.worker_args = type { i32, %struct.worker_args* } diff --git a/tests/cases/phientryimplicit.ll b/tests/cases/phientryimplicit.ll index 8a510f43..b7b17add 100644 --- a/tests/cases/phientryimplicit.ll +++ b/tests/cases/phientryimplicit.ll @@ -1,6 +1,6 @@ ; ModuleID = 'tests/hello_world.bc' -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" -target triple = "i386-pc-linux-gnu" +target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32" +target triple = "le32-unknown-nacl" ; Phi nodes can refer to the entry. And the entry might be unnamed, and doesn't even have a consistent implicit name! @@ -9,35 +9,35 @@ target triple = "i386-pc-linux-gnu" ; [#uses=0] define i32 @main() { %retval = alloca i32, align 4 ; [#uses=1 type=i32*] - %16 = trunc i32 1 to i1 - br i1 %16, label %17, label %26, !dbg !1269853 ; [debug line = 3920:5] + %a16 = trunc i32 1 to i1 + br i1 %a16, label %L17, label %L26, !dbg !1269853 ; [debug line = 3920:5] -; <label>:17 ; preds = %1 - %25 = trunc i32 1 to i1 - br label %26 +L17: + %a25 = trunc i32 1 to i1 + br label %L26 -; <label>:26 ; preds = %17, %1 - %27 = phi i1 [ false, %1 ], [ %25, %17 ] ; [#uses=1 type=i1] +L26: + %a27 = phi i1 [ false, %1 ], [ %25, %L17 ] ; [#uses=1 type=i1] store i32 0, i32* %retval %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0 type=i32] - %cal2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0), i32 %27) ; make sure %27 is used + %cal2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0), i1 %a27) ; make sure %27 is used ret i32 1 } define i32 @main0() { %retval = alloca i32, align 4 ; [#uses=1 type=i32*] - %16 = trunc i32 1 to i1 - br i1 %16, label %17, label %26, !dbg !1269853 ; [debug line = 3920:5] + %a16 = trunc i32 1 to i1 + br i1 %a16, label %L17, label %L26, !dbg !1269853 ; [debug line = 3920:5] -; <label>:17 ; preds = %1 - %25 = trunc i32 1 to i1 - br label %26 +L17: + %a25 = trunc i32 1 to i1 + br label %L26 -; <label>:26 ; preds = %17, %1 - %27 = phi i1 [ false, %0 ], [ %25, %17 ] ; [#uses=1 type=i1] +L26: + %a27 = phi i1 [ false, %0 ], [ %25, %L17 ] ; [#uses=1 type=i1] store i32 0, i32* %retval %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0)) ; [#uses=0 type=i32] - %cal2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0), i32 %27) ; make sure %27 is used + %cal2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([15 x i8]* @.str, i32 0, i32 0), i1 %a27) ; make sure %27 is used ret i32 1 } diff --git a/tests/cases/phiself.ll b/tests/cases/phiself.ll index 81249799..0a06fcca 100644 --- a/tests/cases/phiself.ll +++ b/tests/cases/phiself.ll @@ -1,6 +1,6 @@ ; ModuleID = '/tmp/emscripten_temp/src.cpp.o' -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32-S128" -target triple = "i386-pc-linux-gnu" +target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32" +target triple = "le32-unknown-nacl" @.str = private unnamed_addr constant [7 x i8] c"cheez\0A\00", align 1 @.str1 = private unnamed_addr constant [6 x i8] c"*%d*\0A\00", align 1 diff --git a/tests/cases/ptrtoi64.ll b/tests/cases/ptrtoi64.ll index 01e466fe..5898f529 100644 --- a/tests/cases/ptrtoi64.ll +++ b/tests/cases/ptrtoi64.ll @@ -1,8 +1,8 @@ ; pointer to i64, then to i32 ; ModuleID = '/tmp/emscripten/tmp/src.cpp.o' -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" -target triple = "i386-pc-linux-gnu" +target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32" +target triple = "le32-unknown-nacl" @.str2 = private constant [9 x i8] c"*%d,%d*\0A\00", align 1 ; [#uses=1] @@ -18,10 +18,10 @@ entry: %0 = alloca i32 ; [#uses=2] %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] %sz.i7 = inttoptr i32 400 to i32* ; [#uses=1 type=i32*] - %10 = ptrtoint i32* %sz.i7 to i64, !dbg !8557 ; [#uses=1 type=i64] [debug line = 99:3] - %conv5 = trunc i64 %10 to i32, !dbg !8557 ; [#uses=1 type=i32] [debug line = 99:3] - %11 = ptrtoint i32* %sz.i7 to i8, !dbg !8557 ; [#uses=1 type=i64] [debug line = 99:3] - %conv6 = zext i8 %11 to i32, !dbg !8557 ; [#uses=1 type=i32] [debug line = 99:3] - %55 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @.str2, i32 0, i32 0), i32 %conv5, i32 %conv6) ; [#uses=0] + %a10 = ptrtoint i32* %sz.i7 to i64 + %conv5 = trunc i64 %a10 to i32 + %a11 = ptrtoint i32* %sz.i7 to i8 + %conv6 = zext i8 %a11 to i32 + %a55 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([9 x i8]* @.str2, i32 0, i32 0), i32 %conv5, i32 %conv6) ret i32 0 } diff --git a/tests/cases/sillybitcast.ll b/tests/cases/sillybitcast.ll index c5ca4f9a..50a54da9 100644 --- a/tests/cases/sillybitcast.ll +++ b/tests/cases/sillybitcast.ll @@ -1,6 +1,6 @@ ; ModuleID = '/tmp/emscripten/tmp/src.cpp.o' -target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" -target triple = "i386-pc-linux-gnu" +target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32" +target triple = "le32-unknown-nacl" @.str = private constant [14 x i8] c"hello, world!\00", align 1 ; [#uses=1] diff --git a/tests/cases/sillybitcast2.ll b/tests/cases/sillybitcast2.ll new file mode 100644 index 00000000..02cf8615 --- /dev/null +++ b/tests/cases/sillybitcast2.ll @@ -0,0 +1,35 @@ +; ModuleID = '/tmp/emscripten/tmp/src.cpp.o' +target datalayout = "e-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-p:32:32:32-v128:32:32" +target triple = "le32-unknown-nacl" + +@.str = private constant [14 x i8] c"hello, world!\00", align 1 ; [#uses=1] + +; [#uses=2] +define void @"_Z5hellov"() { +entry: + %0 = call i32 bitcast (i32 (i32*)* @puts to i32 (i8*)*)(i8* getelementptr inbounds ([14 x i8]* @.str, i32 0, i32 0)) ; [#uses=0] + br label %return + +return: ; preds = %entry + ret void +} + +; [#uses=1] +declare i32 @puts(i32*) + +; [#uses=0] +define i32 @main() { +entry: + %retval = alloca i32 ; [#uses=2] + %0 = alloca i32 ; [#uses=2] + %"alloca point" = bitcast i32 0 to i32 ; [#uses=0] + call void @"_Z5hellov"() + store i32 0, i32* %0, align 4 + %1 = load i32* %0, align 4 ; [#uses=1] + store i32 %1, i32* %retval, align 4 + br label %return + +return: ; preds = %entry + %retval1 = load i32* %retval ; [#uses=1] + ret i32 %retval1 +} diff --git a/tests/cases/unaligneddouble.ll b/tests/cases/unaligneddouble.ll index 22b92741..e4067831 100644 --- a/tests/cases/unaligneddouble.ll +++ b/tests/cases/unaligneddouble.ll @@ -10,7 +10,7 @@ entry: %retval = alloca i32, align 4 ; [#uses=1 type=i32*] %doub = alloca double, align 4 store i32 0, i32* %retval - %0 = bitcast double* %doub to i32 + %0 = ptrtoint double* %doub to i32 %1 = uitofp i32 %0 to double store double %1, double* %doub, align 1 store double %1, double* %doub, align 2 diff --git a/tests/runner.py b/tests/runner.py index 8a5e1129..37e307e9 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -328,7 +328,10 @@ process(sys.argv[1]) os.makedirs(ret) return ret - def get_library(self, name, generated_libs, configure=['sh', './configure'], configure_args=[], make=['make'], make_args=['-j', '2'], cache=True, env_init={}, cache_name_extra='', native=False): + def get_library(self, name, generated_libs, configure=['sh', './configure'], configure_args=[], make=['make'], make_args='help', cache=True, env_init={}, cache_name_extra='', native=False): + if make_args == 'help': + make_args = ['-j', str(multiprocessing.cpu_count())] + build_dir = self.get_build_dir() output_dir = self.get_dir() diff --git a/tests/test_benchmark.py b/tests/test_benchmark.py index 63e0041f..2f4d26fd 100644 --- a/tests/test_benchmark.py +++ b/tests/test_benchmark.py @@ -14,6 +14,109 @@ DEFAULT_ARG = '4' TEST_REPS = 2 +CORE_BENCHMARKS = True # core benchmarks vs full regression suite + +class Benchmarker: + def __init__(self, name): + self.name = name + + def bench(self, args, output_parser=None): + self.times = [] + for i in range(TEST_REPS): + start = time.time() + output = self.run(args) + if not output_parser: + curr = time.time()-start + else: + curr = output_parser(output) + self.times.append(curr) + + def display(self, baseline=None): + if baseline == self: baseline = None + mean = sum(self.times)/len(self.times) + squared_times = map(lambda x: x*x, self.times) + mean_of_squared = sum(squared_times)/len(self.times) + std = math.sqrt(mean_of_squared - mean*mean) + sorted_times = self.times[:] + sorted_times.sort() + median = sum(sorted_times[len(sorted_times)/2 - 1:len(sorted_times)/2 + 1])/2 + + print ' %10s: mean: %4.3f (+-%4.3f) secs median: %4.3f range: %4.3f-%4.3f (noise: %4.3f%%) (%d runs)' % (self.name, mean, std, median, min(self.times), max(self.times), 100*std/mean, TEST_REPS), + + if baseline: + mean_baseline = sum(baseline.times)/len(baseline.times) + final = mean / mean_baseline + print ' Relative: %.2f X slower' % final + else: + print + +class NativeBenchmarker(Benchmarker): + def __init__(self, name, cc, cxx): + self.name = name + self.cc = cc + self.cxx = cxx + + def build(self, parent, filename, args, shared_args, emcc_args, native_args, native_exec): + self.parent = parent + if not native_exec: + compiler = self.cxx if filename.endswith('cpp') else self.cc + process = Popen([compiler, '-O2', '-fno-math-errno', filename, '-o', filename+'.native'] + shared_args + native_args, stdout=PIPE, stderr=parent.stderr_redirect) + output = process.communicate() + if process.returncode is not 0: + print >> sys.stderr, "Building native executable with command '%s' failed with a return code %d!" % (' '.join([compiler, '-O2', filename, '-o', filename+'.native']), process.returncode) + print "Output: " + output[0] + else: + print '(using clang)' + shutil.copyfile(native_exec, filename + '.native') + shutil.copymode(native_exec, filename + '.native') + self.filename = filename + + def run(self, args): + process = Popen([self.filename+'.native'] + args, stdout=PIPE, stderr=PIPE) + return process.communicate()[0] + +class JSBenchmarker(Benchmarker): + def __init__(self, name, engine, extra_args=[]): + self.name = name + self.engine = engine + self.extra_args = extra_args + + def build(self, parent, filename, args, shared_args, emcc_args, native_args, native_exec): + self.filename = filename + + open('hardcode.py', 'w').write(''' +def process(filename): + js = open(filename).read() + replaced = js.replace("run();", "run(%s.concat(Module[\\"arguments\\"]));") + assert js != replaced + open(filename, 'w').write(replaced) +import sys +process(sys.argv[1]) +''' % str(args[:-1]) # do not hardcode in the last argument, the default arg +) + + try_delete(filename + '.js') + output = Popen([PYTHON, EMCC, filename, #'-O3', + '-O2', '-s', 'DOUBLE_MODE=0', '-s', 'PRECISE_I64_MATH=0', + '--memory-init-file', '0', '--js-transform', 'python hardcode.py', + '-s', 'TOTAL_MEMORY=128*1024*1024', + #'--closure', '1', + #'-g', + '-o', filename + '.js'] + shared_args + emcc_args + self.extra_args, stdout=PIPE, stderr=PIPE).communicate() + assert os.path.exists(filename + '.js'), 'Failed to compile file: ' + output[0] + + def run(self, args): + return run_js(self.filename + '.js', engine=self.engine, args=args, stderr=PIPE, full_output=True) + +# Benchmarkers +benchmarkers = [ + NativeBenchmarker('clang', CLANG_CC, CLANG), + NativeBenchmarker('gcc', 'gcc', 'g++'), + JSBenchmarker('sm-f32', SPIDERMONKEY_ENGINE, ['-s', 'PRECISE_F32=2']), + JSBenchmarker('sm', SPIDERMONKEY_ENGINE), + JSBenchmarker('v8', V8_ENGINE) +] + class benchmark(RunnerCore): save_dir = True @@ -54,41 +157,6 @@ class benchmark(RunnerCore): JS_ENGINE = Building.JS_ENGINE_OVERRIDE if Building.JS_ENGINE_OVERRIDE is not None else JS_ENGINES[0] print 'Benchmarking JS engine: %s' % JS_ENGINE - def print_stats(self, times, native_times, last=False, reps=TEST_REPS): - if reps == 0: - print '(no reps)' - return - mean = sum(times)/len(times) - squared_times = map(lambda x: x*x, times) - mean_of_squared = sum(squared_times)/len(times) - std = math.sqrt(mean_of_squared - mean*mean) - sorted_times = times[:] - sorted_times.sort() - median = sum(sorted_times[len(sorted_times)/2 - 1:len(sorted_times)/2 + 1])/2 - - mean_native = sum(native_times)/len(native_times) - squared_native_times = map(lambda x: x*x, native_times) - mean_of_squared_native = sum(squared_native_times)/len(native_times) - std_native = math.sqrt(mean_of_squared_native - mean_native*mean_native) - sorted_native_times = native_times[:] - sorted_native_times.sort() - median_native = sum(sorted_native_times[len(sorted_native_times)/2 - 1:len(sorted_native_times)/2 + 1])/2 - - final = mean / mean_native - - if last: - norm = 0 - for i in range(len(times)): - norm += times[i]/native_times[i] - norm /= len(times) - print - print ' JavaScript: %.3f Native: %.3f Ratio: %.3f Normalized ratio: %.3f' % (mean, mean_native, final, norm) - return - - print - print ' JavaScript: mean: %.3f (+-%.3f) secs median: %.3f range: %.3f-%.3f (noise: %3.3f%%) (%d runs)' % (mean, std, median, min(times), max(times), 100*std/mean, reps) - print ' Native : mean: %.3f (+-%.3f) secs median: %.3f range: %.3f-%.3f (noise: %3.3f%%) JS is %.2f X slower' % (mean_native, std_native, median_native, min(native_times), max(native_times), 100*std_native/mean_native, final) - def do_benchmark(self, name, src, expected_output='FAIL', args=[], emcc_args=[], native_args=[], shared_args=[], force_c=False, reps=TEST_REPS, native_exec=None, output_parser=None, args_processor=None): args = args or [DEFAULT_ARG] if args_processor: args = args_processor(args) @@ -98,68 +166,12 @@ class benchmark(RunnerCore): f = open(filename, 'w') f.write(src) f.close() - final_filename = os.path.join(dirname, name + '.js') - open('hardcode.py', 'w').write(''' -def process(filename): - js = open(filename).read() - replaced = js.replace("run();", "run(%s.concat(Module[\\"arguments\\"]));") - assert js != replaced - open(filename, 'w').write(replaced) -import sys -process(sys.argv[1]) -''' % str(args[:-1]) # do not hardcode in the last argument, the default arg -) - - try_delete(final_filename) - output = Popen([PYTHON, EMCC, filename, #'-O3', - '-O2', '-s', 'DOUBLE_MODE=0', '-s', 'PRECISE_I64_MATH=0', - '--memory-init-file', '0', '--js-transform', 'python hardcode.py', - '-s', 'TOTAL_MEMORY=128*1024*1024', - '--closure', '1', - #'-s', 'PRECISE_F32=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] - - # Run JS - times = [] - for i in range(reps): - start = time.time() - js_output = run_js(final_filename, engine=JS_ENGINE, args=args, stderr=PIPE, full_output=True) - - if i == 0 and 'uccessfully compiled asm.js code' in js_output: - if 'asm.js link error' not in js_output: - print "[%s was asm.js'ified]" % name - if not output_parser: - curr = time.time()-start - else: - curr = output_parser(js_output) - times.append(curr) - if i == 0: - # Sanity check on output - self.assertContained(expected_output, js_output) - - # Run natively - if not native_exec: - self.build_native(filename, shared_args + native_args) - else: - shutil.copyfile(native_exec, filename + '.native') - shutil.copymode(native_exec, filename + '.native') - native_times = [] - for i in range(reps): - start = time.time() - native_output = self.run_native(filename, args) - if i == 0: - # Sanity check on output - self.assertContained(expected_output, native_output) - if not output_parser: - curr = time.time()-start - else: - curr = output_parser(native_output) - native_times.append(curr) - - self.print_stats(times, native_times, reps=reps) + print + for b in benchmarkers: + b.build(self, filename, args, shared_args, emcc_args, native_args, native_exec) + b.bench(args, output_parser) + b.display(benchmarkers[0]) def test_primes(self): src = r''' @@ -402,9 +414,11 @@ process(sys.argv[1]) self.fasta('fasta_float', 'float') def test_fasta_double(self): + if CORE_BENCHMARKS: return self.fasta('fasta_double', 'double') def test_fasta_double_full(self): + if CORE_BENCHMARKS: return self.fasta('fasta_double_full', 'double', emcc_args=['-s', 'DOUBLE_MODE=1']) def test_skinning(self): @@ -412,10 +426,12 @@ process(sys.argv[1]) self.do_benchmark('skinning', src, 'blah=0.000000') def test_life(self): + if CORE_BENCHMARKS: return src = open(path_from_root('tests', 'life.c'), 'r').read() self.do_benchmark('life', src, '''--------------------------------''', shared_args=['-std=c99'], force_c=True) def test_linpack_double(self): + if CORE_BENCHMARKS: return def output_parser(output): return 100.0/float(re.search('Unrolled Double Precision +([\d\.]+) Mflops', output).group(1)) self.do_benchmark('linpack_double', open(path_from_root('tests', 'linpack.c')).read(), '''Unrolled Double Precision''', force_c=True, output_parser=output_parser) diff --git a/tests/test_core.py b/tests/test_core.py index 9b072b90..862beb8b 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -351,6 +351,9 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co } ''' self.do_run(src, '*4903566027370624, 153236438355333*') + + if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + code = open(os.path.join(self.get_dir(), 'src.cpp.o.js')).read() assert 'goog.math.Long' not in code, 'i64 precise math should not have been included if not actually used' @@ -459,6 +462,8 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co self.do_run_from_file(src, output) def test_float32_precise(self): + if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + Settings.PRECISE_F32 = 1 test_path = path_from_root('tests', 'core', 'test_float32_precise') @@ -1086,36 +1091,48 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co self.do_run_from_file(src, output) def test_longjmp(self): + if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + test_path = path_from_root('tests', 'core', 'test_longjmp') src, output = (test_path + s for s in ('.in', '.out')) self.do_run_from_file(src, output) def test_longjmp2(self): + if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + test_path = path_from_root('tests', 'core', 'test_longjmp2') src, output = (test_path + s for s in ('.in', '.out')) self.do_run_from_file(src, output) def test_longjmp3(self): + if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + test_path = path_from_root('tests', 'core', 'test_longjmp3') src, output = (test_path + s for s in ('.in', '.out')) self.do_run_from_file(src, output) def test_longjmp4(self): + if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + test_path = path_from_root('tests', 'core', 'test_longjmp4') src, output = (test_path + s for s in ('.in', '.out')) self.do_run_from_file(src, output) def test_longjmp_funcptr(self): + if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + test_path = path_from_root('tests', 'core', 'test_longjmp_funcptr') src, output = (test_path + s for s in ('.in', '.out')) self.do_run_from_file(src, output) def test_longjmp_repeat(self): + if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + Settings.MAX_SETJMPS = 1 test_path = path_from_root('tests', 'core', 'test_longjmp_repeat') @@ -1124,6 +1141,8 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co self.do_run_from_file(src, output) def test_longjmp_stacked(self): + if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + test_path = path_from_root('tests', 'core', 'test_longjmp_stacked') src, output = (test_path + s for s in ('.in', '.out')) @@ -1131,12 +1150,16 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co def test_longjmp_exc(self): + if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + test_path = path_from_root('tests', 'core', 'test_longjmp_exc') src, output = (test_path + s for s in ('.in', '.out')) self.do_run_from_file(src, output) def test_setjmp_many(self): + if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + src = r''' #include <stdio.h> #include <setjmp.h> @@ -1155,6 +1178,7 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co def test_exceptions(self): if Settings.QUANTUM_SIZE == 1: return self.skip("we don't support libcxx in q1") if self.emcc_args is None: return self.skip('need emcc to add in libcxx properly') + if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') Settings.EXCEPTION_DEBUG = 1 @@ -1243,6 +1267,7 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co def test_exception_2(self): if self.emcc_args is None: return self.skip('need emcc to add in libcxx properly') + if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') Settings.DISABLE_EXCEPTION_CATCHING = 0 test_path = path_from_root('tests', 'core', 'test_exception_2') @@ -1251,6 +1276,8 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co self.do_run_from_file(src, output) def test_white_list_exception(self): + if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + Settings.DISABLE_EXCEPTION_CATCHING = 2 Settings.EXCEPTION_CATCHING_WHITELIST = ["__Z12somefunctionv"] Settings.INLINING_LIMIT = 50 # otherwise it is inlined and not identified @@ -1265,6 +1292,7 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co def test_uncaught_exception(self): if self.emcc_args is None: return self.skip('no libcxx inclusion without emcc') + if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') Settings.DISABLE_EXCEPTION_CATCHING = 0 @@ -1303,6 +1331,8 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co self.do_run(src, 'success') def test_typed_exceptions(self): + if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + Settings.DISABLE_EXCEPTION_CATCHING = 0 Settings.SAFE_HEAP = 0 # Throwing null will cause an ignorable null pointer access. src = open(path_from_root('tests', 'exceptions', 'typed.cpp'), 'r').read() @@ -1310,6 +1340,8 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co self.do_run(src, expected) def test_multiexception(self): + if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') + Settings.DISABLE_EXCEPTION_CATCHING = 0 test_path = path_from_root('tests', 'core', 'test_multiexception') @@ -1319,6 +1351,7 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co def test_std_exception(self): if self.emcc_args is None: return self.skip('requires emcc') + if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('todo in fastcomp') Settings.DISABLE_EXCEPTION_CATCHING = 0 self.emcc_args += ['-s', 'SAFE_HEAP=0'] @@ -1844,12 +1877,9 @@ class T(RunnerCore): # Short name, to make it more fun to use manually on the co self.do_run_from_file(src, output, [], lambda x, err: x.replace('\n', '*')) - def test_float_h(self): - process = Popen([PYTHON, EMCC, path_from_root('tests', 'float+.c')], stdout=PIPE, stderr=PIPE) - process.communicate() - assert process.returncode is 0, 'float.h should agree with our system' - def test_llvm_used(self): + if os.environ.get('EMCC_FAST_COMPILER') == '1': return self.skip('pnacl kills llvm_used') + Building.L |