1  
     2  
     3  
     4  
     5  package ssa
     6  
     7  
     8  
     9  
    10  
    11  
    12  func tighten(f *Func) {
    13  	canMove := make([]bool, f.NumValues())
    14  	for _, b := range f.Blocks {
    15  		for _, v := range b.Values {
    16  			if v.Op.isLoweredGetClosurePtr() {
    17  				
    18  				continue
    19  			}
    20  			switch v.Op {
    21  			case OpPhi, OpArg, OpArgIntReg, OpArgFloatReg, OpSelect0, OpSelect1, OpSelectN:
    22  				
    23  				
    24  				
    25  				
    26  				continue
    27  			}
    28  			if v.MemoryArg() != nil {
    29  				
    30  				
    31  				continue
    32  			}
    33  			
    34  			narg := 0
    35  			for _, a := range v.Args {
    36  				if !a.rematerializeable() {
    37  					narg++
    38  				}
    39  			}
    40  			if narg >= 2 && !v.Type.IsFlags() {
    41  				
    42  				
    43  				
    44  				
    45  				continue
    46  			}
    47  			canMove[v.ID] = true
    48  		}
    49  	}
    50  
    51  	
    52  	lca := makeLCArange(f)
    53  
    54  	
    55  	target := make([]*Block, f.NumValues())
    56  
    57  	
    58  	
    59  	idom := f.Idom()
    60  	loops := f.loopnest()
    61  	loops.calculateDepths()
    62  
    63  	changed := true
    64  	for changed {
    65  		changed = false
    66  
    67  		
    68  		for i := range target {
    69  			target[i] = nil
    70  		}
    71  
    72  		
    73  		
    74  		for _, b := range f.Blocks {
    75  			for _, v := range b.Values {
    76  				for i, a := range v.Args {
    77  					if !canMove[a.ID] {
    78  						continue
    79  					}
    80  					use := b
    81  					if v.Op == OpPhi {
    82  						use = b.Preds[i].b
    83  					}
    84  					if target[a.ID] == nil {
    85  						target[a.ID] = use
    86  					} else {
    87  						target[a.ID] = lca.find(target[a.ID], use)
    88  					}
    89  				}
    90  			}
    91  			for _, c := range b.ControlValues() {
    92  				if !canMove[c.ID] {
    93  					continue
    94  				}
    95  				if target[c.ID] == nil {
    96  					target[c.ID] = b
    97  				} else {
    98  					target[c.ID] = lca.find(target[c.ID], b)
    99  				}
   100  			}
   101  		}
   102  
   103  		
   104  		
   105  		for _, b := range f.Blocks {
   106  			origloop := loops.b2l[b.ID]
   107  			for _, v := range b.Values {
   108  				t := target[v.ID]
   109  				if t == nil {
   110  					continue
   111  				}
   112  				targetloop := loops.b2l[t.ID]
   113  				for targetloop != nil && (origloop == nil || targetloop.depth > origloop.depth) {
   114  					t = idom[targetloop.header.ID]
   115  					target[v.ID] = t
   116  					targetloop = loops.b2l[t.ID]
   117  				}
   118  			}
   119  		}
   120  
   121  		
   122  		for _, b := range f.Blocks {
   123  			for i := 0; i < len(b.Values); i++ {
   124  				v := b.Values[i]
   125  				t := target[v.ID]
   126  				if t == nil || t == b {
   127  					
   128  					continue
   129  				}
   130  				
   131  				t.Values = append(t.Values, v)
   132  				v.Block = t
   133  				last := len(b.Values) - 1
   134  				b.Values[i] = b.Values[last]
   135  				b.Values[last] = nil
   136  				b.Values = b.Values[:last]
   137  				changed = true
   138  				i--
   139  			}
   140  		}
   141  	}
   142  }
   143  
   144  
   145  
   146  
   147  func phiTighten(f *Func) {
   148  	for _, b := range f.Blocks {
   149  		for _, v := range b.Values {
   150  			if v.Op != OpPhi {
   151  				continue
   152  			}
   153  			for i, a := range v.Args {
   154  				if !a.rematerializeable() {
   155  					continue 
   156  				}
   157  				if a.Block == b.Preds[i].b {
   158  					continue 
   159  				}
   160  				
   161  				v.SetArg(i, a.copyInto(b.Preds[i].b))
   162  			}
   163  		}
   164  	}
   165  }
   166  
View as plain text