Repository: tetratelabs/wazero
Pull request #1764 (2023-10-06 04:26:09)

wazevo(arm64): support for zero imm lsl
This relaxes the assertion in https://github.com/tetratelabs/wazero/pull/1763

#1496 


Patch:
diff --git a/internal/engine/wazevo/backend/isa/arm64/instr_encoding.go b/internal/engine/wazevo/backend/isa/arm64/instr_encoding.go
index 41de44ad..4d2daa0e 100644
--- a/internal/engine/wazevo/backend/isa/arm64/instr_encoding.go
+++ b/internal/engine/wazevo/backend/isa/arm64/instr_encoding.go
@@ -1715,9 +1715,6 @@ func encodeMoveWideImmediate(opc uint32, rd uint32, imm, shift, _64bit uint64) (
 // encodeAluRRImm encodes as "Bitfield" in
 // https://developer.arm.com/documentation/ddi0596/2020-12/Index-by-Encoding/Data-Processing----Immediate?lang=en#log_imm
 func encodeAluRRImm(op aluOp, rd, rn, amount, _64bit uint32) uint32 {
-	if amount == 0 {
-		panic("Shifting by 0 is not allowed; must be optimized out")
-	}
 	var opc uint32
 	var immr, imms uint32
 	switch op {
@@ -1725,12 +1722,22 @@ func encodeAluRRImm(op aluOp, rd, rn, amount, _64bit uint32) uint32 {
 		// LSL (immediate) is an alias for UBFM.
 		// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/UBFM--Unsigned-Bitfield-Move-?lang=en
 		opc = 0b10
-		if _64bit == 1 {
-			immr = 64 - amount
+		if amount == 0 {
+			// This can be encoded as NOP, but we don't do it for consistency: lsr xn, xm, #0
+			immr = 0
+			if _64bit == 1 {
+				imms = 0b111111
+			} else {
+				imms = 0b11111
+			}
 		} else {
-			immr = 32 - amount
+			if _64bit == 1 {
+				immr = 64 - amount
+			} else {
+				immr = (32 - amount) & 0b11111
+			}
+			imms = immr - 1
 		}
-		imms = immr - 1
 	case aluOpLsr:
 		// LSR (immediate) is an alias for UBFM.
 		// https://developer.arm.com/documentation/ddi0596/2021-12/Base-Instructions/LSR--immediate---Logical-Shift-Right--immediate---an-alias-of-UBFM-?lang=en
diff --git a/internal/engine/wazevo/ssa/instructions.go b/internal/engine/wazevo/ssa/instructions.go
index 0fe82ec5..8a8777df 100644
--- a/internal/engine/wazevo/ssa/instructions.go
+++ b/internal/engine/wazevo/ssa/instructions.go
@@ -639,60 +639,21 @@ const (
 	// `v = bxor_not x, y`.
 	OpcodeBxorNot
 
-	// OpcodeBandImm ...
-	// `v = band_imm x, Y`. (BinaryImm64)
-	OpcodeBandImm
-
-	// OpcodeBorImm ...
-	// `v = bor_imm x, Y`. (BinaryImm64)
-	OpcodeBorImm
-
-	// OpcodeBxorImm ...
-	// `v = bxor_imm x, Y`. (BinaryImm64)
-	OpcodeBxorImm
-
 	// OpcodeRotl rotates the given integer value to the left: `v = Rotl x, y`.
 	OpcodeRotl
 
 	// OpcodeRotr rotates the given integer value to the right: `v = Rotr x, y`.
 	OpcodeRotr
 
-	// OpcodeRotlImm ...
-	// `v = rotl_imm x, Y`. (BinaryImm64)
-	OpcodeRotlImm
-
-	// OpcodeRotrImm ...
-	// `v = rotr_imm x, Y`. (BinaryImm64)
-	OpcodeRotrImm
-
-	// OpcodeIshl ...
-	// `v = ishl x, y`.
+	// OpcodeIshl does logical shift left: `v = Ishl x, y`.
 	OpcodeIshl
 
-	// OpcodeUshr ...
-	// `v = ushr x, y`.
+	// OpcodeUshr does logical shift right: `v = Ushr x, y`.
 	OpcodeUshr
 
-	// OpcodeSshr ...
-	// `v = sshr x, y`.
+	// OpcodeSshr does arithmetic shift right: `v = Sshr x, y`.
 	OpcodeSshr
 
-	// OpcodeIshlImm ...
-	// `v = ishl_imm x, Y`. (BinaryImm64)
-	OpcodeIshlImm
-
-	// OpcodeUshrImm ...
-	// `v = ushr_imm x, Y`. (BinaryImm64)
-	OpcodeUshrImm
-
-	// OpcodeSshrImm ...
-	// `v = sshr_imm x, Y`. (BinaryImm64)
-	OpcodeSshrImm
-
-	// OpcodeBitrev ...
-	// `v = bitrev x`.
-	OpcodeBitrev
-
 	// OpcodeClz counts the number of leading zeros: `v = clz x`.
 	OpcodeClz
 
@@ -2897,34 +2858,16 @@ func (o Opcode) String() (ret string) {
 		return "BorNot"
 	case OpcodeBxorNot:
 		return "BxorNot"
-	case OpcodeBandImm:
-		return "BandImm"
-	case OpcodeBorImm:
-		return "BorImm"
-	case OpcodeBxorImm:
-		return "BxorImm"
 	case OpcodeRotl:
 		return "Rotl"
 	case OpcodeRotr:
 		return "Rotr"
-	case OpcodeRotlImm:
-		return "RotlImm"
-	case OpcodeRotrImm:
-		return "RotrImm"
 	case OpcodeIshl:
 		return "Ishl"
 	case OpcodeUshr:
 		return "Ushr"
 	case OpcodeSshr:
 		return "Sshr"
-	case OpcodeIshlImm:
-		return "IshlImm"
-	case OpcodeUshrImm:
-		return "UshrImm"
-	case OpcodeSshrImm:
-		return "SshrImm"
-	case OpcodeBitrev:
-		return "Bitrev"
 	case OpcodeClz:
 		return "Clz"
 	case OpcodeCtz:


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 d4cf2ed0..1c7ee1c4 100644
--- a/internal/engine/wazevo/backend/isa/arm64/instr_encoding_test.go
+++ b/internal/engine/wazevo/backend/isa/arm64/instr_encoding_test.go
@@ -1398,6 +1398,12 @@ func TestInstruction_encode(t *testing.T) {
 		{want: "4008d41a", setup: func(i *instruction) {
 			i.asALU(aluOpUDiv, operandNR(x0VReg), operandNR(x2VReg), operandNR(x20VReg), false)
 		}},
+		{want: "407c0013", setup: func(i *instruction) {
+			i.asALUShift(aluOpAsr, operandNR(x0VReg), operandNR(x2VReg), operandShiftImm(0), false)
+		}},
+		{want: "40fc4093", setup: func(i *instruction) {
+			i.asALUShift(aluOpAsr, operandNR(x0VReg), operandNR(x2VReg), operandShiftImm(0), true)
+		}},
 		{want: "407c0113", setup: func(i *instruction) {
 			i.asALUShift(aluOpAsr, operandNR(x0VReg), operandNR(x2VReg), operandShiftImm(1), false)
 		}},
@@ -1428,6 +1434,12 @@ func TestInstruction_encode(t *testing.T) {
 		{want: "40fc7fd3", setup: func(i *instruction) {
 			i.asALUShift(aluOpLsr, operandNR(x0VReg), operandNR(x2VReg), operandShiftImm(63), true)
 		}},
+		{want: "407c0053", setup: func(i *instruction) {
+			i.asALUShift(aluOpLsl, operandNR(x0VReg), operandNR(x2VReg), operandShiftImm(0), false)
+		}},
+		{want: "40fc40d3", setup: func(i *instruction) {
+			i.asALUShift(aluOpLsl, operandNR(x0VReg), operandNR(x2VReg), operandShiftImm(0), true)
+		}},
 		{want: "40781f53", setup: func(i *instruction) {
 			i.asALUShift(aluOpLsl, operandNR(x0VReg), operandNR(x2VReg), operandShiftImm(1), false)
 		}},