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.I16:
case TypeKind.I32: {
let currentFunction = compiler.currentFunction;
// possibly overflows, e.g. abs<i8>(-128) == 128
let tempLocal = compiler.currentFunction.getAndFreeTempLocal(Type.i32, false);
ret = module.createSelect( // x > 0 ? x : 0-x
module.createTeeLocal(tempLocal.index, arg0),
module.createBinary(BinaryOp.SubI32, // ifFalse
module.createI32(0),
module.createGetLocal(tempLocal.index, NativeType.I32)
let tempLocal1 = currentFunction.getTempLocal(Type.i32, false);
let tempLocalIndex2 = currentFunction.getAndFreeTempLocal(Type.i32, false).index;
let tempLocalIndex1 = tempLocal1.index;
// (x + (x >> 31)) ^ (x >> 31)
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(tempLocal.index, NativeType.I32),
module.createI32(0)
)
module.createGetLocal(tempLocalIndex2, NativeType.I32)
);
currentFunction.freeTempLocal(tempLocal1);
break;
}
case TypeKind.ISIZE: {
let tempLocal = compiler.currentFunction.getAndFreeTempLocal(compiler.options.usizeType, false);
ret = module.createSelect(
module.createTeeLocal(tempLocal.index, arg0),
module.createBinary(
compiler.options.isWasm64
? BinaryOp.SubI64
: BinaryOp.SubI32,
compiler.options.usizeType.toNativeZero(module),
module.createGetLocal(tempLocal.index, compiler.options.nativeSizeType)
let options = compiler.options;
let currentFunction = compiler.currentFunction;
let wasm64 = options.isWasm64;
let tempLocal1 = currentFunction.getTempLocal(options.usizeType, false);
let tempLocalIndex2 = currentFunction.getAndFreeTempLocal(options.usizeType, false).index;
let tempLocalIndex1 = tempLocal1.index;
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(
compiler.options.isWasm64
? BinaryOp.GtI64
: BinaryOp.GtI32,
module.createGetLocal(tempLocal.index, compiler.options.nativeSizeType),
compiler.options.usizeType.toNativeZero(module)
)
module.createGetLocal(tempLocalIndex2, options.nativeSizeType)
);
currentFunction.freeTempLocal(tempLocal1);
break;
}
case TypeKind.I64: {
let tempLocal = compiler.currentFunction.getAndFreeTempLocal(Type.i64, false);
ret = module.createSelect(
module.createTeeLocal(tempLocal.index, arg0),
module.createBinary(BinaryOp.SubI64,
module.createI64(0, 0),
module.createGetLocal(tempLocal.index, NativeType.I64),
let currentFunction = compiler.currentFunction;
let tempLocal1 = currentFunction.getTempLocal(Type.i64, false);
let tempLocalIndex2 = currentFunction.getAndFreeTempLocal(Type.i64, false).index;
let tempLocalIndex1 = tempLocal1.index;
// (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(tempLocal.index, NativeType.I64),
module.createI64(0, 0)
)
module.createGetLocal(tempLocalIndex2, NativeType.I64)
);
currentFunction.freeTempLocal(tempLocal1);
break;
}
case TypeKind.USIZE: {

View File

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

File diff suppressed because it is too large Load Diff