/* * Copyright © 2012 Intel Corporation * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . * * Author: Benjamin Segovia */ /** * \file liveness.hpp * \author Benjamin Segovia */ #ifndef __GBE_IR_LIVENESS_HPP__ #define __GBE_IR_LIVENESS_HPP__ #include #include "sys/map.hpp" #include "sys/set.hpp" #include "ir/register.hpp" #include "ir/function.hpp" namespace gbe { namespace ir { // Liveness is computed per function class Function; /*! To choose the iteration direction, we either look at predecessors or * successors */ enum DataFlowDirection { DF_PRED = 0, DF_SUCC = 1 }; /*! Compute liveness of each register */ class Liveness : public NonCopyable { public: Liveness(Function &fn); ~Liveness(void); /*! Set of variables used upwards in the block (before a definition) */ typedef set UEVar; /*! Set of variables alive at the exit of the block */ typedef set LiveOut; /*! Set of variables actually killed in each block */ typedef set VarKill; /*! Per-block info */ struct BlockInfo : public NonCopyable { BlockInfo(const BasicBlock &bb) : bb(bb) {} const BasicBlock &bb; INLINE bool inUpwardUsed(Register reg) const { return upwardUsed.contains(reg); } INLINE bool inLiveOut(Register reg) const { return liveOut.contains(reg); } INLINE bool inVarKill(Register reg) const { return varKill.contains(reg); } UEVar upwardUsed; LiveOut liveOut; VarKill varKill; }; /*! Gives for each block the variables alive at entry / exit */ typedef map Info; /*! Return the complete liveness info */ INLINE const Info &getLivenessInfo(void) const { return liveness; } /*! Return the complete block info */ INLINE const BlockInfo &getBlockInfo(const BasicBlock *bb) const { auto it = liveness.find(bb); GBE_ASSERT(it != liveness.end() && it->second != NULL); return *it->second; } /*! Get the set of registers alive at the end of the block */ const LiveOut &getLiveOut(const BasicBlock *bb) const { const BlockInfo &info = this->getBlockInfo(bb); return info.liveOut; } /*! Get the set of registers alive at the beginning of the block */ const UEVar &getLiveIn(const BasicBlock *bb) const { const BlockInfo &info = this->getBlockInfo(bb); return info.upwardUsed; } /*! Return the function the liveness was computed on */ INLINE const Function &getFunction(void) const { return fn; } /*! Actually do something for each successor / predecessor of *all* blocks */ template void foreach(const T &functor) { // Iterate on all blocks for (Info::iterator pair = liveness.begin(); pair != liveness.end(); ++pair) { BlockInfo &info = *(pair->second); const BasicBlock &bb = info.bb; const BlockSet *set = NULL; if (dir == DF_SUCC) set = &bb.getSuccessorSet(); else set = &bb.getPredecessorSet(); // Iterate over all successors for (BlockSet::iterator other = (*set).begin(); other != (*set).end(); ++other) { Info::iterator otherInfo = liveness.find(*other); GBE_ASSERT(otherInfo != liveness.end() && otherInfo->second != NULL); functor(info, *otherInfo->second); } } } private: /*! Store the liveness of all blocks */ Info liveness; /*! Compute the liveness for this function */ Function &fn; /*! Initialize UEVar and VarKill per block */ void initBlock(const BasicBlock &bb); /*! Initialize UEVar and VarKill per instruction */ void initInstruction(BlockInfo &info, const Instruction &insn); /*! Now really compute LiveOut based on UEVar and VarKill */ void computeLiveInOut(void); void computeExtraLiveInOut(set &extentRegs); void analyzeUniform(set *extentRegs); /*! Set of work list block which has exit(return) instruction */ typedef set WorkSet; WorkSet workSet; WorkSet unvisitBlocks; /*! Use custom allocators */ GBE_CLASS(Liveness); }; /*! Output a nice ASCII reprensation of the liveness */ std::ostream &operator<< (std::ostream &out, const Liveness &liveness); } /* namespace ir */ } /* namespace gbe */ #endif /* __GBE_IR_LIVENESS_HPP__ */