Skip to content

Commit

Permalink
all: add floating point option for ARM targets
Browse files Browse the repository at this point in the history
This change introduces new options to set the floating point
mode on ARM targets. The GOARM version number can optionally be
followed by ',hardfloat' or ',softfloat' to select whether to
use hardware instructions or software emulation for floating
point computations, respectively. For example,
GOARM=7,softfloat.

Previously, software floating point support was limited to
GOARM=5. With these options, software floating point is now
extended to all ARM versions, including GOARM=6 and 7. This
change also extends hardware floating point to GOARM=5.

GOARM=5 defaults to softfloat and GOARM=6 and 7 default to
hardfloat.

For #61588

Change-Id: I23dc86fbd0733b262004a2ed001e1032cf371e94
Reviewed-on: https://go-review.googlesource.com/c/go/+/514907
Run-TryBot: Michael Knyszek <[email protected]>
Reviewed-by: Michael Knyszek <[email protected]>
Reviewed-by: Keith Randall <[email protected]>
TryBot-Result: Gopher Robot <[email protected]>
Reviewed-by: Keith Randall <[email protected]>
Auto-Submit: Michael Knyszek <[email protected]>
  • Loading branch information
ludi317 authored and gopherbot committed Nov 20, 2023
1 parent e6b154d commit ee6b347
Show file tree
Hide file tree
Showing 20 changed files with 209 additions and 149 deletions.
4 changes: 2 additions & 2 deletions src/cmd/asm/internal/asm/endtoend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,10 +372,10 @@ func Test386EndToEnd(t *testing.T) {
}

func TestARMEndToEnd(t *testing.T) {
defer func(old int) { buildcfg.GOARM = old }(buildcfg.GOARM)
defer func(old int) { buildcfg.GOARM.Version = old }(buildcfg.GOARM.Version)
for _, goarm := range []int{5, 6, 7} {
t.Logf("GOARM=%d", goarm)
buildcfg.GOARM = goarm
buildcfg.GOARM.Version = goarm
testEndToEnd(t, "arm", "arm")
if goarm == 6 {
testEndToEnd(t, "arm", "armv6")
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/arm/galign.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func Init(arch *ssagen.ArchInfo) {
arch.LinkArch = &arm.Linkarm
arch.REGSP = arm.REGSP
arch.MAXWIDTH = (1 << 32) - 1
arch.SoftFloat = buildcfg.GOARM == 5
arch.SoftFloat = buildcfg.GOARM.SoftFloat
arch.ZeroRange = zerorange
arch.Ginsnop = ginsnop

Expand Down
4 changes: 2 additions & 2 deletions src/cmd/compile/internal/arm/ssa.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
case ssa.OpARMANDconst, ssa.OpARMBICconst:
// try to optimize ANDconst and BICconst to BFC, which saves bytes and ticks
// BFC is only available on ARMv7, and its result and source are in the same register
if buildcfg.GOARM == 7 && v.Reg() == v.Args[0].Reg() {
if buildcfg.GOARM.Version == 7 && v.Reg() == v.Args[0].Reg() {
var val uint32
if v.Op == ssa.OpARMANDconst {
val = ^uint32(v.AuxInt)
Expand Down Expand Up @@ -646,7 +646,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
default:
}
}
if buildcfg.GOARM >= 6 {
if buildcfg.GOARM.Version >= 6 {
// generate more efficient "MOVB/MOVBU/MOVH/MOVHU Reg@>0, Reg" on ARMv6 & ARMv7
genshift(s, v, v.Op.Asm(), 0, v.Args[0].Reg(), v.Reg(), arm.SHIFT_RR, 0)
return
Expand Down
58 changes: 29 additions & 29 deletions src/cmd/compile/internal/ssa/_gen/ARM.rules
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,17 @@

// count trailing zero for ARMv5 and ARMv6
// 32 - CLZ(x&-x - 1)
(Ctz32 <t> x) && buildcfg.GOARM<=6 =>
(Ctz32 <t> x) && buildcfg.GOARM.Version<=6 =>
(RSBconst [32] (CLZ <t> (SUBconst <t> (AND <t> x (RSBconst <t> [0] x)) [1])))
(Ctz16 <t> x) && buildcfg.GOARM<=6 =>
(Ctz16 <t> x) && buildcfg.GOARM.Version<=6 =>
(RSBconst [32] (CLZ <t> (SUBconst <typ.UInt32> (AND <typ.UInt32> (ORconst <typ.UInt32> [0x10000] x) (RSBconst <typ.UInt32> [0] (ORconst <typ.UInt32> [0x10000] x))) [1])))
(Ctz8 <t> x) && buildcfg.GOARM<=6 =>
(Ctz8 <t> x) && buildcfg.GOARM.Version<=6 =>
(RSBconst [32] (CLZ <t> (SUBconst <typ.UInt32> (AND <typ.UInt32> (ORconst <typ.UInt32> [0x100] x) (RSBconst <typ.UInt32> [0] (ORconst <typ.UInt32> [0x100] x))) [1])))

// count trailing zero for ARMv7
(Ctz32 <t> x) && buildcfg.GOARM==7 => (CLZ <t> (RBIT <t> x))
(Ctz16 <t> x) && buildcfg.GOARM==7 => (CLZ <t> (RBIT <typ.UInt32> (ORconst <typ.UInt32> [0x10000] x)))
(Ctz8 <t> x) && buildcfg.GOARM==7 => (CLZ <t> (RBIT <typ.UInt32> (ORconst <typ.UInt32> [0x100] x)))
(Ctz32 <t> x) && buildcfg.GOARM.Version==7 => (CLZ <t> (RBIT <t> x))
(Ctz16 <t> x) && buildcfg.GOARM.Version==7 => (CLZ <t> (RBIT <typ.UInt32> (ORconst <typ.UInt32> [0x10000] x)))
(Ctz8 <t> x) && buildcfg.GOARM.Version==7 => (CLZ <t> (RBIT <typ.UInt32> (ORconst <typ.UInt32> [0x100] x)))

// bit length
(BitLen32 <t> x) => (RSBconst [32] (CLZ <t> x))
Expand All @@ -90,13 +90,13 @@
// t5 = x right rotate 8 bits -- (d, a, b, c )
// result = t4 ^ t5 -- (d, c, b, a )
// using shifted ops this can be done in 4 instructions.
(Bswap32 <t> x) && buildcfg.GOARM==5 =>
(Bswap32 <t> x) && buildcfg.GOARM.Version==5 =>
(XOR <t>
(SRLconst <t> (BICconst <t> (XOR <t> x (SRRconst <t> [16] x)) [0xff0000]) [8])
(SRRconst <t> x [8]))

// byte swap for ARMv6 and above
(Bswap32 x) && buildcfg.GOARM>=6 => (REV x)
(Bswap32 x) && buildcfg.GOARM.Version>=6 => (REV x)

// boolean ops -- booleans are represented with 0=false, 1=true
(AndB ...) => (AND ...)
Expand Down Expand Up @@ -741,10 +741,10 @@
(SUBconst [c] x) && !isARMImmRot(uint32(c)) && isARMImmRot(uint32(-c)) => (ADDconst [-c] x)
(ANDconst [c] x) && !isARMImmRot(uint32(c)) && isARMImmRot(^uint32(c)) => (BICconst [int32(^uint32(c))] x)
(BICconst [c] x) && !isARMImmRot(uint32(c)) && isARMImmRot(^uint32(c)) => (ANDconst [int32(^uint32(c))] x)
(ADDconst [c] x) && buildcfg.GOARM==7 && !isARMImmRot(uint32(c)) && uint32(c)>0xffff && uint32(-c)<=0xffff => (SUBconst [-c] x)
(SUBconst [c] x) && buildcfg.GOARM==7 && !isARMImmRot(uint32(c)) && uint32(c)>0xffff && uint32(-c)<=0xffff => (ADDconst [-c] x)
(ANDconst [c] x) && buildcfg.GOARM==7 && !isARMImmRot(uint32(c)) && uint32(c)>0xffff && ^uint32(c)<=0xffff => (BICconst [int32(^uint32(c))] x)
(BICconst [c] x) && buildcfg.GOARM==7 && !isARMImmRot(uint32(c)) && uint32(c)>0xffff && ^uint32(c)<=0xffff => (ANDconst [int32(^uint32(c))] x)
(ADDconst [c] x) && buildcfg.GOARM.Version==7 && !isARMImmRot(uint32(c)) && uint32(c)>0xffff && uint32(-c)<=0xffff => (SUBconst [-c] x)
(SUBconst [c] x) && buildcfg.GOARM.Version==7 && !isARMImmRot(uint32(c)) && uint32(c)>0xffff && uint32(-c)<=0xffff => (ADDconst [-c] x)
(ANDconst [c] x) && buildcfg.GOARM.Version==7 && !isARMImmRot(uint32(c)) && uint32(c)>0xffff && ^uint32(c)<=0xffff => (BICconst [int32(^uint32(c))] x)
(BICconst [c] x) && buildcfg.GOARM.Version==7 && !isARMImmRot(uint32(c)) && uint32(c)>0xffff && ^uint32(c)<=0xffff => (ANDconst [int32(^uint32(c))] x)
(ADDconst [c] (MOVWconst [d])) => (MOVWconst [c+d])
(ADDconst [c] (ADDconst [d] x)) => (ADDconst [c+d] x)
(ADDconst [c] (SUBconst [d] x)) => (ADDconst [c-d] x)
Expand Down Expand Up @@ -1139,7 +1139,7 @@
// UBFX instruction is supported by ARMv6T2, ARMv7 and above versions, REV16 is supported by
// ARMv6 and above versions. So for ARMv6, we need to match SLLconst, SRLconst and ORshiftLL.
((ADDshiftLL|ORshiftLL|XORshiftLL) <typ.UInt16> [8] (BFXU <typ.UInt16> [int32(armBFAuxInt(8, 8))] x) x) => (REV16 x)
((ADDshiftLL|ORshiftLL|XORshiftLL) <typ.UInt16> [8] (SRLconst <typ.UInt16> [24] (SLLconst [16] x)) x) && buildcfg.GOARM>=6 => (REV16 x)
((ADDshiftLL|ORshiftLL|XORshiftLL) <typ.UInt16> [8] (SRLconst <typ.UInt16> [24] (SLLconst [16] x)) x) && buildcfg.GOARM.Version>=6 => (REV16 x)

// use indexed loads and stores
(MOVWload [0] {sym} (ADD ptr idx) mem) && sym == nil => (MOVWloadidx ptr idx mem)
Expand Down Expand Up @@ -1209,25 +1209,25 @@
(BIC x x) => (MOVWconst [0])

(ADD (MUL x y) a) => (MULA x y a)
(SUB a (MUL x y)) && buildcfg.GOARM == 7 => (MULS x y a)
(RSB (MUL x y) a) && buildcfg.GOARM == 7 => (MULS x y a)
(SUB a (MUL x y)) && buildcfg.GOARM.Version == 7 => (MULS x y a)
(RSB (MUL x y) a) && buildcfg.GOARM.Version == 7 => (MULS x y a)

(NEGF (MULF x y)) && buildcfg.GOARM >= 6 => (NMULF x y)
(NEGD (MULD x y)) && buildcfg.GOARM >= 6 => (NMULD x y)
(MULF (NEGF x) y) && buildcfg.GOARM >= 6 => (NMULF x y)
(MULD (NEGD x) y) && buildcfg.GOARM >= 6 => (NMULD x y)
(NEGF (MULF x y)) && buildcfg.GOARM.Version >= 6 => (NMULF x y)
(NEGD (MULD x y)) && buildcfg.GOARM.Version >= 6 => (NMULD x y)
(MULF (NEGF x) y) && buildcfg.GOARM.Version >= 6 => (NMULF x y)
(MULD (NEGD x) y) && buildcfg.GOARM.Version >= 6 => (NMULD x y)
(NMULF (NEGF x) y) => (MULF x y)
(NMULD (NEGD x) y) => (MULD x y)

// the result will overwrite the addend, since they are in the same register
(ADDF a (MULF x y)) && a.Uses == 1 && buildcfg.GOARM >= 6 => (MULAF a x y)
(ADDF a (NMULF x y)) && a.Uses == 1 && buildcfg.GOARM >= 6 => (MULSF a x y)
(ADDD a (MULD x y)) && a.Uses == 1 && buildcfg.GOARM >= 6 => (MULAD a x y)
(ADDD a (NMULD x y)) && a.Uses == 1 && buildcfg.GOARM >= 6 => (MULSD a x y)
(SUBF a (MULF x y)) && a.Uses == 1 && buildcfg.GOARM >= 6 => (MULSF a x y)
(SUBF a (NMULF x y)) && a.Uses == 1 && buildcfg.GOARM >= 6 => (MULAF a x y)
(SUBD a (MULD x y)) && a.Uses == 1 && buildcfg.GOARM >= 6 => (MULSD a x y)
(SUBD a (NMULD x y)) && a.Uses == 1 && buildcfg.GOARM >= 6 => (MULAD a x y)
(ADDF a (MULF x y)) && a.Uses == 1 && buildcfg.GOARM.Version >= 6 => (MULAF a x y)
(ADDF a (NMULF x y)) && a.Uses == 1 && buildcfg.GOARM.Version >= 6 => (MULSF a x y)
(ADDD a (MULD x y)) && a.Uses == 1 && buildcfg.GOARM.Version >= 6 => (MULAD a x y)
(ADDD a (NMULD x y)) && a.Uses == 1 && buildcfg.GOARM.Version >= 6 => (MULSD a x y)
(SUBF a (MULF x y)) && a.Uses == 1 && buildcfg.GOARM.Version >= 6 => (MULSF a x y)
(SUBF a (NMULF x y)) && a.Uses == 1 && buildcfg.GOARM.Version >= 6 => (MULAF a x y)
(SUBD a (MULD x y)) && a.Uses == 1 && buildcfg.GOARM.Version >= 6 => (MULSD a x y)
(SUBD a (NMULD x y)) && a.Uses == 1 && buildcfg.GOARM.Version >= 6 => (MULAD a x y)

(AND x (MVN y)) => (BIC x y)

Expand Down Expand Up @@ -1259,8 +1259,8 @@
(CMPD x (MOVDconst [0])) => (CMPD0 x)

// bit extraction
(SRAconst (SLLconst x [c]) [d]) && buildcfg.GOARM==7 && uint64(d)>=uint64(c) && uint64(d)<=31 => (BFX [(d-c)|(32-d)<<8] x)
(SRLconst (SLLconst x [c]) [d]) && buildcfg.GOARM==7 && uint64(d)>=uint64(c) && uint64(d)<=31 => (BFXU [(d-c)|(32-d)<<8] x)
(SRAconst (SLLconst x [c]) [d]) && buildcfg.GOARM.Version==7 && uint64(d)>=uint64(c) && uint64(d)<=31 => (BFX [(d-c)|(32-d)<<8] x)
(SRLconst (SLLconst x [c]) [d]) && buildcfg.GOARM.Version==7 && uint64(d)>=uint64(c) && uint64(d)<=31 => (BFXU [(d-c)|(32-d)<<8] x)

// comparison simplification
((EQ|NE) (CMP x (RSBconst [0] y))) => ((EQ|NE) (CMN x y)) // sense of carry bit not preserved; see also #50854
Expand Down
Loading

0 comments on commit ee6b347

Please sign in to comment.