DirectXShaderCompiler/lib/CodeGen/LiveIntervalUnion.cpp

206 строки
6.6 KiB
C++
Исходник Обычный вид История

2016-12-28 22:52:27 +03:00
//===-- LiveIntervalUnion.cpp - Live interval union data structure --------===//
Revert license text in banner comments to original llvm verbage (#33) Fix #30: Revert license text in banner comments to original llvm verbage This commit removes the Microsoft-specific copyright in llvm files and reverts the copyright wording to the original llvm wording. We used the following method to find the files to change: 1. Find all files in DirectXShaderCompiler that are also in llvm 3.7 2. For those files that have the Microsoft-specific copyright, revert it to the original llvm copyright as present in llvm 3.7 3. Revert the copyright in a few files that are not in llvm, but are mostly copies of files in llvm: lib\Transforms\Scalar\ScalarReplAggregatesHLSL.cpp lib\Transforms\Scalar\Reg2MemHLSL.cpp Leave the Microsoft-specific copyright header in files not present in stock llvm: include\dxc\* lib\HLSL\* lib\DxcSupport\* tools\clang\test\HLSL\* tools\clang\test\CodeGenHLSL\* tools\clang\unittests\HLSL\* tools\clang\unittests\HLSLHost\* tools\clang\tools\dxcompiler\* tools\clang\tools\dxa\* tools\clang\tools\dxc\* tools\clang\tools\dxopt\* tools\clang\tools\dxr\* tools\clang\tools\dxv\* tools\clang\tools\dotnetc\* utils\hct\* CONTRIBUTING.md COPYRIGHT LICENSE-MIT README.md cmake\modules\FindD3D12.cmake cmake\modules\FindDiaSDK.cmake cmake\modules\FindTAEF.cmake docs\DXIL.rst docs\HLSLChanges.rst docs\_themes\dxc-theme\layout.html docs\_themes\dxc-theme\theme.conf docs\_themes\dxc-theme\static\dxc-theme.css include\llvm\llvm_assert\assert.h include\llvm\llvm_assert\cassert include\llvm\Support\MSFileSystem.h include\llvm\Support\OacrIgnoreCond.h lib\MSSupport\CMakeLists.txt lib\MSSupport\MSFileSystemImpl.cpp lib\Support\assert.cpp lib\Support\MSFileSystemBasic.cpp lib\Support\Windows\MSFileSystem.inc.cpp lib\Transforms\Scalar\Reg2MemHLSL.cpp lib\Transforms\Scalar\ScalarReplAggregatesHLSL.cpp tools\clang\docs\UsingDxc.rst tools\clang\include\clang\AST\HlslTypes.h tools\clang\include\clang\Basic\BuiltinsDXIL.def tools\clang\include\clang\Basic\LangOptions.fixed.def tools\clang\include\clang\Parse\ParseHLSL.h tools\clang\include\clang\Sema\SemaHLSL.h tools\clang\lib\AST\ASTContextHLSL.cpp tools\clang\lib\AST\HlslTypes.cpp tools\clang\lib\CodeGen\CGHLSLMS.cpp tools\clang\lib\CodeGen\CGHLSLRuntime.cpp tools\clang\lib\CodeGen\CGHLSLRuntime.h tools\clang\lib\Frontend\Rewrite\FrontendActions_rewrite.cpp tools\clang\lib\Parse\HLSLRootSignature.cpp tools\clang\lib\Parse\HLSLRootSignature.h tools\clang\lib\Parse\ParseHLSL.cpp tools\clang\lib\Sema\gen_intrin_main_tables_15.h tools\clang\lib\Sema\SemaHLSL.cpp tools\clang\tools\d3dcomp\CMakeLists.txt tools\clang\tools\d3dcomp\d3dcomp.cpp tools\clang\tools\d3dcomp\d3dcomp.def tools\clang\tools\libclang\dxcisenseimpl.cpp tools\clang\tools\libclang\dxcisenseimpl.h tools\clang\tools\libclang\dxcrewriteunused.cpp tools\clang\tools\libclang\libclang.rc tools\dxexp\CMakeLists.txt tools\dxexp\dxexp.cpp tools\dxexp\LLVMBuild.txt
2017-01-25 04:54:00 +03:00
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// LiveIntervalUnion represents a coalesced set of live intervals. This may be
// used during coalescing to represent a congruence class, or during register
// allocation to model liveness of a physical register.
//
//===----------------------------------------------------------------------===//
2016-12-28 22:52:27 +03:00
#include "llvm/CodeGen/LiveIntervalUnion.h"
#include "llvm/ADT/SparseBitVector.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include <algorithm>
using namespace llvm;
#define DEBUG_TYPE "regalloc"
// Merge a LiveInterval's segments. Guarantee no overlaps.
void LiveIntervalUnion::unify(LiveInterval &VirtReg, const LiveRange &Range) {
if (Range.empty())
return;
++Tag;
// Insert each of the virtual register's live segments into the map.
LiveRange::const_iterator RegPos = Range.begin();
LiveRange::const_iterator RegEnd = Range.end();
SegmentIter SegPos = Segments.find(RegPos->start);
while (SegPos.valid()) {
SegPos.insert(RegPos->start, RegPos->end, &VirtReg);
if (++RegPos == RegEnd)
return;
SegPos.advanceTo(RegPos->start);
}
// We have reached the end of Segments, so it is no longer necessary to search
// for the insertion position.
// It is faster to insert the end first.
--RegEnd;
SegPos.insert(RegEnd->start, RegEnd->end, &VirtReg);
for (; RegPos != RegEnd; ++RegPos, ++SegPos)
SegPos.insert(RegPos->start, RegPos->end, &VirtReg);
}
// Remove a live virtual register's segments from this union.
void LiveIntervalUnion::extract(LiveInterval &VirtReg, const LiveRange &Range) {
if (Range.empty())
return;
++Tag;
// Remove each of the virtual register's live segments from the map.
LiveRange::const_iterator RegPos = Range.begin();
LiveRange::const_iterator RegEnd = Range.end();
SegmentIter SegPos = Segments.find(RegPos->start);
for (;;) {
assert(SegPos.value() == &VirtReg && "Inconsistent LiveInterval");
SegPos.erase();
if (!SegPos.valid())
return;
// Skip all segments that may have been coalesced.
RegPos = Range.advanceTo(RegPos, SegPos.start());
if (RegPos == RegEnd)
return;
SegPos.advanceTo(RegPos->start);
}
}
void
LiveIntervalUnion::print(raw_ostream &OS, const TargetRegisterInfo *TRI) const {
if (empty()) {
OS << " empty\n";
return;
}
for (LiveSegments::const_iterator SI = Segments.begin(); SI.valid(); ++SI) {
OS << " [" << SI.start() << ' ' << SI.stop() << "):"
<< PrintReg(SI.value()->reg, TRI);
}
OS << '\n';
}
#ifndef NDEBUG
// Verify the live intervals in this union and add them to the visited set.
void LiveIntervalUnion::verify(LiveVirtRegBitSet& VisitedVRegs) {
for (SegmentIter SI = Segments.begin(); SI.valid(); ++SI)
VisitedVRegs.set(SI.value()->reg);
}
#endif //!NDEBUG
// Scan the vector of interfering virtual registers in this union. Assume it's
// quite small.
bool LiveIntervalUnion::Query::isSeenInterference(LiveInterval *VirtReg) const {
SmallVectorImpl<LiveInterval*>::const_iterator I =
std::find(InterferingVRegs.begin(), InterferingVRegs.end(), VirtReg);
return I != InterferingVRegs.end();
}
// Collect virtual registers in this union that interfere with this
// query's live virtual register.
//
// The query state is one of:
//
// 1. CheckedFirstInterference == false: Iterators are uninitialized.
// 2. SeenAllInterferences == true: InterferingVRegs complete, iterators unused.
// 3. Iterators left at the last seen intersection.
//
unsigned LiveIntervalUnion::Query::
collectInterferingVRegs(unsigned MaxInterferingRegs) {
// Fast path return if we already have the desired information.
if (SeenAllInterferences || InterferingVRegs.size() >= MaxInterferingRegs)
return InterferingVRegs.size();
// Set up iterators on the first call.
if (!CheckedFirstInterference) {
CheckedFirstInterference = true;
// Quickly skip interference check for empty sets.
if (VirtReg->empty() || LiveUnion->empty()) {
SeenAllInterferences = true;
return 0;
}
// In most cases, the union will start before VirtReg.
VirtRegI = VirtReg->begin();
LiveUnionI.setMap(LiveUnion->getMap());
LiveUnionI.find(VirtRegI->start);
}
LiveInterval::iterator VirtRegEnd = VirtReg->end();
LiveInterval *RecentReg = nullptr;
while (LiveUnionI.valid()) {
assert(VirtRegI != VirtRegEnd && "Reached end of VirtReg");
// Check for overlapping interference.
while (VirtRegI->start < LiveUnionI.stop() &&
VirtRegI->end > LiveUnionI.start()) {
// This is an overlap, record the interfering register.
LiveInterval *VReg = LiveUnionI.value();
if (VReg != RecentReg && !isSeenInterference(VReg)) {
RecentReg = VReg;
InterferingVRegs.push_back(VReg);
if (InterferingVRegs.size() >= MaxInterferingRegs)
return InterferingVRegs.size();
}
// This LiveUnion segment is no longer interesting.
if (!(++LiveUnionI).valid()) {
SeenAllInterferences = true;
return InterferingVRegs.size();
}
}
// The iterators are now not overlapping, LiveUnionI has been advanced
// beyond VirtRegI.
assert(VirtRegI->end <= LiveUnionI.start() && "Expected non-overlap");
// Advance the iterator that ends first.
VirtRegI = VirtReg->advanceTo(VirtRegI, LiveUnionI.start());
if (VirtRegI == VirtRegEnd)
break;
// Detect overlap, handle above.
if (VirtRegI->start < LiveUnionI.stop())
continue;
// Still not overlapping. Catch up LiveUnionI.
LiveUnionI.advanceTo(VirtRegI->start);
}
SeenAllInterferences = true;
return InterferingVRegs.size();
}
void LiveIntervalUnion::Array::init(LiveIntervalUnion::Allocator &Alloc,
unsigned NSize) {
// Reuse existing allocation.
if (NSize == Size)
return;
clear();
Size = NSize;
LIUs = static_cast<LiveIntervalUnion*>(
new char[sizeof(LiveIntervalUnion)*NSize]); // HLSL Change: Use overridable operator new
2016-12-28 22:52:27 +03:00
for (unsigned i = 0; i != Size; ++i)
new(LIUs + i) LiveIntervalUnion(Alloc);
}
void LiveIntervalUnion::Array::clear() {
if (!LIUs)
return;
for (unsigned i = 0; i != Size; ++i)
LIUs[i].~LiveIntervalUnion();
delete[] static_cast<char*>(LIUs); // HLSL Change: Use overridable operator delete
2016-12-28 22:52:27 +03:00
Size = 0;
LIUs = nullptr;
}