diff options
| author | Paul E. Murphy <murp@ibm.com> | 2023-09-18 17:14:03 -0500 |
|---|---|---|
| committer | Paul Murphy <murp@ibm.com> | 2023-10-04 19:10:19 +0000 |
| commit | 36ecff0893e8f30c2ff659acf8c62401f4dcebf7 (patch) | |
| tree | 0f50e6029ea9e5b7dc136f2af0030cb43db645c9 /src/cmd/internal/obj/ppc64/obj9.go | |
| parent | e47cab13a5acfb99ed6e62eeb51772af94c5f526 (diff) | |
| download | go-36ecff0893e8f30c2ff659acf8c62401f4dcebf7.tar.xz | |
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>
Diffstat (limited to 'src/cmd/internal/obj/ppc64/obj9.go')
| -rw-r--r-- | src/cmd/internal/obj/ppc64/obj9.go | 30 |
1 files changed, 23 insertions, 7 deletions
diff --git a/src/cmd/internal/obj/ppc64/obj9.go b/src/cmd/internal/obj/ppc64/obj9.go index 7cd4dc2396..df0c36cde0 100644 --- a/src/cmd/internal/obj/ppc64/obj9.go +++ b/src/cmd/internal/obj/ppc64/obj9.go @@ -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 + } } } |
