diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h index b5b83c7ff1164..5a001b7083945 100644 --- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h +++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h @@ -2057,6 +2057,21 @@ class LLVM_ABI TargetInstrInfo : public MCInstrInfo { /// overhead or too rigid restriction. virtual unsigned getMemOperandAACheckLimit() const { return 16; } + /// Return the maximum number of memory operands to check instruction for + /// memory-related properties. + /// + /// After MIR transformations like tail merging etc. memory operands are + /// united for the merged result instructions. Compiler might ends up with + /// thousands of memory operands for each instruction for tricky CFGs like + /// for switch construction. + /// + /// Even linear algorithms on instructions with thousands of memory operands + /// leads to significant compilation slowdown. + /// + /// Heuristic is designed to limit checks count for algorithms where + /// conservative answer like "I don't know" is possible. + virtual unsigned getMemOperandLinearCheckLimit() const { return 16; } + /// Return an array that contains the ids of the target indices (used for the /// TargetIndex machine operand) and their names. /// diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp index da3665b3b6a0b..f93018dc8b94b 100644 --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -1581,6 +1581,12 @@ bool MachineInstr::hasOrderedMemoryRef() const { if (memoperands_empty()) return true; + // Conservatively skip analysis if there are too many memory operands. Keep + // compilation time reasonable. + const TargetInstrInfo *TII = getMF()->getSubtarget().getInstrInfo(); + if (getNumMemOperands() > TII->getMemOperandLinearCheckLimit()) + return true; + // Check if any of our memory operands are ordered. return llvm::any_of(memoperands(), [](const MachineMemOperand *MMO) { return !MMO->isUnordered(); @@ -1600,7 +1606,15 @@ bool MachineInstr::isDereferenceableInvariantLoad() const { if (memoperands_empty()) return false; - const MachineFrameInfo &MFI = getParent()->getParent()->getFrameInfo(); + const MachineFunction &MF = *getMF(); + + // Conservatively skip analysis if there are too many memory operands. Keep + // compilation time reasonable. + const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); + if (getNumMemOperands() > TII->getMemOperandLinearCheckLimit()) + return false; + + const MachineFrameInfo &MFI = MF.getFrameInfo(); for (MachineMemOperand *MMO : memoperands()) { if (!MMO->isUnordered())