diff options
Diffstat (limited to 'chapter25/src')
| -rw-r--r-- | chapter25/src/main/java/com/seaofnodes/simple/node/LoadNode.java | 16 | ||||
| -rw-r--r-- | chapter25/src/test/java/com/seaofnodes/simple/IncompleteTypesTest.java | 13 |
2 files changed, 27 insertions, 2 deletions
diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/LoadNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/LoadNode.java index 24a2f9b8..ff2d1138 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/LoadNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/LoadNode.java @@ -170,7 +170,12 @@ public class LoadNode extends MemOpNode { // skipping it can make a compound assignment read the old value. if( st._alias==1 ) return null; addDep(st.ptr()); - if( _alias==st._alias && ptr==address(st.ptr()) && off()==st.off() ) return st; + if( _alias==st._alias && ptr==address(st.ptr()) && off()==st.off() ) { + // A full-width load cannot narrow the forwarded value. + if( _declaredType instanceof TypeInteger ti && ti.log_size()==3 && + !addDep(st.val())._type.isa(_type) ) return null; + return st; + } if( _alias==st._alias && !neverAlias(ptr,address(st.ptr())) && !addDep(off())._type.join(addDep(st.off())._type).isHigh() ) return null; mem=st.mem(); @@ -269,8 +274,15 @@ public class LoadNode extends MemOpNode { // Signed extension int shift = Long.numberOfLeadingZeros(ti._max)-1; Node shf = con(shift); - if( shf._type==TypeInteger.ZERO ) + if( shf._type==TypeInteger.ZERO ) { + // A constructor's loop Phi may still have an unsettled type. + // Wait for it instead of weakening the typed Load's users. + if( !val._type.isa(_type) ) { + addDep(val); + return null; + } return val; + } Node shl = new ShlNode(null,val,shf.keep()).peephole(); return new SarNode(null,shl,shf.unkeep()); } diff --git a/chapter25/src/test/java/com/seaofnodes/simple/IncompleteTypesTest.java b/chapter25/src/test/java/com/seaofnodes/simple/IncompleteTypesTest.java index f2f7d882..419cac51 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/IncompleteTypesTest.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/IncompleteTypesTest.java @@ -6,6 +6,19 @@ import com.seaofnodes.simple.type.TypeInteger; import static org.junit.Assert.assertEquals; public class IncompleteTypesTest { + @Test public void testLoadFromUnsettledLoopPhi() { + String src = """ + struct C { int x; }; + val f={int n -> return new C { while(n--) if(n) x=1; }; }; + return f(arg).x; + """; + for( long seed : new long[]{123,456,789} ) { + var code = new CodeGen(src,TypeInteger.BOT,seed,true).driver(CodeGen.Phase.TypeCheck); + for( int arg=0; arg<6; arg++ ) + assertEquals("seed="+seed+" arg="+arg,arg<2 ? "0" : "1",Eval2.eval(code,arg)); + } + } + @Test public void testForwardFieldAndNumericMode() { // At the addition, neither the field's type nor its offset is known. String src = """ |
