blob: 400e6bef4a4a8cd320ba4bb957db4e53803d0d6c [file] [log] [blame]
/*
* Copyright (C) 2015-2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#if ENABLE(B3_JIT)
#include <wtf/GraphNodeWorklist.h>
#include <wtf/IndexSet.h>
#include <wtf/Vector.h>
namespace JSC { namespace B3 {
template<typename BasicBlock>
bool addPredecessor(BasicBlock* block, BasicBlock* predecessor)
{
auto& predecessors = block->predecessors();
if (predecessors.contains(predecessor))
return false;
predecessors.append(predecessor);
return true;
}
template<typename BasicBlock>
bool removePredecessor(BasicBlock* block, BasicBlock* predecessor)
{
auto& predecessors = block->predecessors();
for (unsigned i = 0; i < predecessors.size(); ++i) {
if (predecessors[i] == predecessor) {
predecessors[i--] = predecessors.last();
predecessors.removeLast();
ASSERT(!predecessors.contains(predecessor));
return true;
}
}
return false;
}
template<typename BasicBlock>
bool replacePredecessor(BasicBlock* block, BasicBlock* from, BasicBlock* to)
{
bool changed = false;
// We do it this way because 'to' may already be a predecessor of 'block'.
changed |= removePredecessor(block, from);
changed |= addPredecessor(block, to);
return changed;
}
template<typename BasicBlock>
void updatePredecessorsAfter(BasicBlock* root)
{
Vector<BasicBlock*, 16> worklist;
worklist.append(root);
while (!worklist.isEmpty()) {
BasicBlock* block = worklist.takeLast();
for (BasicBlock* successor : block->successorBlocks()) {
if (addPredecessor(successor, block))
worklist.append(successor);
}
}
}
template<typename BasicBlock>
void clearPredecessors(Vector<std::unique_ptr<BasicBlock>>& blocks)
{
for (auto& block : blocks) {
if (block)
block->predecessors().shrink(0);
}
}
template<typename BasicBlock>
void recomputePredecessors(Vector<std::unique_ptr<BasicBlock>>& blocks)
{
clearPredecessors(blocks);
updatePredecessorsAfter(blocks[0].get());
}
template<typename BasicBlock>
bool isBlockDead(BasicBlock* block)
{
if (!block)
return false;
if (!block->index())
return false;
return block->predecessors().isEmpty();
}
template<typename BasicBlock>
Vector<BasicBlock*> blocksInPreOrder(BasicBlock* root)
{
Vector<BasicBlock*> result;
GraphNodeWorklist<BasicBlock*, IndexSet<BasicBlock*>> worklist;
worklist.push(root);
while (BasicBlock* block = worklist.pop()) {
result.append(block);
for (BasicBlock* successor : block->successorBlocks())
worklist.push(successor);
}
return result;
}
template<typename BasicBlock>
Vector<BasicBlock*> blocksInPostOrder(BasicBlock* root)
{
Vector<BasicBlock*> result;
PostOrderGraphNodeWorklist<BasicBlock*, IndexSet<BasicBlock*>> worklist;
worklist.push(root);
while (GraphNodeWithOrder<BasicBlock*> item = worklist.pop()) {
switch (item.order) {
case GraphVisitOrder::Pre:
worklist.pushPost(item.node);
for (BasicBlock* successor : item.node->successorBlocks())
worklist.push(successor);
break;
case GraphVisitOrder::Post:
result.append(item.node);
break;
}
}
return result;
}
} } // namespace JSC::B3
#endif // ENABLE(B3_JIT)