summaryrefslogtreecommitdiffstats
path: root/llvm/tools
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools')
-rw-r--r--llvm/tools/llvm-mca/CodeRegion.cpp96
-rw-r--r--llvm/tools/llvm-mca/CodeRegion.h8
-rw-r--r--llvm/tools/llvm-mca/CodeRegionGenerator.cpp6
-rw-r--r--llvm/tools/llvm-mca/llvm-mca.cpp5
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;
OpenPOWER on IntegriCloud