Repository: tetratelabs/wazero
Pull request #1681 (2023-09-04 04:38:15)

wazevo(arm64): adds fast path for loading zero f32/64
#1496 


Patch:
diff --git a/internal/engine/wazevo/backend/isa/arm64/instr.go b/internal/engine/wazevo/backend/isa/arm64/instr.go
index d90c99a4..084b70bd 100644
--- a/internal/engine/wazevo/backend/isa/arm64/instr.go
+++ b/internal/engine/wazevo/backend/isa/arm64/instr.go
@@ -1479,6 +1479,8 @@ func (b vecOp) String() string {
 		return "uaddlv"
 	case vecOpBit:
 		return "bit"
+	case vecOpEOR:
+		return "eor"
 	}
 	panic(int(b))
 }
@@ -1487,6 +1489,7 @@ const (
 	vecOpCnt vecOp = iota
 	vecOpUaddlv
 	vecOpBit
+	vecOpEOR
 )
 
 // bitOp determines the type of bitwise operation. Instructions whose kind is one of
diff --git a/internal/engine/wazevo/backend/isa/arm64/instr_encoding.go b/internal/engine/wazevo/backend/isa/arm64/instr_encoding.go
index 92c00fa4..271d9e1a 100644
--- a/internal/engine/wazevo/backend/isa/arm64/instr_encoding.go
+++ b/internal/engine/wazevo/backend/isa/arm64/instr_encoding.go
@@ -322,6 +322,17 @@ func encodeVecRRR(op vecOp, rd, rn, rm uint32, arr vecArrangement) uint32 {
 			panic("BUG")
 		}
 		return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b00011, 0b10, 0b1, q)
+	case vecOpEOR:
+		var q uint32
+		switch arr {
+		case vecArrangement8B:
+			q = 0b0
+		case vecArrangement16B:
+			q = 0b1
+		default:
+			panic("BUG")
+		}
+		return encodeAdvancedSIMDThreeSame(rd, rn, rm, 0b00011, 0b00, 0b1, q)
 	default:
 		panic("TODO")
 	}
diff --git a/internal/engine/wazevo/backend/isa/arm64/lower_constant.go b/internal/engine/wazevo/backend/isa/arm64/lower_constant.go
index f88affe4..1f1ce50e 100644
--- a/internal/engine/wazevo/backend/isa/arm64/lower_constant.go
+++ b/internal/engine/wazevo/backend/isa/arm64/lower_constant.go
@@ -28,11 +28,21 @@ func (m *machine) InsertLoadConstant(instr *ssa.Instruction, vr regalloc.VReg) {
 	switch valType {
 	case ssa.TypeF32:
 		loadF := m.allocateInstr()
-		loadF.asLoadFpuConst32(vr, v)
+		if v == 0 {
+			// Fast path for zero.
+			loadF.asVecRRR(vecOpEOR, operandNR(vr), operandNR(vr), operandNR(vr), vecArrangement8B)
+		} else {
+			loadF.asLoadFpuConst32(vr, v)
+		}
 		m.insert(loadF)
 	case ssa.TypeF64:
 		loadF := m.allocateInstr()
-		loadF.asLoadFpuConst64(vr, v)
+		if v == 0 {
+			// Fast path for zero.
+			loadF.asVecRRR(vecOpEOR, operandNR(vr), operandNR(vr), operandNR(vr), vecArrangement8B)
+		} else {
+			loadF.asLoadFpuConst64(vr, v)
+		}
 		m.insert(loadF)
 	case ssa.TypeI32:
 		if v == 0 {


Test patch:
diff --git a/internal/engine/wazevo/backend/isa/arm64/instr_encoding_test.go b/internal/engine/wazevo/backend/isa/arm64/instr_encoding_test.go
index 30158e7e..3563fd07 100644
--- a/internal/engine/wazevo/backend/isa/arm64/instr_encoding_test.go
+++ b/internal/engine/wazevo/backend/isa/arm64/instr_encoding_test.go
@@ -34,6 +34,12 @@ func TestInstruction_encode(t *testing.T) {
 		{want: "411ca36e", setup: func(i *instruction) {
 			i.asVecRRR(vecOpBit, operandNR(v1VReg), operandNR(v2VReg), operandNR(v3VReg), vecArrangement16B)
 		}},
+		{want: "411c236e", setup: func(i *instruction) {
+			i.asVecRRR(vecOpEOR, operandNR(v1VReg), operandNR(v2VReg), operandNR(v3VReg), vecArrangement16B)
+		}},
+		{want: "411c232e", setup: func(i *instruction) {
+			i.asVecRRR(vecOpEOR, operandNR(v1VReg), operandNR(v2VReg), operandNR(v3VReg), vecArrangement8B)
+		}},
 		{want: "4100839a", setup: func(i *instruction) { i.asCSel(operandNR(x1VReg), operandNR(x2VReg), operandNR(x3VReg), eq, true) }},
 		{want: "4110839a", setup: func(i *instruction) { i.asCSel(operandNR(x1VReg), operandNR(x2VReg), operandNR(x3VReg), ne, true) }},
 		{want: "4100831a", setup: func(i *instruction) { i.asCSel(operandNR(x1VReg), operandNR(x2VReg), operandNR(x3VReg), eq, false) }},