aa
MemSplitNode.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.type.*;
6 import com.cliffc.aa.tvar.*;
7 import com.cliffc.aa.util.Ary;
8 import com.cliffc.aa.util.SB;
9 import org.jetbrains.annotations.NotNull;
10 
11 import java.util.Arrays;
12 import java.util.BitSet;
13 
14 // TODO: Parse12 gen test, seeing many back-to-back identical split/join.
15 
16 // Split a set of aliases into a SESE region, to be joined by a later MemJoin.
17 // This allows more precision in the SESE that may otherwise merge many paths
18 // in and out, and is especially targeting non-inlined calls.
19 public class MemSplitNode extends Node {
21  boolean _is_copy; // Set by MemJoin as last split goes away
22  public MemSplitNode( Node mem ) { super(OP_SPLIT,null,mem); }
23  Node mem() { return in(1); }
24  public MemJoinNode join() {
25  Node prj = ProjNode.proj(this,0);
26  if( prj==null ) return null;
27  Node jn = prj._uses.at(0);
28  return jn instanceof MemJoinNode ? (MemJoinNode)jn : null;
29  }
30 
31  @Override public boolean is_mem() { return true; }
32  @Override String str() {
33  SB sb = new SB();
34  sb.p('(').p("base,");
35  for( int i=1; i<_escs._len; i++ )
36  _escs.at(i).str(sb).p(',');
37  return sb.unchar().p(')').toString();
38  }
39 
40  @Override public Type value(GVNGCM.Mode opt_mode) {
41  Type t = mem()._val;
42  if( !(t instanceof TypeMem) ) return t.oob();
43  TypeMem tmem = (TypeMem)t;
44  // Normal type is for an MProj of the input memory, one per alias class
45  Type[] ts = Types.get(_escs._len);
46  if( _is_copy ) Arrays.fill(ts,t);
47  else {
48  ts[0] = t;
49  for( int i=1; i<_escs._len; i++ )
50  ts[i] = tmem.slice_reaching_aliases(_escs.at(i));
51  }
52  return TypeTuple.make(ts);
53  }
54  @Override public TypeMem all_live() { return TypeMem.ALLMEM; }
55  @Override public void add_reduce_extra() {
56  Node join = join(); // MemSplit is dead, MemJoin changes value
57  if( join!=null ) Env.GVN.add_flow(join);
58  }
59 
60  @Override public boolean unify( boolean test ) {
61  TV2 tself = tvar();
62  if( tself.isa("SplitMem") ) {
63  assert tself._args.size()==_escs._len; // If changing the split-arity, need to reset_tvar
64  return false;
65  }
66  if( test ) return true;
67  Node[] parms = new Node[_escs._len];
68  Arrays.fill(parms,mem());
69  return tvar().unify(TV2.make("SplitMem",this,"unify",parms),test);
70  }
71 
72  // Find index for alias
73  int find_alias_index( int alias ) {
74  if( !_escs.at(0).test(alias) ) return 0; // Not in any set, so base
75  for( int i=1; i<_escs._len; i++ )
76  if( _escs.at(i).test(alias) )
77  return i;
78  throw com.cliffc.aa.AA.unimpl(); // Should be found
79  }
80 
81  // Find the escape set this esc set belongs to, or make a new one.
82  int add_alias( BitsAlias esc ) {
83  assert !esc.is_empty();
84  BitsAlias all = _escs.at(0); // Summary of Right Hand Side(s) escapes
85  if( all.join(esc) == BitsAlias.EMPTY ) { // No overlap
86  _escs.set(0,all.meet(esc)); // Update summary
87  _escs.add(esc); // Add escape set
88  xval(); // Expand val tuple result
89  return _escs._len-1;
90  }
91  for( int i=1; i<_escs._len; i++ )
92  if( esc.isa(_escs.at(i)) )
93  return i; // Found exact alias slice
94  return 0; // No match, partial overlap
95  }
96  void remove_alias( int idx ) {
97  // Remove (non-overlapping) bits from the rollup
98  _escs.set(0,(BitsAlias)_escs.at(0).subtract(_escs.at(idx)));
99  _escs.remove(idx); // Remove the escape set
100  xval(); // Reduce tuple result
101  // Renumber all trailing projections to match
102  for( Node use : _uses ) {
103  MProjNode mprj = (MProjNode)use;
104  if( mprj._idx > idx )
105  mprj.set_idx(mprj._idx-1);
106  }
107  }
108 
109  // A function body was cloned and all aliases split. The 'this' Split takes
110  // the first child and the clone takes the 2nd child.
111  void split_alias( Node copy, BitSet aliases ) {
113  for( int alias = aliases.nextSetBit(0); alias != -1; alias = aliases.nextSetBit(alias + 1)) {
114  int[] kid0_aliases = BitsAlias.get_kids(alias);
115  int newalias1 = kid0_aliases[1];
116  int newalias2 = kid0_aliases[2];
117  cmsp._update(alias,newalias1);
118  this._update(alias,newalias2);
119  }
120  }
121  // Replace the old alias with the new child alias
122  private void _update(int oldalias, int newalias) {
123  BitsAlias esc0 = _escs.at(0);
124  if( esc0.test(oldalias) ) {
125  _escs.set(0, esc0.set(newalias));
126  for( int i=1; i<_escs._len; i++ ) {
127  BitsAlias esc = _escs.at(i);
128  if( esc.test(oldalias) ) {
129  _escs.set(i, esc.set(newalias));
130  break;
131  }
132  }
133  }
134  }
135 
136  // Insert a Split/Join pair, moving the two stacked memory SESE regions
137  // side-by-side. If the SESE region is empty, the head & tail can be the
138  // same, which is true for e.g. StoreNodes & MrgNodes.
139  // tail1->{SESE#1}->head1->tail2->{SESE#2}->head2
140  // New/Mrg pairs are just the Mrg; the New is not part of the SESE region.
141  // Call/CallEpi pairs are: MProj->{CallEpi}->Call.
142  static Node insert_split(Node tail1, BitsAlias head1_escs, Node head1, Node tail2, Node head2) {
143  assert tail1.is_mem() && head1.is_mem() && tail2.is_mem() && head2.is_mem();
144  BitsAlias head2_escs = head2.escapees();
145  assert check_split(head1,head1_escs);
146  // Insert empty split/join above head2
147  MemSplitNode msp = Env.GVN.init(new MemSplitNode(head2.in(1))).unkeep(2);
148  MProjNode mprj= Env.GVN.init(new MProjNode (msp,0 )).unkeep(2);
149  MemJoinNode mjn = Env.GVN.init(new MemJoinNode (mprj ));
150  head2.set_def(1,mjn);
151  mjn._live = tail1._live;
152  // Pull the SESE regions in parallel from below
153  mjn.add_alias_below(head2,head2_escs,tail2);
154  mjn.add_alias_below(head1,head1_escs,tail1);
155  if( mprj.is_dead() ) Env.GVN.revalive(msp);
156  else Env.GVN.revalive(msp,mprj,mjn);
157  if( tail1 instanceof ProjNode ) Env.GVN.add_flow(tail1.in(0));
158  assert Env.START.more_flow(true)==0;
159  Env.GVN.add_mono(mjn); // See if other defs can move into the Join
160  for( Node use : mjn.unkeep(2)._uses )
161  Env.GVN.add_work_all(use); // See if other uses can move into the Join
162  return head1;
163  }
164 
165  static boolean check_split( Node head1, BitsAlias head1_escs ) { return check_split(head1,head1_escs,head1.in(1)); }
166  static boolean check_split( Node head1, BitsAlias head1_escs, Node tail2 ) {
167  // Must have only 1 mem-writer (this can fail if used by different control paths)
168  if( !tail2.check_solo_mem_writer(head1) ) return false;
169  // No alias overlaps
170  if( head1_escs.overlaps(tail2.escapees()) ) return false;
171  // TODO: This is too strong.
172  // Cannot have any Loads following head1; because after the split
173  // they will not see the effects of previous stores that also move
174  // into the split.
175  return (tail2._uses._len==1) ||
176  (tail2._uses._len==2 && tail2._uses.find(Env.DEFMEM)!= -1 );
177  }
178 
179 
180  //@SuppressWarnings("unchecked")
181  @Override @NotNull public MemSplitNode copy( boolean copy_edges) {
182  MemSplitNode nnn = (MemSplitNode)super.copy(copy_edges);
183  nnn._escs = _escs.deepCopy();
184  return nnn;
185  }
186  @Override public Node is_copy(int idx) {
187  if( _is_copy ) return mem();
188  //if( _uses._len==1 && _keep==0 ) return mem(); // Single user
189  return null;
190  }
191  // Modifies all of memory - just does it in parts
192  @Override BitsAlias escapees() { return BitsAlias.FULL; }
193 }
com.cliffc.aa.tvar.TV2._args
NonBlockingHashMap< Comparable, TV2 > _args
Definition: TV2.java:42
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.MemSplitNode.add_reduce_extra
void add_reduce_extra()
Definition: MemSplitNode.java:55
com.cliffc.aa.node.MemSplitNode.copy
MemSplitNode copy(boolean copy_edges)
Definition: MemSplitNode.java:181
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.GVNGCM.add_mono
public< N extends Node > N add_mono(N n)
Definition: GVNGCM.java:51
com.cliffc.aa.node.Node._live
TypeMem _live
Definition: Node.java:89
com.cliffc
com.cliffc.aa.node.Node
Definition: Node.java:16
com.cliffc.aa.util
Definition: AbstractEntry.java:1
com.cliffc.aa.node.Node.OP_SPLIT
static final byte OP_SPLIT
Definition: Node.java:44
com.cliffc.aa.GVNGCM.add_work_all
Node add_work_all(Node n)
Definition: GVNGCM.java:73
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.util.Ary
Definition: Ary.java:11
com.cliffc.aa.type.BitsAlias
Definition: BitsAlias.java:8
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.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._val
Type _val
Definition: Node.java:88
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.AA.unimpl
static RuntimeException unimpl()
Definition: AA.java:10
com.cliffc.aa.type.Bits.test
static boolean test(long[] bits, int i)
Definition: Bits.java:224
com.cliffc.aa.node.MemSplitNode.is_mem
boolean is_mem()
Definition: MemSplitNode.java:31
com.cliffc.aa.node.MProjNode
Definition: MProjNode.java:10
com.cliffc.aa.type.Types
Definition: Types.java:9
com.cliffc.aa.node.MemSplitNode.all_live
TypeMem all_live()
Definition: MemSplitNode.java:54
com.cliffc.aa.Env.START
static StartNode START
Definition: Env.java:14
com.cliffc.aa.node.MemSplitNode.join
MemJoinNode join()
Definition: MemSplitNode.java:24
com.cliffc.aa.util.SB.unchar
SB unchar()
Definition: SB.java:58
com.cliffc.aa.tvar.TV2.make
static TV2 make(@NotNull String name, Node n, @NotNull String alloc_site)
Definition: TV2.java:154
com.cliffc.aa.node.Node.check_solo_mem_writer
boolean check_solo_mem_writer(Node memw)
Definition: Node.java:845
com.cliffc.aa.Env.GVN
static final GVNGCM GVN
Definition: Env.java:13
com.cliffc.aa.node.Node.unkeep
public< N extends Node > N unkeep()
Definition: Node.java:232
com.cliffc.aa.node.MemSplitNode.find_alias_index
int find_alias_index(int alias)
Definition: MemSplitNode.java:73
com.cliffc.aa.node.MemSplitNode.is_copy
Node is_copy(int idx)
Definition: MemSplitNode.java:186
com.cliffc.aa.node.MemSplitNode.check_split
static boolean check_split(Node head1, BitsAlias head1_escs, Node tail2)
Definition: MemSplitNode.java:166
com.cliffc.aa.util.Ary.add
Ary< E > add(E e)
Add element in amortized constant time.
Definition: Ary.java:49
com.cliffc.aa.node.Node.is_dead
boolean is_dead()
Definition: Node.java:820
com.cliffc.aa.node.ProjNode._idx
int _idx
Definition: ProjNode.java:12
com.cliffc.aa.type.Bits.overlaps
boolean overlaps(Bits< B > bs)
Definition: Bits.java:382
com.cliffc.aa.type.Bits.join
static void join(Tree tree, long[] bits0, long[] bits1, long[] bits2)
Definition: Bits.java:349
com.cliffc.aa.node.MemSplitNode.str
String str()
Definition: MemSplitNode.java:32
com.cliffc.aa.util.Ary.remove
E remove(int i)
Slow, linear-time, element removal.
Definition: Ary.java:102
com.cliffc.aa.node.ProjNode.proj
static ProjNode proj(Node head, int idx)
Definition: ProjNode.java:50
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.node.MemSplitNode.check_split
static boolean check_split(Node head1, BitsAlias head1_escs)
Definition: MemSplitNode.java:165
com.cliffc.aa.GVNGCM
Definition: GVNGCM.java:12
com.cliffc.aa.node.ProjNode.set_idx
void set_idx(int idx)
Definition: ProjNode.java:57
com.cliffc.aa.node.MemSplitNode.unify
boolean unify(boolean test)
Definition: MemSplitNode.java:60
com.cliffc.aa.util.Ary.deepCopy
Ary< E > deepCopy()
Definition: Ary.java:333
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.util.SB
Tight/tiny StringBuilder wrapper.
Definition: SB.java:8
com.cliffc.aa.node.MemSplitNode.MemSplitNode
MemSplitNode(Node mem)
Definition: MemSplitNode.java:22
com.cliffc.aa.node.MemSplitNode.mem
Node mem()
Definition: MemSplitNode.java:23
com.cliffc.aa.tvar.TV2.isa
boolean isa(String s)
Definition: TV2.java:77
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.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.MemSplitNode.escapees
BitsAlias escapees()
Definition: MemSplitNode.java:192
com.cliffc.aa.node.MemSplitNode.value
Type value(GVNGCM.Mode opt_mode)
Definition: MemSplitNode.java:40
com.cliffc.aa.util.SB.p
SB p(String s)
Definition: SB.java:13
com.cliffc.aa.node.Node.set_def
Node set_def(int idx, Node n)
Definition: Node.java:154
com.cliffc.aa.node.MemSplitNode._update
void _update(int oldalias, int newalias)
Definition: MemSplitNode.java:122
com.cliffc.aa.tvar.TV2
Definition: TV2.java:23
com.cliffc.aa.node.MemSplitNode
Definition: MemSplitNode.java:19
com.cliffc.aa.type.Type.oob
Type oob()
Definition: Type.java:635
com.cliffc.aa.node.Node.xval
Type xval()
Definition: Node.java:460
com.cliffc.aa.type.BitsAlias.get_kids
static int[] get_kids(int par)
Definition: BitsAlias.java:61
com.cliffc.aa.util.Ary.set
E set(int i, E e)
Set existing element.
Definition: Ary.java:133
com.cliffc.aa.GVNGCM.add_flow
public< N extends Node > N add_flow(N n)
Definition: GVNGCM.java:50
com.cliffc.aa.node.Node.tvar
TV2 tvar()
Definition: Node.java:96
com.cliffc.aa.type.Bits.meet
B meet(final B bs)
Definition: Bits.java:298
com.cliffc.aa.node.MemSplitNode.split_alias
void split_alias(Node copy, BitSet aliases)
Definition: MemSplitNode.java:111
com
com.cliffc.aa.type.Bits.set
B set(int bit)
Definition: Bits.java:264
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.Env
Definition: Env.java:12
com.cliffc.aa.util.SB.toString
String toString()
Definition: SB.java:62
com.cliffc.aa.type
Definition: Bits.java:1
com.cliffc.aa.GVNGCM.init
public< N extends Node > N init(N n)
Definition: GVNGCM.java:99
com.cliffc.aa.type.TypeMem.slice_reaching_aliases
TypeMem slice_reaching_aliases(BitsAlias aliases)
Definition: TypeMem.java:392
com.cliffc.aa.GVNGCM.Mode
Definition: GVNGCM.java:14
com.cliffc.aa.type.Bits.is_empty
boolean is_empty()
Definition: Bits.java:207