mirror of
https://github.com/golang/go
synced 2024-11-11 23:40:22 -07:00
cmd/compile: optimise branchs on riscv64
Make use of multi-control values and branch pseudo-instructions to optimise compiler generated branches. Change-Id: I7a8bf754db3c2082a390bf6a662ccf18cbcbee39 Reviewed-on: https://go-review.googlesource.com/c/go/+/226400 Reviewed-by: Keith Randall <khr@golang.org> Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
000636fdb5
commit
57e32c4fbd
@ -445,16 +445,6 @@
|
||||
(Addr {sym} base) => (MOVaddr {sym} [0] base)
|
||||
(LocalAddr {sym} base _) => (MOVaddr {sym} base)
|
||||
|
||||
// Conditional branches
|
||||
//
|
||||
// cond is 1 if true.
|
||||
//
|
||||
// TODO(prattmic): RISCV branch instructions take two operands to compare,
|
||||
// so we could generate more efficient code by computing the condition in the
|
||||
// branch itself. This should be revisited now that the compiler has support
|
||||
// for two control values (https://golang.org/cl/196557).
|
||||
(If cond yes no) => (BNEZ cond yes no)
|
||||
|
||||
// Calls
|
||||
(StaticCall ...) => (CALLstatic ...)
|
||||
(ClosureCall ...) => (CALLclosure ...)
|
||||
@ -480,11 +470,31 @@
|
||||
(AtomicExchange32 ...) => (LoweredAtomicExchange32 ...)
|
||||
(AtomicExchange64 ...) => (LoweredAtomicExchange64 ...)
|
||||
|
||||
// Conditional branches
|
||||
(If cond yes no) => (BNEZ cond yes no)
|
||||
|
||||
// Optimizations
|
||||
|
||||
// Absorb SNEZ into branch.
|
||||
// Absorb SEQZ/SNEZ into branch.
|
||||
(BEQZ (SEQZ x) yes no) => (BNEZ x yes no)
|
||||
(BEQZ (SNEZ x) yes no) => (BEQZ x yes no)
|
||||
(BNEZ (SEQZ x) yes no) => (BEQZ x yes no)
|
||||
(BNEZ (SNEZ x) yes no) => (BNEZ x 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)
|
||||
(BEQZ (SLT x y) yes no) => (BGE x y yes no)
|
||||
(BNEZ (SLT x y) yes no) => (BLT x y yes no)
|
||||
(BEQZ (SLTU x y) yes no) => (BGEU x y yes no)
|
||||
(BNEZ (SLTU x y) yes no) => (BLTU x y yes no)
|
||||
|
||||
// Convert branch with zero to BEQZ/BNEZ.
|
||||
(BEQ (MOVDconst [0]) cond yes no) => (BEQZ cond yes no)
|
||||
(BEQ cond (MOVDconst [0]) yes no) => (BEQZ cond yes no)
|
||||
(BNE (MOVDconst [0]) cond yes no) => (BNEZ cond yes no)
|
||||
(BNE cond (MOVDconst [0]) yes no) => (BNEZ cond yes no)
|
||||
|
||||
// Store zero
|
||||
(MOVBstore [off] {sym} ptr (MOVBconst [0]) mem) => (MOVBstorezero [off] {sym} ptr mem)
|
||||
(MOVHstore [off] {sym} ptr (MOVHconst [0]) mem) => (MOVHstorezero [off] {sym} ptr mem)
|
||||
|
@ -5120,7 +5120,105 @@ func rewriteValueRISCV64_OpZeroExt8to64(v *Value) bool {
|
||||
}
|
||||
func rewriteBlockRISCV64(b *Block) bool {
|
||||
switch b.Kind {
|
||||
case BlockRISCV64BEQ:
|
||||
// match: (BEQ (MOVDconst [0]) cond yes no)
|
||||
// result: (BEQZ cond yes no)
|
||||
for b.Controls[0].Op == OpRISCV64MOVDconst {
|
||||
v_0 := b.Controls[0]
|
||||
if auxIntToInt64(v_0.AuxInt) != 0 {
|
||||
break
|
||||
}
|
||||
cond := b.Controls[1]
|
||||
b.resetWithControl(BlockRISCV64BEQZ, cond)
|
||||
return true
|
||||
}
|
||||
// match: (BEQ cond (MOVDconst [0]) yes no)
|
||||
// result: (BEQZ cond yes no)
|
||||
for b.Controls[1].Op == OpRISCV64MOVDconst {
|
||||
cond := b.Controls[0]
|
||||
v_1 := b.Controls[1]
|
||||
if auxIntToInt64(v_1.AuxInt) != 0 {
|
||||
break
|
||||
}
|
||||
b.resetWithControl(BlockRISCV64BEQZ, cond)
|
||||
return true
|
||||
}
|
||||
case BlockRISCV64BEQZ:
|
||||
// match: (BEQZ (SEQZ x) yes no)
|
||||
// result: (BNEZ x yes no)
|
||||
for b.Controls[0].Op == OpRISCV64SEQZ {
|
||||
v_0 := b.Controls[0]
|
||||
x := v_0.Args[0]
|
||||
b.resetWithControl(BlockRISCV64BNEZ, x)
|
||||
return true
|
||||
}
|
||||
// match: (BEQZ (SNEZ x) yes no)
|
||||
// result: (BEQZ x yes no)
|
||||
for b.Controls[0].Op == OpRISCV64SNEZ {
|
||||
v_0 := b.Controls[0]
|
||||
x := v_0.Args[0]
|
||||
b.resetWithControl(BlockRISCV64BEQZ, x)
|
||||
return true
|
||||
}
|
||||
// match: (BEQZ (SUB x y) yes no)
|
||||
// result: (BEQ x y yes no)
|
||||
for b.Controls[0].Op == OpRISCV64SUB {
|
||||
v_0 := b.Controls[0]
|
||||
y := v_0.Args[1]
|
||||
x := v_0.Args[0]
|
||||
b.resetWithControl2(BlockRISCV64BEQ, x, y)
|
||||
return true
|
||||
}
|
||||
// match: (BEQZ (SLT x y) yes no)
|
||||
// result: (BGE x y yes no)
|
||||
for b.Controls[0].Op == OpRISCV64SLT {
|
||||
v_0 := b.Controls[0]
|
||||
y := v_0.Args[1]
|
||||
x := v_0.Args[0]
|
||||
b.resetWithControl2(BlockRISCV64BGE, x, y)
|
||||
return true
|
||||
}
|
||||
// match: (BEQZ (SLTU x y) yes no)
|
||||
// result: (BGEU x y yes no)
|
||||
for b.Controls[0].Op == OpRISCV64SLTU {
|
||||
v_0 := b.Controls[0]
|
||||
y := v_0.Args[1]
|
||||
x := v_0.Args[0]
|
||||
b.resetWithControl2(BlockRISCV64BGEU, x, y)
|
||||
return true
|
||||
}
|
||||
case BlockRISCV64BNE:
|
||||
// match: (BNE (MOVDconst [0]) cond yes no)
|
||||
// result: (BNEZ cond yes no)
|
||||
for b.Controls[0].Op == OpRISCV64MOVDconst {
|
||||
v_0 := b.Controls[0]
|
||||
if auxIntToInt64(v_0.AuxInt) != 0 {
|
||||
break
|
||||
}
|
||||
cond := b.Controls[1]
|
||||
b.resetWithControl(BlockRISCV64BNEZ, cond)
|
||||
return true
|
||||
}
|
||||
// match: (BNE cond (MOVDconst [0]) yes no)
|
||||
// result: (BNEZ cond yes no)
|
||||
for b.Controls[1].Op == OpRISCV64MOVDconst {
|
||||
cond := b.Controls[0]
|
||||
v_1 := b.Controls[1]
|
||||
if auxIntToInt64(v_1.AuxInt) != 0 {
|
||||
break
|
||||
}
|
||||
b.resetWithControl(BlockRISCV64BNEZ, cond)
|
||||
return true
|
||||
}
|
||||
case BlockRISCV64BNEZ:
|
||||
// match: (BNEZ (SEQZ x) yes no)
|
||||
// result: (BEQZ x yes no)
|
||||
for b.Controls[0].Op == OpRISCV64SEQZ {
|
||||
v_0 := b.Controls[0]
|
||||
x := v_0.Args[0]
|
||||
b.resetWithControl(BlockRISCV64BEQZ, x)
|
||||
return true
|
||||
}
|
||||
// match: (BNEZ (SNEZ x) yes no)
|
||||
// result: (BNEZ x yes no)
|
||||
for b.Controls[0].Op == OpRISCV64SNEZ {
|
||||
@ -5129,6 +5227,33 @@ func rewriteBlockRISCV64(b *Block) bool {
|
||||
b.resetWithControl(BlockRISCV64BNEZ, x)
|
||||
return true
|
||||
}
|
||||
// match: (BNEZ (SUB x y) yes no)
|
||||
// result: (BNE x y yes no)
|
||||
for b.Controls[0].Op == OpRISCV64SUB {
|
||||
v_0 := b.Controls[0]
|
||||
y := v_0.Args[1]
|
||||
x := v_0.Args[0]
|
||||
b.resetWithControl2(BlockRISCV64BNE, x, y)
|
||||
return true
|
||||
}
|
||||
// match: (BNEZ (SLT x y) yes no)
|
||||
// result: (BLT x y yes no)
|
||||
for b.Controls[0].Op == OpRISCV64SLT {
|
||||
v_0 := b.Controls[0]
|
||||
y := v_0.Args[1]
|
||||
x := v_0.Args[0]
|
||||
b.resetWithControl2(BlockRISCV64BLT, x, y)
|
||||
return true
|
||||
}
|
||||
// match: (BNEZ (SLTU x y) yes no)
|
||||
// result: (BLTU x y yes no)
|
||||
for b.Controls[0].Op == OpRISCV64SLTU {
|
||||
v_0 := b.Controls[0]
|
||||
y := v_0.Args[1]
|
||||
x := v_0.Args[0]
|
||||
b.resetWithControl2(BlockRISCV64BLTU, x, y)
|
||||
return true
|
||||
}
|
||||
case BlockIf:
|
||||
// match: (If cond yes no)
|
||||
// result: (BNEZ cond yes no)
|
||||
|
Loading…
Reference in New Issue
Block a user