diff options
Diffstat (limited to 'llvm/tools')
-rw-r--r-- | llvm/tools/llvm-mca/CodeRegion.cpp | 96 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/CodeRegion.h | 8 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/CodeRegionGenerator.cpp | 6 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/llvm-mca.cpp | 5 |
4 files changed, 88 insertions, 27 deletions
diff --git a/llvm/tools/llvm-mca/CodeRegion.cpp b/llvm/tools/llvm-mca/CodeRegion.cpp index eb04ea3f0d8..bf592f67245 100644 --- a/llvm/tools/llvm-mca/CodeRegion.cpp +++ b/llvm/tools/llvm-mca/CodeRegion.cpp @@ -16,7 +16,7 @@ namespace llvm { namespace mca { -CodeRegions::CodeRegions(llvm::SourceMgr &S) : SM(S) { +CodeRegions::CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) { // Create a default region for the input code sequence. Regions.emplace_back(make_unique<CodeRegion>("", SMLoc())); } @@ -30,41 +30,87 @@ bool CodeRegion::isLocInRange(SMLoc Loc) const { } void CodeRegions::beginRegion(StringRef Description, SMLoc Loc) { - assert(!Regions.empty() && "Missing Default region"); - const CodeRegion &CurrentRegion = *Regions.back(); - if (CurrentRegion.startLoc().isValid() && !CurrentRegion.endLoc().isValid()) { - SM.PrintMessage(Loc, SourceMgr::DK_Warning, - "Ignoring invalid region start"); - return; + if (ActiveRegions.empty()) { + // Remove the default region if there is at least one user defined region. + // By construction, only the default region has an invalid start location. + if (Regions.size() == 1 && !Regions[0]->startLoc().isValid() && + !Regions[0]->endLoc().isValid()) { + ActiveRegions[Description] = 0; + Regions[0] = make_unique<CodeRegion>(Description, Loc); + return; + } + } else { + auto It = ActiveRegions.find(Description); + if (It != ActiveRegions.end()) { + const CodeRegion &R = *Regions[It->second]; + if (Description.empty()) { + SM.PrintMessage(Loc, SourceMgr::DK_Error, + "found multiple overlapping anonymous regions"); + SM.PrintMessage(R.startLoc(), SourceMgr::DK_Note, + "Previous anonymous region was defined here"); + FoundErrors = true; + return; + } + + SM.PrintMessage(Loc, SourceMgr::DK_Error, + "overlapping regions cannot have the same name"); + SM.PrintMessage(R.startLoc(), SourceMgr::DK_Note, + "region " + Description + " was previously defined here"); + FoundErrors = true; + return; + } } - // Remove the default region if there are user defined regions. - if (!CurrentRegion.startLoc().isValid()) - Regions.erase(Regions.begin()); + ActiveRegions[Description] = Regions.size(); Regions.emplace_back(make_unique<CodeRegion>(Description, Loc)); + return; } -void CodeRegions::endRegion(SMLoc Loc) { - assert(!Regions.empty() && "Missing Default region"); - CodeRegion &CurrentRegion = *Regions.back(); - if (CurrentRegion.endLoc().isValid()) { - SM.PrintMessage(Loc, SourceMgr::DK_Warning, - "Ignoring invalid region end"); +void CodeRegions::endRegion(StringRef Description, SMLoc Loc) { + if (Description.empty()) { + // Special case where there is only one user defined region, + // and this LLVM-MCA-END directive doesn't provide a region name. + // In this case, we assume that the user simply wanted to just terminate + // the only active region. + if (ActiveRegions.size() == 1) { + auto It = ActiveRegions.begin(); + Regions[It->second]->setEndLocation(Loc); + ActiveRegions.erase(It); + return; + } + + // Special case where the region end marker applies to the default region. + if (ActiveRegions.empty() && Regions.size() == 1 && + !Regions[0]->startLoc().isValid() && !Regions[0]->endLoc().isValid()) { + Regions[0]->setEndLocation(Loc); + return; + } + } + + auto It = ActiveRegions.find(Description); + if (It != ActiveRegions.end()) { + Regions[It->second]->setEndLocation(Loc); + ActiveRegions.erase(It); return; } - CurrentRegion.setEndLocation(Loc); + FoundErrors = true; + SM.PrintMessage(Loc, SourceMgr::DK_Error, + "found an invalid region end directive"); + if (!Description.empty()) { + SM.PrintMessage(Loc, SourceMgr::DK_Note, + "unable to find an active region named " + Description); + } else { + SM.PrintMessage(Loc, SourceMgr::DK_Note, + "unable to find an active anonymous region"); + } } void CodeRegions::addInstruction(const MCInst &Instruction) { - const SMLoc &Loc = Instruction.getLoc(); - const auto It = - std::find_if(Regions.rbegin(), Regions.rend(), - [Loc](const UniqueCodeRegion &Region) { - return Region->isLocInRange(Loc); - }); - if (It != Regions.rend()) - (*It)->addInstruction(Instruction); + SMLoc Loc = Instruction.getLoc(); + for (UniqueCodeRegion &Region : Regions) + if (Region->isLocInRange(Loc)) + Region->addInstruction(Instruction); } } // namespace mca diff --git a/llvm/tools/llvm-mca/CodeRegion.h b/llvm/tools/llvm-mca/CodeRegion.h index 80532e311ed..cabb4a5d448 100644 --- a/llvm/tools/llvm-mca/CodeRegion.h +++ b/llvm/tools/llvm-mca/CodeRegion.h @@ -79,12 +79,16 @@ public: llvm::StringRef getDescription() const { return Description; } }; +class CodeRegionParseError final : public Error {}; + class CodeRegions { // A source manager. Used by the tool to generate meaningful warnings. llvm::SourceMgr &SM; using UniqueCodeRegion = std::unique_ptr<CodeRegion>; std::vector<UniqueCodeRegion> Regions; + llvm::StringMap<unsigned> ActiveRegions; + bool FoundErrors; CodeRegions(const CodeRegions &) = delete; CodeRegions &operator=(const CodeRegions &) = delete; @@ -101,7 +105,7 @@ public: const_iterator end() const { return Regions.cend(); } void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc); - void endRegion(llvm::SMLoc Loc); + void endRegion(llvm::StringRef Description, llvm::SMLoc Loc); void addInstruction(const llvm::MCInst &Instruction); llvm::SourceMgr &getSourceMgr() const { return SM; } @@ -114,6 +118,8 @@ public: return Region->empty(); }); } + + bool isValid() const { return !FoundErrors; } }; } // namespace mca diff --git a/llvm/tools/llvm-mca/CodeRegionGenerator.cpp b/llvm/tools/llvm-mca/CodeRegionGenerator.cpp index 14b470a417c..c793169e64e 100644 --- a/llvm/tools/llvm-mca/CodeRegionGenerator.cpp +++ b/llvm/tools/llvm-mca/CodeRegionGenerator.cpp @@ -86,7 +86,11 @@ void MCACommentConsumer::HandleComment(SMLoc Loc, StringRef CommentText) { Comment = Comment.drop_front(Position); if (Comment.consume_front("LLVM-MCA-END")) { - Regions.endRegion(Loc); + // Skip spaces and tabs. + Position = Comment.find_first_not_of(" \t"); + if (Position < Comment.size()) + Comment = Comment.drop_front(Position); + Regions.endRegion(Comment, Loc); return; } diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp index 861b6a5809a..e70c8f627ef 100644 --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/tools/llvm-mca/llvm-mca.cpp @@ -364,6 +364,11 @@ int main(int argc, char **argv) { return 1; } const mca::CodeRegions &Regions = *RegionsOrErr; + + // Early exit if errors were found by the code region parsing logic. + if (!Regions.isValid()) + return 1; + if (Regions.empty()) { WithColor::error() << "no assembly instructions found.\n"; return 1; |