| // Copyright 2026 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package ssacompile | |
| // This file contains a simple pass to compute *stack* pointer demographics: | |
| // stack_pointers: count of ir.Name-s that are stack allocated. | |
| // stack_pointers_decomposeAddr_candidate: count of ir.Name-s that are stack allocated and qualifies for | |
| // decompose addr. | |
| // stack_pointers_mem2reg_candidate: count of ir.Name-s that are stack allocated, | |
| // qualifies for mem2reg and are only used in Loads or Stores(as the address, not value). | |
| // stack_scalar_pointers_decomposeAddr_candidate: count of scalar ir.Name-s that are stack allocated and | |
| // qualifies for decompose addr. | |
| // stack_scalar_pointers_decomposeAddr_candidate: count of scalar ir.Name-s that are stack allocated and | |
| // qualifies for decomposeAddr. | |
| // stack_struct_pointers_decomposeAddr_candidate: count of struct pointers that are stack allocated and | |
| // qualifies for decomposeAddr. | |
| import ( | |
| "cmd/compile/internal/ir" | |
| "cmd/compile/internal/ssa" | |
| "cmd/compile/internal/ssa/ssaop" | |
| ) | |
| func ptrStats(f *ssa.Func) { | |
| // Record statistics if stats are enabled. | |
| s := f.NewStats("ptrstats") | |
| if s == nil { | |
| return | |
| } | |
| demographics, _, _ := variableDemographics(f) | |
| nameSeen := make(map[*ir.Name]bool) | |
| for _, b := range f.Blocks { | |
| for _, v := range b.Values { | |
| if !v.Type.IsPtr() { | |
| continue | |
| } | |
| // Peel off OffPtr | |
| base := v | |
| for base.Op == ssaop.OpOffPtr { | |
| base = base.Args[0] | |
| } | |
| if base.Op == ssaop.OpLocalAddr { | |
| n, ok := base.Aux.(*ir.Name) | |
| if ok && (n.Class == ir.PAUTO || isABIInternalParam(f, n)) { | |
| if nameSeen[n] { | |
| continue | |
| } | |
| nameSeen[n] = true | |
| s.Record("stack_pointers", 1) | |
| if demographics[base.Aux].lszmco { | |
| s.Record("stack_pointers_decomposeAddr_candidate", 1) | |
| if demographics[base.Aux].ls { | |
| s.Record("stack_pointers_mem2reg_candidate", 1) | |
| } | |
| if n.Type() != nil { | |
| if n.Type().IsScalar() { | |
| s.Record("stack_scalar_pointers_decomposeAddr_candidate", 1) | |
| } else if n.Type().IsStruct() { | |
| s.Record("stack_struct_pointers_decomposeAddr_candidate", 1) | |
| } | |
| } | |
| } | |
| continue | |
| } | |
| } | |
| } | |
| } | |
| } |