Skip to content

Commit 36ecff0

Browse files
committed
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 <[email protected]> Reviewed-by: Lynn Boger <[email protected]> Reviewed-by: Michael Pratt <[email protected]> Reviewed-by: Matthew Dempsky <[email protected]> Run-TryBot: Paul Murphy <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent e47cab1 commit 36ecff0

File tree

3 files changed

+61
-12
lines changed

3 files changed

+61
-12
lines changed

src/cmd/asm/internal/asm/testdata/ppc64.s

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,17 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
3232
MOVW $2147483649, R5 // 6405800060a50001 or 0600800038a00001
3333
MOVD $2147483649, R5 // 6405800060a50001 or 0600800038a00001
3434
// Hex constant 0xFFFFFFFF80000001
35-
MOVD $-2147483647, R5 // 3ca0800060a50001 or 0603800038a00001
36-
// Hex constant 0xFFFFFFFE00000000 (load of constant on < power10, pli on >= power10
37-
MOVD $-8589934592, R5 // 3ca00000e8a50000 or 0602000038a00000
38-
// Hex constant 0xFFFFFFFE00000000
39-
ADD $-8589934592, R5 // 3fe0fffe63ff00007bff83e463ff00007cbf2a14 or 0602000038a50000
35+
MOVD $-2147483647, R5 // 3ca0800060a50001 or 0603800038a00001
36+
// Hex constant 0xFFFFFFFE00000002 (load of constant on < power10, pli on >= power10
37+
MOVD $-8589934590, R5 // 3ca00000e8a50000 or 0602000038a00002
38+
39+
// TODO: These are preprocessed by the assembler into MOVD $const>>shift, R5; SLD $shift, R5.
40+
// This only captures the MOVD. Should the SLD be appended to the encoding by the test?
41+
// Hex constant 0x20004000000
42+
MOVD $2199090364416, R5 // 60058001
43+
// Hex constant 0xFFFFFE0004000000
44+
MOVD $-2198956146688, R5 // 38a08001
45+
4046
MOVD 8(R3), R4 // e8830008
4147
MOVD (R3)(R4), R5 // 7ca4182a
4248
MOVD (R3)(R0), R5 // 7ca0182a
@@ -168,6 +174,8 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
168174
ADD $-32767, R5, R4 // 38858001
169175
ADD $-32768, R6 // 38c68000
170176
ADD $-32768, R6, R5 // 38a68000
177+
// Hex constant 0xFFFFFFFE00000000
178+
ADD $-8589934592, R5 // 3fe0fffe63ff00007bff83e463ff00007cbf2a14 or 0602000038a50000
171179

172180
//TODO: this compiles to add r5,r6,r0. It should be addi r5,r6,0.
173181
// this is OK since r0 == $0, but the latter is preferred.

src/cmd/internal/obj/ppc64/obj9.go

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import (
3636
"cmd/internal/sys"
3737
"internal/abi"
3838
"log"
39+
"math/bits"
3940
)
4041

4142
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) {
8081
}
8182

8283
case AMOVD:
83-
// 32b constants (signed and unsigned) can be generated via 1 or 2 instructions.
84+
// 32b constants (signed and unsigned) can be generated via 1 or 2 instructions. They can be assembled directly.
8485
isS32 := int64(int32(p.From.Offset)) == p.From.Offset
8586
isU32 := uint64(uint32(p.From.Offset)) == uint64(p.From.Offset)
8687

8788
// If prefixed instructions are supported, a 34b signed constant can be generated by one pli instruction.
8889
isS34 := pfxEnabled && (p.From.Offset<<30)>>30 == p.From.Offset
89-
90-
// If the constant cannot be generated with 2 or less instructions, it must be placed in memory and loaded.
9190
if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE && p.From.Reg == 0 && !isS32 && !isU32 && !isS34 {
92-
p.From.Type = obj.TYPE_MEM
93-
p.From.Sym = ctxt.Int64Sym(p.From.Offset)
94-
p.From.Name = obj.NAME_EXTERN
95-
p.From.Offset = 0
91+
92+
// Is this a shifted 16b constant? If so, rewrite it to avoid a creating and loading a constant.
93+
val := p.From.Offset
94+
shift := bits.TrailingZeros64(uint64(val))
95+
mask := 0xFFFF << shift
96+
if val&int64(mask) == val || (val>>(shift+16) == -1 && (val>>shift)<<shift == val) {
97+
// Rewrite this value into MOVD $const>>shift, Rto; SLD $shift, Rto
98+
q := obj.Appendp(p, c.newprog)
99+
q.As = ASLD
100+
q.From.Type = obj.TYPE_CONST
101+
q.From.Offset = int64(shift)
102+
q.To = p.To
103+
p.From.Offset >>= shift
104+
p = q
105+
} else {
106+
// Load the constant from memory.
107+
p.From.Type = obj.TYPE_MEM
108+
p.From.Sym = ctxt.Int64Sym(p.From.Offset)
109+
p.From.Name = obj.NAME_EXTERN
110+
p.From.Offset = 0
111+
}
96112
}
97113
}
98114

test/codegen/constants.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// asmcheck
2+
3+
// Copyright 2023 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
package codegen
8+
9+
func shifted16BitConstants(out [64]uint64) {
10+
// ppc64x: "MOVD\t[$]8193,", "SLD\t[$]27,"
11+
out[0] = 0x0000010008000000
12+
// ppc64x: "MOVD\t[$]-32767", "SLD\t[$]26,"
13+
out[1] = 0xFFFFFE0004000000
14+
// ppc64x: "MOVD\t[$]-1", "SLD\t[$]48,"
15+
out[2] = 0xFFFF000000000000
16+
// ppc64x: "MOVD\t[$]65535", "SLD\t[$]44,"
17+
out[3] = 0x0FFFF00000000000
18+
19+
// ppc64x: "MOVD\t[$]i64.fffff00000000001[(]SB[)]"
20+
out[4] = 0xFFFFF00000000001
21+
// ppc64x: "MOVD\t[$]i64.fffff80000000001[(]SB[)]"
22+
out[5] = 0xFFFFF80000000001
23+
// ppc64x: "MOVD\t[$]i64.0ffff80000000000[(]SB[)]"
24+
out[6] = 0x0FFFF80000000000
25+
}

0 commit comments

Comments
 (0)