blob: c83c81d053b4bf728f2cd46e4bcebfa8d7687ec5 (
plain)
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
package com.seaofnodes.simple.node;
import com.seaofnodes.print.ExprPrinter;
import com.seaofnodes.simple.codegen.CodeGen;
import com.seaofnodes.simple.type.*;
import com.seaofnodes.simple.util.Utils;
public class IfNode extends CFGNode implements MultiNode {
public IfNode(Node ctrl, Node pred) {
super(ctrl, pred);
CodeGen.CODE.add(this); // Because idoms are complex, just add it
}
public IfNode(IfNode iff) { super(iff); }
@Override public Tag serialTag() { return Tag.If; }
@Override
protected ExprPrinter<Node> _print1(ExprPrinter<Node> p) {
p.p("if( ");
if( in(1)==null ) p.p("never");
else p.n(in(1));
return p.p(" )");
}
public Node ctrl() { return in(0); }
public Node pred() { return in(1); }
// No one unique control follows
@Override public CFGNode uctrl() { return null; }
@Override
public Type compute() {
// If the If node is not reachable then neither is any following Proj
assert !_inputs.isEmpty();
if (ctrl()._type != Type.CONTROL && ctrl()._type != Type.BOTTOM )
return TypeTuple.IF_NEITHER;
Node pred = pred();
Type t = pred._type;
// High types mean NEITHER side is reachable.
// Wait until the type falls to decide which way to go.
if( t.isHigh() )
return TypeTuple.IF_NEITHER;
// If constant is 0 then false branch is reachable
// Else true branch is reachable
if( t.isConstant() )
return (t==Type.NIL || t==TypeInteger.ZERO || (t instanceof TypeFunPtr tfp && tfp._fidxs== XInt.EMPTY) ) ? TypeTuple.IF_FALSE : TypeTuple.IF_TRUE;
// If adding a zero makes a difference, the predicate must not have a zero/null
if( !t.makeZero().isa(t) )
return TypeTuple.IF_TRUE;
return TypeTuple.IF_BOTH;
}
@Override
public Node idealize() {
// Hunt up the immediate dominator tree. If we find an identical if
// test on either the true or false branch, that side wins.
if( !pred()._type.isHighOrConst() )
for( CFGNode dom = idom(), prior=this; dom!=null; prior = dom, dom = dom.idom() )
if( addDep(dom) instanceof IfNode iff &&
prior instanceof CProjNode prj &&
(addDep(iff.pred())==pred() ||
pred() instanceof GuardNode cast && cast._nonZero && iff.pred()==cast.in(1) ) ) {
setDef(1,con( prj._idx==0 ? 1 : 0 ));
return this;
}
return null;
}
// MachNode variants need to support this and negate the conditional test.
// The following CProjs will be inverted by the caller.
public void negate() { throw Utils.TODO(); }
// Negate the sense of a test
public static String negate( String bop ) {
return switch( bop ) {
case "<" -> ">=";
case "<=" -> ">" ;
case "==" -> "!=";
case "!=" -> "==";
case ">" -> "<=";
case ">=" -> "<" ;
default -> throw Utils.TODO();
};
}
// Swap compare operands
public static String swap( String bop ) {
return switch( bop ) {
case "<" -> ">" ;
case "<=" -> ">=";
case "==" -> "==";
case "!=" -> "!=";
case ">" -> "<" ;
case ">=" -> "<=";
default -> throw Utils.TODO();
};
}
}
|