From c189a7bb5486b7b866aeb17b96f4a8d606e39767 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Mon, 23 Sep 2024 19:56:20 -0700 Subject: arrays with loads and stores No range-checking yet. Length is "ary#" TypeStruct with special "[]" field is an array Fix some eager push-load-thru phi --- .../java/com/seaofnodes/simple/Chapter15Test.java | 26 ++++++++++++++- .../com/seaofnodes/simple/evaluator/Evaluator.java | 39 ++++++++++++++++++++-- .../com/seaofnodes/simple/evaluator/Scheduler.java | 9 +++-- 3 files changed, 68 insertions(+), 6 deletions(-) (limited to 'chapter15/src/test/java/com') diff --git a/chapter15/src/test/java/com/seaofnodes/simple/Chapter15Test.java b/chapter15/src/test/java/com/seaofnodes/simple/Chapter15Test.java index f884f18d..15465677 100644 --- a/chapter15/src/test/java/com/seaofnodes/simple/Chapter15Test.java +++ b/chapter15/src/test/java/com/seaofnodes/simple/Chapter15Test.java @@ -21,7 +21,7 @@ return 3.14; assertEquals(3.14, Evaluator.evaluate(stop, 0)); } - @Ignore @Test + @Test public void testBasic() { Parser parser = new Parser( """ @@ -33,6 +33,30 @@ return is[1]; assertEquals(0L, Evaluator.evaluate(stop, 0)); } + @Test + public void testRollingSum() { + Parser parser = new Parser( +""" +int[] ary = new int[arg]; +// Fill [0,1,2,3,4,...] +int i=0; +while( i < ary# ) { + ary[i] = i; + i = i+1; +} +// Fill [0,1,3,6,10,...] +i=0; +while( i < ary# - 1 ) { + ary[i+1] = ary[i+1] + ary[i]; + i = i+1; +} +return ary[1] * 1000 + ary[3]; // 1 * 1000 + 6 +"""); + StopNode stop = parser.parse(false).iterate(true); + assertEquals("return (.[]+(.[]*1000));", stop.toString()); + assertEquals(1006L, Evaluator.evaluate(stop, 4)); + } + @Test public void testBad0() { Parser parser = new Parser( diff --git a/chapter15/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java b/chapter15/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java index b897af7d..40d73b19 100644 --- a/chapter15/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java +++ b/chapter15/src/test/java/com/seaofnodes/simple/evaluator/Evaluator.java @@ -85,8 +85,21 @@ public class Evaluator { private Object alloc(NewNode alloc) { TypeTuple tt = alloc.compute(); TypeStruct type = ((TypeMemPtr)tt._types[1])._obj; + Object[] body=null; + if( type.isAry() ) { + long sz = (Long)val(alloc.in(1)); + int base = alloc._ptr._obj.aryBase(); + int scale = alloc._ptr._obj.aryScale(); + long n = (sz-base)>>scale; + body = new Object[(int)n+1]; // Array body + body[0] = n; // Array length + } else { + body = new Object[type._fields.length]; + } Object[] mems = new Object[type._fields.length+2]; - mems[1] = new Obj(type,new Object[type._fields.length]); + // mems[0] is control + mems[1] = new Obj(type,body); // the ref + // mems[2+...] are memory aliases return mems; } @@ -94,7 +107,17 @@ public class Evaluator { var from = (Obj)val(load.ptr()); var off = val(load.off()); var idx = getFieldIndex(from.struct, load, (Long)off); - return from.fields[idx]; + if( idx==1 && from.struct.isAry() ) { + long len = (Long)from.fields[0]; + int base = from.struct.aryBase(); + int scale = from.struct.aryScale(); + long i = ((Long)off - base)>>scale; + if( i < 0 || i >= len ) + throw new RuntimeException("Array index out of bounds " + off + " <= " + len); + return from.fields[(int)i+1]; + + } else + return from.fields[idx]; } private Object store(StoreNode store) { @@ -102,7 +125,17 @@ public class Evaluator { var off = val(store.off()); var val = val(store.val()); var idx = getFieldIndex(to.struct, store, (Long)off); - to.fields[idx] = val; + if( idx==1 && to.struct.isAry() ) { + long len = (Long)to.fields[0]; + int base = to.struct.aryBase(); + int scale = to.struct.aryScale(); + long i = ((Long)off - base)>>scale; + if( i < 0 || i >= len ) + throw new RuntimeException("Array index out of bounds " + off + " <= " + len); + to.fields[(int)i+1] = val; + + } else + to.fields[idx] = val; return null; } diff --git a/chapter15/src/test/java/com/seaofnodes/simple/evaluator/Scheduler.java b/chapter15/src/test/java/com/seaofnodes/simple/evaluator/Scheduler.java index fd8fdb8d..59c15d3f 100644 --- a/chapter15/src/test/java/com/seaofnodes/simple/evaluator/Scheduler.java +++ b/chapter15/src/test/java/com/seaofnodes/simple/evaluator/Scheduler.java @@ -155,7 +155,10 @@ public class Scheduler { * @return true if all placed inputs are before this node. */ private boolean isValid(NodeData data) { - return data.node._inputs.stream().map(i->i==null?null:d(i)).map(d->d==null||d.users>0?null:d.block).allMatch(d->d==null||dom(d, data.block)==d); + return data.node._inputs.stream() + .map(i->i==null?null:d(i)) + .map(d->d==null||d.users>0?null:d.block) + .allMatch(d->d==null||dom(d, data.block)==d); } /** @@ -399,7 +402,9 @@ public class Scheduler { } } if (!(node instanceof ReturnNode)) - for (Node n:node._outputs) if (n!=null && n instanceof CFGNode && isCFGNodeReady(n) && d(n).block == null) queue.push(d(n)); + for (Node n : node._outputs) + if(n instanceof CFGNode && isCFGNodeReady(n) && d(n).block == null) + queue.push(d(n)); var b = block; for(var in:data.node._inputs) od(in).ifPresent(d->update(d, b)); } -- cgit v1.2.3