Skip to content

cmd/compile, cmd/asm: add support for Zicond extension on riscv64 #75350

@lxq015

Description

@lxq015

Proposal Details

Background

The RISC-V Zicond extension provides conditional zero instructions (czero.eqz and czero.nez), which are useful for implementing conditional moves and other conditional operations without branching. This can lead to performance improvements by avoiding branch mispredictions.

Currently, the Go compiler does not generate these instructions for riscv64 targets, even when the underlying hardware supports them. This represents a missed optimization opportunity.

Proposed Solution

Add comprehensive support for the Zicond extension to the Go toolchain for riscv64, including assembler, compiler, and disassembler support. All features are conditionally enabled when buildcfg.GORISCV64 >= 23.

Implementation Details

  1. Assembler Support (cmd/internal/obj/riscv):
  • Add ACZEROEQZ and ACZERONEZ to instruction enum in cpu.go
  • Add instruction encoding in inst.go:
    • CZEROEQZ: opcode=0x33, funct3=0x5, funct7=0x7
    • CZERONEZ: opcode=0x33, funct3=0x7, funct7=0x7
  • Add instruction data in obj.go with rIIIEncoding format
  • Add instruction names in anames.go
  • Add instruction mapping in obj.go for proper register assignment
  1. Compiler Support (cmd/compile):
    Based on the RISC-V Zicond specification, implement comprehensive SSA lowering rules:

RISCV64latelower.rules

 // Zicond rules support 
(Select <typ.UInt64> cond trueval falseval)  =>  (ADD (CZEROEQZ <typ.UInt64> falseval cond) (CZERONEZ <typ.UInt64> trueval cond))

// Conditional arithmetic operations with Zicond 
(CondSelect <t> (ADD x y) x (SEQZ z)) && buildcfg.GORISCV64 >= 23 => (ADD x (CZERONEZ <t> y z))
(CondSelect <t> (ADD x y) x (SNEZ z)) && buildcfg.GORISCV64 >= 23 => (ADD x (CZEROEQZ <t> y z))

// Conditional subtract operations with Zicond
(CondSelect <t> (SUB x y) x (SEQZ z)) && buildcfg.GORISCV64 >= 23 => (SUB x (CZERONEZ <t> y z))
(CondSelect <t> (SUB x y) x (SNEZ z)) && buildcfg.GORISCV64 >= 23 => (SUB x (CZEROEQZ <t> y z))

// Conditional bitwise-or operations with Zicond
(CondSelect <t> (OR x y) x (SEQZ z)) && buildcfg.GORISCV64 >= 23 => (OR x (CZERONEZ <t> y z))
(CondSelect <t> (OR x y) x (SNEZ z)) && buildcfg.GORISCV64 >= 23 => (OR x (CZEROEQZ <t> y z))

// Conditional bitwise-xor operations with Zicond
(CondSelect <t> (XOR x y) x (SEQZ z)) && buildcfg.GORISCV64 >= 23 => (XOR x (CZERONEZ <t> y z))
(CondSelect <t> (XOR x y) x (SNEZ z)) && buildcfg.GORISCV64 >= 23 => (XOR x (CZEROEQZ <t> y z))

// Conditional bitwise-and operations with Zicond
(CondSelect <t> (AND x y) x (SEQZ z)) && buildcfg.GORISCV64 >= 23 => (OR (AND <t> x y) (CZEROEQZ <t> x z))
(CondSelect <t> (AND x y) x (SNEZ z)) && buildcfg.GORISCV64 >= 23 => (OR (AND <t> x y) (CZERONEZ <t> x z))

// (z == 0) ? x : y
(CondSelect <t> x y (SEQZ z)) && buildcfg.GORISCV64 >= 23 => (OR (CZERONEZ <t> x z) (CZEROEQZ <t> y z))
// (z != 0) ? x : y
(CondSelect <t> x y (SNEZ z)) && buildcfg.GORISCV64 >= 23 => (OR (CZEROEQZ <t> x z) (CZERONEZ <t> y z))

(CondSelect <t> x y cond) && buildcfg.GORISCV64 >= 23 => (OR (CZEROEQZ <t> x cond) (CZERONEZ <t> y cond))

These rules cover various conditional select patterns as specified in the RISC-V Zicond extension documentation, enabling efficient code generation for different conditional scenarios.

  1. Disassembler Support (src/cmd/internal/obj/riscv、cmd/vendor/golang.org/x/arch/riscv64/riscv64asm):
  • Add instruction definitions in tables.go for proper disassembly
  • Add instFormat entries with correct encoding masks and values
  • Add instruction names to opstr array
  1. Build Configuration:
  • All Zicond features are conditionally enabled when buildcfg.GORISCV64 >= 23
  • This ensures compatibility with older RISC-V targets that don't support Zicond

Example

// Go code like:
func condSelect(x, y int, cond bool) int {
    if cond {
        return x
    }
    return y
}

// Could be compiled to use czero.nez/czero.eqz instead of branching code
// when GORISCV64 >= 23

Additional Context

The specification for the Zicond extension can be found in the ratified RVA23 profile or other RISC-V ISA documents.

I am willing to work on implementing this feature and submit a CL for review.

Metadata

Metadata

Assignees

Labels

FeatureRequestIssues asking for a new feature that does not need a proposal.ImplementationIssues describing a semantics-preserving change to the Go implementation.NeedsFixThe path to resolution is known, but the work has not been done.compiler/runtimeIssues related to the Go compiler and/or runtime.

Type

No type

Projects

Status

In Progress

Relationships

None yet

Development

No branches or pull requests

Issue actions