xref: /llvm-project/llvm/tools/llvm-mca/CodeRegion.cpp (revision 56674e8e4a4bb086a03857ec28739b1ecbd05374)
1c6590128SAndrea Di Biagio //===-------------------------- CodeRegion.cpp -----------------*- C++ -* -===//
2c6590128SAndrea Di Biagio //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c6590128SAndrea Di Biagio //
7c6590128SAndrea Di Biagio //===----------------------------------------------------------------------===//
8c6590128SAndrea Di Biagio /// \file
9c6590128SAndrea Di Biagio ///
10c6590128SAndrea Di Biagio /// This file implements methods from the CodeRegions interface.
11c6590128SAndrea Di Biagio ///
12c6590128SAndrea Di Biagio //===----------------------------------------------------------------------===//
13c6590128SAndrea Di Biagio 
14c6590128SAndrea Di Biagio #include "CodeRegion.h"
15c6590128SAndrea Di Biagio 
165a8fd657SFangrui Song namespace llvm {
17c6590128SAndrea Di Biagio namespace mca {
18c6590128SAndrea Di Biagio 
isLocInRange(SMLoc Loc) const1986654dd8SAndrea Di Biagio bool CodeRegion::isLocInRange(SMLoc Loc) const {
20c6590128SAndrea Di Biagio   if (RangeEnd.isValid() && Loc.getPointer() > RangeEnd.getPointer())
21c6590128SAndrea Di Biagio     return false;
22c6590128SAndrea Di Biagio   if (RangeStart.isValid() && Loc.getPointer() < RangeStart.getPointer())
23c6590128SAndrea Di Biagio     return false;
24c6590128SAndrea Di Biagio   return true;
25c6590128SAndrea Di Biagio }
26c6590128SAndrea Di Biagio 
addInstruction(const MCInst & Instruction)2798e342dcSMichael Maitland void CodeRegions::addInstruction(const MCInst &Instruction) {
2898e342dcSMichael Maitland   SMLoc Loc = Instruction.getLoc();
2998e342dcSMichael Maitland   for (UniqueCodeRegion &Region : Regions)
3098e342dcSMichael Maitland     if (Region->isLocInRange(Loc))
3198e342dcSMichael Maitland       Region->addInstruction(Instruction);
3298e342dcSMichael Maitland }
3398e342dcSMichael Maitland 
AnalysisRegions(llvm::SourceMgr & S)3498e342dcSMichael Maitland AnalysisRegions::AnalysisRegions(llvm::SourceMgr &S) : CodeRegions(S) {
3598e342dcSMichael Maitland   // Create a default region for the input code sequence.
3698e342dcSMichael Maitland   Regions.emplace_back(std::make_unique<CodeRegion>("", SMLoc()));
3798e342dcSMichael Maitland }
3898e342dcSMichael Maitland 
beginRegion(StringRef Description,SMLoc Loc)3998e342dcSMichael Maitland void AnalysisRegions::beginRegion(StringRef Description, SMLoc Loc) {
404e62554bSAndrea Di Biagio   if (ActiveRegions.empty()) {
414e62554bSAndrea Di Biagio     // Remove the default region if there is at least one user defined region.
424e62554bSAndrea Di Biagio     // By construction, only the default region has an invalid start location.
434e62554bSAndrea Di Biagio     if (Regions.size() == 1 && !Regions[0]->startLoc().isValid() &&
444e62554bSAndrea Di Biagio         !Regions[0]->endLoc().isValid()) {
454e62554bSAndrea Di Biagio       ActiveRegions[Description] = 0;
460eaee545SJonas Devlieghere       Regions[0] = std::make_unique<CodeRegion>(Description, Loc);
474e62554bSAndrea Di Biagio       return;
484e62554bSAndrea Di Biagio     }
494e62554bSAndrea Di Biagio   } else {
504e62554bSAndrea Di Biagio     auto It = ActiveRegions.find(Description);
514e62554bSAndrea Di Biagio     if (It != ActiveRegions.end()) {
524e62554bSAndrea Di Biagio       const CodeRegion &R = *Regions[It->second];
534e62554bSAndrea Di Biagio       if (Description.empty()) {
5498e342dcSMichael Maitland         SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
554e62554bSAndrea Di Biagio                         "found multiple overlapping anonymous regions");
5698e342dcSMichael Maitland         SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
574e62554bSAndrea Di Biagio                         "Previous anonymous region was defined here");
584e62554bSAndrea Di Biagio         FoundErrors = true;
59c6590128SAndrea Di Biagio         return;
60c6590128SAndrea Di Biagio       }
61c6590128SAndrea Di Biagio 
6298e342dcSMichael Maitland       SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
634e62554bSAndrea Di Biagio                       "overlapping regions cannot have the same name");
6498e342dcSMichael Maitland       SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
654e62554bSAndrea Di Biagio                       "region " + Description + " was previously defined here");
664e62554bSAndrea Di Biagio       FoundErrors = true;
674e62554bSAndrea Di Biagio       return;
684e62554bSAndrea Di Biagio     }
694e62554bSAndrea Di Biagio   }
704e62554bSAndrea Di Biagio 
714e62554bSAndrea Di Biagio   ActiveRegions[Description] = Regions.size();
720eaee545SJonas Devlieghere   Regions.emplace_back(std::make_unique<CodeRegion>(Description, Loc));
73c6590128SAndrea Di Biagio }
74c6590128SAndrea Di Biagio 
endRegion(StringRef Description,SMLoc Loc)7598e342dcSMichael Maitland void AnalysisRegions::endRegion(StringRef Description, SMLoc Loc) {
764e62554bSAndrea Di Biagio   if (Description.empty()) {
774e62554bSAndrea Di Biagio     // Special case where there is only one user defined region,
784e62554bSAndrea Di Biagio     // and this LLVM-MCA-END directive doesn't provide a region name.
794e62554bSAndrea Di Biagio     // In this case, we assume that the user simply wanted to just terminate
804e62554bSAndrea Di Biagio     // the only active region.
814e62554bSAndrea Di Biagio     if (ActiveRegions.size() == 1) {
824e62554bSAndrea Di Biagio       auto It = ActiveRegions.begin();
834e62554bSAndrea Di Biagio       Regions[It->second]->setEndLocation(Loc);
844e62554bSAndrea Di Biagio       ActiveRegions.erase(It);
854e62554bSAndrea Di Biagio       return;
864e62554bSAndrea Di Biagio     }
874e62554bSAndrea Di Biagio 
884e62554bSAndrea Di Biagio     // Special case where the region end marker applies to the default region.
894e62554bSAndrea Di Biagio     if (ActiveRegions.empty() && Regions.size() == 1 &&
904e62554bSAndrea Di Biagio         !Regions[0]->startLoc().isValid() && !Regions[0]->endLoc().isValid()) {
914e62554bSAndrea Di Biagio       Regions[0]->setEndLocation(Loc);
924e62554bSAndrea Di Biagio       return;
934e62554bSAndrea Di Biagio     }
944e62554bSAndrea Di Biagio   }
954e62554bSAndrea Di Biagio 
964e62554bSAndrea Di Biagio   auto It = ActiveRegions.find(Description);
974e62554bSAndrea Di Biagio   if (It != ActiveRegions.end()) {
984e62554bSAndrea Di Biagio     Regions[It->second]->setEndLocation(Loc);
994e62554bSAndrea Di Biagio     ActiveRegions.erase(It);
1004e62554bSAndrea Di Biagio     return;
1014e62554bSAndrea Di Biagio   }
1024e62554bSAndrea Di Biagio 
1034e62554bSAndrea Di Biagio   FoundErrors = true;
10498e342dcSMichael Maitland   SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
1054e62554bSAndrea Di Biagio                   "found an invalid region end directive");
1064e62554bSAndrea Di Biagio   if (!Description.empty()) {
10798e342dcSMichael Maitland     SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
1084e62554bSAndrea Di Biagio                     "unable to find an active region named " + Description);
1094e62554bSAndrea Di Biagio   } else {
11098e342dcSMichael Maitland     SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
1114e62554bSAndrea Di Biagio                     "unable to find an active anonymous region");
1124e62554bSAndrea Di Biagio   }
113c6590128SAndrea Di Biagio }
114c6590128SAndrea Di Biagio 
InstrumentRegions(llvm::SourceMgr & S)11598e342dcSMichael Maitland InstrumentRegions::InstrumentRegions(llvm::SourceMgr &S) : CodeRegions(S) {}
11698e342dcSMichael Maitland 
beginRegion(StringRef Description,SMLoc Loc,UniqueInstrument I)11798e342dcSMichael Maitland void InstrumentRegions::beginRegion(StringRef Description, SMLoc Loc,
118*56674e8eSMichael Maitland                                     UniqueInstrument I) {
11998e342dcSMichael Maitland   if (Description.empty()) {
12098e342dcSMichael Maitland     SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
12198e342dcSMichael Maitland                     "anonymous instrumentation regions are not permitted");
12298e342dcSMichael Maitland     FoundErrors = true;
12398e342dcSMichael Maitland     return;
12498e342dcSMichael Maitland   }
12598e342dcSMichael Maitland 
12698e342dcSMichael Maitland   auto It = ActiveRegions.find(Description);
12798e342dcSMichael Maitland   if (It != ActiveRegions.end()) {
12898e342dcSMichael Maitland     const CodeRegion &R = *Regions[It->second];
12998e342dcSMichael Maitland     SM.PrintMessage(
13098e342dcSMichael Maitland         Loc, llvm::SourceMgr::DK_Error,
13198e342dcSMichael Maitland         "overlapping instrumentation regions cannot be of the same kind");
13298e342dcSMichael Maitland     SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
13398e342dcSMichael Maitland                     "instrumentation region " + Description +
13498e342dcSMichael Maitland                         " was previously defined here");
13598e342dcSMichael Maitland     FoundErrors = true;
13698e342dcSMichael Maitland     return;
13798e342dcSMichael Maitland   }
13898e342dcSMichael Maitland 
13998e342dcSMichael Maitland   ActiveRegions[Description] = Regions.size();
140*56674e8eSMichael Maitland   Regions.emplace_back(
141*56674e8eSMichael Maitland       std::make_unique<InstrumentRegion>(Description, Loc, std::move(I)));
14298e342dcSMichael Maitland }
14398e342dcSMichael Maitland 
endRegion(StringRef Description,SMLoc Loc)14498e342dcSMichael Maitland void InstrumentRegions::endRegion(StringRef Description, SMLoc Loc) {
14598e342dcSMichael Maitland   auto It = ActiveRegions.find(Description);
14698e342dcSMichael Maitland   if (It != ActiveRegions.end()) {
14798e342dcSMichael Maitland     Regions[It->second]->setEndLocation(Loc);
14898e342dcSMichael Maitland     ActiveRegions.erase(It);
14998e342dcSMichael Maitland     return;
15098e342dcSMichael Maitland   }
15198e342dcSMichael Maitland 
15298e342dcSMichael Maitland   FoundErrors = true;
15398e342dcSMichael Maitland   SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
15498e342dcSMichael Maitland                   "found an invalid instrumentation region end directive");
15598e342dcSMichael Maitland   if (!Description.empty()) {
15698e342dcSMichael Maitland     SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
15798e342dcSMichael Maitland                     "unable to find an active instrumentation region named " +
15898e342dcSMichael Maitland                         Description);
15998e342dcSMichael Maitland   }
16098e342dcSMichael Maitland }
16198e342dcSMichael Maitland 
162*56674e8eSMichael Maitland const SmallVector<Instrument *>
getActiveInstruments(SMLoc Loc) const16398e342dcSMichael Maitland InstrumentRegions::getActiveInstruments(SMLoc Loc) const {
164*56674e8eSMichael Maitland   SmallVector<Instrument *> AI;
16598e342dcSMichael Maitland   for (auto &R : Regions) {
16698e342dcSMichael Maitland     if (R->isLocInRange(Loc)) {
16798e342dcSMichael Maitland       InstrumentRegion *IR = static_cast<InstrumentRegion *>(R.get());
168*56674e8eSMichael Maitland       AI.push_back(IR->getInstrument());
16998e342dcSMichael Maitland     }
17098e342dcSMichael Maitland   }
17198e342dcSMichael Maitland   return AI;
172c6590128SAndrea Di Biagio }
173c6590128SAndrea Di Biagio 
174c6590128SAndrea Di Biagio } // namespace mca
1755a8fd657SFangrui Song } // namespace llvm
176