mirror of https://github.com/golang/go.git
cmd/compile: use integer min/max instructions on riscv64
When GORISCV64 enables rva22u64, make use of integer MIN/MINU/MAX/MAXU instructions in compiler rewrite rules. Change-Id: I4e7c514516acad03f2869d4c8936f06582cf7ea9 Reviewed-on: https://go-review.googlesource.com/c/go/+/559660 Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Carlos Amedee <carlos@golang.org> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Meng Zhuo <mengzhuo1203@gmail.com>
This commit is contained in:
parent
27093581b2
commit
3d9a89b057
|
|
@ -288,8 +288,8 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
|||
ssa.OpRISCV64FADDS, ssa.OpRISCV64FSUBS, ssa.OpRISCV64FMULS, ssa.OpRISCV64FDIVS,
|
||||
ssa.OpRISCV64FEQS, ssa.OpRISCV64FNES, ssa.OpRISCV64FLTS, ssa.OpRISCV64FLES,
|
||||
ssa.OpRISCV64FADDD, ssa.OpRISCV64FSUBD, ssa.OpRISCV64FMULD, ssa.OpRISCV64FDIVD,
|
||||
ssa.OpRISCV64FEQD, ssa.OpRISCV64FNED, ssa.OpRISCV64FLTD, ssa.OpRISCV64FLED,
|
||||
ssa.OpRISCV64FSGNJD:
|
||||
ssa.OpRISCV64FEQD, ssa.OpRISCV64FNED, ssa.OpRISCV64FLTD, ssa.OpRISCV64FLED, ssa.OpRISCV64FSGNJD,
|
||||
ssa.OpRISCV64MIN, ssa.OpRISCV64MAX, ssa.OpRISCV64MINU, ssa.OpRISCV64MAXU:
|
||||
r := v.Reg()
|
||||
r1 := v.Args[0].Reg()
|
||||
r2 := v.Args[1].Reg()
|
||||
|
|
|
|||
|
|
@ -834,3 +834,13 @@
|
|||
(F(MADD|NMADD|MSUB|NMSUB)S x y neg:(FNEGS z)) && neg.Uses == 1 => (F(MSUB|NMSUB|MADD|NMADD)S x y z)
|
||||
(F(MADD|NMADD|MSUB|NMSUB)D neg:(FNEGD x) y z) && neg.Uses == 1 => (F(NMSUB|MSUB|NMADD|MADD)D x y z)
|
||||
(F(MADD|NMADD|MSUB|NMSUB)D x y neg:(FNEGD z)) && neg.Uses == 1 => (F(MSUB|NMSUB|MADD|NMADD)D x y z)
|
||||
|
||||
//
|
||||
// Optimisations for rva22u64 and above.
|
||||
//
|
||||
|
||||
// Integer minimum and maximum.
|
||||
(Min64 x y) && buildcfg.GORISCV64 >= 22 => (MIN x y)
|
||||
(Max64 x y) && buildcfg.GORISCV64 >= 22 => (MAX x y)
|
||||
(Min64u x y) && buildcfg.GORISCV64 >= 22 => (MINU x y)
|
||||
(Max64u x y) && buildcfg.GORISCV64 >= 22 => (MAXU x y)
|
||||
|
|
|
|||
|
|
@ -235,6 +235,12 @@ func init() {
|
|||
{name: "XOR", argLength: 2, reg: gp21, asm: "XOR", commutative: true}, // arg0 ^ arg1
|
||||
{name: "XORI", argLength: 1, reg: gp11, asm: "XORI", aux: "Int64"}, // arg0 ^ auxint
|
||||
|
||||
// Minimum and maximum
|
||||
{name: "MIN", argLength: 2, reg: gp21, asm: "MIN", commutative: true}, // min(arg0,arg1), signed
|
||||
{name: "MAX", argLength: 2, reg: gp21, asm: "MAX", commutative: true}, // max(arg0,arg1), signed
|
||||
{name: "MINU", argLength: 2, reg: gp21, asm: "MINU", commutative: true}, // min(arg0,arg1), unsigned
|
||||
{name: "MAXU", argLength: 2, reg: gp21, asm: "MAXU", commutative: true}, // max(arg0,arg1), unsigned
|
||||
|
||||
// Generate boolean values
|
||||
{name: "SEQZ", argLength: 1, reg: gp11, asm: "SEQZ"}, // arg0 == 0, result is 0 or 1
|
||||
{name: "SNEZ", argLength: 1, reg: gp11, asm: "SNEZ"}, // arg0 != 0, result is 0 or 1
|
||||
|
|
|
|||
|
|
@ -285,6 +285,12 @@ var genericOps = []opData{
|
|||
{name: "Abs", argLength: 1}, // absolute value arg0
|
||||
{name: "Copysign", argLength: 2}, // copy sign from arg0 to arg1
|
||||
|
||||
// Integer min/max implementation, if hardware is available.
|
||||
{name: "Min64", argLength: 2}, // min(arg0,arg1), signed
|
||||
{name: "Max64", argLength: 2}, // max(arg0,arg1), signed
|
||||
{name: "Min64u", argLength: 2}, // min(arg0,arg1), unsigned
|
||||
{name: "Max64u", argLength: 2}, // max(arg0,arg1), unsigned
|
||||
|
||||
// Float min/max implementation, if hardware is available.
|
||||
{name: "Min64F", argLength: 2}, // min(arg0,arg1)
|
||||
{name: "Min32F", argLength: 2}, // min(arg0,arg1)
|
||||
|
|
|
|||
|
|
@ -2433,6 +2433,10 @@ const (
|
|||
OpRISCV64RORW
|
||||
OpRISCV64XOR
|
||||
OpRISCV64XORI
|
||||
OpRISCV64MIN
|
||||
OpRISCV64MAX
|
||||
OpRISCV64MINU
|
||||
OpRISCV64MAXU
|
||||
OpRISCV64SEQZ
|
||||
OpRISCV64SNEZ
|
||||
OpRISCV64SLT
|
||||
|
|
@ -3074,6 +3078,10 @@ const (
|
|||
OpRoundToEven
|
||||
OpAbs
|
||||
OpCopysign
|
||||
OpMin64
|
||||
OpMax64
|
||||
OpMin64u
|
||||
OpMax64u
|
||||
OpMin64F
|
||||
OpMin32F
|
||||
OpMax64F
|
||||
|
|
@ -32783,6 +32791,66 @@ var opcodeTable = [...]opInfo{
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MIN",
|
||||
argLen: 2,
|
||||
commutative: true,
|
||||
asm: riscv.AMIN,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
|
||||
{1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MAX",
|
||||
argLen: 2,
|
||||
commutative: true,
|
||||
asm: riscv.AMAX,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
|
||||
{1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MINU",
|
||||
argLen: 2,
|
||||
commutative: true,
|
||||
asm: riscv.AMINU,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
|
||||
{1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MAXU",
|
||||
argLen: 2,
|
||||
commutative: true,
|
||||
asm: riscv.AMAXU,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
|
||||
{1, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 1006632944}, // X5 X6 X7 X8 X9 X10 X11 X12 X13 X14 X15 X16 X17 X18 X19 X20 X21 X22 X23 X24 X25 X26 X28 X29 X30
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "SEQZ",
|
||||
argLen: 1,
|
||||
|
|
@ -40032,6 +40100,26 @@ var opcodeTable = [...]opInfo{
|
|||
argLen: 2,
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "Min64",
|
||||
argLen: 2,
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "Max64",
|
||||
argLen: 2,
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "Min64u",
|
||||
argLen: 2,
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "Max64u",
|
||||
argLen: 2,
|
||||
generic: true,
|
||||
},
|
||||
{
|
||||
name: "Min64F",
|
||||
argLen: 2,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
package ssa
|
||||
|
||||
import "internal/buildcfg"
|
||||
import "math"
|
||||
import "cmd/compile/internal/types"
|
||||
|
||||
|
|
@ -329,15 +330,23 @@ func rewriteValueRISCV64(v *Value) bool {
|
|||
case OpMax32F:
|
||||
v.Op = OpRISCV64LoweredFMAXS
|
||||
return true
|
||||
case OpMax64:
|
||||
return rewriteValueRISCV64_OpMax64(v)
|
||||
case OpMax64F:
|
||||
v.Op = OpRISCV64LoweredFMAXD
|
||||
return true
|
||||
case OpMax64u:
|
||||
return rewriteValueRISCV64_OpMax64u(v)
|
||||
case OpMin32F:
|
||||
v.Op = OpRISCV64LoweredFMINS
|
||||
return true
|
||||
case OpMin64:
|
||||
return rewriteValueRISCV64_OpMin64(v)
|
||||
case OpMin64F:
|
||||
v.Op = OpRISCV64LoweredFMIND
|
||||
return true
|
||||
case OpMin64u:
|
||||
return rewriteValueRISCV64_OpMin64u(v)
|
||||
case OpMod16:
|
||||
return rewriteValueRISCV64_OpMod16(v)
|
||||
case OpMod16u:
|
||||
|
|
@ -2396,6 +2405,78 @@ func rewriteValueRISCV64_OpLsh8x8(v *Value) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValueRISCV64_OpMax64(v *Value) bool {
|
||||
v_1 := v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
// match: (Max64 x y)
|
||||
// cond: buildcfg.GORISCV64 >= 22
|
||||
// result: (MAX x y)
|
||||
for {
|
||||
x := v_0
|
||||
y := v_1
|
||||
if !(buildcfg.GORISCV64 >= 22) {
|
||||
break
|
||||
}
|
||||
v.reset(OpRISCV64MAX)
|
||||
v.AddArg2(x, y)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValueRISCV64_OpMax64u(v *Value) bool {
|
||||
v_1 := v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
// match: (Max64u x y)
|
||||
// cond: buildcfg.GORISCV64 >= 22
|
||||
// result: (MAXU x y)
|
||||
for {
|
||||
x := v_0
|
||||
y := v_1
|
||||
if !(buildcfg.GORISCV64 >= 22) {
|
||||
break
|
||||
}
|
||||
v.reset(OpRISCV64MAXU)
|
||||
v.AddArg2(x, y)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValueRISCV64_OpMin64(v *Value) bool {
|
||||
v_1 := v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
// match: (Min64 x y)
|
||||
// cond: buildcfg.GORISCV64 >= 22
|
||||
// result: (MIN x y)
|
||||
for {
|
||||
x := v_0
|
||||
y := v_1
|
||||
if !(buildcfg.GORISCV64 >= 22) {
|
||||
break
|
||||
}
|
||||
v.reset(OpRISCV64MIN)
|
||||
v.AddArg2(x, y)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValueRISCV64_OpMin64u(v *Value) bool {
|
||||
v_1 := v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
// match: (Min64u x y)
|
||||
// cond: buildcfg.GORISCV64 >= 22
|
||||
// result: (MINU x y)
|
||||
for {
|
||||
x := v_0
|
||||
y := v_1
|
||||
if !(buildcfg.GORISCV64 >= 22) {
|
||||
break
|
||||
}
|
||||
v.reset(OpRISCV64MINU)
|
||||
v.AddArg2(x, y)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValueRISCV64_OpMod16(v *Value) bool {
|
||||
v_1 := v.Args[1]
|
||||
v_0 := v.Args[0]
|
||||
|
|
|
|||
|
|
@ -3785,6 +3785,25 @@ func (s *state) minMax(n *ir.CallExpr) *ssa.Value {
|
|||
})
|
||||
}
|
||||
|
||||
if typ.IsInteger() {
|
||||
if Arch.LinkArch.Family == sys.RISCV64 && buildcfg.GORISCV64 >= 22 && typ.Size() == 8 {
|
||||
var op ssa.Op
|
||||
switch {
|
||||
case typ.IsSigned() && n.Op() == ir.OMIN:
|
||||
op = ssa.OpMin64
|
||||
case typ.IsSigned() && n.Op() == ir.OMAX:
|
||||
op = ssa.OpMax64
|
||||
case typ.IsUnsigned() && n.Op() == ir.OMIN:
|
||||
op = ssa.OpMin64u
|
||||
case typ.IsUnsigned() && n.Op() == ir.OMAX:
|
||||
op = ssa.OpMax64u
|
||||
}
|
||||
return fold(func(x, a *ssa.Value) *ssa.Value {
|
||||
return s.newValue2(op, typ, x, a)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
lt := s.ssaOp(ir.OLT, typ)
|
||||
|
||||
return fold(func(x, a *ssa.Value) *ssa.Value {
|
||||
|
|
|
|||
Loading…
Reference in New Issue