xref: /openbsd-src/gnu/llvm/llvm/tools/llvm-mca/CodeRegion.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===-------------------------- CodeRegion.cpp -----------------*- C++ -* -===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick /// \file
909467b48Spatrick ///
1009467b48Spatrick /// This file implements methods from the CodeRegions interface.
1109467b48Spatrick ///
1209467b48Spatrick //===----------------------------------------------------------------------===//
1309467b48Spatrick 
1409467b48Spatrick #include "CodeRegion.h"
1509467b48Spatrick 
1609467b48Spatrick namespace llvm {
1709467b48Spatrick namespace mca {
1809467b48Spatrick 
isLocInRange(SMLoc Loc) const1909467b48Spatrick bool CodeRegion::isLocInRange(SMLoc Loc) const {
2009467b48Spatrick   if (RangeEnd.isValid() && Loc.getPointer() > RangeEnd.getPointer())
2109467b48Spatrick     return false;
2209467b48Spatrick   if (RangeStart.isValid() && Loc.getPointer() < RangeStart.getPointer())
2309467b48Spatrick     return false;
2409467b48Spatrick   return true;
2509467b48Spatrick }
2609467b48Spatrick 
addInstruction(const MCInst & Instruction)27*d415bd75Srobert void CodeRegions::addInstruction(const MCInst &Instruction) {
28*d415bd75Srobert   SMLoc Loc = Instruction.getLoc();
29*d415bd75Srobert   for (UniqueCodeRegion &Region : Regions)
30*d415bd75Srobert     if (Region->isLocInRange(Loc))
31*d415bd75Srobert       Region->addInstruction(Instruction);
32*d415bd75Srobert }
33*d415bd75Srobert 
AnalysisRegions(llvm::SourceMgr & S)34*d415bd75Srobert AnalysisRegions::AnalysisRegions(llvm::SourceMgr &S) : CodeRegions(S) {
35*d415bd75Srobert   // Create a default region for the input code sequence.
36*d415bd75Srobert   Regions.emplace_back(std::make_unique<CodeRegion>("", SMLoc()));
37*d415bd75Srobert }
38*d415bd75Srobert 
beginRegion(StringRef Description,SMLoc Loc)39*d415bd75Srobert void AnalysisRegions::beginRegion(StringRef Description, SMLoc Loc) {
4009467b48Spatrick   if (ActiveRegions.empty()) {
4109467b48Spatrick     // Remove the default region if there is at least one user defined region.
4209467b48Spatrick     // By construction, only the default region has an invalid start location.
4309467b48Spatrick     if (Regions.size() == 1 && !Regions[0]->startLoc().isValid() &&
4409467b48Spatrick         !Regions[0]->endLoc().isValid()) {
4509467b48Spatrick       ActiveRegions[Description] = 0;
4609467b48Spatrick       Regions[0] = std::make_unique<CodeRegion>(Description, Loc);
4709467b48Spatrick       return;
4809467b48Spatrick     }
4909467b48Spatrick   } else {
5009467b48Spatrick     auto It = ActiveRegions.find(Description);
5109467b48Spatrick     if (It != ActiveRegions.end()) {
5209467b48Spatrick       const CodeRegion &R = *Regions[It->second];
5309467b48Spatrick       if (Description.empty()) {
54*d415bd75Srobert         SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
5509467b48Spatrick                         "found multiple overlapping anonymous regions");
56*d415bd75Srobert         SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
5709467b48Spatrick                         "Previous anonymous region was defined here");
5809467b48Spatrick         FoundErrors = true;
5909467b48Spatrick         return;
6009467b48Spatrick       }
6109467b48Spatrick 
62*d415bd75Srobert       SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
6309467b48Spatrick                       "overlapping regions cannot have the same name");
64*d415bd75Srobert       SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
6509467b48Spatrick                       "region " + Description + " was previously defined here");
6609467b48Spatrick       FoundErrors = true;
6709467b48Spatrick       return;
6809467b48Spatrick     }
6909467b48Spatrick   }
7009467b48Spatrick 
7109467b48Spatrick   ActiveRegions[Description] = Regions.size();
7209467b48Spatrick   Regions.emplace_back(std::make_unique<CodeRegion>(Description, Loc));
7309467b48Spatrick }
7409467b48Spatrick 
endRegion(StringRef Description,SMLoc Loc)75*d415bd75Srobert void AnalysisRegions::endRegion(StringRef Description, SMLoc Loc) {
7609467b48Spatrick   if (Description.empty()) {
7709467b48Spatrick     // Special case where there is only one user defined region,
7809467b48Spatrick     // and this LLVM-MCA-END directive doesn't provide a region name.
7909467b48Spatrick     // In this case, we assume that the user simply wanted to just terminate
8009467b48Spatrick     // the only active region.
8109467b48Spatrick     if (ActiveRegions.size() == 1) {
8209467b48Spatrick       auto It = ActiveRegions.begin();
8309467b48Spatrick       Regions[It->second]->setEndLocation(Loc);
8409467b48Spatrick       ActiveRegions.erase(It);
8509467b48Spatrick       return;
8609467b48Spatrick     }
8709467b48Spatrick 
8809467b48Spatrick     // Special case where the region end marker applies to the default region.
8909467b48Spatrick     if (ActiveRegions.empty() && Regions.size() == 1 &&
9009467b48Spatrick         !Regions[0]->startLoc().isValid() && !Regions[0]->endLoc().isValid()) {
9109467b48Spatrick       Regions[0]->setEndLocation(Loc);
9209467b48Spatrick       return;
9309467b48Spatrick     }
9409467b48Spatrick   }
9509467b48Spatrick 
9609467b48Spatrick   auto It = ActiveRegions.find(Description);
9709467b48Spatrick   if (It != ActiveRegions.end()) {
9809467b48Spatrick     Regions[It->second]->setEndLocation(Loc);
9909467b48Spatrick     ActiveRegions.erase(It);
10009467b48Spatrick     return;
10109467b48Spatrick   }
10209467b48Spatrick 
10309467b48Spatrick   FoundErrors = true;
104*d415bd75Srobert   SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
10509467b48Spatrick                   "found an invalid region end directive");
10609467b48Spatrick   if (!Description.empty()) {
107*d415bd75Srobert     SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
10809467b48Spatrick                     "unable to find an active region named " + Description);
10909467b48Spatrick   } else {
110*d415bd75Srobert     SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
11109467b48Spatrick                     "unable to find an active anonymous region");
11209467b48Spatrick   }
11309467b48Spatrick }
11409467b48Spatrick 
InstrumentRegions(llvm::SourceMgr & S)115*d415bd75Srobert InstrumentRegions::InstrumentRegions(llvm::SourceMgr &S) : CodeRegions(S) {}
116*d415bd75Srobert 
beginRegion(StringRef Description,SMLoc Loc,SharedInstrument I)117*d415bd75Srobert void InstrumentRegions::beginRegion(StringRef Description, SMLoc Loc,
118*d415bd75Srobert                                     SharedInstrument I) {
119*d415bd75Srobert   if (Description.empty()) {
120*d415bd75Srobert     SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
121*d415bd75Srobert                     "anonymous instrumentation regions are not permitted");
122*d415bd75Srobert     FoundErrors = true;
123*d415bd75Srobert     return;
124*d415bd75Srobert   }
125*d415bd75Srobert 
126*d415bd75Srobert   auto It = ActiveRegions.find(Description);
127*d415bd75Srobert   if (It != ActiveRegions.end()) {
128*d415bd75Srobert     const CodeRegion &R = *Regions[It->second];
129*d415bd75Srobert     SM.PrintMessage(
130*d415bd75Srobert         Loc, llvm::SourceMgr::DK_Error,
131*d415bd75Srobert         "overlapping instrumentation regions cannot be of the same kind");
132*d415bd75Srobert     SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
133*d415bd75Srobert                     "instrumentation region " + Description +
134*d415bd75Srobert                         " was previously defined here");
135*d415bd75Srobert     FoundErrors = true;
136*d415bd75Srobert     return;
137*d415bd75Srobert   }
138*d415bd75Srobert 
139*d415bd75Srobert   ActiveRegions[Description] = Regions.size();
140*d415bd75Srobert   Regions.emplace_back(std::make_unique<InstrumentRegion>(Description, Loc, I));
141*d415bd75Srobert }
142*d415bd75Srobert 
endRegion(StringRef Description,SMLoc Loc)143*d415bd75Srobert void InstrumentRegions::endRegion(StringRef Description, SMLoc Loc) {
144*d415bd75Srobert   auto It = ActiveRegions.find(Description);
145*d415bd75Srobert   if (It != ActiveRegions.end()) {
146*d415bd75Srobert     Regions[It->second]->setEndLocation(Loc);
147*d415bd75Srobert     ActiveRegions.erase(It);
148*d415bd75Srobert     return;
149*d415bd75Srobert   }
150*d415bd75Srobert 
151*d415bd75Srobert   FoundErrors = true;
152*d415bd75Srobert   SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
153*d415bd75Srobert                   "found an invalid instrumentation region end directive");
154*d415bd75Srobert   if (!Description.empty()) {
155*d415bd75Srobert     SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
156*d415bd75Srobert                     "unable to find an active instrumentation region named " +
157*d415bd75Srobert                         Description);
158*d415bd75Srobert   }
159*d415bd75Srobert }
160*d415bd75Srobert 
161*d415bd75Srobert const SmallVector<SharedInstrument>
getActiveInstruments(SMLoc Loc) const162*d415bd75Srobert InstrumentRegions::getActiveInstruments(SMLoc Loc) const {
163*d415bd75Srobert   SmallVector<SharedInstrument> AI;
164*d415bd75Srobert   for (auto &R : Regions) {
165*d415bd75Srobert     if (R->isLocInRange(Loc)) {
166*d415bd75Srobert       InstrumentRegion *IR = static_cast<InstrumentRegion *>(R.get());
167*d415bd75Srobert       AI.emplace_back(IR->getInstrument());
168*d415bd75Srobert     }
169*d415bd75Srobert   }
170*d415bd75Srobert   return AI;
17109467b48Spatrick }
17209467b48Spatrick 
17309467b48Spatrick } // namespace mca
17409467b48Spatrick } // namespace llvm
175