Compiler projects using llvm
#ifndef INCLUDE_UNIT_LOOP_INFO_H
#define INCLUDE_UNIT_LOOP_INFO_H

#include <vector>
#include <memory>
#include "llvm/IR/PassManager.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AliasSetTracker.h"


namespace llvm {
    class Value;
    class Instruction;
    class BasicBlock;
    class DominatorTree;
    class LoadInst;
    class StoreInst;
}

using namespace llvm;

namespace ece479k {

struct UnitLoopInfo {
private:
    // The basic blocks that form this loop
    SmallPtrSet<BasicBlock*, 16> set;
    // The blocks in *reverse* order
    SmallVector<BasicBlock*, 16> blocks;
public:
    BasicBlock const* header;
    BasicBlock const* preheader;
    SmallPtrSet<BasicBlock const*, 4> exits;
private:
    std::unique_ptr<AliasSetTracker> alias_sets;
public:
    using alias_results = AAResults&;

    // Record a natural loop given its backedge from end to header
    UnitLoopInfo(BasicBlock* header, BasicBlock* end, alias_results AA, DominatorTree& DT);

    /*loop properties*/
    [[nodiscard]] bool contains(BasicBlock const*) const;
    [[nodiscard]] bool contains(BasicBlock const&) const;
    [[nodiscard]] bool contains(Instruction const*) const;
    [[nodiscard]] bool contains(Instruction const&) const;
    [[nodiscard]] bool contains(Value const*) const;
    [[nodiscard]] bool contains(Value const&) const;

    /*loop invariants*/
    [[nodiscard]] bool is_invariant(Value const*) const;
    [[nodiscard]] bool is_invariant(Value const&) const;
    [[nodiscard]] bool is_invariant(Instruction const*) const;
    [[nodiscard]] bool is_invariant(Instruction const&) const;
    [[nodiscard]] bool has_invariant_operands(Instruction const*) const;
    [[nodiscard]] bool has_invariant_operands(Instruction const&) const;

    /*utility*/
    [[nodiscard]] std::vector<Instruction*> instructions() const;
    [[nodiscard]] std::vector<Instruction*> instructions(std::function<bool(Instruction const&)> const&) const;
    [[nodiscard]] AliasSet const& alias_for(LoadInst const*) const;
    [[nodiscard]] AliasSet const& alias_for(StoreInst const*) const;
};

/// Loop Identification Analysis Pass. Produces a UnitLoopInfo object which
/// should contain any information about the loops in the function which is
/// needed for your implementation of LICM
class UnitLoopAnalysis : public AnalysisInfoMixin<UnitLoopAnalysis> {
    friend AnalysisInfoMixin<UnitLoopAnalysis>;
    static AnalysisKey Key;

public:
    using Result = std::vector<UnitLoopInfo>;

    Result run(Function &F, FunctionAnalysisManager &AM);
};

} // namespace ece479k
#endif // INCLUDE_UNIT_LOOP_INFO_H