InterferenceCache.h revision f1c709837bd11c5383fce3b8a026a7c8eaabba86
15907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen//===-- InterferenceCache.h - Caching per-block interference ---*- C++ -*--===//
25907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen//
35907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen//                     The LLVM Compiler Infrastructure
45907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen//
55907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen// This file is distributed under the University of Illinois Open Source
65907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen// License. See LICENSE.TXT for details.
75907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen//
85907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen//===----------------------------------------------------------------------===//
95907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen//
105907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen// InterferenceCache remembers per-block interference in LiveIntervalUnions.
115907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen//
125907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen//===----------------------------------------------------------------------===//
135907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
145907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen#ifndef LLVM_CODEGEN_INTERFERENCECACHE
155907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen#define LLVM_CODEGEN_INTERFERENCECACHE
165907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
175907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen#include "LiveIntervalUnion.h"
185907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
195907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesennamespace llvm {
205907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
215907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesenclass InterferenceCache {
225907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  const TargetRegisterInfo *TRI;
235907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  LiveIntervalUnion *LIUArray;
245907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  SlotIndexes *Indexes;
255907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  MachineFunction *MF;
265907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
275907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  /// BlockInterference - information about the interference in a single basic
285907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  /// block.
295907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  struct BlockInterference {
305907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    BlockInterference() : Tag(0) {}
315907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    unsigned Tag;
325907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    SlotIndex First;
335907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    SlotIndex Last;
345907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  };
355907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
365907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  /// Entry - A cache entry containing interference information for all aliases
375907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  /// of PhysReg in all basic blocks.
385907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  class Entry {
395907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    /// PhysReg - The register currently represented.
405907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    unsigned PhysReg;
415907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
425907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    /// Tag - Cache tag is changed when any of the underlying LiveIntervalUnions
435907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    /// change.
445907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    unsigned Tag;
455907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
46f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen    /// RefCount - The total number of Cursor instances referring to this Entry.
47f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen    unsigned RefCount;
48f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen
499d29cbad32814f31c91cd2464a3c74df412b0aacJakob Stoklund Olesen    /// MF - The current function.
509d29cbad32814f31c91cd2464a3c74df412b0aacJakob Stoklund Olesen    MachineFunction *MF;
519d29cbad32814f31c91cd2464a3c74df412b0aacJakob Stoklund Olesen
525907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    /// Indexes - Mapping block numbers to SlotIndex ranges.
535907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    SlotIndexes *Indexes;
545907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
555907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    /// PrevPos - The previous position the iterators were moved to.
565907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    SlotIndex PrevPos;
575907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
585907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    /// AliasTags - A LiveIntervalUnion pointer and tag for each alias of
595907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    /// PhysReg.
605907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    SmallVector<std::pair<LiveIntervalUnion*, unsigned>, 8> Aliases;
615907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
625907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    typedef LiveIntervalUnion::SegmentIter Iter;
635907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
645907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    /// Iters - an iterator for each alias
655907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    SmallVector<Iter, 8> Iters;
665907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
675907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    /// Blocks - Interference for each block in the function.
685907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    SmallVector<BlockInterference, 8> Blocks;
695907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
705907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    /// update - Recompute Blocks[MBBNum]
715907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    void update(unsigned MBBNum);
725907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
735907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  public:
74f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen    Entry() : PhysReg(0), Tag(0), RefCount(0), Indexes(0) {}
755907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
769d29cbad32814f31c91cd2464a3c74df412b0aacJakob Stoklund Olesen    void clear(MachineFunction *mf, SlotIndexes *indexes) {
77f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen      assert(!hasRefs() && "Cannot clear cache entry with references");
785907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen      PhysReg = 0;
799d29cbad32814f31c91cd2464a3c74df412b0aacJakob Stoklund Olesen      MF = mf;
805907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen      Indexes = indexes;
815907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    }
825907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
835907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    unsigned getPhysReg() const { return PhysReg; }
845907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
85f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen    void addRef(int Delta) { RefCount += Delta; }
86f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen
87f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen    bool hasRefs() const { return RefCount > 0; }
88f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen
895907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    void revalidate();
905907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
915907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    /// valid - Return true if this is a valid entry for physReg.
925907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    bool valid(LiveIntervalUnion *LIUArray, const TargetRegisterInfo *TRI);
935907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
945907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    /// reset - Initialize entry to represent physReg's aliases.
955907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    void reset(unsigned physReg,
965907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen               LiveIntervalUnion *LIUArray,
975907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen               const TargetRegisterInfo *TRI,
985907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen               const MachineFunction *MF);
995907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
1005907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    /// get - Return an up to date BlockInterference.
1015907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    BlockInterference *get(unsigned MBBNum) {
1025907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen      if (Blocks[MBBNum].Tag != Tag)
1035907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen        update(MBBNum);
1045907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen      return &Blocks[MBBNum];
1055907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    }
1065907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  };
1075907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
1085907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  // We don't keep a cache entry for every physical register, that would use too
1095907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  // much memory. Instead, a fixed number of cache entries are used in a round-
1105907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  // robin manner.
1115907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  enum { CacheEntries = 32 };
1125907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
1135907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  // Point to an entry for each physreg. The entry pointed to may not be up to
1145907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  // date, and it may have been reused for a different physreg.
1155907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  SmallVector<unsigned char, 2> PhysRegEntries;
1165907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
1175907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  // Next round-robin entry to be picked.
1185907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  unsigned RoundRobin;
1195907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
1205907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  // The actual cache entries.
1215907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  Entry Entries[CacheEntries];
1225907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
1235907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  // get - Get a valid entry for PhysReg.
1245907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  Entry *get(unsigned PhysReg);
1255907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
1265907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesenpublic:
1275907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  InterferenceCache() : TRI(0), LIUArray(0), Indexes(0), MF(0), RoundRobin(0) {}
1285907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
1295907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  /// init - Prepare cache for a new function.
1305907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  void init(MachineFunction*, LiveIntervalUnion*, SlotIndexes*,
1315907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen            const TargetRegisterInfo *);
1325907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
133f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen  /// getMaxCursors - Return the maximum number of concurrent cursors that can
134f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen  /// be supported.
135f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen  unsigned getMaxCursors() const { return CacheEntries; }
136f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen
1375907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  /// Cursor - The primary query interface for the block interference cache.
1385907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  class Cursor {
1395907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    Entry *CacheEntry;
1405907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    BlockInterference *Current;
141f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen
142f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen    void setEntry(Entry *E) {
143f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen      Current = 0;
144f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen      // Update reference counts. Nothing happens when RefCount reaches 0, so
145f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen      // we don't have to check for E == CacheEntry etc.
146f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen      if (CacheEntry)
147f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen        CacheEntry->addRef(-1);
148f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen      CacheEntry = E;
149f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen      if (CacheEntry)
150f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen        CacheEntry->addRef(+1);
151f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen    }
152f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen
1535907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  public:
154c66a37df73f70ec3dbed06277763624f33ee3512Jakob Stoklund Olesen    /// Cursor - Create a dangling cursor.
155c66a37df73f70ec3dbed06277763624f33ee3512Jakob Stoklund Olesen    Cursor() : CacheEntry(0), Current(0) {}
156f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen    ~Cursor() { setEntry(0); }
157f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen
158f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen    Cursor(const Cursor &O) : CacheEntry(0), Current(0) {
159f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen      setEntry(O.CacheEntry);
160f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen    }
161f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen
162f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen    Cursor &operator=(const Cursor &O) {
163f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen      setEntry(O.CacheEntry);
164f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen      return *this;
165f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen    }
166c66a37df73f70ec3dbed06277763624f33ee3512Jakob Stoklund Olesen
167c66a37df73f70ec3dbed06277763624f33ee3512Jakob Stoklund Olesen    /// setPhysReg - Point this cursor to PhysReg's interference.
168c66a37df73f70ec3dbed06277763624f33ee3512Jakob Stoklund Olesen    void setPhysReg(InterferenceCache &Cache, unsigned PhysReg) {
169f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen      // Release reference before getting a new one. That guarantees we can
170f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen      // actually have CacheEntries live cursors.
171f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen      setEntry(0);
172f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen      if (PhysReg)
173f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen        setEntry(Cache.get(PhysReg));
174c66a37df73f70ec3dbed06277763624f33ee3512Jakob Stoklund Olesen    }
1755907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
1765907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    /// moveTo - Move cursor to basic block MBBNum.
1775907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    void moveToBlock(unsigned MBBNum) {
1785907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen      Current = CacheEntry->get(MBBNum);
1795907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    }
1805907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
1815907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    /// hasInterference - Return true if the current block has any interference.
1825907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    bool hasInterference() {
1835907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen      return Current->First.isValid();
1845907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    }
1855907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
1865907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    /// first - Return the starting index of the first interfering range in the
1875907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    /// current block.
1885907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    SlotIndex first() {
1895907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen      return Current->First;
1905907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    }
1915907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
1925907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    /// last - Return the ending index of the last interfering range in the
1935907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    /// current block.
1945907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    SlotIndex last() {
1955907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen      return Current->Last;
1965907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen    }
1975907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  };
1985907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
1995907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen  friend class Cursor;
2005907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen};
2015907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
2025907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen} // namespace llvm
2035907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen
2045907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen#endif
205