aa
MemJoinNode.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.tvar.TV2;
6 import com.cliffc.aa.type.*;
7 import com.cliffc.aa.util.Ary;
8 
9 import static com.cliffc.aa.AA.MEM_IDX;
10 import static com.cliffc.aa.Env.GVN;
11 
12 // Join a split set of aliases from a SESE region, split by an earlier MemSplit.
13 // This allows more precision in the SESE that may otherwise merge many paths
14 // in and out, and is especially targeting non-inlined calls.
15 public class MemJoinNode extends Node {
16 
17  public MemJoinNode( MProjNode mprj ) { super(OP_JOIN,mprj); assert mprj.in(0) instanceof MemSplitNode; }
18 
19  MemSplitNode msp() { // The MemSplit
20  Node n = in(0).in(0);
21  return n instanceof MemSplitNode ? (MemSplitNode)n : null;
22  }
23  @Override public boolean is_mem() { return true; }
24 
25  @Override public Node ideal_reduce() {
26  MemSplitNode msp = msp();
27  // If the split count is lower than 2, then the split serves no purpose
28  if( _defs._len == 2 && val(1).isa(_val) && _keep==0 ) {
29  msp._is_copy=true;
30  GVNGCM.retype_mem(null,msp(),in(1), false);
31  for( Node use : msp()._uses ) GVN.add_reduce(use);
32  return in(1); // Just become the last split
33  }
34 
35  // If some Split/Join path clears out, remove the (useless) split.
36  for( int i=1; i<_defs._len; i++ )
37  if( in(i) instanceof MProjNode && in(i).in(0)==msp && in(i)._uses._len==1 ) {
38  in(0).xval(); // Update the default type
39  msp.remove_alias(i);
40  GVN.add_dead(in(i));
41  return remove(i);
42  }
43 
44  return null;
45  }
46  @Override public void add_flow_def_extra(Node chg) {
47  if( _uses._len==1 ) {
48  Node u = _uses.at(0);
49  if( u instanceof StoreNode ||
50  u instanceof MrgProjNode )
51  GVN.add_reduce(u);
52  }
53  }
54 
55  @Override public Node ideal_mono() {
56  // If the Split memory has an obvious SESE region, move it into the Split
57  MemSplitNode msp = msp();
58  if( msp==null ) return null; // During cleanout of dead code
59  Node mem = msp.mem();
60  if( !mem.is_prim() && mem.check_solo_mem_writer(msp) ) { // Split is only memory writer after mem
61  Node head = find_sese_head(mem); // Find head of SESE region
62  if( head instanceof MemSplitNode ) // Back to back split/join combo
63  return combine_splits((MemSplitNode)head);
64  if( head != null && head.in(1).check_solo_mem_writer(head) ) // Head is the only writer after the above-head
65  // Move from Split.mem() to head inside the split/join area
66  return add_alias_above(head);
67  }
68  return null;
69  }
70 
71 
72  static Node find_sese_head(Node mem) {
73  if( mem instanceof MemJoinNode ) return ((MemJoinNode)mem).msp(); // Merge Split with prior Join
74  if( mem instanceof StoreNode ) return mem; // Move Store into Split/Join
75  if( mem instanceof MemPrimNode.LValueWrite ) return mem; // Array store
76  if( mem instanceof MProjNode ) {
77  Node head = mem.in(0);
78  if( head instanceof CallNode ) return null; // Do not swallow a Call/CallEpi into a Split/Join
79  if( head instanceof CallEpiNode ) return null; // Do not swallow a Call/CallEpi into a Split/Join
80  if( head instanceof MemSplitNode ) return null; // TODO: Handle back-to-back split/join/split/join
81  throw com.cliffc.aa.AA.unimpl(); // Break out another SESE split
82  }
83  if( mem instanceof MrgProjNode ) return mem;
84  if( mem instanceof ParmNode ) return null;
85  if( mem instanceof PhiNode ) return null;
86  if( mem instanceof StartMemNode ) return null;
87  if( mem instanceof ConNode ) return null;
88  throw com.cliffc.aa.AA.unimpl(); // Break out another SESE split
89  }
90 
91  // Move one escape set from the lower Split/Join to the upper.
92  private Node combine_splits( MemSplitNode head ) {
93  MemSplitNode msp = msp();
94  MemJoinNode mjn = (MemJoinNode)msp.mem();
95  if( _defs._len==1 ) return null; // Nothing to move
96  if( true )
97  // TODO: Fails right now because types get OOO when removing a Split/Join
98 
99  // TODO: Perhaps: upon moving a SESE region into the Split/Join,
100  // immediately the Split types the 'other' aliases as "use" (ISUSED),
101  // i.e. low as possible. Later optimizations that lift these nodes (such
102  // as when the Split/Join optimizes away) then only lifts types.
103  return null;
104 
105  // Get the escaping set being moved.
106  // Remove esc set from lower rollup and add to upper
107  BitsAlias esc = msp._escs.pop();
108  msp._escs.set(0,(BitsAlias)msp._escs.at(0).subtract(esc));
109  int idx = head.add_alias(esc);
110  assert idx!=0; // No partial overlaps; actually we could just legit bail here, no assert
111  if( idx == mjn._defs._len ) // Add edge Join->Split as needed
112  mjn.add_def(GVN.xform(new MProjNode(head,idx))); // Add a new MProj from MemSplit
113  // Move SESE region from lower Split/Join to upper Split/Join
115  prj.subsume(mjn.in(idx));
116  mjn.set_def(idx,in(_defs._len-1));
117  remove(_defs._len-1);
118 
119  // Moving this can *lower* the upper Join type, if an allocation moves up.
120  Type tt = mjn.xval();
121  msp.xval();
122  for( Node use : msp._uses )
123  use._val = tt;
124 
125  return this;
126  }
127 
128  @Override public Type value(GVNGCM.Mode opt_mode) {
129  MemSplitNode msp = msp();
130  if( msp==null ) return TypeMem.ANYMEM;
131 
132  // Gather all memories
133  boolean diff=false;
134  TypeMem[] mems = new TypeMem[_defs._len];
135  for( int i=0; i<_defs._len; i++ ) {
136  Type t = val(i);
137  if( t == Type.ANY ) t = TypeMem.ANYMEM;
138  if( t == Type.ALL ) t = TypeMem.ALLMEM;
139  if( !(t instanceof TypeMem) ) return t.oob(TypeMem.ALLMEM);
140  mems[i] = (TypeMem)t;
141  if( i>0 && !diff ) diff = mems[i]!=mems[0];
142  }
143  if( !diff ) return mems[0]; // All memories the same
144 
145  // Walk all aliases and take from matching escape set in the Split. Since
146  // nothing overlaps this is unambiguous.
147  Ary<BitsAlias> escs = msp()._escs;
148  TypeObj[] pubs = new TypeObj[Env.DEFMEM._defs._len];
149  for( int alias=1, i; alias<Env.DEFMEM._defs._len; alias++ ) {
150  if( escs.at(0).test_recur(alias) ) { // In some RHS set
151  for( i=1; i<_defs._len; i++ )
152  if( escs.at(i).test_recur(alias) )
153  break;
154  } else i=0; // In the base memory
155  if( alias == 1 || Env.DEFMEM.in(alias) != null ) // Check never-made aliases
156  pubs[alias] = mems[i].at(alias); // Merge alias
157  }
158  return TypeMem.make0(pubs);
159  }
160  @Override public TypeMem all_live() { return TypeMem.ALLMEM; }
161 
162  @Override public TypeMem live_use( GVNGCM.Mode opt_mode, Node def ) { return _live; }
163  @Override public TypeMem live( GVNGCM.Mode opt_mode ) {
164  if( _keep>0 ) return _live;
165  return super.live(opt_mode);
166  }
167 
168  // Unify alias-by-alias, except on the alias sets
169  @Override public boolean unify( boolean test ) {
170  MemSplitNode msp = msp();
171  if( msp==null ) return false;
172  TV2 tmem = tvar(0);
173  boolean progress = tvar().unify(tmem,test);
174  if( progress && test ) return true;
175  Ary<BitsAlias> escs = msp()._escs;
176  for( int i=1; i<_defs._len; i++ ) {
177  if( !tvar(i).isa("Mem") ) continue; // TODO: Unify anyways, forces faster progress
178  progress |= tmem.unify_alias(escs.at(i),tvar(i),test);
179  if( progress && test ) return true;
180  }
181  return progress;
182  }
183 
184  // Move the given SESE region just ahead of the split into the join/split
185  // area. The head node has the escape-set.
187  MemSplitNode msp = msp();
188  Node base = msp.mem(); // Base of SESE region
189  assert base.check_solo_mem_writer(msp); // msp is only memory writer after base
190  assert head.in(1).check_solo_mem_writer(head); // head is the 1 memory writer after head.in
191  try( GVNGCM.Build<MemJoinNode> X = GVN.new Build<>() ) {
192  int idx = msp.add_alias(head.escapees()); // Add escape set, find index
193  Node mprj;
194  if( idx == _defs._len ) { // Escape set added at the end
195  add_def(mprj = X.xform(new MProjNode(msp,idx))); // Add a new MProj from MemSplit
196  } else {
197  assert idx!=0; // No partial overlap; all escape sets are independent
198  mprj = ProjNode.proj(msp,idx); // Find match MProj
199  }
200  // Resort edges to move SESE region inside
201  msp.set_def(1,head.in(1)); // Move Split->base edge to Split->head.in(1)
202  mprj.insert(base); // Move split mprj users to base
203  head.set_def(1,mprj); // Move head->head.in(1) to head->MProj
204  X.add(msp);
205  X.add(mprj);
206  X.add(base);
207  X.add(head);
208  base.unkeep(); mprj.unkeep();
209  GVN.revalive(mprj,base);
210  base.keep(); mprj.keep();
211  return (X._ret=this);
212  }
213  }
214 
215  // Move the given SESE region just behind of the join into the join/split
216  // area. The head node has the escape-set.
217  void add_alias_below( Node head, BitsAlias head1_escs, Node base ) {
218  assert head.is_mem() && base.is_mem();
219  GVN.add_unuse(this);
220  MemSplitNode msp = msp();
221  int idx = msp.add_alias(head1_escs); // Add escape set, find index
222  Node mspj;
223  if( idx == _defs._len ) { // Escape set added at the end
224  add_def(mspj = GVN.init(new MProjNode(msp,idx)).unkeep(2));
225  mspj._tvar = msp.mem().tvar(); // Need to upgrade tvar to a TMem
226  } else { // Inserted into prior region
227  mspj = in(idx);
228  assert idx!=0; // No partial overlap; all escape sets are independent
229  }
230  // Reset edges to move SESE region inside
231  head.set_def(MEM_IDX,in(idx));
232  base.insert(this);
233  set_def(idx,base);
234  // Move any accidental refs to DefMem back to base
235  int didx = Env.DEFMEM._defs.find(this);
236  if( didx != -1 ) Env.DEFMEM.set_def(didx,base);
237  GVN.revalive(mspj,head,base);
238  }
239 
241  old.keep(); // Called from inside old.ideal(), must keep alive until exit
242  add_alias_below(GVN.add_work_all(nnn),nnn.escapees(),nnn);
243  old.unkeep(); // Alive, but keep==0
244  nnn.xval(); xval(); // Force update, since not locally monotonic
245  GVN.add_flow_defs(this);
246  assert Env.START.more_flow(true)==0;
247  return this;
248  }
249 
250  // Find a compatible alias edge, including base memory if nothing overlaps.
251  // Return null for any partial overlaps.
253  Ary<BitsAlias> escs = msp()._escs;
254  if( escs.at(0).join(esc) == BitsAlias.EMPTY ) // No overlap with any other alias set
255  return msp().mem(); // Can completely bypass
256  // Overlaps with at least 1
257  for( int i=1; i<escs._len; i++ )
258  if( esc.isa(escs.at(i)) ) // Fully contained with alias set 'i'?
259  return in(i); // Can use this memory
260  return null; // Not fully contained within any 1 alias set
261  }
262  // Modifies all of memory
263  @Override BitsAlias escapees() { return BitsAlias.FULL; }
264 }
com.cliffc.aa.type.BitsAlias.FULL
static BitsAlias FULL
Definition: BitsAlias.java:27
com.cliffc.aa.node.MemSplitNode.remove_alias
void remove_alias(int idx)
Definition: MemSplitNode.java:96
com.cliffc.aa.util.Ary.at
E at(int i)
Definition: Ary.java:25
com.cliffc.aa.node.MemSplitNode.add_alias
int add_alias(BitsAlias esc)
Definition: MemSplitNode.java:82
com.cliffc.aa.tvar.TV2.unify
boolean unify(TV2 that, boolean test)
Definition: TV2.java:288
com.cliffc.aa.node.Node.escapees
BitsAlias escapees()
Definition: Node.java:859
com.cliffc.aa.node.MemPrimNode
Definition: MemPrimNode.java:10
com.cliffc.aa.node.MemSplitNode._is_copy
boolean _is_copy
Definition: MemSplitNode.java:21
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.node.Node._live
TypeMem _live
Definition: Node.java:89
com.cliffc
com.cliffc.aa.util.Ary.pop
E pop()
Definition: Ary.java:41
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.tvar
Definition: TV2.java:1
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.node.StoreNode
Definition: StoreNode.java:14
com.cliffc.aa.util.Ary
Definition: Ary.java:11
com.cliffc.aa.node.PhiNode
Definition: PhiNode.java:9
com.cliffc.aa.AA.MEM_IDX
static final int MEM_IDX
Definition: AA.java:14
com.cliffc.aa.type.BitsAlias
Definition: BitsAlias.java:8
com.cliffc.aa.node.Node.keep
public< N extends Node > N keep()
Definition: Node.java:228
com.cliffc.aa.util.Ary._len
int _len
Definition: Ary.java:13
com.cliffc.aa.type.TypeMem.ALLMEM
static final TypeMem ALLMEM
Definition: TypeMem.java:228
com.cliffc.aa.node.Node.OP_JOIN
static final byte OP_JOIN
Definition: Node.java:30
com.cliffc.aa.node.Node._val
Type _val
Definition: Node.java:88
com.cliffc.aa.node.StartMemNode
Definition: StartMemNode.java:8
com.cliffc.aa.type.Type.ANY
static final Type ANY
Definition: Type.java:325
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.MemJoinNode.add_alias_below
void add_alias_below(Node head, BitsAlias head1_escs, Node base)
Definition: MemJoinNode.java:217
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.MProjNode
Definition: MProjNode.java:10
com.cliffc.aa.type.TypeMem.ANYMEM
static final TypeMem ANYMEM
Definition: TypeMem.java:228
com.cliffc.aa.Env.START
static StartNode START
Definition: Env.java:14
com.cliffc.aa.node.MemJoinNode.ideal_reduce
Node ideal_reduce()
Definition: MemJoinNode.java:25
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.check_solo_mem_writer
boolean check_solo_mem_writer(Node memw)
Definition: Node.java:845
com.cliffc.aa.node.MemJoinNode.can_bypass
Node can_bypass(BitsAlias esc)
Definition: MemJoinNode.java:252
com.cliffc.aa.type.TypeMem.make0
static TypeMem make0(TypeObj[] as)
Definition: TypeMem.java:170
com.cliffc.aa.Env.GVN
static final GVNGCM GVN
Definition: Env.java:13
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.MemJoinNode.add_flow_def_extra
void add_flow_def_extra(Node chg)
Definition: MemJoinNode.java:46
com.cliffc.aa.node.MemJoinNode.live_use
TypeMem live_use(GVNGCM.Mode opt_mode, Node def)
Definition: MemJoinNode.java:162
com.cliffc.aa.node.MemJoinNode.msp
MemSplitNode msp()
Definition: MemJoinNode.java:19
com.cliffc.aa.node.MemJoinNode.unify
boolean unify(boolean test)
Definition: MemJoinNode.java:169
com.cliffc.aa.type.TypeMem.live
TypeLive live()
Definition: TypeMem.java:559
com.cliffc.aa.node.MemJoinNode.escapees
BitsAlias escapees()
Definition: MemJoinNode.java:263
com.cliffc.aa.node.Node._keep
byte _keep
Definition: Node.java:86
com.cliffc.aa.node.MemJoinNode.value
Type value(GVNGCM.Mode opt_mode)
Definition: MemJoinNode.java:128
com.cliffc.aa.node.ProjNode.proj
static ProjNode proj(Node head, int idx)
Definition: ProjNode.java:50
com.cliffc.aa.tvar.TV2.unify_alias
boolean unify_alias(BitsAlias aliases, TV2 mem, boolean test)
Definition: TV2.java:515
com.cliffc.aa.GVNGCM.retype_mem
static void retype_mem(BitSet aliases, Node mem, Node exit, boolean skip_calls)
Definition: GVNGCM.java:330
com.cliffc.aa.node.Node.in
Node in(int i)
Definition: Node.java:126
com.cliffc.aa.GVNGCM
Definition: GVNGCM.java:12
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.Node.insert
Node insert(int idx, Node n)
Definition: Node.java:165
com.cliffc.aa.node.MemSplitNode.mem
Node mem()
Definition: MemSplitNode.java:23
com.cliffc.aa.node.Node._uses
Ary< Node > _uses
Definition: Node.java:245
com.cliffc.aa.node.Node.is_mem
boolean is_mem()
Definition: Node.java:838
com.cliffc.aa.AA
an implementation of language AA
Definition: AA.java:9
com.cliffc.aa.node.Node.val
Type val(int idx)
Definition: Node.java:470
com.cliffc.aa.type.Bits.isa
boolean isa(B bs)
Definition: Bits.java:372
com.cliffc.aa
Definition: AA.java:1
com.cliffc.aa.node.MemSplitNode._escs
Ary< BitsAlias > _escs
Definition: MemSplitNode.java:20
com.cliffc.aa.node.MrgProjNode
Definition: MrgProjNode.java:10
com.cliffc.aa.node.MemJoinNode.add_alias_below_new
MemJoinNode add_alias_below_new(Node nnn, Node old)
Definition: MemJoinNode.java:240
com.cliffc.aa.node.MemJoinNode.add_alias_above
MemJoinNode add_alias_above(Node head)
Definition: MemJoinNode.java:186
com.cliffc.aa.node.MemJoinNode.ideal_mono
Node ideal_mono()
Definition: MemJoinNode.java:55
com.cliffc.aa.node.Node.set_def
Node set_def(int idx, Node n)
Definition: Node.java:154
com.cliffc.aa.node.CallEpiNode
Definition: CallEpiNode.java:24
com.cliffc.aa.node.ParmNode
Definition: ParmNode.java:14
com.cliffc.aa.tvar.TV2
Definition: TV2.java:23
com.cliffc.aa.node.MemSplitNode
Definition: MemSplitNode.java:19
com.cliffc.aa.node.MemJoinNode.is_mem
boolean is_mem()
Definition: MemJoinNode.java:23
com.cliffc.aa.type.Type.oob
Type oob()
Definition: Type.java:635
com.cliffc.aa.node.MemJoinNode.live
TypeMem live(GVNGCM.Mode opt_mode)
Definition: MemJoinNode.java:163
com.cliffc.aa.node.Node.xval
Type xval()
Definition: Node.java:460
com.cliffc.aa.node.MemJoinNode.combine_splits
Node combine_splits(MemSplitNode head)
Definition: MemJoinNode.java:92
com.cliffc.aa.GVNGCM.Build
Definition: GVNGCM.java:356
com.cliffc.aa.util.Ary.set
E set(int i, E e)
Set existing element.
Definition: Ary.java:133
com.cliffc.aa.node.MemJoinNode.all_live
TypeMem all_live()
Definition: MemJoinNode.java:160
com.cliffc.aa.node.Node._tvar
TV2 _tvar
Definition: Node.java:94
com.cliffc.aa.node.Node.tvar
TV2 tvar()
Definition: Node.java:96
com.cliffc.aa.node.MemJoinNode.find_sese_head
static Node find_sese_head(Node mem)
Definition: MemJoinNode.java:72
com
com.cliffc.aa.node.MemJoinNode.MemJoinNode
MemJoinNode(MProjNode mprj)
Definition: MemJoinNode.java:17
com.cliffc.aa.Env.DEFMEM
static DefMemNode DEFMEM
Definition: Env.java:19
com.cliffc.aa.type.TypeMem.at
TypeObj at(int alias)
Definition: TypeMem.java:135
com.cliffc.aa.Env
Definition: Env.java:12
com.cliffc.aa.type
Definition: Bits.java:1
com.cliffc.aa.node.MemPrimNode.LValueWrite
Definition: MemPrimNode.java:200
com.cliffc.aa.node.Node._defs
Ary< Node > _defs
Definition: Node.java:124
com.cliffc.aa.GVNGCM.Mode
Definition: GVNGCM.java:14