]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: use MOV(D|F) with const for Const(64|32)F on riscv64
authorMeng Zhuo <mengzhuo@iscas.ac.cn>
Fri, 12 Sep 2025 09:45:56 +0000 (17:45 +0800)
committerMeng Zhuo <mengzhuo@iscas.ac.cn>
Mon, 27 Oct 2025 01:35:09 +0000 (18:35 -0700)
The original Const64F using: AUIPC + LD + FMVDX to load
float64 const, we can use AUIPC + FLD instead, same as Const32F.

Change-Id: I8ca0a0e90d820a26e69b74cd25df3cc662132bf7
Reviewed-on: https://go-review.googlesource.com/c/go/+/703215
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Joel Sing <joel@sing.id.au>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.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/opGen.go
src/cmd/compile/internal/ssa/rewrite.go
src/cmd/compile/internal/ssa/rewriteRISCV64.go
test/codegen/floats.go

index 61de983bb02c0053d8d39c5cde8ea2dfa415bce4..9aa77c3d02bd914fb5d9591a9821928c50b458c6 100644 (file)
@@ -446,6 +446,14 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
                p.From.Offset = v.AuxInt
                p.To.Type = obj.TYPE_REG
                p.To.Reg = v.Reg()
+       case ssa.OpRISCV64FMOVDconst, ssa.OpRISCV64FMOVFconst:
+               p := s.Prog(v.Op.Asm())
+               p.From.Type = obj.TYPE_FCONST
+               p.From.Val = v.AuxFloat()
+               p.From.Name = obj.NAME_NONE
+               p.From.Reg = obj.REG_NONE
+               p.To.Type = obj.TYPE_REG
+               p.To.Reg = v.Reg()
        case ssa.OpRISCV64MOVaddr:
                p := s.Prog(v.Op.Asm())
                p.From.Type = obj.TYPE_ADDR
index 7059273eb2fd4c598cf83d8927ec65060233ece0..49bdbc875fc3cdbdef4a91e17c6daa1430d26ab1 100644 (file)
 (OffPtr [off] ptr) => (ADD (MOVDconst [off]) ptr)
 
 (Const(64|32|16|8) [val]) => (MOVDconst [int64(val)])
-(Const32F [val]) => (FMVSX (MOVDconst [int64(math.Float32bits(val))]))
-(Const64F [val]) => (FMVDX (MOVDconst [int64(math.Float64bits(val))]))
+(Const(64|32)F ...) => (FMOV(D|F)const ...)
 (ConstNil) => (MOVDconst [0])
 (ConstBool [val]) => (MOVDconst [int64(b2i(val))])
 
 (F(MADD|NMADD|MSUB|NMSUB)D x y neg:(FNEGD z)) && neg.Uses == 1 => (F(MSUB|NMSUB|MADD|NMADD)D x y z)
 
 // Test for -∞ (bit 0) using 64 bit classify instruction.
-(FLTD x (FMVDX (MOVDconst [int64(math.Float64bits(-math.MaxFloat64))]))) => (ANDI [1] (FCLASSD x))
-(FLED (FMVDX (MOVDconst [int64(math.Float64bits(-math.MaxFloat64))])) x) => (SNEZ (ANDI <typ.Int64> [0xff &^ 1] (FCLASSD x)))
-(FEQD x (FMVDX (MOVDconst [int64(math.Float64bits(math.Inf(-1)))])))  => (ANDI [1] (FCLASSD x))
-(FNED x (FMVDX (MOVDconst [int64(math.Float64bits(math.Inf(-1)))])))  => (SEQZ (ANDI <typ.Int64> [1] (FCLASSD x)))
+(FLTD x (FMOVDconst [c])) && float64ExactBits(c, -math.MaxFloat64) => (ANDI [1] (FCLASSD x))
+(FLED (FMOVDconst [c]) x) && float64ExactBits(c, -math.MaxFloat64) => (SNEZ (ANDI <typ.Int64> [0xff &^ 1] (FCLASSD x)))
+(FEQD x (FMOVDconst [c])) && float64ExactBits(c, math.Inf(-1)) => (ANDI [1] (FCLASSD x))
+(FNED x (FMOVDconst [c])) && float64ExactBits(c, math.Inf(-1)) => (SEQZ (ANDI <typ.Int64> [1] (FCLASSD x)))
 
 // Test for +∞ (bit 7) using 64 bit classify instruction.
-(FLTD (FMVDX (MOVDconst [int64(math.Float64bits(math.MaxFloat64))])) x) => (SNEZ (ANDI <typ.Int64> [1<<7] (FCLASSD x)))
-(FLED x (FMVDX (MOVDconst [int64(math.Float64bits(math.MaxFloat64))]))) => (SNEZ (ANDI <typ.Int64> [0xff &^ (1<<7)] (FCLASSD x)))
-(FEQD x (FMVDX (MOVDconst [int64(math.Float64bits(math.Inf(1)))]))) => (SNEZ (ANDI <typ.Int64> [1<<7] (FCLASSD x)))
-(FNED x (FMVDX (MOVDconst [int64(math.Float64bits(math.Inf(1)))]))) => (SEQZ (ANDI <typ.Int64> [1<<7] (FCLASSD x)))
+(FLTD (FMOVDconst [c]) x) && float64ExactBits(c, math.MaxFloat64) => (SNEZ (ANDI <typ.Int64> [1<<7] (FCLASSD x)))
+(FLED x (FMOVDconst [c])) && float64ExactBits(c, math.MaxFloat64) => (SNEZ (ANDI <typ.Int64> [0xff &^ (1<<7)] (FCLASSD x)))
+(FEQD x (FMOVDconst [c])) && float64ExactBits(c, math.Inf(1)) => (SNEZ (ANDI <typ.Int64> [1<<7] (FCLASSD x)))
+(FNED x (FMOVDconst [c])) && float64ExactBits(c, math.Inf(1)) => (SEQZ (ANDI <typ.Int64> [1<<7] (FCLASSD x)))
 
 //
 // Optimisations for rva22u64 and above.
index 99f8f036379e7b6f59d21a7ea149a73ae9919ccd..a0e1ab9754d34954239c8603ea7b10b2a479df5b 100644 (file)
@@ -132,6 +132,7 @@ func init() {
                gpcas    = regInfo{inputs: []regMask{gpspsbgMask, gpgMask, gpgMask}, outputs: []regMask{gpMask}}
                gpatomic = regInfo{inputs: []regMask{gpspsbgMask, gpgMask}}
 
+               fp01    = regInfo{outputs: []regMask{fpMask}}
                fp11    = regInfo{inputs: []regMask{fpMask}, outputs: []regMask{fpMask}}
                fp21    = regInfo{inputs: []regMask{fpMask, fpMask}, outputs: []regMask{fpMask}}
                fp31    = regInfo{inputs: []regMask{fpMask, fpMask, fpMask}, outputs: []regMask{fpMask}}
@@ -176,7 +177,9 @@ func init() {
                {name: "MOVaddr", argLength: 1, reg: gp11sb, asm: "MOV", aux: "SymOff", rematerializeable: true, symEffect: "Addr"}, // arg0 + auxint + offset encoded in aux
                // auxint+aux == add auxint and the offset of the symbol in aux (if any) to the effective address
 
-               {name: "MOVDconst", reg: gp01, asm: "MOV", typ: "UInt64", aux: "Int64", rematerializeable: true}, // auxint
+               {name: "MOVDconst", reg: gp01, asm: "MOV", typ: "UInt64", aux: "Int64", rematerializeable: true},      // auxint
+               {name: "FMOVDconst", reg: fp01, asm: "MOVD", typ: "Float64", aux: "Float64", rematerializeable: true}, // auxint
+               {name: "FMOVFconst", reg: fp01, asm: "MOVF", typ: "Float32", aux: "Float32", rematerializeable: true}, // auxint
 
                // Loads: load <size> bits from arg0+auxint+aux and extend to 64 bits; arg1=mem
                {name: "MOVBload", argLength: 2, reg: gpload, asm: "MOVB", aux: "SymOff", typ: "Int8", faultOnNilArg0: true, symEffect: "Read"},     //  8 bits, sign extend
index 061f1333382af4c9a75e5f941a9304192087581d..16a983a56878d033f4f0721638e924d2f6dded62 100644 (file)
@@ -2491,6 +2491,8 @@ const (
        OpRISCV64REMUW
        OpRISCV64MOVaddr
        OpRISCV64MOVDconst
+       OpRISCV64FMOVDconst
+       OpRISCV64FMOVFconst
        OpRISCV64MOVBload
        OpRISCV64MOVHload
        OpRISCV64MOVWload
@@ -33462,6 +33464,30 @@ var opcodeTable = [...]opInfo{
                        },
                },
        },
+       {
+               name:              "FMOVDconst",
+               auxType:           auxFloat64,
+               argLen:            0,
+               rematerializeable: true,
+               asm:               riscv.AMOVD,
+               reg: regInfo{
+                       outputs: []outputInfo{
+                               {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+                       },
+               },
+       },
+       {
+               name:              "FMOVFconst",
+               auxType:           auxFloat32,
+               argLen:            0,
+               rematerializeable: true,
+               asm:               riscv.AMOVF,
+               reg: regInfo{
+                       outputs: []outputInfo{
+                               {0, 9223372034707292160}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31
+                       },
+               },
+       },
        {
                name:           "MOVBload",
                auxType:        auxSymOff,
index 9ea735a67d4b7f09f79fb87880a32a18d23878c7..16c28e1ea4572ceae7f9d16f5ef831c0461ee2eb 100644 (file)
@@ -757,6 +757,11 @@ func arm64ConditionalParamsToAuxInt(v arm64ConditionalParams) int64 {
        i |= int64(v.cond)
        return i
 }
+
+func float64ExactBits(f float64, c float64) bool {
+       return math.Float64bits(f) == math.Float64bits(c)
+}
+
 func flagConstantToAuxInt(x flagConstant) int64 {
        return int64(x)
 }
index a7b4cf1bc402d1e93c9c831a20bcfe92ac96ed92..8a390eb85c8870901346fd6585ee46ca999148a9 100644 (file)
@@ -137,11 +137,13 @@ func rewriteValueRISCV64(v *Value) bool {
        case OpConst32:
                return rewriteValueRISCV64_OpConst32(v)
        case OpConst32F:
-               return rewriteValueRISCV64_OpConst32F(v)
+               v.Op = OpRISCV64FMOVFconst
+               return true
        case OpConst64:
                return rewriteValueRISCV64_OpConst64(v)
        case OpConst64F:
-               return rewriteValueRISCV64_OpConst64F(v)
+               v.Op = OpRISCV64FMOVDconst
+               return true
        case OpConst8:
                return rewriteValueRISCV64_OpConst8(v)
        case OpConstBool:
@@ -1098,20 +1100,6 @@ func rewriteValueRISCV64_OpConst32(v *Value) bool {
                return true
        }
 }
-func rewriteValueRISCV64_OpConst32F(v *Value) bool {
-       b := v.Block
-       typ := &b.Func.Config.Types
-       // match: (Const32F [val])
-       // result: (FMVSX (MOVDconst [int64(math.Float32bits(val))]))
-       for {
-               val := auxIntToFloat32(v.AuxInt)
-               v.reset(OpRISCV64FMVSX)
-               v0 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
-               v0.AuxInt = int64ToAuxInt(int64(math.Float32bits(val)))
-               v.AddArg(v0)
-               return true
-       }
-}
 func rewriteValueRISCV64_OpConst64(v *Value) bool {
        // match: (Const64 [val])
        // result: (MOVDconst [int64(val)])
@@ -1122,20 +1110,6 @@ func rewriteValueRISCV64_OpConst64(v *Value) bool {
                return true
        }
 }
-func rewriteValueRISCV64_OpConst64F(v *Value) bool {
-       b := v.Block
-       typ := &b.Func.Config.Types
-       // match: (Const64F [val])
-       // result: (FMVDX (MOVDconst [int64(math.Float64bits(val))]))
-       for {
-               val := auxIntToFloat64(v.AuxInt)
-               v.reset(OpRISCV64FMVDX)
-               v0 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
-               v0.AuxInt = int64ToAuxInt(int64(math.Float64bits(val)))
-               v.AddArg(v0)
-               return true
-       }
-}
 func rewriteValueRISCV64_OpConst8(v *Value) bool {
        // match: (Const8 [val])
        // result: (MOVDconst [int64(val)])
@@ -3608,16 +3582,17 @@ func rewriteValueRISCV64_OpRISCV64FEQD(v *Value) bool {
        v_0 := v.Args[0]
        b := v.Block
        typ := &b.Func.Config.Types
-       // match: (FEQD x (FMVDX (MOVDconst [int64(math.Float64bits(math.Inf(-1)))])))
+       // match: (FEQD x (FMOVDconst [c]))
+       // cond: float64ExactBits(c, math.Inf(-1))
        // result: (ANDI [1] (FCLASSD x))
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
                        x := v_0
-                       if v_1.Op != OpRISCV64FMVDX {
+                       if v_1.Op != OpRISCV64FMOVDconst {
                                continue
                        }
-                       v_1_0 := v_1.Args[0]
-                       if v_1_0.Op != OpRISCV64MOVDconst || auxIntToInt64(v_1_0.AuxInt) != int64(math.Float64bits(math.Inf(-1))) {
+                       c := auxIntToFloat64(v_1.AuxInt)
+                       if !(float64ExactBits(c, math.Inf(-1))) {
                                continue
                        }
                        v.reset(OpRISCV64ANDI)
@@ -3629,16 +3604,17 @@ func rewriteValueRISCV64_OpRISCV64FEQD(v *Value) bool {
                }
                break
        }
-       // match: (FEQD x (FMVDX (MOVDconst [int64(math.Float64bits(math.Inf(1)))])))
+       // match: (FEQD x (FMOVDconst [c]))
+       // cond: float64ExactBits(c, math.Inf(1))
        // result: (SNEZ (ANDI <typ.Int64> [1<<7] (FCLASSD x)))
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
                        x := v_0
-                       if v_1.Op != OpRISCV64FMVDX {
+                       if v_1.Op != OpRISCV64FMOVDconst {
                                continue
                        }
-                       v_1_0 := v_1.Args[0]
-                       if v_1_0.Op != OpRISCV64MOVDconst || auxIntToInt64(v_1_0.AuxInt) != int64(math.Float64bits(math.Inf(1))) {
+                       c := auxIntToFloat64(v_1.AuxInt)
+                       if !(float64ExactBits(c, math.Inf(1))) {
                                continue
                        }
                        v.reset(OpRISCV64SNEZ)
@@ -3659,17 +3635,18 @@ func rewriteValueRISCV64_OpRISCV64FLED(v *Value) bool {
        v_0 := v.Args[0]
        b := v.Block
        typ := &b.Func.Config.Types
-       // match: (FLED (FMVDX (MOVDconst [int64(math.Float64bits(-math.MaxFloat64))])) x)
+       // match: (FLED (FMOVDconst [c]) x)
+       // cond: float64ExactBits(c, -math.MaxFloat64)
        // result: (SNEZ (ANDI <typ.Int64> [0xff &^ 1] (FCLASSD x)))
        for {
-               if v_0.Op != OpRISCV64FMVDX {
+               if v_0.Op != OpRISCV64FMOVDconst {
                        break
                }
-               v_0_0 := v_0.Args[0]
-               if v_0_0.Op != OpRISCV64MOVDconst || auxIntToInt64(v_0_0.AuxInt) != int64(math.Float64bits(-math.MaxFloat64)) {
+               c := auxIntToFloat64(v_0.AuxInt)
+               x := v_1
+               if !(float64ExactBits(c, -math.MaxFloat64)) {
                        break
                }
-               x := v_1
                v.reset(OpRISCV64SNEZ)
                v0 := b.NewValue0(v.Pos, OpRISCV64ANDI, typ.Int64)
                v0.AuxInt = int64ToAuxInt(0xff &^ 1)
@@ -3679,15 +3656,16 @@ func rewriteValueRISCV64_OpRISCV64FLED(v *Value) bool {
                v.AddArg(v0)
                return true
        }
-       // match: (FLED x (FMVDX (MOVDconst [int64(math.Float64bits(math.MaxFloat64))])))
+       // match: (FLED x (FMOVDconst [c]))
+       // cond: float64ExactBits(c, math.MaxFloat64)
        // result: (SNEZ (ANDI <typ.Int64> [0xff &^ (1<<7)] (FCLASSD x)))
        for {
                x := v_0
-               if v_1.Op != OpRISCV64FMVDX {
+               if v_1.Op != OpRISCV64FMOVDconst {
                        break
                }
-               v_1_0 := v_1.Args[0]
-               if v_1_0.Op != OpRISCV64MOVDconst || auxIntToInt64(v_1_0.AuxInt) != int64(math.Float64bits(math.MaxFloat64)) {
+               c := auxIntToFloat64(v_1.AuxInt)
+               if !(float64ExactBits(c, math.MaxFloat64)) {
                        break
                }
                v.reset(OpRISCV64SNEZ)
@@ -3706,15 +3684,16 @@ func rewriteValueRISCV64_OpRISCV64FLTD(v *Value) bool {
        v_0 := v.Args[0]
        b := v.Block
        typ := &b.Func.Config.Types
-       // match: (FLTD x (FMVDX (MOVDconst [int64(math.Float64bits(-math.MaxFloat64))])))
+       // match: (FLTD x (FMOVDconst [c]))
+       // cond: float64ExactBits(c, -math.MaxFloat64)
        // result: (ANDI [1] (FCLASSD x))
        for {
                x := v_0
-               if v_1.Op != OpRISCV64FMVDX {
+               if v_1.Op != OpRISCV64FMOVDconst {
                        break
                }
-               v_1_0 := v_1.Args[0]
-               if v_1_0.Op != OpRISCV64MOVDconst || auxIntToInt64(v_1_0.AuxInt) != int64(math.Float64bits(-math.MaxFloat64)) {
+               c := auxIntToFloat64(v_1.AuxInt)
+               if !(float64ExactBits(c, -math.MaxFloat64)) {
                        break
                }
                v.reset(OpRISCV64ANDI)
@@ -3724,17 +3703,18 @@ func rewriteValueRISCV64_OpRISCV64FLTD(v *Value) bool {
                v.AddArg(v0)
                return true
        }
-       // match: (FLTD (FMVDX (MOVDconst [int64(math.Float64bits(math.MaxFloat64))])) x)
+       // match: (FLTD (FMOVDconst [c]) x)
+       // cond: float64ExactBits(c, math.MaxFloat64)
        // result: (SNEZ (ANDI <typ.Int64> [1<<7] (FCLASSD x)))
        for {
-               if v_0.Op != OpRISCV64FMVDX {
+               if v_0.Op != OpRISCV64FMOVDconst {
                        break
                }
-               v_0_0 := v_0.Args[0]
-               if v_0_0.Op != OpRISCV64MOVDconst || auxIntToInt64(v_0_0.AuxInt) != int64(math.Float64bits(math.MaxFloat64)) {
+               c := auxIntToFloat64(v_0.AuxInt)
+               x := v_1
+               if !(float64ExactBits(c, math.MaxFloat64)) {
                        break
                }
-               x := v_1
                v.reset(OpRISCV64SNEZ)
                v0 := b.NewValue0(v.Pos, OpRISCV64ANDI, typ.Int64)
                v0.AuxInt = int64ToAuxInt(1 << 7)
@@ -4175,16 +4155,17 @@ func rewriteValueRISCV64_OpRISCV64FNED(v *Value) bool {
        v_0 := v.Args[0]
        b := v.Block
        typ := &b.Func.Config.Types
-       // match: (FNED x (FMVDX (MOVDconst [int64(math.Float64bits(math.Inf(-1)))])))
+       // match: (FNED x (FMOVDconst [c]))
+       // cond: float64ExactBits(c, math.Inf(-1))
        // result: (SEQZ (ANDI <typ.Int64> [1] (FCLASSD x)))
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
                        x := v_0
-                       if v_1.Op != OpRISCV64FMVDX {
+                       if v_1.Op != OpRISCV64FMOVDconst {
                                continue
                        }
-                       v_1_0 := v_1.Args[0]
-                       if v_1_0.Op != OpRISCV64MOVDconst || auxIntToInt64(v_1_0.AuxInt) != int64(math.Float64bits(math.Inf(-1))) {
+                       c := auxIntToFloat64(v_1.AuxInt)
+                       if !(float64ExactBits(c, math.Inf(-1))) {
                                continue
                        }
                        v.reset(OpRISCV64SEQZ)
@@ -4198,16 +4179,17 @@ func rewriteValueRISCV64_OpRISCV64FNED(v *Value) bool {
                }
                break
        }
-       // match: (FNED x (FMVDX (MOVDconst [int64(math.Float64bits(math.Inf(1)))])))
+       // match: (FNED x (FMOVDconst [c]))
+       // cond: float64ExactBits(c, math.Inf(1))
        // result: (SEQZ (ANDI <typ.Int64> [1<<7] (FCLASSD x)))
        for {
                for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
                        x := v_0
-                       if v_1.Op != OpRISCV64FMVDX {
+                       if v_1.Op != OpRISCV64FMOVDconst {
                                continue
                        }
-                       v_1_0 := v_1.Args[0]
-                       if v_1_0.Op != OpRISCV64MOVDconst || auxIntToInt64(v_1_0.AuxInt) != int64(math.Float64bits(math.Inf(1))) {
+                       c := auxIntToFloat64(v_1.AuxInt)
+                       if !(float64ExactBits(c, math.Inf(1))) {
                                continue
                        }
                        v.reset(OpRISCV64SEQZ)
index 666c983b56ac04dd9b9f30d66ba654ded6362e58..b453cabf3b44e0863016ca08459301be4e25996a 100644 (file)
@@ -268,10 +268,12 @@ func Float64DenormalFloat32Constant() float64 {
 
 func Float32ConstantStore(p *float32) {
        // amd64:"MOVL\t[$]1085133554"
+       // riscv64: "MOVF\t[$]f32.40add2f2"
        *p = 5.432
 }
 
 func Float64ConstantStore(p *float64) {
-       // amd64:"MOVQ\t[$]4617801906721357038"
+       // amd64: "MOVQ\t[$]4617801906721357038"
+       // riscv64: "MOVD\t[$]f64.4015ba5e353f7cee"
        *p = 5.432
 }