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 }