xref: /freebsd/contrib/llvm-project/llvm/tools/llvm-mca/CodeRegion.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
10b57cec5SDimitry Andric //===-------------------------- CodeRegion.cpp -----------------*- C++ -* -===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric /// \file
90b57cec5SDimitry Andric ///
100b57cec5SDimitry Andric /// This file implements methods from the CodeRegions interface.
110b57cec5SDimitry Andric ///
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "CodeRegion.h"
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric namespace llvm {
170b57cec5SDimitry Andric namespace mca {
180b57cec5SDimitry Andric 
isLocInRange(SMLoc Loc) const190b57cec5SDimitry Andric bool CodeRegion::isLocInRange(SMLoc Loc) const {
200b57cec5SDimitry Andric   if (RangeEnd.isValid() && Loc.getPointer() > RangeEnd.getPointer())
210b57cec5SDimitry Andric     return false;
220b57cec5SDimitry Andric   if (RangeStart.isValid() && Loc.getPointer() < RangeStart.getPointer())
230b57cec5SDimitry Andric     return false;
240b57cec5SDimitry Andric   return true;
250b57cec5SDimitry Andric }
260b57cec5SDimitry Andric 
addInstruction(const MCInst & Instruction)27bdd1243dSDimitry Andric void CodeRegions::addInstruction(const MCInst &Instruction) {
28bdd1243dSDimitry Andric   SMLoc Loc = Instruction.getLoc();
29bdd1243dSDimitry Andric   for (UniqueCodeRegion &Region : Regions)
30bdd1243dSDimitry Andric     if (Region->isLocInRange(Loc))
31bdd1243dSDimitry Andric       Region->addInstruction(Instruction);
32bdd1243dSDimitry Andric }
33bdd1243dSDimitry Andric 
AnalysisRegions(llvm::SourceMgr & S)34bdd1243dSDimitry Andric AnalysisRegions::AnalysisRegions(llvm::SourceMgr &S) : CodeRegions(S) {
35bdd1243dSDimitry Andric   // Create a default region for the input code sequence.
36bdd1243dSDimitry Andric   Regions.emplace_back(std::make_unique<CodeRegion>("", SMLoc()));
37bdd1243dSDimitry Andric }
38bdd1243dSDimitry Andric 
beginRegion(StringRef Description,SMLoc Loc)39bdd1243dSDimitry Andric void AnalysisRegions::beginRegion(StringRef Description, SMLoc Loc) {
400b57cec5SDimitry Andric   if (ActiveRegions.empty()) {
410b57cec5SDimitry Andric     // Remove the default region if there is at least one user defined region.
420b57cec5SDimitry Andric     // By construction, only the default region has an invalid start location.
430b57cec5SDimitry Andric     if (Regions.size() == 1 && !Regions[0]->startLoc().isValid() &&
440b57cec5SDimitry Andric         !Regions[0]->endLoc().isValid()) {
450b57cec5SDimitry Andric       ActiveRegions[Description] = 0;
468bcb0991SDimitry Andric       Regions[0] = std::make_unique<CodeRegion>(Description, Loc);
470b57cec5SDimitry Andric       return;
480b57cec5SDimitry Andric     }
490b57cec5SDimitry Andric   } else {
500b57cec5SDimitry Andric     auto It = ActiveRegions.find(Description);
510b57cec5SDimitry Andric     if (It != ActiveRegions.end()) {
520b57cec5SDimitry Andric       const CodeRegion &R = *Regions[It->second];
530b57cec5SDimitry Andric       if (Description.empty()) {
54bdd1243dSDimitry Andric         SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
550b57cec5SDimitry Andric                         "found multiple overlapping anonymous regions");
56bdd1243dSDimitry Andric         SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
570b57cec5SDimitry Andric                         "Previous anonymous region was defined here");
580b57cec5SDimitry Andric         FoundErrors = true;
590b57cec5SDimitry Andric         return;
600b57cec5SDimitry Andric       }
610b57cec5SDimitry Andric 
62bdd1243dSDimitry Andric       SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
630b57cec5SDimitry Andric                       "overlapping regions cannot have the same name");
64bdd1243dSDimitry Andric       SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
650b57cec5SDimitry Andric                       "region " + Description + " was previously defined here");
660b57cec5SDimitry Andric       FoundErrors = true;
670b57cec5SDimitry Andric       return;
680b57cec5SDimitry Andric     }
690b57cec5SDimitry Andric   }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   ActiveRegions[Description] = Regions.size();
728bcb0991SDimitry Andric   Regions.emplace_back(std::make_unique<CodeRegion>(Description, Loc));
730b57cec5SDimitry Andric }
740b57cec5SDimitry Andric 
endRegion(StringRef Description,SMLoc Loc)75bdd1243dSDimitry Andric void AnalysisRegions::endRegion(StringRef Description, SMLoc Loc) {
760b57cec5SDimitry Andric   if (Description.empty()) {
770b57cec5SDimitry Andric     // Special case where there is only one user defined region,
780b57cec5SDimitry Andric     // and this LLVM-MCA-END directive doesn't provide a region name.
790b57cec5SDimitry Andric     // In this case, we assume that the user simply wanted to just terminate
800b57cec5SDimitry Andric     // the only active region.
810b57cec5SDimitry Andric     if (ActiveRegions.size() == 1) {
820b57cec5SDimitry Andric       auto It = ActiveRegions.begin();
830b57cec5SDimitry Andric       Regions[It->second]->setEndLocation(Loc);
840b57cec5SDimitry Andric       ActiveRegions.erase(It);
850b57cec5SDimitry Andric       return;
860b57cec5SDimitry Andric     }
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric     // Special case where the region end marker applies to the default region.
890b57cec5SDimitry Andric     if (ActiveRegions.empty() && Regions.size() == 1 &&
900b57cec5SDimitry Andric         !Regions[0]->startLoc().isValid() && !Regions[0]->endLoc().isValid()) {
910b57cec5SDimitry Andric       Regions[0]->setEndLocation(Loc);
920b57cec5SDimitry Andric       return;
930b57cec5SDimitry Andric     }
940b57cec5SDimitry Andric   }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   auto It = ActiveRegions.find(Description);
970b57cec5SDimitry Andric   if (It != ActiveRegions.end()) {
980b57cec5SDimitry Andric     Regions[It->second]->setEndLocation(Loc);
990b57cec5SDimitry Andric     ActiveRegions.erase(It);
1000b57cec5SDimitry Andric     return;
1010b57cec5SDimitry Andric   }
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   FoundErrors = true;
104bdd1243dSDimitry Andric   SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
1050b57cec5SDimitry Andric                   "found an invalid region end directive");
1060b57cec5SDimitry Andric   if (!Description.empty()) {
107bdd1243dSDimitry Andric     SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
1080b57cec5SDimitry Andric                     "unable to find an active region named " + Description);
1090b57cec5SDimitry Andric   } else {
110bdd1243dSDimitry Andric     SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
1110b57cec5SDimitry Andric                     "unable to find an active anonymous region");
1120b57cec5SDimitry Andric   }
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric 
InstrumentRegions(llvm::SourceMgr & S)115bdd1243dSDimitry Andric InstrumentRegions::InstrumentRegions(llvm::SourceMgr &S) : CodeRegions(S) {}
116bdd1243dSDimitry Andric 
beginRegion(StringRef Description,SMLoc Loc,UniqueInstrument I)117bdd1243dSDimitry Andric void InstrumentRegions::beginRegion(StringRef Description, SMLoc Loc,
118*06c3fb27SDimitry Andric                                     UniqueInstrument I) {
119bdd1243dSDimitry Andric   if (Description.empty()) {
120bdd1243dSDimitry Andric     SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
121bdd1243dSDimitry Andric                     "anonymous instrumentation regions are not permitted");
122bdd1243dSDimitry Andric     FoundErrors = true;
123bdd1243dSDimitry Andric     return;
124bdd1243dSDimitry Andric   }
125bdd1243dSDimitry Andric 
126bdd1243dSDimitry Andric   auto It = ActiveRegions.find(Description);
127bdd1243dSDimitry Andric   if (It != ActiveRegions.end()) {
128bdd1243dSDimitry Andric     const CodeRegion &R = *Regions[It->second];
129bdd1243dSDimitry Andric     SM.PrintMessage(
130bdd1243dSDimitry Andric         Loc, llvm::SourceMgr::DK_Error,
131bdd1243dSDimitry Andric         "overlapping instrumentation regions cannot be of the same kind");
132bdd1243dSDimitry Andric     SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
133bdd1243dSDimitry Andric                     "instrumentation region " + Description +
134bdd1243dSDimitry Andric                         " was previously defined here");
135bdd1243dSDimitry Andric     FoundErrors = true;
136bdd1243dSDimitry Andric     return;
137bdd1243dSDimitry Andric   }
138bdd1243dSDimitry Andric 
139bdd1243dSDimitry Andric   ActiveRegions[Description] = Regions.size();
140*06c3fb27SDimitry Andric   Regions.emplace_back(
141*06c3fb27SDimitry Andric       std::make_unique<InstrumentRegion>(Description, Loc, std::move(I)));
142bdd1243dSDimitry Andric }
143bdd1243dSDimitry Andric 
endRegion(StringRef Description,SMLoc Loc)144bdd1243dSDimitry Andric void InstrumentRegions::endRegion(StringRef Description, SMLoc Loc) {
145bdd1243dSDimitry Andric   auto It = ActiveRegions.find(Description);
146bdd1243dSDimitry Andric   if (It != ActiveRegions.end()) {
147bdd1243dSDimitry Andric     Regions[It->second]->setEndLocation(Loc);
148bdd1243dSDimitry Andric     ActiveRegions.erase(It);
149bdd1243dSDimitry Andric     return;
150bdd1243dSDimitry Andric   }
151bdd1243dSDimitry Andric 
152bdd1243dSDimitry Andric   FoundErrors = true;
153bdd1243dSDimitry Andric   SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
154bdd1243dSDimitry Andric                   "found an invalid instrumentation region end directive");
155bdd1243dSDimitry Andric   if (!Description.empty()) {
156bdd1243dSDimitry Andric     SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
157bdd1243dSDimitry Andric                     "unable to find an active instrumentation region named " +
158bdd1243dSDimitry Andric                         Description);
159bdd1243dSDimitry Andric   }
160bdd1243dSDimitry Andric }
161bdd1243dSDimitry Andric 
162*06c3fb27SDimitry Andric const SmallVector<Instrument *>
getActiveInstruments(SMLoc Loc) const163bdd1243dSDimitry Andric InstrumentRegions::getActiveInstruments(SMLoc Loc) const {
164*06c3fb27SDimitry Andric   SmallVector<Instrument *> AI;
165bdd1243dSDimitry Andric   for (auto &R : Regions) {
166bdd1243dSDimitry Andric     if (R->isLocInRange(Loc)) {
167bdd1243dSDimitry Andric       InstrumentRegion *IR = static_cast<InstrumentRegion *>(R.get());
168*06c3fb27SDimitry Andric       AI.push_back(IR->getInstrument());
169bdd1243dSDimitry Andric     }
170bdd1243dSDimitry Andric   }
171bdd1243dSDimitry Andric   return AI;
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric } // namespace mca
1750b57cec5SDimitry Andric } // namespace llvm
176