cmd/compile/internal/ssa: simplify riscv64 FCLASSD rewrite rules

We don't need to check that the bit patterns of the constants
match, it is sufficient to just check the constant is equal to the
given value.

While we're here also change the FCLASSD rules to use a bit pattern
for the mask. I think this improves readability, particularly as
more uses of FCLASSD get added (e.g. CL 717560).

These changes should not affect codegen.

Change-Id: I92a6338dc71e6a71e04306f67d7d86016c6e9c47
Reviewed-on: https://go-review.googlesource.com/c/go/+/717580
Reviewed-by: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
Michael Munday 2025-11-03 23:05:25 +00:00 committed by Gopher Robot
parent 856238615d
commit a7d174ccaa
3 changed files with 40 additions and 84 deletions

View file

@ -823,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 (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)))
(FLTD x (FMOVDconst [-math.MaxFloat64])) => (ANDI [0b00_0000_0001] (FCLASSD x))
(FLED (FMOVDconst [-math.MaxFloat64]) x) => (SNEZ (ANDI <typ.Int64> [0b00_1111_1110] (FCLASSD x)))
(FEQD x (FMOVDconst [math.Inf(-1)])) => (ANDI [0b00_0000_0001] (FCLASSD x))
(FNED x (FMOVDconst [math.Inf(-1)])) => (SEQZ (ANDI <typ.Int64> [0b00_0000_0001] (FCLASSD x)))
// Test for +∞ (bit 7) using 64 bit classify instruction.
(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)))
(FLTD (FMOVDconst [math.MaxFloat64]) x) => (SNEZ (ANDI <typ.Int64> [0b00_1000_0000] (FCLASSD x)))
(FLED x (FMOVDconst [math.MaxFloat64])) => (SNEZ (ANDI <typ.Int64> [0b00_0111_1111] (FCLASSD x)))
(FEQD x (FMOVDconst [math.Inf(1)])) => (SNEZ (ANDI <typ.Int64> [0b00_1000_0000] (FCLASSD x)))
(FNED x (FMOVDconst [math.Inf(1)])) => (SEQZ (ANDI <typ.Int64> [0b00_1000_0000] (FCLASSD x)))
//
// Optimisations for rva22u64 and above.

View file

@ -765,10 +765,6 @@ func arm64ConditionalParamsToAuxInt(v arm64ConditionalParams) int64 {
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

@ -3582,21 +3582,16 @@ func rewriteValueRISCV64_OpRISCV64FEQD(v *Value) bool {
v_0 := v.Args[0]
b := v.Block
typ := &b.Func.Config.Types
// match: (FEQD x (FMOVDconst [c]))
// cond: float64ExactBits(c, math.Inf(-1))
// result: (ANDI [1] (FCLASSD x))
// match: (FEQD x (FMOVDconst [math.Inf(-1)]))
// result: (ANDI [0b00_0000_0001] (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 != OpRISCV64FMOVDconst {
continue
}
c := auxIntToFloat64(v_1.AuxInt)
if !(float64ExactBits(c, math.Inf(-1))) {
if v_1.Op != OpRISCV64FMOVDconst || auxIntToFloat64(v_1.AuxInt) != math.Inf(-1) {
continue
}
v.reset(OpRISCV64ANDI)
v.AuxInt = int64ToAuxInt(1)
v.AuxInt = int64ToAuxInt(0b00_0000_0001)
v0 := b.NewValue0(v.Pos, OpRISCV64FCLASSD, typ.Int64)
v0.AddArg(x)
v.AddArg(v0)
@ -3604,22 +3599,17 @@ func rewriteValueRISCV64_OpRISCV64FEQD(v *Value) bool {
}
break
}
// match: (FEQD x (FMOVDconst [c]))
// cond: float64ExactBits(c, math.Inf(1))
// result: (SNEZ (ANDI <typ.Int64> [1<<7] (FCLASSD x)))
// match: (FEQD x (FMOVDconst [math.Inf(1)]))
// result: (SNEZ (ANDI <typ.Int64> [0b00_1000_0000] (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 != OpRISCV64FMOVDconst {
continue
}
c := auxIntToFloat64(v_1.AuxInt)
if !(float64ExactBits(c, math.Inf(1))) {
if v_1.Op != OpRISCV64FMOVDconst || auxIntToFloat64(v_1.AuxInt) != math.Inf(1) {
continue
}
v.reset(OpRISCV64SNEZ)
v0 := b.NewValue0(v.Pos, OpRISCV64ANDI, typ.Int64)
v0.AuxInt = int64ToAuxInt(1 << 7)
v0.AuxInt = int64ToAuxInt(0b00_1000_0000)
v1 := b.NewValue0(v.Pos, OpRISCV64FCLASSD, typ.Int64)
v1.AddArg(x)
v0.AddArg(v1)
@ -3635,42 +3625,32 @@ func rewriteValueRISCV64_OpRISCV64FLED(v *Value) bool {
v_0 := v.Args[0]
b := v.Block
typ := &b.Func.Config.Types
// match: (FLED (FMOVDconst [c]) x)
// cond: float64ExactBits(c, -math.MaxFloat64)
// result: (SNEZ (ANDI <typ.Int64> [0xff &^ 1] (FCLASSD x)))
// match: (FLED (FMOVDconst [-math.MaxFloat64]) x)
// result: (SNEZ (ANDI <typ.Int64> [0b00_1111_1110] (FCLASSD x)))
for {
if v_0.Op != OpRISCV64FMOVDconst {
if v_0.Op != OpRISCV64FMOVDconst || auxIntToFloat64(v_0.AuxInt) != -math.MaxFloat64 {
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)
v0.AuxInt = int64ToAuxInt(0b00_1111_1110)
v1 := b.NewValue0(v.Pos, OpRISCV64FCLASSD, typ.Int64)
v1.AddArg(x)
v0.AddArg(v1)
v.AddArg(v0)
return true
}
// match: (FLED x (FMOVDconst [c]))
// cond: float64ExactBits(c, math.MaxFloat64)
// result: (SNEZ (ANDI <typ.Int64> [0xff &^ (1<<7)] (FCLASSD x)))
// match: (FLED x (FMOVDconst [math.MaxFloat64]))
// result: (SNEZ (ANDI <typ.Int64> [0b00_0111_1111] (FCLASSD x)))
for {
x := v_0
if v_1.Op != OpRISCV64FMOVDconst {
break
}
c := auxIntToFloat64(v_1.AuxInt)
if !(float64ExactBits(c, math.MaxFloat64)) {
if v_1.Op != OpRISCV64FMOVDconst || auxIntToFloat64(v_1.AuxInt) != math.MaxFloat64 {
break
}
v.reset(OpRISCV64SNEZ)
v0 := b.NewValue0(v.Pos, OpRISCV64ANDI, typ.Int64)
v0.AuxInt = int64ToAuxInt(0xff &^ (1 << 7))
v0.AuxInt = int64ToAuxInt(0b00_0111_1111)
v1 := b.NewValue0(v.Pos, OpRISCV64FCLASSD, typ.Int64)
v1.AddArg(x)
v0.AddArg(v1)
@ -3684,40 +3664,30 @@ func rewriteValueRISCV64_OpRISCV64FLTD(v *Value) bool {
v_0 := v.Args[0]
b := v.Block
typ := &b.Func.Config.Types
// match: (FLTD x (FMOVDconst [c]))
// cond: float64ExactBits(c, -math.MaxFloat64)
// result: (ANDI [1] (FCLASSD x))
// match: (FLTD x (FMOVDconst [-math.MaxFloat64]))
// result: (ANDI [0b00_0000_0001] (FCLASSD x))
for {
x := v_0
if v_1.Op != OpRISCV64FMOVDconst {
break
}
c := auxIntToFloat64(v_1.AuxInt)
if !(float64ExactBits(c, -math.MaxFloat64)) {
if v_1.Op != OpRISCV64FMOVDconst || auxIntToFloat64(v_1.AuxInt) != -math.MaxFloat64 {
break
}
v.reset(OpRISCV64ANDI)
v.AuxInt = int64ToAuxInt(1)
v.AuxInt = int64ToAuxInt(0b00_0000_0001)
v0 := b.NewValue0(v.Pos, OpRISCV64FCLASSD, typ.Int64)
v0.AddArg(x)
v.AddArg(v0)
return true
}
// match: (FLTD (FMOVDconst [c]) x)
// cond: float64ExactBits(c, math.MaxFloat64)
// result: (SNEZ (ANDI <typ.Int64> [1<<7] (FCLASSD x)))
// match: (FLTD (FMOVDconst [math.MaxFloat64]) x)
// result: (SNEZ (ANDI <typ.Int64> [0b00_1000_0000] (FCLASSD x)))
for {
if v_0.Op != OpRISCV64FMOVDconst {
if v_0.Op != OpRISCV64FMOVDconst || auxIntToFloat64(v_0.AuxInt) != math.MaxFloat64 {
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)
v0.AuxInt = int64ToAuxInt(0b00_1000_0000)
v1 := b.NewValue0(v.Pos, OpRISCV64FCLASSD, typ.Int64)
v1.AddArg(x)
v0.AddArg(v1)
@ -4155,22 +4125,17 @@ func rewriteValueRISCV64_OpRISCV64FNED(v *Value) bool {
v_0 := v.Args[0]
b := v.Block
typ := &b.Func.Config.Types
// match: (FNED x (FMOVDconst [c]))
// cond: float64ExactBits(c, math.Inf(-1))
// result: (SEQZ (ANDI <typ.Int64> [1] (FCLASSD x)))
// match: (FNED x (FMOVDconst [math.Inf(-1)]))
// result: (SEQZ (ANDI <typ.Int64> [0b00_0000_0001] (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 != OpRISCV64FMOVDconst {
continue
}
c := auxIntToFloat64(v_1.AuxInt)
if !(float64ExactBits(c, math.Inf(-1))) {
if v_1.Op != OpRISCV64FMOVDconst || auxIntToFloat64(v_1.AuxInt) != math.Inf(-1) {
continue
}
v.reset(OpRISCV64SEQZ)
v0 := b.NewValue0(v.Pos, OpRISCV64ANDI, typ.Int64)
v0.AuxInt = int64ToAuxInt(1)
v0.AuxInt = int64ToAuxInt(0b00_0000_0001)
v1 := b.NewValue0(v.Pos, OpRISCV64FCLASSD, typ.Int64)
v1.AddArg(x)
v0.AddArg(v1)
@ -4179,22 +4144,17 @@ func rewriteValueRISCV64_OpRISCV64FNED(v *Value) bool {
}
break
}
// match: (FNED x (FMOVDconst [c]))
// cond: float64ExactBits(c, math.Inf(1))
// result: (SEQZ (ANDI <typ.Int64> [1<<7] (FCLASSD x)))
// match: (FNED x (FMOVDconst [math.Inf(1)]))
// result: (SEQZ (ANDI <typ.Int64> [0b00_1000_0000] (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 != OpRISCV64FMOVDconst {
continue
}
c := auxIntToFloat64(v_1.AuxInt)
if !(float64ExactBits(c, math.Inf(1))) {
if v_1.Op != OpRISCV64FMOVDconst || auxIntToFloat64(v_1.AuxInt) != math.Inf(1) {
continue
}
v.reset(OpRISCV64SEQZ)
v0 := b.NewValue0(v.Pos, OpRISCV64ANDI, typ.Int64)
v0.AuxInt = int64ToAuxInt(1 << 7)
v0.AuxInt = int64ToAuxInt(0b00_1000_0000)
v1 := b.NewValue0(v.Pos, OpRISCV64FCLASSD, typ.Int64)
v1.AddArg(x)
v0.AddArg(v1)