blob: 9520554b698aad96fb83e74b86c4213d393a92cb [file] [log] [blame]
/*
* Copyright (C) 2015 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 "B3Procedure.h"
#include "B3UpsilonValue.h"
#include <wtf/GraphNodeWorklist.h>
#include <wtf/IndexMap.h>
namespace JSC { namespace B3 {
class PhiChildren {
WTF_MAKE_FAST_ALLOCATED;
public:
PhiChildren(Procedure&);
~PhiChildren();
class ValueCollection {
public:
ValueCollection(Vector<UpsilonValue*>* values = nullptr)
: m_values(values)
{
}
unsigned size() const { return m_values->size(); }
Value* at(unsigned index) const { return m_values->at(index)->child(0); }
Value* operator[](unsigned index) const { return at(index); }
bool contains(Value* value) const
{
for (unsigned i = size(); i--;) {
if (at(i) == value)
return true;
}
return false;
}
class iterator {
public:
iterator(Vector<UpsilonValue*>* values = nullptr, unsigned index = 0)
: m_values(values)
, m_index(index)
{
}
Value* operator*() const
{
return m_values->at(m_index)->child(0);
}
iterator& operator++()
{
m_index++;
return *this;
}
bool operator==(const iterator& other) const
{
ASSERT(m_values == other.m_values);
return m_index == other.m_index;
}
bool operator!=(const iterator& other) const
{
return !(*this == other);
}
private:
Vector<UpsilonValue*>* m_values;
unsigned m_index;
};
iterator begin() const { return iterator(m_values); }
iterator end() const { return iterator(m_values, m_values->size()); }
private:
Vector<UpsilonValue*>* m_values;
};
class UpsilonCollection {
public:
UpsilonCollection()
{
}
UpsilonCollection(PhiChildren* phiChildren, Value* value, Vector<UpsilonValue*>* values)
: m_phiChildren(phiChildren)
, m_value(value)
, m_values(values)
{
}
unsigned size() const { return m_values->size(); }
Value* at(unsigned index) const { return m_values->at(index); }
Value* operator[](unsigned index) const { return at(index); }
bool contains(Value* value) const { return m_values->contains(value); }
typedef Vector<UpsilonValue*>::const_iterator iterator;
Vector<UpsilonValue*>::const_iterator begin() const { return m_values->begin(); }
Vector<UpsilonValue*>::const_iterator end() const { return m_values->end(); }
ValueCollection values() { return ValueCollection(m_values); }
template<typename Functor>
void forAllTransitiveIncomingValues(const Functor& functor)
{
if (m_value->opcode() != Phi) {
functor(m_value);
return;
}
GraphNodeWorklist<Value*> worklist;
worklist.push(m_value);
while (Value* phi = worklist.pop()) {
for (Value* child : m_phiChildren->at(phi).values()) {
if (child->opcode() == Phi)
worklist.push(child);
else
functor(child);
}
}
}
bool transitivelyUses(Value* candidate)
{
bool result = false;
forAllTransitiveIncomingValues(
[&] (Value* child) {
result |= child == candidate;
});
return result;
}
private:
PhiChildren* m_phiChildren { nullptr };
Value* m_value { nullptr };
Vector<UpsilonValue*>* m_values { nullptr };
};
UpsilonCollection at(Value* value) { return UpsilonCollection(this, value, &m_upsilons[value]); }
UpsilonCollection operator[](Value* value) { return at(value); }
const Vector<Value*, 8>& phis() const { return m_phis; }
private:
IndexMap<Value*, Vector<UpsilonValue*>> m_upsilons;
Vector<Value*, 8> m_phis;
};
} } // namespace JSC::B3
#endif // ENABLE(B3_JIT)