aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp2
-rw-r--r--llvm/lib/CodeGen/CMakeLists.txt1
-rw-r--r--llvm/lib/CodeGen/CodeGen.cpp2
-rw-r--r--llvm/lib/CodeGen/InlineSpiller.cpp21
-rw-r--r--llvm/lib/CodeGen/LiveRangeEdit.cpp108
-rw-r--r--llvm/lib/CodeGen/MIR2Vec.cpp300
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp8
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h2
-rw-r--r--llvm/lib/CodeGen/SplitKit.cpp4
9 files changed, 368 insertions, 80 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
index d98d180..dc38f5a 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
@@ -240,6 +240,8 @@ bool DebugHandlerBase::isUnsignedDIType(const DIType *Ty) {
Encoding == dwarf::DW_ATE_complex_float ||
Encoding == dwarf::DW_ATE_signed_fixed ||
Encoding == dwarf::DW_ATE_unsigned_fixed ||
+ (Encoding >= dwarf::DW_ATE_lo_user &&
+ Encoding <= dwarf::DW_ATE_hi_user) ||
(Ty->getTag() == dwarf::DW_TAG_unspecified_type &&
Ty->getName() == "decltype(nullptr)")) &&
"Unsupported encoding");
diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt
index f8f9bbb..b6872605 100644
--- a/llvm/lib/CodeGen/CMakeLists.txt
+++ b/llvm/lib/CodeGen/CMakeLists.txt
@@ -155,6 +155,7 @@ add_llvm_component_library(LLVMCodeGen
MIRFSDiscriminator.cpp
MIRSampleProfile.cpp
MIRYamlMapping.cpp
+ MIR2Vec.cpp
MLRegAllocEvictAdvisor.cpp
MLRegAllocPriorityAdvisor.cpp
ModuloSchedule.cpp
diff --git a/llvm/lib/CodeGen/CodeGen.cpp b/llvm/lib/CodeGen/CodeGen.cpp
index 9e0cb3b..c438eae 100644
--- a/llvm/lib/CodeGen/CodeGen.cpp
+++ b/llvm/lib/CodeGen/CodeGen.cpp
@@ -96,6 +96,8 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
initializeMachineSchedulerLegacyPass(Registry);
initializeMachineSinkingLegacyPass(Registry);
initializeMachineUniformityAnalysisPassPass(Registry);
+ initializeMIR2VecVocabLegacyAnalysisPass(Registry);
+ initializeMIR2VecVocabPrinterLegacyPassPass(Registry);
initializeMachineUniformityInfoPrinterPassPass(Registry);
initializeMachineVerifierLegacyPassPass(Registry);
initializeObjCARCContractLegacyPassPass(Registry);
diff --git a/llvm/lib/CodeGen/InlineSpiller.cpp b/llvm/lib/CodeGen/InlineSpiller.cpp
index 0c2b74c..d6e8505 100644
--- a/llvm/lib/CodeGen/InlineSpiller.cpp
+++ b/llvm/lib/CodeGen/InlineSpiller.cpp
@@ -671,10 +671,22 @@ bool InlineSpiller::reMaterializeFor(LiveInterval &VirtReg, MachineInstr &MI) {
LiveInterval &OrigLI = LIS.getInterval(Original);
VNInfo *OrigVNI = OrigLI.getVNInfoAt(UseIdx);
- LiveRangeEdit::Remat RM(ParentVNI);
- RM.OrigMI = LIS.getInstructionFromIndex(OrigVNI->def);
+ assert(OrigVNI && "corrupted sub-interval");
+ MachineInstr *DefMI = LIS.getInstructionFromIndex(OrigVNI->def);
+ // This can happen if for two reasons: 1) This could be a phi valno,
+ // or 2) the remat def has already been removed from the original
+ // live interval; this happens if we rematted to all uses, and
+ // then further split one of those live ranges.
+ if (!DefMI) {
+ markValueUsed(&VirtReg, ParentVNI);
+ LLVM_DEBUG(dbgs() << "\tcannot remat missing def for " << UseIdx << '\t'
+ << MI);
+ return false;
+ }
- if (!Edit->canRematerializeAt(RM, OrigVNI, UseIdx)) {
+ LiveRangeEdit::Remat RM(ParentVNI);
+ RM.OrigMI = DefMI;
+ if (!Edit->canRematerializeAt(RM, UseIdx)) {
markValueUsed(&VirtReg, ParentVNI);
LLVM_DEBUG(dbgs() << "\tcannot remat for " << UseIdx << '\t' << MI);
return false;
@@ -739,9 +751,6 @@ bool InlineSpiller::reMaterializeFor(LiveInterval &VirtReg, MachineInstr &MI) {
/// reMaterializeAll - Try to rematerialize as many uses as possible,
/// and trim the live ranges after.
void InlineSpiller::reMaterializeAll() {
- if (!Edit->anyRematerializable())
- return;
-
UsedValues.clear();
// Try to remat before all uses of snippets.
diff --git a/llvm/lib/CodeGen/LiveRangeEdit.cpp b/llvm/lib/CodeGen/LiveRangeEdit.cpp
index 59bc82d..5b0365d 100644
--- a/llvm/lib/CodeGen/LiveRangeEdit.cpp
+++ b/llvm/lib/CodeGen/LiveRangeEdit.cpp
@@ -68,41 +68,12 @@ Register LiveRangeEdit::createFrom(Register OldReg) {
return VReg;
}
-void LiveRangeEdit::scanRemattable() {
- for (VNInfo *VNI : getParent().valnos) {
- if (VNI->isUnused())
- continue;
- Register Original = VRM->getOriginal(getReg());
- LiveInterval &OrigLI = LIS.getInterval(Original);
- VNInfo *OrigVNI = OrigLI.getVNInfoAt(VNI->def);
- if (!OrigVNI)
- continue;
- MachineInstr *DefMI = LIS.getInstructionFromIndex(OrigVNI->def);
- if (!DefMI)
- continue;
- if (TII.isReMaterializable(*DefMI))
- Remattable.insert(OrigVNI);
- }
- ScannedRemattable = true;
-}
-
-bool LiveRangeEdit::anyRematerializable() {
- if (!ScannedRemattable)
- scanRemattable();
- return !Remattable.empty();
-}
-
-bool LiveRangeEdit::canRematerializeAt(Remat &RM, VNInfo *OrigVNI,
- SlotIndex UseIdx) {
- assert(ScannedRemattable && "Call anyRematerializable first");
+bool LiveRangeEdit::canRematerializeAt(Remat &RM, SlotIndex UseIdx) {
+ assert(RM.OrigMI && "No defining instruction for remattable value");
- // Use scanRemattable info.
- if (!Remattable.count(OrigVNI))
+ if (!TII.isReMaterializable(*RM.OrigMI))
return false;
- // No defining instruction provided.
- assert(RM.OrigMI && "No defining instruction for remattable value");
-
// Verify that all used registers are available with the same values.
if (!VirtRegAuxInfo::allUsesAvailableAt(RM.OrigMI, UseIdx, LIS, MRI, TII))
return false;
@@ -303,6 +274,37 @@ void LiveRangeEdit::eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink) {
}
}
+ // If the dest of MI is an original reg and MI is reMaterializable,
+ // don't delete the inst. Replace the dest with a new reg, and keep
+ // the inst for remat of other siblings. The inst is saved in
+ // LiveRangeEdit::DeadRemats and will be deleted after all the
+ // allocations of the func are done. Note that if we keep the
+ // instruction with the original operands, that handles the physreg
+ // operand case (described just below) as well.
+ // However, immediately delete instructions which have unshrunk virtual
+ // register uses. That may provoke RA to split an interval at the KILL
+ // and later result in an invalid live segment end.
+ if (isOrigDef && DeadRemats && !HasLiveVRegUses &&
+ TII.isReMaterializable(*MI)) {
+ LiveInterval &NewLI = createEmptyIntervalFrom(Dest, false);
+ VNInfo::Allocator &Alloc = LIS.getVNInfoAllocator();
+ VNInfo *VNI = NewLI.getNextValue(Idx, Alloc);
+ NewLI.addSegment(LiveInterval::Segment(Idx, Idx.getDeadSlot(), VNI));
+
+ if (DestSubReg) {
+ const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
+ auto *SR =
+ NewLI.createSubRange(Alloc, TRI->getSubRegIndexLaneMask(DestSubReg));
+ SR->addSegment(LiveInterval::Segment(Idx, Idx.getDeadSlot(),
+ SR->getNextValue(Idx, Alloc)));
+ }
+
+ pop_back();
+ DeadRemats->insert(MI);
+ const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
+ MI->substituteRegister(Dest, NewLI.reg(), 0, TRI);
+ assert(MI->registerDefIsDead(NewLI.reg(), &TRI));
+ }
// Currently, we don't support DCE of physreg live ranges. If MI reads
// any unreserved physregs, don't erase the instruction, but turn it into
// a KILL instead. This way, the physreg live ranges don't end up
@@ -310,7 +312,7 @@ void LiveRangeEdit::eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink) {
// FIXME: It would be better to have something like shrinkToUses() for
// physregs. That could potentially enable more DCE and it would free up
// the physreg. It would not happen often, though.
- if (ReadsPhysRegs) {
+ else if (ReadsPhysRegs) {
MI->setDesc(TII.get(TargetOpcode::KILL));
// Remove all operands that aren't physregs.
for (unsigned i = MI->getNumOperands(); i; --i) {
@@ -322,41 +324,11 @@ void LiveRangeEdit::eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink) {
MI->dropMemRefs(*MI->getMF());
LLVM_DEBUG(dbgs() << "Converted physregs to:\t" << *MI);
} else {
- // If the dest of MI is an original reg and MI is reMaterializable,
- // don't delete the inst. Replace the dest with a new reg, and keep
- // the inst for remat of other siblings. The inst is saved in
- // LiveRangeEdit::DeadRemats and will be deleted after all the
- // allocations of the func are done.
- // However, immediately delete instructions which have unshrunk virtual
- // register uses. That may provoke RA to split an interval at the KILL
- // and later result in an invalid live segment end.
- if (isOrigDef && DeadRemats && !HasLiveVRegUses &&
- TII.isReMaterializable(*MI)) {
- LiveInterval &NewLI = createEmptyIntervalFrom(Dest, false);
- VNInfo::Allocator &Alloc = LIS.getVNInfoAllocator();
- VNInfo *VNI = NewLI.getNextValue(Idx, Alloc);
- NewLI.addSegment(LiveInterval::Segment(Idx, Idx.getDeadSlot(), VNI));
-
- if (DestSubReg) {
- const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
- auto *SR = NewLI.createSubRange(
- Alloc, TRI->getSubRegIndexLaneMask(DestSubReg));
- SR->addSegment(LiveInterval::Segment(Idx, Idx.getDeadSlot(),
- SR->getNextValue(Idx, Alloc)));
- }
-
- pop_back();
- DeadRemats->insert(MI);
- const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
- MI->substituteRegister(Dest, NewLI.reg(), 0, TRI);
- assert(MI->registerDefIsDead(NewLI.reg(), &TRI));
- } else {
- if (TheDelegate)
- TheDelegate->LRE_WillEraseInstruction(MI);
- LIS.RemoveMachineInstrFromMaps(*MI);
- MI->eraseFromParent();
- ++NumDCEDeleted;
- }
+ if (TheDelegate)
+ TheDelegate->LRE_WillEraseInstruction(MI);
+ LIS.RemoveMachineInstrFromMaps(*MI);
+ MI->eraseFromParent();
+ ++NumDCEDeleted;
}
// Erase any virtregs that are now empty and unused. There may be <undef>
diff --git a/llvm/lib/CodeGen/MIR2Vec.cpp b/llvm/lib/CodeGen/MIR2Vec.cpp
new file mode 100644
index 0000000..83c5646
--- /dev/null
+++ b/llvm/lib/CodeGen/MIR2Vec.cpp
@@ -0,0 +1,300 @@
+//===- MIR2Vec.cpp - Implementation of MIR2Vec ---------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM
+// Exceptions. See the LICENSE file for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file implements the MIR2Vec algorithm for Machine IR embeddings.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/MIR2Vec.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/IR/Module.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Regex.h"
+
+using namespace llvm;
+using namespace mir2vec;
+
+#define DEBUG_TYPE "mir2vec"
+
+STATISTIC(MIRVocabMissCounter,
+ "Number of lookups to MIR entities not present in the vocabulary");
+
+namespace llvm {
+namespace mir2vec {
+cl::OptionCategory MIR2VecCategory("MIR2Vec Options");
+
+// FIXME: Use a default vocab when not specified
+static cl::opt<std::string>
+ VocabFile("mir2vec-vocab-path", cl::Optional,
+ cl::desc("Path to the vocabulary file for MIR2Vec"), cl::init(""),
+ cl::cat(MIR2VecCategory));
+cl::opt<float> OpcWeight("mir2vec-opc-weight", cl::Optional, cl::init(1.0),
+ cl::desc("Weight for machine opcode embeddings"),
+ cl::cat(MIR2VecCategory));
+} // namespace mir2vec
+} // namespace llvm
+
+//===----------------------------------------------------------------------===//
+// Vocabulary Implementation
+//===----------------------------------------------------------------------===//
+
+MIRVocabulary::MIRVocabulary(VocabMap &&OpcodeEntries,
+ const TargetInstrInfo *TII) {
+ // Fixme: Use static factory methods for creating vocabularies instead of
+ // public constructors
+ // Early return for invalid inputs - creates empty/invalid vocabulary
+ if (!TII || OpcodeEntries.empty())
+ return;
+
+ buildCanonicalOpcodeMapping(*TII);
+
+ unsigned CanonicalOpcodeCount = UniqueBaseOpcodeNames.size();
+ assert(CanonicalOpcodeCount > 0 &&
+ "No canonical opcodes found for target - invalid vocabulary");
+ Layout.OperandBase = CanonicalOpcodeCount;
+ generateStorage(OpcodeEntries, *TII);
+ Layout.TotalEntries = Storage.size();
+}
+
+std::string MIRVocabulary::extractBaseOpcodeName(StringRef InstrName) {
+ // Extract base instruction name using regex to capture letters and
+ // underscores Examples: "ADD32rr" -> "ADD", "ARITH_FENCE" -> "ARITH_FENCE"
+ //
+ // TODO: Consider more sophisticated extraction:
+ // - Handle complex prefixes like "AVX1_SETALLONES" correctly (Currently, it
+ // would naively map to "AVX")
+ // - Extract width suffixes (8,16,32,64) as separate features
+ // - Capture addressing mode suffixes (r,i,m,ri,etc.) for better analysis
+ // (Currently, instances like "MOV32mi" map to "MOV", but "ADDPDrr" would map
+ // to "ADDPDrr")
+
+ assert(!InstrName.empty() && "Instruction name should not be empty");
+
+ // Use regex to extract initial sequence of letters and underscores
+ static const Regex BaseOpcodeRegex("([a-zA-Z_]+)");
+ SmallVector<StringRef, 2> Matches;
+
+ if (BaseOpcodeRegex.match(InstrName, &Matches) && Matches.size() > 1) {
+ StringRef Match = Matches[1];
+ // Trim trailing underscores
+ while (!Match.empty() && Match.back() == '_')
+ Match = Match.drop_back();
+ return Match.str();
+ }
+
+ // Fallback to original name if no pattern matches
+ return InstrName.str();
+}
+
+unsigned MIRVocabulary::getCanonicalIndexForBaseName(StringRef BaseName) const {
+ assert(!UniqueBaseOpcodeNames.empty() && "Canonical mapping not built");
+ auto It = std::find(UniqueBaseOpcodeNames.begin(),
+ UniqueBaseOpcodeNames.end(), BaseName.str());
+ assert(It != UniqueBaseOpcodeNames.end() &&
+ "Base name not found in unique opcodes");
+ return std::distance(UniqueBaseOpcodeNames.begin(), It);
+}
+
+std::string MIRVocabulary::getStringKey(unsigned Pos) const {
+ assert(isValid() && "MIR2Vec Vocabulary is invalid");
+ assert(Pos < Layout.TotalEntries && "Position out of bounds in vocabulary");
+
+ // For now, all entries are opcodes since we only have one section
+ if (Pos < Layout.OperandBase && Pos < UniqueBaseOpcodeNames.size()) {
+ // Convert canonical index back to base opcode name
+ auto It = UniqueBaseOpcodeNames.begin();
+ std::advance(It, Pos);
+ return *It;
+ }
+
+ llvm_unreachable("Invalid position in vocabulary");
+ return "";
+}
+
+void MIRVocabulary::generateStorage(const VocabMap &OpcodeMap,
+ const TargetInstrInfo &TII) {
+
+ // Helper for handling missing entities in the vocabulary.
+ // Currently, we use a zero vector. In the future, we will throw an error to
+ // ensure that *all* known entities are present in the vocabulary.
+ auto handleMissingEntity = [](StringRef Key) {
+ LLVM_DEBUG(errs() << "MIR2Vec: Missing vocabulary entry for " << Key
+ << "; using zero vector. This will result in an error "
+ "in the future.\n");
+ ++MIRVocabMissCounter;
+ };
+
+ // Initialize opcode embeddings section
+ unsigned EmbeddingDim = OpcodeMap.begin()->second.size();
+ std::vector<Embedding> OpcodeEmbeddings(Layout.OperandBase,
+ Embedding(EmbeddingDim));
+
+ // Populate opcode embeddings using canonical mapping
+ for (auto COpcodeName : UniqueBaseOpcodeNames) {
+ if (auto It = OpcodeMap.find(COpcodeName); It != OpcodeMap.end()) {
+ auto COpcodeIndex = getCanonicalIndexForBaseName(COpcodeName);
+ assert(COpcodeIndex < Layout.OperandBase &&
+ "Canonical index out of bounds");
+ OpcodeEmbeddings[COpcodeIndex] = It->second;
+ } else {
+ handleMissingEntity(COpcodeName);
+ }
+ }
+
+ // TODO: Add operand/argument embeddings as additional sections
+ // This will require extending the vocabulary format and layout
+
+ // Scale the vocabulary sections based on the provided weights
+ auto scaleVocabSection = [](std::vector<Embedding> &Embeddings,
+ double Weight) {
+ for (auto &Embedding : Embeddings)
+ Embedding *= Weight;
+ };
+ scaleVocabSection(OpcodeEmbeddings, OpcWeight);
+
+ std::vector<std::vector<Embedding>> Sections(1);
+ Sections[0] = std::move(OpcodeEmbeddings);
+
+ Storage = ir2vec::VocabStorage(std::move(Sections));
+}
+
+void MIRVocabulary::buildCanonicalOpcodeMapping(const TargetInstrInfo &TII) {
+ // Check if already built
+ if (!UniqueBaseOpcodeNames.empty())
+ return;
+
+ // Build mapping from opcodes to canonical base opcode indices
+ for (unsigned Opcode = 0; Opcode < TII.getNumOpcodes(); ++Opcode) {
+ std::string BaseOpcode = extractBaseOpcodeName(TII.getName(Opcode));
+ UniqueBaseOpcodeNames.insert(BaseOpcode);
+ }
+
+ LLVM_DEBUG(dbgs() << "MIR2Vec: Built canonical mapping for target with "
+ << UniqueBaseOpcodeNames.size()
+ << " unique base opcodes\n");
+}
+
+//===----------------------------------------------------------------------===//
+// MIR2VecVocabLegacyAnalysis Implementation
+//===----------------------------------------------------------------------===//
+
+char MIR2VecVocabLegacyAnalysis::ID = 0;
+INITIALIZE_PASS_BEGIN(MIR2VecVocabLegacyAnalysis, "mir2vec-vocab-analysis",
+ "MIR2Vec Vocabulary Analysis", false, true)
+INITIALIZE_PASS_DEPENDENCY(MachineModuleInfoWrapperPass)
+INITIALIZE_PASS_END(MIR2VecVocabLegacyAnalysis, "mir2vec-vocab-analysis",
+ "MIR2Vec Vocabulary Analysis", false, true)
+
+StringRef MIR2VecVocabLegacyAnalysis::getPassName() const {
+ return "MIR2Vec Vocabulary Analysis";
+}
+
+Error MIR2VecVocabLegacyAnalysis::readVocabulary() {
+ // TODO: Extend vocabulary format to support multiple sections
+ // (opcodes, operands, etc.) similar to IR2Vec structure
+ if (VocabFile.empty())
+ return createStringError(
+ errc::invalid_argument,
+ "MIR2Vec vocabulary file path not specified; set it "
+ "using --mir2vec-vocab-path");
+
+ auto BufOrError = MemoryBuffer::getFileOrSTDIN(VocabFile, /*IsText=*/true);
+ if (!BufOrError)
+ return createFileError(VocabFile, BufOrError.getError());
+
+ auto Content = BufOrError.get()->getBuffer();
+
+ Expected<json::Value> ParsedVocabValue = json::parse(Content);
+ if (!ParsedVocabValue)
+ return ParsedVocabValue.takeError();
+
+ unsigned Dim = 0;
+ if (auto Err = ir2vec::VocabStorage::parseVocabSection(
+ "entities", *ParsedVocabValue, StrVocabMap, Dim))
+ return Err;
+
+ return Error::success();
+}
+
+void MIR2VecVocabLegacyAnalysis::emitError(Error Err, LLVMContext &Ctx) {
+ Ctx.emitError(toString(std::move(Err)));
+}
+
+mir2vec::MIRVocabulary
+MIR2VecVocabLegacyAnalysis::getMIR2VecVocabulary(const Module &M) {
+ if (StrVocabMap.empty()) {
+ if (Error Err = readVocabulary()) {
+ emitError(std::move(Err), M.getContext());
+ return mir2vec::MIRVocabulary(std::move(StrVocabMap), nullptr);
+ }
+ }
+
+ // Get machine module info to access machine functions and target info
+ MachineModuleInfo &MMI = getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
+
+ // Find first available machine function to get target instruction info
+ for (const auto &F : M) {
+ if (F.isDeclaration())
+ continue;
+
+ if (auto *MF = MMI.getMachineFunction(F)) {
+ const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
+ return mir2vec::MIRVocabulary(std::move(StrVocabMap), TII);
+ }
+ }
+
+ // No machine functions available - return invalid vocabulary
+ emitError(make_error<StringError>("No machine functions found in module",
+ inconvertibleErrorCode()),
+ M.getContext());
+ return mir2vec::MIRVocabulary(std::move(StrVocabMap), nullptr);
+}
+
+//===----------------------------------------------------------------------===//
+// Printer Passes Implementation
+//===----------------------------------------------------------------------===//
+
+char MIR2VecVocabPrinterLegacyPass::ID = 0;
+INITIALIZE_PASS_BEGIN(MIR2VecVocabPrinterLegacyPass, "print-mir2vec-vocab",
+ "MIR2Vec Vocabulary Printer Pass", false, true)
+INITIALIZE_PASS_DEPENDENCY(MIR2VecVocabLegacyAnalysis)
+INITIALIZE_PASS_DEPENDENCY(MachineModuleInfoWrapperPass)
+INITIALIZE_PASS_END(MIR2VecVocabPrinterLegacyPass, "print-mir2vec-vocab",
+ "MIR2Vec Vocabulary Printer Pass", false, true)
+
+bool MIR2VecVocabPrinterLegacyPass::runOnMachineFunction(MachineFunction &MF) {
+ return false;
+}
+
+bool MIR2VecVocabPrinterLegacyPass::doFinalization(Module &M) {
+ auto &Analysis = getAnalysis<MIR2VecVocabLegacyAnalysis>();
+ auto MIR2VecVocab = Analysis.getMIR2VecVocabulary(M);
+
+ if (!MIR2VecVocab.isValid()) {
+ OS << "MIR2Vec Vocabulary Printer: Invalid vocabulary\n";
+ return false;
+ }
+
+ unsigned Pos = 0;
+ for (const auto &Entry : MIR2VecVocab) {
+ OS << "Key: " << MIR2VecVocab.getStringKey(Pos++) << ": ";
+ Entry.print(OS);
+ }
+
+ return false;
+}
+
+MachineFunctionPass *
+llvm::createMIR2VecVocabPrinterLegacyPass(raw_ostream &OS) {
+ return new MIR2VecVocabPrinterLegacyPass(OS);
+}
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
index 83bb1df..b5f8a61 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
@@ -3740,7 +3740,11 @@ bool DAGTypeLegalizer::SoftPromoteHalfOperand(SDNode *N, unsigned OpNo) {
case ISD::STRICT_FP_TO_SINT:
case ISD::STRICT_FP_TO_UINT:
case ISD::FP_TO_SINT:
- case ISD::FP_TO_UINT: Res = SoftPromoteHalfOp_FP_TO_XINT(N); break;
+ case ISD::FP_TO_UINT:
+ case ISD::LRINT:
+ case ISD::LLRINT:
+ Res = SoftPromoteHalfOp_Op0WithStrict(N);
+ break;
case ISD::FP_TO_SINT_SAT:
case ISD::FP_TO_UINT_SAT:
Res = SoftPromoteHalfOp_FP_TO_XINT_SAT(N); break;
@@ -3819,7 +3823,7 @@ SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FP_EXTEND(SDNode *N) {
return DAG.getNode(GetPromotionOpcode(SVT, RVT), SDLoc(N), RVT, Op);
}
-SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FP_TO_XINT(SDNode *N) {
+SDValue DAGTypeLegalizer::SoftPromoteHalfOp_Op0WithStrict(SDNode *N) {
EVT RVT = N->getValueType(0);
bool IsStrict = N->isStrictFPOpcode();
SDValue Op = N->getOperand(IsStrict ? 1 : 0);
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
index 586c341..d580ce0 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
@@ -843,7 +843,7 @@ private:
SDValue SoftPromoteHalfOp_FAKE_USE(SDNode *N, unsigned OpNo);
SDValue SoftPromoteHalfOp_FCOPYSIGN(SDNode *N, unsigned OpNo);
SDValue SoftPromoteHalfOp_FP_EXTEND(SDNode *N);
- SDValue SoftPromoteHalfOp_FP_TO_XINT(SDNode *N);
+ SDValue SoftPromoteHalfOp_Op0WithStrict(SDNode *N);
SDValue SoftPromoteHalfOp_FP_TO_XINT_SAT(SDNode *N);
SDValue SoftPromoteHalfOp_SETCC(SDNode *N);
SDValue SoftPromoteHalfOp_SELECT_CC(SDNode *N, unsigned OpNo);
diff --git a/llvm/lib/CodeGen/SplitKit.cpp b/llvm/lib/CodeGen/SplitKit.cpp
index f118ee5..f9ecb2c 100644
--- a/llvm/lib/CodeGen/SplitKit.cpp
+++ b/llvm/lib/CodeGen/SplitKit.cpp
@@ -376,8 +376,6 @@ void SplitEditor::reset(LiveRangeEdit &LRE, ComplementSpillMode SM) {
if (SpillMode)
LICalc[1].reset(&VRM.getMachineFunction(), LIS.getSlotIndexes(), &MDT,
&LIS.getVNInfoAllocator());
-
- Edit->anyRematerializable();
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
@@ -638,7 +636,7 @@ VNInfo *SplitEditor::defFromParent(unsigned RegIdx, const VNInfo *ParentVNI,
LiveRangeEdit::Remat RM(ParentVNI);
RM.OrigMI = LIS.getInstructionFromIndex(OrigVNI->def);
if (RM.OrigMI && TII.isAsCheapAsAMove(*RM.OrigMI) &&
- Edit->canRematerializeAt(RM, OrigVNI, UseIdx)) {
+ Edit->canRematerializeAt(RM, UseIdx)) {
if (!rematWillIncreaseRestriction(RM.OrigMI, MBB, UseIdx)) {
SlotIndex Def = Edit->rematerializeAt(MBB, I, Reg, RM, TRI, Late);
++NumRemats;