From 646c3eee06fa4b1b869e8183977aa46d4d4eb646 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Sun, 28 Aug 2022 02:32:06 +1000 Subject: [PATCH] cmd/compile: negate comparision with FNES/FNED on riscv64 The FNES and FNED instructions are pseudo-instructions, which the assembler expands to FEQS/NEG or FEQD/NEG - if we're comparing the result via a branch instruction, we can avoid an instruction by negating both the branch comparision and the floating point comparision. This only removes a handful of instructions from the Go binary, however, it will provide benefit to floating point intensive code. Change-Id: I4e3124440b7659acc4d9bc9948b755a4900a422f Reviewed-on: https://go-review.googlesource.com/c/go/+/426261 Reviewed-by: Meng Zhuo TryBot-Result: Gopher Robot Run-TryBot: Joel Sing Run-TryBot: Meng Zhuo Reviewed-by: Cherry Mui Reviewed-by: Heschi Kreinick --- .../compile/internal/ssa/gen/RISCV64.rules | 6 ++ .../compile/internal/ssa/rewriteRISCV64.go | 68 +++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/src/cmd/compile/internal/ssa/gen/RISCV64.rules b/src/cmd/compile/internal/ssa/gen/RISCV64.rules index 82a9c83284..a49a9148ea 100644 --- a/src/cmd/compile/internal/ssa/gen/RISCV64.rules +++ b/src/cmd/compile/internal/ssa/gen/RISCV64.rules @@ -620,6 +620,12 @@ (BEQZ (NEG x) yes no) => (BEQZ x yes no) (BNEZ (NEG x) yes no) => (BNEZ x yes no) +// Negate comparision with FNES/FNED. +(BEQZ (FNES x y) yes no) => (BNEZ (FEQS x y) yes no) +(BNEZ (FNES x y) yes no) => (BEQZ (FEQS x y) yes no) +(BEQZ (FNED x y) yes no) => (BNEZ (FEQD x y) yes no) +(BNEZ (FNED x y) yes no) => (BEQZ (FEQD x y) yes no) + // Convert BEQZ/BNEZ into more optimal branch conditions. (BEQZ (SUB x y) yes no) => (BEQ x y yes no) (BNEZ (SUB x y) yes no) => (BNE x y yes no) diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go index a46664fc90..052e9d2039 100644 --- a/src/cmd/compile/internal/ssa/rewriteRISCV64.go +++ b/src/cmd/compile/internal/ssa/rewriteRISCV64.go @@ -7847,6 +7847,40 @@ func rewriteBlockRISCV64(b *Block) bool { b.resetWithControl(BlockRISCV64BEQZ, x) return true } + // match: (BEQZ (FNES x y) yes no) + // result: (BNEZ (FEQS x y) yes no) + for b.Controls[0].Op == OpRISCV64FNES { + v_0 := b.Controls[0] + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + y := v_0_1 + v0 := b.NewValue0(v_0.Pos, OpRISCV64FEQS, t) + v0.AddArg2(x, y) + b.resetWithControl(BlockRISCV64BNEZ, v0) + return true + } + } + // match: (BEQZ (FNED x y) yes no) + // result: (BNEZ (FEQD x y) yes no) + for b.Controls[0].Op == OpRISCV64FNED { + v_0 := b.Controls[0] + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + y := v_0_1 + v0 := b.NewValue0(v_0.Pos, OpRISCV64FEQD, t) + v0.AddArg2(x, y) + b.resetWithControl(BlockRISCV64BNEZ, v0) + return true + } + } // match: (BEQZ (SUB x y) yes no) // result: (BEQ x y yes no) for b.Controls[0].Op == OpRISCV64SUB { @@ -7968,6 +8002,40 @@ func rewriteBlockRISCV64(b *Block) bool { b.resetWithControl(BlockRISCV64BNEZ, x) return true } + // match: (BNEZ (FNES x y) yes no) + // result: (BEQZ (FEQS x y) yes no) + for b.Controls[0].Op == OpRISCV64FNES { + v_0 := b.Controls[0] + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + y := v_0_1 + v0 := b.NewValue0(v_0.Pos, OpRISCV64FEQS, t) + v0.AddArg2(x, y) + b.resetWithControl(BlockRISCV64BEQZ, v0) + return true + } + } + // match: (BNEZ (FNED x y) yes no) + // result: (BEQZ (FEQD x y) yes no) + for b.Controls[0].Op == OpRISCV64FNED { + v_0 := b.Controls[0] + t := v_0.Type + _ = v_0.Args[1] + v_0_0 := v_0.Args[0] + v_0_1 := v_0.Args[1] + for _i0 := 0; _i0 <= 1; _i0, v_0_0, v_0_1 = _i0+1, v_0_1, v_0_0 { + x := v_0_0 + y := v_0_1 + v0 := b.NewValue0(v_0.Pos, OpRISCV64FEQD, t) + v0.AddArg2(x, y) + b.resetWithControl(BlockRISCV64BEQZ, v0) + return true + } + } // match: (BNEZ (SUB x y) yes no) // result: (BNE x y yes no) for b.Controls[0].Op == OpRISCV64SUB { -- 2.48.1