Files
clang-p2996/llvm/tools/llvm-mca/CodeRegion.h
Michael Maitland 98e342dca2 [RISCV][llvm-mca] Use LMUL Instruments to provide more accurate reports on RISCV
On x86 and AArch, SIMD instructions encode all of the scheduling information in the instruction
itself. For example, VADD.I16 q0, q1, q2 is a neon instruction that operates on 16-bit integer
elements stored in 128-bit Q registers, which leads to eight 16-bit lanes in parallel. This kind
of information impacts how the instruction takes to execute and what dependencies this may cause.

On RISCV however, the data that impacts scheduling is encoded in CSR registers such as vtype or
vl, in addition with the instruction itself. But MCA does not track or use the data in these
registers. This patch fixes this problem by introducing Instruments into MCA.

* Replace `CodeRegions` with `AnalysisRegions`
* Add `Instrument` and `InstrumentManager`
* Add `InstrumentRegions`
* Add RISCV Instrument and `InstrumentManager`
* Parse `Instruments` in driver
* Use instruments to override schedule class
* RISCV use lmul instrument to override schedule class
* Fix unit tests to pass empty instruments
* Add -ignore-im clopt to disable this change

A prior version of this patch was commited in 5e82ee5373. 2323a4ee61 reverted
that change because the unit test files caused build errors. The change with fixes
were committed in b88b8307bf but reverted once again e8e92c8313 due to more
build errors.

This commit adds the prior changes and fixes the build error.

Differential Revision: https://reviews.llvm.org/D137440
2022-11-18 09:55:15 -08:00

196 lines
6.3 KiB
C++

//===-------------------------- CodeRegion.h -------------------*- C++ -* -===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
/// \file
///
/// This file implements class CodeRegion and CodeRegions, InstrumentRegion,
/// AnalysisRegions, and InstrumentRegions.
///
/// A CodeRegion describes a region of assembly code guarded by special LLVM-MCA
/// comment directives.
///
/// # LLVM-MCA-BEGIN foo
/// ... ## asm
/// # LLVM-MCA-END
///
/// A comment starting with substring LLVM-MCA-BEGIN marks the beginning of a
/// new region of code.
/// A comment starting with substring LLVM-MCA-END marks the end of the
/// last-seen region of code.
///
/// Code regions are not allowed to overlap. Each region can have a optional
/// description; internally, regions are described by a range of source
/// locations (SMLoc objects).
///
/// An instruction (a MCInst) is added to a CodeRegion R only if its
/// location is in range [R.RangeStart, R.RangeEnd].
///
/// A InstrumentRegion describes a region of assembly code guarded by
/// special LLVM-MCA comment directives.
///
/// # LLVM-MCA-<INSTRUMENTATION_TYPE> <data>
/// ... ## asm
///
/// where INSTRUMENTATION_TYPE is a type defined in llvm and expects to use
/// data.
///
/// A comment starting with substring LLVM-MCA-<INSTRUMENTATION_TYPE>
/// brings data into scope for llvm-mca to use in its analysis for
/// all following instructions.
///
/// If the same INSTRUMENTATION_TYPE is found later in the instruction list,
/// then the original InstrumentRegion will be automatically ended,
/// and a new InstrumentRegion will begin.
///
/// If there are comments containing the different INSTRUMENTATION_TYPEs,
/// then both data sets remain available. In contrast with a CodeRegion,
/// an InstrumentRegion does not need a comment to end the region.
//
// An instruction (a MCInst) is added to an InstrumentRegion R only
// if its location is in range [R.RangeStart, R.RangeEnd].
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVM_MCA_CODEREGION_H
#define LLVM_TOOLS_LLVM_MCA_CODEREGION_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MCA/CustomBehaviour.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/SourceMgr.h"
#include <vector>
namespace llvm {
namespace mca {
/// A region of assembly code.
///
/// It identifies a sequence of machine instructions.
class CodeRegion {
// An optional descriptor for this region.
llvm::StringRef Description;
// Instructions that form this region.
llvm::SmallVector<llvm::MCInst, 16> Instructions;
// Source location range.
llvm::SMLoc RangeStart;
llvm::SMLoc RangeEnd;
CodeRegion(const CodeRegion &) = delete;
CodeRegion &operator=(const CodeRegion &) = delete;
public:
CodeRegion(llvm::StringRef Desc, llvm::SMLoc Start)
: Description(Desc), RangeStart(Start) {}
void addInstruction(const llvm::MCInst &Instruction) {
Instructions.emplace_back(Instruction);
}
llvm::SMLoc startLoc() const { return RangeStart; }
llvm::SMLoc endLoc() const { return RangeEnd; }
void setEndLocation(llvm::SMLoc End) { RangeEnd = End; }
bool empty() const { return Instructions.empty(); }
bool isLocInRange(llvm::SMLoc Loc) const;
llvm::ArrayRef<llvm::MCInst> getInstructions() const { return Instructions; }
llvm::StringRef getDescription() const { return Description; }
};
/// Alias AnalysisRegion with CodeRegion since CodeRegionGenerator
/// is absract and AnalysisRegionGenerator operates on AnalysisRegions
using AnalysisRegion = CodeRegion;
/// A CodeRegion that contains instrumentation that can be used
/// in analysis of the region.
class InstrumentRegion : public CodeRegion {
/// Instrument for this region.
SharedInstrument Instrument;
public:
InstrumentRegion(llvm::StringRef Desc, llvm::SMLoc Start, SharedInstrument I)
: CodeRegion(Desc, Start), Instrument(I) {}
public:
SharedInstrument getInstrument() const { return Instrument; }
};
class CodeRegionParseError final : public Error {};
class CodeRegions {
CodeRegions(const CodeRegions &) = delete;
CodeRegions &operator=(const CodeRegions &) = delete;
protected:
// 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;
public:
CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) {}
typedef std::vector<UniqueCodeRegion>::iterator iterator;
typedef std::vector<UniqueCodeRegion>::const_iterator const_iterator;
iterator begin() { return Regions.begin(); }
iterator end() { return Regions.end(); }
const_iterator begin() const { return Regions.cbegin(); }
const_iterator end() const { return Regions.cend(); }
void addInstruction(const llvm::MCInst &Instruction);
llvm::SourceMgr &getSourceMgr() const { return SM; }
llvm::ArrayRef<llvm::MCInst> getInstructionSequence(unsigned Idx) const {
return Regions[Idx]->getInstructions();
}
bool empty() const {
return llvm::all_of(Regions, [](const UniqueCodeRegion &Region) {
return Region->empty();
});
}
bool isValid() const { return !FoundErrors; }
bool isRegionActive(llvm::StringRef Description) const {
return ActiveRegions.find(Description) != ActiveRegions.end();
}
};
struct AnalysisRegions : public CodeRegions {
AnalysisRegions(llvm::SourceMgr &S);
void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc);
void endRegion(llvm::StringRef Description, llvm::SMLoc Loc);
};
struct InstrumentRegions : public CodeRegions {
InstrumentRegions(llvm::SourceMgr &S);
void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc,
SharedInstrument Instrument);
void endRegion(llvm::StringRef Description, llvm::SMLoc Loc);
const SmallVector<SharedInstrument>
getActiveInstruments(llvm::SMLoc Loc) const;
};
} // namespace mca
} // namespace llvm
#endif