github.com/cloudwego/frugal@v0.1.15/internal/atm/ssa/rename.go (about)

     1  /*
     2   * Copyright 2022 ByteDance Inc.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package ssa
    18  
    19  import (
    20      `github.com/oleiade/lane`
    21  )
    22  
    23  type _Renamer struct {
    24      count map[Reg]int
    25      stack map[Reg][]int
    26  }
    27  
    28  func newRenamer() _Renamer {
    29      return _Renamer {
    30          count: make(map[Reg]int),
    31          stack: make(map[Reg][]int),
    32      }
    33  }
    34  
    35  func (self _Renamer) popr(r Reg) {
    36      if n := len(self.stack[r]); n != 0 {
    37          self.stack[r] = self.stack[r][:n - 1]
    38      }
    39  }
    40  
    41  func (self _Renamer) topr(r Reg) int {
    42      if n := len(self.stack[r]); n == 0 {
    43          return 0
    44      } else {
    45          return self.stack[r][n - 1]
    46      }
    47  }
    48  
    49  func (self _Renamer) pushr(r Reg) (i int) {
    50      i = self.count[r]
    51      self.count[r] = i + 1
    52      self.stack[r] = append(self.stack[r], i)
    53      return
    54  }
    55  
    56  func (self _Renamer) renameuses(ins IrNode) {
    57      if u, ok := ins.(IrUsages); ok {
    58          for _, a := range u.Usages() {
    59              *a = a.Derive(self.topr(*a))
    60          }
    61      }
    62  }
    63  
    64  func (self _Renamer) renamedefs(ins IrNode, buf *[]Reg) {
    65      if s, ok := ins.(IrDefinitions); ok {
    66          for _, def := range s.Definitions() {
    67              *buf = append(*buf, *def)
    68              *def = def.Derive(self.pushr(*def))
    69          }
    70      }
    71  }
    72  
    73  func (self _Renamer) renameblock(cfg *CFG, bb *BasicBlock) {
    74      var r Reg
    75      var d []Reg
    76      var n IrNode
    77  
    78      /* rename Phi nodes */
    79      for _, n = range bb.Phi {
    80          self.renamedefs(n, &d)
    81      }
    82  
    83      /* rename body */
    84      for _, n = range bb.Ins {
    85          self.renameuses(n)
    86          self.renamedefs(n, &d)
    87      }
    88  
    89      /* get the successor iterator */
    90      tr := bb.Term
    91      it := tr.Successors()
    92  
    93      /* rename terminators */
    94      self.renameuses(tr)
    95      self.renamedefs(tr, &d)
    96  
    97      /* rename all the Phi node of it's successors */
    98      for it.Next() {
    99          for _, phi := range it.Block().Phi {
   100              r = *phi.V[bb]
   101              phi.V[bb] = regnewref(r.Derive(self.topr(r)))
   102          }
   103      }
   104  
   105      /* rename all it's children in the dominator tree */
   106      for _, p := range cfg.DominatorOf[bb.Id] {
   107          self.renameblock(cfg, p)
   108      }
   109  
   110      /* pop the definations */
   111      for _, s := range d {
   112          self.popr(s)
   113      }
   114  }
   115  
   116  func renameRegisters(cfg *CFG) {
   117      newRenamer().renameblock(cfg, cfg.Root)
   118      normalizeRegisters(cfg)
   119  }
   120  
   121  func assignRegisters(rr []*Reg, rm map[Reg]Reg, cfg *CFG) {
   122      for _, r := range rr {
   123          if r.Kind() != K_zero {
   124              if v, ok := rm[*r]; ok {
   125                  panic("register redefined: " + r.String())
   126              } else {
   127                  v = r.Normalize(cfg.allocreg())
   128                  *r, rm[*r] = v, v
   129              }
   130          }
   131      }
   132  }
   133  
   134  func replaceRegisters(rr []*Reg, rm map[Reg]Reg) {
   135      for _, r := range rr {
   136          if r.Kind() != K_zero {
   137              if v, ok := rm[*r]; ok {
   138                  *r = v
   139              } else {
   140                  panic("use of undefined register: " + r.String())
   141              }
   142          }
   143      }
   144  }
   145  
   146  func normalizeRegisters(cfg *CFG) {
   147      q := lane.NewQueue()
   148      r := make(map[Reg]Reg)
   149  
   150      /* find all the register definations */
   151      for q.Enqueue(cfg.Root); !q.Empty(); {
   152          p := q.Dequeue().(*BasicBlock)
   153          addImmediateDominated(cfg.DominatorOf, p, q)
   154  
   155          /* assign Phi nodes */
   156          for _, n := range p.Phi {
   157              assignRegisters(n.Definitions(), r, cfg)
   158          }
   159  
   160          /* assign instructions */
   161          for _, n := range p.Ins {
   162              if d, ok := n.(IrDefinitions); ok {
   163                  assignRegisters(d.Definitions(), r, cfg)
   164              }
   165          }
   166  
   167          /* assign terminators */
   168          if d, ok := p.Term.(IrDefinitions); ok {
   169              assignRegisters(d.Definitions(), r, cfg)
   170          }
   171      }
   172  
   173      /* normalize each block */
   174      for q.Enqueue(cfg.Root); !q.Empty(); {
   175          p := q.Dequeue().(*BasicBlock)
   176          addImmediateDominated(cfg.DominatorOf, p, q)
   177  
   178          /* replace Phi nodes */
   179          for _, n := range p.Phi {
   180              replaceRegisters(n.Usages(), r)
   181          }
   182  
   183          /* replace instructions */
   184          for _, n := range p.Ins {
   185              if u, ok := n.(IrUsages); ok {
   186                  replaceRegisters(u.Usages(), r)
   187              }
   188          }
   189  
   190          /* replace terminators */
   191          if u, ok := p.Term.(IrUsages); ok {
   192              replaceRegisters(u.Usages(), r)
   193          }
   194      }
   195  }