github.com/cloudwego/frugal@v0.1.15/internal/atm/ssa/pass_zeroreg.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 `runtime` 21 ) 22 23 // ZeroReg replaces read to %z or %nil to a register that was 24 // initialized to zero for architectures that does not have constant 25 // zero registers, such as `x86_64`. 26 type ZeroReg struct{} 27 28 func (ZeroReg) replace(cfg *CFG) { 29 cfg.PostOrder().ForEach(func(bb *BasicBlock) { 30 var ok bool 31 var rr *Reg 32 var use IrUsages 33 34 /* create the instruction buffer */ 35 ins := bb.Ins 36 bb.Ins = make([]IrNode, 0, len(ins)) 37 38 /* zero register replacer */ 39 replacez := func(v IrUsages, ins *[]IrNode, tail IrNode) { 40 var z Reg 41 var r *Reg 42 43 /* insert an zeroing instruction if needed */ 44 for _, r = range v.Usages() { 45 if r.Kind() == K_zero { 46 z = cfg.CreateRegister(false) 47 *ins = append(*ins, IrArchZero(z)) 48 break 49 } 50 } 51 52 /* substitute all the zero register usages */ 53 for _, r = range v.Usages() { 54 if r.Kind() == K_zero { 55 *r = z 56 } 57 } 58 59 /* add the instruction if needed */ 60 if tail != nil { 61 *ins = append(*ins, tail) 62 } 63 } 64 65 /* scan all the Phi nodes */ 66 for _, p := range bb.Pred { 67 var z Reg 68 var v *IrPhi 69 70 /* insert an zeroing instruction to it's predecessor if needed */ 71 for _, v = range bb.Phi { 72 if v.V[p].Kind() == K_zero { 73 z = cfg.CreateRegister(false) 74 p.Ins = append(p.Ins, IrArchZero(z)) 75 break 76 } 77 } 78 79 /* substitute all the zero register usages */ 80 for _, v = range bb.Phi { 81 if rr = v.V[p]; rr.Kind() == K_zero { 82 *rr = z 83 } 84 } 85 } 86 87 /* scan all the instructions */ 88 for _, v := range ins { 89 if use, ok = v.(IrUsages); ok { 90 replacez(use, &bb.Ins, v) 91 } else { 92 bb.Ins = append(bb.Ins, v) 93 } 94 } 95 96 /* scan the terminator */ 97 if use, ok = bb.Term.(IrUsages); ok { 98 replacez(use, &bb.Ins, nil) 99 } 100 }) 101 } 102 103 //goland:noinspection GoBoolExpressions 104 func (self ZeroReg) Apply(cfg *CFG) { 105 if runtime.GOARCH == "amd64" { 106 self.replace(cfg) 107 } 108 }