mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.ssa] cmd/compile: optimize NilCheck in SSA for ARM
Like AMD64, don't issue NilCheck instruction if the subsequent block has a load or store at the same address. Pass test/nilptr3_ssa.go. Updates #15365. Change-Id: Ic88780dab8c4893c57d1c95f663760cc185fe51e Reviewed-on: https://go-review.googlesource.com/24451 Reviewed-by: David Chase <drchase@google.com> Run-TryBot: David Chase <drchase@google.com>
This commit is contained in:
parent
8eadb89266
commit
df43cf033f
1 changed files with 61 additions and 0 deletions
|
|
@ -52,6 +52,10 @@ var ssaRegToReg = []int16{
|
||||||
0, // SB isn't a real register. We fill an Addr.Reg field with 0 in this case.
|
0, // SB isn't a real register. We fill an Addr.Reg field with 0 in this case.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Smallest possible faulting page at address zero,
|
||||||
|
// see ../../../../runtime/internal/sys/arch_arm.go
|
||||||
|
const minZeroPage = 4096
|
||||||
|
|
||||||
// loadByType returns the load instruction of the given type.
|
// loadByType returns the load instruction of the given type.
|
||||||
func loadByType(t ssa.Type) obj.As {
|
func loadByType(t ssa.Type) obj.As {
|
||||||
if t.IsFloat() {
|
if t.IsFloat() {
|
||||||
|
|
@ -514,6 +518,63 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||||
p.To.Sym = gc.Linksym(gc.Pkglookup("duffcopy", gc.Runtimepkg))
|
p.To.Sym = gc.Linksym(gc.Pkglookup("duffcopy", gc.Runtimepkg))
|
||||||
p.To.Offset = v.AuxInt
|
p.To.Offset = v.AuxInt
|
||||||
case ssa.OpARMLoweredNilCheck:
|
case ssa.OpARMLoweredNilCheck:
|
||||||
|
// Optimization - if the subsequent block has a load or store
|
||||||
|
// at the same address, we don't need to issue this instruction.
|
||||||
|
mem := v.Args[1]
|
||||||
|
for _, w := range v.Block.Succs[0].Block().Values {
|
||||||
|
if w.Op == ssa.OpPhi {
|
||||||
|
if w.Type.IsMemory() {
|
||||||
|
mem = w
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(w.Args) == 0 || !w.Args[len(w.Args)-1].Type.IsMemory() {
|
||||||
|
// w doesn't use a store - can't be a memory op.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if w.Args[len(w.Args)-1] != mem {
|
||||||
|
v.Fatalf("wrong store after nilcheck v=%s w=%s", v, w)
|
||||||
|
}
|
||||||
|
switch w.Op {
|
||||||
|
case ssa.OpARMMOVBload, ssa.OpARMMOVBUload, ssa.OpARMMOVHload, ssa.OpARMMOVHUload,
|
||||||
|
ssa.OpARMMOVWload, ssa.OpARMMOVFload, ssa.OpARMMOVDload,
|
||||||
|
ssa.OpARMMOVBstore, ssa.OpARMMOVHstore, ssa.OpARMMOVWstore,
|
||||||
|
ssa.OpARMMOVFstore, ssa.OpARMMOVDstore:
|
||||||
|
// arg0 is ptr, auxint is offset
|
||||||
|
if w.Args[0] == v.Args[0] && w.Aux == nil && w.AuxInt >= 0 && w.AuxInt < minZeroPage {
|
||||||
|
if gc.Debug_checknil != 0 && int(v.Line) > 1 {
|
||||||
|
gc.Warnl(v.Line, "removed nil check")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case ssa.OpARMDUFFZERO, ssa.OpARMLoweredZero:
|
||||||
|
// arg0 is ptr
|
||||||
|
if w.Args[0] == v.Args[0] {
|
||||||
|
if gc.Debug_checknil != 0 && int(v.Line) > 1 {
|
||||||
|
gc.Warnl(v.Line, "removed nil check")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
case ssa.OpARMDUFFCOPY, ssa.OpARMLoweredMove:
|
||||||
|
// arg0 is dst ptr, arg1 is src ptr
|
||||||
|
if w.Args[0] == v.Args[0] || w.Args[1] == v.Args[0] {
|
||||||
|
if gc.Debug_checknil != 0 && int(v.Line) > 1 {
|
||||||
|
gc.Warnl(v.Line, "removed nil check")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
if w.Type.IsMemory() {
|
||||||
|
if w.Op == ssa.OpVarDef || w.Op == ssa.OpVarKill || w.Op == ssa.OpVarLive {
|
||||||
|
// these ops are OK
|
||||||
|
mem = w
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// We can't delay the nil check past the next store.
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
// Issue a load which will fault if arg is nil.
|
// Issue a load which will fault if arg is nil.
|
||||||
p := gc.Prog(arm.AMOVB)
|
p := gc.Prog(arm.AMOVB)
|
||||||
p.From.Type = obj.TYPE_MEM
|
p.From.Type = obj.TYPE_MEM
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue