From: Meng Zhuo Date: Fri, 12 Sep 2025 09:45:56 +0000 (+0800) Subject: cmd/compile: use MOV(D|F) with const for Const(64|32)F on riscv64 X-Git-Tag: go1.26rc1~476 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=d7a52f93696477a9858dc09a784b4945d3045983;p=gostls13.git cmd/compile: use MOV(D|F) with const for Const(64|32)F on riscv64 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 Reviewed-by: Joel Sing Reviewed-by: David Chase Reviewed-by: Dmitri Shuralyov --- diff --git a/src/cmd/compile/internal/riscv64/ssa.go b/src/cmd/compile/internal/riscv64/ssa.go index 61de983bb0..9aa77c3d02 100644 --- a/src/cmd/compile/internal/riscv64/ssa.go +++ b/src/cmd/compile/internal/riscv64/ssa.go @@ -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 diff --git a/src/cmd/compile/internal/ssa/_gen/RISCV64.rules b/src/cmd/compile/internal/ssa/_gen/RISCV64.rules index 7059273eb2..49bdbc875f 100644 --- a/src/cmd/compile/internal/ssa/_gen/RISCV64.rules +++ b/src/cmd/compile/internal/ssa/_gen/RISCV64.rules @@ -467,8 +467,7 @@ (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))]) @@ -824,16 +823,16 @@ (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 [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 [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 [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 [1] (FCLASSD x))) // Test for +∞ (bit 7) using 64 bit classify instruction. -(FLTD (FMVDX (MOVDconst [int64(math.Float64bits(math.MaxFloat64))])) x) => (SNEZ (ANDI [1<<7] (FCLASSD x))) -(FLED x (FMVDX (MOVDconst [int64(math.Float64bits(math.MaxFloat64))]))) => (SNEZ (ANDI [0xff &^ (1<<7)] (FCLASSD x))) -(FEQD x (FMVDX (MOVDconst [int64(math.Float64bits(math.Inf(1)))]))) => (SNEZ (ANDI [1<<7] (FCLASSD x))) -(FNED x (FMVDX (MOVDconst [int64(math.Float64bits(math.Inf(1)))]))) => (SEQZ (ANDI [1<<7] (FCLASSD x))) +(FLTD (FMOVDconst [c]) x) && float64ExactBits(c, math.MaxFloat64) => (SNEZ (ANDI [1<<7] (FCLASSD x))) +(FLED x (FMOVDconst [c])) && float64ExactBits(c, math.MaxFloat64) => (SNEZ (ANDI [0xff &^ (1<<7)] (FCLASSD x))) +(FEQD x (FMOVDconst [c])) && float64ExactBits(c, math.Inf(1)) => (SNEZ (ANDI [1<<7] (FCLASSD x))) +(FNED x (FMOVDconst [c])) && float64ExactBits(c, math.Inf(1)) => (SEQZ (ANDI [1<<7] (FCLASSD x))) // // Optimisations for rva22u64 and above. diff --git a/src/cmd/compile/internal/ssa/_gen/RISCV64Ops.go b/src/cmd/compile/internal/ssa/_gen/RISCV64Ops.go index 99f8f03637..a0e1ab9754 100644 --- a/src/cmd/compile/internal/ssa/_gen/RISCV64Ops.go +++ b/src/cmd/compile/internal/ssa/_gen/RISCV64Ops.go @@ -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 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 diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go index 061f133338..16a983a568 100644 --- a/src/cmd/compile/internal/ssa/opGen.go +++ b/src/cmd/compile/internal/ssa/opGen.go @@ -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, diff --git a/src/cmd/compile/internal/ssa/rewrite.go b/src/cmd/compile/internal/ssa/rewrite.go index 9ea735a67d..16c28e1ea4 100644 --- a/src/cmd/compile/internal/ssa/rewrite.go +++ b/src/cmd/compile/internal/ssa/rewrite.go @@ -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) } diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go index a7b4cf1bc4..8a390eb85c 100644 --- a/src/cmd/compile/internal/ssa/rewriteRISCV64.go +++ b/src/cmd/compile/internal/ssa/rewriteRISCV64.go @@ -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 [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 [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 [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 [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 [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 [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) diff --git a/test/codegen/floats.go b/test/codegen/floats.go index 666c983b56..b453cabf3b 100644 --- a/test/codegen/floats.go +++ b/test/codegen/floats.go @@ -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 }