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) }