| // Copyright 2025 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 ssa |
| |
| // useInfo provides a map from a value to the users of that value. |
| // We do not keep track of this data in the IR directly, as it is |
| // expensive to keep updated. But sometimes we need to compute it |
| // temporarily. |
| // |
| // A useInfo is only valid until the next modification of the IR. |
| // |
| // Note that block control uses are not reported. (TODO: add |
| // if needed.) |
| // Also, index of use is not reported. (TODO: add if needed.) |
| // |
| // We keep track of all uses in a single array, and use a |
| // starts array to tell us where to find the sub-array for |
| // each value. |
| // |
| // For a function with 10 values, we would have: |
| // |
| // starts[0] starts[1] starts[2] starts[9] len(uses) |
| // | | | | | |
| // v v v v v |
| // +------------+------------+-...-+------------+ |
| // | uses of v0 | uses of v1 | ... | uses of v9 | |
| // +------------+------------+-...-+------------+ |
| // |
| // We can find all the uses of v by listing all entries |
| // of uses between starts[v.ID] and starts[v.ID+1]. |
| type useInfo struct { |
| starts []int32 |
| uses []*Value |
| } |
| |
| // build useInfo for a function. Result only valid until |
| // the next modification of f. |
| func uses(f *Func) useInfo { |
| // Write down number of uses of each value. |
| idx := f.Cache.allocInt32Slice(f.NumValues()) |
| for _, b := range f.Blocks { |
| for _, v := range b.Values { |
| idx[v.ID] = v.Uses |
| } |
| } |
| |
| // Compute cumulative sum of uses up to and |
| // including each value ID. |
| var cum int32 |
| for vid, uses := range idx { |
| cum += uses |
| idx[vid] = cum |
| } |
| |
| // Compute uses. |
| uses := f.Cache.allocValueSlice(int(cum)) |
| for _, b := range f.Blocks { |
| for _, v := range b.Values { |
| for _, a := range v.Args { |
| idx[a.ID]-- |
| uses[idx[a.ID]] = v |
| } |
| } |
| } |
| for _, b := range f.Blocks { |
| for _, c := range b.ControlValues() { |
| // We don't track block control uses, but |
| // we have to decrement idx values here |
| // so that the accounting comes out right. |
| // Each value will have, at the start of its |
| // use list, a bunch of nils that represent |
| // the number of Block.Control uses. |
| idx[c.ID]-- |
| } |
| } |
| |
| // The loop above decremented each idx entry |
| // by the number of uses. It now contains |
| // the sum of uses up to, but not including, |
| // each value ID. |
| return useInfo{starts: idx, uses: uses} |
| } |
| |
| // get returns a list of uses of v. |
| // Every use in an argument slot is listed (e.g. for |
| // w=(Add v v), w is listed twice in the uses of v). |
| // Uses by Block.Controls are not reported. |
| func (u useInfo) get(v *Value) []*Value { |
| i := u.starts[v.ID] |
| var j int32 |
| if int(v.ID) < len(u.starts)-1 { |
| j = u.starts[v.ID+1] |
| } else { |
| j = int32(len(u.uses)) |
| } |
| r := u.uses[i:j] |
| // skip nil entries from block control uses |
| for len(r) > 0 && r[0] == nil { |
| r = r[1:] |
| } |
| return r |
| } |
| |
| func (u useInfo) free(f *Func) { |
| f.Cache.freeInt32Slice(u.starts) |
| f.Cache.freeValueSlice(u.uses) |
| } |