cmd/compile/internal/ssa: limit zbb to rva22u64 for riscv64
The ANDN/ORN/XNOR was introduced in zbb which only mandatory
in RVA22U64 profile
diff --git a/src/cmd/compile/internal/ssa/_gen/RISCV64latelower.rules b/src/cmd/compile/internal/ssa/_gen/RISCV64latelower.rules
index 7acaa2f..68542eb 100644
--- a/src/cmd/compile/internal/ssa/_gen/RISCV64latelower.rules
+++ b/src/cmd/compile/internal/ssa/_gen/RISCV64latelower.rules
@@ -2,11 +2,11 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Combine bitwise operation and bitwise inversion.
-(AND x (NOT y)) => (ANDN x y)
-(OR x (NOT y)) => (ORN x y)
-(XOR x (NOT y)) => (XNOR x y)
-(NOT (XOR x y)) => (XNOR x y)
+// Combine bitwise operation and bitwise inversion (requires Zbb, RVA22U64+).
+(AND x (NOT y)) && buildcfg.GORISCV64 >= 22 => (ANDN x y)
+(OR x (NOT y)) && buildcfg.GORISCV64 >= 22 => (ORN x y)
+(XOR x (NOT y)) && buildcfg.GORISCV64 >= 22 => (XNOR x y)
+(NOT (XOR x y)) && buildcfg.GORISCV64 >= 22 => (XNOR x y)
// Fold constant shift with extension.
(SRAI [c] (MOVBreg x)) && c < 8 => (SRAI [56+c] (SLLI <typ.Int64> [56] x))
diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64latelower.go b/src/cmd/compile/internal/ssa/rewriteRISCV64latelower.go
index d2c3a8f..e025fd2 100644
--- a/src/cmd/compile/internal/ssa/rewriteRISCV64latelower.go
+++ b/src/cmd/compile/internal/ssa/rewriteRISCV64latelower.go
@@ -2,6 +2,8 @@
package ssa
+import "internal/buildcfg"
+
func rewriteValueRISCV64latelower(v *Value) bool {
switch v.Op {
case OpRISCV64AND:
@@ -25,6 +27,7 @@
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (AND x (NOT y))
+ // cond: buildcfg.GORISCV64 >= 22
// result: (ANDN x y)
for {
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
@@ -33,6 +36,9 @@
continue
}
y := v_1.Args[0]
+ if !(buildcfg.GORISCV64 >= 22) {
+ continue
+ }
v.reset(OpRISCV64ANDN)
v.AddArg2(x, y)
return true
@@ -44,6 +50,7 @@
func rewriteValueRISCV64latelower_OpRISCV64NOT(v *Value) bool {
v_0 := v.Args[0]
// match: (NOT (XOR x y))
+ // cond: buildcfg.GORISCV64 >= 22
// result: (XNOR x y)
for {
if v_0.Op != OpRISCV64XOR {
@@ -51,6 +58,9 @@
}
y := v_0.Args[1]
x := v_0.Args[0]
+ if !(buildcfg.GORISCV64 >= 22) {
+ break
+ }
v.reset(OpRISCV64XNOR)
v.AddArg2(x, y)
return true
@@ -61,6 +71,7 @@
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (OR x (NOT y))
+ // cond: buildcfg.GORISCV64 >= 22
// result: (ORN x y)
for {
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
@@ -69,6 +80,9 @@
continue
}
y := v_1.Args[0]
+ if !(buildcfg.GORISCV64 >= 22) {
+ continue
+ }
v.reset(OpRISCV64ORN)
v.AddArg2(x, y)
return true
@@ -309,6 +323,7 @@
v_1 := v.Args[1]
v_0 := v.Args[0]
// match: (XOR x (NOT y))
+ // cond: buildcfg.GORISCV64 >= 22
// result: (XNOR x y)
for {
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
@@ -317,6 +332,9 @@
continue
}
y := v_1.Args[0]
+ if !(buildcfg.GORISCV64 >= 22) {
+ continue
+ }
v.reset(OpRISCV64XNOR)
v.AddArg2(x, y)
return true
diff --git a/test/codegen/bits.go b/test/codegen/bits.go
index cda1820..3ca700f 100644
--- a/test/codegen/bits.go
+++ b/test/codegen/bits.go
@@ -165,7 +165,8 @@
// amd64:"BTRQ"
// arm64:"MOVD [$]1," "LSL" "BIC"
// loong64:"MOVV [$]1," "SLLV" "ANDN"
- // riscv64:"ANDI [$]63," "MOV [$]1," "SLL " "ANDN"
+ // riscv64/rva20u64: -"ANDN"
+ // riscv64/rva22u64,riscv64/rva23u64:"ANDI [$]63," "MOV [$]1," "SLL " "ANDN"
n += b &^ (1 << (a & 63))
// amd64:"BTRQ [$]63,"
@@ -390,7 +391,8 @@
// amd64:"BTRL"
// arm64:"AND [$]31," "MOVD [$]1," "LSL" "BIC"
// loong64:"MOVV [$]1," "SLL R" "ANDN"
- // riscv64:"ANDI [$]31," "MOV [$]1," "SLL " "ANDN"
+ // riscv64/rva20u64: -"ANDN"
+ // riscv64/rva22u64,riscv64/rva23u64:"ANDI [$]31," "MOV [$]1," "SLL " "ANDN"
n += b &^ (1 << (a & 31))
// amd64:"ANDL [$]2147483647,"
@@ -482,36 +484,42 @@
func bitsAndNot(x, y uint32) uint32 {
// arm64:`BIC ` -`AND`
// loong64:"ANDN " -"AND "
- // riscv64:"ANDN" -"AND "
+ // riscv64/rva20u64: "AND " -"ANDN"
+ // riscv64/rva22u64,riscv64/rva23u64:"ANDN" -"AND "
return x &^ y
}
func bitsXorNot(x, y, z uint32, a []uint32, n, m uint64) uint64 {
// arm64:`EON ` -`EOR` -`MVN`
// loong64:"NOR" "XOR"
- // riscv64:"XNOR " -"MOV [$]" -"XOR "
+ // riscv64/rva20u64: "XOR " -"XNOR"
+ // riscv64/rva22u64,riscv64/rva23u64:"XNOR " -"MOV [$]" -"XOR "
a[0] = x ^ (y ^ 0xffffffff)
// arm64:`EON ` -`EOR` -`MVN`
// loong64:"XOR" "NOR"
- // riscv64:"XNOR" -"XOR "
+ // riscv64/rva20u64: "XOR " -"XNOR"
+ // riscv64/rva22u64,riscv64/rva23u64:"XNOR" -"XOR "
a[1] = ^(y ^ z)
// arm64:`EON ` -`XOR`
// loong64:"NOR" "XOR"
- // riscv64:"XNOR" -"XOR " -"NOT"
+ // riscv64/rva20u64: "XOR " -"XNOR"
+ // riscv64/rva22u64,riscv64/rva23u64:"XNOR" -"XOR " -"NOT"
a[2] = x ^ ^z
// arm64:`EON ` -`EOR` -`MVN`
// loong64:"NOR" "XOR"
- // riscv64:"XNOR" -"MOV [$]" -"XOR "
+ // riscv64/rva20u64: "XOR " -"XNOR"
+ // riscv64/rva22u64,riscv64/rva23u64:"XNOR" -"MOV [$]" -"XOR "
return n ^ (m ^ 0xffffffffffffffff)
}
func bitsOrNot(x, y uint32) uint32 {
// arm64:"ORN " -"ORR"
// loong64:"ORN" -"OR "
- // riscv64:"ORN" -"OR "
+ // riscv64/rva20u64: "OR " -"ORN"
+ // riscv64/rva22u64,riscv64/rva23u64:"ORN" -"OR "
return x | ^y
}
diff --git a/test/codegen/logic.go b/test/codegen/logic.go
index 0d1beeb..5668c12 100644
--- a/test/codegen/logic.go
+++ b/test/codegen/logic.go
@@ -22,6 +22,8 @@
// Verify (OR x (NOT y)) rewrites to (ORN x y) where supported
func ornot(x, y int) int {
// ppc64x:"ORN"
+ // riscv64/rva20u64:"OR" "NOT"
+ // riscv64/rva22u64,riscv64/rva23u64:"ORN"
z := x | ^y
return z
}
@@ -29,6 +31,7 @@
// Verify that (OR (NOT x) (NOT y)) rewrites to (NOT (AND x y))
func orDemorgans(x, y int) int {
// amd64:"AND" -"OR"
+ // riscv64:"AND" "NOT"
z := ^x | ^y
return z
}
@@ -36,6 +39,7 @@
// Verify that (AND (NOT x) (NOT y)) rewrites to (NOT (OR x y))
func andDemorgans(x, y int) int {
// amd64:"OR" -"AND"
+ // riscv64:"OR" "NOT"
z := ^x & ^y
return z
}
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Actually, it's always safe to emit ZBB instructions, regardless of the currently selected profile. If you're building with RVA20U64, the assembler will synthesise the ZBB instructions with a number of RVA20U64 instructions. See
https://pkg.go.dev/cmd/internal/obj/riscv#hdr-RISC_V_extensions
for more details.
Are you seeing a performance penalty when these rules fire on RVA20U64?
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Actually, it's always safe to emit ZBB instructions, regardless of the currently selected profile. If you're building with RVA20U64, the assembler will synthesise the ZBB instructions with a number of RVA20U64 instructions. See
https://pkg.go.dev/cmd/internal/obj/riscv#hdr-RISC_V_extensions
for more details.
Are you seeing a performance penalty when these rules fire on RVA20U64?
Ah, thanks for the heads up. There’s no performance degradation, but it’s confusing for a programmer. I was debugging gdb with my k3 and found that it’s AND NOT instead of ANDN. I think it’s better to be explicit, as the profile described.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
Meng ZhuoActually, it's always safe to emit ZBB instructions, regardless of the currently selected profile. If you're building with RVA20U64, the assembler will synthesise the ZBB instructions with a number of RVA20U64 instructions. See
https://pkg.go.dev/cmd/internal/obj/riscv#hdr-RISC_V_extensions
for more details.
Are you seeing a performance penalty when these rules fire on RVA20U64?
Ah, thanks for the heads up. There’s no performance degradation, but it’s confusing for a programmer. I was debugging gdb with my k3 and found that it’s AND NOT instead of ANDN. I think it’s better to be explicit, as the profile described.
I guess though this is the way we decided to do things when we added support for Zbb. If you look in the pure assembler routines you'll also see things like ANDN and ORN used freely without profile checks. So the current compiler rules are consistent with the handwritten assembly code and the documentation. The section I linked to in the documentation was written to help alleviate the confusion.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |
I'm not sure whether it's nessacry. Those rules were introduced in CL 611895, since Joel has already provided pseudo-instructions in assembler.
| Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. |