github.com/cloudwego/frugal@v0.1.15/internal/atm/ssa/pass_blockmerge.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 // BlockMerge merges redundant intermediate blocks (blocks with a single 20 // outgoing edge which goes to another block with a single incoming edge). 21 type BlockMerge struct{} 22 23 func (BlockMerge) Apply(cfg *CFG) { 24 for { 25 var rt bool 26 var nx *BasicBlock 27 var it IrSuccessors 28 var tr IrTerminator 29 30 /* check every block */ 31 cfg.PostOrder().ForEach(func(bb *BasicBlock) { 32 tr = bb.Term 33 it = tr.Successors() 34 35 /* it must have successors */ 36 if !it.Next() { 37 return 38 } 39 40 /* it must have exactly 1 successor, and the successor must have exactly 1 predecessor */ 41 if nx = it.Block(); it.Next() || len(nx.Pred) != 1 { 42 return 43 } 44 45 /* merge the two blocks */ 46 rt = true 47 bb.Ins = append(bb.Ins, nx.Ins...) 48 bb.Term = nx.Term 49 50 /* must not have Phi nodes */ 51 if len(nx.Phi) != 0 { 52 panic("invalid Phi node found in intermediate blocks") 53 } 54 55 /* get the successor iterator */ 56 tr = nx.Term 57 it = tr.Successors() 58 59 /* update all predecessors references */ 60 for it.Next() { 61 rb := it.Block() 62 pp := rb.Pred 63 64 /* update predecessor list */ 65 for i, p := range pp { 66 if p == nx { 67 pp[i] = bb 68 } 69 } 70 71 /* update in Phi nodes */ 72 for _, v := range rb.Phi { 73 v.V[bb] = v.V[nx] 74 delete(v.V, nx) 75 } 76 } 77 }) 78 79 /* rebuild the dominator tree, and retry if needed */ 80 if cfg.Rebuild(); !rt { 81 break 82 } 83 } 84 } 85