]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/riscv: improve handling of float point moves
authorJoel Sing <joel@sing.id.au>
Fri, 12 Sep 2025 10:54:49 +0000 (20:54 +1000)
committerJoel Sing <joel@sing.id.au>
Tue, 16 Sep 2025 15:43:10 +0000 (08:43 -0700)
Translate moves from an integer register to a floating point register, or
from a floating point register to an integer register, to the appropriate
move instruction (i.e. FMVXW/FMVWX/FMVXD/FMVDX).

Add support for MOVF with a constant - we previously added support for MOVD
but not for MOVF. Add special handling for 0.0, which we can translate to
a move from the zero register to a floating point register (leveraging the
above mentioned change).

Change-Id: If8df2f5610e69b4ec0af85efb884951024685f5b
Reviewed-on: https://go-review.googlesource.com/c/go/+/703216
Reviewed-by: Meng Zhuo <mengzhuo1203@gmail.com>
Reviewed-by: Mark Freeman <markfreeman@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Mark Ryan <markdryan@rivosinc.com>
src/cmd/asm/internal/asm/testdata/riscv64.s
src/cmd/internal/obj/riscv/obj.go

index 4f7e7acd77c90af1255c671d72b7ebf848da8008..39d2faac257e405f23a517867945194da3228cc5 100644 (file)
@@ -1952,12 +1952,23 @@ start:
        MOVF    4(X5), F0                               // 07a04200
        MOVF    F0, 4(X5)                               // 27a20200
        MOVF    F0, F1                                  // d3000020
+       MOVF    X1, F3                                  // d38100f0
+       MOVF    F3, X1                                  // d38001e0
+       MOVF    X0, F3                                  // d30100f0
+       MOVF    $(0.0), F3                              // d30100f0
+
+       // Converted to load of symbol (AUIPC + FLW)
+       MOVF    $(709.78271289338397), F3               // 970f000087a10f00
 
        MOVD    4(X5), F0                               // 07b04200
        MOVD    F0, 4(X5)                               // 27b20200
        MOVD    F0, F1                                  // d3000022
+       MOVD    F3, X1                                  // d38001e2
+       MOVD    X1, F3                                  // d38100f2
+       MOVD    X0, F3                                  // d30100f2
+       MOVD    $(0.0), F3                              // d30100f2
 
-       // Convert to load of symbol (AUIPC + FLD)
+       // Converted to load of symbol (AUIPC + FLD)
        MOVD    $(709.78271289338397), F3               // 970f000087b10f00
 
        // TLS load with local-exec (LUI + ADDIW + ADD of TP + load)
index 1538d03179be24a26a0f7b671271eff4ec65c81b..fcdea57460c083d31752d1be4cad66712ba83d94 100644 (file)
@@ -29,6 +29,7 @@ import (
        "internal/abi"
        "internal/buildcfg"
        "log"
+       "math"
        "math/bits"
        "strings"
 )
@@ -145,9 +146,29 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
                        p.From.Offset = 0
                }
 
+       case AMOVF:
+               if p.From.Type == obj.TYPE_FCONST && p.From.Name == obj.NAME_NONE && p.From.Reg == obj.REG_NONE {
+                       f64 := p.From.Val.(float64)
+                       f32 := float32(f64)
+                       if math.Float32bits(f32) == 0 {
+                               p.From.Type = obj.TYPE_REG
+                               p.From.Reg = REG_ZERO
+                               break
+                       }
+                       p.From.Type = obj.TYPE_MEM
+                       p.From.Sym = ctxt.Float32Sym(f32)
+                       p.From.Name = obj.NAME_EXTERN
+                       p.From.Offset = 0
+               }
+
        case AMOVD:
                if p.From.Type == obj.TYPE_FCONST && p.From.Name == obj.NAME_NONE && p.From.Reg == obj.REG_NONE {
                        f64 := p.From.Val.(float64)
+                       if math.Float64bits(f64) == 0 {
+                               p.From.Type = obj.TYPE_REG
+                               p.From.Reg = REG_ZERO
+                               break
+                       }
                        p.From.Type = obj.TYPE_MEM
                        p.From.Sym = ctxt.Float64Sym(f64)
                        p.From.Name = obj.NAME_EXTERN
@@ -3254,16 +3275,37 @@ func instructionsForMOV(p *obj.Prog) []*instruction {
        case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG:
                // Handle register to register moves.
                switch p.As {
-               case AMOV: // MOV Ra, Rb -> ADDI $0, Ra, Rb
+               case AMOV:
+                       // MOV Ra, Rb -> ADDI $0, Ra, Rb
                        ins.as, ins.rs1, ins.rs2, ins.imm = AADDI, uint32(p.From.Reg), obj.REG_NONE, 0
-               case AMOVW: // MOVW Ra, Rb -> ADDIW $0, Ra, Rb
+               case AMOVW:
+                       // MOVW Ra, Rb -> ADDIW $0, Ra, Rb
                        ins.as, ins.rs1, ins.rs2, ins.imm = AADDIW, uint32(p.From.Reg), obj.REG_NONE, 0
-               case AMOVBU: // MOVBU Ra, Rb -> ANDI $255, Ra, Rb
+               case AMOVBU:
+                       // MOVBU Ra, Rb -> ANDI $255, Ra, Rb
                        ins.as, ins.rs1, ins.rs2, ins.imm = AANDI, uint32(p.From.Reg), obj.REG_NONE, 255
-               case AMOVF: // MOVF Ra, Rb -> FSGNJS Ra, Ra, Rb
-                       ins.as, ins.rs1 = AFSGNJS, uint32(p.From.Reg)
-               case AMOVD: // MOVD Ra, Rb -> FSGNJD Ra, Ra, Rb
-                       ins.as, ins.rs1 = AFSGNJD, uint32(p.From.Reg)
+               case AMOVF:
+                       // MOVF Ra, Rb -> FSGNJS Ra, Ra, Rb
+                       //          or -> FMVWX  Ra, Rb
+                       //          or -> FMVXW  Ra, Rb
+                       if ins.rs2 >= REG_X0 && ins.rs2 <= REG_X31 && ins.rd >= REG_F0 && ins.rd <= REG_F31 {
+                               ins.as = AFMVWX
+                       } else if ins.rs2 >= REG_F0 && ins.rs2 <= REG_F31 && ins.rd >= REG_X0 && ins.rd <= REG_X31 {
+                               ins.as = AFMVXW
+                       } else {
+                               ins.as, ins.rs1 = AFSGNJS, uint32(p.From.Reg)
+                       }
+               case AMOVD:
+                       // MOVD Ra, Rb -> FSGNJD Ra, Ra, Rb
+                       //          or -> FMVDX  Ra, Rb
+                       //          or -> FMVXD  Ra, Rb
+                       if ins.rs2 >= REG_X0 && ins.rs2 <= REG_X31 && ins.rd >= REG_F0 && ins.rd <= REG_F31 {
+                               ins.as = AFMVDX
+                       } else if ins.rs2 >= REG_F0 && ins.rs2 <= REG_F31 && ins.rd >= REG_X0 && ins.rd <= REG_X31 {
+                               ins.as = AFMVXD
+                       } else {
+                               ins.as, ins.rs1 = AFSGNJD, uint32(p.From.Reg)
+                       }
                case AMOVB, AMOVH:
                        if buildcfg.GORISCV64 >= 22 {
                                // Use SEXTB or SEXTH to extend.