cmd/compile: absorb NEG into branch when possible on riscv64

We can end up with this situation due to our equality tests being based on
'SEQZ (SUB x y)' - if x is a zero valued constant, 'SUB x y' can be converted
to 'NEG x'. When used with a branch the SEQZ can be absorbed, leading to
'BNEZ (NEG x)' where the NEG is redundant.

Removes around 1700 instructions from the go binary on riscv64.

Change-Id: I947a080d8bf7d2d6378ab114172e2342ce2c51db
Reviewed-on: https://go-review.googlesource.com/c/go/+/342850
Trust: Joel Sing <joel@sing.id.au>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
This commit is contained in:
Joel Sing 2021-08-17 19:09:33 +10:00
parent bcd146d398
commit 8fff20ffeb
2 changed files with 28 additions and 0 deletions

View file

@ -588,6 +588,10 @@
(BNEZ (SEQZ x) yes no) => (BEQZ x yes no)
(BNEZ (SNEZ x) yes no) => (BNEZ x yes no)
// Absorb NEG into branch when possible.
(BEQZ x:(NEG y) yes no) && x.Uses == 1 => (BEQZ y yes no)
(BNEZ x:(NEG y) yes no) && x.Uses == 1 => (BNEZ 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

@ -6102,6 +6102,18 @@ func rewriteBlockRISCV64(b *Block) bool {
b.resetWithControl(BlockRISCV64BEQZ, x)
return true
}
// match: (BEQZ x:(NEG y) yes no)
// cond: x.Uses == 1
// result: (BEQZ y yes no)
for b.Controls[0].Op == OpRISCV64NEG {
x := b.Controls[0]
y := x.Args[0]
if !(x.Uses == 1) {
break
}
b.resetWithControl(BlockRISCV64BEQZ, y)
return true
}
// match: (BEQZ (SUB x y) yes no)
// result: (BEQ x y yes no)
for b.Controls[0].Op == OpRISCV64SUB {
@ -6215,6 +6227,18 @@ func rewriteBlockRISCV64(b *Block) bool {
b.resetWithControl(BlockRISCV64BNEZ, x)
return true
}
// match: (BNEZ x:(NEG y) yes no)
// cond: x.Uses == 1
// result: (BNEZ y yes no)
for b.Controls[0].Op == OpRISCV64NEG {
x := b.Controls[0]
y := x.Args[0]
if !(x.Uses == 1) {
break
}
b.resetWithControl(BlockRISCV64BNEZ, y)
return true
}
// match: (BNEZ (SUB x y) yes no)
// result: (BNE x y yes no)
for b.Controls[0].Op == OpRISCV64SUB {