]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj/riscv: avoid obj.Prog rewriting for constant loads
authorJoel Sing <joel@sing.id.au>
Tue, 17 Aug 2021 18:45:11 +0000 (18:45 +0000)
committerJoel Sing <joel@sing.id.au>
Sat, 4 Sep 2021 10:42:34 +0000 (10:42 +0000)
Rather than rewriting the obj.Prog for a MOV pseudo-instruction targeting
a constant to register load, generate the appropriate machine instruction
sequence directly.

Change-Id: I38e62f282b39be2a0a241f32280d306558d49b44
Reviewed-on: https://go-review.googlesource.com/c/go/+/344450
Trust: Joel Sing <joel@sing.id.au>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>

src/cmd/asm/internal/asm/testdata/riscv64.s
src/cmd/internal/obj/riscv/obj.go

index 173c50f2e18a0a7540776947d6574febfa790022..b22d1a7e37833e45c0a0b0b3e36ea3bd4fce7e22 100644 (file)
@@ -282,6 +282,8 @@ start:
        MOV     X5, X6                                  // 13830200
        MOV     $2047, X5                               // 9b02f07f
        MOV     $-2048, X5                              // 9b020080
+       MOV     $2048, X5                               // b71200009b820280
+       MOV     $-2049, X5                              // b7f2ffff9b82f27f
 
        // Converted to load of symbol.
        MOV     $4294967296, X5                         // 97020000
index f602183e04f027f9eecd5b5c948317cacb64402b..3ccd4895734f5a092b097d30562c2b9acd553dae 100644 (file)
@@ -305,42 +305,12 @@ func rewriteMOV(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog) {
                }
 
        case obj.TYPE_CONST:
-               // MOV $c, R
-               // If c is small enough, convert to:
-               //   ADD $c, ZERO, R
-               // If not, convert to:
-               //   LUI top20bits(c), R
-               //   ADD bottom12bits(c), R, R
                if p.As != AMOV {
                        ctxt.Diag("%v: unsupported constant load", p)
                }
                if p.To.Type != obj.TYPE_REG {
                        ctxt.Diag("%v: constant load must target register", p)
                }
-               off := p.From.Offset
-               to := p.To
-
-               low, high, err := Split32BitImmediate(off)
-               if err != nil {
-                       ctxt.Diag("%v: constant %d too large: %v", p, off, err)
-               }
-
-               // LUI is only necessary if the offset doesn't fit in 12-bits.
-               needLUI := high != 0
-               if needLUI {
-                       p.As = ALUI
-                       p.To = to
-                       // Pass top 20 bits to LUI.
-                       p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high}
-                       p = obj.Appendp(p, newprog)
-               }
-               p.As = AADDIW
-               p.To = to
-               p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: low}
-               p.Reg = REG_ZERO
-               if needLUI {
-                       p.Reg = to.Reg
-               }
 
        case obj.TYPE_ADDR: // MOV $sym+off(SP/SB), R
                if p.To.Type != obj.TYPE_REG || p.As != AMOV {
@@ -1845,6 +1815,28 @@ func instructionsForMOV(p *obj.Prog) []*instruction {
        inss := []*instruction{ins}
 
        switch {
+       case p.From.Type == obj.TYPE_CONST && p.To.Type == obj.TYPE_REG:
+               // Handle constant to register moves.
+               low, high, err := Split32BitImmediate(ins.imm)
+               if err != nil {
+                       p.Ctxt.Diag("%v: constant %d too large: %v", p, ins.imm, err)
+                       return nil
+               }
+
+               // MOV $c, R -> ADD $c, ZERO, R
+               ins.as, ins.rs1, ins.rs2, ins.imm = AADDIW, REG_ZERO, obj.REG_NONE, low
+
+               // LUI is only necessary if the constant does not fit in 12 bits.
+               if high == 0 {
+                       break
+               }
+
+               // LUI top20bits(c), R
+               // ADD bottom12bits(c), R, R
+               insLUI := &instruction{as: ALUI, rd: ins.rd, imm: high}
+               ins.rs1 = ins.rd
+               inss = []*instruction{insLUI, ins}
+
        case p.From.Type == obj.TYPE_REG && p.To.Type == obj.TYPE_REG:
                // Handle register to register moves.
                switch p.As {