aa
CallNode.java
Go to the documentation of this file.
1 package com.cliffc.aa.node;
2 
3 import com.cliffc.aa.Env;
4 import com.cliffc.aa.GVNGCM;
5 import com.cliffc.aa.Parse;
6 import com.cliffc.aa.type.*;
7 import com.cliffc.aa.util.Ary;
8 import org.jetbrains.annotations.NotNull;
9 
10 import java.util.Arrays;
11 import java.util.BitSet;
12 
13 import static com.cliffc.aa.AA.*;
14 import static com.cliffc.aa.Env.GVN;
15 
16 // Call/apply node.
17 //
18 // Control is not required for an apply but inlining the function body will
19 // require it; slot 0 is for Control. Slot 1 is function memory, slot 2 the
20 // function ptr - a Node typed as a TypeFunPtr; can be a FunPtrNode, an
21 // Unresolved, or e.g. a Phi or a Load. Slots 3+ are for other args.
22 //
23 // When the function type simplifies to a single FIDX, the Call can inline.
24 //
25 // TFPs are actually Closures and include an extra argument for the enclosed
26 // environment (actually expanded out to one arg-per-used-scope). These extra
27 // arguments are part of the function signature but are not direct inputs into
28 // the call. FP2Closure strips out the FIDX and passes on just the display.
29 //
30 // The Call-graph is lazily discovered during GCP/opto. Before then all
31 // functions are kept alive with a special control (see FunNode), and all Calls
32 // are assumed to call all functions... unless their fun() input is a trival
33 // function constant.
34 //
35 // As the Call-graph is discovered, Calls are "wired" to make it explicit: the
36 // Call control is wired to the FunNode/Region; call args are wired directly to
37 // function ParmNodes/PhiNode; the CallEpi is wired to the function RetNode.
38 // After GCP/opto the call-graph is explicit and fairly precise. The call-site
39 // index is just like a ReturnPC value on a real machine; it dictates which of
40 // several possible returns apply... and can be merged like a PhiNode.
41 //
42 // Memory into a Call is limited to call-reachable read-write memory.
43 // Memory out of a Call is limited to call-reachable writable memory.
44 //
45 // ASCIIGram: Vertical lines are part of the original graph.
46 // Horizontal lines are lazily wired during GCP.
47 //
48 // TFP&Math
49 // Memory: limited to reachable
50 // | | arg0 arg1
51 // | \ | / Other Calls
52 // | | | / / | \
53 // | v v v / | \
54 // | Call / | \
55 // | C/M/Args / | \
56 // | +--------->------>-------> Wired during GCP
57 // | FUN0 FUN1 FUN2
58 // | +--+ +--+ +--+
59 // | | | | | | |
60 // | | | | | | |
61 // | +--+ +--+ +--+
62 // | /-----Ret<---Ret<---Ret--\ Wired during GCP
63 // | CallEpi fptr fptr fptr Other
64 // | CProj \ | / CallEpis
65 // | MProj \ | /
66 // | DProj TFP&Math
67 // \ / | \
68 // MemMerge: limited to reachable writable
69 //
70 // Wiring a Call changes the Node graph and has to preserve invariants. The
71 // graph has a major type invariant: at every moment in time computing the
72 // value() call on a Node (from the types of its inputs) produces a type which
73 // is monotonically better (either up or down, according to iter() vs gcp()).
74 //
75 // Wiring adds a bunch of edges and thus inputs. The graph has to keep the
76 // type invariant after adding the edges, and this is not always possible; the
77 // types can flow to the Fun and the Call at a different rate, and the two
78 // not-connected Nodes might be out-of-type-order relative to each other. The
79 // progress and monotonicity properties guarantee they will eventually align.
80 //
81 // Discovery of a CG edge happens when a Call's function value changes, but
82 // graph type alignment might be much later. We want to act on the discovery
83 // of a CG edge now, but not flow types until they align. See CallEpi for
84 // wired_not_typed bits.
85 
86 public class CallNode extends Node {
87  int _rpc; // Call-site return PC
88  boolean _unpacked; // One-shot flag; call site allows unpacking a tuple
89  boolean _is_copy; // One-shot flag; Call will collapse
90  public boolean _not_resolved_by_gcp; // One-shot flag set when GCP cannot resolve; this Call is definitely in-error
91  // Example: call(arg1,arg2)
92  // _badargs[0] points to the opening paren.
93  // _badargs[1] points to the start of arg1, same for arg2, etc.
94  Parse[] _badargs; // Errors for e.g. wrong arg counts or incompatible args; one error point per arg.
95  public CallNode( boolean unpacked, Parse[] badargs, Node... defs ) {
96  super(OP_CALL,defs);
97  assert defs[DSP_IDX]==null || defs[DSP_IDX]._val==Type.ALL || defs[DSP_IDX]._val==Type.ANY || defs[DSP_IDX]._val instanceof TypeMemPtr; // Temp; not required
98  assert defs.length > DSP_IDX+1;
99  _rpc = BitsRPC.new_rpc(BitsRPC.ALL); // Unique call-site index
100  _unpacked=unpacked; // Arguments are typically packed into a tuple and need unpacking, but not always
101  _badargs = badargs;
102  }
103 
104  @Override public String xstr() { return _is_copy ? "CopyCall" : (is_dead() ? "Xall" : "Call"); } // Self short name
105  String str() { return xstr(); } // Inline short name
106  @Override public boolean is_mem() { // Some calls are known to not write memory
107  CallEpiNode cepi = cepi();
108  return cepi!=null && ProjNode.proj(cepi,MEM_IDX)!=null;
109  }
110 
111  // Call arguments:
112  // 0 - Control. If XCTRL, call is not reached.
113  // 1 - Memory. This is memory into the call and also arg#0
114  // 2 - Display, a TypeMemPtr. Can be nil, if no display is passed.
115  // 3+ Other "normal" arguments, numbered#ARG_IDX and up.
116  // Last - Set of FIDXS for call targets, typed as a TFP with the display ignored.
117  // The output type here is trimmed to what is "resolved"
118  public Node ctl() { return in(CTL_IDX); }
119  public Node mem() { return in(MEM_IDX); }
120  public Node dsp() { return in(DSP_IDX); } // Display
121  public Node fdx() { return _defs.last(); } // FIDX
122 
123  // Number of actual arguments, including closure/display at DSP_IDX, and not
124  // counting the FIDX in the last position.
125  int nargs() { return _defs._len-1; }
126  // Actual arguments. Arg(1) is allowed and refers to memory; arg(2) to the Display/TFP.
127  Node arg ( int x ) { assert x>=0; return _defs.at(x); }
128  // Set an argument. Use 'set_fun' to set the Code.
129  Node set_arg (int idx, Node arg) { assert idx>=DSP_IDX && idx <nargs(); return set_def(idx,arg); }
130  public Node set_dsp( Node dsp) { return set_def(DSP_IDX, dsp); }
131  public void set_mem( Node mem) { set_def(MEM_IDX, mem); }
132  public Node set_fdx( Node fun) { return set_def(_defs._len-1,fun); }
133  public BitsFun fidxs() {
134  Type tf = fdx()._val;
135  return tf instanceof TypeFunPtr ? ((TypeFunPtr)tf).fidxs() : null;
136  }
137 
138  // Add a bunch of utilities for breaking down a Call.value tuple:
139  // takes a Type, upcasts to tuple, & slices by name.
140  // ts[0] == in(0) == ctl() == Ctrl
141  // ts[1] == in(1) == mem() == Mem into the callee = mem()
142  // ts[2] == in(2) == fun() == Display pointer, NOT FUNCTION POINTER, no FIDX.
143  // ts[3] == in(3) == arg(3)
144  // ts[4] == in(4) == arg(4)
145  // ....
146  // ts[_defs._len-1] = Function pointer with FIDX.
147  // ts[_defs._len] = Escape-in aliases as a BitsAlias
148  static Type tctl( Type tcall ) { return ((TypeTuple)tcall).at(CTL_IDX); }
149  static TypeMem emem( Type tcall ) { return emem( ((TypeTuple)tcall)._ts ); }
150  static TypeMem emem( Type[] ts ) { return (TypeMem ) ts[MEM_IDX]; } // callee memory passed into function
151  static TypeMemPtr tesc( Type tcall ) {
152  if( !(tcall instanceof TypeTuple) ) return tcall.oob(TypeMemPtr.OOP);
153  TypeTuple tt = (TypeTuple)tcall;
154  return (TypeMemPtr)tt.at(tt.len()-1);
155  }
156  // No-check must-be-correct get TFP
157  static public TypeFunPtr ttfp( Type tcall ) {
158  TypeTuple tt = (TypeTuple)tcall;
159  return (TypeFunPtr)tt.at(tt.len()-2); // 2nd-to-last type
160  }
161  // Return TFP or null if not well structured
162  static public TypeFunPtr ttfpx(Type tcall ) {
163  if( !(tcall instanceof TypeTuple) ) return null;
164  TypeTuple tt = (TypeTuple)tcall;
165  Type t = tt.at(tt.len()-2);
166  return t instanceof TypeFunPtr ? (TypeFunPtr)t : null;
167  }
168  static TypeTuple set_ttfp( TypeTuple tcall, TypeFunPtr nfptr ) { return tcall.set(tcall.len()-2,nfptr); }
169  static Type targ( Type tcall, int x ) { return targ(((TypeTuple)tcall)._ts,x); }
170  static Type targ( Type[] ts, int x ) { return ts[x]; }
171 
172  // Clones during inlining all become unique new call sites. The original RPC
173  // splits into 2, and the two new children RPCs replace it entirely. The
174  // original RPC may exist in the type system for a little while, until the
175  // children propagate everywhere.
176  @Override @NotNull public CallNode copy( boolean copy_edges) {
177  CallNode call = (CallNode)super.copy(copy_edges);
178  Node old_rpc = Node.con(TypeRPC.make(_rpc));
179  call._rpc = BitsRPC.new_rpc(_rpc); // Children RPC
180  set_rpc(BitsRPC.new_rpc(_rpc)); // New child RPC for 'this' as well.
181  // Swap out the existing old rpc users for the new.
182  // Might be no users of either.
183  Node new_rpc = Node.con(TypeRPC.make(_rpc));
184  old_rpc.subsume(new_rpc);
185  return call;
186  }
187 
188  @Override public Node ideal_reduce() {
189  Node cc = in(0).is_copy(0);
190  if( cc!=null ) return set_def(0,cc);
191  // When do I do 'pattern matching'? For the moment, right here: if not
192  // already unpacked a tuple, and can see the NewNode, unpack it right now.
193  if( !_unpacked ) { // Not yet unpacked a tuple
194  assert nargs()==ARG_IDX+1;// Memory, Display plus the arg tuple
195  Node arg = arg(ARG_IDX);
196  Type tadr = arg._val;
197  if( tadr instanceof TypeMemPtr && arg instanceof ProjNode ) {
198  int alias = ((TypeMemPtr)tadr)._aliases.abit();
199  if( alias == -1 ) throw unimpl(); // Handle multiple aliases, handle all/empty
200  Node mem = mem();
201  if( mem instanceof FreshNode ) mem = ((FreshNode)mem).id();
202  // Bypass a MemJoin
203  if( mem instanceof MemJoinNode ) {
204  int jdx = ((MemJoinNode)mem).msp().find_alias_index(alias);
205  if( jdx!=0 ) mem = mem.in(jdx);
206  }
207  // Find a tuple being passed in directly; unpack
208  if( mem instanceof MrgProjNode && mem.in(0)==arg.in(0) ) {
209  NewNode nnn = (NewNode)arg.in(0);
210  Node fdx = pop();
211  remove(_defs._len-1); // Pop off the NewNode tuple
212  int len = nnn._defs._len;
213  for( int i=1; NewNode.def_idx(i)<len; i++ ) // Push the args; unpacks the tuple
214  add_def( nnn.fld(i));
215  add_def(fdx); // FIDX is last
216  _unpacked = true; // Only do it once
217  keep().xval(); // Recompute value, this is not monotonic since replacing tuple with args
218  GVN.add_work_all(unkeep());// Revisit after unpacking
219  return this;
220  }
221  }
222  }
223 
224  Type tc = _val;
225  if( !(tc instanceof TypeTuple) ) return null;
226  TypeTuple tcall = (TypeTuple)tc;
227 
228  // Dead, do nothing
229  if( tctl(tcall)!=Type.CTRL ) { // Dead control (NOT dead self-type, which happens if we do not resolve)
230  if( (ctl() instanceof ConNode) ) return null;
231  // Kill all inputs with type-safe dead constants
234  if( is_dead() ) return this;
235  for( int i=ARG_IDX; i<_defs._len; i++ )
236  set_def(i,Env.ANY);
237  //gvn.add_work_defs(this);
238  //return set_def(0,Env.XCTRL,gvn);
239  throw unimpl();
240  }
241 
242  // Have some sane function choices?
243  TypeFunPtr tfp = ttfp(tcall);
244  BitsFun fidxs = tfp.fidxs();
245  if( fidxs==BitsFun.EMPTY ) // TODO: zap function to empty function constant
246  return null; // Zero choices
247 
248  // If we have a single function allowed, force the function constant.
249  Node fdx = fdx(); // Function epilog/function pointer
250  int fidx = fidxs.abit(); // Check for single target
251  if( fidx != -1 && !(fdx instanceof FunPtrNode) ) {
252  // Check that the single target is well-formed
253  FunNode fun = FunNode.find_fidx(Math.abs(fidx));
254  if( fun != null && !fun.is_dead() ) {
255  RetNode ret = fun.ret();
256  if( ret != null ) {
257  // The same function might be called with different displays; make
258  // sure we get the right one. See if there is a single un-escaped
259  // FunPtr. Common for non-upwardsly exposed targets.
260  FunPtrNode fptr = ret.funptr();
261  if( fptr != null && !fptr.display()._live.live().is_escape() )
262  return set_dsp(fptr);
263  // See if FunPtr is available just above an Unresolved.
264  if( fdx instanceof UnresolvedNode ) {
265  fptr = ((UnresolvedNode)fdx).find_fidx(fidx);
266  if( fptr != null ) { // Gonna improve
267  if( dsp() instanceof FP2DispNode && dsp().in(0)==fdx )
268  set_dsp(fptr.display());
269  return set_fdx(fptr);
270  }
271  }
272  }
273  }
274  }
275 
276  // If the function is unresolved, see if we can resolve it now.
277  // Fidxs are typically low during iter, but can be high during
278  // iter post-GCP on error calls where nothing resolves.
279  CallEpiNode cepi = cepi();
280  if( fidx == -1 && !fidxs.above_center() && !fidxs.test(1)) {
281  FunPtrNode fptr = least_cost(fidxs, fdx); // Check for least-cost target
282  if( fptr != null ) {
283  if( cepi!=null ) Env.GVN.add_reduce(cepi); // Might unwire
284  if( fptr.display()._val.isa(dsp()._val) )
285  set_dsp(fptr.display());
286  set_fdx(fptr); // Resolve to 1 choice
287  xval(); // Force value update; least-cost LOWERS types (by removing a choice)
288  add_flow_use_extra(fptr);
289  if( cepi!=null ) Env.GVN.add_reduce(cepi); // Might unwire
290  return this;
291  }
292  }
293 
294  // See if the display is always dead; common for Unresolved of primitives.
295  UnresolvedNode unk;
296  if( fdx instanceof UnOrFunPtrNode && (unk=((UnOrFunPtrNode)fdx).unk())!=null &&
297  !(dsp() instanceof ConNode && dsp()._val==Type.ANY) ) {
298  boolean dsp_nil=true;
299  for( Node fptr : unk._defs )
300  if( !(fptr instanceof FunPtrNode) || ((FunPtrNode)fptr).display()._val!=TypeMemPtr.NO_DISP )
301  { dsp_nil=false; break; }
302  if( dsp_nil ) { // Display is unused by any Unresolved
303  set_dsp(Env.ANY);
304  return this;
305  }
306  }
307 
308 
309  // Wire valid targets.
310  if( cepi!=null && cepi.check_and_wire() )
311  return this; // Some wiring happened
312 
313  // Check for dead args and trim; must be after all wiring is done because
314  // unknown call targets can appear during GCP and use the args. After GCP,
315  // still must verify all called functions have the arg as dead, because
316  // alive args still need to resolve. Constants are an issue, because they
317  // fold into the Parm and the Call can lose the matching DProj while the
318  // arg is still alive.
319  if( GVN._opt_mode._CG && err(true)==null ) {
320  Node progress = null;
321  for( int i=DSP_IDX; i<nargs(); i++ )
322  if( ProjNode.proj(this,i)==null &&
323  !(arg(i) instanceof ConNode) ) // Not already folded
324  progress = set_arg(i,Env.ANY); // Kill dead arg
325  if( progress != null ) return this;
326  }
327 
328  return null;
329  }
330  // Call reduces, then check the CEPI for reducing
331  @Override public void add_reduce_extra() {
332  Node cepi = cepi();
333  if( !_is_copy && cepi!=null )
335  if( mem() instanceof MrgProjNode )
336  Env.GVN.add_reduce(this);
337  Env.GVN.add_flow(mem()); // Dead pointer args reduced to ANY, so mem() liveness lifts
338  }
339 
340  @Override public Node ideal_grow() {
341  // Check for a prior New and move past the call (pushes a store-like
342  // behavior down). The New address must not be reachable from the Call
343  // arguments transitively, which is detected in the escape-in set.
344 
345  // Inserting a MemSplit is a ideal_grow, and swap_new could be an
346  // ideal_mono, but they both use the same large correctness tests, so both
347  // go under ideal_grow to avoid recomputing the test.
348  Node mem = mem();
349  CallEpiNode cepi = cepi();
350  if( _keep>0 || cepi==null || !(mem._val instanceof TypeMem) ) return null;
351  ProjNode cepim = ProjNode.proj(cepi,MEM_IDX); // Memory projection from CEPI
352  ProjNode cepid = ProjNode.proj(cepi,REZ_IDX); // Return projection from CEPI
353  if( cepim == null ) return null;
354  if( !(cepim._val instanceof TypeMem) ) return null;
355  TypeMem tmcepi = (TypeMem) cepim._val;
356  if( !mem._val.isa(tmcepi) ) return null; // Call entry stale relative to exit
357  BitsAlias escs = escapees();
358  // Check for prior MrgProj/New
359  if( mem instanceof MrgProjNode )
360  return _ideal_grow((MrgProjNode)mem,cepim,cepid,escs,-1);
361  // Check for prior Join/MrgProj/New
362  if( mem instanceof MemJoinNode ) {
363  for( int i=1; i<mem._defs._len; i++ )
364  if( mem.in(i) instanceof MrgProjNode ) {
365  Node x = _ideal_grow((MrgProjNode)mem.in(i),cepim,cepid,escs,i);
366  if( x!=null ) return x;
367  }
368  }
369  return null;
370  }
371 
372  // Check for a Call/New that can either bypass or be placed in parallel
373  private Node _ideal_grow(MrgProjNode mem, ProjNode cepim, ProjNode cepid, BitsAlias escs, int i) {
374  // No alias overlaps
375  int alias = mem.nnn()._alias;
376  if( escs.test_recur(alias) ) return null;
377  // No other readers or writers. Expect the Call (or Join) and optionally DEFMEM
378  if( mem._uses._len>2 ) return null;
379  if( mem._uses._len==2 && mem._uses.find(Env.DEFMEM)==-1 ) return null; // Something other than DEFMEM
380 
381  // If call returns same as new (via recursion), cannot split, but CAN swap.
382  TypeMem tmcepi = (TypeMem) cepim._val;
383  BitsAlias esc_out = CallEpiNode.esc_out(tmcepi,cepid==null ? Type.XNIL : cepid._val);
384  BitsAlias escs2 = escs.meet(esc_out);
385  Node jn = mem();
386  if( !escs2.is_empty() && !esc_out.test_recur(alias) ) { // No return conflict, so parallelize memory
387  if( jn==mem ) // Bare Call/New; add a Split/Join.
388  return MemSplitNode.insert_split(cepim,escs2,this,mem,mem);
389  return null; // TODO: allow Call to move into existing JOIN
390  } else { // Else move New below Call.
391  if( jn!=mem ) { // Move New below Join
392  Node pre = mem.mem();
393  jn.set_def(i,pre);
394  mem.set_def(MEM_IDX,jn);
395  set_mem(mem);
396  Env.GVN.add_unuse(jn);
397  Env.GVN.add_unuse(mem);
398  }
399  return swap_new(cepim,mem); // Move New below Call
400  }
401  }
402 
403  // Swap a New and a Call, when we cannot use a Split/Join.
404  private Node swap_new(Node cepim, MrgProjNode mrg ) {
405  cepim.keep();
406  cepim.insert(mrg);
407  set_def(1,mrg.mem());
408  mrg.set_def(1,cepim.unkeep());
409  Env.GVN.revalive(mrg);
410  Env.GVN.add_flow_uses(mrg);
411  Env.GVN.add_flow(this);
412  Env.GVN.add_flow(cepim.in(0));
413  return this;
414  }
415 
416  // Pass thru all inputs directly - just a direct gather/scatter. The gather
417  // enforces SESE which in turn allows more precise memory and aliasing. The
418  // full scatter lets users decide the meaning; e.g. wired FunNodes will take
419  // the full arg set but if the call is not reachable the FunNode will not
420  // merge from that path. Result tuple type:
421  @Override public Type value(GVNGCM.Mode opt_mode) {
422  // Pinch to XCTRL/CTRL
423  Type ctl = ctl()._val;
424  if( ctl != Type.CTRL ) return ctl.oob();
425 
426  // Not a memory to the call?
427  Type mem = mem()==null ? TypeMem.ANYMEM : mem()._val;
428  TypeMem tmem = mem instanceof TypeMem ? (TypeMem)mem : TypeMem.ANYMEM;
429 
430  // Result type includes a type-per-input and an extra roll-up type of all
431  // escaping aliases.
432  final Type[] ts = Types.get(_defs._len+1);
433  ts[CTL_IDX] = Type.CTRL;
434  ts[MEM_IDX] = tmem; // Memory into the callee, not caller
435 
436  // Copy args for called functions. FIDX is refined below.
437  // Also gather all aliases from all args.
439  for( int i=DSP_IDX; i<nargs(); i++ )
440  as = as.meet(get_alias(ts[i] = arg(i)==null ? Type.XSCALAR : arg(i)._val));
441  // Recursively search memory for aliases; compute escaping aliases
442  BitsAlias as2 = tmem.all_reaching_aliases(as);
443  ts[_defs._len] = TypeMemPtr.make(as2,TypeObj.ISUSED); // Set escapes as last type
444  // Only pass along escaping aliases; others are not available to the call
445  // body. In the case of recursive calls, aliases made new in the body may
446  // not be passed into the recursive calls, and thus not into the call head
447  // and thus avoids self-merging. Once we decide to inline, keep the entire
448  // alias set since this filtering by the CallNode goes away as we inline.
449  if( !_is_copy ) ts[MEM_IDX] = tmem.slice_reaching_aliases(as2);
450 
451  // Not a function to call?
452  Type tfx = fdx()==null ? TypeFunPtr.GENERIC_FUNPTR : fdx()._val;
453  if( !(tfx instanceof TypeFunPtr) )
454  tfx = tfx.oob(TypeFunPtr.GENERIC_FUNPTR);
455  TypeFunPtr tfp = (TypeFunPtr)tfx;
456  BitsFun fidxs = tfp.fidxs();
457  if( _not_resolved_by_gcp && // If overloads not resolvable, then take them all and we are in-error
459  tfp = tfp.make_from(fidxs.dual()); // Force FIDXS low (take all), and we are in-error
460 
461  ts[_defs._len-1] = tfp; // FIDX is the last _def, 2nd-to-last type in ts
462 
463  return TypeTuple.make(ts);
464  }
465  // Get (shallow) aliases from the type
466  private BitsAlias get_alias( Type t ) {
467  if( t instanceof TypeMemPtr ) return ((TypeMemPtr)t)._aliases;
468  if( TypeMemPtr.OOP.isa(t) ) return BitsAlias.FULL;
469  return BitsAlias.EMPTY;
470  }
471 
472  @Override BitsAlias escapees() {
473  BitsAlias esc_in = tesc(_val)._aliases;
474  CallEpiNode cepi = cepi();
476  BitsAlias esc_out = CallEpiNode.esc_out((TypeMem)tcepi.at(1),tcepi.at(2));
477  TypeMem precall = (TypeMem) mem()._val;
478  BitsAlias esc_out2 = precall.and_unused(esc_out); // Filter by unused pre-call
479  return esc_out2.meet(esc_in);
480  }
481  @Override public void add_flow_extra(Type old) {
482  if( old==Type.ANY || _val==Type.ANY ||
483  (old instanceof TypeTuple && ttfp(old).above_center()) )
484  Env.GVN.add_flow_defs(this); // Args can be more-alive or more-dead
485  // If Call flips to being in-error, all incoming args forced live/escape
486  for( Node def : _defs )
487  if( def!=null && def._live!=TypeMem.ESCAPE && err(true)!=null )
488  Env.GVN.add_flow(def);
489  // If not resolved, might now resolve
490  if( _val instanceof TypeTuple && ttfp(_val)._fidxs.abit()==-1 )
491  Env.GVN.add_reduce(this);
492  }
493  @Override public void add_flow_def_extra(Node chg) {
494  // Projections live after a call alter liveness of incoming args
495  if( chg instanceof ProjNode )
496  Env.GVN.add_flow(in(((ProjNode)chg)._idx));
497  }
498  @Override public void add_flow_use_extra(Node chg) {
499  CallEpiNode cepi = cepi();
500  if( chg == fdx() ) { // FIDX falls to sane from too-high
501  Env.GVN.add_flow_defs(this); // All args become alive
502  if( cepi!=null ) {
503  Env.GVN.add_work_all(cepi); // FDX gets stable, might wire, might unify_lift
504  Env.GVN.add_flow_defs(cepi); // Wired Rets might no longer be alive (might unwire)
505  }
506  } else if( chg == mem() ) {
507  if( cepi != null ) Env.GVN.add_flow(cepi);
508  } else { // Args lifted, may resolve
509  if( fdx() instanceof UnresolvedNode )
510  Env.GVN.add_reduce(this);
511  if( Env.GVN._opt_mode._CG && err(true)==null )
512  Env.GVN.add_flow(mem()); // Call not-in-error, memory may lift
513  }
514  }
515 
516  // Compute live across uses. If pre-GCP, then we may not be wired and thus
517  // have not seen all possible function-body uses. Check for #FIDXs == nwired().
518  @Override public TypeMem live(GVNGCM.Mode opt_mode) {
519  if( !opt_mode._CG ) {
520  BitsFun fidxs = fidxs();
521  if( fidxs == null ) return TypeMem.ALLMEM; // Assume Something Good will yet happen
522  if( fidxs.above_center() ) return _live; // Got choices, dunno which one will stick
523  CallEpiNode cepi = cepi();
524  if( cepi==null ) return _live; // Collapsing
525  if( ctl()._val == Type.XCTRL ) return _live; // Unreachable
526  // Expand (actually fail) if any parents
527  BitSet bs = fidxs.tree().plus_kids(fidxs);
528  if( bs.cardinality() > cepi.nwired() ) // More things to call
529  return _live; // Cannot improve
530  }
531  // All choices discovered during GCP. If the call is in-error it may not
532  // resolve and so will have no uses other than the CallEpi - which is good
533  // enough to declare this live, so it exists for errors.
534  return super.live(opt_mode);
535  }
536  @Override public TypeMem all_live() { return TypeMem.ALLMEM; }
537  @Override public TypeMem live_use(GVNGCM.Mode opt_mode, Node def ) {
538  if( def==fdx() ) { // Function argument
539  if( def instanceof ThretNode ) return TypeMem.ALLMEM; // Always inlines eagerly, so this is always temporary
540  if( !opt_mode._CG ) return TypeMem.ESCAPE; // Prior to GCP, assume all fptrs are alive and display escapes
541  // During GCP, unresolved calls might resolve & remove this use. Keep dead till resolve fails.
542  // If we have a fidx directly, use it more precisely.
543  int dfidx = def instanceof FunPtrNode ? ((FunPtrNode)def).ret()._fidx : -1;
544  return live_use_call(dfidx);
545  }
546  if( def==ctl() ) return TypeMem.ALIVE;
547  if( def!=mem() ) { // Some argument
548  // Check that all fidxs are wired; an unwired fidx might be in-error
549  // and we want the argument alive for errors. This is a value turn-
550  // around point (high fidxs need to fall)
551 
552  // Pre GCP, might not wire (yet), assume fully used by unwired valid fcn
553  // target, so ESCAPE.
554 
555  // 1st GCP, wiring appears over time, if not wired assume it will be and
556  // do the optimistic proj test.
557 
558  // Post GCP, if not wired, then Call is in error, so ESCAPE.
559  if( opt_mode._CG && _val==Type.ANY ) return TypeMem.DEAD;
560  if( opt_mode._CG && // Either mid-GCP or post-GCP
561  (def==dsp() || // Display is not a user-visible arg, so if unused can go away
562  (err(true)==null && // Not in-error
563  // And fully wired (no new users will wire)
564  (opt_mode==GVNGCM.Mode.Opto || all_fcns_wired()) )) ) {
565  int argn = _defs.find(def);
566  ProjNode proj = ProjNode.proj(this, argn);
567  if( proj == null || proj._live == TypeMem.DEAD )
568  return TypeMem.DEAD; // Arg not used
569  }
570  if( def instanceof ThretNode ) return TypeMem.ALLMEM;
571  assert def.all_live().basic_live();
572  return TypeMem.ESCAPE; // Args always alive and escape
573  }
574 
575  // After we have the exact callers, use liveness directly. True if we have
576  // the Call Graph, or the callers are known directly. If the call is
577  // in-error, act as-if we do not known the Call Graph.
578  if( !(_val instanceof TypeTuple) ) // No type to sharpen
579  return _val.oob(TypeMem.ALLMEM);
580  if( opt_mode._CG || fdx() instanceof FunPtrNode ) // All callers known
581  return err(true)==null ? _live : TypeMem.ALLMEM; // Use live directly (unless in error)
582 
583  // Unknown future callees act as-if all available aliases are read from and
584  // thus live.
585  BitsAlias aliases = BitsAlias.EMPTY;
586  for( int i=DSP_IDX; i<nargs(); i++ ) {
587  Type targ = targ(_val,i);
588  if( TypeMemPtr.OOP.isa(targ) )
589  { aliases=BitsAlias.FULL; break; } // All possible pointers, so all memory is alive
590  if( !(targ instanceof TypeMemPtr) ) continue; // Not a pointer, does not need memory to sharpen
591  if( targ.above_center() ) continue; // Have infinite choices still, no memory
592  aliases = aliases.meet(((TypeMemPtr)targ)._aliases);
593  }
594  // Conservative too strong; need only memories that go as deep as the
595  // formal types.
596  TypeMem caller_mem = emem(_val);
597  TypeMem tmem2 = caller_mem.slice_reaching_aliases(caller_mem.all_reaching_aliases(aliases));
598  return (TypeMem)tmem2.meet(_live);
599  }
600 
601  private boolean all_fcns_wired() {
602  BitsFun fidxs = fidxs();
603  if( _is_copy || fidxs==null ) return true;
604  CallEpiNode cepi = cepi();
605  return cepi != null && fidxs.bitCount() <= cepi.nwired();
606  }
607 
608  TypeMem live_use_call( int dfidx ) {
609  Type tcall = _val;
610  if( !(tcall instanceof TypeTuple) )
611  return tcall.above_center() ? TypeMem.DEAD : TypeMem.LNO_DISP;
612  TypeFunPtr tfp = ttfp(tcall);
613  // If resolve has chosen this dfidx, then the FunPtr is alive.
614  BitsFun fidxs = tfp.fidxs();
615  if( fidxs.above_center() ) return TypeMem.DEAD; // Nothing above-center is chosen
616  if( dfidx != -1 && !fidxs.test_recur(dfidx) ) return TypeMem.DEAD; // Not in the fidx set.
617  if( tfp.is_con() && !(fdx() instanceof FunPtrNode) )
618  return TypeMem.DEAD; // Will be replaced by a constant
619  // Otherwise the FIDX is alive
620  return TypeMem.LNO_DISP;
621  }
622 
623  // Amongst these choices return the least-cost. Some or all might be invalid.
624  public FunPtrNode least_cost(BitsFun choices, Node unk) {
625  if( choices==BitsFun.EMPTY ) return null;
626  assert choices.bitCount() > 0; // Must be some choices
627  assert choices.abit()!= -1 || (choices.above_center() == (GVN._opt_mode==GVNGCM.Mode.Opto));
628  int best_cvts=99999; // Too expensive
629  FunPtrNode best_fptr=null; //
630  TypeTuple best_formals=null; //
631  boolean tied=false; // Ties not allowed
632  for( int fidx : choices ) {
633  // Parent/kids happen during inlining
634  for( int kidx=fidx; kidx!=0; kidx=BitsFun.next_kid(fidx,kidx) ) {
635  if( BitsFun.is_parent(kidx) )
636  continue;
637 
638  FunNode fun = FunNode.find_fidx(kidx);
639  if( fun.nargs()!=nargs() || fun.in(0)==fun ) continue; // BAD/dead
640  TypeTuple formals = fun._sig._formals; // Type of each argument
641  int cvts=0; // Arg conversion cost
642  for( int j=DSP_IDX; j<nargs(); j++ ) {
643  Type actual = arg(j)._val;
644  Type formal = formals.at(j);
645  if( actual==formal ) continue;
646  if( Type.ALL==formal ) continue; // Allows even error arguments
647  byte cvt = actual.isBitShape(formal); // +1 needs convert, 0 no-cost convert, -1 unknown, 99 never
648  if( cvt == -1 ) return null; // Might be the best choice, or only choice, dunno
649  cvts += cvt;
650  }
651 
652  if( cvts < best_cvts ) {
653  best_cvts = cvts;
654  best_fptr = get_fptr(fun,unk); // This can be null, if function is run-time computed & has multiple displays.
655  best_formals = formals;
656  tied=false;
657  } else if( cvts==best_cvts ) {
658  // Look for monotonic formals
659  int fcnt=0, bcnt=0;
660  for( int i=0; i<formals._ts.length; i++ ) {
661  Type ff = formals.at(i), bf = best_formals.at(i);
662  if( ff==bf ) continue;
663  Type mt = ff.meet(bf);
664  if( ff==mt ) bcnt++; // Best formal is higher than new
665  else if( bf==mt ) fcnt++; // New formal is higher than best
666  else { fcnt=bcnt=-1; break; } // Not monotonic, no obvious winner
667  }
668  // If one is monotonically higher than the other, take it
669  if( fcnt > 0 && bcnt==0 ) { best_fptr = get_fptr(fun,unk); best_formals = formals; }
670  else if( fcnt==0 && bcnt > 0 ) {} // Keep current
671  else tied=true; // Tied, ambiguous
672  }
673  }
674  }
675  if( best_cvts >= 99 ) return null; // No valid functions
676  return tied ? null : best_fptr; // Ties need to have the ambiguity broken another way
677  }
678  private static FunPtrNode get_fptr(FunNode fun, Node unk) {
679  RetNode ret = fun.ret();
680  FunPtrNode fptr = ret.funptr();
681  if( fptr != null ) return fptr; // Only one choice
682  if( !(unk instanceof UnresolvedNode) ) return null; // No selection of fptrs to pick from
683  for( Node def : unk._defs )
684  if( ((FunPtrNode)def).ret()== ret )
685  return (FunPtrNode)def;
686  return null;
687  }
688 
689  // Gather incoming args. NOT an application point (yet), that is a CallEpi.
690  //@Override public TV2 new_tvar(String alloc_site) { return TV2.make("Args",this,alloc_site,parms()); }
691 
692  //@Override public boolean unify( boolean test ) { assert tvar().isa("Args"); return false; }
693 
694  @Override public ErrMsg err( boolean fast ) {
695  // Fail for passed-in unknown references directly.
696  for( int j=ARG_IDX; j<nargs(); j++ )
697  if( arg(j)!=null && arg(j).is_forward_ref() )
698  return fast ? ErrMsg.FAST : ErrMsg.forward_ref(_badargs[j-ARG_IDX+1], FunNode.find_fidx(((FunPtrNode)arg(j)).ret()._fidx).fptr());
699  // Expect a function pointer
700  TypeFunPtr tfp = ttfpx(_val);
701  if( tfp==null ) {
702  if( fast ) return ErrMsg.FAST;
703  Type t = _val;
704  if( t instanceof TypeTuple ) t = ((TypeTuple)t).at(DSP_IDX);
705  return ErrMsg.unresolved(_badargs[0],"A function is being called, but "+t+" is not a function type");
706  }
707 
708  // Indirectly, forward-ref for function type
709  if( tfp.is_forward_ref() ) // Forward ref on incoming function
710  return fast ? ErrMsg.FAST : ErrMsg.forward_ref(_badargs[0], FunNode.find_fidx(tfp.fidx()).fptr());
711 
712  BitsFun fidxs = tfp.fidxs();
713  if( fidxs.above_center() ) return null; // Not resolved (yet)
714  // bad-arg-count
715  if( tfp._nargs != nargs() )
716  return fast ? ErrMsg.FAST : ErrMsg.syntax(_badargs[0],"Passing "+(nargs()-ARG_IDX)+" arguments to "+tfp.names(false)+" which takes "+(tfp._nargs-ARG_IDX)+" arguments");
717 
718  // Call did not resolve.
719  if( fidxs.is_empty() ) // This is an unresolved call
720  return fast ? ErrMsg.FAST : ErrMsg.unresolved(_badargs[0],"Unable to resolve call");
721 
722  // Also happens if more than one FIDX shares the same Unresolved.
723  // Basically means we did not clone enough to remove a choice amongst primitives.
724  // Bail out here if we see more than one Unresolved.
725  Node munr = null;
726  for( int fidx : fidxs ) { // All fidxs to Call
727  FunNode fun = FunNode.find_fidx(fidx);
728  if( fun==null || fun.is_dead() || fun.ret()==null ) continue; // No such function (probably dead and mid-cleanup)
729  outer:
730  for( Node fptrs : fun.ret()._uses ) // FunPtrs for each fidx (typically 1)
731  if( fptrs instanceof FunPtrNode )
732  for( Node unr : fptrs._uses ) // Unresolved behind each FunPtr (typically 1)
733  if( unr instanceof UnresolvedNode && // Unresolved includes fdxs in this Call FDX set?
734  unr._val instanceof TypeFunPtr &&
735  ((TypeFunPtr)(tfp.join(unr._val)))._fidxs.abit() == -1 ) {
736  if( munr == null || munr._val==unr._val ) { munr = unr; continue outer; }
737  return fast ? ErrMsg.FAST : ErrMsg.unresolved(_badargs[0],"Unable to resolve call");
738  }
739  }
740 
741  // Now do an arg-check. No more than 1 unresolved, so the error message is
742  // more sensible.
743  BitsFun.Tree<BitsFun> tree = fidxs.tree();
744  for( int j=ARG_IDX; j<nargs(); j++ ) {
745  Type actual = arg(j).sharptr(mem());
746  Ary<Type> ts=null;
747  for( int fidx : fidxs ) {
748  if( fidx==0 ) continue;
749  for( int kid=fidx; kid!=0; kid = tree.next_kid(fidx,kid) ) {
750  FunNode fun = FunNode.find_fidx(kid);
751  if( fun==null || fun.is_dead() ) continue;
752  TypeTuple formals = fun._sig._formals; // Type of each argument
753  if( fun.parm(j)==null ) continue; // Formal is dead
754  Type formal = formals.at(j);
755  if( actual.isa(formal) ) continue; // Actual is a formal
756  if( fast ) return ErrMsg.FAST; // Fail-fast
757  if( ts==null ) ts = new Ary<>(new Type[1],0);
758  if( ts.find(formal) == -1 ) // Dup filter
759  ts.push(formal); // Add broken type
760  }
761  }
762  if( ts!=null )
763  return ErrMsg.typerr(_badargs[j-ARG_IDX+1],actual, mem()._val,ts.asAry());
764  }
765 
766  return null;
767  }
768 
769  public CallEpiNode cepi() {
770  for( Node cepi : _uses ) // Find CallEpi for bypass aliases
771  if( cepi instanceof CallEpiNode )
772  return (CallEpiNode)cepi;
773  return null;
774  }
775  @Override public Node is_copy(int idx) { return _is_copy ? (_val==Type.ANY ? Env.ANY : in(idx)) : null; }
776  void set_rpc(int rpc) { unelock(); _rpc=rpc; } // Unlock before changing hash
777  @Override public int hashCode() { return super.hashCode()+_rpc; }
778  @Override public boolean equals(Object o) {
779  if( this==o ) return true;
780  if( !super.equals(o) ) return false;
781  if( !(o instanceof CallNode) ) return false;
782  CallNode call = (CallNode)o;
783  return _rpc==call._rpc;
784  }
785  @Override Node is_pure_call() { return fdx().is_pure_call()==null ? null : mem(); }
786  public Node[] parms() {
787  return _defs._len>= DSP_IDX ? Arrays.copyOf(_defs._es,_defs._len-1) : new Node[0]; // All defs, except the FIDX.
788  }
789 }
com.cliffc.aa.type.Bits.dual
B dual()
Definition: Bits.java:368
com.cliffc.aa.type.BitsAlias.FULL
static BitsAlias FULL
Definition: BitsAlias.java:27
com.cliffc.aa.node.CallNode.live_use_call
TypeMem live_use_call(int dfidx)
Definition: CallNode.java:608
com.cliffc.aa.node.CallNode.copy
CallNode copy(boolean copy_edges)
Definition: CallNode.java:176
com.cliffc.aa.type.TypeTuple.set
TypeTuple set(int idx, Type t)
Definition: TypeTuple.java:186
com.cliffc.aa.node.CallNode.hashCode
int hashCode()
Definition: CallNode.java:777
com.cliffc.aa.node.CallNode.set_mem
void set_mem(Node mem)
Definition: CallNode.java:131
com.cliffc.aa.type.TypeMemPtr.NO_DISP
static final Type NO_DISP
Definition: TypeMemPtr.java:80
com.cliffc.aa.type.BitsRPC.ALL
static final int ALL
Definition: BitsRPC.java:25
com.cliffc.aa.node.CallNode._unpacked
boolean _unpacked
Definition: CallNode.java:88
com.cliffc.aa.type.BitsFun.EMPTY
static final BitsFun EMPTY
Definition: BitsFun.java:37
com.cliffc.aa.GVNGCM.add_unuse
Node add_unuse(Node n)
Definition: GVNGCM.java:59
com.cliffc.aa.node.MrgProjNode.mem
Node mem()
Definition: MrgProjNode.java:15
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.ThretNode
Definition: ThretNode.java:14
com.cliffc.aa.util.Ary.push
E push(E e)
Add element in amortized constant time.
Definition: Ary.java:58
com.cliffc.aa.type.TypeFunPtr._nargs
int _nargs
Definition: TypeFunPtr.java:27
com.cliffc.aa.type.TypeRPC.make
static TypeRPC make(BitsRPC rpcs)
Definition: TypeRPC.java:25
com.cliffc.aa.type.Type.isa
boolean isa(Type t)
Definition: Type.java:623
com.cliffc.aa.node.CallNode.cepi
CallEpiNode cepi()
Definition: CallNode.java:769
com.cliffc.aa.node.CallNode.mem
Node mem()
Definition: CallNode.java:119
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.type.Type.join
Type join(Type t)
Definition: Type.java:619
com.cliffc.aa.node.Node.len
int len()
Definition: Node.java:125
com.cliffc.aa.type.TypeMem.XMEM
static final TypeMem XMEM
Definition: TypeMem.java:225
com.cliffc.aa.type.TypeMemPtr.OOP
static final TypeMemPtr OOP
Definition: TypeMemPtr.java:94
com.cliffc.aa.node.Node._live
TypeMem _live
Definition: Node.java:89
com.cliffc.aa.node.CallNode.is_copy
Node is_copy(int idx)
Definition: CallNode.java:775
com.cliffc.aa.GVNGCM.add_flow_uses
void add_flow_uses(Node n)
Definition: GVNGCM.java:55
com.cliffc
com.cliffc.aa.node.CallNode.ideal_grow
Node ideal_grow()
Definition: CallNode.java:340
com.cliffc.aa.node.CallNode._is_copy
boolean _is_copy
Definition: CallNode.java:89
com.cliffc.aa.node.CallNode.get_alias
BitsAlias get_alias(Type t)
Definition: CallNode.java:466
com.cliffc.aa.type.Type.XSCALAR
static final Type XSCALAR
Definition: Type.java:329
com.cliffc.aa.node.Node
Definition: Node.java:16
com.cliffc.aa.node.CallNode.live
TypeMem live(GVNGCM.Mode opt_mode)
Definition: CallNode.java:518
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.UnOrFunPtrNode
Definition: UnOrFunPtrNode.java:6
com.cliffc.aa.type.TypeFunPtr.GENERIC_FUNPTR
static final TypeFunPtr GENERIC_FUNPTR
Definition: TypeFunPtr.java:80
com.cliffc.aa.type.TypeMem.ESCAPE
static final TypeMem ESCAPE
Definition: TypeMem.java:227
com.cliffc.aa.node.CallNode.is_mem
boolean is_mem()
Definition: CallNode.java:106
com.cliffc.aa.node.FP2DispNode
Definition: FP2DispNode.java:7
com.cliffc.aa.GVNGCM.add_work_all
Node add_work_all(Node n)
Definition: GVNGCM.java:73
com.cliffc.aa.type.Type
an implementation of language AA
Definition: Type.java:94
com.cliffc.aa.node.MemJoinNode
Definition: MemJoinNode.java:15
com.cliffc.aa.util.Ary
Definition: Ary.java:11
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.CallNode.add_flow_extra
void add_flow_extra(Type old)
Definition: CallNode.java:481
com.cliffc.aa.GVNGCM.revalive
void revalive(Node... ns)
Definition: GVNGCM.java:103
com.cliffc.aa.type.TypeTuple
Definition: TypeTuple.java:11
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.type.TypeFunPtr._fidxs
BitsFun _fidxs
Definition: TypeFunPtr.java:26
com.cliffc.aa.node.Node.unelock
void unelock()
Definition: Node.java:128
com.cliffc.aa.node.CallNode.ttfpx
static TypeFunPtr ttfpx(Type tcall)
Definition: CallNode.java:162
com.cliffc.aa.type.TypeFunPtr.fidxs
BitsFun fidxs()
Definition: TypeFunPtr.java:127
com.cliffc.aa.GVNGCM.Mode._CG
final boolean _CG
Definition: GVNGCM.java:19
com.cliffc.aa.type.TypeMem.ALLMEM
static final TypeMem ALLMEM
Definition: TypeMem.java:228
com.cliffc.aa.type.BitsFun.tree
Tree< BitsFun > tree()
Definition: BitsFun.java:23
com.cliffc.aa.node.Node._val
Type _val
Definition: Node.java:88
com.cliffc.aa.type.Type.ANY
static final Type ANY
Definition: Type.java:325
com.cliffc.aa.node.Node.ErrMsg
Definition: Node.java:888
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.type.TypeLive.is_escape
boolean is_escape()
Definition: TypeLive.java:48
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.CallEpiNode.check_and_wire
boolean check_and_wire()
Definition: CallEpiNode.java:179
com.cliffc.aa.node.RetNode
Definition: RetNode.java:19
com.cliffc.aa.type.Bits.test_recur
boolean test_recur(int i)
Definition: Bits.java:232
com.cliffc.aa.node.CallNode
Definition: CallNode.java:86
com.cliffc.aa.type.Bits.test
static boolean test(long[] bits, int i)
Definition: Bits.java:224
com.cliffc.aa.node.Node.OP_CALL
static final byte OP_CALL
Definition: Node.java:17
com.cliffc.aa.type.TypeMem.ANYMEM
static final TypeMem ANYMEM
Definition: TypeMem.java:228
com.cliffc.aa.type.Types
Definition: Types.java:9
com.cliffc.aa.type.BitsRPC.new_rpc
static int new_rpc(int par)
Definition: BitsRPC.java:26
com.cliffc.aa.type.Type.ALL
static final Type ALL
Definition: Type.java:324
com.cliffc.aa.util.Ary.asAry
E[] asAry()
Definition: Ary.java:172
com.cliffc.aa.type.TypeFunPtr.is_forward_ref
boolean is_forward_ref()
Definition: TypeFunPtr.java:186
com.cliffc.aa.type.Bits.above_center
boolean above_center()
Definition: Bits.java:204
com.cliffc.aa.Env.GVN
static final GVNGCM GVN
Definition: Env.java:13
com.cliffc.aa.type.TypeMem.LNO_DISP
static final TypeMem LNO_DISP
Definition: TypeMem.java:226
com.cliffc.aa.type.TypeObj
Definition: TypeObj.java:15
com.cliffc.aa.type.Type.isBitShape
byte isBitShape(Type t)
Definition: Type.java:814
com.cliffc.aa.node.FunNode.fptr
FunPtrNode fptr()
Definition: FunNode.java:908
com.cliffc.aa.node.NewNode.def_idx
static int def_idx(int fld)
Definition: NewNode.java:52
com.cliffc.aa.node.Node.unkeep
public< N extends Node > N unkeep()
Definition: Node.java:232
com.cliffc.aa.node.CallNode.nargs
int nargs()
Definition: CallNode.java:125
com.cliffc.aa.type.TypeMem.and_unused
BitsAlias and_unused(BitsAlias escs)
Definition: TypeMem.java:498
com.cliffc.aa.type.BitsFun.is_parent
static boolean is_parent(int idx)
Definition: BitsFun.java:48
com.cliffc.aa.type.Type.above_center
boolean above_center()
Definition: Type.java:741
com.cliffc.aa.node.Node.ErrMsg.syntax
static ErrMsg syntax(Parse loc, String msg)
Definition: Node.java:900
com.cliffc.aa.node.Node.is_dead
boolean is_dead()
Definition: Node.java:820
com.cliffc.aa.type.TypeFunPtr.fidx
int fidx()
Definition: TypeFunPtr.java:128
com.cliffc.aa.type.TypeMem.live
TypeLive live()
Definition: TypeMem.java:559
com.cliffc.aa.node.CallNode._rpc
int _rpc
Definition: CallNode.java:87
com.cliffc.aa.node.NewNode.fld
Node fld(int fld)
Definition: NewNode.java:53
com.cliffc.aa.node.CallNode._ideal_grow
Node _ideal_grow(MrgProjNode mem, ProjNode cepim, ProjNode cepid, BitsAlias escs, int i)
Definition: CallNode.java:373
com.cliffc.aa.node.CallNode.parms
Node[] parms()
Definition: CallNode.java:786
com.cliffc.aa.node.CallNode._not_resolved_by_gcp
boolean _not_resolved_by_gcp
Definition: CallNode.java:90
com.cliffc.aa.node.RetNode._fidx
int _fidx
Definition: RetNode.java:20
com.cliffc.aa.node.Node._keep
byte _keep
Definition: Node.java:86
com.cliffc.aa.node.CallNode.escapees
BitsAlias escapees()
Definition: CallNode.java:472
com.cliffc.aa.node.ProjNode.proj
static ProjNode proj(Node head, int idx)
Definition: ProjNode.java:50
com.cliffc.aa.type.BitsRPC
Definition: BitsRPC.java:8
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.type.TypeTuple.len
int len()
Definition: TypeTuple.java:183
com.cliffc.aa.node.CallNode.add_flow_def_extra
void add_flow_def_extra(Node chg)
Definition: CallNode.java:493
com.cliffc.aa.node.FunNode.find_fidx
static FunNode find_fidx(int fidx)
Definition: FunNode.java:101
com.cliffc.aa.node.CallEpiNode.esc_out
static BitsAlias esc_out(TypeMem tmem, Type trez)
Definition: CallEpiNode.java:361
com.cliffc.aa.type.TypeMem.basic_live
boolean basic_live()
Definition: TypeMem.java:561
com.cliffc.aa.type.TypeObj.ISUSED
static final TypeObj ISUSED
Definition: TypeObj.java:45
com.cliffc.aa.node.Node.ErrMsg.FAST
static final ErrMsg FAST
Definition: Node.java:893
com.cliffc.aa.type.TypeTuple.make
static TypeTuple make(boolean any, Type[] ts)
Definition: TypeTuple.java:82
com.cliffc.aa.node.Node.in
Node in(int i)
Definition: Node.java:126
com.cliffc.aa.type.Types.get
Type[] get()
Definition: Types.java:66
com.cliffc.aa.type.TypeMem.ALIVE
static final TypeMem ALIVE
Definition: TypeMem.java:226
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.node.FreshNode
Definition: FreshNode.java:11
com.cliffc.aa.node.CallNode.fidxs
BitsFun fidxs()
Definition: CallNode.java:133
com.cliffc.aa.type.BitsAlias.EMPTY
static BitsAlias EMPTY
Definition: BitsAlias.java:27
com.cliffc.aa.node.ProjNode
Definition: ProjNode.java:11
com.cliffc.aa.node.FunPtrNode.ret
RetNode ret()
Definition: FunPtrNode.java:62
com.cliffc.aa.type.BitsFun
Definition: BitsFun.java:7
com.cliffc.aa.node.Node.insert
Node insert(int idx, Node n)
Definition: Node.java:165
com.cliffc.aa.node.CallNode.least_cost
FunPtrNode least_cost(BitsFun choices, Node unk)
Definition: CallNode.java:624
com.cliffc.aa.node.CallNode.ctl
Node ctl()
Definition: CallNode.java:118
com.cliffc.aa.node.CallNode.emem
static TypeMem emem(Type[] ts)
Definition: CallNode.java:150
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.FunNode.nargs
int nargs()
Definition: FunNode.java:190
com.cliffc.aa.node.CallNode.equals
boolean equals(Object o)
Definition: CallNode.java:778
com.cliffc.aa.AA
an implementation of language AA
Definition: AA.java:9
com.cliffc.aa.type.Bits.bitCount
int bitCount()
Definition: Bits.java:113
com.cliffc.aa.node.CallNode.str
String str()
Definition: CallNode.java:105
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.node.NewNode
Definition: NewNode.java:17
com.cliffc.aa.node.CallNode.all_fcns_wired
boolean all_fcns_wired()
Definition: CallNode.java:601
com.cliffc.aa.node.FunNode._sig
TypeFunSig _sig
Definition: FunNode.java:62
com.cliffc.aa.node.CallNode.add_flow_use_extra
void add_flow_use_extra(Node chg)
Definition: CallNode.java:498
com.cliffc.aa.node.CallNode.set_arg
Node set_arg(int idx, Node arg)
Definition: CallNode.java:129
com.cliffc.aa.node.MrgProjNode
Definition: MrgProjNode.java:10
com.cliffc.aa.node.Node.is_forward_ref
boolean is_forward_ref()
Definition: Node.java:830
com.cliffc.aa.type.Bits.abit
int abit()
Definition: Bits.java:203
com.cliffc.aa.node.CallEpiNode.nwired
int nwired()
Definition: CallEpiNode.java:37
com.cliffc.aa.node.CallNode.ttfp
static TypeFunPtr ttfp(Type tcall)
Definition: CallNode.java:157
com.cliffc.aa.type.TypeMemPtr._aliases
BitsAlias _aliases
Definition: TypeMemPtr.java:16
com.cliffc.aa.type.TypeTuple.at
Type at(int idx)
Definition: TypeTuple.java:182
com.cliffc.aa.node.Node.set_def
Node set_def(int idx, Node n)
Definition: Node.java:154
com.cliffc.aa.node.CallNode.targ
static Type targ(Type[] ts, int x)
Definition: CallNode.java:170
com.cliffc.aa.type.TypeTuple.CALLE
static final TypeTuple CALLE
Definition: TypeTuple.java:131
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.type.Type.dual
final T dual()
Definition: Type.java:361
com.cliffc.aa.node.CallEpiNode
Definition: CallEpiNode.java:24
com.cliffc.aa.node.FunNode.parm
ParmNode parm(int idx)
Definition: FunNode.java:887
com.cliffc.aa.node.CallNode.tctl
static Type tctl(Type tcall)
Definition: CallNode.java:148
com.cliffc.aa.type.BitsFun.next_kid
static int next_kid(int alias, int kid)
Definition: BitsFun.java:52
com.cliffc.aa.node.MemSplitNode
Definition: MemSplitNode.java:19
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.type.TypeRPC
Definition: TypeRPC.java:7
com.cliffc.aa.node.CallNode.xstr
String xstr()
Definition: CallNode.java:104
com.cliffc.aa.type.Type.oob
Type oob()
Definition: Type.java:635
com.cliffc.aa.type.TypeMem.all_reaching_aliases
BitsAlias all_reaching_aliases(BitsAlias aliases)
Definition: TypeMem.java:349
com.cliffc.aa.node.CallNode.get_fptr
static FunPtrNode get_fptr(FunNode fun, Node unk)
Definition: CallNode.java:678
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.type.TypeTuple._ts
Type[] _ts
Definition: TypeTuple.java:13
com.cliffc.aa.GVNGCM._opt_mode
Mode _opt_mode
Definition: GVNGCM.java:22
com.cliffc.aa.type.Type.XNIL
static final Type XNIL
Definition: Type.java:333
com.cliffc.aa.type.TypeFunPtr.names
String names(boolean debug)
Definition: TypeFunPtr.java:64
com.cliffc.aa.node.CallNode.swap_new
Node swap_new(Node cepim, MrgProjNode mrg)
Definition: CallNode.java:404
com.cliffc.aa.node.CallNode.live_use
TypeMem live_use(GVNGCM.Mode opt_mode, Node def)
Definition: CallNode.java:537
com.cliffc.aa.node.Node.pop
Node pop()
Definition: Node.java:174
com.cliffc.aa.GVNGCM.add_flow
public< N extends Node > N add_flow(N n)
Definition: GVNGCM.java:50
com.cliffc.aa.node.CallNode.set_fdx
Node set_fdx(Node fun)
Definition: CallNode.java:132
com.cliffc.aa.node.RetNode.funptr
FunPtrNode funptr()
Definition: RetNode.java:37
com.cliffc.aa.node.CallNode.targ
static Type targ(Type tcall, int x)
Definition: CallNode.java:169
com.cliffc.aa.node.CallNode.set_dsp
Node set_dsp(Node dsp)
Definition: CallNode.java:130
com.cliffc.aa.util.Ary.find
int find(E e)
Find the first matching element using ==, or -1 if none.
Definition: Ary.java:192
com.cliffc.aa.node.CallNode.set_ttfp
static TypeTuple set_ttfp(TypeTuple tcall, TypeFunPtr nfptr)
Definition: CallNode.java:168
com.cliffc.aa.node.CallNode.arg
Node arg(int x)
Definition: CallNode.java:127
com.cliffc.aa.node.FunNode
Definition: FunNode.java:58
com.cliffc.aa.type.Bits.meet
B meet(final B bs)
Definition: Bits.java:298
com.cliffc.aa.node.FunPtrNode.display
Node display()
Definition: FunPtrNode.java:63
com.cliffc.aa.node.CallNode.fdx
Node fdx()
Definition: CallNode.java:121
com.cliffc.aa.node.CallNode._badargs
Parse[] _badargs
Definition: CallNode.java:94
com.cliffc.aa.node.Node.ErrMsg.forward_ref
static ErrMsg forward_ref(Parse loc, FunPtrNode fun)
Definition: Node.java:896
com.cliffc.aa.node.CallNode.is_pure_call
Node is_pure_call()
Definition: CallNode.java:785
com.cliffc.aa.Env.ANY
static ConNode ANY
Definition: Env.java:24
com.cliffc.aa.node.CallNode.add_reduce_extra
void add_reduce_extra()
Definition: CallNode.java:331
com
com.cliffc.aa.node.CallNode.err
ErrMsg err(boolean fast)
Definition: CallNode.java:694
com.cliffc.aa.node.CallNode.ideal_reduce
Node ideal_reduce()
Definition: CallNode.java:188
com.cliffc.aa.node.CallNode.CallNode
CallNode(boolean unpacked, Parse[] badargs, Node... defs)
Definition: CallNode.java:95
com.cliffc.aa.Env.DEFMEM
static DefMemNode DEFMEM
Definition: Env.java:19
com.cliffc.aa.node.MemSplitNode.insert_split
static Node insert_split(Node tail1, BitsAlias head1_escs, Node head1, Node tail2, Node head2)
Definition: MemSplitNode.java:142
com.cliffc.aa.type.TypeFunPtr.is_con
boolean is_con()
Definition: TypeFunPtr.java:136
com.cliffc.aa.Env
Definition: Env.java:12
com.cliffc.aa.node.CallNode.set_rpc
void set_rpc(int rpc)
Definition: CallNode.java:776
com.cliffc.aa.type
Definition: Bits.java:1
com.cliffc.aa.node.Node._defs
Ary< Node > _defs
Definition: Node.java:124
com.cliffc.aa.node.CallNode.all_live
TypeMem all_live()
Definition: CallNode.java:536
com.cliffc.aa.type.TypeMemPtr
Definition: TypeMemPtr.java:14
com.cliffc.aa.Parse
an implementation of language AA
Definition: Parse.java:68
com.cliffc.aa.type.TypeMem.slice_reaching_aliases
TypeMem slice_reaching_aliases(BitsAlias aliases)
Definition: TypeMem.java:392
com.cliffc.aa.node.CallNode.emem
static TypeMem emem(Type tcall)
Definition: CallNode.java:149
com.cliffc.aa.node.FunNode.ret
RetNode ret()
Definition: FunNode.java:900
com.cliffc.aa.GVNGCM.Mode
Definition: GVNGCM.java:14
com.cliffc.aa.type.TypeFunSig._formals
TypeTuple _formals
Definition: TypeFunSig.java:15
com.cliffc.aa.node.CallNode.dsp
Node dsp()
Definition: CallNode.java:120
com.cliffc.aa.node.CallNode.tesc
static TypeMemPtr tesc(Type tcall)
Definition: CallNode.java:151
com.cliffc.aa.type.Bits.is_empty
boolean is_empty()
Definition: Bits.java:207
com.cliffc.aa.type.TypeFunPtr.make_from
TypeFunPtr make_from(TypeMemPtr disp)
Definition: TypeFunPtr.java:75
com.cliffc.aa.node.CallNode.value
Type value(GVNGCM.Mode opt_mode)
Definition: CallNode.java:421
com.cliffc.aa.type.TypeMemPtr.make
static TypeMemPtr make(BitsAlias aliases, TypeObj obj)
Definition: TypeMemPtr.java:66