Skip to content

Commit b68ac90

Browse files
danylo1999V8-internal LUCI CQ
authored andcommitted
[wasm] add support for relaxed ternary SIMDs
This adds madd, nmadd, laneselect, dot_i8x16_i7x16_add_s from the relaxed SIMD proposal. Bug: 427134596 Change-Id: I9bbb71973d3ca501e878d666076c5bdbd0526339 Reviewed-on: https://chrome-internal-review.googlesource.com/c/v8/fuzzilli/+/8444156 Commit-Queue: Danylo Mocherniuk <[email protected]> Reviewed-by: Matthias Liedtke <[email protected]>
1 parent 6d18850 commit b68ac90

16 files changed

+510
-135
lines changed

Sources/Fuzzilli/Base/ProgramBuilder.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3623,6 +3623,11 @@ public class ProgramBuilder {
36233623
return b.emit(WasmSimd128IntegerBinOp(shape: shape, binOpKind: integerBinOpKind), withInputs: [left, right], types: [.wasmSimd128, rhsInputType]).output
36243624
}
36253625

3626+
@discardableResult
3627+
public func wasmSimd128IntegerTernaryOp(_ left: Variable, _ mid: Variable, _ right: Variable, _ shape: WasmSimd128Shape, _ integerTernaryOpKind: WasmSimd128IntegerTernaryOpKind) -> Variable {
3628+
return b.emit(WasmSimd128IntegerTernaryOp(shape: shape, ternaryOpKind: integerTernaryOpKind), withInputs: [left, mid, right], types: [.wasmSimd128, .wasmSimd128, .wasmSimd128]).output
3629+
}
3630+
36263631
@discardableResult
36273632
public func wasmSimd128FloatUnOp(_ input: Variable, _ shape: WasmSimd128Shape, _ floatUnOpKind: WasmSimd128FloatUnOpKind) -> Variable {
36283633
return b.emit(WasmSimd128FloatUnOp(shape: shape, unOpKind: floatUnOpKind), withInputs: [input], types: [.wasmSimd128]).output
@@ -3633,6 +3638,11 @@ public class ProgramBuilder {
36333638
return b.emit(WasmSimd128FloatBinOp(shape: shape, binOpKind: floatBinOpKind), withInputs: [left, right], types: [.wasmSimd128, .wasmSimd128]).output
36343639
}
36353640

3641+
@discardableResult
3642+
public func wasmSimd128FloatTernaryOp(_ left: Variable, _ mid: Variable, _ right: Variable, _ shape: WasmSimd128Shape, _ floatTernaryOpKind: WasmSimd128FloatTernaryOpKind) -> Variable {
3643+
return b.emit(WasmSimd128FloatTernaryOp(shape: shape, ternaryOpKind: floatTernaryOpKind), withInputs: [left, mid, right], types: [.wasmSimd128, .wasmSimd128, .wasmSimd128]).output
3644+
}
3645+
36363646
@discardableResult
36373647
public func wasmSimd128Compare(_ lhs: Variable, _ rhs: Variable, _ shape: WasmSimd128Shape, _ compareOpKind: WasmSimd128CompareOpKind) -> Variable {
36383648
return b.emit(WasmSimd128Compare(shape: shape, compareOpKind: compareOpKind), withInputs: [lhs, rhs], types: [.wasmSimd128, .wasmSimd128]).output

Sources/Fuzzilli/CodeGen/CodeGeneratorWeights.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,8 +303,10 @@ public let codeGeneratorWeights = [
303303
"ConstSimd128Generator": 5,
304304
"WasmSimd128IntegerUnOpGenerator": 5,
305305
"WasmSimd128IntegerBinOpGenerator": 5,
306+
"WasmSimd128IntegerTernaryOpGenerator": 2,
306307
"WasmSimd128FloatUnOpGenerator": 5,
307308
"WasmSimd128FloatBinOpGenerator": 5,
309+
"WasmSimd128FloatTernaryOpGenerator": 2,
308310
"WasmSimd128CompareGenerator": 5,
309311
"WasmSimdSplatGenerator": 5,
310312
"WasmSimdExtractLaneGenerator": 5,

Sources/Fuzzilli/CodeGen/WasmCodeGenerators.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,16 @@ public let WasmCodeGenerators: [CodeGenerator] = [
10521052
function.wasmSimd128IntegerBinOp(lhs, rhs, shape, binOpKind)
10531053
},
10541054

1055+
CodeGenerator("WasmSimd128IntegerTernaryOpGenerator", inContext: .wasmFunction, inputs: .required(.wasmSimd128, .wasmSimd128, .wasmSimd128)) { b, left, mid, right in
1056+
let shape = chooseUniform(from: WasmSimd128Shape.allCases.filter{ $0.isFloat() } )
1057+
let ternaryOpKind = chooseUniform(from: WasmSimd128IntegerTernaryOpKind.allCases.filter{
1058+
$0.isValidForShape(shape: shape)
1059+
})
1060+
1061+
let function = b.currentWasmModule.currentWasmFunction;
1062+
function.wasmSimd128IntegerTernaryOp(left, mid, right, shape, ternaryOpKind)
1063+
},
1064+
10551065
CodeGenerator("WasmSimd128FloatUnOpGenerator", inContext: .wasmFunction, inputs: .required(.wasmSimd128)) { b, input in
10561066
let shape = chooseUniform(from: WasmSimd128Shape.allCases.filter{ $0.isFloat() })
10571067
let unOpKind = chooseUniform(from: WasmSimd128FloatUnOpKind.allCases.filter{
@@ -1072,6 +1082,16 @@ public let WasmCodeGenerators: [CodeGenerator] = [
10721082
function.wasmSimd128FloatBinOp(lhs, rhs, shape, binOpKind)
10731083
},
10741084

1085+
CodeGenerator("WasmSimd128FloatTernaryOpGenerator", inContext: .wasmFunction, inputs: .required(.wasmSimd128, .wasmSimd128, .wasmSimd128)) { b, left, mid, right in
1086+
let shape = chooseUniform(from: WasmSimd128Shape.allCases.filter{ $0.isFloat() } )
1087+
let ternaryOpKind = chooseUniform(from: WasmSimd128FloatTernaryOpKind.allCases.filter{
1088+
$0.isValidForShape(shape: shape)
1089+
})
1090+
1091+
let function = b.currentWasmModule.currentWasmFunction;
1092+
function.wasmSimd128FloatTernaryOp(left, mid, right, shape, ternaryOpKind)
1093+
},
1094+
10751095
CodeGenerator("WasmSimd128CompareGenerator", inContext: .wasmFunction, inputs: .required(.wasmSimd128, .wasmSimd128)) { b, lhs, rhs in
10761096
let shape = chooseUniform(from: WasmSimd128Shape.allCases)
10771097
let compareOpKind = b.randomSimd128CompareOpKind(shape)

Sources/Fuzzilli/FuzzIL/Instruction.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,6 +1409,11 @@ extension Instruction: ProtobufConvertible {
14091409
$0.shape = UInt32(op.shape.rawValue)
14101410
$0.binaryOperator = Int32(op.binOpKind.rawValue)
14111411
}
1412+
case .wasmSimd128IntegerTernaryOp(let op):
1413+
$0.wasmSimd128IntegerTernaryOp = Fuzzilli_Protobuf_WasmSimd128IntegerTernaryOp.with {
1414+
$0.shape = UInt32(op.shape.rawValue)
1415+
$0.opcode = Int32(op.ternaryOpKind.rawValue)
1416+
}
14121417
case .wasmSimd128FloatUnOp(let op):
14131418
$0.wasmSimd128FloatUnOp = Fuzzilli_Protobuf_WasmSimd128FloatUnOp.with {
14141419
$0.shape = UInt32(op.shape.rawValue)
@@ -1419,6 +1424,11 @@ extension Instruction: ProtobufConvertible {
14191424
$0.shape = UInt32(op.shape.rawValue)
14201425
$0.binaryOperator = Int32(op.binOpKind.rawValue)
14211426
}
1427+
case .wasmSimd128FloatTernaryOp(let op):
1428+
$0.wasmSimd128FloatTernaryOp = Fuzzilli_Protobuf_WasmSimd128FloatTernaryOp.with {
1429+
$0.shape = UInt32(op.shape.rawValue)
1430+
$0.opcode = Int32(op.ternaryOpKind.rawValue)
1431+
}
14221432
case .wasmSimd128Compare(let op):
14231433
$0.wasmSimd128Compare = Fuzzilli_Protobuf_WasmSimd128Compare.with {
14241434
$0.shape = UInt32(op.shape.rawValue)
@@ -2362,6 +2372,10 @@ extension Instruction: ProtobufConvertible {
23622372
let shape = WasmSimd128Shape(rawValue: UInt8(p.shape))!
23632373
let binOpKind = WasmSimd128IntegerBinOpKind(rawValue: Int(p.binaryOperator))!
23642374
op = WasmSimd128IntegerBinOp(shape: shape, binOpKind: binOpKind)
2375+
case .wasmSimd128IntegerTernaryOp(let p):
2376+
let shape = WasmSimd128Shape(rawValue: UInt8(p.shape))!
2377+
let ternaryOpKind = WasmSimd128IntegerTernaryOpKind(rawValue: Int(p.opcode))!
2378+
op = WasmSimd128IntegerTernaryOp(shape: shape, ternaryOpKind: ternaryOpKind)
23652379
case .wasmSimd128FloatUnOp(let p):
23662380
let shape = WasmSimd128Shape(rawValue: UInt8(p.shape))!
23672381
let unOpKind = WasmSimd128FloatUnOpKind(rawValue: Int(p.unaryOperator))!
@@ -2370,6 +2384,10 @@ extension Instruction: ProtobufConvertible {
23702384
let shape = WasmSimd128Shape(rawValue: UInt8(p.shape))!
23712385
let binOpKind = WasmSimd128FloatBinOpKind(rawValue: Int(p.binaryOperator))!
23722386
op = WasmSimd128FloatBinOp(shape: shape, binOpKind: binOpKind)
2387+
case .wasmSimd128FloatTernaryOp(let p):
2388+
let shape = WasmSimd128Shape(rawValue: UInt8(p.shape))!
2389+
let ternaryOpKind = WasmSimd128FloatTernaryOpKind(rawValue: Int(p.opcode))!
2390+
op = WasmSimd128FloatTernaryOp(shape: shape, ternaryOpKind: ternaryOpKind)
23732391
case .wasmSimd128Compare(let p):
23742392
let shape = WasmSimd128Shape(rawValue: UInt8(p.shape))!
23752393
let compareOpKind = if shape.isFloat() {

Sources/Fuzzilli/FuzzIL/JSTyper.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,8 +622,10 @@ public struct JSTyper: Analyzer {
622622
case .constSimd128(_),
623623
.wasmSimd128Compare(_),
624624
.wasmSimd128IntegerBinOp(_),
625+
.wasmSimd128IntegerTernaryOp(_),
625626
.wasmSimd128FloatUnOp(_),
626627
.wasmSimd128FloatBinOp(_),
628+
.wasmSimd128FloatTernaryOp(_),
627629
.wasmSimdSplat(_),
628630
.wasmSimdLoad(_),
629631
.wasmSimdLoadLane(_),

Sources/Fuzzilli/FuzzIL/Opcodes.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,8 +316,10 @@ enum Opcode {
316316
case wasmSimd128Compare(WasmSimd128Compare)
317317
case wasmSimd128IntegerUnOp(WasmSimd128IntegerUnOp)
318318
case wasmSimd128IntegerBinOp(WasmSimd128IntegerBinOp)
319+
case wasmSimd128IntegerTernaryOp(WasmSimd128IntegerTernaryOp)
319320
case wasmSimd128FloatUnOp(WasmSimd128FloatUnOp)
320321
case wasmSimd128FloatBinOp(WasmSimd128FloatBinOp)
322+
case wasmSimd128FloatTernaryOp(WasmSimd128FloatTernaryOp)
321323
case wasmSimdSplat(WasmSimdSplat)
322324
case wasmSimdExtractLane(WasmSimdExtractLane)
323325
case wasmSimdReplaceLane(WasmSimdReplaceLane)

Sources/Fuzzilli/FuzzIL/WasmOperations.swift

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1555,6 +1555,37 @@ final class WasmSimd128IntegerBinOp: WasmOperation {
15551555
}
15561556
}
15571557

1558+
public enum WasmSimd128IntegerTernaryOpKind: Int, CaseIterable {
1559+
// i8x16: 0x100 + offset
1560+
// i16x8: 0x101 + offset
1561+
// i32x4: 0x102 + offset
1562+
// i64x2: 0x103 + offset
1563+
1564+
case relaxed_laneselect = 9
1565+
case relaxed_dot_i8x16_i7x16_add_s = 17
1566+
1567+
func isValidForShape(shape: WasmSimd128Shape) -> Bool {
1568+
if shape.isFloat() { return false }
1569+
switch self {
1570+
case .relaxed_laneselect: return true
1571+
case .relaxed_dot_i8x16_i7x16_add_s: return shape == .i32x4
1572+
}
1573+
}
1574+
}
1575+
1576+
final class WasmSimd128IntegerTernaryOp: WasmOperation {
1577+
override var opcode: Opcode { .wasmSimd128IntegerTernaryOp(self) }
1578+
let shape: WasmSimd128Shape
1579+
let ternaryOpKind: WasmSimd128IntegerTernaryOpKind
1580+
1581+
init(shape: WasmSimd128Shape, ternaryOpKind: WasmSimd128IntegerTernaryOpKind) {
1582+
assert(ternaryOpKind.isValidForShape(shape: shape))
1583+
self.shape = shape
1584+
self.ternaryOpKind = ternaryOpKind
1585+
super.init(numInputs: 3, numOutputs: 1, attributes: [.isMutable], requiredContext: [.wasmFunction])
1586+
}
1587+
}
1588+
15581589
public enum WasmSimd128FloatUnOpKind: Int, CaseIterable {
15591590
case ceil
15601591
case floor
@@ -1631,6 +1662,30 @@ final class WasmSimd128FloatBinOp: WasmOperation {
16311662
}
16321663
}
16331664

1665+
public enum WasmSimd128FloatTernaryOpKind: Int, CaseIterable {
1666+
// f32x4: 0x100 + offset
1667+
// f64x2: 0x102 + offset
1668+
case madd = 5
1669+
case nmadd = 6
1670+
1671+
func isValidForShape(shape: WasmSimd128Shape) -> Bool {
1672+
return shape.isFloat()
1673+
}
1674+
}
1675+
1676+
final class WasmSimd128FloatTernaryOp: WasmOperation {
1677+
override var opcode: Opcode { .wasmSimd128FloatTernaryOp(self) }
1678+
let shape: WasmSimd128Shape
1679+
let ternaryOpKind: WasmSimd128FloatTernaryOpKind
1680+
1681+
init(shape: WasmSimd128Shape, ternaryOpKind: WasmSimd128FloatTernaryOpKind) {
1682+
assert(ternaryOpKind.isValidForShape(shape: shape))
1683+
self.shape = shape
1684+
self.ternaryOpKind = ternaryOpKind
1685+
super.init(numInputs: 3, numOutputs: 1, attributes: [.isMutable], requiredContext: [.wasmFunction])
1686+
}
1687+
}
1688+
16341689
final class WasmSimdSplat: WasmOperation {
16351690
enum Kind: UInt8, CaseIterable {
16361691
case I8x16 = 0x0F

Sources/Fuzzilli/Lifting/FuzzILLifter.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1190,12 +1190,18 @@ public class FuzzILLifter: Lifter {
11901190
case .wasmSimd128IntegerBinOp(let op):
11911191
w.emit("\(output()) <- WasmSimd128IntegerBinOp \(op.shape) \(op.binOpKind) \(input(0)) \(input(1))")
11921192

1193+
case .wasmSimd128IntegerTernaryOp(let op):
1194+
w.emit("\(output()) <- WasmSimd128IntegerTernaryOp \(op.shape) \(op.ternaryOpKind) \(input(0)) \(input(1)) \(input(2))")
1195+
11931196
case .wasmSimd128FloatUnOp(let op):
11941197
w.emit("\(output()) <- WasmSimd128FloatUnOp \(op.shape).\(op.unOpKind) \(input(0))")
11951198

11961199
case .wasmSimd128FloatBinOp(let op):
11971200
w.emit("\(output()) <- WasmSimd128FloatBinOp \(op.shape).\(op.binOpKind) \(input(0)) \(input(1))")
11981201

1202+
case .wasmSimd128FloatTernaryOp(let op):
1203+
w.emit("\(output()) <- WasmSimd128FloatTernaryOp \(op.shape).\(op.ternaryOpKind) \(input(0)) \(input(1)) \(input(2))")
1204+
11991205
case .wasmSimd128Compare(let op):
12001206
w.emit("\(output()) <- WasmSimd128Compare \(op.shape) \(op.compareOpKind) \(input(0)) \(input(1))")
12011207

Sources/Fuzzilli/Lifting/JavaScriptLifter.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1655,8 +1655,10 @@ public class JavaScriptLifter: Lifter {
16551655
.constSimd128(_),
16561656
.wasmSimd128IntegerUnOp(_),
16571657
.wasmSimd128IntegerBinOp(_),
1658+
.wasmSimd128IntegerTernaryOp(_),
16581659
.wasmSimd128FloatUnOp(_),
16591660
.wasmSimd128FloatBinOp(_),
1661+
.wasmSimd128FloatTernaryOp(_),
16601662
.wasmSimd128Compare(_),
16611663
.wasmSimdSplat(_),
16621664
.wasmSimdExtractLane(_),

Sources/Fuzzilli/Lifting/WasmLifter.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1893,6 +1893,16 @@ public class WasmLifter {
18931893
encoding += Leb128.unsignedEncode(0x01)
18941894
}
18951895
return encoding
1896+
case .wasmSimd128IntegerTernaryOp(let op):
1897+
assert(WasmSimd128IntegerTernaryOpKind.allCases.count == 2, "New WasmSimd128IntegerTernaryOpKind added: check if the encoding is still correct!")
1898+
let base = switch op.shape {
1899+
case .i8x16: 0x100
1900+
case .i16x8: 0x101
1901+
case .i32x4: 0x102
1902+
case .i64x2: 0x103
1903+
default: fatalError("Shape \(op.shape) not supported for WasmSimd128IntegerTernaryOp")
1904+
}
1905+
return Data([Prefix.Simd.rawValue]) + Leb128.unsignedEncode(base + op.ternaryOpKind.rawValue) + Leb128.unsignedEncode(0x01)
18961906
case .wasmSimd128FloatUnOp(let op):
18971907
assert(WasmSimd128FloatUnOpKind.allCases.count == 7, "New WasmSimd128FloatUnOpKind added: check if the encoding is still correct!")
18981908
let encoding = switch op.shape {
@@ -1920,6 +1930,14 @@ public class WasmLifter {
19201930
case .wasmSimd128FloatBinOp(let op):
19211931
assert(WasmSimd128FloatBinOpKind.allCases.count == 10, "New WasmSimd128FloatBinOpKind added: check if the encoding is still correct!")
19221932
return Data([Prefix.Simd.rawValue]) + Leb128.unsignedEncode(op.getOpcode()) + Leb128.unsignedEncode(0x01)
1933+
case .wasmSimd128FloatTernaryOp(let op):
1934+
assert(WasmSimd128FloatTernaryOpKind.allCases.count == 2, "New WasmSimd128FloatTernaryOpKind added: check if the encoding is still correct!")
1935+
let base = switch op.shape {
1936+
case .f32x4: 0x100
1937+
case .f64x2: 0x102
1938+
default: fatalError("Shape \(op.shape) not supported for WasmSimd128FloatTernaryOp")
1939+
}
1940+
return Data([Prefix.Simd.rawValue]) + Leb128.unsignedEncode(base + op.ternaryOpKind.rawValue) + Leb128.unsignedEncode(0x01)
19231941
case .wasmSimd128Compare(let op):
19241942
assert(WasmIntegerCompareOpKind.allCases.count == 10, "New WasmIntegerCompareOpKind added: check if the encoding is still correct!")
19251943
assert(WasmFloatCompareOpKind.allCases.count == 6, "New WasmFloatCompareOpKind added: check if the encoding is still correct!")

0 commit comments

Comments
 (0)