aa
Node.java
Go to the documentation of this file.
1 package com.cliffc.aa.node;
2 
3 import com.cliffc.aa.*;
4 import com.cliffc.aa.tvar.TV2;
5 import com.cliffc.aa.type.*;
6 import com.cliffc.aa.util.*;
7 import org.jetbrains.annotations.NotNull;
8 
9 import java.util.HashSet;
10 import java.util.concurrent.ConcurrentHashMap;
11 import java.util.function.Predicate;
12 
13 import static com.cliffc.aa.AA.unimpl;
14 
15 // Sea-of-Nodes
16 public abstract class Node implements Cloneable {
17  static final byte OP_CALL = 1;
18  static final byte OP_CALLEPI= 2;
19  static final byte OP_CAST = 3;
20  static final byte OP_CON = 4;
21  static final byte OP_CONTYPE= 5;
22  static final byte OP_CPROJ = 6;
23  static final byte OP_DEFMEM = 7;
24  static final byte OP_ERR = 8;
25  static final byte OP_FRESH = 9;
26  static final byte OP_FP2DISP=10;
27  static final byte OP_FUN =11;
28  static final byte OP_FUNPTR =12;
29  static final byte OP_IF =13;
30  static final byte OP_JOIN =14;
31  static final byte OP_LOAD =15;
32  static final byte OP_LOOP =16;
33  static final byte OP_NAME =17; // Cast a prior NewObj to have a runtime Name
34  static final byte OP_NEWOBJ =18; // Allocate a new struct
35  static final byte OP_NEWARY =19; // Allocate a new array
36  static final byte OP_NEWSTR =20; // Allocate a new string
37  static final byte OP_PARM =21;
38  static final byte OP_PHI =22;
39  static final byte OP_PRIM =23;
40  static final byte OP_PROJ =24;
41  static final byte OP_REGION =25;
42  static final byte OP_RET =26;
43  static final byte OP_SCOPE =27;
44  static final byte OP_SPLIT =28;
45  static final byte OP_START =29;
46  static final byte OP_STMEM =30;
47  static final byte OP_STORE =31;
48  static final byte OP_THRET =32;
49  static final byte OP_THUNK =33;
50  static final byte OP_TYPE =34;
51  static final byte OP_UNR =35;
52  static final byte OP_MAX =36;
53 
54  private static final String[] STRS = new String[] { null, "Call", "CallEpi", "Cast", "Con", "ConType", "CProj", "DefMem", "Err", "Fresh", "FP2Disp", "Fun", "FunPtr", "If", "Join", "Load", "Loop", "Name", "NewObj", "NewAry", "NewStr", "Parm", "Phi", "Prim", "Proj", "Region", "Return", "Scope","Split", "Start", "StartMem", "Store", "Thret", "Thunk", "Type", "Unresolved" };
55  static { assert STRS.length==OP_MAX; }
56 
57  // Unique dense node-numbering
58  public static int _INIT0_CNT;
59  private static int CNT=1; // Do not hand out UID 0
60  private static final VBitSet LIVE = new VBitSet(); // Conservative approximation of live; due to loops some things may be marked live, but are dead
61  int newuid() {
62  assert CNT < 100000 : "infinite node create loop";
63  if( CNT==AA.UID )
64  System.out.print("");
65  LIVE.set(CNT);
66  return CNT++;
67  }
68 
69  // Initial state after loading e.g. primitives.
70  public static void init0() {
71  assert LIVE.get(CNT-1) && !LIVE.get(CNT);
73  }
74  // Reset is called after a top-level exec exits (e.g. junits) with no parse
75  // state left alive. NOT called after a line in the REPL or a user-call to
76  // "eval" as user state carries on.
77  public static void reset_to_init0() {
78  CNT = 0;
79  LIVE.clear();
80  VALS.clear();
81  }
82 
83 
84  public int _uid; // Unique ID, will have gaps, used to give a dense numbering to nodes
85  final byte _op; // Opcode (besides the object class), used to avoid v-calls in some places
86  public byte _keep; // Keep-alive in parser, even as last use goes away
87  public boolean _elock;// Edge-lock: cannot modify edges because messes up hashCode & GVN
88  public Type _val; // Value; starts at ALL and lifts towards ANY.
89  public TypeMem _live; // Liveness; assumed live in gvn.iter(), assumed dead in gvn.gcp().
90  // Hindley-Milner inspired typing, or CNC Thesis based congruence-class
91  // typing. This is a Type Variable which can unify with other TV2s forcing
92  // Type-equivalence (JOIN of unified Types), and includes gross structure
93  // (functions, structs, pointers, or simple Types).
94  @NotNull TV2 _tvar;
95  // H-M Type-Variables
96  public TV2 tvar() {
97  TV2 tv = _tvar.find(); // Do U-F step
98  return tv == _tvar ? tv : (_tvar = tv); // Update U-F style in-place.
99  }
100  public TV2 tvar(int x) { return in(x).tvar(); } // nth TV2
101  public TV2 new_tvar(String alloc_site) { return TV2.make_leaf(this,alloc_site); }
102 
103  // Hash is function+inputs, or opcode+input_uids, and is invariant over edge
104  // order (so we can swap edges without rehashing)
105  @Override public int hashCode() {
106  int sum = _op;
107  for( int i=0; i<_defs._len; i++ ) if( _defs._es[i] != null ) sum ^= _defs._es[i]._uid;
108  return sum;
109  }
110  // Equals is function+inputs, or opcode+input_uids. Uses pointer-equality
111  // checks for input equality checks.
112  @Override public boolean equals(Object o) {
113  if( this==o ) return true;
114  if( !(o instanceof Node) ) return false;
115  Node n = (Node)o;
116  if( _op != n._op ) return false;
117  if( n._defs==null || _defs._len != n._defs._len ) return false;
118  // Note pointer-equality
119  for( int i=0; i<_defs._len; i++ ) if( _defs._es[i] != n._defs._es[i] ) return false;
120  return true;
121  }
122 
123  // Defs. Generally fixed length, ordered, nulls allowed, no unused trailing space. Zero is Control.
124  public Ary<Node> _defs;
125  public int len() { return _defs._len; }
126  public Node in( int i) { return _defs.at(i); }
127  // Edge lock check, or anything that changes the hash
128  public void unelock() {
129  assert check_vals(); // elock & VALs match
130  if( _elock ) { // Edge-locked
131  _elock=false; // Unlock
132  Node x = VALS.remove(this);
133  assert x==this; // Got the right node out
134  Env.GVN.add_reduce(Env.GVN.add_flow(this));
135  }
136  }
137  Node _elock() { // No assert version, used for new nodes
138  assert check_vals(); // elock & VALs match
139  if( !_elock && VALS.get(this)==null ) { _elock = true; VALS.put(this,this); }
140  return this;
141  }
142 
143  private boolean check_vals( ) {
144  Node x = VALS.get(this), old=null;
145  if( x == this ) old=this; // Found in table quickly
146  // Hunt the hard way
147  else for( Node o : VALS.keySet() ) if( o._uid == _uid ) { old=o; break; }
148  return (old!=null) == _elock;
149  }
150 
151  // Add def/use edge
152  public Node add_def(Node n) { unelock(); _defs.add(n); if( n!=null ) n._uses.add(this); return this; }
153  // Replace def/use edge
154  public Node set_def( int idx, Node n ) {
155  unelock();
156  Node old = _defs.at(idx); // Get old value
157  // Add edge to new guy before deleting old, in case old goes dead and
158  // recursively makes new guy go dead also
159  if( (_defs._es[idx] = n) != null ) n._uses.add(this);
160  return unuse(old);
161  }
162 
163  public void replace(Node old, Node nnn) { unelock(); _defs.replace(old,nnn); }
164 
165  public Node insert (int idx, Node n) { unelock(); _defs.insert(idx,n); if( n!=null ) n._uses.add(this); return this; }
166  // Return Node at idx, withOUT auto-deleting it, even if this is the last
167  // use. Used by the parser to retrieve final Nodes from tmp holders. Does
168  // NOT preserve order.
169  public void del( int idx ) {
170  unelock();
171  Node n = _defs.del(idx);
172  if( n != null ) n._uses.del(this);
173  }
174  public Node pop( ) { unelock(); Node n = _defs.pop(); unuse(n); return n; }
175  // Remove Node at idx, auto-delete and preserve order.
176  public Node remove(int idx) { unelock(); return unuse(_defs.remove(idx)); }
177 
178  private Node unuse( Node old ) {
179  if( old == null ) return this;
180  old._uses.del(this);
181  // Either last use of old & goes dead, or at least 1 fewer uses & changes liveness
182  Env.GVN.add_unuse(old);
183  if( old._uses._len!=0 && old._keep ==0 ) old.add_flow_def_extra(this);
184  return this;
185  }
186 
187  // Replace, but do not delete this. Really used to insert a node in front of
188  // this. Does graph-structure changes, making pointers-to-this point to nnn.
189  // Changes neither 'this' nor 'nnn'. Does not enforce any monotonicity nor
190  // unification.
191  public void insert( Node nnn ) {
192  if( _uses._len>0 ) unelock(); // Hacking edges
193  while( _uses._len > 0 ) {
194  Node u = _uses.del(0); // Old use
195  u.replace(this,nnn); // was this now nnn
196  nnn._uses.add(u);
197  }
198  }
199 
200  // Complete replacement; point uses to 'nnn' and removes 'this'.
201  public Node subsume( Node nnn ) {
202  assert !nnn.is_dead();
203  insert(nnn); // Change graph shape
204  nnn.keep(); // Keep-alive
205  kill(); // Delete the old, and anything it uses
206  return nnn.unkeep(); // Remove keep-alive
207  }
208 
209  // Kill a node; all inputs are null'd out; this may put more dead Nodes on
210  // the dead worklist. Return this for progress, null for no-progress.
211  public Node kill( ) {
212  if( is_dead() ) return null;
213  assert _uses._len==0 && _keep==0;
214  // Similar to unelock(), except do not put on any worklist
215  if( _elock ) { _elock = false; Node x = VALS.remove(this); assert x == this; }
216  while( _defs._len > 0 ) unuse(_defs.pop());
217  set_dead(); // officially dead now
218  LIVE.clear(_uid); // Off the LIVE set. CNT cannot roll back unless the GVN worklists are also clear
219  return this;
220  }
221  // Called when GVN worklists are empty
222  public static void roll_back_CNT() { while( !LIVE.get(CNT-1) ) CNT--; }
223 
224  // "keep" a Node during all optimizations because it is somehow unfinished.
225  // Typically used when needing to build several Nodes before building the
226  // typically using Node; during construction the earlier Nodes have no users
227  // (yet) and are not dead. Acts "as if" there is an unknown user.
228  public <N extends Node> N keep() { return keep(1); }
229  @SuppressWarnings("unchecked")
230  public <N extends Node> N keep(int d) { _keep+=d; return (N)this; }
231  // Remove the keep flag, but do not delete.
232  public <N extends Node> N unkeep() { return unkeep(1); }
233  @SuppressWarnings("unchecked")
234  public <N extends Node> N unkeep(int d) {
235  assert _keep >= d; _keep-=d;
236  return (N)this;
237  }
238  // Remove the keep flag, and immediately allow optimizations.
239  public <N extends Node> N unhook() {
240  if( _keep==1 ) Env.GVN.add_work_all(this);
241  return unkeep();
242  }
243 
244  // Uses. Generally variable length; unordered, no nulls, compressed, unused trailing space
245  public Ary<Node> _uses;
246 
247  Node( byte op ) { this(op,new Node[0]); }
248  Node( byte op, Node... defs ) {
249  _op = op;
250  _uid = newuid();
251  _defs = new Ary<>(defs);
252  _uses = new Ary<>(new Node[1],0);
253  for( Node def : defs ) if( def != null ) def._uses.add(this);
254  _val = Type.ALL;
255  _live = all_live();
256  _tvar = new_tvar("constructor");
257  }
258 
259  // Is a primitive
260  public boolean is_prim() { return _INIT0_CNT==0 || _uid<_INIT0_CNT; }
261 
262  // Make a copy of the base node, with no defs nor uses and a new UID.
263  // Some variations will use the CallEpi for e.g. better error messages.
264  @NotNull public Node copy( boolean copy_edges) {
265  try {
266  Node n = (Node)clone();
267  n._uid = newuid(); // A new UID
268  n._defs = new Ary<>(new Node[1],0); // New empty defs
269  n._uses = new Ary<>(new Node[1],0); // New empty uses
270  n._tvar = n.new_tvar("copy_constructor");
271  n._keep = 0; // Not keeping, even if cloning a mid-keeper operation
272  n._elock=false; // Not in GVN
273  if( copy_edges )
274  for( Node def : _defs )
275  n.add_def(def);
276  Env.GVN.add_work_all(n);
277  return n;
278  } catch( CloneNotSupportedException cns ) { throw new RuntimeException(cns); }
279  }
280 
281  // Short string name
282  public String xstr() { return STRS[_op]; } // Self short name
283  String str() { return xstr(); } // Inline longer name
284  @Override public String toString() { return dump(0,new SB(),false).toString(); }
285  // Dump
286  public String dump( int max ) { return dump(max,is_prim(),false); }
287  // Dump including primitives
288  public String dump( int max, boolean prims, boolean plive ) { return dump(0, new SB(),max,new VBitSet(),prims,plive).toString(); }
289  // Dump one node, no recursion
290  private SB dump( int d, SB sb, boolean plive ) {
291  String xs = String.format("%s%4d: %-7.7s ",plive ? _live : "",_uid,xstr());
292  sb.i(d).p(xs);
293  if( is_dead() ) return sb.p("DEAD");
294  for( Node n : _defs ) sb.p(n == null ? "____ " : String.format("%4d ",n._uid));
295  sb.p(" [[");
296  for( Node n : _uses ) sb.p(String.format("%4d ",n._uid));
297  sb.p("]] ");
298  sb.p(str()).s();
299  if( _val==null ) sb.p("----");
300  else _val.str(sb,new VBitSet(),null,true);
301 
302  return sb;
303  }
304  // Dump one node IF not already dumped, no recursion
305  private void dump(int d, SB sb, VBitSet bs, boolean plive) {
306  if( bs.tset(_uid) ) return;
307  dump(d,sb,plive).nl();
308  }
309  // Recursively print, up to depth
310  private SB dump( int d, SB sb, int max, VBitSet bs, boolean prims, boolean plive ) {
311  if( bs.tset(_uid) ) return sb;
312  if( d < max ) { // Limit at depth
313  // Print parser scopes first (deepest)
314  for( Node n : _defs ) if( n instanceof ScopeNode ) n.dump(d+1,sb,max,bs,prims,plive);
315  // Print constants early
316  for( Node n : _defs ) if( n instanceof ConNode ) n.dump(d+1,sb,max,bs,prims,plive);
317  // Do not recursively print root Scope, nor Unresolved of primitives.
318  // These are too common, and uninteresting.
319  for( Node n : _defs ) if( n != null && (!prims && n.is_prim() && n._defs._len > 3) ) bs.set(n._uid);
320  // Recursively print most of the rest, just not the multi-node combos and
321  // Unresolve & FunPtrs.
322  for( Node n : _defs )
323  if( n != null && !n.is_multi_head() && !n.is_multi_tail() &&
324  !(n instanceof UnresolvedNode) && !(n instanceof FunPtrNode) )
325  n.dump(d+1,sb,max,bs,prims,plive);
326  // Print Unresolved and FunPtrs, which typically catch whole functions.
327  for( Node n : _defs )
328  if( (n instanceof UnresolvedNode) || (n instanceof FunPtrNode) )
329  n.dump(d+1,sb,max,bs,prims,plive);
330  // Print anything not yet printed, including multi-node combos
331  for( Node n : _defs ) if( n != null && !n.is_multi_head() ) n.dump(d+1,sb,max,bs,prims,plive);
332  for( Node n : _defs ) if( n != null ) n.dump(d+1,sb,max,bs,prims,plive);
333  }
334  // Print multi-node combos all-at-once, including all tails even if they
335  // exceed the depth limit by 1.
336  Node x = is_multi_tail() ? in(0) : this;
337  if( x != null && x.is_multi_head() ) {
338  int dx = d+(x==this?0:1);
339  // Print all tails paths, all at once - nothing recursively below the tail
340  for( Node n : x._uses )
341  if( n.is_multi_tail() )
342  for( Node m : n._defs )
343  if( dx<max) m.dump(dx+1,sb,max,bs,prims,plive);
344  if( x==this ) bs.clear(_uid); // Reset for self, so prints right now
345  x.dump(dx,sb,bs,plive); // Conditionally print head of combo
346  // Print all combo tails, if not already printed
347  if( x!=this ) bs.clear(_uid); // Reset for self, so prints in the mix below
348  for( Node n : x._uses ) if( n.is_multi_tail() ) n.dump(dx-1,sb,bs,plive);
349  return sb;
350  } else { // Neither combo head nor tail, just print
351  return dump(d,sb,plive).nl();
352  }
353  }
354  public boolean is_multi_head() { return _op==OP_CALL || _op==OP_CALLEPI || _op==OP_FUN || _op==OP_IF || _op==OP_LOOP || _op==OP_NEWOBJ || _op==OP_NEWSTR || _op==OP_REGION || _op==OP_SPLIT || _op==OP_START; }
355  private boolean is_multi_tail() { return _op==OP_PARM || _op==OP_PHI || _op==OP_PROJ || _op==OP_CPROJ; }
356  boolean is_CFG() { return _op==OP_CALL || _op==OP_CALLEPI || _op==OP_FUN || _op==OP_RET || _op==OP_IF || _op==OP_LOOP || _op==OP_REGION || _op==OP_START || _op==OP_CPROJ || _op==OP_SCOPE; }
357 
358  public String dumprpo( boolean prims, boolean plive ) {
359  Ary<Node> nodes = new Ary<>(new Node[1],0);
360  postorder(nodes,new VBitSet());
361  // Dump in reverse post order
362  SB sb = new SB();
363  Node prior = null;
364  for( int i=nodes._len-1; i>=0; i-- ) {
365  Node n = nodes.at(i);
366  if( !(n._uid <= Env.ALL_CTRL._uid || !n.is_prim() || prims) )
367  continue; // Visited, but do not print
368  // Add a nl after the last of a multi-tail sequence.
369  if( (prior != null && prior.is_multi_tail() && !n.is_multi_tail()) ||
370  // Add a nl before the start of a multi-head sequence.
371  n.is_multi_head() )
372  sb.nl();
373  if( n._op==OP_FUN ) _header((FunNode)n,sb);
374  n.dump(0,sb,plive).nl();
375  if( n._op==OP_RET && n.in(4) instanceof FunNode ) _header((FunNode)n.in(4),sb);
376  prior = n;
377  }
378  return sb.toString();
379  }
380  private static void _header(FunNode fun, SB sb) {
381  sb.p("============ ").p(fun==null?"null":fun.name()).p(" ============").nl();
382  }
383  private void postorder( Ary<Node> nodes, VBitSet bs ) {
384  if( bs.tset(_uid) ) return;
385  // If CFG, walk the CFG first. Do not walk thru Returns (into Calls) as
386  // this breaks up the whole- functions-at-once.
387  if( is_CFG() && _op!=OP_RET ) {
388  // Walk any CProj first.
389  for( Node use : _uses )
390  if( use._op == OP_CPROJ )
391  use.postorder(nodes,bs);
392  // Walk the CFG, walking CallEpis last
393  for( Node use : _uses )
394  if( !(use instanceof CallEpiNode) && use.is_CFG() )
395  use.postorder(nodes,bs);
396  for( Node use : _uses )
397  if( (use instanceof CallEpiNode) && use.is_CFG() )
398  use.postorder(nodes,bs);
399  }
400 
401  // Walk the rest (especially data). Since visit bits are set on the CFGs
402  // its OK to walk them also. Calls are special, since their Proj's feed
403  // into a Fun's Parms. We want the Fun to walk its own Parms, in order so
404  // ignore these edges. Since the Parms are all reachable from the Fun they
405  // get walked eventually.
406  if( _op != OP_CALL && _op!=OP_RET ) {
407  if( _op!=OP_SPLIT || _uses._len!=2 )
408  for( Node use : _uses )
409  use.postorder(nodes,bs);
410  else { // For MemSplit, walk the "busy" side first
411  Node p0 = _uses.at(0), p1 = _uses.at(1);
412  if( ((ProjNode)p0)._idx==1 ) { p0=p1; p1=_uses.at(0); } // Swap
413  p1.postorder(nodes,bs);
414  p0.postorder(nodes,bs);
415  }
416  }
417 
418  // Slight PO tweak: heads and tails together.
419  if( is_multi_head() )
420  for( Node use : _uses )
421  if( use.is_multi_tail() )
422  nodes.push(use);
423  if( !is_multi_tail() ) nodes.push(this);
424  }
425 
426  // Utility during debugging to find a reachable Node by _uid
427  public Node find( int uid ) { return find(uid,new VBitSet()); }
428  private Node find( int uid, VBitSet bs ) {
429  if( _uid==uid ) return this;
430  if( bs.tset(_uid) || is_dead() ) return null;
431  Node m;
432  for( Node n : _defs ) if( n!=null && (m=n.find(uid,bs)) !=null ) return m;
433  for( Node n : _uses ) if( (m=n.find(uid,bs)) !=null ) return m;
434  return null;
435  }
436 
437  // Graph rewriting. Strictly reducing Nodes or Edges. Cannot make a new
438  // Node, save that for the expanding ideal calls.
439  // Returns null if no-progress or a better version of 'this'. The
440  // transformed graph must remain monotonic in both value() and live().
441  public Node ideal_reduce() { return null; }
442 
443  // Graph rewriting. Keeps the same count of Nodes & Edges but might change
444  // Edges or replace Nodes. Returns null for no-progress.
445  public Node ideal_mono() { return null; }
446 
447  // Graph rewriting. General growing xforms are here, except for inlining.
448  // Things like inserting MemSplit/MemJoin (which strictly increase graph
449  // parallelism). Returns null for no-progress.
450  public Node ideal_grow() { return null; }
451 
452  // Compute the current best Type for this Node, based on the types of its
453  // inputs. May return Type.ALL, especially if its inputs are in error. It
454  // must be monotonic. This is a forwards-flow transfer-function computation.
455  abstract public Type value(GVNGCM.Mode opt_mode);
456 
457  // Shortcut to update self-value. Typically used in contexts where it is NOT
458  // locally monotonic - hence we cannot run any monotonicity asserts until the
459  // invariant is restored over the entire region.
460  public Type xval( ) {
461  Type oval = _val; // Get old type
462  Type nval = value(Env.GVN._opt_mode); // Get best type
463  if( nval!=oval ) {
464  _val = nval;
465  Env.GVN.add_flow_uses(this); // Put uses on worklist... values flows downhill
466  }
467  return nval;
468  }
469 
470  public Type val(int idx) { return in(idx)._val; }
471 
472  // Compute the current best liveness for this Node, based on the liveness of
473  // its uses. If basic_liveness(), returns a simple DEAD/ALIVE. Otherwise
474  // computes the alive memory set down to the field level. May return
475  // TypeMem.FULL, especially if its uses are of unwired functions.
476  // It must be monotonic.
477  // This is a reverse-flow transfer-function computation.
478  public TypeMem live( GVNGCM.Mode opt_mode ) {
479  if( _keep>0 ) return all_live();
480  // Compute meet/union of all use livenesses
481  TypeMem live = TypeMem.DEAD; // Start at lattice top
482  for( Node use : _uses ) // Computed across all uses
483  if( use.live_uses() ) {
484  TypeMem ulive = use.live_use(opt_mode, this);
485  live = (TypeMem)live.meet(ulive); // Make alive used fields
486  }
487  assert live==TypeMem.DEAD || live.basic_live()==all_live().basic_live();
488  assert live!=TypeMem.LIVE_BOT || (_val !=Type.CTRL && _val !=Type.XCTRL);
489  return live;
490  }
491  public boolean live_uses() {
492  return _live != TypeMem.DEAD && // Only live uses make more live
493  // And no chance use turns into a constant (which then does not use anything)
494  !(_live.basic_live() && _val.may_be_con() && !is_prim() && err(true)==null &&
495  // FunPtrs still use their Rets, even if constant
496  !(this instanceof FunPtrNode));
497  }
498 
499  // Shortcut to update self-live
500  public Node xliv( GVNGCM.Mode opt_mode ) { _live = live(opt_mode); return this; }
501  // Compute local contribution of use liveness to this def.
502  // Overridden in subclasses that do per-def liveness.
503  public TypeMem live_use( GVNGCM.Mode opt_mode, Node def ) {
504  return _keep>0 ? all_live() : _live;
505  }
506 
507  // Default lower-bound liveness. For control, its always "ALIVE" and for
508  // memory opts (and tuples with memory) its "ALLMEM".
509  public TypeMem all_live() { return TypeMem.LIVE_BOT; }
510 
511  // The _val changed here, and more than the immediate _neighbors might change
512  // value/live
513  public void add_flow_extra(Type old) { }
514  public void add_flow_use_extra(Node chg) { }
515  public void add_flow_def_extra(Node chg) { }
516  // Inputs changed here, and more than the immediate _neighbors might reduce
517  public void add_reduce_extra() { }
518 
519  // Unifies this Node with others; Call/CallEpi with Fun/Parm/Ret. NewNodes &
520  // Load/Stores, etc. Returns true if progress, and puts neighbors back on
521  // the worklist. If 'test' then make no changes, but return if progress
522  // would be made.
523  public boolean unify(boolean test) { return false; }
524 
525  // Return any type error message, or null if no error
526  public ErrMsg err( boolean fast ) { return null; }
527 
528  // Operator precedence is only valid for binary functions.
529  // 1-9: Normal precedence
530  // 0 : Balanced op; precedence is from Parse.term() and not expr().
531  // -1 : Invalid
532  // -2 : Forward ref.
533  public byte op_prec() { return -1; }
534 
535 
536  // Global expressions, to remove redundant Nodes
537  public static final ConcurrentHashMap<Node,Node> VALS = new ConcurrentHashMap<>();
538 
539  // Reducing xforms, strictly fewer Nodes or Edges. n may be either in or out
540  // of VALS. If a replacement is found, replace. In any case, put in the
541  // VALS table. Return null if no progress, or this or the replacement.
542  // If keep is 0, there are no hidden users and can hack away.
543  // If keep is 1, there is exactly one hidden user, which will use the returned replacement.
544  // If keep is 2+, there are many hidden users and the Node cannot be replaced.
545  public Node do_reduce() {
546  assert check_vals();
547  Node nnn = _do_reduce();
548  if( nnn!=null ) { // Something happened
549  if( nnn!=this ) { // Replacement
550  assert _keep<=1; // Can only replace if zero or one
551  Env.GVN.add_flow_uses(this); // Visit users
553  if( _keep==1 ) { _keep--; nnn._keep++; } // Move keep bits over
554  subsume(nnn); // Replace
555  for( Node use : nnn._uses ) {
556  use.add_reduce_extra();
557  use.add_flow_use_extra(nnn);
558  }
559  }
560  Env.GVN.add_reduce(nnn); // Rerun the replacement
561  return nnn._elock(); // After putting in VALS
562  }
563  // No progress; put in VALS and return
564  _elock();
565  return null;
566  }
567 
568  // Check for being not-live, being a constant, CSE in VALS table, and then
569  // call out to ideal_reduce. Returns an equivalent replacement (or self).
570  private Node _do_reduce() {
571  // Replace with a constant, if possible
572  if( should_con(_val) )
573  return con(_val);
574 
575  // Try CSE
576  if( !_elock ) { // Not in VALS
577  Node x = VALS.get(this); // Try VALS
578  if( x != null ) // Hit
579  return merge(x); // Graph replace with x
580  }
581 
582  // Try general ideal call
583  Node x = ideal_reduce(); // Try the general reduction
584  if( x != null )
585  return merge(x); // Graph replace with x
586 
587  return null; // No change
588  }
589 
590 
591  // Change values at this Node directly.
592  public Node do_flow() {
593  Node progress=null;
594  // Compute live bits. If progress, push the defs on the flow worklist.
595  // This is a reverse flow computation. Always assumed live if keep.
596  if( _keep==0 ) {
597  TypeMem oliv = _live;
598  TypeMem nliv = live(Env.GVN._opt_mode);
599  if( oliv != nliv ) { // Progress?
600  progress = this; // Progress!
601  assert nliv.isa(oliv); // Monotonically improving
602  _live = nliv; // Record progress
603  for( Node def : _defs ) // Put defs on worklist... liveness flows uphill
604  if( def != null ) Env.GVN.add_flow(def).add_flow_def_extra(this);
605  add_flow_extra(oliv);
606  }
607  }
608 
609  // Compute best value. If progress, push uses on the flow worklist.
610  // This is a forward flow computation.
611  Type oval = _val; // Get old type
612  Type nval = value(Env.GVN._opt_mode);// Get best type
613  if( nval!=oval ) {
614  progress = this; // Progress!
615  assert nval.isa(oval); // Monotonically improving
616  _val = nval;
617  // If becoming a constant, check for replacing with a ConNode
618  if( !oval.may_be_con() && nval.may_be_con() ) {
619  Env.GVN.add_reduce(this);
620  Env.GVN.add_flow_defs(this); // Since a constant, inputs are no longer live
621  }
622  // Put uses on worklist... values flows downhill
623  for( Node use : _uses )
624  Env.GVN.add_flow(use).add_flow_use_extra(this);
625  // Progressing on CFG can mean CFG paths go dead
626  if( is_CFG() ) for( Node use : _uses ) if( use.is_CFG() ) Env.GVN.add_reduce(use);
627  add_flow_extra(oval);
628  }
629  return progress;
630  }
631 
632  public Node do_mono() {
633  Node x= ideal_mono();
634  if( x==null ) return null;
635  assert x==this;
637  }
638 
639  public Node do_grow() {
640  Node nnn = ideal_grow();
641  if( nnn==null || nnn==this || is_dead() ) return nnn;
642  assert _keep<=1;
643  if( _keep==1 ) { _keep--; nnn._keep++; Env.GVN.add_dead(this); } // Doing an arbitrary replacement
644  return Env.GVN.add_flow(Env.GVN.add_reduce(nnn));
645  }
646 
647  // Replace with a ConNode iff
648  // - Not already a ConNode AND
649  // - Not an ErrNode AND
650  // - Type.is_con()
651  public boolean should_con(Type t) {
652  if( this instanceof ConNode || // Already a constant
653  (this instanceof FunPtrNode && _val.is_con()) || // Already a constant
654  this instanceof ErrNode || // Never touch an ErrNode
655  this instanceof FreshNode ||// These modify the TVars but not the constant flows
656  is_prim() ) // Never touch a Primitive
657  return false; // Already a constant, or never touch an ErrNode
658  // Constant argument to call: keep for call resolution.
659  // Call can always inline to fold constant.
660  if( this instanceof ProjNode && in(0) instanceof CallNode && ((ProjNode)this)._idx>0 )
661  return false;
662  // Is in-error; do not remove the error.
663  if( err(true) != null )
664  return false;
665  // Is a constant
666  return t.is_con();
667  }
668 
669  // Make globally shared common ConNode for this type.
670  public static @NotNull Node con( Type t ) {
671  assert t==t.simple_ptr();
672  Node con;
673  if( t instanceof TypeFunPtr && ((TypeFunPtr)t)._fidxs.abit()!=-1 )
674  con = new FunPtrNode(FunNode.find_fidx(((TypeFunPtr)t).fidx()).ret(),Env.ANY);
675  else
676  con = new ConNode<>(t);
677  Node con2 = VALS.get(con);
678  if( con2 != null ) { // Found a prior constant
679  con.kill(); // Kill the just-made one
680  con = con2;
681  con._live = TypeMem.LIVE_BOT; // Adding more liveness
682  } else { // New constant
683  con._val = t; // Typed
684  con._elock(); // Put in VALS, since if Con appears once, probably appears again in the same XFORM call
685  }
686  Env.GVN.add_flow(con); // Updated live flows
687  return con;
688  }
689 
690  // Forward reachable walk, setting types to ANY and making all dead.
691  public final void walk_initype( GVNGCM gvn, VBitSet bs ) {
692  if( bs.tset(_uid) ) return; // Been there, done that
693  _val = Type.ANY; // Highest value
694  _live = TypeMem.DEAD; // Not alive
695  // Walk reachable graph
696  gvn.add_flow(this);
697  for( Node use : _uses ) use.walk_initype(gvn,bs);
698  for( Node def : _defs ) if( def != null ) def.walk_initype(gvn,bs);
699  }
700 
701  // At least as alive
702  private Node merge(Node x) {
703  x._live = (TypeMem)x._live.meet(_live);
704  return Env.GVN.add_flow(x);
705  }
706 
707  // Node n is new, but cannot call GVN.iter() so cannot call the general xform.
708  public Node init1( ) {
709  Node x = VALS.get(this);
711  if( x!=null ) { // Hit in GVN table
712  merge(x);
713  kill(); // Kill just-init'd
714  return x; // Return old
715  }
716  _elock();
718  return Env.GVN.add_work_all(this);
719  }
720 
721  // Assert all ideal, value and liveness calls are done
722  public final boolean more_ideal(VBitSet bs) {
723  if( bs.tset(_uid) ) return false; // Been there, done that
724  if( _keep == 0 && _live.is_live() ) { // Only non-keeps, which is just top-level scope and prims
725  Type t = value(Env.GVN._opt_mode);
726  if( _val != t )
727  return true; // Found a value improvement
729  if( _live != live )
730  return true; // Found a liveness improvement
731  Node x;
732  x = do_reduce(); if( x != null )
733  return true; // Found an ideal call
734  x = do_mono(); if( x != null )
735  return true; // Found an ideal call
736  x = do_grow(); if( x != null )
737  return true; // Found an ideal call
738  if( this instanceof FunNode ) ((FunNode)this).ideal_inline(true);
739  }
740  for( Node def : _defs ) if( def != null && def.more_ideal(bs) ) return true;
741  for( Node use : _uses ) if( use != null && use.more_ideal(bs) ) return true;
742  return false;
743  }
744 
745  // Assert all value and liveness calls only go forwards. Returns >0 for failures.
746  private static final VBitSet FLOW_VISIT = new VBitSet();
747  public final int more_flow(boolean lifting) { FLOW_VISIT.clear(); return more_flow(lifting,0); }
748  private int more_flow( boolean lifting, int errs ) {
749  if( FLOW_VISIT.tset(_uid) ) return errs; // Been there, done that
750  if( Env.GVN.on_dead(this) ) return errs; // Do not check dying nodes
751  // Check for only forwards flow, and if possible then also on worklist
752  Type oval= _val, nval = value(Env.GVN._opt_mode);
753  TypeMem oliv=_live, nliv = live (Env.GVN._opt_mode);
754  boolean hm = false;
755  if( nval != oval || nliv != oliv || hm ) {
756  boolean ok = lifting
757  ? nval.isa(oval) && nliv.isa(oliv)
758  : oval.isa(nval) && oliv.isa(nliv);
759  if( !ok || (!Env.GVN.on_flow(this) && !Env.GVN.on_dead(this) && _keep==0) ) { // Still-to-be-computed?
760  FLOW_VISIT.clear(_uid); // Pop-frame & re-run in debugger
761  System.err.println(dump(0,new SB(),true)); // Rolling backwards not allowed
762  errs++;
763  }
764  }
765  for( Node def : _defs ) if( def != null ) errs = def.more_flow(lifting,errs);
766  for( Node use : _uses ) if( use != null ) errs = use.more_flow(lifting,errs);
767  return errs;
768  }
769 
770  // Gather errors, walking from Scope to START.
771  public void walkerr_def( HashSet<ErrMsg> errs, VBitSet bs ) {
772  if( bs.tset(_uid) ) return; // Been there, done that
773  for( int i=0; i<_defs._len; i++ ) {
774  Node def = _defs.at(i); // Walk data defs for more errors
775  if( def == null || def._val == Type.XCTRL ) continue;
776  // Walk function bodies that are wired, but not bare FunPtrs.
777  if( def instanceof FunPtrNode && !def.is_forward_ref() )
778  continue;
779  def.walkerr_def(errs,bs);
780  }
781  if( is_prim() ) return;
782  // Skip reporting if any input is 'all', as the input should report instead.
783  for( Node def : _defs )
784  if( def !=null && def._val ==Type.ALL )
785  return; // Skip reporting.
786  adderr(errs);
787  }
788 
789  private void adderr( HashSet<ErrMsg> errs ) {
790  ErrMsg msg = err(false);
791  if( msg==null ) return;
792  msg._order = errs.size();
793  errs.add(msg);
794  }
795 
796  // GCP optimizations on the live subgraph
797  public void walk_opt( VBitSet visit ) {
798  assert !is_dead();
799  if( visit.tset(_uid) ) return; // Been there, done that
800 
801  // Replace any constants. Since the node computes a constant, its inputs
802  // were never marked live, and so go dead and so go to ANY and so are not
803  // available to recompute the constant later.
804  Type val = _val;
805  TypeFunPtr tfp;
806  if( val instanceof TypeFunPtr &&
807  _live.live_no_disp() &&
808  (tfp=(TypeFunPtr)val)._disp!=TypeMemPtr.NO_DISP )
809  val = tfp.make_no_disp();
810  if( should_con(val) )
812 
813  // Walk reachable graph
814  if( is_dead() ) return;
815  Env.GVN.add_work_all(this);
816  for( Node def : _defs ) if( def != null ) def.walk_opt(visit);
817  for( Node use : _uses ) use.walk_opt(visit);
818  }
819 
820  public boolean is_dead() { return _uses == null; }
821  public void set_dead( ) { _defs = _uses = null; } // TODO: Poor-mans indication of a dead node, probably needs to recycle these...
822 
823  // Overridden in subclasses that return TypeTuple value types. Such nodes
824  // are always followed by ProjNodes to break out the tuple slices. If the
825  // node optimizes, each ProjNode becomes a copy of some other value... based
826  // on the ProjNode index
827  public Node is_copy(int idx) { return null; }
828 
829  // Only true for some RetNodes and FunNodes
830  public boolean is_forward_ref() { return false; }
831 
832  // True if this Call/CallEpi pair does not read or write memory.
833  // True for most primitives. Returns the pre-call memory or null.
834  Node is_pure_call() { return null; }
835 
836  // True if normally (not in-error) produces a TypeMem value or a TypeTuple
837  // with a TypeMem at(MEM_IDX).
838  public boolean is_mem() { return false; }
839  // For most memory-producing Nodes, exactly 1 memory producer follows.
840  public Node get_mem_writer() {
841  for( Node use : _uses ) if( use.is_mem() ) return use;
842  return null;
843  }
844  // Easy assertion check
845  boolean check_solo_mem_writer(Node memw) {
846  if( is_prim() ) return true; // Several top-level memory primitives, including top scope & defmem blow this
847  boolean found=false;
848  for( Node use : _uses )
849  if( use == memw ) found=true; // Only memw mem-writer follows
850  else if( use.is_mem() ) return false; // Found a 2nd mem-writer
851  return found;
852  }
853 
854  // Shortcut
855  public Type sharptr( Node mem ) { return mem._val.sharptr(_val); }
856 
857  // Aliases that a MemJoin might choose between. Not valid for nodes which do
858  // not manipulate memory.
859  BitsAlias escapees() { throw unimpl("graph error"); }
860 
861  // Walk a subset of the dominator tree, looking for the last place (highest
862  // in tree) this predicate passes, or null if it never does.
863  Node walk_dom_last(Predicate<Node> P) {
864  assert in(0) != null; // All default control nodes pass ctrl in slot 0
865  Node n = in(0).walk_dom_last(P);
866  if( n != null ) return n; // Take last answer first
867  return P.test(this) ? this : null;
868  }
869 
870  // ----------------------------------------------
871  // Error levels
872  public enum Level {
873  ForwardRef, // Forward refs
874  ErrNode, // ErrNodes
875  Syntax, // Syntax
876  Field, // Field naming errors
877  TypeErr, // Type errors
878  NilAdr, // Address might be nil on mem op
879  BadArgs, // Unspecified primitive bad args
880  UnresolvedCall, // Unresolved calls
881  AllTypeErr, // Type errors, with one of the types All
882  Assert, // Assert type errors
883  TrailingJunk, // Trailing syntax junk
884  MixedPrimGC, // Mixed primitives & GC
885  }
886 
887  // Error messages
888  public static class ErrMsg implements Comparable<ErrMsg> {
889  public Parse _loc; // Point in code to blame
890  public final String _msg; // Printable error message, minus code context
891  public final Level _lvl; // Priority for printing
892  public int _order; // Message order as they are found.
893  public static final ErrMsg FAST = new ErrMsg(null,"fast",Level.Syntax);
894  public static final ErrMsg BADARGS = new ErrMsg(null,"bad arguments",Level.BadArgs);
895  public ErrMsg(Parse loc, String msg, Level lvl) { _loc=loc; _msg=msg; _lvl=lvl; }
896  public static ErrMsg forward_ref(Parse loc, FunPtrNode fun) { return forward_ref(loc,fun._name); }
897  public static ErrMsg forward_ref(Parse loc, String name) {
898  return new ErrMsg(loc,"Unknown ref '"+name+"'",Level.ForwardRef);
899  }
900  public static ErrMsg syntax(Parse loc, String msg) {
901  return new ErrMsg(loc,msg,Level.Syntax);
902  }
903  public static ErrMsg unresolved(Parse loc, String msg) {
904  return new ErrMsg(loc,msg,Level.UnresolvedCall);
905  }
906  public static ErrMsg typerr( Parse loc, Type actual, Type t0mem, Type expected ) { return typerr(loc,actual,t0mem,expected,Level.TypeErr); }
907  public static ErrMsg typerr( Parse loc, Type actual, Type t0mem, Type expected, Level lvl ) {
908  TypeMem tmem = t0mem instanceof TypeMem ? (TypeMem)t0mem : null;
909  VBitSet vb = new VBitSet();
910  SB sb = actual.str(new SB(),vb, tmem, false).p(" is not a ");
911  vb.clear();
912  expected.str(sb,vb,null,false); // Expected is already a complex ptr, does not depend on memory
913  if( actual==Type.ALL && lvl==Level.TypeErr ) lvl=Level.AllTypeErr; // ALLs have failed earlier, so this is a lower priority error report
914  return new ErrMsg(loc,sb.toString(),lvl);
915  }
916  public static ErrMsg typerr( Parse loc, Type actual, Type t0mem, Type[] expecteds ) {
917  TypeMem tmem = t0mem instanceof TypeMem ? (TypeMem)t0mem : null;
918  VBitSet vb = new VBitSet();
919  SB sb = actual.str(new SB(),vb, tmem,false);
920  sb.p( expecteds.length==1 ? " is not a " : " is none of (");
921  vb.clear();
922  for( Type expect : expecteds ) expect.str(sb,vb,null,false).p(',');
923  sb.unchar().p(expecteds.length==1 ? "" : ")");
924  return new ErrMsg(loc,sb.toString(),Level.TypeErr);
925  }
926  public static ErrMsg asserterr( Parse loc, Type actual, Type t0mem, Type expected ) {
927  return typerr(loc,actual,t0mem,expected,Level.Assert);
928  }
929  public static ErrMsg field(Parse loc, String msg, String fld, boolean closure, TypeObj to) {
930  SB sb = new SB().p(msg).p(closure ? " val '" : " field '.").p(fld).p("'");
931  if( to != null && !closure ) to.str(sb.p(" in "),new VBitSet(),null,false);
932  return new ErrMsg(loc,sb.toString(),Level.Field);
933  }
934  public static ErrMsg niladr(Parse loc, String msg, String fld) {
935  String f = fld==null ? msg : msg+" field '."+fld+"'";
936  return new ErrMsg(loc,f,Level.NilAdr);
937  }
938  public static ErrMsg badGC(Parse loc) {
939  return new ErrMsg(loc,"Cannot mix GC and non-GC types",Level.MixedPrimGC);
940  }
941  public static ErrMsg trailingjunk(Parse loc) {
942  return new ErrMsg(loc,"Syntax error; trailing junk",Level.TrailingJunk);
943  }
944 
945  @Override public String toString() {
946  return _loc==null ? _msg : _loc.errLocMsg(_msg);
947  }
948  @Override public int compareTo(ErrMsg msg) {
949  int cmp = _lvl.compareTo(msg._lvl);
950  if( cmp != 0 ) return cmp;
951  return _order - msg._order;
952  //cmp = _loc.compareTo(msg._loc);
953  //if( cmp != 0 ) return cmp;
954  //return _msg.compareTo(msg._msg);
955  }
956  @Override public boolean equals(Object obj) {
957  if( this==obj ) return true;
958  if( !(obj instanceof ErrMsg) ) return false;
959  ErrMsg err = (ErrMsg)obj;
960  if( _lvl!=err._lvl || !_msg.equals(err._msg) ) return false;
961  // Spread a missing loc; cheaty but only a little bit.
962  // TODO: track down missing loc in Parser
963  if( _loc==null && err._loc!=null ) _loc=err._loc;
964  if( _loc!=null && err._loc==null ) err._loc=_loc;
965  return _loc==err._loc || _loc.equals(err._loc);
966  }
967  @Override public int hashCode() {
968  return (_loc==null ? 0 : _loc.hashCode())+_msg.hashCode()+_lvl.hashCode();
969  }
970  }
971 
972 }
com.cliffc.aa.node.Node.ErrMsg.compareTo
int compareTo(ErrMsg msg)
Definition: Node.java:948
com.cliffc.aa.node.Node.OP_PROJ
static final byte OP_PROJ
Definition: Node.java:40
com.cliffc.aa.node.Node.roll_back_CNT
static void roll_back_CNT()
Definition: Node.java:222
com.cliffc.aa.util.Ary.at
E at(int i)
Definition: Ary.java:25
com.cliffc.aa.type.TypeMemPtr.NO_DISP
static final Type NO_DISP
Definition: TypeMemPtr.java:80
com.cliffc.aa.node.Node.OP_NEWARY
static final byte OP_NEWARY
Definition: Node.java:35
com.cliffc.aa.node.Node._do_reduce
Node _do_reduce()
Definition: Node.java:570
com.cliffc.aa.node.Node.ErrMsg.equals
boolean equals(Object obj)
Definition: Node.java:956
com.cliffc.aa.node.Node.Level.AllTypeErr
AllTypeErr
Definition: Node.java:881
com.cliffc.aa.node.Node.Level.Field
Field
Definition: Node.java:876
com.cliffc.aa.node.Node.escapees
BitsAlias escapees()
Definition: Node.java:859
com.cliffc.aa.GVNGCM.add_unuse
Node add_unuse(Node n)
Definition: GVNGCM.java:59
com.cliffc.aa.type.TypeMem.DEAD
static final TypeMem DEAD
Definition: TypeMem.java:226
com.cliffc.aa.type.TypeFunPtr
Definition: TypeFunPtr.java:23
com.cliffc.aa.node.Node.Level.ErrNode
ErrNode
Definition: Node.java:874
com.cliffc.aa.util.Ary.push
E push(E e)
Add element in amortized constant time.
Definition: Ary.java:58
com.cliffc.aa.node.Node.OP_START
static final byte OP_START
Definition: Node.java:45
com.cliffc.aa.type.Type.isa
boolean isa(Type t)
Definition: Type.java:623
com.cliffc.aa.type.TypeMem.live_no_disp
boolean live_no_disp()
Definition: TypeMem.java:320
com.cliffc.aa.node.Node.walk_dom_last
Node walk_dom_last(Predicate< Node > P)
Definition: Node.java:863
com.cliffc.aa.node.Node.live
TypeMem live(GVNGCM.Mode opt_mode)
Definition: Node.java:478
com.cliffc.aa.AA.UID
static int UID
Definition: AA.java:43
com.cliffc.aa.type.TypeMem
Memory type; the state of all of memory; memory edges order memory ops.
Definition: TypeMem.java:53
com.cliffc.aa.GVNGCM.add_mono
public< N extends Node > N add_mono(N n)
Definition: GVNGCM.java:51
com.cliffc.aa.node.Node.len
int len()
Definition: Node.java:125
com.cliffc.aa.node.Node.dump
void dump(int d, SB sb, VBitSet bs, boolean plive)
Definition: Node.java:305
com.cliffc.aa.Parse.hashCode
int hashCode()
Definition: Parse.java:1497
com.cliffc.aa.node.Node._live
TypeMem _live
Definition: Node.java:89
com.cliffc.aa.node.Node.OP_LOOP
static final byte OP_LOOP
Definition: Node.java:32
com.cliffc.aa.GVNGCM.add_flow_uses
void add_flow_uses(Node n)
Definition: GVNGCM.java:55
com.cliffc.aa.node.Node.OP_ERR
static final byte OP_ERR
Definition: Node.java:24
com.cliffc
com.cliffc.aa.node.Node.get_mem_writer
Node get_mem_writer()
Definition: Node.java:840
com.cliffc.aa.node.Node.OP_CON
static final byte OP_CON
Definition: Node.java:20
com.cliffc.aa.node.ScopeNode
Definition: ScopeNode.java:17
com.cliffc.aa.type.TypeMem.LIVE_BOT
static final TypeMem LIVE_BOT
Definition: TypeMem.java:226
com.cliffc.aa.node.Node.add_flow_use_extra
void add_flow_use_extra(Node chg)
Definition: Node.java:514
com.cliffc.aa.node.Node
Definition: Node.java:16
com.cliffc.aa.util
Definition: AbstractEntry.java:1
com.cliffc.aa.node.Node.subsume
Node subsume(Node nnn)
Definition: Node.java:201
com.cliffc.aa.node.Node.VALS
static final ConcurrentHashMap< Node, Node > VALS
Definition: Node.java:537
com.cliffc.aa.node.Node.OP_SPLIT
static final byte OP_SPLIT
Definition: Node.java:44
com.cliffc.aa.type.TypeMem.is_live
boolean is_live()
Definition: TypeMem.java:560
com.cliffc.aa.node.Node.do_flow
Node do_flow()
Definition: Node.java:592
com.cliffc.aa.GVNGCM.add_work_all
Node add_work_all(Node n)
Definition: GVNGCM.java:73
com.cliffc.aa.node.Node.OP_FUNPTR
static final byte OP_FUNPTR
Definition: Node.java:28
com.cliffc.aa.tvar
Definition: TV2.java:1
com.cliffc.aa.node.Node.more_ideal
final boolean more_ideal(VBitSet bs)
Definition: Node.java:722
com.cliffc.aa.type.Type
an implementation of language AA
Definition: Type.java:94
com.cliffc.aa.node.Node.dump
String dump(int max, boolean prims, boolean plive)
Definition: Node.java:288
com.cliffc.aa.node.Node.OP_CALLEPI
static final byte OP_CALLEPI
Definition: Node.java:18
com.cliffc.aa.util.SB.clear
SB clear()
Definition: SB.java:61
com.cliffc.aa.util.Ary
Definition: Ary.java:11
com.cliffc.aa.node.Node.is_multi_tail
boolean is_multi_tail()
Definition: Node.java:355
com.cliffc.aa.node.Node.add_flow_def_extra
void add_flow_def_extra(Node chg)
Definition: Node.java:515
com.cliffc.aa.type.BitsAlias
Definition: BitsAlias.java:8
com.cliffc.aa.node.Node.ErrMsg.typerr
static ErrMsg typerr(Parse loc, Type actual, Type t0mem, Type expected)
Definition: Node.java:906
com.cliffc.aa.node.Node.do_mono
Node do_mono()
Definition: Node.java:632
com.cliffc.aa.node.Node.find
Node find(int uid, VBitSet bs)
Definition: Node.java:428
com.cliffc.aa.node.Node.is_pure_call
Node is_pure_call()
Definition: Node.java:834
com.cliffc.aa.node.Node.keep
public< N extends Node > N keep()
Definition: Node.java:228
com.cliffc.aa.node.Node.OP_THUNK
static final byte OP_THUNK
Definition: Node.java:49
com.cliffc.aa.node.Node.OP_CONTYPE
static final byte OP_CONTYPE
Definition: Node.java:21
com.cliffc.aa.util.Ary._len
int _len
Definition: Ary.java:13
com.cliffc.aa.node.Node.dump
SB dump(int d, SB sb, int max, VBitSet bs, boolean prims, boolean plive)
Definition: Node.java:310
com.cliffc.aa.node.Node.err
ErrMsg err(boolean fast)
Definition: Node.java:526
com.cliffc.aa.node.Node.ErrMsg._msg
final String _msg
Definition: Node.java:890
com.cliffc.aa.node.Node.ErrMsg.niladr
static ErrMsg niladr(Parse loc, String msg, String fld)
Definition: Node.java:934
com.cliffc.aa.node.Node.unelock
void unelock()
Definition: Node.java:128
com.cliffc.aa.node.Node.Level.TrailingJunk
TrailingJunk
Definition: Node.java:883
com.cliffc.aa.node.Node.Level.MixedPrimGC
MixedPrimGC
Definition: Node.java:884
com.cliffc.aa.node.Node.OP_JOIN
static final byte OP_JOIN
Definition: Node.java:30
com.cliffc.aa.node.Node._elock
Node _elock()
Definition: Node.java:137
com.cliffc.aa.node.Node._val
Type _val
Definition: Node.java:88
com.cliffc.aa.node.Node.find
Node find(int uid)
Definition: Node.java:427
com.cliffc.aa.type.Type.ANY
static final Type ANY
Definition: Type.java:325
com.cliffc.aa.node.Node.OP_FRESH
static final byte OP_FRESH
Definition: Node.java:25
com.cliffc.aa.node.Node.ErrMsg
Definition: Node.java:888
com.cliffc.aa.node.Node.OP_FUN
static final byte OP_FUN
Definition: Node.java:27
com.cliffc.aa.node.ConNode
Definition: ConNode.java:9
com.cliffc.aa.node.Node.add_def
Node add_def(Node n)
Definition: Node.java:152
com.cliffc.aa.node.FunPtrNode
Definition: FunPtrNode.java:40
com.cliffc.aa.type.Type.meet
final Type meet(Type t)
Definition: Type.java:412
com.cliffc.aa.node.CallNode
Definition: CallNode.java:86
com.cliffc.aa.AA.unimpl
static RuntimeException unimpl()
Definition: AA.java:10
com.cliffc.aa.node.Node.OP_THRET
static final byte OP_THRET
Definition: Node.java:48
com.cliffc.aa.type.Type.str
SB str(SB sb, VBitSet dups, TypeMem mem, boolean debug)
Definition: Type.java:131
com.cliffc.aa.node.Node.OP_CALL
static final byte OP_CALL
Definition: Node.java:17
com.cliffc.aa.node.Node.ErrMsg._order
int _order
Definition: Node.java:892
com.cliffc.aa.node.Node.init0
static void init0()
Definition: Node.java:70
com.cliffc.aa.node.Node.ideal_reduce
Node ideal_reduce()
Definition: Node.java:441
com.cliffc.aa.util.SB.unchar
SB unchar()
Definition: SB.java:58
com.cliffc.aa.node.Node.insert
void insert(Node nnn)
Definition: Node.java:191
com.cliffc.aa.type.Type.ALL
static final Type ALL
Definition: Type.java:324
com.cliffc.aa.node.Node.is_prim
boolean is_prim()
Definition: Node.java:260
com.cliffc.aa.node.Node.postorder
void postorder(Ary< Node > nodes, VBitSet bs)
Definition: Node.java:383
com.cliffc.aa.node.Node.check_solo_mem_writer
boolean check_solo_mem_writer(Node memw)
Definition: Node.java:845
com.cliffc.aa.node.Node.Node
Node(byte op)
Definition: Node.java:247
com.cliffc.aa.util.VBitSet.tset
boolean tset(int idx)
Definition: VBitSet.java:7
com.cliffc.aa.node.Node.ErrMsg.typerr
static ErrMsg typerr(Parse loc, Type actual, Type t0mem, Type expected, Level lvl)
Definition: Node.java:907
com.cliffc.aa.node.Node.OP_MAX
static final byte OP_MAX
Definition: Node.java:52
com.cliffc.aa.node.Node.Level.Assert
Assert
Definition: Node.java:882
com.cliffc.aa.Env.GVN
static final GVNGCM GVN
Definition: Env.java:13
com.cliffc.aa.node.FunNode.name
static String name(int fidx, boolean debug)
Definition: FunNode.java:109
com.cliffc.aa.node.Node.CNT
static int CNT
Definition: Node.java:59
com.cliffc.aa.type.TypeObj
Definition: TypeObj.java:15
com.cliffc.aa.node.Node.unkeep
public< N extends Node > N unkeep()
Definition: Node.java:232
com.cliffc.aa.node.Node.unhook
public< N extends Node > N unhook()
Definition: Node.java:239
com.cliffc.aa.type.Type.is_con
boolean is_con()
Definition: Type.java:776
com.cliffc.aa.node.Node.OP_CAST
static final byte OP_CAST
Definition: Node.java:19
com.cliffc.aa.node.Node.FLOW_VISIT
static final VBitSet FLOW_VISIT
Definition: Node.java:746
com.cliffc.aa.node.Node.ErrMsg.syntax
static ErrMsg syntax(Parse loc, String msg)
Definition: Node.java:900
com.cliffc.aa.node.Node.should_con
boolean should_con(Type t)
Definition: Node.java:651
com.cliffc.aa.node.Node.is_dead
boolean is_dead()
Definition: Node.java:820
com.cliffc.aa.node.Node.value
abstract Type value(GVNGCM.Mode opt_mode)
com.cliffc.aa.node.Node.OP_IF
static final byte OP_IF
Definition: Node.java:29
com.cliffc.aa.node.Node.kill
Node kill()
Definition: Node.java:211
com.cliffc.aa.node.Node.OP_DEFMEM
static final byte OP_DEFMEM
Definition: Node.java:23
com.cliffc.aa.node.Node._keep
byte _keep
Definition: Node.java:86
com.cliffc.aa.node.ErrNode
Error nodes.
Definition: ErrNode.java:10
com.cliffc.aa.node.Node.dumprpo
String dumprpo(boolean prims, boolean plive)
Definition: Node.java:358
com.cliffc.aa.node.Node.adderr
void adderr(HashSet< ErrMsg > errs)
Definition: Node.java:789
com.cliffc.aa.node.Node.merge
Node merge(Node x)
Definition: Node.java:702
com.cliffc.aa.node.Node.ErrMsg.forward_ref
static ErrMsg forward_ref(Parse loc, String name)
Definition: Node.java:897
com.cliffc.aa.Parse.equals
boolean equals(Object loc)
Definition: Parse.java:1491
com.cliffc.aa.type.Type.CTRL
static final Type CTRL
Definition: Type.java:326
com.cliffc.aa.node.Node.is_copy
Node is_copy(int idx)
Definition: Node.java:827
com.cliffc.aa.node.Node.ErrMsg._lvl
final Level _lvl
Definition: Node.java:891
com.cliffc.aa.node.Node.STRS
static final String[] STRS
Definition: Node.java:54
com.cliffc.aa.node.Node.ErrMsg.trailingjunk
static ErrMsg trailingjunk(Parse loc)
Definition: Node.java:941
com.cliffc.aa.util.SB.s
SB s()
Definition: SB.java:41
com.cliffc.aa.node.FunNode.find_fidx
static FunNode find_fidx(int fidx)
Definition: FunNode.java:101
com.cliffc.aa.Parse.errLocMsg
String errLocMsg(String s)
Definition: Parse.java:1466
com.cliffc.aa.type.TypeMem.basic_live
boolean basic_live()
Definition: TypeMem.java:561
com.cliffc.aa.node.Node.ErrMsg.FAST
static final ErrMsg FAST
Definition: Node.java:893
com.cliffc.aa.node.Node.in
Node in(int i)
Definition: Node.java:126
com.cliffc.aa.node.Node.OP_SCOPE
static final byte OP_SCOPE
Definition: Node.java:43
com.cliffc.aa.node.Node.hashCode
int hashCode()
Definition: Node.java:105
com.cliffc.aa.GVNGCM.on_flow
boolean on_flow(Node n)
Definition: GVNGCM.java:40
com.cliffc.aa.tvar.TV2.make_leaf
static TV2 make_leaf(Node n, @NotNull String alloc_site)
Definition: TV2.java:126
com.cliffc.aa.node.Node.set_dead
void set_dead()
Definition: Node.java:821
com.cliffc.aa.node.Node.OP_LOAD
static final byte OP_LOAD
Definition: Node.java:31
com.cliffc.aa.type.Type.may_be_con
boolean may_be_con()
Definition: Type.java:759
com.cliffc.aa.type.Type.XCTRL
static final Type XCTRL
Definition: Type.java:327
com.cliffc.aa.GVNGCM
Definition: GVNGCM.java:12
com.cliffc.aa.type.Type.sharptr
Type sharptr(Type ptr)
Definition: Type.java:930
com.cliffc.aa.node.Node.unuse
Node unuse(Node old)
Definition: Node.java:178
com.cliffc.aa.node.Node.OP_NEWOBJ
static final byte OP_NEWOBJ
Definition: Node.java:34
com.cliffc.aa.type.TypeFunPtr.make_no_disp
TypeFunPtr make_no_disp()
Definition: TypeFunPtr.java:77
com.cliffc.aa.node.Node.ErrMsg.asserterr
static ErrMsg asserterr(Parse loc, Type actual, Type t0mem, Type expected)
Definition: Node.java:926
com.cliffc.aa.node.Node._INIT0_CNT
static int _INIT0_CNT
Definition: Node.java:58
com.cliffc.aa.type.Type.simple_ptr
Type simple_ptr()
Definition: Type.java:358
com.cliffc.aa.node.FreshNode
Definition: FreshNode.java:11
com.cliffc.aa.node.ProjNode
Definition: ProjNode.java:11
com.cliffc.aa.node.Node.walk_initype
final void walk_initype(GVNGCM gvn, VBitSet bs)
Definition: Node.java:691
com.cliffc.aa.util.VBitSet
Definition: VBitSet.java:5
com.cliffc.aa.node.Node.Level.ForwardRef
ForwardRef
Definition: Node.java:873
com.cliffc.aa.node.Node.add_reduce_extra
void add_reduce_extra()
Definition: Node.java:517
Comparable
com.cliffc.aa.node.Node.more_flow
final int more_flow(boolean lifting)
Definition: Node.java:747
com.cliffc.aa.type.TypeObj.str
SB str(SB sb, VBitSet dups, TypeMem mem, boolean debug)
Definition: TypeObj.java:34
com.cliffc.aa.node.Node.insert
Node insert(int idx, Node n)
Definition: Node.java:165
NotNull
com.cliffc.aa.util.SB
Tight/tiny StringBuilder wrapper.
Definition: SB.java:8
com.cliffc.aa.node.Node.con
static Node con(Type t)
Definition: Node.java:670
com.cliffc.aa.node.Node._uses
Ary< Node > _uses
Definition: Node.java:245
com.cliffc.aa.node.Node.OP_NEWSTR
static final byte OP_NEWSTR
Definition: Node.java:36
com.cliffc.aa.node.Node.Node
Node(byte op, Node... defs)
Definition: Node.java:248
com.cliffc.aa.node.Node.is_mem
boolean is_mem()
Definition: Node.java:838
com.cliffc.aa.node.Node.ideal_grow
Node ideal_grow()
Definition: Node.java:450
com.cliffc.aa.AA
an implementation of language AA
Definition: AA.java:9
com.cliffc.aa.node.Node._header
static void _header(FunNode fun, SB sb)
Definition: Node.java:380
com.cliffc.aa.node.Node.OP_CPROJ
static final byte OP_CPROJ
Definition: Node.java:22
com.cliffc.aa.node.Node.is_CFG
boolean is_CFG()
Definition: Node.java:356
com.cliffc.aa.node.Node.OP_STORE
static final byte OP_STORE
Definition: Node.java:47
com.cliffc.aa.node.Node.val
Type val(int idx)
Definition: Node.java:470
com.cliffc.aa.node.Node.LIVE
static final VBitSet LIVE
Definition: Node.java:60
com.cliffc.aa
Definition: AA.java:1
com.cliffc.aa.node.Node.all_live
TypeMem all_live()
Definition: Node.java:509
com.cliffc.aa.node.UnresolvedNode
Definition: UnresolvedNode.java:13
com.cliffc.aa.util.SB.nl
SB nl()
Definition: SB.java:48
com.cliffc.aa.node.Node.toString
String toString()
Definition: Node.java:284
com.cliffc.aa.node.Node.xstr
String xstr()
Definition: Node.java:282
com.cliffc.aa.node.Node._elock
boolean _elock
Definition: Node.java:87
com.cliffc.aa.node.Node.copy
Node copy(boolean copy_edges)
Definition: Node.java:264
Cloneable
com.cliffc.aa.node.Node.Level.NilAdr
NilAdr
Definition: Node.java:878
com.cliffc.aa.node.Node.is_forward_ref
boolean is_forward_ref()
Definition: Node.java:830
com.cliffc.aa.node.FunPtrNode._name
String _name
Definition: FunPtrNode.java:41
com.cliffc.aa.util.SB.p
SB p(String s)
Definition: SB.java:13
com.cliffc.aa.node.Node.OP_PRIM
static final byte OP_PRIM
Definition: Node.java:39
com.cliffc.aa.node.Node.set_def
Node set_def(int idx, Node n)
Definition: Node.java:154
com.cliffc.aa.node.Node.OP_TYPE
static final byte OP_TYPE
Definition: Node.java:50
com.cliffc.aa.node.Node.do_grow
Node do_grow()
Definition: Node.java:639
com.cliffc.aa.node.Node.ErrMsg.ErrMsg
ErrMsg(Parse loc, String msg, Level lvl)
Definition: Node.java:895
com.cliffc.aa.node.Node.equals
boolean equals(Object o)
Definition: Node.java:112
com.cliffc.aa.node.Node.sharptr
Type sharptr(Node mem)
Definition: Node.java:855
com.cliffc.aa.GVNGCM.add_reduce
public< N extends Node > N add_reduce(N n)
Definition: GVNGCM.java:49
com.cliffc.aa.node.Node.reset_to_init0
static void reset_to_init0()
Definition: Node.java:77
com.cliffc.aa.node.Node.del
void del(int idx)
Definition: Node.java:169
com.cliffc.aa.node.CallEpiNode
Definition: CallEpiNode.java:24
com.cliffc.aa.node.Node._op
final byte _op
Definition: Node.java:85
com.cliffc.aa.node.Node.walkerr_def
void walkerr_def(HashSet< ErrMsg > errs, VBitSet bs)
Definition: Node.java:771
com.cliffc.aa.tvar.TV2
Definition: TV2.java:23
com.cliffc.aa.node.Node.OP_UNR
static final byte OP_UNR
Definition: Node.java:51
com.cliffc.aa.node.Node.OP_FP2DISP
static final byte OP_FP2DISP
Definition: Node.java:26
com.cliffc.aa.GVNGCM.Mode.Opto
Opto
Definition: GVNGCM.java:17
com.cliffc.aa.GVNGCM.add_flow_defs
void add_flow_defs(Node n)
Definition: GVNGCM.java:54
com.cliffc.aa.node.Node.OP_PARM
static final byte OP_PARM
Definition: Node.java:37
com.cliffc.aa.node.Node.is_multi_head
boolean is_multi_head()
Definition: Node.java:354
com.cliffc.aa.node.Node.xval
Type xval()
Definition: Node.java:460
com.cliffc.aa.node.Node.ErrMsg.unresolved
static ErrMsg unresolved(Parse loc, String msg)
Definition: Node.java:903
com.cliffc.aa.node.Node.OP_RET
static final byte OP_RET
Definition: Node.java:42
com.cliffc.aa.GVNGCM._opt_mode
Mode _opt_mode
Definition: GVNGCM.java:22
com.cliffc.aa.node.Node.str
String str()
Definition: Node.java:283
com.cliffc.aa.node.Node.unify
boolean unify(boolean test)
Definition: Node.java:523
com.cliffc.aa.node.Node.pop
Node pop()
Definition: Node.java:174
com.cliffc.aa.node.Node.newuid
int newuid()
Definition: Node.java:61
com.cliffc.aa.GVNGCM.add_flow
public< N extends Node > N add_flow(N n)
Definition: GVNGCM.java:50
com.cliffc.aa.util.SB.i
SB i(int d)
Definition: SB.java:38
com.cliffc.aa.GVNGCM.add_dead
void add_dead(Node n)
Definition: GVNGCM.java:48
com.cliffc.aa.node.Node.live_use
TypeMem live_use(GVNGCM.Mode opt_mode, Node def)
Definition: Node.java:503
com.cliffc.aa.node.Node.dump
String dump(int max)
Definition: Node.java:286
com.cliffc.aa.node.Node.more_flow
int more_flow(boolean lifting, int errs)
Definition: Node.java:748
com.cliffc.aa.node.Node.Level.UnresolvedCall
UnresolvedCall
Definition: Node.java:880
com.cliffc.aa.node.Node.ErrMsg._loc
Parse _loc
Definition: Node.java:889
com.cliffc.aa.node.Node.Level
Definition: Node.java:872
com.cliffc.aa.node.Node._tvar
TV2 _tvar
Definition: Node.java:94
com.cliffc.aa.node.Node.OP_NAME
static final byte OP_NAME
Definition: Node.java:33
com.cliffc.aa.node.Node.ideal_mono
Node ideal_mono()
Definition: Node.java:445
com.cliffc.aa.node.Node._uid
int _uid
Definition: Node.java:84
com.cliffc.aa.node.Node.tvar
TV2 tvar()
Definition: Node.java:96
com.cliffc.aa.node.Node.ErrMsg.toString
String toString()
Definition: Node.java:945
com.cliffc.aa.node.FunNode
Definition: FunNode.java:58
com.cliffc.aa.node.Node.init1
Node init1()
Definition: Node.java:708
com.cliffc.aa.node.Node.check_vals
boolean check_vals()
Definition: Node.java:143
com.cliffc.aa.node.Node.ErrMsg.forward_ref
static ErrMsg forward_ref(Parse loc, FunPtrNode fun)
Definition: Node.java:896
com.cliffc.aa.node.Node.tvar
TV2 tvar(int x)
Definition: Node.java:100
com.cliffc.aa.node.Node.ErrMsg.hashCode
int hashCode()
Definition: Node.java:967
com.cliffc.aa.Env.ANY
static ConNode ANY
Definition: Env.java:24
com.cliffc.aa.node.Node.Level.TypeErr
TypeErr
Definition: Node.java:877
com
com.cliffc.aa.node.Node.Level.BadArgs
BadArgs
Definition: Node.java:879
com.cliffc.aa.node.Node.Level.Syntax
Syntax
Definition: Node.java:875
com.cliffc.aa.node.Node.do_reduce
Node do_reduce()
Definition: Node.java:545
com.cliffc.aa.node.Node.replace
void replace(Node old, Node nnn)
Definition: Node.java:163
com.cliffc.aa.node.Node.dump
SB dump(int d, SB sb, boolean plive)
Definition: Node.java:290
com.cliffc.aa.node.Node.new_tvar
TV2 new_tvar(String alloc_site)
Definition: Node.java:101
com.cliffc.aa.node.Node.OP_PHI
static final byte OP_PHI
Definition: Node.java:38
com.cliffc.aa.node.Node.OP_STMEM
static final byte OP_STMEM
Definition: Node.java:46
com.cliffc.aa.node.Node.op_prec
byte op_prec()
Definition: Node.java:533
com.cliffc.aa.node.Node.ErrMsg.BADARGS
static final ErrMsg BADARGS
Definition: Node.java:894
com.cliffc.aa.Env
Definition: Env.java:12
com.cliffc.aa.node.Node.ErrMsg.typerr
static ErrMsg typerr(Parse loc, Type actual, Type t0mem, Type[] expecteds)
Definition: Node.java:916
com.cliffc.aa.util.SB.toString
String toString()
Definition: SB.java:62
com.cliffc.aa.node.Node.walk_opt
void walk_opt(VBitSet visit)
Definition: Node.java:797
com.cliffc.aa.type
Definition: Bits.java:1
com.cliffc.aa.GVNGCM.on_dead
boolean on_dead(Node n)
Definition: GVNGCM.java:39
com.cliffc.aa.node.Node.add_flow_extra
void add_flow_extra(Type old)
Definition: Node.java:513
com.cliffc.aa.node.Node._defs
Ary< Node > _defs
Definition: Node.java:124
com.cliffc.aa.tvar.TV2.find
TV2 find()
Definition: TV2.java:240
com.cliffc.aa.type.TypeMemPtr
Definition: TypeMemPtr.java:14
com.cliffc.aa.node.Node.OP_REGION
static final byte OP_REGION
Definition: Node.java:41
com.cliffc.aa.Parse
an implementation of language AA
Definition: Parse.java:68
com.cliffc.aa.Env.ALL_CTRL
static ConNode ALL_CTRL
Definition: Env.java:20
com.cliffc.aa.node.FunNode.ret
RetNode ret()
Definition: FunNode.java:900
com.cliffc.aa.GVNGCM.Mode
Definition: GVNGCM.java:14
com.cliffc.aa.node.Node.ErrMsg.field
static ErrMsg field(Parse loc, String msg, String fld, boolean closure, TypeObj to)
Definition: Node.java:929
com.cliffc.aa.node.Node.xliv
Node xliv(GVNGCM.Mode opt_mode)
Definition: Node.java:500
com.cliffc.aa.node.Node.live_uses
boolean live_uses()
Definition: Node.java:491
com.cliffc.aa.node.Node.ErrMsg.badGC
static ErrMsg badGC(Parse loc)
Definition: Node.java:938