mirror of
https://github.com/golang/go
synced 2024-09-05 16:04:50 +00:00
cmd/internal/obj/ppc64: generate small, shifted constants in register
Check for shifted 16b constants, and transform them to avoid the load penalty. This should be much faster than loading, and reduce binary size by reducing the constant pool size. Change-Id: I6834e08be7ca88e3b77449d226d08d199db84299 Reviewed-on: https://go-review.googlesource.com/c/go/+/531119 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Lynn Boger <laboger@linux.vnet.ibm.com> Reviewed-by: Michael Pratt <mpratt@google.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Paul Murphy <murp@ibm.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
e47cab13a5
commit
36ecff0893
18
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
18
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
|
@ -32,11 +32,17 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
|||
MOVW $2147483649, R5 // 6405800060a50001 or 0600800038a00001
|
||||
MOVD $2147483649, R5 // 6405800060a50001 or 0600800038a00001
|
||||
// Hex constant 0xFFFFFFFF80000001
|
||||
MOVD $-2147483647, R5 // 3ca0800060a50001 or 0603800038a00001
|
||||
// Hex constant 0xFFFFFFFE00000000 (load of constant on < power10, pli on >= power10
|
||||
MOVD $-8589934592, R5 // 3ca00000e8a50000 or 0602000038a00000
|
||||
// Hex constant 0xFFFFFFFE00000000
|
||||
ADD $-8589934592, R5 // 3fe0fffe63ff00007bff83e463ff00007cbf2a14 or 0602000038a50000
|
||||
MOVD $-2147483647, R5 // 3ca0800060a50001 or 0603800038a00001
|
||||
// Hex constant 0xFFFFFFFE00000002 (load of constant on < power10, pli on >= power10
|
||||
MOVD $-8589934590, R5 // 3ca00000e8a50000 or 0602000038a00002
|
||||
|
||||
// TODO: These are preprocessed by the assembler into MOVD $const>>shift, R5; SLD $shift, R5.
|
||||
// This only captures the MOVD. Should the SLD be appended to the encoding by the test?
|
||||
// Hex constant 0x20004000000
|
||||
MOVD $2199090364416, R5 // 60058001
|
||||
// Hex constant 0xFFFFFE0004000000
|
||||
MOVD $-2198956146688, R5 // 38a08001
|
||||
|
||||
MOVD 8(R3), R4 // e8830008
|
||||
MOVD (R3)(R4), R5 // 7ca4182a
|
||||
MOVD (R3)(R0), R5 // 7ca0182a
|
||||
|
@ -168,6 +174,8 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
|||
ADD $-32767, R5, R4 // 38858001
|
||||
ADD $-32768, R6 // 38c68000
|
||||
ADD $-32768, R6, R5 // 38a68000
|
||||
// Hex constant 0xFFFFFFFE00000000
|
||||
ADD $-8589934592, R5 // 3fe0fffe63ff00007bff83e463ff00007cbf2a14 or 0602000038a50000
|
||||
|
||||
//TODO: this compiles to add r5,r6,r0. It should be addi r5,r6,0.
|
||||
// this is OK since r0 == $0, but the latter is preferred.
|
||||
|
|
|
@ -36,6 +36,7 @@ import (
|
|||
"cmd/internal/sys"
|
||||
"internal/abi"
|
||||
"log"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
|
||||
|
@ -80,19 +81,34 @@ func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
|
|||
}
|
||||
|
||||
case AMOVD:
|
||||
// 32b constants (signed and unsigned) can be generated via 1 or 2 instructions.
|
||||
// 32b constants (signed and unsigned) can be generated via 1 or 2 instructions. They can be assembled directly.
|
||||
isS32 := int64(int32(p.From.Offset)) == p.From.Offset
|
||||
isU32 := uint64(uint32(p.From.Offset)) == uint64(p.From.Offset)
|
||||
|
||||
// If prefixed instructions are supported, a 34b signed constant can be generated by one pli instruction.
|
||||
isS34 := pfxEnabled && (p.From.Offset<<30)>>30 == p.From.Offset
|
||||
|
||||
// If the constant cannot be generated with 2 or less instructions, it must be placed in memory and loaded.
|
||||
if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE && p.From.Reg == 0 && !isS32 && !isU32 && !isS34 {
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Sym = ctxt.Int64Sym(p.From.Offset)
|
||||
p.From.Name = obj.NAME_EXTERN
|
||||
p.From.Offset = 0
|
||||
|
||||
// Is this a shifted 16b constant? If so, rewrite it to avoid a creating and loading a constant.
|
||||
val := p.From.Offset
|
||||
shift := bits.TrailingZeros64(uint64(val))
|
||||
mask := 0xFFFF << shift
|
||||
if val&int64(mask) == val || (val>>(shift+16) == -1 && (val>>shift)<<shift == val) {
|
||||
// Rewrite this value into MOVD $const>>shift, Rto; SLD $shift, Rto
|
||||
q := obj.Appendp(p, c.newprog)
|
||||
q.As = ASLD
|
||||
q.From.Type = obj.TYPE_CONST
|
||||
q.From.Offset = int64(shift)
|
||||
q.To = p.To
|
||||
p.From.Offset >>= shift
|
||||
p = q
|
||||
} else {
|
||||
// Load the constant from memory.
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Sym = ctxt.Int64Sym(p.From.Offset)
|
||||
p.From.Name = obj.NAME_EXTERN
|
||||
p.From.Offset = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
25
test/codegen/constants.go
Normal file
25
test/codegen/constants.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
// asmcheck
|
||||
|
||||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package codegen
|
||||
|
||||
func shifted16BitConstants(out [64]uint64) {
|
||||
// ppc64x: "MOVD\t[$]8193,", "SLD\t[$]27,"
|
||||
out[0] = 0x0000010008000000
|
||||
// ppc64x: "MOVD\t[$]-32767", "SLD\t[$]26,"
|
||||
out[1] = 0xFFFFFE0004000000
|
||||
// ppc64x: "MOVD\t[$]-1", "SLD\t[$]48,"
|
||||
out[2] = 0xFFFF000000000000
|
||||
// ppc64x: "MOVD\t[$]65535", "SLD\t[$]44,"
|
||||
out[3] = 0x0FFFF00000000000
|
||||
|
||||
// ppc64x: "MOVD\t[$]i64.fffff00000000001[(]SB[)]"
|
||||
out[4] = 0xFFFFF00000000001
|
||||
// ppc64x: "MOVD\t[$]i64.fffff80000000001[(]SB[)]"
|
||||
out[5] = 0xFFFFF80000000001
|
||||
// ppc64x: "MOVD\t[$]i64.0ffff80000000000[(]SB[)]"
|
||||
out[6] = 0x0FFFF80000000000
|
||||
}
|
Loading…
Reference in a new issue