mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile,cmd/internal/obj/riscv: load >32-bit constants from memory for riscv64
Follow what MIPS does and load >32-bit constants from memory using two instructions, rather than generating a four to six instruction sequence. This removes more than 2,500 instructions from the Go binary. This also makes it possible to load >32-bit constants via a single assembly instruction, if required. Change-Id: Ie679a0754071e6d8c52fe0d027f00eb241b3a758 Reviewed-on: https://go-review.googlesource.com/c/go/+/302609 Trust: Joel Sing <joel@sing.id.au> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
42c25e65f3
commit
c2d625168f
4 changed files with 23 additions and 67 deletions
25
src/cmd/asm/internal/asm/testdata/riscv64.s
vendored
25
src/cmd/asm/internal/asm/testdata/riscv64.s
vendored
|
|
@ -280,6 +280,9 @@ start:
|
||||||
MOV $2047, X5 // 9b02f07f
|
MOV $2047, X5 // 9b02f07f
|
||||||
MOV $-2048, X5 // 9b020080
|
MOV $-2048, X5 // 9b020080
|
||||||
|
|
||||||
|
// Converted to load of symbol.
|
||||||
|
MOV $4294967296, X5 // 97020000
|
||||||
|
|
||||||
MOV (X5), X6 // 03b30200
|
MOV (X5), X6 // 03b30200
|
||||||
MOV 4(X5), X6 // 03b34200
|
MOV 4(X5), X6 // 03b34200
|
||||||
MOVB (X5), X6 // 03830200
|
MOVB (X5), X6 // 03830200
|
||||||
|
|
@ -325,7 +328,7 @@ start:
|
||||||
// These jumps can get printed as jumps to 2 because they go to the
|
// These jumps can get printed as jumps to 2 because they go to the
|
||||||
// second instruction in the function (the first instruction is an
|
// second instruction in the function (the first instruction is an
|
||||||
// invisible stack pointer adjustment).
|
// invisible stack pointer adjustment).
|
||||||
JMP start // JMP 2 // 6ff09fc2
|
JMP start // JMP 2 // 6ff01fc2
|
||||||
JMP (X5) // 67800200
|
JMP (X5) // 67800200
|
||||||
JMP 4(X5) // 67804200
|
JMP 4(X5) // 67804200
|
||||||
|
|
||||||
|
|
@ -338,16 +341,16 @@ start:
|
||||||
JMP asmtest(SB) // 970f0000
|
JMP asmtest(SB) // 970f0000
|
||||||
|
|
||||||
// Branch pseudo-instructions
|
// Branch pseudo-instructions
|
||||||
BEQZ X5, start // BEQZ X5, 2 // e38602c0
|
BEQZ X5, start // BEQZ X5, 2 // e38202c0
|
||||||
BGEZ X5, start // BGEZ X5, 2 // e3d402c0
|
BGEZ X5, start // BGEZ X5, 2 // e3d002c0
|
||||||
BGT X5, X6, start // BGT X5, X6, 2 // e34253c0
|
BGT X5, X6, start // BGT X5, X6, 2 // e34e53be
|
||||||
BGTU X5, X6, start // BGTU X5, X6, 2 // e36053c0
|
BGTU X5, X6, start // BGTU X5, X6, 2 // e36c53be
|
||||||
BGTZ X5, start // BGTZ X5, 2 // e34e50be
|
BGTZ X5, start // BGTZ X5, 2 // e34a50be
|
||||||
BLE X5, X6, start // BLE X5, X6, 2 // e35c53be
|
BLE X5, X6, start // BLE X5, X6, 2 // e35853be
|
||||||
BLEU X5, X6, start // BLEU X5, X6, 2 // e37a53be
|
BLEU X5, X6, start // BLEU X5, X6, 2 // e37653be
|
||||||
BLEZ X5, start // BLEZ X5, 2 // e35850be
|
BLEZ X5, start // BLEZ X5, 2 // e35450be
|
||||||
BLTZ X5, start // BLTZ X5, 2 // e3c602be
|
BLTZ X5, start // BLTZ X5, 2 // e3c202be
|
||||||
BNEZ X5, start // BNEZ X5, 2 // e39402be
|
BNEZ X5, start // BNEZ X5, 2 // e39002be
|
||||||
|
|
||||||
// Set pseudo-instructions
|
// Set pseudo-instructions
|
||||||
SEQZ X15, X15 // 93b71700
|
SEQZ X15, X15 // 93b71700
|
||||||
|
|
|
||||||
|
|
@ -531,15 +531,6 @@
|
||||||
(ConstNil) => (MOVDconst [0])
|
(ConstNil) => (MOVDconst [0])
|
||||||
(ConstBool [val]) => (MOVDconst [int64(b2i(val))])
|
(ConstBool [val]) => (MOVDconst [int64(b2i(val))])
|
||||||
|
|
||||||
// Convert 64 bit immediate to two 32 bit immediates, combine with add and shift.
|
|
||||||
// The lower 32 bit immediate will be treated as signed,
|
|
||||||
// so if it is negative, adjust for the borrow by incrementing the top half.
|
|
||||||
// We don't have to worry about overflow from the increment,
|
|
||||||
// because if the top half is all 1s, and int32(c) is negative,
|
|
||||||
// then the overall constant fits in an int32.
|
|
||||||
(MOVDconst <t> [c]) && !is32Bit(c) && int32(c) < 0 => (ADD (SLLI <t> [32] (MOVDconst [c>>32+1])) (MOVDconst [int64(int32(c))]))
|
|
||||||
(MOVDconst <t> [c]) && !is32Bit(c) && int32(c) >= 0 => (ADD (SLLI <t> [32] (MOVDconst [c>>32+0])) (MOVDconst [int64(int32(c))]))
|
|
||||||
|
|
||||||
(Addr {sym} base) => (MOVaddr {sym} [0] base)
|
(Addr {sym} base) => (MOVaddr {sym} [0] base)
|
||||||
(LocalAddr {sym} base _) => (MOVaddr {sym} base)
|
(LocalAddr {sym} base _) => (MOVaddr {sym} base)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -438,8 +438,6 @@ func rewriteValueRISCV64(v *Value) bool {
|
||||||
return rewriteValueRISCV64_OpRISCV64MOVBstore(v)
|
return rewriteValueRISCV64_OpRISCV64MOVBstore(v)
|
||||||
case OpRISCV64MOVBstorezero:
|
case OpRISCV64MOVBstorezero:
|
||||||
return rewriteValueRISCV64_OpRISCV64MOVBstorezero(v)
|
return rewriteValueRISCV64_OpRISCV64MOVBstorezero(v)
|
||||||
case OpRISCV64MOVDconst:
|
|
||||||
return rewriteValueRISCV64_OpRISCV64MOVDconst(v)
|
|
||||||
case OpRISCV64MOVDload:
|
case OpRISCV64MOVDload:
|
||||||
return rewriteValueRISCV64_OpRISCV64MOVDload(v)
|
return rewriteValueRISCV64_OpRISCV64MOVDload(v)
|
||||||
case OpRISCV64MOVDnop:
|
case OpRISCV64MOVDnop:
|
||||||
|
|
@ -3262,51 +3260,6 @@ func rewriteValueRISCV64_OpRISCV64MOVBstorezero(v *Value) bool {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueRISCV64_OpRISCV64MOVDconst(v *Value) bool {
|
|
||||||
b := v.Block
|
|
||||||
typ := &b.Func.Config.Types
|
|
||||||
// match: (MOVDconst <t> [c])
|
|
||||||
// cond: !is32Bit(c) && int32(c) < 0
|
|
||||||
// result: (ADD (SLLI <t> [32] (MOVDconst [c>>32+1])) (MOVDconst [int64(int32(c))]))
|
|
||||||
for {
|
|
||||||
t := v.Type
|
|
||||||
c := auxIntToInt64(v.AuxInt)
|
|
||||||
if !(!is32Bit(c) && int32(c) < 0) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpRISCV64ADD)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpRISCV64SLLI, t)
|
|
||||||
v0.AuxInt = int64ToAuxInt(32)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
|
|
||||||
v1.AuxInt = int64ToAuxInt(c>>32 + 1)
|
|
||||||
v0.AddArg(v1)
|
|
||||||
v2 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
|
|
||||||
v2.AuxInt = int64ToAuxInt(int64(int32(c)))
|
|
||||||
v.AddArg2(v0, v2)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// match: (MOVDconst <t> [c])
|
|
||||||
// cond: !is32Bit(c) && int32(c) >= 0
|
|
||||||
// result: (ADD (SLLI <t> [32] (MOVDconst [c>>32+0])) (MOVDconst [int64(int32(c))]))
|
|
||||||
for {
|
|
||||||
t := v.Type
|
|
||||||
c := auxIntToInt64(v.AuxInt)
|
|
||||||
if !(!is32Bit(c) && int32(c) >= 0) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
v.reset(OpRISCV64ADD)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpRISCV64SLLI, t)
|
|
||||||
v0.AuxInt = int64ToAuxInt(32)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
|
|
||||||
v1.AuxInt = int64ToAuxInt(c>>32 + 0)
|
|
||||||
v0.AddArg(v1)
|
|
||||||
v2 := b.NewValue0(v.Pos, OpRISCV64MOVDconst, typ.UInt64)
|
|
||||||
v2.AuxInt = int64ToAuxInt(int64(int32(c)))
|
|
||||||
v.AddArg2(v0, v2)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
func rewriteValueRISCV64_OpRISCV64MOVDload(v *Value) bool {
|
func rewriteValueRISCV64_OpRISCV64MOVDload(v *Value) bool {
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,15 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
|
||||||
case ASBREAK:
|
case ASBREAK:
|
||||||
// SBREAK is the old name for EBREAK.
|
// SBREAK is the old name for EBREAK.
|
||||||
p.As = AEBREAK
|
p.As = AEBREAK
|
||||||
|
|
||||||
|
case AMOV:
|
||||||
|
// Put >32-bit constants in memory and load them.
|
||||||
|
if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE && p.From.Reg == 0 && int64(int32(p.From.Offset)) != p.From.Offset {
|
||||||
|
p.From.Type = obj.TYPE_MEM
|
||||||
|
p.From.Sym = ctxt.Int64Sym(p.From.Offset)
|
||||||
|
p.From.Name = obj.NAME_EXTERN
|
||||||
|
p.From.Offset = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue