X7ROOT File Manager
Current Path:
/opt/golang/1.19.4/src/cmd/compile/internal/ssa
opt
/
golang
/
1.19.4
/
src
/
cmd
/
compile
/
internal
/
ssa
/
📁
..
📄
README.md
(8.14 KB)
📄
TODO
(950 B)
📄
addressingmodes.go
(23.64 KB)
📄
bench_test.go
(531 B)
📄
biasedsparsemap.go
(2.71 KB)
📄
block.go
(11.1 KB)
📄
branchelim.go
(11.98 KB)
📄
branchelim_test.go
(5.21 KB)
📄
cache.go
(2.46 KB)
📄
check.go
(16.59 KB)
📄
checkbce.go
(956 B)
📄
compile.go
(18.19 KB)
📄
config.go
(11.7 KB)
📄
copyelim.go
(1.83 KB)
📄
copyelim_test.go
(1.29 KB)
📄
critical.go
(3.19 KB)
📄
cse.go
(9.43 KB)
📄
cse_test.go
(4.25 KB)
📄
deadcode.go
(9.61 KB)
📄
deadcode_test.go
(3.49 KB)
📄
deadstore.go
(9.08 KB)
📄
deadstore_test.go
(4.09 KB)
📄
debug.go
(56.34 KB)
📄
debug_lines_test.go
(8.29 KB)
📄
debug_test.go
(28.75 KB)
📄
decompose.go
(13.41 KB)
📄
dom.go
(7.98 KB)
📄
dom_test.go
(13.34 KB)
📄
expand_calls.go
(63.5 KB)
📄
export_test.go
(3.23 KB)
📄
flagalloc.go
(6.68 KB)
📄
flags_amd64_test.s
(533 B)
📄
flags_arm64_test.s
(699 B)
📄
flags_test.go
(2.49 KB)
📄
func.go
(27.08 KB)
📄
func_test.go
(13.07 KB)
📄
fuse.go
(6.5 KB)
📄
fuse_branchredirect.go
(3.24 KB)
📄
fuse_comparisons.go
(4.04 KB)
📄
fuse_test.go
(7.21 KB)
📁
gen
📄
html.go
(34.72 KB)
📄
id.go
(576 B)
📄
layout.go
(4.82 KB)
📄
lca.go
(3.77 KB)
📄
lca_test.go
(1.65 KB)
📄
likelyadjust.go
(15.24 KB)
📄
location.go
(3.06 KB)
📄
loopbce.go
(10.54 KB)
📄
loopreschedchecks.go
(15.86 KB)
📄
looprotate.go
(2.61 KB)
📄
lower.go
(1.36 KB)
📄
magic.go
(15.77 KB)
📄
magic_test.go
(9.1 KB)
📄
nilcheck.go
(11.06 KB)
📄
nilcheck_test.go
(12.17 KB)
📄
numberlines.go
(7.83 KB)
📄
op.go
(18.65 KB)
📄
opGen.go
(1.01 MB)
📄
opt.go
(308 B)
📄
passbm_test.go
(3.14 KB)
📄
phielim.go
(1.48 KB)
📄
phiopt.go
(8.08 KB)
📄
poset.go
(37.2 KB)
📄
poset_test.go
(18.14 KB)
📄
print.go
(3.85 KB)
📄
prove.go
(41.82 KB)
📄
regalloc.go
(83.69 KB)
📄
regalloc_test.go
(6.49 KB)
📄
rewrite.go
(53.49 KB)
📄
rewrite386.go
(289.01 KB)
📄
rewrite386splitload.go
(4.05 KB)
📄
rewriteAMD64.go
(888.95 KB)
📄
rewriteAMD64splitload.go
(21.41 KB)
📄
rewriteARM.go
(487.7 KB)
📄
rewriteARM64.go
(751.84 KB)
📄
rewriteCond_test.go
(10.62 KB)
📄
rewriteLOONG64.go
(193.44 KB)
📄
rewriteMIPS.go
(174.44 KB)
📄
rewriteMIPS64.go
(195.55 KB)
📄
rewritePPC64.go
(431.6 KB)
📄
rewriteRISCV64.go
(159.66 KB)
📄
rewriteS390X.go
(433.4 KB)
📄
rewriteWasm.go
(109.86 KB)
📄
rewrite_test.go
(6.91 KB)
📄
rewritedec.go
(10.16 KB)
📄
rewritedec64.go
(63.77 KB)
📄
rewritegeneric.go
(617.96 KB)
📄
schedule.go
(18.23 KB)
📄
schedule_test.go
(2.91 KB)
📄
shift_test.go
(4.05 KB)
📄
shortcircuit.go
(12.63 KB)
📄
shortcircuit_test.go
(1.31 KB)
📄
sizeof_test.go
(855 B)
📄
softfloat.go
(1.99 KB)
📄
sparsemap.go
(1.98 KB)
📄
sparseset.go
(1.54 KB)
📄
sparsetree.go
(8.05 KB)
📄
stackalloc.go
(12.79 KB)
📄
stackframe.go
(290 B)
📄
stmtlines_test.go
(2.96 KB)
📁
testdata
📄
tighten.go
(4.3 KB)
📄
trim.go
(4.24 KB)
📄
tuple.go
(1.97 KB)
📄
value.go
(15.21 KB)
📄
writebarrier.go
(19.29 KB)
📄
writebarrier_test.go
(1.75 KB)
📄
xposmap.go
(3.29 KB)
📄
zcse.go
(2.07 KB)
📄
zeroextension_test.go
(1.66 KB)
Editing: dom.go
// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package ssa // This file contains code to compute the dominator tree // of a control-flow graph. // postorder computes a postorder traversal ordering for the // basic blocks in f. Unreachable blocks will not appear. func postorder(f *Func) []*Block { return postorderWithNumbering(f, nil) } type blockAndIndex struct { b *Block index int // index is the number of successor edges of b that have already been explored. } // postorderWithNumbering provides a DFS postordering. // This seems to make loop-finding more robust. func postorderWithNumbering(f *Func, ponums []int32) []*Block { seen := make([]bool, f.NumBlocks()) // result ordering order := make([]*Block, 0, len(f.Blocks)) // stack of blocks and next child to visit // A constant bound allows this to be stack-allocated. 32 is // enough to cover almost every postorderWithNumbering call. s := make([]blockAndIndex, 0, 32) s = append(s, blockAndIndex{b: f.Entry}) seen[f.Entry.ID] = true for len(s) > 0 { tos := len(s) - 1 x := s[tos] b := x.b if i := x.index; i < len(b.Succs) { s[tos].index++ bb := b.Succs[i].Block() if !seen[bb.ID] { seen[bb.ID] = true s = append(s, blockAndIndex{b: bb}) } continue } s = s[:tos] if ponums != nil { ponums[b.ID] = int32(len(order)) } order = append(order, b) } return order } type linkedBlocks func(*Block) []Edge const nscratchslices = 7 // experimentally, functions with 512 or fewer blocks account // for 75% of memory (size) allocation for dominator computation // in make.bash. const minscratchblocks = 512 func (cache *Cache) scratchBlocksForDom(maxBlockID int) (a, b, c, d, e, f, g []ID) { tot := maxBlockID * nscratchslices scratch := cache.domblockstore if len(scratch) < tot { // req = min(1.5*tot, nscratchslices*minscratchblocks) // 50% padding allows for graph growth in later phases. req := (tot * 3) >> 1 if req < nscratchslices*minscratchblocks { req = nscratchslices * minscratchblocks } scratch = make([]ID, req) cache.domblockstore = scratch } else { // Clear as much of scratch as we will (re)use scratch = scratch[0:tot] for i := range scratch { scratch[i] = 0 } } a = scratch[0*maxBlockID : 1*maxBlockID] b = scratch[1*maxBlockID : 2*maxBlockID] c = scratch[2*maxBlockID : 3*maxBlockID] d = scratch[3*maxBlockID : 4*maxBlockID] e = scratch[4*maxBlockID : 5*maxBlockID] f = scratch[5*maxBlockID : 6*maxBlockID] g = scratch[6*maxBlockID : 7*maxBlockID] return } func dominators(f *Func) []*Block { preds := func(b *Block) []Edge { return b.Preds } succs := func(b *Block) []Edge { return b.Succs } //TODO: benchmark and try to find criteria for swapping between // dominatorsSimple and dominatorsLT return f.dominatorsLTOrig(f.Entry, preds, succs) } // 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 { // Adapted directly from the original TOPLAS article's "simple" algorithm maxBlockID := entry.Func.NumBlocks() semi, vertex, label, parent, ancestor, bucketHead, bucketLink := f.Cache.scratchBlocksForDom(maxBlockID) // This version uses integers for most of the computation, // to make the work arrays smaller and pointer-free. // fromID translates from ID to *Block where that is needed. fromID := make([]*Block, maxBlockID) for _, v := range f.Blocks { fromID[v.ID] = v } idom := make([]*Block, maxBlockID) // Step 1. Carry out a depth first search of the problem graph. Number // the vertices from 1 to n as they are reached during the search. n := f.dfsOrig(entry, succFn, semi, vertex, label, parent) for i := n; i >= 2; i-- { w := vertex[i] // step2 in TOPLAS paper for _, e := range predFn(fromID[w]) { v := e.b if semi[v.ID] == 0 { // skip unreachable predecessor // not in original, but we're using existing pred instead of building one. continue } u := evalOrig(v.ID, ancestor, semi, label) if semi[u] < semi[w] { semi[w] = semi[u] } } // add w to bucket[vertex[semi[w]]] // implement bucket as a linked list implemented // in a pair of arrays. vsw := vertex[semi[w]] bucketLink[w] = bucketHead[vsw] bucketHead[vsw] = w linkOrig(parent[w], w, ancestor) // step3 in TOPLAS paper for v := bucketHead[parent[w]]; v != 0; v = bucketLink[v] { u := evalOrig(v, ancestor, semi, label) if semi[u] < semi[v] { idom[v] = fromID[u] } else { idom[v] = fromID[parent[w]] } } } // step 4 in toplas paper for i := ID(2); i <= n; i++ { w := vertex[i] if idom[w].ID != vertex[semi[w]] { idom[w] = idom[idom[w].ID] } } return idom } // dfs 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 { n := ID(0) s := make([]*Block, 0, 256) s = append(s, entry) for len(s) > 0 { v := s[len(s)-1] s = s[:len(s)-1] // recursing on v if semi[v.ID] != 0 { continue // already visited } n++ semi[v.ID] = n vertex[n] = v.ID label[v.ID] = v.ID // ancestor[v] already zero for _, e := range succFn(v) { w := e.b // if it has a dfnum, we've already visited it if semi[w.ID] == 0 { // yes, w can be pushed multiple times. s = append(s, w) parent[w.ID] = v.ID // keep overwriting this till it is visited. } } } return n } // compressOrig is the "simple" compress function from LT paper func compressOrig(v ID, ancestor, semi, label []ID) { if ancestor[ancestor[v]] != 0 { compressOrig(ancestor[v], ancestor, semi, label) if semi[label[ancestor[v]]] < semi[label[v]] { label[v] = label[ancestor[v]] } ancestor[v] = ancestor[ancestor[v]] } } // evalOrig is the "simple" eval function from LT paper func evalOrig(v ID, ancestor, semi, label []ID) ID { if ancestor[v] == 0 { return v } compressOrig(v, ancestor, semi, label) return label[v] } func linkOrig(v, w ID, ancestor []ID) { ancestor[w] = v } // dominators 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 { // A simple algorithm for now // Cooper, Harvey, Kennedy idom := make([]*Block, f.NumBlocks()) // Compute postorder walk post := f.postorder() // Make map from block id to order index (for intersect call) postnum := make([]int, f.NumBlocks()) for i, b := range post { postnum[b.ID] = i } // Make the entry block a self-loop idom[f.Entry.ID] = f.Entry if postnum[f.Entry.ID] != len(post)-1 { f.Fatalf("entry block %v not last in postorder", f.Entry) } // Compute relaxation of idom entries for { changed := false for i := len(post) - 2; i >= 0; i-- { b := post[i] var d *Block for _, e := range b.Preds { p := e.b if idom[p.ID] == nil { continue } if d == nil { d = p continue } d = intersect(d, p, postnum, idom) } if d != idom[b.ID] { idom[b.ID] = d changed = true } } if !changed { break } } // Set idom of entry block to nil instead of itself. idom[f.Entry.ID] = nil return idom } // 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 { // TODO: This loop is O(n^2). It used to be used in nilcheck, // see BenchmarkNilCheckDeep*. for b != c { if postnum[b.ID] < postnum[c.ID] { b = idom[b.ID] } else { c = idom[c.ID] } } return b }
Upload File
Create Folder