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 <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>
This commit is contained in:
Meng Zhuo
2025-09-12 17:45:56 +08:00
parent 6f04a92be3
commit d7a52f9369
7 changed files with 103 additions and 78 deletions

View 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

View File

@@ -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 <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.

View 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

View 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,

View 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)
}

View 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 {
break
}
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpRISCV64MOVDconst || auxIntToInt64(v_0_0.AuxInt) != int64(math.Float64bits(-math.MaxFloat64)) {
if v_0.Op != OpRISCV64FMOVDconst {
break
}
c := auxIntToFloat64(v_0.AuxInt)
x := v_1
if !(float64ExactBits(c, -math.MaxFloat64)) {
break
}
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 {
break
}
v_0_0 := v_0.Args[0]
if v_0_0.Op != OpRISCV64MOVDconst || auxIntToInt64(v_0_0.AuxInt) != int64(math.Float64bits(math.MaxFloat64)) {
if v_0.Op != OpRISCV64FMOVDconst {
break
}
c := auxIntToFloat64(v_0.AuxInt)
x := v_1
if !(float64ExactBits(c, math.MaxFloat64)) {
break
}
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)

View 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
}