mirror of
https://github.com/golang/go
synced 2024-11-23 08:50:03 -07:00
cmd/compile: convert SLT/SLTU with constant into immediate form on riscv64
Convert SLT/SLTU with a suitably valued constant into a SLTI/SLTIU instruction. This can reduce instructions and avoid register loads. Now that we generate more SLTI/SLTIU instructions, absorb these into branches when it makes sense to do so. Removes more than 800 instructions from the Go binary on linux/riscv64. Change-Id: I42c4e00486697acd4da7669d441b5690795f18ae Reviewed-on: https://go-review.googlesource.com/c/go/+/428499 Reviewed-by: Wayne Zuo <wdvxdr@golangcn.org> Run-TryBot: Joel Sing <joel@sing.id.au> Reviewed-by: Cherry Mui <cherryyz@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Joedian Reid <joedian@golang.org>
This commit is contained in:
parent
0ca355318f
commit
ba8c94b5f2
@ -2,13 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Optimizations TODO:
|
||||
// * Use SLTI and SLTIU for comparisons to constants, instead of SLT/SLTU with constants in registers
|
||||
// * Use the zero register instead of moving 0 into a register.
|
||||
// * Add rules to avoid generating a temp bool value for (If (SLT[U] ...) ...).
|
||||
// * Arrange for non-trivial Zero and Move lowerings to use aligned loads and stores.
|
||||
// * Avoid using Neq32 for writeBarrier.enabled checks.
|
||||
|
||||
// Lowering arithmetic
|
||||
(Add64 ...) => (ADD ...)
|
||||
(AddPtr ...) => (ADD ...)
|
||||
@ -626,6 +619,10 @@
|
||||
(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)
|
||||
(BEQZ (SLTI [x] y) yes no) => (BGE y (MOVDconst [x]) yes no)
|
||||
(BNEZ (SLTI [x] y) yes no) => (BLT y (MOVDconst [x]) yes no)
|
||||
(BEQZ (SLTIU [x] y) yes no) => (BGEU y (MOVDconst [x]) yes no)
|
||||
(BNEZ (SLTIU [x] y) yes no) => (BLTU y (MOVDconst [x]) yes no)
|
||||
|
||||
// Convert branch with zero to more optimal branch zero.
|
||||
(BEQ (MOVDconst [0]) cond yes no) => (BEQZ cond yes no)
|
||||
@ -763,9 +760,11 @@
|
||||
(AND (MOVDconst [val]) x) && is32Bit(val) => (ANDI [val] x)
|
||||
(OR (MOVDconst [val]) x) && is32Bit(val) => (ORI [val] x)
|
||||
(XOR (MOVDconst [val]) x) && is32Bit(val) => (XORI [val] x)
|
||||
(SLL x (MOVDconst [val])) => (SLLI [int64(val&63)] x)
|
||||
(SRL x (MOVDconst [val])) => (SRLI [int64(val&63)] x)
|
||||
(SRA x (MOVDconst [val])) => (SRAI [int64(val&63)] x)
|
||||
(SLL x (MOVDconst [val])) => (SLLI [int64(val&63)] x)
|
||||
(SRL x (MOVDconst [val])) => (SRLI [int64(val&63)] x)
|
||||
(SRA x (MOVDconst [val])) => (SRAI [int64(val&63)] x)
|
||||
(SLT x (MOVDconst [val])) && val >= -2048 && val <= 2047 => (SLTI [val] x)
|
||||
(SLTU x (MOVDconst [val])) && val >= -2048 && val <= 2047 => (SLTIU [val] x)
|
||||
|
||||
// Convert const subtraction into ADDI with negative immediate, where possible.
|
||||
(SUB x (MOVDconst [val])) && is32Bit(-val) => (ADDI [-val] x)
|
||||
|
@ -5618,6 +5618,23 @@ func rewriteValueRISCV64_OpRISCV64SLLI(v *Value) bool {
|
||||
func rewriteValueRISCV64_OpRISCV64SLT(v *Value) bool {
|
||||
v_1 := v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
// match: (SLT x (MOVDconst [val]))
|
||||
// cond: val >= -2048 && val <= 2047
|
||||
// result: (SLTI [val] x)
|
||||
for {
|
||||
x := v_0
|
||||
if v_1.Op != OpRISCV64MOVDconst {
|
||||
break
|
||||
}
|
||||
val := auxIntToInt64(v_1.AuxInt)
|
||||
if !(val >= -2048 && val <= 2047) {
|
||||
break
|
||||
}
|
||||
v.reset(OpRISCV64SLTI)
|
||||
v.AuxInt = int64ToAuxInt(val)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (SLT x x)
|
||||
// result: (MOVDconst [0])
|
||||
for {
|
||||
@ -5730,6 +5747,23 @@ func rewriteValueRISCV64_OpRISCV64SLTIU(v *Value) bool {
|
||||
func rewriteValueRISCV64_OpRISCV64SLTU(v *Value) bool {
|
||||
v_1 := v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
// match: (SLTU x (MOVDconst [val]))
|
||||
// cond: val >= -2048 && val <= 2047
|
||||
// result: (SLTIU [val] x)
|
||||
for {
|
||||
x := v_0
|
||||
if v_1.Op != OpRISCV64MOVDconst {
|
||||
break
|
||||
}
|
||||
val := auxIntToInt64(v_1.AuxInt)
|
||||
if !(val >= -2048 && val <= 2047) {
|
||||
break
|
||||
}
|
||||
v.reset(OpRISCV64SLTIU)
|
||||
v.AuxInt = int64ToAuxInt(val)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (SLTU x x)
|
||||
// result: (MOVDconst [0])
|
||||
for {
|
||||
@ -8282,6 +8316,28 @@ func rewriteBlockRISCV64(b *Block) bool {
|
||||
b.resetWithControl2(BlockRISCV64BGEU, x, y)
|
||||
return true
|
||||
}
|
||||
// match: (BEQZ (SLTI [x] y) yes no)
|
||||
// result: (BGE y (MOVDconst [x]) yes no)
|
||||
for b.Controls[0].Op == OpRISCV64SLTI {
|
||||
v_0 := b.Controls[0]
|
||||
x := auxIntToInt64(v_0.AuxInt)
|
||||
y := v_0.Args[0]
|
||||
v0 := b.NewValue0(b.Pos, OpRISCV64MOVDconst, typ.UInt64)
|
||||
v0.AuxInt = int64ToAuxInt(x)
|
||||
b.resetWithControl2(BlockRISCV64BGE, y, v0)
|
||||
return true
|
||||
}
|
||||
// match: (BEQZ (SLTIU [x] y) yes no)
|
||||
// result: (BGEU y (MOVDconst [x]) yes no)
|
||||
for b.Controls[0].Op == OpRISCV64SLTIU {
|
||||
v_0 := b.Controls[0]
|
||||
x := auxIntToInt64(v_0.AuxInt)
|
||||
y := v_0.Args[0]
|
||||
v0 := b.NewValue0(b.Pos, OpRISCV64MOVDconst, typ.UInt64)
|
||||
v0.AuxInt = int64ToAuxInt(x)
|
||||
b.resetWithControl2(BlockRISCV64BGEU, y, v0)
|
||||
return true
|
||||
}
|
||||
case BlockRISCV64BGE:
|
||||
// match: (BGE (MOVDconst [0]) cond yes no)
|
||||
// result: (BLEZ cond yes no)
|
||||
@ -8437,6 +8493,28 @@ func rewriteBlockRISCV64(b *Block) bool {
|
||||
b.resetWithControl2(BlockRISCV64BLTU, x, y)
|
||||
return true
|
||||
}
|
||||
// match: (BNEZ (SLTI [x] y) yes no)
|
||||
// result: (BLT y (MOVDconst [x]) yes no)
|
||||
for b.Controls[0].Op == OpRISCV64SLTI {
|
||||
v_0 := b.Controls[0]
|
||||
x := auxIntToInt64(v_0.AuxInt)
|
||||
y := v_0.Args[0]
|
||||
v0 := b.NewValue0(b.Pos, OpRISCV64MOVDconst, typ.UInt64)
|
||||
v0.AuxInt = int64ToAuxInt(x)
|
||||
b.resetWithControl2(BlockRISCV64BLT, y, v0)
|
||||
return true
|
||||
}
|
||||
// match: (BNEZ (SLTIU [x] y) yes no)
|
||||
// result: (BLTU y (MOVDconst [x]) yes no)
|
||||
for b.Controls[0].Op == OpRISCV64SLTIU {
|
||||
v_0 := b.Controls[0]
|
||||
x := auxIntToInt64(v_0.AuxInt)
|
||||
y := v_0.Args[0]
|
||||
v0 := b.NewValue0(b.Pos, OpRISCV64MOVDconst, typ.UInt64)
|
||||
v0.AuxInt = int64ToAuxInt(x)
|
||||
b.resetWithControl2(BlockRISCV64BLTU, y, v0)
|
||||
return true
|
||||
}
|
||||
case BlockIf:
|
||||
// match: (If cond yes no)
|
||||
// result: (BNEZ (MOVBUreg <typ.UInt64> cond) yes no)
|
||||
|
Loading…
Reference in New Issue
Block a user