From 6378f57b30f1141850ef7c260972ae109450b023 Mon Sep 17 00:00:00 2001 From: bbudge Date: Thu, 6 Aug 2015 13:24:45 -0700 Subject: [PATCH] V8: Add SIMD functions for Phase 1. Float32x4: abs, neg, sqrt, reciprocalApproximation, reciprocalSqrtApproximation, add, sub, mul, div, min, max, minNum, maxNum, lessThan, lessThanOrEqual, greaterThan, greaterThanOrEqual, equal, notEqual, select, swizzle, shuffle, fromInt32x4, fromInt32x4Bits, fromInt16x8Bits, fromInt8x16Bits. Int32x4: neg, add, sub, mul, min, max, and, or, xor, not, shiftLeftByScalar, shiftRightLogicalByScalar, shiftRightArithmeticByScalar, lessThan, lessThanOrEqual, greaterThan, greaterThanOrEqual, equal, notEqual, select, swizzle, shuffle, fromFloat32x4, fromFloat32x4Bits, fromInt16x8Bits, fromInt8x16Bits. Int16x8: neg, add, sub, mul, min, max, and, or, xor, not, shiftLeftByScalar, shiftRightLogicalByScalar, shiftRightArithmeticByScalar, lessThan, lessThanOrEqual, greaterThan, greaterThanOrEqual, equal, notEqual, select, swizzle, shuffle, fromFloat32x4Bits, fromInt32x4Bits, fromInt8x16Bits. Int8x16: neg, add, sub, mul, min, max, and, or, xor, not, shiftLeftByScalar, shiftRightLogicalByScalar, shiftRightArithmeticByScalar, lessThan, lessThanOrEqual, greaterThan, greaterThanOrEqual, equal, notEqual, select, swizzle, shuffle, fromFloat32x4Bits, fromInt32x4Bits, fromInt16x8Bitss. Bool32x4, Bool16x8, Bool8x16: and, or, not, anyTrue, allTrue, select, swizzle, shuffle. I might have forgotten a few. LOG=N BUG=v8:4124 Review URL: https://codereview.chromium.org/1230343003 Cr-Commit-Position: refs/heads/master@{#30051} --- src/harmony-simd.js | 439 ++++++++++++++++++++++-- src/messages.js | 30 +- src/objects.cc | 8 + src/objects.h | 2 + src/runtime/runtime-simd.cc | 789 ++++++++++++++++++++++++++++++++++++++------ src/runtime/runtime.h | 208 ++++++++++-- 6 files changed, 1302 insertions(+), 174 deletions(-) diff --git a/src/harmony-simd.js b/src/harmony-simd.js index 5119adc..3cc18c2 100644 --- a/src/harmony-simd.js +++ b/src/harmony-simd.js @@ -13,21 +13,33 @@ var GlobalSIMD = global.SIMD; -macro SIMD_TYPES(FUNCTION) +macro SIMD_FLOAT_TYPES(FUNCTION) FUNCTION(Float32x4, float32x4, 4) +endmacro + +macro SIMD_INT_TYPES(FUNCTION) FUNCTION(Int32x4, int32x4, 4) -FUNCTION(Bool32x4, bool32x4, 4) FUNCTION(Int16x8, int16x8, 8) -FUNCTION(Bool16x8, bool16x8, 8) FUNCTION(Int8x16, int8x16, 16) +endmacro + +macro SIMD_BOOL_TYPES(FUNCTION) +FUNCTION(Bool32x4, bool32x4, 4) +FUNCTION(Bool16x8, bool16x8, 8) FUNCTION(Bool8x16, bool8x16, 16) endmacro +macro SIMD_ALL_TYPES(FUNCTION) +SIMD_FLOAT_TYPES(FUNCTION) +SIMD_INT_TYPES(FUNCTION) +SIMD_BOOL_TYPES(FUNCTION) +endmacro + macro DECLARE_GLOBALS(NAME, TYPE, LANES) var GlobalNAME = GlobalSIMD.NAME; endmacro -SIMD_TYPES(DECLARE_GLOBALS) +SIMD_ALL_TYPES(DECLARE_GLOBALS) macro DECLARE_COMMON_FUNCTIONS(NAME, TYPE, LANES) function NAMECheckJS(a) { @@ -73,35 +85,46 @@ function NAMEValueOf() { function NAMEExtractLaneJS(instance, lane) { return %NAMEExtractLane(instance, lane); } -endmacro -SIMD_TYPES(DECLARE_COMMON_FUNCTIONS) +function NAMEEqualJS(a, b) { + return %NAMEEqual(a, b); +} -macro SIMD_NUMERIC_TYPES(FUNCTION) -FUNCTION(Float32x4) -FUNCTION(Int32x4) -FUNCTION(Int16x8) -FUNCTION(Int8x16) +function NAMENotEqualJS(a, b) { + return %NAMENotEqual(a, b); +} endmacro -macro DECLARE_NUMERIC_FUNCTIONS(NAME) -function NAMEReplaceLaneJS(instance, lane, value) { - return %NAMEReplaceLane(instance, lane, TO_NUMBER_INLINE(value)); +SIMD_ALL_TYPES(DECLARE_COMMON_FUNCTIONS) + +macro DECLARE_INT_FUNCTIONS(NAME, TYPE, LANES) +function NAMEShiftLeftByScalarJS(instance, shift) { + return %NAMEShiftLeftByScalar(instance, shift); } -endmacro -SIMD_NUMERIC_TYPES(DECLARE_NUMERIC_FUNCTIONS) +function NAMEShiftRightLogicalByScalarJS(instance, shift) { + return %NAMEShiftRightLogicalByScalar(instance, shift); +} -macro SIMD_BOOL_TYPES(FUNCTION) -FUNCTION(Bool32x4) -FUNCTION(Bool16x8) -FUNCTION(Bool8x16) +function NAMEShiftRightArithmeticByScalarJS(instance, shift) { + return %NAMEShiftRightArithmeticByScalar(instance, shift); +} endmacro -macro DECLARE_BOOL_FUNCTIONS(NAME) +SIMD_INT_TYPES(DECLARE_INT_FUNCTIONS) + +macro DECLARE_BOOL_FUNCTIONS(NAME, TYPE, LANES) function NAMEReplaceLaneJS(instance, lane, value) { return %NAMEReplaceLane(instance, lane, value); } + +function NAMEAnyTrueJS(s) { + return %NAMEAnyTrue(s); +} + +function NAMEAllTrueJS(s) { + return %NAMEAllTrue(s); +} endmacro SIMD_BOOL_TYPES(DECLARE_BOOL_FUNCTIONS) @@ -119,6 +142,124 @@ endmacro SIMD_UNSIGNED_INT_TYPES(DECLARE_UNSIGNED_INT_FUNCTIONS) +macro SIMD_NUMERIC_TYPES(FUNCTION) +SIMD_FLOAT_TYPES(FUNCTION) +SIMD_INT_TYPES(FUNCTION) +endmacro + +macro DECLARE_NUMERIC_FUNCTIONS(NAME, TYPE, LANES) +function NAMEReplaceLaneJS(instance, lane, value) { + return %NAMEReplaceLane(instance, lane, TO_NUMBER_INLINE(value)); +} + +function NAMESelectJS(selector, a, b) { + return %NAMESelect(selector, a, b); +} + +function NAMENegJS(a) { + return %NAMENeg(a); +} + +function NAMEAddJS(a, b) { + return %NAMEAdd(a, b); +} + +function NAMESubJS(a, b) { + return %NAMESub(a, b); +} + +function NAMEMulJS(a, b) { + return %NAMEMul(a, b); +} + +function NAMEMinJS(a, b) { + return %NAMEMin(a, b); +} + +function NAMEMaxJS(a, b) { + return %NAMEMax(a, b); +} + +function NAMELessThanJS(a, b) { + return %NAMELessThan(a, b); +} + +function NAMELessThanOrEqualJS(a, b) { + return %NAMELessThanOrEqual(a, b); +} + +function NAMEGreaterThanJS(a, b) { + return %NAMEGreaterThan(a, b); +} + +function NAMEGreaterThanOrEqualJS(a, b) { + return %NAMEGreaterThanOrEqual(a, b); +} +endmacro + +SIMD_NUMERIC_TYPES(DECLARE_NUMERIC_FUNCTIONS) + +macro SIMD_LOGICAL_TYPES(FUNCTION) +SIMD_INT_TYPES(FUNCTION) +SIMD_BOOL_TYPES(FUNCTION) +endmacro + +macro DECLARE_LOGICAL_FUNCTIONS(NAME, TYPE, LANES) +function NAMEAndJS(a, b) { + return %NAMEAnd(a, b); +} + +function NAMEOrJS(a, b) { + return %NAMEOr(a, b); +} + +function NAMEXorJS(a, b) { + return %NAMEXor(a, b); +} + +function NAMENotJS(a) { + return %NAMENot(a); +} +endmacro + +SIMD_LOGICAL_TYPES(DECLARE_LOGICAL_FUNCTIONS) + +macro SIMD_FROM_TYPES(FUNCTION) +FUNCTION(Float32x4, Int32x4) +FUNCTION(Int32x4, Float32x4) +endmacro + +macro DECLARE_FROM_FUNCTIONS(TO, FROM) +function TOFromFROMJS(a) { + return %TOFromFROM(a); +} +endmacro + +SIMD_FROM_TYPES(DECLARE_FROM_FUNCTIONS) + +macro SIMD_FROM_BITS_TYPES(FUNCTION) +FUNCTION(Float32x4, Int32x4) +FUNCTION(Float32x4, Int16x8) +FUNCTION(Float32x4, Int8x16) +FUNCTION(Int32x4, Float32x4) +FUNCTION(Int32x4, Int16x8) +FUNCTION(Int32x4, Int8x16) +FUNCTION(Int16x8, Float32x4) +FUNCTION(Int16x8, Int32x4) +FUNCTION(Int16x8, Int8x16) +FUNCTION(Int8x16, Float32x4) +FUNCTION(Int8x16, Int32x4) +FUNCTION(Int8x16, Int16x8) +endmacro + +macro DECLARE_FROM_BITS_FUNCTIONS(TO, FROM) +function TOFromFROMBitsJS(a) { + return %TOFromFROMBits(a); +} +endmacro + +SIMD_FROM_BITS_TYPES(DECLARE_FROM_BITS_FUNCTIONS) + //------------------------------------------------------------------- function Float32x4Constructor(c0, c1, c2, c3) { @@ -133,6 +274,51 @@ function Float32x4Splat(s) { } +function Float32x4AbsJS(a) { + return %Float32x4Abs(a); +} + + +function Float32x4SqrtJS(a) { + return %Float32x4Sqrt(a); +} + + +function Float32x4RecipApproxJS(a) { + return %Float32x4RecipApprox(a); +} + + +function Float32x4RecipSqrtApproxJS(a) { + return %Float32x4RecipSqrtApprox(a); +} + + +function Float32x4DivJS(a, b) { + return %Float32x4Div(a, b); +} + + +function Float32x4MinNumJS(a, b) { + return %Float32x4MinNum(a, b); +} + + +function Float32x4MaxNumJS(a, b) { + return %Float32x4MaxNum(a, b); +} + + +function Float32x4SwizzleJS(a, c0, c1, c2, c3) { + return %Float32x4Swizzle(a, c0, c1, c2, c3); +} + + +function Float32x4ShuffleJS(a, b, c0, c1, c2, c3) { + return %Float32x4Shuffle(a, b, c0, c1, c2, c3); +} + + function Int32x4Constructor(c0, c1, c2, c3) { if (%_IsConstructCall()) throw MakeTypeError(kNotConstructor, "Int32x4"); return %CreateInt32x4(TO_NUMBER_INLINE(c0), TO_NUMBER_INLINE(c1), @@ -145,6 +331,16 @@ function Int32x4Splat(s) { } +function Int32x4SwizzleJS(a, c0, c1, c2, c3) { + return %Int32x4Swizzle(a, c0, c1, c2, c3); +} + + +function Int32x4ShuffleJS(a, b, c0, c1, c2, c3) { + return %Int32x4Shuffle(a, b, c0, c1, c2, c3); +} + + function Bool32x4Constructor(c0, c1, c2, c3) { if (%_IsConstructCall()) throw MakeTypeError(kNotConstructor, "Bool32x4"); return %CreateBool32x4(c0, c1, c2, c3); @@ -155,6 +351,15 @@ function Bool32x4Splat(s) { return %CreateBool32x4(s, s, s, s); } +function Bool32x4SwizzleJS(a, c0, c1, c2, c3) { + return %Bool32x4Swizzle(a, c0, c1, c2, c3); +} + + +function Bool32x4ShuffleJS(a, b, c0, c1, c2, c3) { + return %Bool32x4Shuffle(a, b, c0, c1, c2, c3); +} + function Int16x8Constructor(c0, c1, c2, c3, c4, c5, c6, c7) { if (%_IsConstructCall()) throw MakeTypeError(kNotConstructor, "Int16x8"); @@ -170,6 +375,16 @@ function Int16x8Splat(s) { } +function Int16x8SwizzleJS(a, c0, c1, c2, c3, c4, c5, c6, c7) { + return %Int16x8Swizzle(a, c0, c1, c2, c3, c4, c5, c6, c7); +} + + +function Int16x8ShuffleJS(a, b, c0, c1, c2, c3, c4, c5, c6, c7) { + return %Int16x8Shuffle(a, b, c0, c1, c2, c3, c4, c5, c6, c7); +} + + function Bool16x8Constructor(c0, c1, c2, c3, c4, c5, c6, c7) { if (%_IsConstructCall()) throw MakeTypeError(kNotConstructor, "Bool16x8"); return %CreateBool16x8(c0, c1, c2, c3, c4, c5, c6, c7); @@ -181,6 +396,16 @@ function Bool16x8Splat(s) { } +function Bool16x8SwizzleJS(a, c0, c1, c2, c3, c4, c5, c6, c7) { + return %Bool16x8Swizzle(a, c0, c1, c2, c3, c4, c5, c6, c7); +} + + +function Bool16x8ShuffleJS(a, b, c0, c1, c2, c3, c4, c5, c6, c7) { + return %Bool16x8Shuffle(a, b, c0, c1, c2, c3, c4, c5, c6, c7); +} + + function Int8x16Constructor(c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15) { if (%_IsConstructCall()) throw MakeTypeError(kNotConstructor, "Int8x16"); @@ -200,6 +425,20 @@ function Int8x16Splat(s) { } +function Int8x16SwizzleJS(a, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, + c12, c13, c14, c15) { + return %Int8x16Swizzle(a, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, + c12, c13, c14, c15); +} + + +function Int8x16ShuffleJS(a, b, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, + c11, c12, c13, c14, c15) { + return %Int8x16Shuffle(a, b, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, + c11, c12, c13, c14, c15); +} + + function Bool8x16Constructor(c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, c14, c15) { if (%_IsConstructCall()) throw MakeTypeError(kNotConstructor, "Bool8x16"); @@ -213,6 +452,20 @@ function Bool8x16Splat(s) { } +function Bool8x16SwizzleJS(a, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, + c12, c13, c14, c15) { + return %Bool8x16Swizzle(a, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, + c12, c13, c14, c15); +} + + +function Bool8x16ShuffleJS(a, b, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, + c11, c12, c13, c14, c15) { + return %Bool8x16Shuffle(a, b, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, + c11, c12, c13, c14, c15); +} + + %AddNamedProperty(GlobalSIMD, symbolToStringTag, 'SIMD', READ_ONLY | DONT_ENUM); macro SETUP_SIMD_TYPE(NAME, TYPE, LANES) @@ -229,7 +482,7 @@ utils.InstallFunctions(GlobalNAME.prototype, DONT_ENUM, [ ]); endmacro -SIMD_TYPES(SETUP_SIMD_TYPE) +SIMD_ALL_TYPES(SETUP_SIMD_TYPE) //------------------------------------------------------------------- @@ -238,6 +491,32 @@ utils.InstallFunctions(GlobalFloat32x4, DONT_ENUM, [ 'check', Float32x4CheckJS, 'extractLane', Float32x4ExtractLaneJS, 'replaceLane', Float32x4ReplaceLaneJS, + 'neg', Float32x4NegJS, + 'abs', Float32x4AbsJS, + 'sqrt', Float32x4SqrtJS, + 'reciprocalApproximation', Float32x4RecipApproxJS, + 'reciprocalSqrtApproximation', Float32x4RecipSqrtApproxJS, + 'add', Float32x4AddJS, + 'sub', Float32x4SubJS, + 'mul', Float32x4MulJS, + 'div', Float32x4DivJS, + 'min', Float32x4MinJS, + 'max', Float32x4MaxJS, + 'minNum', Float32x4MinNumJS, + 'maxNum', Float32x4MaxNumJS, + 'lessThan', Float32x4LessThanJS, + 'lessThanOrEqual', Float32x4LessThanOrEqualJS, + 'greaterThan', Float32x4GreaterThanJS, + 'greaterThanOrEqual', Float32x4GreaterThanOrEqualJS, + 'equal', Float32x4EqualJS, + 'notEqual', Float32x4NotEqualJS, + 'select', Float32x4SelectJS, + 'swizzle', Float32x4SwizzleJS, + 'shuffle', Float32x4ShuffleJS, + 'fromInt32x4', Float32x4FromInt32x4JS, + 'fromInt32x4Bits', Float32x4FromInt32x4BitsJS, + 'fromInt16x8Bits', Float32x4FromInt16x8BitsJS, + 'fromInt8x16Bits', Float32x4FromInt8x16BitsJS, ]); utils.InstallFunctions(GlobalInt32x4, DONT_ENUM, [ @@ -245,6 +524,32 @@ utils.InstallFunctions(GlobalInt32x4, DONT_ENUM, [ 'check', Int32x4CheckJS, 'extractLane', Int32x4ExtractLaneJS, 'replaceLane', Int32x4ReplaceLaneJS, + 'neg', Int32x4NegJS, + 'add', Int32x4AddJS, + 'sub', Int32x4SubJS, + 'mul', Int32x4MulJS, + 'min', Int32x4MinJS, + 'max', Int32x4MaxJS, + 'and', Int32x4AndJS, + 'or', Int32x4OrJS, + 'xor', Int32x4XorJS, + 'not', Int32x4NotJS, + 'shiftLeftByScalar', Int32x4ShiftLeftByScalarJS, + 'shiftRightLogicalByScalar', Int32x4ShiftRightLogicalByScalarJS, + 'shiftRightArithmeticByScalar', Int32x4ShiftRightArithmeticByScalarJS, + 'lessThan', Int32x4LessThanJS, + 'lessThanOrEqual', Int32x4LessThanOrEqualJS, + 'greaterThan', Int32x4GreaterThanJS, + 'greaterThanOrEqual', Int32x4GreaterThanOrEqualJS, + 'equal', Int32x4EqualJS, + 'notEqual', Int32x4NotEqualJS, + 'select', Int32x4SelectJS, + 'swizzle', Int32x4SwizzleJS, + 'shuffle', Int32x4ShuffleJS, + 'fromFloat32x4', Int32x4FromFloat32x4JS, + 'fromFloat32x4Bits', Int32x4FromFloat32x4BitsJS, + 'fromInt16x8Bits', Int32x4FromInt16x8BitsJS, + 'fromInt8x16Bits', Int32x4FromInt8x16BitsJS, ]); utils.InstallFunctions(GlobalBool32x4, DONT_ENUM, [ @@ -252,6 +557,16 @@ utils.InstallFunctions(GlobalBool32x4, DONT_ENUM, [ 'check', Bool32x4CheckJS, 'extractLane', Bool32x4ExtractLaneJS, 'replaceLane', Bool32x4ReplaceLaneJS, + 'and', Bool32x4AndJS, + 'or', Bool32x4OrJS, + 'xor', Bool32x4XorJS, + 'not', Bool32x4NotJS, + 'anyTrue', Bool32x4AnyTrueJS, + 'allTrue', Bool32x4AllTrueJS, + 'equal', Bool32x4EqualJS, + 'notEqual', Bool32x4NotEqualJS, + 'swizzle', Bool32x4SwizzleJS, + 'shuffle', Bool32x4ShuffleJS, ]); utils.InstallFunctions(GlobalInt16x8, DONT_ENUM, [ @@ -260,6 +575,31 @@ utils.InstallFunctions(GlobalInt16x8, DONT_ENUM, [ 'extractLane', Int16x8ExtractLaneJS, 'unsignedExtractLane', Int16x8UnsignedExtractLaneJS, 'replaceLane', Int16x8ReplaceLaneJS, + 'neg', Int16x8NegJS, + 'add', Int16x8AddJS, + 'sub', Int16x8SubJS, + 'mul', Int16x8MulJS, + 'min', Int16x8MinJS, + 'max', Int16x8MaxJS, + 'and', Int16x8AndJS, + 'or', Int16x8OrJS, + 'xor', Int16x8XorJS, + 'not', Int16x8NotJS, + 'shiftLeftByScalar', Int16x8ShiftLeftByScalarJS, + 'shiftRightLogicalByScalar', Int16x8ShiftRightLogicalByScalarJS, + 'shiftRightArithmeticByScalar', Int16x8ShiftRightArithmeticByScalarJS, + 'lessThan', Int16x8LessThanJS, + 'lessThanOrEqual', Int16x8LessThanOrEqualJS, + 'greaterThan', Int16x8GreaterThanJS, + 'greaterThanOrEqual', Int16x8GreaterThanOrEqualJS, + 'equal', Int16x8EqualJS, + 'notEqual', Int16x8NotEqualJS, + 'select', Int16x8SelectJS, + 'swizzle', Int16x8SwizzleJS, + 'shuffle', Int16x8ShuffleJS, + 'fromFloat32x4Bits', Int16x8FromFloat32x4BitsJS, + 'fromInt32x4Bits', Int16x8FromInt32x4BitsJS, + 'fromInt8x16Bits', Int16x8FromInt8x16BitsJS, ]); utils.InstallFunctions(GlobalBool16x8, DONT_ENUM, [ @@ -267,6 +607,16 @@ utils.InstallFunctions(GlobalBool16x8, DONT_ENUM, [ 'check', Bool16x8CheckJS, 'extractLane', Bool16x8ExtractLaneJS, 'replaceLane', Bool16x8ReplaceLaneJS, + 'and', Bool16x8AndJS, + 'or', Bool16x8OrJS, + 'xor', Bool16x8XorJS, + 'not', Bool16x8NotJS, + 'anyTrue', Bool16x8AnyTrueJS, + 'allTrue', Bool16x8AllTrueJS, + 'equal', Bool16x8EqualJS, + 'notEqual', Bool16x8NotEqualJS, + 'swizzle', Bool16x8SwizzleJS, + 'shuffle', Bool16x8ShuffleJS, ]); utils.InstallFunctions(GlobalInt8x16, DONT_ENUM, [ @@ -275,6 +625,31 @@ utils.InstallFunctions(GlobalInt8x16, DONT_ENUM, [ 'extractLane', Int8x16ExtractLaneJS, 'unsignedExtractLane', Int8x16UnsignedExtractLaneJS, 'replaceLane', Int8x16ReplaceLaneJS, + 'neg', Int8x16NegJS, + 'add', Int8x16AddJS, + 'sub', Int8x16SubJS, + 'mul', Int8x16MulJS, + 'min', Int8x16MinJS, + 'max', Int8x16MaxJS, + 'and', Int8x16AndJS, + 'or', Int8x16OrJS, + 'xor', Int8x16XorJS, + 'not', Int8x16NotJS, + 'shiftLeftByScalar', Int8x16ShiftLeftByScalarJS, + 'shiftRightLogicalByScalar', Int8x16ShiftRightLogicalByScalarJS, + 'shiftRightArithmeticByScalar', Int8x16ShiftRightArithmeticByScalarJS, + 'lessThan', Int8x16LessThanJS, + 'lessThanOrEqual', Int8x16LessThanOrEqualJS, + 'greaterThan', Int8x16GreaterThanJS, + 'greaterThanOrEqual', Int8x16GreaterThanOrEqualJS, + 'equal', Int8x16EqualJS, + 'notEqual', Int8x16NotEqualJS, + 'select', Int8x16SelectJS, + 'swizzle', Int8x16SwizzleJS, + 'shuffle', Int8x16ShuffleJS, + 'fromFloat32x4Bits', Int8x16FromFloat32x4BitsJS, + 'fromInt32x4Bits', Int8x16FromInt32x4BitsJS, + 'fromInt16x8Bits', Int8x16FromInt16x8BitsJS, ]); utils.InstallFunctions(GlobalBool8x16, DONT_ENUM, [ @@ -282,6 +657,26 @@ utils.InstallFunctions(GlobalBool8x16, DONT_ENUM, [ 'check', Bool8x16CheckJS, 'extractLane', Bool8x16ExtractLaneJS, 'replaceLane', Bool8x16ReplaceLaneJS, + 'and', Bool8x16AndJS, + 'or', Bool8x16OrJS, + 'xor', Bool8x16XorJS, + 'not', Bool8x16NotJS, + 'anyTrue', Bool8x16AnyTrueJS, + 'allTrue', Bool8x16AllTrueJS, + 'equal', Bool8x16EqualJS, + 'notEqual', Bool8x16NotEqualJS, + 'swizzle', Bool8x16SwizzleJS, + 'shuffle', Bool8x16ShuffleJS, ]); +utils.Export(function(to) { + to.Float32x4ToString = Float32x4ToString; + to.Int32x4ToString = Int32x4ToString; + to.Bool32x4ToString = Bool32x4ToString; + to.Int16x8ToString = Int16x8ToString; + to.Bool16x8ToString = Bool16x8ToString; + to.Int8x16ToString = Int8x16ToString; + to.Bool8x16ToString = Bool8x16ToString; +}); + }) diff --git a/src/messages.js b/src/messages.js index 29fa978..ad1f4c2 100644 --- a/src/messages.js +++ b/src/messages.js @@ -45,12 +45,28 @@ var StringCharAt; var StringIndexOf; var StringSubstring; +var Float32x4ToString; +var Int32x4ToString; +var Bool32x4ToString; +var Int16x8ToString; +var Bool16x8ToString; +var Int8x16ToString; +var Bool8x16ToString; + + utils.Import(function(from) { ArrayJoin = from.ArrayJoin; ObjectToString = from.ObjectToString; StringCharAt = from.StringCharAt; StringIndexOf = from.StringIndexOf; StringSubstring = from.StringSubstring; + Float32x4ToString = from.Float32x4ToString; + Int32x4ToString = from.Int32x4ToString; + Bool32x4ToString = from.Bool32x4ToString; + Int16x8ToString = from.Int16x8ToString; + Bool16x8ToString = from.Bool16x8ToString; + Int8x16ToString = from.Int8x16ToString; + Bool8x16ToString = from.Bool8x16ToString; }); // ------------------------------------------------------------------- @@ -88,13 +104,13 @@ function NoSideEffectToString(obj) { if (IS_SYMBOL(obj)) return %_CallFunction(obj, $symbolToString); if (IS_SIMD_VALUE(obj)) { switch (typeof(obj)) { - case 'float32x4': return %_CallFunction(obj, $float32x4ToString); - case 'int32x4': return %_CallFunction(obj, $int32x4ToString); - case 'bool32x4': return %_CallFunction(obj, $bool32x4ToString); - case 'int16x8': return %_CallFunction(obj, $int16x8ToString); - case 'bool16x8': return %_CallFunction(obj, $bool16x8ToString); - case 'int16x8': return %_CallFunction(obj, $int16x8ToString); - case 'bool16x8': return %_CallFunction(obj, $bool16x8ToString); + case 'float32x4': return %_CallFunction(obj, Float32x4ToString); + case 'int32x4': return %_CallFunction(obj, Int32x4ToString); + case 'bool32x4': return %_CallFunction(obj, Bool32x4ToString); + case 'int16x8': return %_CallFunction(obj, Int16x8ToString); + case 'bool16x8': return %_CallFunction(obj, Bool16x8ToString); + case 'int16x8': return %_CallFunction(obj, Int16x8ToString); + case 'bool16x8': return %_CallFunction(obj, Bool16x8ToString); } } if (IS_OBJECT(obj) diff --git a/src/objects.cc b/src/objects.cc index a86d053..12c8d17 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -1634,6 +1634,9 @@ void HeapNumber::HeapNumberPrint(std::ostream& os) { // NOLINT #define READ_INT64_FIELD(p, offset) \ (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) +#define READ_BYTE_FIELD(p, offset) \ + (*reinterpret_cast(FIELD_ADDR_CONST(p, offset))) + bool Simd128Value::BitwiseEquals(const Simd128Value* other) const { return READ_INT64_FIELD(this, kValueOffset) == @@ -1657,6 +1660,11 @@ uint32_t Simd128Value::Hash() const { } +void Simd128Value::CopyBits(void* destination) const { + memcpy(destination, &READ_BYTE_FIELD(this, kValueOffset), kSimd128Size); +} + + String* JSReceiver::class_name() { if (IsJSFunction() || IsJSFunctionProxy()) { return GetHeap()->Function_string(); diff --git a/src/objects.h b/src/objects.h index 6d052ef..257f0e5 100644 --- a/src/objects.h +++ b/src/objects.h @@ -1611,6 +1611,8 @@ class Simd128Value : public HeapObject { bool BitwiseEquals(const Simd128Value* other) const; // Computes a hash from the 128 bit value, viewed as 4 32-bit integers. uint32_t Hash() const; + // Copies the 16 bytes of SIMD data to the destination address. + void CopyBits(void* destination) const; // Layout description. static const int kValueOffset = HeapObject::kHeaderSize; diff --git a/src/runtime/runtime-simd.cc b/src/runtime/runtime-simd.cc index 4c184aa..3d050d8 100644 --- a/src/runtime/runtime-simd.cc +++ b/src/runtime/runtime-simd.cc @@ -13,85 +13,6 @@ // the SIMD.js draft spec: // http://littledan.github.io/simd.html -#define CONVERT_SIMD_LANE_ARG_CHECKED(name, index, lanes) \ - CONVERT_INT32_ARG_CHECKED(name, index); \ - RUNTIME_ASSERT(name >= 0 && name < lanes); - -#define SIMD_CREATE_NUMERIC_FUNCTION(type, lane_type, lane_count) \ - RUNTIME_FUNCTION(Runtime_Create##type) { \ - static const int kLaneCount = lane_count; \ - HandleScope scope(isolate); \ - DCHECK(args.length() == kLaneCount); \ - lane_type lanes[kLaneCount]; \ - for (int i = 0; i < kLaneCount; i++) { \ - CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, i); \ - lanes[i] = ConvertNumber(number->Number()); \ - } \ - return *isolate->factory()->New##type(lanes); \ - } - -#define SIMD_CREATE_BOOLEAN_FUNCTION(type, lane_count) \ - RUNTIME_FUNCTION(Runtime_Create##type) { \ - static const int kLaneCount = lane_count; \ - HandleScope scope(isolate); \ - DCHECK(args.length() == kLaneCount); \ - bool lanes[kLaneCount]; \ - for (int i = 0; i < kLaneCount; i++) { \ - lanes[i] = args[i]->BooleanValue(); \ - } \ - return *isolate->factory()->New##type(lanes); \ - } - -#define SIMD_CHECK_FUNCTION(type) \ - RUNTIME_FUNCTION(Runtime_##type##Check) { \ - HandleScope scope(isolate); \ - CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ - return *a; \ - } - -#define SIMD_EXTRACT_LANE_FUNCTION(type, lanes, extract_fn) \ - RUNTIME_FUNCTION(Runtime_##type##ExtractLane) { \ - HandleScope scope(isolate); \ - DCHECK(args.length() == 2); \ - CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ - CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, lanes); \ - return *isolate->factory()->extract_fn(a->get_lane(lane)); \ - } - -#define SIMD_REPLACE_NUMERIC_LANE_FUNCTION(type, lane_type, lane_count) \ - RUNTIME_FUNCTION(Runtime_##type##ReplaceLane) { \ - static const int kLaneCount = lane_count; \ - HandleScope scope(isolate); \ - DCHECK(args.length() == 3); \ - CONVERT_ARG_HANDLE_CHECKED(type, simd, 0); \ - CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, kLaneCount); \ - CONVERT_NUMBER_ARG_HANDLE_CHECKED(number, 2); \ - lane_type lanes[kLaneCount]; \ - for (int i = 0; i < kLaneCount; i++) { \ - lanes[i] = simd->get_lane(i); \ - } \ - lanes[lane] = ConvertNumber(number->Number()); \ - Handle result = isolate->factory()->New##type(lanes); \ - return *result; \ - } - -#define SIMD_REPLACE_BOOLEAN_LANE_FUNCTION(type, lane_count) \ - RUNTIME_FUNCTION(Runtime_##type##ReplaceLane) { \ - static const int kLaneCount = lane_count; \ - HandleScope scope(isolate); \ - DCHECK(args.length() == 3); \ - CONVERT_ARG_HANDLE_CHECKED(type, simd, 0); \ - CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, kLaneCount); \ - bool lanes[kLaneCount]; \ - for (int i = 0; i < kLaneCount; i++) { \ - lanes[i] = simd->get_lane(i); \ - } \ - lanes[lane] = args[2]->BooleanValue(); \ - Handle result = isolate->factory()->New##type(lanes); \ - return *result; \ - } - - namespace v8 { namespace internal { @@ -134,8 +55,82 @@ bool Equals(Float32x4* a, Float32x4* b) { return true; } + +// TODO(bbudge): Make this consistent with SIMD instruction results. +inline float RecipApprox(float a) { return 1.0f / a; } + + +// TODO(bbudge): Make this consistent with SIMD instruction results. +inline float RecipSqrtApprox(float a) { return 1.0f / std::sqrt(a); } + + +// Saturating addition for int16_t and int8_t. +template +inline T AddSaturate(T a, T b) { + const T max = std::numeric_limits::max(); + const T min = std::numeric_limits::min(); + int32_t result = a + b; + if (result > max) return max; + if (result < min) return min; + return result; +} + + +// Saturating subtraction for int16_t and int8_t. +template +inline T SubSaturate(T a, T b) { + const T max = std::numeric_limits::max(); + const T min = std::numeric_limits::min(); + int32_t result = a - b; + if (result > max) return max; + if (result < min) return min; + return result; +} + + +inline float Min(float a, float b) { + if (a < b) return a; + if (a > b) return b; + if (a == b) return std::signbit(a) ? a : b; + return std::numeric_limits::quiet_NaN(); +} + + +inline float Max(float a, float b) { + if (a > b) return a; + if (a < b) return b; + if (a == b) return std::signbit(b) ? a : b; + return std::numeric_limits::quiet_NaN(); +} + + +inline float MinNumber(float a, float b) { + if (std::isnan(a)) return b; + if (std::isnan(b)) return a; + return Min(a, b); +} + + +inline float MaxNumber(float a, float b) { + if (std::isnan(a)) return b; + if (std::isnan(b)) return a; + return Max(a, b); +} + + +inline bool CanCast(int32_t a) { return true; } + + +inline bool CanCast(float a) { + return a > std::numeric_limits::min() && + a < std::numeric_limits::max(); +} + } // namespace +//------------------------------------------------------------------- + +// SIMD helper functions. RUNTIME_FUNCTION(Runtime_IsSimdValue) { HandleScope scope(isolate); @@ -212,32 +207,617 @@ RUNTIME_FUNCTION(Runtime_SimdSameValueZero) { } -SIMD_CREATE_NUMERIC_FUNCTION(Float32x4, float, 4) -SIMD_CREATE_NUMERIC_FUNCTION(Int32x4, int32_t, 4) -SIMD_CREATE_BOOLEAN_FUNCTION(Bool32x4, 4) -SIMD_CREATE_NUMERIC_FUNCTION(Int16x8, int16_t, 8) -SIMD_CREATE_BOOLEAN_FUNCTION(Bool16x8, 8) -SIMD_CREATE_NUMERIC_FUNCTION(Int8x16, int8_t, 16) -SIMD_CREATE_BOOLEAN_FUNCTION(Bool8x16, 16) +//------------------------------------------------------------------- + +// Utility macros. + +#define CONVERT_SIMD_LANE_ARG_CHECKED(name, index, lanes) \ + CONVERT_INT32_ARG_CHECKED(name, index); \ + RUNTIME_ASSERT(name >= 0 && name < lanes); + +#define SIMD_UNARY_OP(type, lane_type, lane_count, op, result) \ + static const int kLaneCount = lane_count; \ + DCHECK(args.length() == 1); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + lane_type lanes[kLaneCount]; \ + for (int i = 0; i < kLaneCount; i++) { \ + lanes[i] = op(a->get_lane(i)); \ + } \ + Handle result = isolate->factory()->New##type(lanes); + +#define SIMD_BINARY_OP(type, lane_type, lane_count, op, result) \ + static const int kLaneCount = lane_count; \ + DCHECK(args.length() == 2); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + CONVERT_ARG_HANDLE_CHECKED(type, b, 1); \ + lane_type lanes[kLaneCount]; \ + for (int i = 0; i < kLaneCount; i++) { \ + lanes[i] = op(a->get_lane(i), b->get_lane(i)); \ + } \ + Handle result = isolate->factory()->New##type(lanes); + +#define SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, op, result) \ + static const int kLaneCount = lane_count; \ + DCHECK(args.length() == 2); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + CONVERT_ARG_HANDLE_CHECKED(type, b, 1); \ + bool lanes[kLaneCount]; \ + for (int i = 0; i < kLaneCount; i++) { \ + lanes[i] = a->get_lane(i) op b->get_lane(i); \ + } \ + Handle result = isolate->factory()->New##bool_type(lanes); + +//------------------------------------------------------------------- + +// Common functions. + +#define GET_NUMERIC_ARG(lane_type, name, index) \ + CONVERT_NUMBER_ARG_HANDLE_CHECKED(a, index); \ + name = ConvertNumber(a->Number()); + +#define GET_BOOLEAN_ARG(lane_type, name, index) \ + name = args[index]->BooleanValue(); + +#define SIMD_ALL_TYPES(FUNCTION) \ + FUNCTION(Float32x4, float, 4, NewNumber, GET_NUMERIC_ARG) \ + FUNCTION(Int32x4, int32_t, 4, NewNumber, GET_NUMERIC_ARG) \ + FUNCTION(Bool32x4, bool, 4, ToBoolean, GET_BOOLEAN_ARG) \ + FUNCTION(Int16x8, int16_t, 8, NewNumber, GET_NUMERIC_ARG) \ + FUNCTION(Bool16x8, bool, 8, ToBoolean, GET_BOOLEAN_ARG) \ + FUNCTION(Int8x16, int8_t, 16, NewNumber, GET_NUMERIC_ARG) \ + FUNCTION(Bool8x16, bool, 16, ToBoolean, GET_BOOLEAN_ARG) + +#define SIMD_CREATE_FUNCTION(type, lane_type, lane_count, extract, replace) \ + RUNTIME_FUNCTION(Runtime_Create##type) { \ + static const int kLaneCount = lane_count; \ + HandleScope scope(isolate); \ + DCHECK(args.length() == kLaneCount); \ + lane_type lanes[kLaneCount]; \ + for (int i = 0; i < kLaneCount; i++) { \ + replace(lane_type, lanes[i], i) \ + } \ + return *isolate->factory()->New##type(lanes); \ + } + +#define SIMD_EXTRACT_FUNCTION(type, lane_type, lane_count, extract, replace) \ + RUNTIME_FUNCTION(Runtime_##type##ExtractLane) { \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 2); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, lane_count); \ + return *isolate->factory()->extract(a->get_lane(lane)); \ + } + +#define SIMD_REPLACE_FUNCTION(type, lane_type, lane_count, extract, replace) \ + RUNTIME_FUNCTION(Runtime_##type##ReplaceLane) { \ + static const int kLaneCount = lane_count; \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 3); \ + CONVERT_ARG_HANDLE_CHECKED(type, simd, 0); \ + CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, kLaneCount); \ + lane_type lanes[kLaneCount]; \ + for (int i = 0; i < kLaneCount; i++) { \ + lanes[i] = simd->get_lane(i); \ + } \ + replace(lane_type, lanes[lane], 2); \ + Handle result = isolate->factory()->New##type(lanes); \ + return *result; \ + } + +#define SIMD_CHECK_FUNCTION(type, lane_type, lane_count, extract, replace) \ + RUNTIME_FUNCTION(Runtime_##type##Check) { \ + HandleScope scope(isolate); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + return *a; \ + } +#define SIMD_SWIZZLE_FUNCTION(type, lane_type, lane_count, extract, replace) \ + RUNTIME_FUNCTION(Runtime_##type##Swizzle) { \ + static const int kLaneCount = lane_count; \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 1 + kLaneCount); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + lane_type lanes[kLaneCount]; \ + for (int i = 0; i < kLaneCount; i++) { \ + CONVERT_SIMD_LANE_ARG_CHECKED(index, i + 1, kLaneCount); \ + lanes[i] = a->get_lane(index); \ + } \ + Handle result = isolate->factory()->New##type(lanes); \ + return *result; \ + } -SIMD_CHECK_FUNCTION(Float32x4) -SIMD_CHECK_FUNCTION(Int32x4) -SIMD_CHECK_FUNCTION(Bool32x4) -SIMD_CHECK_FUNCTION(Int16x8) -SIMD_CHECK_FUNCTION(Bool16x8) -SIMD_CHECK_FUNCTION(Int8x16) -SIMD_CHECK_FUNCTION(Bool8x16) +#define SIMD_SHUFFLE_FUNCTION(type, lane_type, lane_count, extract, replace) \ + RUNTIME_FUNCTION(Runtime_##type##Shuffle) { \ + static const int kLaneCount = lane_count; \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 2 + kLaneCount); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + CONVERT_ARG_HANDLE_CHECKED(type, b, 1); \ + lane_type lanes[kLaneCount]; \ + for (int i = 0; i < kLaneCount; i++) { \ + CONVERT_SIMD_LANE_ARG_CHECKED(index, i + 2, kLaneCount * 2); \ + lanes[i] = index < kLaneCount ? a->get_lane(index) \ + : b->get_lane(index - kLaneCount); \ + } \ + Handle result = isolate->factory()->New##type(lanes); \ + return *result; \ + } +SIMD_ALL_TYPES(SIMD_CREATE_FUNCTION) +SIMD_ALL_TYPES(SIMD_EXTRACT_FUNCTION) +SIMD_ALL_TYPES(SIMD_REPLACE_FUNCTION) +SIMD_ALL_TYPES(SIMD_CHECK_FUNCTION) +SIMD_ALL_TYPES(SIMD_SWIZZLE_FUNCTION) +SIMD_ALL_TYPES(SIMD_SHUFFLE_FUNCTION) -SIMD_EXTRACT_LANE_FUNCTION(Float32x4, 4, NewNumber) -SIMD_EXTRACT_LANE_FUNCTION(Int32x4, 4, NewNumber) -SIMD_EXTRACT_LANE_FUNCTION(Bool32x4, 4, ToBoolean) -SIMD_EXTRACT_LANE_FUNCTION(Int16x8, 8, NewNumber) -SIMD_EXTRACT_LANE_FUNCTION(Bool16x8, 8, ToBoolean) -SIMD_EXTRACT_LANE_FUNCTION(Int8x16, 16, NewNumber) -SIMD_EXTRACT_LANE_FUNCTION(Bool8x16, 16, ToBoolean) +//------------------------------------------------------------------- +// Float-only functions. + +#define SIMD_ABS_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Abs) { \ + HandleScope scope(isolate); \ + SIMD_UNARY_OP(type, lane_type, lane_count, std::abs, result); \ + return *result; \ + } + +#define SIMD_SQRT_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Sqrt) { \ + HandleScope scope(isolate); \ + SIMD_UNARY_OP(type, lane_type, lane_count, std::sqrt, result); \ + return *result; \ + } + +#define SIMD_RECIP_APPROX_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##RecipApprox) { \ + HandleScope scope(isolate); \ + SIMD_UNARY_OP(type, lane_type, lane_count, RecipApprox, result); \ + return *result; \ + } + +#define SIMD_RECIP_SQRT_APPROX_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##RecipSqrtApprox) { \ + HandleScope scope(isolate); \ + SIMD_UNARY_OP(type, lane_type, lane_count, RecipSqrtApprox, result); \ + return *result; \ + } + +#define BINARY_DIV(a, b) (a) / (b) +#define SIMD_DIV_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Div) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_DIV, result); \ + return *result; \ + } + +#define SIMD_MINNUM_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##MinNum) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, MinNumber, result); \ + return *result; \ + } + +#define SIMD_MAXNUM_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##MaxNum) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, MaxNumber, result); \ + return *result; \ + } + +SIMD_ABS_FUNCTION(Float32x4, float, 4) +SIMD_SQRT_FUNCTION(Float32x4, float, 4) +SIMD_RECIP_APPROX_FUNCTION(Float32x4, float, 4) +SIMD_RECIP_SQRT_APPROX_FUNCTION(Float32x4, float, 4) +SIMD_DIV_FUNCTION(Float32x4, float, 4) +SIMD_MINNUM_FUNCTION(Float32x4, float, 4) +SIMD_MAXNUM_FUNCTION(Float32x4, float, 4) + +//------------------------------------------------------------------- + +// Int-only functions. + +#define SIMD_INT_TYPES(FUNCTION) \ + FUNCTION(Int32x4, int32_t, 32, 4) \ + FUNCTION(Int16x8, int16_t, 16, 8) \ + FUNCTION(Int8x16, int8_t, 8, 16) + +#define CONVERT_SHIFT_ARG_CHECKED(name, index) \ + RUNTIME_ASSERT(args[index]->IsNumber()); \ + int32_t signed_shift = 0; \ + RUNTIME_ASSERT(args[index]->ToInt32(&signed_shift)); \ + uint32_t name = bit_cast(signed_shift); + +#define SIMD_LSL_FUNCTION(type, lane_type, lane_bits, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##ShiftLeftByScalar) { \ + static const int kLaneCount = lane_count; \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 2); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + CONVERT_SHIFT_ARG_CHECKED(shift, 1); \ + lane_type lanes[kLaneCount] = {0}; \ + if (shift < lane_bits) { \ + for (int i = 0; i < kLaneCount; i++) { \ + lanes[i] = a->get_lane(i) << shift; \ + } \ + } \ + Handle result = isolate->factory()->New##type(lanes); \ + return *result; \ + } + +#define SIMD_LSR_FUNCTION(type, lane_type, lane_bits, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##ShiftRightLogicalByScalar) { \ + static const int kLaneCount = lane_count; \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 2); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + CONVERT_SHIFT_ARG_CHECKED(shift, 1); \ + lane_type lanes[kLaneCount] = {0}; \ + if (shift < lane_bits) { \ + for (int i = 0; i < kLaneCount; i++) { \ + lanes[i] = static_cast( \ + bit_cast(a->get_lane(i)) >> shift); \ + } \ + } \ + Handle result = isolate->factory()->New##type(lanes); \ + return *result; \ + } + +#define SIMD_ASR_FUNCTION(type, lane_type, lane_bits, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##ShiftRightArithmeticByScalar) { \ + static const int kLaneCount = lane_count; \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 2); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + CONVERT_SHIFT_ARG_CHECKED(shift, 1); \ + if (shift >= lane_bits) shift = lane_bits - 1; \ + lane_type lanes[kLaneCount]; \ + for (int i = 0; i < kLaneCount; i++) { \ + int64_t shifted = static_cast(a->get_lane(i)) >> shift; \ + lanes[i] = static_cast(shifted); \ + } \ + Handle result = isolate->factory()->New##type(lanes); \ + return *result; \ + } + +SIMD_INT_TYPES(SIMD_LSL_FUNCTION) +SIMD_INT_TYPES(SIMD_LSR_FUNCTION) +SIMD_INT_TYPES(SIMD_ASR_FUNCTION) + +//------------------------------------------------------------------- + +// Bool-only functions. + +#define SIMD_BOOL_TYPES(FUNCTION) \ + FUNCTION(Bool32x4, 4) \ + FUNCTION(Bool16x8, 8) \ + FUNCTION(Bool8x16, 16) + +#define SIMD_ANY_FUNCTION(type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##AnyTrue) { \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 1); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + bool result = false; \ + for (int i = 0; i < lane_count; i++) { \ + if (a->get_lane(i)) { \ + result = true; \ + break; \ + } \ + } \ + return isolate->heap()->ToBoolean(result); \ + } + +#define SIMD_ALL_FUNCTION(type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##AllTrue) { \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 1); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 0); \ + bool result = true; \ + for (int i = 0; i < lane_count; i++) { \ + if (!a->get_lane(i)) { \ + result = false; \ + break; \ + } \ + } \ + return isolate->heap()->ToBoolean(result); \ + } + +SIMD_BOOL_TYPES(SIMD_ANY_FUNCTION) +SIMD_BOOL_TYPES(SIMD_ALL_FUNCTION) + +//------------------------------------------------------------------- + +// Small Int-only functions. + +#define SIMD_SMALL_INT_TYPES(FUNCTION) \ + FUNCTION(Int16x8, int16_t, 8) \ + FUNCTION(Int8x16, int8_t, 16) + +#define SIMD_ADD_SATURATE_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##AddSaturate) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, AddSaturate, result); \ + return *result; \ + } + +#define BINARY_SUB(a, b) (a) - (b) +#define SIMD_SUB_SATURATE_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##SubSaturate) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, SubSaturate, result); \ + return *result; \ + } + +SIMD_SMALL_INT_TYPES(SIMD_ADD_SATURATE_FUNCTION) +SIMD_SMALL_INT_TYPES(SIMD_SUB_SATURATE_FUNCTION) + +//------------------------------------------------------------------- + +// Numeric functions. + +#define SIMD_NUMERIC_TYPES(FUNCTION) \ + FUNCTION(Float32x4, float, 4) \ + FUNCTION(Int32x4, int32_t, 4) \ + FUNCTION(Int16x8, int16_t, 8) \ + FUNCTION(Int8x16, int8_t, 16) + +#define SIMD_NEG_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Neg) { \ + HandleScope scope(isolate); \ + SIMD_UNARY_OP(type, lane_type, lane_count, -, result); \ + return *result; \ + } + +#define BINARY_ADD(a, b) (a) + (b) +#define SIMD_ADD_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Add) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_ADD, result); \ + return *result; \ + } + +#define BINARY_SUB(a, b) (a) - (b) +#define SIMD_SUB_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Sub) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_SUB, result); \ + return *result; \ + } + +#define BINARY_MUL(a, b) (a) * (b) +#define SIMD_MUL_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Mul) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_MUL, result); \ + return *result; \ + } + +#define SIMD_MIN_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Min) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, Min, result); \ + return *result; \ + } + +#define SIMD_MAX_FUNCTION(type, lane_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Max) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, Max, result); \ + return *result; \ + } + +SIMD_NUMERIC_TYPES(SIMD_NEG_FUNCTION) +SIMD_NUMERIC_TYPES(SIMD_ADD_FUNCTION) +SIMD_NUMERIC_TYPES(SIMD_SUB_FUNCTION) +SIMD_NUMERIC_TYPES(SIMD_MUL_FUNCTION) +SIMD_NUMERIC_TYPES(SIMD_MIN_FUNCTION) +SIMD_NUMERIC_TYPES(SIMD_MAX_FUNCTION) + +//------------------------------------------------------------------- + +// Relational functions. + +#define SIMD_RELATIONAL_TYPES(FUNCTION) \ + FUNCTION(Float32x4, Bool32x4, 4) \ + FUNCTION(Int32x4, Bool32x4, 4) \ + FUNCTION(Int16x8, Bool16x8, 8) \ + FUNCTION(Int8x16, Bool8x16, 16) + +#define SIMD_EQUALITY_TYPES(FUNCTION) \ + SIMD_RELATIONAL_TYPES(FUNCTION) \ + FUNCTION(Bool32x4, Bool32x4, 4) \ + FUNCTION(Bool16x8, Bool16x8, 8) \ + FUNCTION(Bool8x16, Bool8x16, 16) + +#define SIMD_EQUAL_FUNCTION(type, bool_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Equal) { \ + HandleScope scope(isolate); \ + SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, ==, result); \ + return *result; \ + } + +#define SIMD_NOT_EQUAL_FUNCTION(type, bool_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##NotEqual) { \ + HandleScope scope(isolate); \ + SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, !=, result); \ + return *result; \ + } + +SIMD_EQUALITY_TYPES(SIMD_EQUAL_FUNCTION) +SIMD_EQUALITY_TYPES(SIMD_NOT_EQUAL_FUNCTION) + +#define SIMD_LESS_THAN_FUNCTION(type, bool_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##LessThan) { \ + HandleScope scope(isolate); \ + SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, <, result); \ + return *result; \ + } + +#define SIMD_LESS_THAN_OR_EQUAL_FUNCTION(type, bool_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##LessThanOrEqual) { \ + HandleScope scope(isolate); \ + SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, <=, result); \ + return *result; \ + } + +#define SIMD_GREATER_THAN_FUNCTION(type, bool_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##GreaterThan) { \ + HandleScope scope(isolate); \ + SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, >, result); \ + return *result; \ + } + +#define SIMD_GREATER_THAN_OR_EQUAL_FUNCTION(type, bool_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##GreaterThanOrEqual) { \ + HandleScope scope(isolate); \ + SIMD_RELATIONAL_OP(type, bool_type, lane_count, a, b, >=, result); \ + return *result; \ + } + +SIMD_RELATIONAL_TYPES(SIMD_LESS_THAN_FUNCTION) +SIMD_RELATIONAL_TYPES(SIMD_LESS_THAN_OR_EQUAL_FUNCTION) +SIMD_RELATIONAL_TYPES(SIMD_GREATER_THAN_FUNCTION) +SIMD_RELATIONAL_TYPES(SIMD_GREATER_THAN_OR_EQUAL_FUNCTION) + +//------------------------------------------------------------------- + +// Logical functions. + +#define SIMD_LOGICAL_TYPES(FUNCTION) \ + FUNCTION(Int32x4, int32_t, 4, _INT) \ + FUNCTION(Int16x8, int16_t, 8, _INT) \ + FUNCTION(Int8x16, int8_t, 16, _INT) \ + FUNCTION(Bool32x4, bool, 4, _BOOL) \ + FUNCTION(Bool16x8, bool, 8, _BOOL) \ + FUNCTION(Bool8x16, bool, 16, _BOOL) + +#define BINARY_AND_INT(a, b) (a) & (b) +#define BINARY_AND_BOOL(a, b) (a) && (b) +#define SIMD_AND_FUNCTION(type, lane_type, lane_count, op) \ + RUNTIME_FUNCTION(Runtime_##type##And) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_AND##op, result); \ + return *result; \ + } + +#define BINARY_OR_INT(a, b) (a) | (b) +#define BINARY_OR_BOOL(a, b) (a) || (b) +#define SIMD_OR_FUNCTION(type, lane_type, lane_count, op) \ + RUNTIME_FUNCTION(Runtime_##type##Or) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_OR##op, result); \ + return *result; \ + } + +#define BINARY_XOR_INT(a, b) (a) ^ (b) +#define BINARY_XOR_BOOL(a, b) (a) != (b) +#define SIMD_XOR_FUNCTION(type, lane_type, lane_count, op) \ + RUNTIME_FUNCTION(Runtime_##type##Xor) { \ + HandleScope scope(isolate); \ + SIMD_BINARY_OP(type, lane_type, lane_count, BINARY_XOR##op, result); \ + return *result; \ + } + +#define UNARY_NOT_INT ~ +#define UNARY_NOT_BOOL ! +#define SIMD_NOT_FUNCTION(type, lane_type, lane_count, op) \ + RUNTIME_FUNCTION(Runtime_##type##Not) { \ + HandleScope scope(isolate); \ + SIMD_UNARY_OP(type, lane_type, lane_count, UNARY_NOT##op, result); \ + return *result; \ + } + +SIMD_LOGICAL_TYPES(SIMD_AND_FUNCTION) +SIMD_LOGICAL_TYPES(SIMD_OR_FUNCTION) +SIMD_LOGICAL_TYPES(SIMD_XOR_FUNCTION) +SIMD_LOGICAL_TYPES(SIMD_NOT_FUNCTION) + +//------------------------------------------------------------------- + +// Select functions. + +#define SIMD_SELECT_TYPES(FUNCTION) \ + FUNCTION(Float32x4, float, Bool32x4, 4) \ + FUNCTION(Int32x4, int32_t, Bool32x4, 4) \ + FUNCTION(Int16x8, int16_t, Bool16x8, 8) \ + FUNCTION(Int8x16, int8_t, Bool8x16, 16) + +#define SIMD_SELECT_FUNCTION(type, lane_type, bool_type, lane_count) \ + RUNTIME_FUNCTION(Runtime_##type##Select) { \ + static const int kLaneCount = lane_count; \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 3); \ + CONVERT_ARG_HANDLE_CHECKED(bool_type, mask, 0); \ + CONVERT_ARG_HANDLE_CHECKED(type, a, 1); \ + CONVERT_ARG_HANDLE_CHECKED(type, b, 2); \ + lane_type lanes[kLaneCount]; \ + for (int i = 0; i < kLaneCount; i++) { \ + lanes[i] = mask->get_lane(i) ? a->get_lane(i) : b->get_lane(i); \ + } \ + Handle result = isolate->factory()->New##type(lanes); \ + return *result; \ + } + +SIMD_SELECT_TYPES(SIMD_SELECT_FUNCTION) + +//------------------------------------------------------------------- + +// Casting functions. + +#define SIMD_FROM_TYPES(FUNCTION) \ + FUNCTION(Float32x4, float, 4, Int32x4, int32_t) \ + FUNCTION(Int32x4, int32_t, 4, Float32x4, float) + +#define SIMD_FROM_FUNCTION(type, lane_type, lane_count, from_type, from_ctype) \ + RUNTIME_FUNCTION(Runtime_##type##From##from_type) { \ + static const int kLaneCount = lane_count; \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 1); \ + CONVERT_ARG_HANDLE_CHECKED(from_type, a, 0); \ + lane_type lanes[kLaneCount]; \ + for (int i = 0; i < kLaneCount; i++) { \ + from_ctype a_value = a->get_lane(i); \ + RUNTIME_ASSERT(CanCast(a_value)); \ + lanes[i] = static_cast(a_value); \ + } \ + Handle result = isolate->factory()->New##type(lanes); \ + return *result; \ + } + +SIMD_FROM_TYPES(SIMD_FROM_FUNCTION) + +#define SIMD_FROM_BITS_TYPES(FUNCTION) \ + FUNCTION(Float32x4, float, 4, Int32x4) \ + FUNCTION(Float32x4, float, 4, Int16x8) \ + FUNCTION(Float32x4, float, 4, Int8x16) \ + FUNCTION(Int32x4, int32_t, 4, Float32x4) \ + FUNCTION(Int32x4, int32_t, 4, Int16x8) \ + FUNCTION(Int32x4, int32_t, 4, Int8x16) \ + FUNCTION(Int16x8, int16_t, 8, Float32x4) \ + FUNCTION(Int16x8, int16_t, 8, Int32x4) \ + FUNCTION(Int16x8, int16_t, 8, Int8x16) \ + FUNCTION(Int8x16, int8_t, 16, Float32x4) \ + FUNCTION(Int8x16, int8_t, 16, Int32x4) \ + FUNCTION(Int8x16, int8_t, 16, Int16x8) + +#define SIMD_FROM_BITS_FUNCTION(type, lane_type, lane_count, from_type) \ + RUNTIME_FUNCTION(Runtime_##type##From##from_type##Bits) { \ + static const int kLaneCount = lane_count; \ + HandleScope scope(isolate); \ + DCHECK(args.length() == 1); \ + CONVERT_ARG_HANDLE_CHECKED(from_type, a, 0); \ + lane_type lanes[kLaneCount]; \ + a->CopyBits(lanes); \ + Handle result = isolate->factory()->New##type(lanes); \ + return *result; \ + } + +SIMD_FROM_BITS_TYPES(SIMD_FROM_BITS_FUNCTION) + +//------------------------------------------------------------------- + +// Unsigned extract functions. +// TODO(bbudge): remove when spec changes to include unsigned int types. RUNTIME_FUNCTION(Runtime_Int16x8UnsignedExtractLane) { HandleScope scope(isolate); @@ -255,14 +835,5 @@ RUNTIME_FUNCTION(Runtime_Int8x16UnsignedExtractLane) { CONVERT_SIMD_LANE_ARG_CHECKED(lane, 1, 16); return *isolate->factory()->NewNumber(bit_cast(a->get_lane(lane))); } - - -SIMD_REPLACE_NUMERIC_LANE_FUNCTION(Float32x4, float, 4) -SIMD_REPLACE_NUMERIC_LANE_FUNCTION(Int32x4, int32_t, 4) -SIMD_REPLACE_BOOLEAN_LANE_FUNCTION(Bool32x4, 4) -SIMD_REPLACE_NUMERIC_LANE_FUNCTION(Int16x8, int16_t, 8) -SIMD_REPLACE_BOOLEAN_LANE_FUNCTION(Bool16x8, 8) -SIMD_REPLACE_NUMERIC_LANE_FUNCTION(Int8x16, int8_t, 16) -SIMD_REPLACE_BOOLEAN_LANE_FUNCTION(Bool8x16, 16) } // namespace internal } // namespace v8 diff --git a/src/runtime/runtime.h b/src/runtime/runtime.h index 28292a0..5f64b74 100644 --- a/src/runtime/runtime.h +++ b/src/runtime/runtime.h @@ -562,42 +562,178 @@ namespace internal { F(Arguments, 1, 1) -#define FOR_EACH_INTRINSIC_SIMD(F) \ - F(IsSimdValue, 1, 1) \ - F(SimdToObject, 1, 1) \ - F(SimdEquals, 2, 1) \ - F(SimdSameValue, 2, 1) \ - F(SimdSameValueZero, 2, 1) \ - F(CreateFloat32x4, 4, 1) \ - F(CreateInt32x4, 4, 1) \ - F(CreateBool32x4, 4, 1) \ - F(CreateInt16x8, 8, 1) \ - F(CreateBool16x8, 8, 1) \ - F(CreateInt8x16, 16, 1) \ - F(CreateBool8x16, 16, 1) \ - F(Float32x4Check, 1, 1) \ - F(Int32x4Check, 1, 1) \ - F(Bool32x4Check, 1, 1) \ - F(Int16x8Check, 1, 1) \ - F(Bool16x8Check, 1, 1) \ - F(Int8x16Check, 1, 1) \ - F(Bool8x16Check, 1, 1) \ - F(Float32x4ExtractLane, 2, 1) \ - F(Int32x4ExtractLane, 2, 1) \ - F(Bool32x4ExtractLane, 2, 1) \ - F(Int16x8ExtractLane, 2, 1) \ - F(Int16x8UnsignedExtractLane, 2, 1) \ - F(Bool16x8ExtractLane, 2, 1) \ - F(Int8x16ExtractLane, 2, 1) \ - F(Int8x16UnsignedExtractLane, 2, 1) \ - F(Bool8x16ExtractLane, 2, 1) \ - F(Float32x4ReplaceLane, 3, 1) \ - F(Int32x4ReplaceLane, 3, 1) \ - F(Bool32x4ReplaceLane, 3, 1) \ - F(Int16x8ReplaceLane, 3, 1) \ - F(Bool16x8ReplaceLane, 3, 1) \ - F(Int8x16ReplaceLane, 3, 1) \ - F(Bool8x16ReplaceLane, 3, 1) +#define FOR_EACH_INTRINSIC_SIMD(F) \ + F(IsSimdValue, 1, 1) \ + F(SimdToObject, 1, 1) \ + F(SimdEquals, 2, 1) \ + F(SimdSameValue, 2, 1) \ + F(SimdSameValueZero, 2, 1) \ + F(CreateFloat32x4, 4, 1) \ + F(CreateInt32x4, 4, 1) \ + F(CreateBool32x4, 4, 1) \ + F(CreateInt16x8, 8, 1) \ + F(CreateBool16x8, 8, 1) \ + F(CreateInt8x16, 16, 1) \ + F(CreateBool8x16, 16, 1) \ + F(Float32x4Check, 1, 1) \ + F(Float32x4ExtractLane, 2, 1) \ + F(Float32x4ReplaceLane, 3, 1) \ + F(Float32x4Abs, 1, 1) \ + F(Float32x4Neg, 1, 1) \ + F(Float32x4Sqrt, 1, 1) \ + F(Float32x4RecipApprox, 1, 1) \ + F(Float32x4RecipSqrtApprox, 1, 1) \ + F(Float32x4Add, 2, 1) \ + F(Float32x4Sub, 2, 1) \ + F(Float32x4Mul, 2, 1) \ + F(Float32x4Div, 2, 1) \ + F(Float32x4Min, 2, 1) \ + F(Float32x4Max, 2, 1) \ + F(Float32x4MinNum, 2, 1) \ + F(Float32x4MaxNum, 2, 1) \ + F(Float32x4LessThan, 2, 1) \ + F(Float32x4LessThanOrEqual, 2, 1) \ + F(Float32x4GreaterThan, 2, 1) \ + F(Float32x4GreaterThanOrEqual, 2, 1) \ + F(Float32x4Equal, 2, 1) \ + F(Float32x4NotEqual, 2, 1) \ + F(Float32x4Select, 3, 1) \ + F(Float32x4Swizzle, 5, 1) \ + F(Float32x4Shuffle, 6, 1) \ + F(Float32x4FromInt32x4, 1, 1) \ + F(Float32x4FromInt32x4Bits, 1, 1) \ + F(Float32x4FromInt16x8Bits, 1, 1) \ + F(Float32x4FromInt8x16Bits, 1, 1) \ + F(Int32x4Check, 1, 1) \ + F(Int32x4ExtractLane, 2, 1) \ + F(Int32x4ReplaceLane, 3, 1) \ + F(Int32x4Neg, 1, 1) \ + F(Int32x4Add, 2, 1) \ + F(Int32x4Sub, 2, 1) \ + F(Int32x4Mul, 2, 1) \ + F(Int32x4Min, 2, 1) \ + F(Int32x4Max, 2, 1) \ + F(Int32x4And, 2, 1) \ + F(Int32x4Or, 2, 1) \ + F(Int32x4Xor, 2, 1) \ + F(Int32x4Not, 1, 1) \ + F(Int32x4ShiftLeftByScalar, 2, 1) \ + F(Int32x4ShiftRightLogicalByScalar, 2, 1) \ + F(Int32x4ShiftRightArithmeticByScalar, 2, 1) \ + F(Int32x4LessThan, 2, 1) \ + F(Int32x4LessThanOrEqual, 2, 1) \ + F(Int32x4GreaterThan, 2, 1) \ + F(Int32x4GreaterThanOrEqual, 2, 1) \ + F(Int32x4Equal, 2, 1) \ + F(Int32x4NotEqual, 2, 1) \ + F(Int32x4Select, 3, 1) \ + F(Int32x4Swizzle, 5, 1) \ + F(Int32x4Shuffle, 6, 1) \ + F(Int32x4FromFloat32x4, 1, 1) \ + F(Int32x4FromFloat32x4Bits, 1, 1) \ + F(Int32x4FromInt16x8Bits, 1, 1) \ + F(Int32x4FromInt8x16Bits, 1, 1) \ + F(Bool32x4Check, 1, 1) \ + F(Bool32x4ExtractLane, 2, 1) \ + F(Bool32x4ReplaceLane, 3, 1) \ + F(Bool32x4And, 2, 1) \ + F(Bool32x4Or, 2, 1) \ + F(Bool32x4Xor, 2, 1) \ + F(Bool32x4Not, 1, 1) \ + F(Bool32x4AnyTrue, 1, 1) \ + F(Bool32x4AllTrue, 1, 1) \ + F(Bool32x4Equal, 2, 1) \ + F(Bool32x4NotEqual, 2, 1) \ + F(Bool32x4Swizzle, 5, 1) \ + F(Bool32x4Shuffle, 6, 1) \ + F(Int16x8Check, 1, 1) \ + F(Int16x8ExtractLane, 2, 1) \ + F(Int16x8UnsignedExtractLane, 2, 1) \ + F(Int16x8ReplaceLane, 3, 1) \ + F(Int16x8Neg, 1, 1) \ + F(Int16x8Add, 2, 1) \ + F(Int16x8AddSaturate, 2, 1) \ + F(Int16x8Sub, 2, 1) \ + F(Int16x8SubSaturate, 2, 1) \ + F(Int16x8Mul, 2, 1) \ + F(Int16x8Min, 2, 1) \ + F(Int16x8Max, 2, 1) \ + F(Int16x8And, 2, 1) \ + F(Int16x8Or, 2, 1) \ + F(Int16x8Xor, 2, 1) \ + F(Int16x8Not, 1, 1) \ + F(Int16x8ShiftLeftByScalar, 2, 1) \ + F(Int16x8ShiftRightLogicalByScalar, 2, 1) \ + F(Int16x8ShiftRightArithmeticByScalar, 2, 1) \ + F(Int16x8LessThan, 2, 1) \ + F(Int16x8LessThanOrEqual, 2, 1) \ + F(Int16x8GreaterThan, 2, 1) \ + F(Int16x8GreaterThanOrEqual, 2, 1) \ + F(Int16x8Equal, 2, 1) \ + F(Int16x8NotEqual, 2, 1) \ + F(Int16x8Select, 3, 1) \ + F(Int16x8Swizzle, 9, 1) \ + F(Int16x8Shuffle, 10, 1) \ + F(Int16x8FromFloat32x4Bits, 1, 1) \ + F(Int16x8FromInt32x4Bits, 1, 1) \ + F(Int16x8FromInt8x16Bits, 1, 1) \ + F(Bool16x8Check, 1, 1) \ + F(Bool16x8ExtractLane, 2, 1) \ + F(Bool16x8ReplaceLane, 3, 1) \ + F(Bool16x8And, 2, 1) \ + F(Bool16x8Or, 2, 1) \ + F(Bool16x8Xor, 2, 1) \ + F(Bool16x8Not, 1, 1) \ + F(Bool16x8AnyTrue, 1, 1) \ + F(Bool16x8AllTrue, 1, 1) \ + F(Bool16x8Equal, 2, 1) \ + F(Bool16x8NotEqual, 2, 1) \ + F(Bool16x8Swizzle, 9, 1) \ + F(Bool16x8Shuffle, 10, 1) \ + F(Int8x16Check, 1, 1) \ + F(Int8x16ExtractLane, 2, 1) \ + F(Int8x16UnsignedExtractLane, 2, 1) \ + F(Int8x16ReplaceLane, 3, 1) \ + F(Int8x16Neg, 1, 1) \ + F(Int8x16Add, 2, 1) \ + F(Int8x16AddSaturate, 2, 1) \ + F(Int8x16Sub, 2, 1) \ + F(Int8x16SubSaturate, 2, 1) \ + F(Int8x16Mul, 2, 1) \ + F(Int8x16Min, 2, 1) \ + F(Int8x16Max, 2, 1) \ + F(Int8x16And, 2, 1) \ + F(Int8x16Or, 2, 1) \ + F(Int8x16Xor, 2, 1) \ + F(Int8x16Not, 1, 1) \ + F(Int8x16ShiftLeftByScalar, 2, 1) \ + F(Int8x16ShiftRightLogicalByScalar, 2, 1) \ + F(Int8x16ShiftRightArithmeticByScalar, 2, 1) \ + F(Int8x16LessThan, 2, 1) \ + F(Int8x16LessThanOrEqual, 2, 1) \ + F(Int8x16GreaterThan, 2, 1) \ + F(Int8x16GreaterThanOrEqual, 2, 1) \ + F(Int8x16Equal, 2, 1) \ + F(Int8x16NotEqual, 2, 1) \ + F(Int8x16Select, 3, 1) \ + F(Int8x16Swizzle, 17, 1) \ + F(Int8x16Shuffle, 18, 1) \ + F(Int8x16FromFloat32x4Bits, 1, 1) \ + F(Int8x16FromInt32x4Bits, 1, 1) \ + F(Int8x16FromInt16x8Bits, 1, 1) \ + F(Bool8x16Check, 1, 1) \ + F(Bool8x16ExtractLane, 2, 1) \ + F(Bool8x16ReplaceLane, 3, 1) \ + F(Bool8x16And, 2, 1) \ + F(Bool8x16Or, 2, 1) \ + F(Bool8x16Xor, 2, 1) \ + F(Bool8x16Not, 1, 1) \ + F(Bool8x16AnyTrue, 1, 1) \ + F(Bool8x16AllTrue, 1, 1) \ + F(Bool8x16Equal, 2, 1) \ + F(Bool8x16NotEqual, 2, 1) \ + F(Bool8x16Swizzle, 17, 1) \ + F(Bool8x16Shuffle, 18, 1) #define FOR_EACH_INTRINSIC_STRINGS(F) \ -- 2.7.4