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 <mzh@golangcn.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Joel Sing <joel@sing.id.au>
Run-TryBot: Meng Zhuo <mzh@golangcn.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Heschi Kreinick <heschi@google.com>
This commit is contained in:
Joel Sing 2022-08-28 02:32:06 +10:00
parent 9154d4a2a4
commit 646c3eee06
2 changed files with 74 additions and 0 deletions

View file

@ -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 <t> x y) yes no) => (BNEZ (FEQS <t> x y) yes no)
(BNEZ (FNES <t> x y) yes no) => (BEQZ (FEQS <t> x y) yes no)
(BEQZ (FNED <t> x y) yes no) => (BNEZ (FEQD <t> x y) yes no)
(BNEZ (FNED <t> x y) yes no) => (BEQZ (FEQD <t> 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)

View file

@ -7847,6 +7847,40 @@ func rewriteBlockRISCV64(b *Block) bool {
b.resetWithControl(BlockRISCV64BEQZ, x)
return true
}
// match: (BEQZ (FNES <t> x y) yes no)
// result: (BNEZ (FEQS <t> 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 <t> x y) yes no)
// result: (BNEZ (FEQD <t> 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 <t> x y) yes no)
// result: (BEQZ (FEQS <t> 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 <t> x y) yes no)
// result: (BEQZ (FEQD <t> 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 {