2 * Copyright (C) 2012 Intel Corporation. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "DFGRedundantPhiEliminationPhase.h"
33 namespace JSC
{ namespace DFG
{
35 class RedundantPhiEliminationPhase
: public Phase
{
37 RedundantPhiEliminationPhase(Graph
& graph
)
38 : Phase(graph
, "redundant phi elimination")
46 changed
= fixupPhis();
49 updateBlockVariableInformation();
51 // Update the Phi references from non-Phi nodes, e.g., the GetLocals.
52 for (NodeIndex index
= 0; index
< m_graph
.size(); ++index
) {
53 Node
& node
= m_graph
[index
];
55 if (!node
.shouldGenerate())
60 replacePhiChild(node
, 0);
70 NodeIndex
getRedundantReplacement(NodeIndex phi
)
72 NodeIndex child1
= m_graph
[phi
].child1().indexUnchecked();
73 NodeIndex candidate
= child1
== phi
? NoNode
: child1
;
75 NodeIndex child2
= m_graph
[phi
].child2().indexUnchecked();
76 if (candidate
!= NoNode
) {
77 if (child2
!= NoNode
&& child2
!= candidate
&& child2
!= phi
)
79 } else if (child2
!= phi
)
82 NodeIndex child3
= m_graph
[phi
].child3().indexUnchecked();
83 if (candidate
!= NoNode
) {
84 if (child3
!= NoNode
&& child3
!= candidate
&& child3
!= phi
)
86 } else if (child3
!= phi
)
92 bool replacePhiChild(Node
& node
, unsigned childIndex
)
94 ASSERT(childIndex
< 3);
96 bool replaced
= false;
97 NodeIndex child
= node
.children
.child(childIndex
).indexUnchecked();
98 if (child
!= NoNode
&& m_graph
[child
].op() == Phi
) {
99 NodeIndex childReplacement
= getRedundantReplacement(child
);
100 if (childReplacement
!= NoNode
) {
101 node
.children
.child(childIndex
).setIndex(childReplacement
);
103 if (node
.refCount()) {
104 m_graph
[childReplacement
].ref();
105 m_graph
.deref(child
);
114 bool changed
= false;
116 for (BlockIndex block
= 0; block
< m_graph
.m_blocks
.size(); ++block
) {
117 Vector
<NodeIndex
>& phis
= m_graph
.m_blocks
[block
]->phis
;
119 for (size_t i
= 0; i
< phis
.size(); ++i
) {
120 NodeIndex phi
= phis
[i
];
121 Node
& phiNode
= m_graph
[phi
];
123 changed
|= (replacePhiChild(phiNode
, 0) && phiNode
.refCount());
124 changed
|= (replacePhiChild(phiNode
, 1) && phiNode
.refCount());
125 changed
|= (replacePhiChild(phiNode
, 2) && phiNode
.refCount());
132 void updateBlockVariableInformation()
134 // Redundant Phi nodes are eliminated, we need to update
135 // the variable information if it references them.
136 for (BlockIndex blockIndex
= 0; blockIndex
< m_graph
.m_blocks
.size(); ++blockIndex
) {
137 BasicBlock
* basicBlock
= m_graph
.m_blocks
[blockIndex
].get();
139 for (size_t arg
= 0; arg
< basicBlock
->variablesAtHead
.numberOfArguments(); ++arg
) {
140 NodeIndex nodeIndex
= basicBlock
->variablesAtHead
.argument(arg
);
141 if (nodeIndex
!= NoNode
&& m_graph
[nodeIndex
].op() == Phi
&& !m_graph
[nodeIndex
].refCount()) {
142 NodeIndex replacement
= getRedundantReplacement(nodeIndex
);
143 if (replacement
!= NoNode
) {
144 // This argument must be unused in this block.
145 ASSERT(basicBlock
->variablesAtTail
.argument(arg
) == nodeIndex
);
146 basicBlock
->variablesAtHead
.argument(arg
) = replacement
;
147 basicBlock
->variablesAtTail
.argument(arg
) = replacement
;
152 for (size_t local
= 0; local
< basicBlock
->variablesAtHead
.numberOfLocals(); ++local
) {
153 NodeIndex nodeIndex
= basicBlock
->variablesAtHead
.local(local
);
154 if (nodeIndex
!= NoNode
&& m_graph
[nodeIndex
].op() == Phi
&& !m_graph
[nodeIndex
].refCount()) {
155 NodeIndex replacement
= getRedundantReplacement(nodeIndex
);
156 if (replacement
!= NoNode
) {
157 // This local variable must be unused in this block.
158 ASSERT(basicBlock
->variablesAtTail
.local(local
) == nodeIndex
);
159 basicBlock
->variablesAtHead
.local(local
) = replacement
;
160 basicBlock
->variablesAtTail
.local(local
) = replacement
;
169 void performRedundantPhiElimination(Graph
& graph
)
171 runPhase
<RedundantPhiEliminationPhase
>(graph
);
174 } } // namespace JSC::DFG
176 #endif // ENABLE(DFG_JIT)