[llvm] [MachineOutliner] Remove LOHs from outlined candidates (PR #143617)

Ellis Hoag via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 12 16:27:07 PDT 2025


https://github.com/ellishg updated https://github.com/llvm/llvm-project/pull/143617

>From 30acec2164a34bbb9a8d6cf12ffd52efe480dbc4 Mon Sep 17 00:00:00 2001
From: Ellis Hoag <ellishoag at meta.com>
Date: Tue, 10 Jun 2025 10:34:35 -0700
Subject: [PATCH 1/4] [LOH] Remove hints when outlining

---
 llvm/include/llvm/CodeGen/TargetInstrInfo.h   |  6 ++
 llvm/lib/CodeGen/MachineOutliner.cpp          | 18 ++++++
 llvm/lib/Target/AArch64/AArch64InstrInfo.cpp  | 16 ++---
 llvm/lib/Target/AArch64/AArch64InstrInfo.h    |  1 +
 .../AArch64/AArch64MachineFunctionInfo.h      | 13 ++++
 .../CodeGen/AArch64/machine-outliner-loh.ll   | 63 +++++++++++++++++++
 6 files changed, 110 insertions(+), 7 deletions(-)
 create mode 100644 llvm/test/CodeGen/AArch64/machine-outliner-loh.ll

diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
index b5b83c7ff1164..3aec8791b7957 100644
--- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
@@ -2184,6 +2184,12 @@ class LLVM_ABI TargetInstrInfo : public MCInstrInfo {
                                        MachineBasicBlock::iterator &MIT,
                                        unsigned Flags) const;
 
+  /// Remove all Linker Optimization Hints associated with instructions in
+  // \p MIs and \return the number of hints removed.
+  virtual size_t clearLOHs(const SmallPtrSetImpl<MachineInstr *> &MIs) const {
+    return 0;
+  }
+
   /// Optional target hook that returns true if \p MBB is safe to outline from,
   /// and returns any target-specific information in \p Flags.
   virtual bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
diff --git a/llvm/lib/CodeGen/MachineOutliner.cpp b/llvm/lib/CodeGen/MachineOutliner.cpp
index e48612369a5db..02a08e4d50818 100644
--- a/llvm/lib/CodeGen/MachineOutliner.cpp
+++ b/llvm/lib/CodeGen/MachineOutliner.cpp
@@ -104,6 +104,7 @@ STATISTIC(StableHashAttempts,
           "Count of hashing attempts made for outlined functions");
 STATISTIC(StableHashDropped,
           "Count of unsuccessful hashing attempts for outlined functions");
+STATISTIC(NumRemovedLOHs, "Total number of Linker Optimization Hints removed");
 
 // Set to true if the user wants the outliner to run on linkonceodr linkage
 // functions. This is false by default because the linker can dedupe linkonceodr
@@ -1075,6 +1076,23 @@ bool MachineOutliner::outline(
                       << " B) > threshold (" << OutlinerBenefitThreshold
                       << " B)\n");
 
+    // Remove all Linker Optimization Hints from the candidates since we did not
+    // check if the set of hints are the same for each of them.
+    // TODO: The intersection of the LOHs from all candidates should be legal in
+    // the outlined function.
+    SmallPtrSet<MachineInstr *, 2> MIs;
+    std::optional<size_t> MinRemovedLOHs;
+    for (Candidate &C : OF->Candidates) {
+      const TargetInstrInfo &TII = *C.getMF()->getSubtarget().getInstrInfo();
+      for (MachineInstr &MI : C)
+        MIs.insert(&MI);
+      size_t NumRemoved = TII.clearLOHs(MIs);
+      MIs.clear();
+      MinRemovedLOHs =
+          std::min(MinRemovedLOHs.value_or(NumRemoved), NumRemoved);
+    }
+    NumRemovedLOHs += MinRemovedLOHs.value_or(0);
+
     // It's beneficial. Create the function and outline its sequence's
     // occurrences.
     OF->MF = createOutlinedFunction(M, *OF, Mapper, OutlinedFunctionNum);
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index 951cb93ea8f8c..ea04bd4cf2428 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -9641,14 +9641,20 @@ AArch64InstrInfo::getOutlinableRanges(MachineBasicBlock &MBB,
   return Ranges;
 }
 
+size_t
+AArch64InstrInfo::clearLOHs(const SmallPtrSetImpl<MachineInstr *> &MIs) const {
+  if (MIs.empty())
+    return 0;
+  auto *MI = *MIs.begin();
+  auto *FuncInfo = MI->getMF()->getInfo<AArch64FunctionInfo>();
+  return FuncInfo->clearLOHs(MIs);
+}
+
 outliner::InstrType
 AArch64InstrInfo::getOutliningTypeImpl(const MachineModuleInfo &MMI,
                                        MachineBasicBlock::iterator &MIT,
                                        unsigned Flags) const {
   MachineInstr &MI = *MIT;
-  MachineBasicBlock *MBB = MI.getParent();
-  MachineFunction *MF = MBB->getParent();
-  AArch64FunctionInfo *FuncInfo = MF->getInfo<AArch64FunctionInfo>();
 
   // Don't outline anything used for return address signing. The outlined
   // function will get signed later if needed
@@ -9676,10 +9682,6 @@ AArch64InstrInfo::getOutliningTypeImpl(const MachineModuleInfo &MMI,
     return outliner::InstrType::Illegal;
   }
 
-  // Don't outline LOHs.
-  if (FuncInfo->getLOHRelated().count(&MI))
-    return outliner::InstrType::Illegal;
-
   // We can only outline these if we will tail call the outlined function, or
   // fix up the CFI offsets. Currently, CFI instructions are outlined only if
   // in a tail call.
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.h b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
index 7c255da333e4b..45817e85e3826 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
@@ -493,6 +493,7 @@ class AArch64InstrInfo final : public AArch64GenInstrInfo {
   outliner::InstrType getOutliningTypeImpl(const MachineModuleInfo &MMI,
                                            MachineBasicBlock::iterator &MIT,
                                            unsigned Flags) const override;
+  size_t clearLOHs(const SmallPtrSetImpl<MachineInstr *> &MIs) const override;
   SmallVector<
       std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>
   getOutlinableRanges(MachineBasicBlock &MBB, unsigned &Flags) const override;
diff --git a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
index 361d5ec3f2b22..0c0217cf4fa3f 100644
--- a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
@@ -504,6 +504,19 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
     LOHRelated.insert_range(Args);
   }
 
+  size_t clearLOHs(const SmallPtrSetImpl<MachineInstr *> &MIs) {
+    size_t InitialSize = LOHContainerSet.size();
+    erase_if(LOHContainerSet, [&](const auto &D) {
+      return any_of(D.getArgs(), [&](auto *Arg) { return MIs.contains(Arg); });
+    });
+    // In theory there could be an LOH with one label in MIs and another label
+    // outside MIs, however we don't know if the label outside MIs is used in
+    // any other LOHs, so we can't remove them from LOHRelated. In that case, we
+    // might produce a few extra labels, but it won't break anything.
+    LOHRelated.remove_if([&](auto *MI) { return MIs.contains(MI); });
+    return InitialSize - LOHContainerSet.size();
+  };
+
   SmallVectorImpl<ForwardedRegister> &getForwardedMustTailRegParms() {
     return ForwardedMustTailRegParms;
   }
diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-loh.ll b/llvm/test/CodeGen/AArch64/machine-outliner-loh.ll
new file mode 100644
index 0000000000000..66914d70c23f9
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-loh.ll
@@ -0,0 +1,63 @@
+; RUN: llc -verify-machineinstrs -mtriple=aarch64-apple-darwin < %s | FileCheck %s --implicit-check-not=.loh --check-prefixes=CHECK,LOH
+; RUN: llc -verify-machineinstrs -mtriple=aarch64-apple-darwin -enable-machine-outliner < %s | FileCheck %s --implicit-check-not=.loh --check-prefixes=CHECK,OUTLINE
+
+ at A = global i32 0, align 4
+ at B = global i32 0, align 4
+
+declare void @foo();
+declare void @bar(ptr %a);
+declare void @goo(ptr %a);
+
+; CHECK-LABEL: _a0:
+define i32 @a0(i32 %a) {
+  %addr = getelementptr inbounds i32, ptr @A, i32 0
+  %res = load i32, ptr %addr, align 4
+  ; LOH:      [[L0:Lloh.+]]:
+  ; LOH-NEXT:   adrp x19, _A at PAGE
+  ; LOH-NEXT: [[L1:Lloh.+]]:
+  ; LOH-NEXT:   add x19, x19, _A at PAGEOFF
+  call void @foo()
+  ; OUTLINE:      bl _OUTLINED_FUNCTION_0
+  ; OUTLINE-NEXT: mov x0, x19
+  ; OUTLINE-NEXT: bl _bar
+  call void @bar(ptr %addr)
+  %addr2 = getelementptr inbounds i32, ptr @B, i32 4
+  store i32 0, ptr %addr2, align 4
+  ; CHECK:      [[L2:Lloh.+]]:
+  ; CHECK-NEXT:   adrp x8, _B at PAGE
+  ; CHECK-NEXT: [[L3:Lloh.+]]:
+  ; CHECK-NEXT:   add x8, x8, _B at PAGEOFF
+  ; CHECK-NEXT:   mov w0, w20
+  ; CHECK-NEXT: [[L4:Lloh.+]]:
+  ; CHECK-NEXT:   str wzr, [x8, #16]
+  ret i32 %res
+  ; LOH-DAG:   .loh AdrpAdd [[L0]], [[L1]]
+  ; CHECK-DAG: .loh AdrpAddStr [[L2]], [[L3]], [[L4]]
+  ; CHECK:     .cfi_endproc
+}
+
+; CHECK-LABEL: _a1:
+define i32 @a1(i32 %a) {
+  %addr = getelementptr inbounds i32, ptr @A, i32 0
+  %res = load i32, ptr %addr, align 4
+  ; LOH:      [[L5:Lloh.+]]:
+  ; LOH-NEXT:   adrp x19, _A at PAGE
+  ; LOH-NEXT: [[L6:Lloh.+]]:
+  ; LOH-NEXT:   add x19, x19, _A at PAGEOFF
+  call void @foo()
+  ; OUTLINE:      bl _OUTLINED_FUNCTION_0
+  ; OUTLINE-NEXT: mov x0, x19
+  ; OUTLINE-NEXT: bl _goo
+  call void @goo(ptr %addr)
+  ret i32 %res
+  ; LOH:   .loh AdrpAdd [[L5]], [[L6]]
+  ; CHECK: .cfi_endproc
+}
+
+; Note: it is not safe to add LOHs to this function as outlined functions do not
+; follow calling convention and thus x19 could be live across the call.
+; OUTLINE: _OUTLINED_FUNCTION_0:
+; OUTLINE:   adrp x19, _A at PAGE
+; OUTLINE:   add x19, x19, _A at PAGEOFF
+; OUTLINE:   ldr w20, [x19]
+; OUTLINE:   b _foo

>From 09aeee933db51e1176a8f3f36cd781aac1c8d4c6 Mon Sep 17 00:00:00 2001
From: Ellis Hoag <ellishoag at meta.com>
Date: Wed, 11 Jun 2025 10:11:10 -0700
Subject: [PATCH 2/4] rename func

---
 llvm/include/llvm/CodeGen/TargetInstrInfo.h          | 9 ++++++---
 llvm/lib/CodeGen/MachineOutliner.cpp                 | 2 +-
 llvm/lib/Target/AArch64/AArch64InstrInfo.cpp         | 6 +++---
 llvm/lib/Target/AArch64/AArch64InstrInfo.h           | 3 ++-
 llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h | 3 ++-
 5 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
index 3aec8791b7957..d32578540f207 100644
--- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
@@ -2184,9 +2184,12 @@ class LLVM_ABI TargetInstrInfo : public MCInstrInfo {
                                        MachineBasicBlock::iterator &MIT,
                                        unsigned Flags) const;
 
-  /// Remove all Linker Optimization Hints associated with instructions in
-  // \p MIs and \return the number of hints removed.
-  virtual size_t clearLOHs(const SmallPtrSetImpl<MachineInstr *> &MIs) const {
+  /// Remove all Linker Optimization Hints (LOH) associated with instructions in
+  /// \p MIs and \return the number of hints removed. This is useful in
+  /// transformations that cause these hints to be illegal, like in the machine
+  /// outliner.
+  virtual size_t clearLinkerOptimizationHints(
+      const SmallPtrSetImpl<MachineInstr *> &MIs) const {
     return 0;
   }
 
diff --git a/llvm/lib/CodeGen/MachineOutliner.cpp b/llvm/lib/CodeGen/MachineOutliner.cpp
index 02a08e4d50818..9934482673b4a 100644
--- a/llvm/lib/CodeGen/MachineOutliner.cpp
+++ b/llvm/lib/CodeGen/MachineOutliner.cpp
@@ -1086,7 +1086,7 @@ bool MachineOutliner::outline(
       const TargetInstrInfo &TII = *C.getMF()->getSubtarget().getInstrInfo();
       for (MachineInstr &MI : C)
         MIs.insert(&MI);
-      size_t NumRemoved = TII.clearLOHs(MIs);
+      size_t NumRemoved = TII.clearLinkerOptimizationHints(MIs);
       MIs.clear();
       MinRemovedLOHs =
           std::min(MinRemovedLOHs.value_or(NumRemoved), NumRemoved);
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index ea04bd4cf2428..c3e23a1bdecc8 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -9641,13 +9641,13 @@ AArch64InstrInfo::getOutlinableRanges(MachineBasicBlock &MBB,
   return Ranges;
 }
 
-size_t
-AArch64InstrInfo::clearLOHs(const SmallPtrSetImpl<MachineInstr *> &MIs) const {
+size_t AArch64InstrInfo::clearLinkerOptimizationHints(
+    const SmallPtrSetImpl<MachineInstr *> &MIs) const {
   if (MIs.empty())
     return 0;
   auto *MI = *MIs.begin();
   auto *FuncInfo = MI->getMF()->getInfo<AArch64FunctionInfo>();
-  return FuncInfo->clearLOHs(MIs);
+  return FuncInfo->clearLinkerOptimizationHints(MIs);
 }
 
 outliner::InstrType
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.h b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
index 45817e85e3826..34882c96c4497 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
@@ -493,7 +493,8 @@ class AArch64InstrInfo final : public AArch64GenInstrInfo {
   outliner::InstrType getOutliningTypeImpl(const MachineModuleInfo &MMI,
                                            MachineBasicBlock::iterator &MIT,
                                            unsigned Flags) const override;
-  size_t clearLOHs(const SmallPtrSetImpl<MachineInstr *> &MIs) const override;
+  size_t clearLinkerOptimizationHints(
+      const SmallPtrSetImpl<MachineInstr *> &MIs) const override;
   SmallVector<
       std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>
   getOutlinableRanges(MachineBasicBlock &MBB, unsigned &Flags) const override;
diff --git a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
index 0c0217cf4fa3f..e61f2280865b4 100644
--- a/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h
@@ -504,7 +504,8 @@ class AArch64FunctionInfo final : public MachineFunctionInfo {
     LOHRelated.insert_range(Args);
   }
 
-  size_t clearLOHs(const SmallPtrSetImpl<MachineInstr *> &MIs) {
+  size_t
+  clearLinkerOptimizationHints(const SmallPtrSetImpl<MachineInstr *> &MIs) {
     size_t InitialSize = LOHContainerSet.size();
     erase_if(LOHContainerSet, [&](const auto &D) {
       return any_of(D.getArgs(), [&](auto *Arg) { return MIs.contains(Arg); });

>From c109081af20934e2bc115ffdc06568eefecb8f87 Mon Sep 17 00:00:00 2001
From: Ellis Hoag <ellishoag at meta.com>
Date: Wed, 11 Jun 2025 14:17:30 -0700
Subject: [PATCH 3/4] add mir test

---
 llvm/lib/CodeGen/MachineOutliner.cpp          |  9 +---
 .../CodeGen/AArch64/machine-outliner-loh.mir  | 50 +++++++++++++++++++
 2 files changed, 52 insertions(+), 7 deletions(-)
 create mode 100644 llvm/test/CodeGen/AArch64/machine-outliner-loh.mir

diff --git a/llvm/lib/CodeGen/MachineOutliner.cpp b/llvm/lib/CodeGen/MachineOutliner.cpp
index 9934482673b4a..da73bd376bbe2 100644
--- a/llvm/lib/CodeGen/MachineOutliner.cpp
+++ b/llvm/lib/CodeGen/MachineOutliner.cpp
@@ -1076,22 +1076,17 @@ bool MachineOutliner::outline(
                       << " B) > threshold (" << OutlinerBenefitThreshold
                       << " B)\n");
 
-    // Remove all Linker Optimization Hints from the candidates since we did not
-    // check if the set of hints are the same for each of them.
+    // Remove all Linker Optimization Hints from the candidates.
     // TODO: The intersection of the LOHs from all candidates should be legal in
     // the outlined function.
     SmallPtrSet<MachineInstr *, 2> MIs;
-    std::optional<size_t> MinRemovedLOHs;
     for (Candidate &C : OF->Candidates) {
       const TargetInstrInfo &TII = *C.getMF()->getSubtarget().getInstrInfo();
       for (MachineInstr &MI : C)
         MIs.insert(&MI);
-      size_t NumRemoved = TII.clearLinkerOptimizationHints(MIs);
+      NumRemovedLOHs += TII.clearLinkerOptimizationHints(MIs);
       MIs.clear();
-      MinRemovedLOHs =
-          std::min(MinRemovedLOHs.value_or(NumRemoved), NumRemoved);
     }
-    NumRemovedLOHs += MinRemovedLOHs.value_or(0);
 
     // It's beneficial. Create the function and outline its sequence's
     // occurrences.
diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-loh.mir b/llvm/test/CodeGen/AArch64/machine-outliner-loh.mir
new file mode 100644
index 0000000000000..c613e316f828f
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-loh.mir
@@ -0,0 +1,50 @@
+# RUN: llc %s -mtriple=aarch64-apple-ios -run-pass=aarch64-collect-loh -run-pass=machine-outliner -stats -o - 2>%t | FileCheck %s
+# RUN: FileCheck %s --input-file=%t --check-prefix=STATS
+# REQUIRES: asserts
+
+--- |
+  define void  @func0() noredzone minsize { ret void }
+
+  @g0 = external global i32
+...
+---
+# CHECK-LABEL: name: func0
+name: func0
+tracksRegLiveness: true
+body: |
+  ; CHECK-LABEL: bb.0:
+  bb.0:
+    ; CHECK: BL @OUTLINED_FUNCTION_0
+    $x10 = ADRP target-flags(aarch64-page) @g0
+    $x11 = ADDXri $x10, target-flags(aarch64-pageoff) @g0, 0
+    $w0 = ORRWri $wzr, 1
+    $w0 = ORRWri $wzr, 1
+    $w0 = ORRWri $wzr, 1
+    $w0 = ORRWri $wzr, 1
+
+  ; CHECK-LABEL: bb.1:
+  bb.1:
+    ; CHECK: BL @OUTLINED_FUNCTION_0
+    ; MCLOH_AdrpAdd is not generated because $x11 is still live. If we want to
+    ; outline these instructions, we must remove the MCLOH_AdrpAdd from bb.0.
+    $x10 = ADRP target-flags(aarch64-page) @g0
+    $x11 = ADDXri $x10, target-flags(aarch64-pageoff) @g0, 0
+    $w0 = ORRWri $wzr, 1
+    $w0 = ORRWri $wzr, 1
+    $w0 = ORRWri $wzr, 1
+    $w0 = ORRWri $wzr, 1
+    ; CHECK: $x12 = ADDXri $x11, target-flags(aarch64-pageoff) @g0, 0
+    $x12 = ADDXri $x11, target-flags(aarch64-pageoff) @g0, 0
+
+...
+
+# CHECK-LABEL: name: OUTLINED_FUNCTION_0
+# CHECK:           $x10 = ADRP target-flags(aarch64-page) @g0
+# CHECK:           $x11 = ADDXri $x10, target-flags(aarch64-pageoff) @g0, 0
+# CHECK:           $w0 = ORRWri $wzr, 1
+# CHECK:           $w0 = ORRWri $wzr, 1
+# CHECK:           $w0 = ORRWri $wzr, 1
+# CHECK:           $w0 = ORRWri $wzr, 1
+
+# STATS: 1 aarch64-collect-loh - Number of simplifiable ADRP + ADD
+# STATS: 1 machine-outliner    - Total number of Linker Optimization Hints removed

>From e62480b9d6ef165ae696fd9e148cd9b54df6ccbe Mon Sep 17 00:00:00 2001
From: Ellis Hoag <ellishoag at meta.com>
Date: Thu, 12 Jun 2025 16:26:54 -0700
Subject: [PATCH 4/4] Use TargetMachine

---
 llvm/include/llvm/CodeGen/TargetInstrInfo.h      |  9 ---------
 llvm/include/llvm/Target/TargetMachine.h         | 10 ++++++++++
 llvm/lib/CodeGen/MachineOutliner.cpp             |  8 ++++++--
 llvm/lib/Target/AArch64/AArch64InstrInfo.cpp     |  9 ---------
 llvm/lib/Target/AArch64/AArch64InstrInfo.h       |  2 --
 llvm/lib/Target/AArch64/AArch64TargetMachine.cpp |  9 +++++++++
 llvm/lib/Target/AArch64/AArch64TargetMachine.h   |  3 +++
 7 files changed, 28 insertions(+), 22 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/TargetInstrInfo.h b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
index d32578540f207..b5b83c7ff1164 100644
--- a/llvm/include/llvm/CodeGen/TargetInstrInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetInstrInfo.h
@@ -2184,15 +2184,6 @@ class LLVM_ABI TargetInstrInfo : public MCInstrInfo {
                                        MachineBasicBlock::iterator &MIT,
                                        unsigned Flags) const;
 
-  /// Remove all Linker Optimization Hints (LOH) associated with instructions in
-  /// \p MIs and \return the number of hints removed. This is useful in
-  /// transformations that cause these hints to be illegal, like in the machine
-  /// outliner.
-  virtual size_t clearLinkerOptimizationHints(
-      const SmallPtrSetImpl<MachineInstr *> &MIs) const {
-    return 0;
-  }
-
   /// Optional target hook that returns true if \p MBB is safe to outline from,
   /// and returns any target-specific information in \p Flags.
   virtual bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h
index 906926729ed74..a2d5409fdf50b 100644
--- a/llvm/include/llvm/Target/TargetMachine.h
+++ b/llvm/include/llvm/Target/TargetMachine.h
@@ -37,6 +37,7 @@ using ModulePassManager = PassManager<Module>;
 
 class Function;
 class GlobalValue;
+class MachineInstr;
 class MachineModuleInfoWrapperPass;
 struct MachineSchedContext;
 class Mangler;
@@ -518,6 +519,15 @@ class TargetMachine {
 
   // MachineRegisterInfo callback function
   virtual void registerMachineRegisterInfoCallback(MachineFunction &MF) const {}
+
+  /// Remove all Linker Optimization Hints (LOH) associated with instructions in
+  /// \p MIs and \return the number of hints removed. This is useful in
+  /// transformations that cause these hints to be illegal, like in the machine
+  /// outliner.
+  virtual size_t clearLinkerOptimizationHints(
+      const SmallPtrSetImpl<MachineInstr *> &MIs) const {
+    return 0;
+  }
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/CodeGen/MachineOutliner.cpp b/llvm/lib/CodeGen/MachineOutliner.cpp
index da73bd376bbe2..b0bce2c21a470 100644
--- a/llvm/lib/CodeGen/MachineOutliner.cpp
+++ b/llvm/lib/CodeGen/MachineOutliner.cpp
@@ -67,6 +67,7 @@
 #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
 #include "llvm/CodeGen/Passes.h"
 #include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/IR/DIBuilder.h"
 #include "llvm/IR/IRBuilder.h"
@@ -77,6 +78,7 @@
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/SuffixTree.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetMachine.h"
 #include "llvm/Transforms/Utils/ModuleUtils.h"
 #include <tuple>
 #include <vector>
@@ -427,6 +429,7 @@ struct MachineOutliner : public ModulePass {
   static char ID;
 
   MachineModuleInfo *MMI = nullptr;
+  const TargetMachine *TM = nullptr;
 
   /// Set to true if the outliner should consider functions with
   /// linkonceodr linkage.
@@ -462,6 +465,7 @@ struct MachineOutliner : public ModulePass {
 
   void getAnalysisUsage(AnalysisUsage &AU) const override {
     AU.addRequired<MachineModuleInfoWrapperPass>();
+    AU.addRequired<TargetPassConfig>();
     AU.addPreserved<MachineModuleInfoWrapperPass>();
     AU.addUsedIfAvailable<ImmutableModuleSummaryIndexWrapperPass>();
     AU.setPreservesAll();
@@ -1081,10 +1085,9 @@ bool MachineOutliner::outline(
     // the outlined function.
     SmallPtrSet<MachineInstr *, 2> MIs;
     for (Candidate &C : OF->Candidates) {
-      const TargetInstrInfo &TII = *C.getMF()->getSubtarget().getInstrInfo();
       for (MachineInstr &MI : C)
         MIs.insert(&MI);
-      NumRemovedLOHs += TII.clearLinkerOptimizationHints(MIs);
+      NumRemovedLOHs += TM->clearLinkerOptimizationHints(MIs);
       MIs.clear();
     }
 
@@ -1399,6 +1402,7 @@ bool MachineOutliner::runOnModule(Module &M) {
   initializeOutlinerMode(M);
 
   MMI = &getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
+  TM = &getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
 
   // Number to append to the current outlined function.
   unsigned OutlinedFunctionNum = 0;
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index c3e23a1bdecc8..ea57ea8873d40 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -9641,15 +9641,6 @@ AArch64InstrInfo::getOutlinableRanges(MachineBasicBlock &MBB,
   return Ranges;
 }
 
-size_t AArch64InstrInfo::clearLinkerOptimizationHints(
-    const SmallPtrSetImpl<MachineInstr *> &MIs) const {
-  if (MIs.empty())
-    return 0;
-  auto *MI = *MIs.begin();
-  auto *FuncInfo = MI->getMF()->getInfo<AArch64FunctionInfo>();
-  return FuncInfo->clearLinkerOptimizationHints(MIs);
-}
-
 outliner::InstrType
 AArch64InstrInfo::getOutliningTypeImpl(const MachineModuleInfo &MMI,
                                        MachineBasicBlock::iterator &MIT,
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.h b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
index 34882c96c4497..7c255da333e4b 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h
@@ -493,8 +493,6 @@ class AArch64InstrInfo final : public AArch64GenInstrInfo {
   outliner::InstrType getOutliningTypeImpl(const MachineModuleInfo &MMI,
                                            MachineBasicBlock::iterator &MIT,
                                            unsigned Flags) const override;
-  size_t clearLinkerOptimizationHints(
-      const SmallPtrSetImpl<MachineInstr *> &MIs) const override;
   SmallVector<
       std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>
   getOutlinableRanges(MachineBasicBlock &MBB, unsigned &Flags) const override;
diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
index 50f52cca6c8ac..a9c9c450976d4 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp
@@ -509,6 +509,15 @@ AArch64TargetMachine::createPostMachineScheduler(MachineSchedContext *C) const {
   return DAG;
 }
 
+size_t AArch64TargetMachine::clearLinkerOptimizationHints(
+    const SmallPtrSetImpl<MachineInstr *> &MIs) const {
+  if (MIs.empty())
+    return 0;
+  auto *MI = *MIs.begin();
+  auto *FuncInfo = MI->getMF()->getInfo<AArch64FunctionInfo>();
+  return FuncInfo->clearLinkerOptimizationHints(MIs);
+}
+
 void AArch64leTargetMachine::anchor() { }
 
 AArch64leTargetMachine::AArch64leTargetMachine(
diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.h b/llvm/lib/Target/AArch64/AArch64TargetMachine.h
index f8ba41f215430..b9e522dd6f226 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetMachine.h
+++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.h
@@ -76,6 +76,9 @@ class AArch64TargetMachine : public CodeGenTargetMachineImpl {
   ScheduleDAGInstrs *
   createPostMachineScheduler(MachineSchedContext *C) const override;
 
+  size_t clearLinkerOptimizationHints(
+      const SmallPtrSetImpl<MachineInstr *> &MIs) const override;
+
 private:
   bool isLittle;
 };



More information about the llvm-commits mailing list