Skip to content

Commit 653a4bd

Browse files
committed
cmd/compile: optimize loads from readonly globals into constants
Instead of MOVB go.string."foo"(SB), AX do MOVB $102, AX When we know the global we're loading from is readonly, we can do that read at compile time. I've made this arch-dependent mostly because the cases where this happens often are memory->memory moves, and those don't get decomposed until lowering. Did amd64/386/arm/arm64. Other architectures could follow. Update #26498 Change-Id: I41b1dc831b2cd0a52dac9b97f4f4457888a46389 Reviewed-on: https://go-review.googlesource.com/c/141118 Run-TryBot: Keith Randall <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Josh Bleecher Snyder <[email protected]>
1 parent df459d5 commit 653a4bd

File tree

10 files changed

+459
-31
lines changed

10 files changed

+459
-31
lines changed

src/cmd/compile/internal/ssa/gen/386.rules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,3 +1206,7 @@
12061206
(CMPLload {sym} [off] ptr (MOVLconst [c]) mem) && validValAndOff(int64(int32(c)),off) -> (CMPLconstload {sym} [makeValAndOff(int64(int32(c)),off)] ptr mem)
12071207
(CMPWload {sym} [off] ptr (MOVLconst [c]) mem) && validValAndOff(int64(int16(c)),off) -> (CMPWconstload {sym} [makeValAndOff(int64(int16(c)),off)] ptr mem)
12081208
(CMPBload {sym} [off] ptr (MOVLconst [c]) mem) && validValAndOff(int64(int8(c)),off) -> (CMPBconstload {sym} [makeValAndOff(int64(int8(c)),off)] ptr mem)
1209+
1210+
(MOVBload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVLconst [int64(read8(sym, off))])
1211+
(MOVWload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVLconst [int64(read16(sym, off, config.BigEndian))])
1212+
(MOVLload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVLconst [int64(int32(read32(sym, off, config.BigEndian)))])

src/cmd/compile/internal/ssa/gen/AMD64.rules

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,11 +1073,11 @@
10731073
// Fold constants into stores.
10741074
(MOVQstore [off] {sym} ptr (MOVQconst [c]) mem) && validValAndOff(c,off) ->
10751075
(MOVQstoreconst [makeValAndOff(c,off)] {sym} ptr mem)
1076-
(MOVLstore [off] {sym} ptr (MOVLconst [c]) mem) && validOff(off) ->
1076+
(MOVLstore [off] {sym} ptr (MOV(L|Q)const [c]) mem) && validOff(off) ->
10771077
(MOVLstoreconst [makeValAndOff(int64(int32(c)),off)] {sym} ptr mem)
1078-
(MOVWstore [off] {sym} ptr (MOVLconst [c]) mem) && validOff(off) ->
1078+
(MOVWstore [off] {sym} ptr (MOV(L|Q)const [c]) mem) && validOff(off) ->
10791079
(MOVWstoreconst [makeValAndOff(int64(int16(c)),off)] {sym} ptr mem)
1080-
(MOVBstore [off] {sym} ptr (MOVLconst [c]) mem) && validOff(off) ->
1080+
(MOVBstore [off] {sym} ptr (MOV(L|Q)const [c]) mem) && validOff(off) ->
10811081
(MOVBstoreconst [makeValAndOff(int64(int8(c)),off)] {sym} ptr mem)
10821082

10831083
// Fold address offsets into constant stores.
@@ -2487,3 +2487,8 @@
24872487
&& validValAndOff(0,off)
24882488
&& clobber(l) ->
24892489
@l.Block (CMP(Q|L|W|B)constload {sym} [makeValAndOff(0,off)] ptr mem)
2490+
2491+
(MOVBload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVLconst [int64(read8(sym, off))])
2492+
(MOVWload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVLconst [int64(read16(sym, off, config.BigEndian))])
2493+
(MOVLload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVQconst [int64(read32(sym, off, config.BigEndian))])
2494+
(MOVQload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVQconst [int64(read64(sym, off, config.BigEndian))])

src/cmd/compile/internal/ssa/gen/ARM.rules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,3 +1544,7 @@
15441544
(GE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (GE (TEQshiftLLreg x y z) yes no)
15451545
(GE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (GE (TEQshiftRLreg x y z) yes no)
15461546
(GE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (GE (TEQshiftRAreg x y z) yes no)
1547+
1548+
(MOVBUload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVWconst [int64(read8(sym, off))])
1549+
(MOVHUload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVWconst [int64(read16(sym, off, config.BigEndian))])
1550+
(MOVWload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVWconst [int64(int32(read32(sym, off, config.BigEndian)))])

src/cmd/compile/internal/ssa/gen/ARM64.rules

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2957,3 +2957,8 @@
29572957
(FSUBD a (FNMULD x y)) -> (FMADDD a x y)
29582958
(FSUBS (FNMULS x y) a) -> (FNMADDS a x y)
29592959
(FSUBD (FNMULD x y) a) -> (FNMADDD a x y)
2960+
2961+
(MOVBUload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVDconst [int64(read8(sym, off))])
2962+
(MOVHUload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVDconst [int64(read16(sym, off, config.BigEndian))])
2963+
(MOVWUload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVDconst [int64(read32(sym, off, config.BigEndian))])
2964+
(MOVDload [off] {sym} (SB) _) && symIsRO(sym) -> (MOVDconst [int64(read64(sym, off, config.BigEndian))])

src/cmd/compile/internal/ssa/rewrite.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ package ssa
77
import (
88
"cmd/compile/internal/types"
99
"cmd/internal/obj"
10+
"cmd/internal/objabi"
1011
"cmd/internal/src"
12+
"encoding/binary"
1113
"fmt"
1214
"io"
1315
"math"
@@ -1090,3 +1092,45 @@ func needRaceCleanup(sym interface{}, v *Value) bool {
10901092
}
10911093
return true
10921094
}
1095+
1096+
// symIsRO reports whether sym is a read-only global.
1097+
func symIsRO(sym interface{}) bool {
1098+
lsym := sym.(*obj.LSym)
1099+
return lsym.Type == objabi.SRODATA && len(lsym.R) == 0
1100+
}
1101+
1102+
// read8 reads one byte from the read-only global sym at offset off.
1103+
func read8(sym interface{}, off int64) uint8 {
1104+
lsym := sym.(*obj.LSym)
1105+
return lsym.P[off]
1106+
}
1107+
1108+
// read16 reads two bytes from the read-only global sym at offset off.
1109+
func read16(sym interface{}, off int64, bigEndian bool) uint16 {
1110+
lsym := sym.(*obj.LSym)
1111+
if bigEndian {
1112+
return binary.BigEndian.Uint16(lsym.P[off:])
1113+
} else {
1114+
return binary.LittleEndian.Uint16(lsym.P[off:])
1115+
}
1116+
}
1117+
1118+
// read32 reads four bytes from the read-only global sym at offset off.
1119+
func read32(sym interface{}, off int64, bigEndian bool) uint32 {
1120+
lsym := sym.(*obj.LSym)
1121+
if bigEndian {
1122+
return binary.BigEndian.Uint32(lsym.P[off:])
1123+
} else {
1124+
return binary.LittleEndian.Uint32(lsym.P[off:])
1125+
}
1126+
}
1127+
1128+
// read64 reads eight bytes from the read-only global sym at offset off.
1129+
func read64(sym interface{}, off int64, bigEndian bool) uint64 {
1130+
lsym := sym.(*obj.LSym)
1131+
if bigEndian {
1132+
return binary.BigEndian.Uint64(lsym.P[off:])
1133+
} else {
1134+
return binary.LittleEndian.Uint64(lsym.P[off:])
1135+
}
1136+
}

src/cmd/compile/internal/ssa/rewrite386.go

Lines changed: 54 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)