//===----- HexagonMCChecker.h - Instruction bundle checking ---------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This implements the checking of insns inside a bundle according to the // packet constraint rules of the Hexagon ISA. // //===----------------------------------------------------------------------===// #ifndef HEXAGONMCCHECKER_H #define HEXAGONMCCHECKER_H #include <map> #include <set> #include <queue> #include "MCTargetDesc/HexagonMCShuffler.h" using namespace llvm; namespace llvm { class MCOperandInfo; typedef struct { unsigned Error, Warning, ShuffleError; unsigned Register; } ErrInfo_T; class HexagonMCErrInfo { public: enum { CHECK_SUCCESS = 0, // Errors. CHECK_ERROR_BRANCHES = 0x00001, CHECK_ERROR_NEWP = 0x00002, CHECK_ERROR_NEWV = 0x00004, CHECK_ERROR_REGISTERS = 0x00008, CHECK_ERROR_READONLY = 0x00010, CHECK_ERROR_LOOP = 0x00020, CHECK_ERROR_ENDLOOP = 0x00040, CHECK_ERROR_SOLO = 0x00080, CHECK_ERROR_SHUFFLE = 0x00100, CHECK_ERROR_NOSLOTS = 0x00200, CHECK_ERROR_UNKNOWN = 0x00400, // Warnings. CHECK_WARN_CURRENT = 0x10000, CHECK_WARN_TEMPORARY = 0x20000 }; ErrInfo_T s; void reset() { s.Error = CHECK_SUCCESS; s.Warning = CHECK_SUCCESS; s.ShuffleError = HexagonShuffler::SHUFFLE_SUCCESS; s.Register = Hexagon::NoRegister; }; HexagonMCErrInfo() { reset(); }; void setError(unsigned e, unsigned r = Hexagon::NoRegister) { s.Error = e; s.Register = r; }; void setWarning(unsigned w, unsigned r = Hexagon::NoRegister) { s.Warning = w; s.Register = r; }; void setShuffleError(unsigned e) { s.ShuffleError = e; }; }; /// Check for a valid bundle. class HexagonMCChecker { /// Insn bundle. MCInst& MCB; MCInst& MCBDX; const MCRegisterInfo& RI; MCInstrInfo const &MCII; MCSubtargetInfo const &STI; bool bLoadErrInfo; /// Set of definitions: register #, if predicated, if predicated true. typedef std::pair<unsigned, bool> PredSense; static const PredSense Unconditional; typedef std::multiset<PredSense> PredSet; typedef std::multiset<PredSense>::iterator PredSetIterator; typedef llvm::DenseMap<unsigned, PredSet>::iterator DefsIterator; llvm::DenseMap<unsigned, PredSet> Defs; /// Information about how a new-value register is defined or used: /// PredReg = predicate register, 0 if use/def not predicated, /// Cond = true/false for if(PredReg)/if(!PredReg) respectively, /// IsFloat = true if definition produces a floating point value /// (not valid for uses), /// IsNVJ = true if the use is a new-value branch (not valid for /// definitions). struct NewSense { unsigned PredReg; bool IsFloat, IsNVJ, Cond; // The special-case "constructors": static NewSense Jmp(bool isNVJ) { NewSense NS = { /*PredReg=*/ 0, /*IsFloat=*/ false, /*IsNVJ=*/ isNVJ, /*Cond=*/ false }; return NS; } static NewSense Use(unsigned PR, bool True) { NewSense NS = { /*PredReg=*/ PR, /*IsFloat=*/ false, /*IsNVJ=*/ false, /*Cond=*/ True }; return NS; } static NewSense Def(unsigned PR, bool True, bool Float) { NewSense NS = { /*PredReg=*/ PR, /*IsFloat=*/ Float, /*IsNVJ=*/ false, /*Cond=*/ True }; return NS; } }; /// Set of definitions that produce new register: typedef llvm::SmallVector<NewSense,2> NewSenseList; typedef llvm::DenseMap<unsigned, NewSenseList>::iterator NewDefsIterator; llvm::DenseMap<unsigned, NewSenseList> NewDefs; /// Set of weak definitions whose clashes should be enforced selectively. typedef std::set<unsigned>::iterator SoftDefsIterator; std::set<unsigned> SoftDefs; /// Set of current definitions committed to the register file. typedef std::set<unsigned>::iterator CurDefsIterator; std::set<unsigned> CurDefs; /// Set of temporary definitions not committed to the register file. typedef std::set<unsigned>::iterator TmpDefsIterator; std::set<unsigned> TmpDefs; /// Set of new predicates used. typedef std::set<unsigned>::iterator NewPredsIterator; std::set<unsigned> NewPreds; /// Set of predicates defined late. typedef std::multiset<unsigned>::iterator LatePredsIterator; std::multiset<unsigned> LatePreds; /// Set of uses. typedef std::set<unsigned>::iterator UsesIterator; std::set<unsigned> Uses; /// Set of new values used: new register, if new-value jump. typedef llvm::DenseMap<unsigned, NewSense>::iterator NewUsesIterator; llvm::DenseMap<unsigned, NewSense> NewUses; /// Pre-defined set of read-only registers. typedef std::set<unsigned>::iterator ReadOnlyIterator; std::set<unsigned> ReadOnly; std::queue<ErrInfo_T> ErrInfoQ; HexagonMCErrInfo CrntErrInfo; void getErrInfo() { if (bLoadErrInfo == true) { if (ErrInfoQ.empty()) { CrntErrInfo.reset(); } else { CrntErrInfo.s = ErrInfoQ.front(); ErrInfoQ.pop(); } } bLoadErrInfo = false; } void init(); void init(MCInst const&); // Checks performed. bool checkBranches(); bool checkPredicates(); bool checkNewValues(); bool checkRegisters(); bool checkSolo(); bool checkShuffle(); bool checkSlots(); static void compoundRegisterMap(unsigned&); bool isPredicateRegister(unsigned R) const { return (Hexagon::P0 == R || Hexagon::P1 == R || Hexagon::P2 == R || Hexagon::P3 == R); }; bool isLoopRegister(unsigned R) const { return (Hexagon::SA0 == R || Hexagon::LC0 == R || Hexagon::SA1 == R || Hexagon::LC1 == R); }; bool hasValidNewValueDef(const NewSense &Use, const NewSenseList &Defs) const; public: explicit HexagonMCChecker(MCInstrInfo const &MCII, MCSubtargetInfo const &STI, MCInst& mcb, MCInst &mcbdx, const MCRegisterInfo& ri); bool check(); /// add a new error/warning void addErrInfo(HexagonMCErrInfo &err) { ErrInfoQ.push(err.s); }; /// Return the error code for the last operation in the insn bundle. unsigned getError() { getErrInfo(); return CrntErrInfo.s.Error; }; unsigned getWarning() { getErrInfo(); return CrntErrInfo.s.Warning; }; unsigned getShuffleError() { getErrInfo(); return CrntErrInfo.s.ShuffleError; }; unsigned getErrRegister() { getErrInfo(); return CrntErrInfo.s.Register; }; bool getNextErrInfo() { bLoadErrInfo = true; return (ErrInfoQ.empty()) ? false : (getErrInfo(), true); } }; } #endif // HEXAGONMCCHECKER_H