]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: use integer min/max instructions on riscv64
authorJoel Sing <joel@sing.id.au>
Wed, 31 Jan 2024 13:39:30 +0000 (00:39 +1100)
committerJoel Sing <joel@sing.id.au>
Mon, 19 Aug 2024 13:46:02 +0000 (13:46 +0000)
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>
src/cmd/compile/internal/riscv64/ssa.go
src/cmd/compile/internal/ssa/_gen/RISCV64.rules
src/cmd/compile/internal/ssa/_gen/RISCV64Ops.go
src/cmd/compile/internal/ssa/_gen/genericOps.go
src/cmd/compile/internal/ssa/opGen.go
src/cmd/compile/internal/ssa/rewriteRISCV64.go
src/cmd/compile/internal/ssagen/ssa.go

index 3c57bc93bcaa597d00ab8e8d15f07d83ef7ac5e9..10fea07e60f36b3a6a537ea49980755e69467830 100644 (file)
@@ -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()
index c2df4333156b38a10df82378da98d794e8fcff1a..7d8fb79e17d56240c8ab6a4b15601b1b90ceb75e 100644 (file)
 (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)
index 13fa91864bfd942cdfb99207433d388e85e78608..7323cb119c975a5ba7ec2541d6120955c07118a5 100644 (file)
@@ -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
index 47d82924e6007c0159f3e4199587657570232ff0..c3043f58d05e609b063237e9f9d4e64604da1868 100644 (file)
@@ -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)
index ef39c6894fd5cb453a532cde3bed2245023ec60f..a1dafe37cf219a2ab84dd5d0357a3bc3eab67c25 100644 (file)
@@ -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,
index f033b25bddeb100e282de729326fbe4dc4b757fa..0ad90782586a0be14288b3a28b94bdedee3ebbfd 100644 (file)
@@ -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]
index 14e75f74f376320b7d4043c013cc2a5cd5fa5fcf..dd16169103cd5036eb765e8e73202318e819dcc7 100644 (file)
@@ -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 {