Jakob Stoklund Olesen | ceadc01 | 2010-12-15 23:41:23 +0000 | [diff] [blame] | 1 | //===- MachineLoopRanges.cpp - Ranges of machine loops --------------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file provides the implementation of the MachineLoopRanges analysis. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #include "llvm/CodeGen/MachineLoopRanges.h" |
| 15 | #include "llvm/CodeGen/MachineLoopInfo.h" |
| 16 | #include "llvm/CodeGen/Passes.h" |
| 17 | |
| 18 | using namespace llvm; |
| 19 | |
| 20 | char MachineLoopRanges::ID = 0; |
| 21 | INITIALIZE_PASS_BEGIN(MachineLoopRanges, "machine-loop-ranges", |
| 22 | "Machine Loop Ranges", true, true) |
| 23 | INITIALIZE_PASS_DEPENDENCY(SlotIndexes) |
| 24 | INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) |
| 25 | INITIALIZE_PASS_END(MachineLoopRanges, "machine-loop-ranges", |
| 26 | "Machine Loop Ranges", true, true) |
| 27 | |
| 28 | char &llvm::MachineLoopRangesID = MachineLoopRanges::ID; |
| 29 | |
| 30 | void MachineLoopRanges::getAnalysisUsage(AnalysisUsage &AU) const { |
| 31 | AU.setPreservesAll(); |
| 32 | AU.addRequiredTransitive<SlotIndexes>(); |
| 33 | AU.addRequiredTransitive<MachineLoopInfo>(); |
| 34 | MachineFunctionPass::getAnalysisUsage(AU); |
| 35 | } |
| 36 | |
| 37 | /// runOnMachineFunction - Don't do much, loop ranges are computed on demand. |
| 38 | bool MachineLoopRanges::runOnMachineFunction(MachineFunction &) { |
| 39 | releaseMemory(); |
| 40 | Indexes = &getAnalysis<SlotIndexes>(); |
| 41 | return false; |
| 42 | } |
| 43 | |
| 44 | void MachineLoopRanges::releaseMemory() { |
| 45 | DeleteContainerSeconds(Cache); |
| 46 | Cache.clear(); |
| 47 | } |
| 48 | |
| 49 | MachineLoopRange *MachineLoopRanges::getLoopRange(const MachineLoop *Loop) { |
| 50 | MachineLoopRange *&Range = Cache[Loop]; |
| 51 | if (!Range) |
| 52 | Range = new MachineLoopRange(Loop, Allocator, *Indexes); |
| 53 | return Range; |
| 54 | } |
| 55 | |
| 56 | /// Create a MachineLoopRange, only accessible to MachineLoopRanges. |
| 57 | MachineLoopRange::MachineLoopRange(const MachineLoop *loop, |
| 58 | MachineLoopRange::Allocator &alloc, |
| 59 | SlotIndexes &Indexes) |
Jakob Stoklund Olesen | 090100f | 2010-12-17 18:13:52 +0000 | [diff] [blame] | 60 | : Loop(loop), Intervals(alloc), Area(0) { |
Jakob Stoklund Olesen | ceadc01 | 2010-12-15 23:41:23 +0000 | [diff] [blame] | 61 | // Compute loop coverage. |
| 62 | for (MachineLoop::block_iterator I = Loop->block_begin(), |
| 63 | E = Loop->block_end(); I != E; ++I) { |
| 64 | const std::pair<SlotIndex, SlotIndex> &Range = Indexes.getMBBRange(*I); |
| 65 | Intervals.insert(Range.first, Range.second, 1u); |
Jakob Stoklund Olesen | 090100f | 2010-12-17 18:13:52 +0000 | [diff] [blame] | 66 | Area += Range.first.distance(Range.second); |
Jakob Stoklund Olesen | ceadc01 | 2010-12-15 23:41:23 +0000 | [diff] [blame] | 67 | } |
| 68 | } |
| 69 | |
| 70 | /// overlaps - Return true if this loop overlaps the given range of machine |
| 71 | /// instructions. |
| 72 | bool MachineLoopRange::overlaps(SlotIndex Start, SlotIndex Stop) { |
Jakob Stoklund Olesen | ff2e9b4 | 2010-12-17 04:09:47 +0000 | [diff] [blame] | 73 | Map::const_iterator I = Intervals.find(Start); |
Jakob Stoklund Olesen | ceadc01 | 2010-12-15 23:41:23 +0000 | [diff] [blame] | 74 | return I.valid() && Stop > I.start(); |
| 75 | } |
| 76 | |
Jakob Stoklund Olesen | 090100f | 2010-12-17 18:13:52 +0000 | [diff] [blame] | 77 | unsigned MachineLoopRange::getNumber() const { |
| 78 | return Loop->getHeader()->getNumber(); |
| 79 | } |
| 80 | |
| 81 | /// byNumber - Comparator for array_pod_sort that sorts a list of |
| 82 | /// MachineLoopRange pointers by number. |
| 83 | int MachineLoopRange::byNumber(const void *pa, const void *pb) { |
| 84 | const MachineLoopRange *a = *static_cast<MachineLoopRange *const *>(pa); |
| 85 | const MachineLoopRange *b = *static_cast<MachineLoopRange *const *>(pb); |
| 86 | unsigned na = a->getNumber(); |
| 87 | unsigned nb = b->getNumber(); |
| 88 | if (na < nb) |
| 89 | return -1; |
| 90 | if (na > nb) |
| 91 | return 1; |
| 92 | return 0; |
| 93 | } |
| 94 | |
| 95 | /// byAreaDesc - Comparator for array_pod_sort that sorts a list of |
| 96 | /// MachineLoopRange pointers by: |
| 97 | /// 1. Descending area. |
| 98 | /// 2. Ascending number. |
| 99 | int MachineLoopRange::byAreaDesc(const void *pa, const void *pb) { |
| 100 | const MachineLoopRange *a = *static_cast<MachineLoopRange *const *>(pa); |
| 101 | const MachineLoopRange *b = *static_cast<MachineLoopRange *const *>(pb); |
| 102 | if (a->getArea() != b->getArea()) |
| 103 | return a->getArea() > b->getArea() ? -1 : 1; |
| 104 | return byNumber(pa, pb); |
| 105 | } |
| 106 | |
Jakob Stoklund Olesen | ceadc01 | 2010-12-15 23:41:23 +0000 | [diff] [blame] | 107 | void MachineLoopRange::print(raw_ostream &OS) const { |
Jakob Stoklund Olesen | 090100f | 2010-12-17 18:13:52 +0000 | [diff] [blame] | 108 | OS << "Loop#" << getNumber() << " ="; |
Jakob Stoklund Olesen | ff2e9b4 | 2010-12-17 04:09:47 +0000 | [diff] [blame] | 109 | for (Map::const_iterator I = Intervals.begin(); I.valid(); ++I) |
Jakob Stoklund Olesen | ceadc01 | 2010-12-15 23:41:23 +0000 | [diff] [blame] | 110 | OS << " [" << I.start() << ';' << I.stop() << ')'; |
| 111 | } |
| 112 | |
| 113 | raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineLoopRange &MLR) { |
| 114 | MLR.print(OS); |
| 115 | return OS; |
| 116 | } |