aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MCA/InstrBuilder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/MCA/InstrBuilder.cpp')
-rw-r--r--llvm/lib/MCA/InstrBuilder.cpp96
1 files changed, 75 insertions, 21 deletions
diff --git a/llvm/lib/MCA/InstrBuilder.cpp b/llvm/lib/MCA/InstrBuilder.cpp
index d8283f8d2682..45acea253587 100644
--- a/llvm/lib/MCA/InstrBuilder.cpp
+++ b/llvm/lib/MCA/InstrBuilder.cpp
@@ -14,16 +14,19 @@
#include "llvm/MCA/InstrBuilder.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/Statistic.h"
#include "llvm/MC/MCInst.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
-#define DEBUG_TYPE "llvm-mca"
+#define DEBUG_TYPE "llvm-mca-instrbuilder"
namespace llvm {
namespace mca {
+char RecycledInstErr::ID = 0;
+
InstrBuilder::InstrBuilder(const llvm::MCSubtargetInfo &sti,
const llvm::MCInstrInfo &mcii,
const llvm::MCRegisterInfo &mri,
@@ -572,6 +575,7 @@ InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
LLVM_DEBUG(dbgs() << "\n\t\tOpcode Name= " << MCII.getName(Opcode) << '\n');
LLVM_DEBUG(dbgs() << "\t\tSchedClassID=" << SchedClassID << '\n');
+ LLVM_DEBUG(dbgs() << "\t\tOpcode=" << Opcode << '\n');
// Create a new empty descriptor.
std::unique_ptr<InstrDesc> ID = std::make_unique<InstrDesc>();
@@ -593,13 +597,6 @@ InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
FirstReturnInst = false;
}
- ID->MayLoad = MCDesc.mayLoad();
- ID->MayStore = MCDesc.mayStore();
- ID->HasSideEffects = MCDesc.hasUnmodeledSideEffects();
- ID->BeginGroup = SCDesc.BeginGroup;
- ID->EndGroup = SCDesc.EndGroup;
- ID->RetireOOO = SCDesc.RetireOOO;
-
initializeUsedResources(*ID, SCDesc, STI, ProcResourceMasks);
computeMaxLatency(*ID, MCDesc, SCDesc, STI);
@@ -618,7 +615,7 @@ InstrBuilder::createInstrDescImpl(const MCInst &MCI) {
// Now add the new descriptor.
bool IsVariadic = MCDesc.isVariadic();
- if (!IsVariadic && !IsVariant) {
+ if ((ID->IsRecyclable = !IsVariadic && !IsVariant)) {
Descriptors[MCI.getOpcode()] = std::move(ID);
return *Descriptors[MCI.getOpcode()];
}
@@ -638,14 +635,43 @@ InstrBuilder::getOrCreateInstrDesc(const MCInst &MCI) {
return createInstrDescImpl(MCI);
}
+STATISTIC(NumVariantInst, "Number of MCInsts that doesn't have static Desc");
+
Expected<std::unique_ptr<Instruction>>
InstrBuilder::createInstruction(const MCInst &MCI) {
Expected<const InstrDesc &> DescOrErr = getOrCreateInstrDesc(MCI);
if (!DescOrErr)
return DescOrErr.takeError();
const InstrDesc &D = *DescOrErr;
- std::unique_ptr<Instruction> NewIS =
- std::make_unique<Instruction>(D, MCI.getOpcode());
+ Instruction *NewIS = nullptr;
+ std::unique_ptr<Instruction> CreatedIS;
+ bool IsInstRecycled = false;
+
+ if (!D.IsRecyclable)
+ ++NumVariantInst;
+
+ if (D.IsRecyclable && InstRecycleCB) {
+ if (auto *I = InstRecycleCB(D)) {
+ NewIS = I;
+ NewIS->reset();
+ IsInstRecycled = true;
+ }
+ }
+ if (!IsInstRecycled) {
+ CreatedIS = std::make_unique<Instruction>(D, MCI.getOpcode());
+ NewIS = CreatedIS.get();
+ }
+
+ const MCInstrDesc &MCDesc = MCII.get(MCI.getOpcode());
+ const MCSchedClassDesc &SCDesc =
+ *STI.getSchedModel().getSchedClassDesc(D.SchedClassID);
+
+ NewIS->setMayLoad(MCDesc.mayLoad());
+ NewIS->setMayStore(MCDesc.mayStore());
+ NewIS->setHasSideEffects(MCDesc.hasUnmodeledSideEffects());
+ NewIS->setBeginGroup(SCDesc.BeginGroup);
+ NewIS->setEndGroup(SCDesc.EndGroup);
+ NewIS->setRetireOOO(SCDesc.RetireOOO);
// Check if this is a dependency breaking instruction.
APInt Mask;
@@ -663,6 +689,7 @@ InstrBuilder::createInstruction(const MCInst &MCI) {
// Initialize Reads first.
MCPhysReg RegID = 0;
+ size_t Idx = 0U;
for (const ReadDescriptor &RD : D.Reads) {
if (!RD.isImplicitRead()) {
// explicit read.
@@ -681,15 +708,22 @@ InstrBuilder::createInstruction(const MCInst &MCI) {
continue;
// Okay, this is a register operand. Create a ReadState for it.
- NewIS->getUses().emplace_back(RD, RegID);
- ReadState &RS = NewIS->getUses().back();
+ ReadState *RS = nullptr;
+ if (IsInstRecycled && Idx < NewIS->getUses().size()) {
+ NewIS->getUses()[Idx] = ReadState(RD, RegID);
+ RS = &NewIS->getUses()[Idx++];
+ } else {
+ NewIS->getUses().emplace_back(RD, RegID);
+ RS = &NewIS->getUses().back();
+ ++Idx;
+ }
if (IsDepBreaking) {
// A mask of all zeroes means: explicit input operands are not
// independent.
if (Mask.isZero()) {
if (!RD.isImplicitRead())
- RS.setIndependentFromDef();
+ RS->setIndependentFromDef();
} else {
// Check if this register operand is independent according to `Mask`.
// Note that Mask may not have enough bits to describe all explicit and
@@ -699,15 +733,21 @@ InstrBuilder::createInstruction(const MCInst &MCI) {
if (Mask.getBitWidth() > RD.UseIndex) {
// Okay. This map describe register use `RD.UseIndex`.
if (Mask[RD.UseIndex])
- RS.setIndependentFromDef();
+ RS->setIndependentFromDef();
}
}
}
}
+ if (IsInstRecycled && Idx < NewIS->getUses().size())
+ NewIS->getUses().pop_back_n(NewIS->getUses().size() - Idx);
// Early exit if there are no writes.
- if (D.Writes.empty())
- return std::move(NewIS);
+ if (D.Writes.empty()) {
+ if (IsInstRecycled)
+ return llvm::make_error<RecycledInstErr>(NewIS);
+ else
+ return std::move(CreatedIS);
+ }
// Track register writes that implicitly clear the upper portion of the
// underlying super-registers using an APInt.
@@ -720,6 +760,7 @@ InstrBuilder::createInstruction(const MCInst &MCI) {
// Initialize writes.
unsigned WriteIndex = 0;
+ Idx = 0U;
for (const WriteDescriptor &WD : D.Writes) {
RegID = WD.isImplicitWrite() ? WD.RegisterID
: MCI.getOperand(WD.OpIndex).getReg();
@@ -730,13 +771,26 @@ InstrBuilder::createInstruction(const MCInst &MCI) {
}
assert(RegID && "Expected a valid register ID!");
- NewIS->getDefs().emplace_back(WD, RegID,
- /* ClearsSuperRegs */ WriteMask[WriteIndex],
- /* WritesZero */ IsZeroIdiom);
+ if (IsInstRecycled && Idx < NewIS->getDefs().size()) {
+ NewIS->getDefs()[Idx++] =
+ WriteState(WD, RegID,
+ /* ClearsSuperRegs */ WriteMask[WriteIndex],
+ /* WritesZero */ IsZeroIdiom);
+ } else {
+ NewIS->getDefs().emplace_back(WD, RegID,
+ /* ClearsSuperRegs */ WriteMask[WriteIndex],
+ /* WritesZero */ IsZeroIdiom);
+ ++Idx;
+ }
++WriteIndex;
}
+ if (IsInstRecycled && Idx < NewIS->getDefs().size())
+ NewIS->getDefs().pop_back_n(NewIS->getDefs().size() - Idx);
- return std::move(NewIS);
+ if (IsInstRecycled)
+ return llvm::make_error<RecycledInstErr>(NewIS);
+ else
+ return std::move(CreatedIS);
}
} // namespace mca
} // namespace llvm