1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
package com.seaofnodes.simple;
import com.seaofnodes.simple.codegen.*;
import com.seaofnodes.simple.node.*;
import org.junit.Test;
import static org.junit.Assert.*;
public class Chapter11Test {
@Test public void testIndependentField() {
var code = new CodeGen("""
struct S { int x; int y; };
!S !s = new S;
s.x = 42;
while (arg > 0) { s.y = s.y + arg; arg = arg - 1; }
return s.x;
""").parse().opto();
var stop = code._stop;
assertEquals("return 42;",stop.toString());
assertEquals("42",Eval2.eval(code,5));
assertNull(stop.walk(n -> n instanceof LoadNode ? n : null));
}
@Test public void testParallelMemoryPhis() {
var code = new CodeGen("""
struct S { int x; int y; int z; };
!S !a = new S; !S !b = new S;
!S !p = a; if (arg) p = b;
while (arg > 0) {
a.x = p.x + arg;
a.y = p.y + 2;
a.z = p.z + 3;
arg = arg - 1;
}
return a;
""").parse().opto();
var stop = code._stop;
int[] phis = {0};
stop.walk(n -> {
// Store sinking can replace field memory Phis with value Phis.
if (n instanceof PhiNode) phis[0]++;
if (n instanceof MemMergeNode m && m.in(1) instanceof BulkMemPhiNode b)
for(int a=b._aliases.nextSetBit(0); a>=0; a=b._aliases.nextSetBit(a+1))
assertTrue(a<m.nIns() && m.in(a)!=null);
assertFalse(n instanceof PhiNode && n.isMem() &&
!(n instanceof MemPhiNode) && !(n instanceof BulkMemPhiNode) && !(n instanceof ParmNode));
return null;
});
assertTrue(phis[0]>=4); // Three fields and the loop counter.
assertEquals("S{x=1,y=2,z=3}",Eval2.eval(code,4));
}
@Test public void testLateSliceWorklist() {
// Seed 97 exposed a store selecting a bulk predecessor without queuing
// it. Keep both the worklist assertion and the final heap check.
for (int seed : new int[]{0,97,123,456}) {
var code = new CodeGen(Chapter10Test.NESTED_MEMORY,com.seaofnodes.simple.type.TypeInteger.BOT,seed).parse();
code.opto();
assertEquals("S{x=9,y=25,z=17}",Eval2.eval(code,4));
}
}
}
|