summaryrefslogtreecommitdiff
path: root/src/jit/nodeinfo.h
blob: 1937cc4377e03ad29b75becd86a025e6d692cb3f (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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#ifndef _NODEINFO_H_
#define _NODEINFO_H_

struct GenTree;

class LinearScan;
typedef unsigned int LsraLocation;

class TreeNodeInfo
{
public:
    TreeNodeInfo()
    {
        loc                 = 0;
        _dstCount           = 0;
        _srcCount           = 0;
        _internalIntCount   = 0;
        _internalFloatCount = 0;

        srcCandsIndex          = 0;
        dstCandsIndex          = 0;
        internalCandsIndex     = 0;
        isLocalDefUse          = false;
        isHelperCallWithKills  = false;
        isLsraAdded            = false;
        isDelayFree            = false;
        hasDelayFreeSrc        = false;
        isTgtPref              = false;
        regOptional            = false;
        definesAnyRegisters    = false;
        isInternalRegDelayFree = false;
#ifdef DEBUG
        isInitialized = false;
#endif
    }

    // dst
    __declspec(property(put = setDstCount, get = getDstCount)) int dstCount;
    void setDstCount(int count)
    {
        assert(count <= MAX_RET_REG_COUNT);
        _dstCount = (char)count;
    }
    int getDstCount()
    {
        return _dstCount;
    }

    // src
    __declspec(property(put = setSrcCount, get = getSrcCount)) int srcCount;
    void setSrcCount(int count)
    {
        _srcCount = (char)count;
        assert(_srcCount == count);
    }
    int getSrcCount()
    {
        return _srcCount;
    }

    // internalInt
    __declspec(property(put = setInternalIntCount, get = getInternalIntCount)) int internalIntCount;
    void setInternalIntCount(int count)
    {
        _internalIntCount = (char)count;
        assert(_internalIntCount == count);
    }
    int getInternalIntCount()
    {
        return _internalIntCount;
    }

    // internalFloat
    __declspec(property(put = setInternalFloatCount, get = getInternalFloatCount)) int internalFloatCount;
    void setInternalFloatCount(int count)
    {
        _internalFloatCount = (char)count;
        assert(_internalFloatCount == count);
    }
    int getInternalFloatCount()
    {
        return _internalFloatCount;
    }

    // SrcCandidates are constraints of the consuming (parent) operation applied to this node
    // (i.e. what registers it is constrained to consume).
    regMaskTP getSrcCandidates(LinearScan* lsra);
    void setSrcCandidates(LinearScan* lsra, regMaskTP mask);
    // DstCandidates are constraints of this node (i.e. what registers it is constrained to produce).
    regMaskTP getDstCandidates(LinearScan* lsra);
    void setDstCandidates(LinearScan* lsra, regMaskTP mask);
    // InternalCandidates are constraints of the registers used as temps in the evaluation of this node.
    regMaskTP getInternalCandidates(LinearScan* lsra);
    void setInternalCandidates(LinearScan* lsra, regMaskTP mask);
    void addInternalCandidates(LinearScan* lsra, regMaskTP mask);

    LsraLocation loc;

public:
    unsigned char srcCandsIndex;
    unsigned char dstCandsIndex;
    unsigned char internalCandsIndex;

private:
    unsigned char _srcCount : 5;
    unsigned char _dstCount : 3;
    unsigned char _internalIntCount : 3;
    unsigned char _internalFloatCount : 3;

public:
    // isLocalDefUse identifies trees that produce a value that is not consumed elsewhere.
    // Examples include stack arguments to a call (they are immediately stored), lhs of comma
    // nodes, or top-level nodes that are non-void.
    unsigned char isLocalDefUse : 1;

    // isHelperCallWithKills is set when this is a helper call that kills more than just its in/out regs.
    unsigned char isHelperCallWithKills : 1;

    // Is this node added by LSRA, e.g. as a resolution or copy/reload move.
    unsigned char isLsraAdded : 1;

    // isDelayFree is set when the register defined by this node will interfere with the destination
    // of the consuming node, and therefore it must not be freed immediately after use.
    unsigned char isDelayFree : 1;

    // hasDelayFreeSrc is set when this node has sources that are marked "isDelayFree".  This is because,
    // we may eventually "contain" this node, in which case we don't want it's children (which have
    // already been marked "isDelayFree" to be handled that way when allocating.
    unsigned char hasDelayFreeSrc : 1;

    // isTgtPref is set to true when we have a rmw op, where we would like the result to be allocated
    // in the same register as op1.
    unsigned char isTgtPref : 1;

    // Whether a spilled second src can be treated as a contained operand
    unsigned char regOptional : 1;

    // Whether or not a node defines any registers, whether directly (for nodes where dstCout is non-zero)
    // or indirectly (for contained nodes, which propagate the transitive closure of the registers
    // defined by their inputs). Used during buildRefPositionsForNode in order to avoid unnecessary work.
    unsigned char definesAnyRegisters : 1;

    // Whether internal register needs to be different from targetReg
    // in which result is produced.
    unsigned char isInternalRegDelayFree : 1;

#ifdef DEBUG
    // isInitialized is set when the tree node is handled.
    unsigned char isInitialized : 1;
#endif

public:
    // Initializes the TreeNodeInfo value with the given values.
    void Initialize(LinearScan* lsra, GenTree* node, LsraLocation location);

#ifdef DEBUG
    void dump(LinearScan* lsra);

    // This method checks to see whether the information has been initialized,
    // and is in a consistent state
    bool IsValid(LinearScan* lsra)
    {
        return (isInitialized &&
                ((getSrcCandidates(lsra) | getInternalCandidates(lsra) | getDstCandidates(lsra)) &
                 ~(RBM_ALLFLOAT | RBM_ALLINT)) == 0);
    }
#endif // DEBUG
};

#endif // _NODEINFO_H_