diff options
| author | Cliff Click <cliffc@acm.org> | 2026-08-10 11:11:18 -0700 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2026-10-08 16:52:27 -0700 |
| commit | d32f97238c903765dec4e9a9f3cbfa5fd12cded6 (patch) | |
| tree | a5ac731801ef7066bab6359c4e85c2bdd20082a6 /src/main/java/com/seaofnodes/simple/node/GuardNode.java | |
| parent | b5ebb2032aa04cf4506d533127d373d4cf5a25c6 (diff) | |
| download | Simple-linear.tar.gz Simple-linear.zip | |
Chapter 25: Modules, Separate Compilation, and SSA Constructionlinear
Co-authored-by: Hsiang-Ying Fu <66062782+fuhsnn@users.noreply.github.com>
Co-authored-by: fuhsnn <66062782+fuhsnn@users.noreply.github.com>
Co-authored-by: Symious <14933944+symious@users.noreply.github.com>
Co-authored-by: Jun Kawasaki <jun784@gmail.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'src/main/java/com/seaofnodes/simple/node/GuardNode.java')
| -rw-r--r-- | src/main/java/com/seaofnodes/simple/node/GuardNode.java | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/src/main/java/com/seaofnodes/simple/node/GuardNode.java b/src/main/java/com/seaofnodes/simple/node/GuardNode.java new file mode 100644 index 00000000..0ce504d9 --- /dev/null +++ b/src/main/java/com/seaofnodes/simple/node/GuardNode.java @@ -0,0 +1,68 @@ +package com.seaofnodes.simple.node; + +import com.seaofnodes.print.ExprPrinter; + +import com.seaofnodes.simple.type.Type; +import com.seaofnodes.simple.type.TypeScalar; +import com.seaofnodes.simple.util.BAOS; +import com.seaofnodes.simple.util.Utils; + +import java.util.HashMap; +import java.util.IdentityHashMap; + +// A branch-proven refinement to zero/null or non-zero/non-null. The value +// family is deliberately taken from the input when it becomes known. +public class GuardNode extends Node { + public final boolean _nonZero; + + public GuardNode(boolean nonZero, Node ctrl, Node val) { + super(ctrl,val); + _nonZero = nonZero; + } + + public GuardNode(GuardNode guard) { + super(guard); + _nonZero = guard._nonZero; + } + + @Override public Tag serialTag() { return Tag.Guard; } + @Override public void packed(BAOS baos, HashMap<String,Integer> strs, HashMap<Type,Integer> types, IdentityHashMap<Node,Integer> anodes) { + baos.write(_nonZero ? 1 : 0); + } + static Node make(BAOS bais) { return new GuardNode(bais.read()!=0,null,null); } + + @Override public String label() { return _nonZero ? "(!=0)" : "(==0)"; } + + @Override protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) { + return p.p(label()).n(in(1)); + } + + @Override public Type compute() { + // Guard is a pinned, path-local fact. If its control path is not + // executable, the fact is not executable either, regardless of how the + // value input sharpens later. + Type c = in(0)._type; + if( c != Type.CONTROL && c != Type.BOTTOM ) + return Type.TOP; + Type t = in(1)._type; + if( t==Type.BOTTOM || t==Type.TOP ) return t; + // The scalar envelope does not identify a value family. Preserve it + // until SCCP learns whether this is an int, float, pointer, or fptr; + // choosing generic ptr here can be weaker than a later concrete type. + if( t==TypeScalar.BOT || t==TypeScalar.TOP ) return t; + Type t2 = _nonZero ? t.nonZero() : t.makeZero(); + return t2==null ? (_type==null ? Type.TOP : _type) : t2; // No sane answer for e.g. not-zero of a zero + } + + @Override public Node idealize() { + if( in(0)._type != Type.CONTROL && in(0)._type != Type.BOTTOM ) + return null; + if( in(1)._type==Type.BOTTOM || in(1)._type==Type.TOP ) return null; + if( _type.isHighOrConst() && in(1)._type.isa(_type) ) + return in(1); + return null; + } + + @Override public boolean eq(Node n) { return _nonZero==((GuardNode)n)._nonZero; } + @Override int hash() { return _nonZero ? 1 : 0; } +} |
