cmd/compile: use SLLW for Lsh32x(64|32|16|8) on riscv64

Use SLLW for left shift of 32 bit values on riscv64 - this potentially
avoids the need to extend the input and/or output.

Change-Id: I19dcf624af9ad8245c48e0810eec7a676a164f91
Reviewed-on: https://go-review.googlesource.com/c/go/+/748921
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Julian Zhu <jz531210@gmail.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
diff --git a/src/cmd/compile/internal/ssa/_gen/RISCV64.rules b/src/cmd/compile/internal/ssa/_gen/RISCV64.rules
index 491be21..504c75a 100644
--- a/src/cmd/compile/internal/ssa/_gen/RISCV64.rules
+++ b/src/cmd/compile/internal/ssa/_gen/RISCV64.rules
@@ -120,8 +120,9 @@
 
 // Shifts
 
-// SLL only considers the bottom 6 bits of y. If y > 64, the result should
-// always be 0.
+// SLL only considers the bottom 6 bits of y, similarly SLLW only considers the
+// bottom 5 bits of y. Ensure that the result is always zero if the shift exceeds
+// the maximum value.
 //
 // Breaking down the operation:
 //
@@ -130,27 +131,27 @@
 // If y < 64, this is the value we want. Otherwise, we want zero.
 //
 // So, we AND with -1 * uint64(y < 64), which is 0xfffff... if y < 64 and 0 otherwise.
-(Lsh8x8   <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL <t> x y) (Neg8  <t> (SLTIU <t> [64] (ZeroExt8to64  y))))
-(Lsh8x16  <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL <t> x y) (Neg8  <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
-(Lsh8x32  <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL <t> x y) (Neg8  <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
-(Lsh8x64  <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL <t> x y) (Neg8  <t> (SLTIU <t> [64] y)))
-(Lsh16x8  <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL <t> x y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt8to64  y))))
-(Lsh16x16 <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL <t> x y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
-(Lsh16x32 <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL <t> x y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
-(Lsh16x64 <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL <t> x y) (Neg16 <t> (SLTIU <t> [64] y)))
-(Lsh32x8  <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt8to64  y))))
-(Lsh32x16 <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
-(Lsh32x32 <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
-(Lsh32x64 <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] y)))
-(Lsh64x8  <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt8to64  y))))
-(Lsh64x16 <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
-(Lsh64x32 <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
-(Lsh64x64 <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL <t> x y) (Neg64 <t> (SLTIU <t> [64] y)))
+(Lsh8x8   <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL  <t> x y) (Neg8  <t> (SLTIU <t> [64] (ZeroExt8to64  y))))
+(Lsh8x16  <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL  <t> x y) (Neg8  <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
+(Lsh8x32  <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL  <t> x y) (Neg8  <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
+(Lsh8x64  <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL  <t> x y) (Neg8  <t> (SLTIU <t> [64] y)))
+(Lsh16x8  <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL  <t> x y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt8to64  y))))
+(Lsh16x16 <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL  <t> x y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
+(Lsh16x32 <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL  <t> x y) (Neg16 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
+(Lsh16x64 <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL  <t> x y) (Neg16 <t> (SLTIU <t> [64] y)))
+(Lsh32x8  <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLLW <t> x y) (Neg32 <t> (SLTIU <t> [32] (ZeroExt8to64  y))))
+(Lsh32x16 <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLLW <t> x y) (Neg32 <t> (SLTIU <t> [32] (ZeroExt16to64 y))))
+(Lsh32x32 <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLLW <t> x y) (Neg32 <t> (SLTIU <t> [32] (ZeroExt32to64 y))))
+(Lsh32x64 <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLLW <t> x y) (Neg32 <t> (SLTIU <t> [32] y)))
+(Lsh64x8  <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL  <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt8to64  y))))
+(Lsh64x16 <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL  <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
+(Lsh64x32 <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL  <t> x y) (Neg64 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
+(Lsh64x64 <t> x y) && !ssa.ShiftIsBounded(v) => (AND (SLL  <t> x y) (Neg64 <t> (SLTIU <t> [64] y)))
 
-(Lsh8x(64|32|16|8)  x y) && ssa.ShiftIsBounded(v) => (SLL x y)
-(Lsh16x(64|32|16|8) x y) && ssa.ShiftIsBounded(v) => (SLL x y)
-(Lsh32x(64|32|16|8) x y) && ssa.ShiftIsBounded(v) => (SLL x y)
-(Lsh64x(64|32|16|8) x y) && ssa.ShiftIsBounded(v) => (SLL x y)
+(Lsh8x(64|32|16|8)  x y) && ssa.ShiftIsBounded(v) => (SLL  x y)
+(Lsh16x(64|32|16|8) x y) && ssa.ShiftIsBounded(v) => (SLL  x y)
+(Lsh32x(64|32|16|8) x y) && ssa.ShiftIsBounded(v) => (SLLW x y)
+(Lsh64x(64|32|16|8) x y) && ssa.ShiftIsBounded(v) => (SLL  x y)
 
 // SRL only considers the bottom 6 bits of y, similarly SRLW only considers the
 // bottom 5 bits of y. Ensure that the result is always zero if the shift exceeds
diff --git a/src/cmd/compile/internal/ssarewrite/rewriteriscv64/rewriteRISCV64.go b/src/cmd/compile/internal/ssarewrite/rewriteriscv64/rewriteRISCV64.go
index aa73086..7c6b165 100644
--- a/src/cmd/compile/internal/ssarewrite/rewriteriscv64/rewriteRISCV64.go
+++ b/src/cmd/compile/internal/ssarewrite/rewriteriscv64/rewriteRISCV64.go
@@ -2138,7 +2138,7 @@
 	typ := &b.Func.Config.Types
 	// match: (Lsh32x16 <t> x y)
 	// cond: !ssa.ShiftIsBounded(v)
-	// result: (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt16to64 y))))
+	// result: (AND (SLLW <t> x y) (Neg32 <t> (SLTIU <t> [32] (ZeroExt16to64 y))))
 	for {
 		t := v.Type
 		x := v_0
@@ -2147,11 +2147,11 @@
 			break
 		}
 		v.Reset(ssaop.OpRISCV64AND)
-		v0 := b.NewValue0(v.Pos, ssaop.OpRISCV64SLL, t)
+		v0 := b.NewValue0(v.Pos, ssaop.OpRISCV64SLLW, t)
 		v0.AddArg2(x, y)
 		v1 := b.NewValue0(v.Pos, ssaop.OpNeg32, t)
 		v2 := b.NewValue0(v.Pos, ssaop.OpRISCV64SLTIU, t)
-		v2.AuxInt = ssa.Int64ToAuxInt(64)
+		v2.AuxInt = ssa.Int64ToAuxInt(32)
 		v3 := b.NewValue0(v.Pos, ssaop.OpZeroExt16to64, typ.UInt64)
 		v3.AddArg(y)
 		v2.AddArg(v3)
@@ -2161,14 +2161,14 @@
 	}
 	// match: (Lsh32x16 x y)
 	// cond: ssa.ShiftIsBounded(v)
-	// result: (SLL x y)
+	// result: (SLLW x y)
 	for {
 		x := v_0
 		y := v_1
 		if !(ssa.ShiftIsBounded(v)) {
 			break
 		}
-		v.Reset(ssaop.OpRISCV64SLL)
+		v.Reset(ssaop.OpRISCV64SLLW)
 		v.AddArg2(x, y)
 		return true
 	}
@@ -2181,7 +2181,7 @@
 	typ := &b.Func.Config.Types
 	// match: (Lsh32x32 <t> x y)
 	// cond: !ssa.ShiftIsBounded(v)
-	// result: (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt32to64 y))))
+	// result: (AND (SLLW <t> x y) (Neg32 <t> (SLTIU <t> [32] (ZeroExt32to64 y))))
 	for {
 		t := v.Type
 		x := v_0
@@ -2190,11 +2190,11 @@
 			break
 		}
 		v.Reset(ssaop.OpRISCV64AND)
-		v0 := b.NewValue0(v.Pos, ssaop.OpRISCV64SLL, t)
+		v0 := b.NewValue0(v.Pos, ssaop.OpRISCV64SLLW, t)
 		v0.AddArg2(x, y)
 		v1 := b.NewValue0(v.Pos, ssaop.OpNeg32, t)
 		v2 := b.NewValue0(v.Pos, ssaop.OpRISCV64SLTIU, t)
-		v2.AuxInt = ssa.Int64ToAuxInt(64)
+		v2.AuxInt = ssa.Int64ToAuxInt(32)
 		v3 := b.NewValue0(v.Pos, ssaop.OpZeroExt32to64, typ.UInt64)
 		v3.AddArg(y)
 		v2.AddArg(v3)
@@ -2204,14 +2204,14 @@
 	}
 	// match: (Lsh32x32 x y)
 	// cond: ssa.ShiftIsBounded(v)
-	// result: (SLL x y)
+	// result: (SLLW x y)
 	for {
 		x := v_0
 		y := v_1
 		if !(ssa.ShiftIsBounded(v)) {
 			break
 		}
-		v.Reset(ssaop.OpRISCV64SLL)
+		v.Reset(ssaop.OpRISCV64SLLW)
 		v.AddArg2(x, y)
 		return true
 	}
@@ -2223,7 +2223,7 @@
 	b := v.Block
 	// match: (Lsh32x64 <t> x y)
 	// cond: !ssa.ShiftIsBounded(v)
-	// result: (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] y)))
+	// result: (AND (SLLW <t> x y) (Neg32 <t> (SLTIU <t> [32] y)))
 	for {
 		t := v.Type
 		x := v_0
@@ -2232,11 +2232,11 @@
 			break
 		}
 		v.Reset(ssaop.OpRISCV64AND)
-		v0 := b.NewValue0(v.Pos, ssaop.OpRISCV64SLL, t)
+		v0 := b.NewValue0(v.Pos, ssaop.OpRISCV64SLLW, t)
 		v0.AddArg2(x, y)
 		v1 := b.NewValue0(v.Pos, ssaop.OpNeg32, t)
 		v2 := b.NewValue0(v.Pos, ssaop.OpRISCV64SLTIU, t)
-		v2.AuxInt = ssa.Int64ToAuxInt(64)
+		v2.AuxInt = ssa.Int64ToAuxInt(32)
 		v2.AddArg(y)
 		v1.AddArg(v2)
 		v.AddArg2(v0, v1)
@@ -2244,14 +2244,14 @@
 	}
 	// match: (Lsh32x64 x y)
 	// cond: ssa.ShiftIsBounded(v)
-	// result: (SLL x y)
+	// result: (SLLW x y)
 	for {
 		x := v_0
 		y := v_1
 		if !(ssa.ShiftIsBounded(v)) {
 			break
 		}
-		v.Reset(ssaop.OpRISCV64SLL)
+		v.Reset(ssaop.OpRISCV64SLLW)
 		v.AddArg2(x, y)
 		return true
 	}
@@ -2264,7 +2264,7 @@
 	typ := &b.Func.Config.Types
 	// match: (Lsh32x8 <t> x y)
 	// cond: !ssa.ShiftIsBounded(v)
-	// result: (AND (SLL <t> x y) (Neg32 <t> (SLTIU <t> [64] (ZeroExt8to64 y))))
+	// result: (AND (SLLW <t> x y) (Neg32 <t> (SLTIU <t> [32] (ZeroExt8to64 y))))
 	for {
 		t := v.Type
 		x := v_0
@@ -2273,11 +2273,11 @@
 			break
 		}
 		v.Reset(ssaop.OpRISCV64AND)
-		v0 := b.NewValue0(v.Pos, ssaop.OpRISCV64SLL, t)
+		v0 := b.NewValue0(v.Pos, ssaop.OpRISCV64SLLW, t)
 		v0.AddArg2(x, y)
 		v1 := b.NewValue0(v.Pos, ssaop.OpNeg32, t)
 		v2 := b.NewValue0(v.Pos, ssaop.OpRISCV64SLTIU, t)
-		v2.AuxInt = ssa.Int64ToAuxInt(64)
+		v2.AuxInt = ssa.Int64ToAuxInt(32)
 		v3 := b.NewValue0(v.Pos, ssaop.OpZeroExt8to64, typ.UInt64)
 		v3.AddArg(y)
 		v2.AddArg(v3)
@@ -2287,14 +2287,14 @@
 	}
 	// match: (Lsh32x8 x y)
 	// cond: ssa.ShiftIsBounded(v)
-	// result: (SLL x y)
+	// result: (SLLW x y)
 	for {
 		x := v_0
 		y := v_1
 		if !(ssa.ShiftIsBounded(v)) {
 			break
 		}
-		v.Reset(ssaop.OpRISCV64SLL)
+		v.Reset(ssaop.OpRISCV64SLLW)
 		v.AddArg2(x, y)
 		return true
 	}
diff --git a/test/codegen/bits.go b/test/codegen/bits.go
index ceef3e4..80ccd57 100644
--- a/test/codegen/bits.go
+++ b/test/codegen/bits.go
@@ -319,7 +319,7 @@
 	// amd64:"BTL"
 	// arm64:"AND [$]31," "MOVD [$]1," "LSL" "TSTW"
 	// loong64:"MOVV [$]1," "SLL R" "AND R" "MOVWU" "BNE"
-	// riscv64:"ANDI [$]31," "MOV [$]1," "SLL " "AND "
+	// riscv64:"ANDI [$]31," "MOV [$]1," "SLLW" "AND "
 	if a&(1<<(b&31)) != 0 {
 		return 1
 	}
@@ -362,7 +362,7 @@
 	// amd64:"BTSL"
 	// arm64:"AND [$]31," "MOVD [$]1," "LSL" "ORR"
 	// loong64:"MOVV [$]1," "SLL " "OR "
-	// riscv64:"ANDI [$]31," "MOV [$]1," "SLL " "OR "
+	// riscv64:"ANDI [$]31," "MOV [$]1," "SLLW " "OR "
 	n += b | (1 << (a & 31))
 
 	// amd64:"ORL [$]-2147483648,"
@@ -390,7 +390,7 @@
 	// amd64:"BTRL"
 	// arm64:"AND [$]31," "MOVD [$]1," "LSL" "BIC"
 	// loong64:"MOVV [$]1," "SLL R" "ANDN"
-	// riscv64:"ANDI [$]31," "MOV [$]1," "SLL " "ANDN"
+	// riscv64:"ANDI [$]31," "MOV [$]1," "SLLW " "ANDN"
 	n += b &^ (1 << (a & 31))
 
 	// amd64:"ANDL [$]2147483647,"
@@ -418,7 +418,7 @@
 	// amd64:"BTCL"
 	// arm64:"AND [$]31," "MOVD [$]1," "LSL" "EOR"
 	// loong64:"MOVV [$]1," "SLL R" "XOR"
-	// riscv64:"ANDI [$]31," "MOV [$]1," "SLL " "XOR "
+	// riscv64:"ANDI [$]31," "MOV [$]1," "SLLW " "XOR "
 	n += b ^ (1 << (a & 31))
 
 	// amd64:"XORL [$]-2147483648,"
diff --git a/test/codegen/shift.go b/test/codegen/shift.go
index b627e2e..1c0d94d 100644
--- a/test/codegen/shift.go
+++ b/test/codegen/shift.go
@@ -13,7 +13,7 @@
 func lshConst64x64(v int64) int64 {
 	// loong64:"SLLV"
 	// ppc64x:"SLD"
-	// riscv64:"SLLI" -"AND" -"SLTIU"
+	// riscv64:"SLLI " -"AND" -"SLTIU"
 	return v << uint64(33)
 }
 
@@ -122,7 +122,7 @@
 func lshConst32x1Add(x int32) int32 {
 	// amd64:-"ADD" "SHLL [$]2"
 	// loong64:-"ADD" "SLL [$]2"
-	// riscv64:-"ADD" "SLLI [$]2"
+	// riscv64:-"ADD" "SLLIW [$]2"
 	// ppc64x:-"ADD" "SLW [$]2"
 	return (x + x) << 1
 }
@@ -138,7 +138,7 @@
 func lshConst32x2Add(x int32) int32 {
 	// amd64:-"ADD" "SHLL [$]3"
 	// loong64:-"ADD" "SLL [$]3"
-	// riscv64:-"ADD" "SLLI [$]3"
+	// riscv64:-"ADD" "SLLIW [$]3"
 	// ppc64x:-"ADD" "SLW [$]3"
 	return (x + x) << 2
 }
@@ -154,7 +154,7 @@
 func lshConst32x31Add(x int32) int32 {
 	// amd64:-"ADD" -"SHL" "XORL AX, AX"
 	// loong64:-"ADD" -"SLL " "MOVV R0"
-	// riscv64:-"ADD" -"SLLI" "MOV [$]0"
+	// riscv64:-"ADD" -"SLLIW" "MOV [$]0"
 	// ppc64x:-"ADD" -"SLW" "MOVD [$]0"
 	return (x + x) << 31
 }
@@ -261,13 +261,14 @@
 	// arm64:"LSL" -"AND"
 	// loong64:"SLL " "AND" "SGTU" "MASKEQZ"
 	// ppc64x:"ISEL" -"ORN"
-	// riscv64:"SLL" -"AND " -"SLTIU"
+	// riscv64:"SLLW" "AND " "SLTIU"
 	// s390x:-"RISBGZ" -"AND" -"LOCGR"
 	return v << (s & 63)
 }
 
 func lsh5Mask32x64(v int32, s uint64) int32 {
 	// loong64:"SLL " -"AND"
+	// riscv64:"SLLW" -"AND " -"SLTIU"
 	return v << (s & 31)
 }