From: Joel Sing Date: Tue, 17 Aug 2021 18:45:11 +0000 (+0000) Subject: cmd/internal/obj/riscv: avoid obj.Prog rewriting for constant loads X-Git-Tag: go1.18beta1~1485 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=9cb5716f009ea71564a9ee84d653d7a76adf9926;p=gostls13.git cmd/internal/obj/riscv: avoid obj.Prog rewriting for constant loads 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 Reviewed-by: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Go Bot --- diff --git a/src/cmd/asm/internal/asm/testdata/riscv64.s b/src/cmd/asm/internal/asm/testdata/riscv64.s index 173c50f2e1..b22d1a7e37 100644 --- a/src/cmd/asm/internal/asm/testdata/riscv64.s +++ b/src/cmd/asm/internal/asm/testdata/riscv64.s @@ -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 diff --git a/src/cmd/internal/obj/riscv/obj.go b/src/cmd/internal/obj/riscv/obj.go index f602183e04..3ccd489573 100644 --- a/src/cmd/internal/obj/riscv/obj.go +++ b/src/cmd/internal/obj/riscv/obj.go @@ -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 {