// postorder computes a postorder traversal ordering for the // basic blocks in f. Unreachable blocks will not appear. func postorder(f *Func) []*Block { … } type blockAndIndex … // postorderWithNumbering provides a DFS postordering. // This seems to make loop-finding more robust. func postorderWithNumbering(f *Func, ponums []int32) []*Block { … } type linkedBlocks … func dominators(f *Func) []*Block { … } // dominatorsLTOrig runs Lengauer-Tarjan to compute a dominator tree starting at // entry and using predFn/succFn to find predecessors/successors to allow // computing both dominator and post-dominator trees. func (f *Func) dominatorsLTOrig(entry *Block, predFn linkedBlocks, succFn linkedBlocks) []*Block { … } // dfsOrig performs a depth first search over the blocks starting at entry block // (in arbitrary order). This is a de-recursed version of dfs from the // original Tarjan-Lengauer TOPLAS article. It's important to return the // same values for parent as the original algorithm. func (f *Func) dfsOrig(entry *Block, succFn linkedBlocks, semi, vertex, label, parent []ID) ID { … } // compressOrig is the "simple" compress function from LT paper. func compressOrig(v ID, ancestor, semi, label []ID) { … } // evalOrig is the "simple" eval function from LT paper. func evalOrig(v ID, ancestor, semi, label []ID) ID { … } func linkOrig(v, w ID, ancestor []ID) { … } // dominatorsSimple computes the dominator tree for f. It returns a slice // which maps block ID to the immediate dominator of that block. // Unreachable blocks map to nil. The entry block maps to nil. func dominatorsSimple(f *Func) []*Block { … } // intersect finds the closest dominator of both b and c. // It requires a postorder numbering of all the blocks. func intersect(b, c *Block, postnum []int, idom []*Block) *Block { … }