summaryrefslogtreecommitdiff
path: root/src/main/java/com/seaofnodes/simple/node/MemPhiNode.java
blob: cdfaaf97546496f2bbec641b4778658cd4a400e6 (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
package com.seaofnodes.simple.node;

import com.seaofnodes.simple.type.Type;
import com.seaofnodes.simple.type.TypeMem;
import com.seaofnodes.simple.codegen.GlobalBits;
import com.seaofnodes.simple.util.BAOS;

import java.util.HashMap;
import java.util.IdentityHashMap;

/** A Phi for one precise memory alias. */
public class MemPhiNode extends PhiNode {

    public final int _alias;

    public MemPhiNode(String label, int alias, Node... inputs) {
        super(label, inputs);
        assert alias > 1;
        _alias = alias;
    }

    public MemPhiNode(MemPhiNode phi) {
        super(phi,phi._label);
        _alias = phi._alias;
    }

    @Override public Tag serialTag() { return Tag.MemPhi; }

    @Override
    public void packed(BAOS baos, HashMap<String,Integer> strs, HashMap<Type,Integer> types,
                       IdentityHashMap<Node,Integer> anodes) {
        super.packed(baos,strs,types,anodes);
        baos.packed2(_alias);
    }

    static Node make(BAOS bais, String[] strs, Type[] types, GlobalBits fileAliases, GlobalBits aliases) {
        Node[] ins = new Node[bais.packed1()];
        String label = strs[bais.packed2()];
        int alias = bais.packed2();
        if( alias >= GlobalBits.RESERVED ) alias = aliases.map(fileAliases,alias);
        return new MemPhiNode(label,alias,ins);
    }

    @Override
    public Type compute() {
        Type t = super.compute();
        assert BulkMemPhiNode.checkMem(this,_alias);
        if( !(t instanceof TypeMem tmem) ) return t;
        assert tmem._alias==1 || tmem._alias==_alias;
        // This Phi structurally knows its alias, but not whether the field is
        // final.  Do not infer slice finality from evolving input types.
        return TypeMem.make(_alias,tmem._t,tmem._one,tmem._clz,false,tmem._escFs,tmem._escAs);
    }

    @Override
    public Node idealize() {
        // A precise memory Phi can always bypass a MemMerge and select its
        // matching slice.
        for( int i=1; i<nIns(); i++ )
            if( in(i) instanceof MemMergeNode mem ) {
                setDef(i,mem.alias(_alias));
                return this;
            }
        if( nIns()==3 && region() instanceof LoopNode loop && !loop.inProgress() &&
            in(2) instanceof StoreNode st && st.mem()==this ) {
            Node sink = st.sink(this);
            if( sink!=null ) return sink;
        }
        return super.idealize();
    }

    @Override public boolean eq(Node n) {
        return _alias==((MemPhiNode)n)._alias && super.eq(n);
    }

    @Override int hash() { return _alias; }
}