Optimize builtin abs for integers (#420)

This commit is contained in:
Max Graey 2019-01-15 19:22:24 +02:00 committed by Daniel Wirtz
parent 2aa5c437c7
commit 72dc26e255
3 changed files with 857 additions and 845 deletions

View File

@ -640,55 +640,80 @@ export function compileCall(
case TypeKind.I8: case TypeKind.I8:
case TypeKind.I16: case TypeKind.I16:
case TypeKind.I32: { case TypeKind.I32: {
let currentFunction = compiler.currentFunction;
// possibly overflows, e.g. abs<i8>(-128) == 128 // possibly overflows, e.g. abs<i8>(-128) == 128
let tempLocal = compiler.currentFunction.getAndFreeTempLocal(Type.i32, false); let tempLocal1 = currentFunction.getTempLocal(Type.i32, false);
ret = module.createSelect( // x > 0 ? x : 0-x let tempLocalIndex2 = currentFunction.getAndFreeTempLocal(Type.i32, false).index;
module.createTeeLocal(tempLocal.index, arg0), let tempLocalIndex1 = tempLocal1.index;
module.createBinary(BinaryOp.SubI32, // ifFalse
module.createI32(0), // (x + (x >> 31)) ^ (x >> 31)
module.createGetLocal(tempLocal.index, NativeType.I32) ret = module.createBinary(BinaryOp.XorI32,
module.createBinary(BinaryOp.AddI32,
module.createTeeLocal(
tempLocalIndex2,
module.createBinary(BinaryOp.ShrI32,
module.createTeeLocal(tempLocalIndex1, arg0),
module.createI32(31)
)
),
module.createGetLocal(tempLocalIndex1, NativeType.I32)
), ),
module.createBinary(BinaryOp.GtI32, module.createGetLocal(tempLocalIndex2, NativeType.I32)
module.createGetLocal(tempLocal.index, NativeType.I32),
module.createI32(0)
)
); );
currentFunction.freeTempLocal(tempLocal1);
break; break;
} }
case TypeKind.ISIZE: { case TypeKind.ISIZE: {
let tempLocal = compiler.currentFunction.getAndFreeTempLocal(compiler.options.usizeType, false); let options = compiler.options;
ret = module.createSelect( let currentFunction = compiler.currentFunction;
module.createTeeLocal(tempLocal.index, arg0), let wasm64 = options.isWasm64;
module.createBinary(
compiler.options.isWasm64 let tempLocal1 = currentFunction.getTempLocal(options.usizeType, false);
? BinaryOp.SubI64 let tempLocalIndex2 = currentFunction.getAndFreeTempLocal(options.usizeType, false).index;
: BinaryOp.SubI32, let tempLocalIndex1 = tempLocal1.index;
compiler.options.usizeType.toNativeZero(module),
module.createGetLocal(tempLocal.index, compiler.options.nativeSizeType) ret = module.createBinary(wasm64 ? BinaryOp.XorI64 : BinaryOp.XorI32,
module.createBinary(wasm64 ? BinaryOp.AddI64 : BinaryOp.AddI32,
module.createTeeLocal(
tempLocalIndex2,
module.createBinary(wasm64 ? BinaryOp.ShrI64 : BinaryOp.ShrI32,
module.createTeeLocal(tempLocalIndex1, arg0),
wasm64 ? module.createI64(63) : module.createI32(31)
)
),
module.createGetLocal(tempLocalIndex1, options.nativeSizeType)
), ),
module.createBinary( module.createGetLocal(tempLocalIndex2, options.nativeSizeType)
compiler.options.isWasm64
? BinaryOp.GtI64
: BinaryOp.GtI32,
module.createGetLocal(tempLocal.index, compiler.options.nativeSizeType),
compiler.options.usizeType.toNativeZero(module)
)
); );
currentFunction.freeTempLocal(tempLocal1);
break; break;
} }
case TypeKind.I64: { case TypeKind.I64: {
let tempLocal = compiler.currentFunction.getAndFreeTempLocal(Type.i64, false); let currentFunction = compiler.currentFunction;
ret = module.createSelect(
module.createTeeLocal(tempLocal.index, arg0), let tempLocal1 = currentFunction.getTempLocal(Type.i64, false);
module.createBinary(BinaryOp.SubI64, let tempLocalIndex2 = currentFunction.getAndFreeTempLocal(Type.i64, false).index;
module.createI64(0, 0), let tempLocalIndex1 = tempLocal1.index;
module.createGetLocal(tempLocal.index, NativeType.I64),
// (x + (x >> 63)) ^ (x >> 63)
ret = module.createBinary(BinaryOp.XorI64,
module.createBinary(BinaryOp.AddI64,
module.createTeeLocal(
tempLocalIndex2,
module.createBinary(BinaryOp.ShrI64,
module.createTeeLocal(tempLocalIndex1, arg0),
module.createI64(63)
)
),
module.createGetLocal(tempLocalIndex1, NativeType.I64)
), ),
module.createBinary(BinaryOp.GtI64, module.createGetLocal(tempLocalIndex2, NativeType.I64)
module.createGetLocal(tempLocal.index, NativeType.I64),
module.createI64(0, 0)
)
); );
currentFunction.freeTempLocal(tempLocal1);
break; break;
} }
case TypeKind.USIZE: { case TypeKind.USIZE: {

View File

@ -318,13 +318,13 @@
drop drop
i32.const -42 i32.const -42
tee_local $0 tee_local $0
i32.const 0 i32.const 31
i32.shr_s
tee_local $1
get_local $0 get_local $0
i32.sub i32.add
get_local $0 get_local $1
i32.const 0 i32.xor
i32.gt_s
select
drop drop
i32.const 1 i32.const 1
tee_local $0 tee_local $0
@ -363,13 +363,13 @@
set_global $builtins/i set_global $builtins/i
i32.const -42 i32.const -42
tee_local $0 tee_local $0
i32.const 0 i32.const 31
i32.shr_s
tee_local $1
get_local $0 get_local $0
i32.sub i32.add
get_local $0 get_local $1
i32.const 0 i32.xor
i32.gt_s
select
set_global $builtins/i set_global $builtins/i
get_global $builtins/i get_global $builtins/i
i32.const 42 i32.const 42
@ -444,13 +444,13 @@
drop drop
i64.const -42 i64.const -42
tee_local $2 tee_local $2
i64.const 0 i64.const 63
i64.shr_s
tee_local $3
get_local $2 get_local $2
i64.sub i64.add
get_local $2 get_local $3
i64.const 0 i64.xor
i64.gt_s
select
drop drop
i64.const 1 i64.const 1
i64.clz i64.clz
@ -471,13 +471,13 @@
set_global $builtins/I set_global $builtins/I
i64.const -42 i64.const -42
tee_local $2 tee_local $2
i64.const 0 i64.const 63
i64.shr_s
tee_local $3
get_local $2 get_local $2
i64.sub i64.add
get_local $2 get_local $3
i64.const 0 i64.xor
i64.gt_s
select
set_global $builtins/I set_global $builtins/I
get_global $builtins/I get_global $builtins/I
i64.const 42 i64.const 42

File diff suppressed because it is too large Load Diff