Skip to content

Commit 3a9bc57

Browse files
committed
cmd/internal/obj/arm64, cmd/link: use two instructions rather than three for loads from memory
Reduces size of godoc .text section by about 75k (or 1.4%). Change-Id: I65850aa569aefbddd6cb07c6ae1addcc39cab6a5 Reviewed-on: https://go-review.googlesource.com/13993 Reviewed-by: Russ Cox <[email protected]>
1 parent a7d331b commit 3a9bc57

4 files changed

Lines changed: 132 additions & 50 deletions

File tree

src/cmd/internal/obj/arm64/asm7.go

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -260,16 +260,16 @@ var optab = []Optab{
260260
{AMOVW, C_VCONADDR, C_NONE, C_REG, 68, 8, 0, 0, 0},
261261
{AMOVD, C_VCON, C_NONE, C_REG, 12, 4, 0, LFROM, 0},
262262
{AMOVD, C_VCONADDR, C_NONE, C_REG, 68, 8, 0, 0, 0},
263-
{AMOVB, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
264-
{AMOVBU, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
265-
{AMOVH, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
266-
{AMOVW, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
267-
{AMOVD, C_REG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
268-
{AMOVB, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
269-
{AMOVBU, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
270-
{AMOVH, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
271-
{AMOVW, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
272-
{AMOVD, C_ADDR, C_NONE, C_REG, 65, 12, 0, 0, 0},
263+
{AMOVB, C_REG, C_NONE, C_ADDR, 64, 8, 0, 0, 0},
264+
{AMOVBU, C_REG, C_NONE, C_ADDR, 64, 8, 0, 0, 0},
265+
{AMOVH, C_REG, C_NONE, C_ADDR, 64, 8, 0, 0, 0},
266+
{AMOVW, C_REG, C_NONE, C_ADDR, 64, 8, 0, 0, 0},
267+
{AMOVD, C_REG, C_NONE, C_ADDR, 64, 8, 0, 0, 0},
268+
{AMOVB, C_ADDR, C_NONE, C_REG, 65, 8, 0, 0, 0},
269+
{AMOVBU, C_ADDR, C_NONE, C_REG, 65, 8, 0, 0, 0},
270+
{AMOVH, C_ADDR, C_NONE, C_REG, 65, 8, 0, 0, 0},
271+
{AMOVW, C_ADDR, C_NONE, C_REG, 65, 8, 0, 0, 0},
272+
{AMOVD, C_ADDR, C_NONE, C_REG, 65, 8, 0, 0, 0},
273273
{AMOVD, C_TLS_LE, C_NONE, C_REG, 69, 4, 0, 0, 0},
274274
{AMOVD, C_TLS_IE, C_NONE, C_REG, 70, 8, 0, 0, 0},
275275
{AMUL, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
@@ -450,10 +450,10 @@ var optab = []Optab{
450450
{AFMOVS, C_LOREG, C_NONE, C_FREG, 31, 8, 0, LFROM, 0},
451451
{AFMOVD, C_LAUTO, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0},
452452
{AFMOVD, C_LOREG, C_NONE, C_FREG, 31, 8, 0, LFROM, 0},
453-
{AFMOVS, C_FREG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
454-
{AFMOVS, C_ADDR, C_NONE, C_FREG, 65, 12, 0, 0, 0},
455-
{AFMOVD, C_FREG, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
456-
{AFMOVD, C_ADDR, C_NONE, C_FREG, 65, 12, 0, 0, 0},
453+
{AFMOVS, C_FREG, C_NONE, C_ADDR, 64, 8, 0, 0, 0},
454+
{AFMOVS, C_ADDR, C_NONE, C_FREG, 65, 8, 0, 0, 0},
455+
{AFMOVD, C_FREG, C_NONE, C_ADDR, 64, 8, 0, 0, 0},
456+
{AFMOVD, C_ADDR, C_NONE, C_FREG, 65, 8, 0, 0, 0},
457457
{AFADDS, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0},
458458
{AFADDS, C_FREG, C_FREG, C_FREG, 54, 4, 0, 0, 0},
459459
{AFADDS, C_FCON, C_NONE, C_FREG, 54, 4, 0, 0, 0},
@@ -2701,28 +2701,26 @@ func asmout(ctxt *obj.Link, p *obj.Prog, o *Optab, out []uint32) {
27012701

27022702
o1 = ADR(0, uint32(d), uint32(p.To.Reg))
27032703

2704-
/* reloc ops */
2704+
/* reloc ops */
27052705
case 64: /* movT R,addr -> adrp + add + movT R, (REGTMP) */
27062706
o1 = ADR(1, 0, REGTMP)
2707-
o2 = opirr(ctxt, AADD) | REGTMP&31<<5 | REGTMP&31
2707+
o2 = olsr12u(ctxt, int32(opstr12(ctxt, int(p.As))), 0, REGTMP, int(p.From.Reg))
27082708
rel := obj.Addrel(ctxt.Cursym)
27092709
rel.Off = int32(ctxt.Pc)
27102710
rel.Siz = 8
27112711
rel.Sym = p.To.Sym
27122712
rel.Add = p.To.Offset
2713-
rel.Type = obj.R_ADDRARM64
2714-
o3 = olsr12u(ctxt, int32(opstr12(ctxt, int(p.As))), 0, REGTMP, int(p.From.Reg))
2713+
rel.Type = movereloc(p.As)
27152714

2716-
case 65: /* movT addr,R -> adrp + add + movT (REGTMP), R */
2715+
case 65: /* movT addr,R -> adrp REGTMP, 0; ldr R, [REGTMP, #0] + relocs */
27172716
o1 = ADR(1, 0, REGTMP)
2718-
o2 = opirr(ctxt, AADD) | REGTMP&31<<5 | REGTMP&31
2717+
o2 = olsr12u(ctxt, int32(opldr12(ctxt, int(p.As))), 0, REGTMP, int(p.To.Reg))
27192718
rel := obj.Addrel(ctxt.Cursym)
27202719
rel.Off = int32(ctxt.Pc)
2721-
rel.Siz = 8
27222720
rel.Sym = p.From.Sym
27232721
rel.Add = p.From.Offset
2724-
rel.Type = obj.R_ADDRARM64
2725-
o3 = olsr12u(ctxt, int32(opldr12(ctxt, int(p.As))), 0, REGTMP, int(p.To.Reg))
2722+
rel.Siz = 8
2723+
rel.Type = movereloc(p.As)
27262724

27272725
case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */
27282726
v := int32(p.From.Offset)
@@ -4161,3 +4159,19 @@ func movesize(a int) int {
41614159
return -1
41624160
}
41634161
}
4162+
4163+
func movereloc(a int16) int32 {
4164+
switch movesize(int(a)) {
4165+
case 0:
4166+
return obj.R_ARM64_LOAD8
4167+
case 1:
4168+
return obj.R_ARM64_LOAD16
4169+
case 2:
4170+
return obj.R_ARM64_LOAD32
4171+
case 3:
4172+
return obj.R_ARM64_LOAD64
4173+
case -1:
4174+
panic("xxx")
4175+
}
4176+
return -1
4177+
}

src/cmd/internal/obj/link.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,11 @@ const (
457457
// referenced (thread local) symbol from the GOT.
458458
R_ARM64_TLS_IE
459459

460+
R_ARM64_LOAD8
461+
R_ARM64_LOAD16
462+
R_ARM64_LOAD32
463+
R_ARM64_LOAD64
464+
460465
// PPC64.
461466

462467
// R_POWER_TLS_LE is used to implement the "local exec" model for tls

src/cmd/link/internal/arm64/asm.go

Lines changed: 86 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,30 @@ func elfreloc1(r *ld.Reloc, sectoff int64) int {
8282
ld.Thearch.Vput(uint64(sectoff + 4))
8383
ld.Thearch.Vput(ld.R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC | uint64(elfsym)<<32)
8484

85+
case obj.R_ARM64_LOAD8:
86+
ld.Thearch.Vput(ld.R_AARCH64_ADR_PREL_PG_HI21 | uint64(elfsym)<<32)
87+
ld.Thearch.Vput(uint64(r.Xadd))
88+
ld.Thearch.Vput(uint64(sectoff + 4))
89+
ld.Thearch.Vput(ld.R_AARCH64_LDST8_ABS_LO12_NC | uint64(elfsym)<<32)
90+
91+
case obj.R_ARM64_LOAD16:
92+
ld.Thearch.Vput(ld.R_AARCH64_ADR_PREL_PG_HI21 | uint64(elfsym)<<32)
93+
ld.Thearch.Vput(uint64(r.Xadd))
94+
ld.Thearch.Vput(uint64(sectoff + 4))
95+
ld.Thearch.Vput(ld.R_AARCH64_LDST16_ABS_LO12_NC | uint64(elfsym)<<32)
96+
97+
case obj.R_ARM64_LOAD32:
98+
ld.Thearch.Vput(ld.R_AARCH64_ADR_PREL_PG_HI21 | uint64(elfsym)<<32)
99+
ld.Thearch.Vput(uint64(r.Xadd))
100+
ld.Thearch.Vput(uint64(sectoff + 4))
101+
ld.Thearch.Vput(ld.R_AARCH64_LDST32_ABS_LO12_NC | uint64(elfsym)<<32)
102+
103+
case obj.R_ARM64_LOAD64:
104+
ld.Thearch.Vput(ld.R_AARCH64_ADR_PREL_PG_HI21 | uint64(elfsym)<<32)
105+
ld.Thearch.Vput(uint64(r.Xadd))
106+
ld.Thearch.Vput(uint64(sectoff + 4))
107+
ld.Thearch.Vput(ld.R_AARCH64_LDST64_ABS_LO12_NC | uint64(elfsym)<<32)
108+
85109
case obj.R_CALLARM64:
86110
if r.Siz != 4 {
87111
return -1
@@ -178,13 +202,72 @@ func machoreloc1(r *ld.Reloc, sectoff int64) int {
178202
return 0
179203
}
180204

205+
func archrelocaddr(r *ld.Reloc, s *ld.LSym, val *int64) int {
206+
var o1, o2 uint32
207+
if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
208+
o1 = uint32(*val >> 32)
209+
o2 = uint32(*val)
210+
} else {
211+
o1 = uint32(*val)
212+
o2 = uint32(*val >> 32)
213+
}
214+
215+
// We are inserting an address into two instructions: adrp and
216+
// then either addi or a load.
217+
address := ld.Symaddr(r.Sym) + r.Add
218+
pgaddress := (address &^ 0xfff) - ((s.Value + int64(r.Off)) &^ 0xfff)
219+
if pgaddress < -1<<31 || pgaddress >= 1<<31 {
220+
ld.Ctxt.Diag("relocation for %s is too big (>=2G): %d", s.Name, pgaddress)
221+
}
222+
pgoff := uint32(address & 0xfff)
223+
o1 |= uint32((((pgaddress >> 12) & 3) << 29) | (((pgaddress >> 12 >> 2) & 0x7ffff) << 5))
224+
225+
switch r.Type {
226+
case obj.R_ADDRARM64, obj.R_ARM64_LOAD8:
227+
o2 |= pgoff << 10
228+
229+
case obj.R_ARM64_LOAD16:
230+
if pgoff&0x1 != 0 {
231+
ld.Diag("offset for 16-byte load/store has unaligned value %d", pgoff)
232+
}
233+
o2 |= pgoff << 9
234+
235+
case obj.R_ARM64_LOAD32:
236+
if pgoff&0x3 != 0 {
237+
ld.Diag("offset for 32-byte load/store has unaligned value %d", pgoff)
238+
}
239+
o2 |= pgoff << 8
240+
241+
case obj.R_ARM64_LOAD64:
242+
if pgoff&0x7 != 0 {
243+
ld.Diag("offset for 64-byte load/store has unaligned value %d", pgoff)
244+
}
245+
o2 |= pgoff << 7
246+
247+
default:
248+
return -1
249+
}
250+
251+
if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
252+
*val = int64(o1)<<32 | int64(o2)
253+
} else {
254+
*val = int64(o2)<<32 | int64(o1)
255+
}
256+
return 0
257+
}
258+
181259
func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
182260
if ld.Linkmode == ld.LinkExternal {
183261
switch r.Type {
184262
default:
185263
return -1
186264

187-
case obj.R_ADDRARM64:
265+
case obj.R_ADDRARM64,
266+
obj.R_ARM64_LOAD8,
267+
obj.R_ARM64_LOAD16,
268+
obj.R_ARM64_LOAD32,
269+
obj.R_ARM64_LOAD64:
270+
188271
r.Done = 0
189272

190273
// set up addend for eventual relocation via outer symbol.
@@ -253,32 +336,8 @@ func archreloc(r *ld.Reloc, s *ld.LSym, val *int64) int {
253336
*val = ld.Symaddr(r.Sym) + r.Add - ld.Symaddr(ld.Linklookup(ld.Ctxt, ".got", 0))
254337
return 0
255338

256-
case obj.R_ADDRARM64:
257-
t := ld.Symaddr(r.Sym) + r.Add - ((s.Value + int64(r.Off)) &^ 0xfff)
258-
if t >= 1<<32 || t < -1<<32 {
259-
ld.Diag("program too large, address relocation distance = %d", t)
260-
}
261-
262-
var o0, o1 uint32
263-
264-
if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
265-
o0 = uint32(*val >> 32)
266-
o1 = uint32(*val)
267-
} else {
268-
o0 = uint32(*val)
269-
o1 = uint32(*val >> 32)
270-
}
271-
272-
o0 |= (uint32((t>>12)&3) << 29) | (uint32((t>>12>>2)&0x7ffff) << 5)
273-
o1 |= uint32(t&0xfff) << 10
274-
275-
// when laid out, the instruction order must always be o1, o2.
276-
if ld.Ctxt.Arch.ByteOrder == binary.BigEndian {
277-
*val = int64(o0)<<32 | int64(o1)
278-
} else {
279-
*val = int64(o1)<<32 | int64(o0)
280-
}
281-
return 0
339+
case obj.R_ADDRARM64, obj.R_ARM64_LOAD8, obj.R_ARM64_LOAD16, obj.R_ARM64_LOAD32, obj.R_ARM64_LOAD64:
340+
return archrelocaddr(r, s, val)
282341

283342
case obj.R_ARM64_TLS_LE:
284343
r.Done = 0

src/cmd/link/internal/ld/elf.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,10 @@ const (
372372
R_AARCH64_CALL26 = 283
373373
R_AARCH64_ADR_PREL_PG_HI21 = 275
374374
R_AARCH64_ADD_ABS_LO12_NC = 277
375+
R_AARCH64_LDST8_ABS_LO12_NC = 278
376+
R_AARCH64_LDST16_ABS_LO12_NC = 284
377+
R_AARCH64_LDST32_ABS_LO12_NC = 285
378+
R_AARCH64_LDST64_ABS_LO12_NC = 286
375379
R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 = 541
376380
R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 542
377381
R_AARCH64_TLSLE_MOVW_TPREL_G0 = 547

0 commit comments

Comments
 (0)