Source file src/cmd/compile/internal/ssacompile/ptrstats.go

     1  // Copyright 2026 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ssacompile
     6  
     7  // This file contains a simple pass to compute *stack* pointer demographics:
     8  //	stack_pointers: count of ir.Name-s that are stack allocated.
     9  //	stack_pointers_decomposeAddr_candidate: count of ir.Name-s that are stack allocated and qualifies for
    10  //		decompose addr.
    11  //	stack_pointers_mem2reg_candidate: count of ir.Name-s that are stack allocated,
    12  //		qualifies for mem2reg and are only used in Loads or Stores(as the address, not value).
    13  //	stack_scalar_pointers_decomposeAddr_candidate: count of scalar ir.Name-s that are stack allocated and
    14  //		qualifies for decompose addr.
    15  //	stack_scalar_pointers_decomposeAddr_candidate: count of scalar ir.Name-s that are stack allocated and
    16  //		qualifies for decomposeAddr.
    17  //	stack_struct_pointers_decomposeAddr_candidate: count of struct pointers that are stack allocated and
    18  //		qualifies for decomposeAddr.
    19  
    20  import (
    21  	"cmd/compile/internal/ir"
    22  	"cmd/compile/internal/ssa"
    23  	"cmd/compile/internal/ssa/ssaop"
    24  )
    25  
    26  func ptrStats(f *ssa.Func) {
    27  	// Record statistics if stats are enabled.
    28  	s := f.NewStats("ptrstats")
    29  	if s == nil {
    30  		return
    31  	}
    32  
    33  	demographics, _, _ := variableDemographics(f)
    34  
    35  	nameSeen := make(map[*ir.Name]bool)
    36  	for _, b := range f.Blocks {
    37  		for _, v := range b.Values {
    38  			if !v.Type.IsPtr() {
    39  				continue
    40  			}
    41  			// Peel off OffPtr
    42  			base := v
    43  			for base.Op == ssaop.OpOffPtr {
    44  				base = base.Args[0]
    45  			}
    46  			if base.Op == ssaop.OpLocalAddr {
    47  				n, ok := base.Aux.(*ir.Name)
    48  				if ok && (n.Class == ir.PAUTO || isABIInternalParam(f, n)) {
    49  					if nameSeen[n] {
    50  						continue
    51  					}
    52  					nameSeen[n] = true
    53  					s.Record("stack_pointers", 1)
    54  					if demographics[base.Aux].lszmco {
    55  						s.Record("stack_pointers_decomposeAddr_candidate", 1)
    56  						if demographics[base.Aux].ls {
    57  							s.Record("stack_pointers_mem2reg_candidate", 1)
    58  						}
    59  						if n.Type() != nil {
    60  							if n.Type().IsScalar() {
    61  								s.Record("stack_scalar_pointers_decomposeAddr_candidate", 1)
    62  							} else if n.Type().IsStruct() {
    63  								s.Record("stack_struct_pointers_decomposeAddr_candidate", 1)
    64  							}
    65  						}
    66  					}
    67  					continue
    68  				}
    69  			}
    70  		}
    71  	}
    72  }
    73  

View as plain text