[llvm] [NewPM] Port x86-indirect-branch-tracking (PR #179874)

Kyungtak Woo via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 5 00:08:56 PST 2026


https://github.com/kevinwkt updated https://github.com/llvm/llvm-project/pull/179874

>From 939ba4a2eccc92eff0caf5f05c591b996d943ace Mon Sep 17 00:00:00 2001
From: Kyungtak Woo <kevinwkt at google.com>
Date: Thu, 5 Feb 2026 07:28:20 +0000
Subject: [PATCH 1/3] [X86] Port X86IndirectBranchTracking to New Pass Manager

---
 llvm/lib/Target/X86/X86.h                     | 10 ++-
 llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp |  3 +-
 .../Target/X86/X86IndirectBranchTracking.cpp  | 69 +++++++++++--------
 llvm/lib/Target/X86/X86PassRegistry.def       |  2 +-
 llvm/lib/Target/X86/X86TargetMachine.cpp      |  2 +-
 llvm/test/CodeGen/X86/llc-pipeline-npm.ll     |  4 ++
 6 files changed, 55 insertions(+), 35 deletions(-)

diff --git a/llvm/lib/Target/X86/X86.h b/llvm/lib/Target/X86/X86.h
index 89ebd59539686..422149a8ca0d0 100644
--- a/llvm/lib/Target/X86/X86.h
+++ b/llvm/lib/Target/X86/X86.h
@@ -59,7 +59,14 @@ FunctionPass *createX86IssueVZeroUpperPass();
 
 /// This pass inserts ENDBR instructions before indirect jump/call
 /// destinations as part of CET IBT mechanism.
-FunctionPass *createX86IndirectBranchTrackingPass();
+class X86IndirectBranchTrackingPass
+    : public PassInfoMixin<X86IndirectBranchTrackingPass> {
+public:
+  PreservedAnalyses run(MachineFunction &MF,
+                        MachineFunctionAnalysisManager &MFAM);
+};
+
+FunctionPass *createX86IndirectBranchTrackingLegacyPass();
 
 /// Return a pass that pads short functions with NOOPs.
 /// This will prevent a stall when returning on the Atom.
@@ -429,6 +436,7 @@ void initializeX86FastPreTileConfigLegacyPass(PassRegistry &);
 void initializeX86FastTileConfigLegacyPass(PassRegistry &);
 void initializeX86FixupSetCCLegacyPass(PassRegistry &);
 void initializeX86FlagsCopyLoweringLegacyPass(PassRegistry &);
+void initializeX86IndirectBranchTrackingLegacyPass(PassRegistry &);
 void initializeX86LoadValueInjectionLoadHardeningLegacyPass(PassRegistry &);
 void initializeX86LoadValueInjectionRetHardeningLegacyPass(PassRegistry &);
 void initializeX86LowerAMXIntrinsicsLegacyPassPass(PassRegistry &);
diff --git a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
index 1e2198a95bbae..1b3201f3980fe 100644
--- a/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
+++ b/llvm/lib/Target/X86/X86CodeGenPassBuilder.cpp
@@ -174,8 +174,7 @@ void X86CodeGenPassBuilder::addPreEmitPass(PassManagerWrapper &PMW) const {
     addMachineFunctionPass(BreakFalseDepsPass(), PMW);
   }
 
-  // TODO(boomanaiden154): Add X86IndirectBranchTrackingPass here once it has
-  // been ported.
+  addMachineFunctionPass(X86IndirectBranchTrackingPass(), PMW);
   // TODO(boomanaiden154): Add X86IssueVZeroUpperPass here once it has been
   // ported.
 
diff --git a/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp b/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp
index 52be14228e555..1c9de4693e1da 100644
--- a/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp
+++ b/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp
@@ -36,42 +36,29 @@ cl::opt<bool> IndirectBranchTracking(
 STATISTIC(NumEndBranchAdded, "Number of ENDBR instructions added");
 
 namespace {
-class X86IndirectBranchTrackingPass : public MachineFunctionPass {
+class X86IndirectBranchTrackingLegacy : public MachineFunctionPass {
 public:
-  X86IndirectBranchTrackingPass() : MachineFunctionPass(ID) {}
+  static char ID;
+
+  X86IndirectBranchTrackingLegacy() : MachineFunctionPass(ID) {}
 
   StringRef getPassName() const override {
     return "X86 Indirect Branch Tracking";
   }
 
   bool runOnMachineFunction(MachineFunction &MF) override;
-
-private:
-  static char ID;
-
-  /// Machine instruction info used throughout the class.
-  const X86InstrInfo *TII = nullptr;
-
-  /// Endbr opcode for the current machine function.
-  unsigned int EndbrOpcode = 0;
-
-  /// Adds a new ENDBR instruction to the beginning of the MBB.
-  /// The function will not add it if already exists.
-  /// It will add ENDBR32 or ENDBR64 opcode, depending on the target.
-  /// \returns true if the ENDBR was added and false otherwise.
-  bool addENDBR(MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const;
 };
 
-} // end anonymous namespace
-
-char X86IndirectBranchTrackingPass::ID = 0;
-
-FunctionPass *llvm::createX86IndirectBranchTrackingPass() {
-  return new X86IndirectBranchTrackingPass();
-}
+/// Adds a new ENDBR instruction to the beginning of the MBB.
+/// The function will not add it if already exists.
+/// It will add ENDBR32 or ENDBR64 opcode, depending on the target.
+/// \returns true if the ENDBR was added and false otherwise.
+static bool addENDBR(MachineBasicBlock &MBB, MachineBasicBlock::iterator I) {
+  MachineFunction &MF = *MBB.getParent();
+  const X86Subtarget &SubTarget = MF.getSubtarget<X86Subtarget>();
+  const X86InstrInfo *TII = SubTarget.getInstrInfo();
+  unsigned EndbrOpcode = SubTarget.is64Bit() ? X86::ENDBR64 : X86::ENDBR32;
 
-bool X86IndirectBranchTrackingPass::addENDBR(
-    MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const {
   assert(TII && "Target instruction info was not initialized");
   assert((X86::ENDBR64 == EndbrOpcode || X86::ENDBR32 == EndbrOpcode) &&
          "Unexpected Endbr opcode");
@@ -86,6 +73,17 @@ bool X86IndirectBranchTrackingPass::addENDBR(
   return false;
 }
 
+} // end anonymous namespace
+
+char X86IndirectBranchTrackingLegacy::ID = 0;
+
+INITIALIZE_PASS(X86IndirectBranchTrackingLegacy, DEBUG_TYPE,
+                "X86 Indirect Branch Tracking", false, false)
+
+FunctionPass *llvm::createX86IndirectBranchTrackingLegacyPass() {
+  return new X86IndirectBranchTrackingLegacy();
+}
+
 static bool IsCallReturnTwice(llvm::MachineOperand &MOp) {
   if (!MOp.isGlobal())
     return false;
@@ -113,7 +111,7 @@ static bool needsPrologueENDBR(MachineFunction &MF, const Module *M) {
   }
 }
 
-bool X86IndirectBranchTrackingPass::runOnMachineFunction(MachineFunction &MF) {
+static bool runIndirectBranchTracking(MachineFunction &MF) {
   const X86Subtarget &SubTarget = MF.getSubtarget<X86Subtarget>();
 
   const Module *M = MF.getFunction().getParent();
@@ -135,9 +133,6 @@ bool X86IndirectBranchTrackingPass::runOnMachineFunction(MachineFunction &MF) {
   // True if the current MF was changed and false otherwise.
   bool Changed = false;
 
-  TII = SubTarget.getInstrInfo();
-  EndbrOpcode = SubTarget.is64Bit() ? X86::ENDBR64 : X86::ENDBR32;
-
   // If function is reachable indirectly, mark the first BB with ENDBR.
   if (needsPrologueENDBR(MF, M)) {
     auto MBB = MF.begin();
@@ -189,3 +184,17 @@ bool X86IndirectBranchTrackingPass::runOnMachineFunction(MachineFunction &MF) {
   }
   return Changed;
 }
+
+bool X86IndirectBranchTrackingLegacy::runOnMachineFunction(
+    MachineFunction &MF) {
+  return runIndirectBranchTracking(MF);
+}
+
+PreservedAnalyses
+X86IndirectBranchTrackingPass::run(MachineFunction &MF,
+                                   MachineFunctionAnalysisManager &MFAM) {
+  return runIndirectBranchTracking(MF)
+             ? getMachineFunctionPassPreservedAnalyses()
+                   .preserveSet<CFGAnalyses>()
+             : PreservedAnalyses::all();
+}
diff --git a/llvm/lib/Target/X86/X86PassRegistry.def b/llvm/lib/Target/X86/X86PassRegistry.def
index 4fb6935712818..6fae244e56bf7 100644
--- a/llvm/lib/Target/X86/X86PassRegistry.def
+++ b/llvm/lib/Target/X86/X86PassRegistry.def
@@ -45,6 +45,7 @@ MACHINE_FUNCTION_PASS("x86-fixup-inst-tuning", X86FixupInstTuningPass())
 MACHINE_FUNCTION_PASS("x86-fixup-leas", X86FixupLEAsPass())
 MACHINE_FUNCTION_PASS("x86-fixup-setcc", X86FixupSetCCPass())
 MACHINE_FUNCTION_PASS("x86-fixup-vector-constants", X86FixupVectorConstantsPass())
+MACHINE_FUNCTION_PASS("x86-indirect-branch-tracking", X86IndirectBranchTrackingPass())
 MACHINE_FUNCTION_PASS("x86-flags-copy-lowering", X86FlagsCopyLoweringPass())
 MACHINE_FUNCTION_PASS("x86-fp-stackifier", X86FPStackifierPass())
 MACHINE_FUNCTION_PASS("x86-isel", X86ISelDAGToDAGPass(*this))
@@ -67,7 +68,6 @@ MACHINE_FUNCTION_PASS("x86-wineh-unwindv2", X86WinEHUnwindV2Pass())
 DUMMY_MACHINE_FUNCTION_PASS("x86-cleanup-local-dynamic-tls", X86CleanupLocalDynamicTLSPass())
 DUMMY_MACHINE_FUNCTION_PASS("x86-execution-domain-fix", X86ExecutionDomainFix())
 DUMMY_MACHINE_FUNCTION_PASS("x86-global-base-reg", X86GlobalBaseRegPass())
-DUMMY_MACHINE_FUNCTION_PASS("x86-indirect-branch-tracking", X86IndirectBranchTrackingPass())
 DUMMY_MACHINE_FUNCTION_PASS("x86-indirect-thunks", X86IndirectThunks())
 DUMMY_MACHINE_FUNCTION_PASS("x86-insert-x87-wait", X86InsertX87WaitPass())
 DUMMY_MACHINE_FUNCTION_PASS("x86-issue-vzero-upper", X86IssueVZeroUpperPass())
diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp
index 81c18fecd43b0..a1e9ed3d10840 100644
--- a/llvm/lib/Target/X86/X86TargetMachine.cpp
+++ b/llvm/lib/Target/X86/X86TargetMachine.cpp
@@ -566,7 +566,7 @@ void X86PassConfig::addPreEmitPass() {
     addPass(createBreakFalseDeps());
   }
 
-  addPass(createX86IndirectBranchTrackingPass());
+  addPass(createX86IndirectBranchTrackingLegacyPass());
 
   addPass(createX86IssueVZeroUpperPass());
 
diff --git a/llvm/test/CodeGen/X86/llc-pipeline-npm.ll b/llvm/test/CodeGen/X86/llc-pipeline-npm.ll
index 7c0ddc69ebec7..a5a77b719fba2 100644
--- a/llvm/test/CodeGen/X86/llc-pipeline-npm.ll
+++ b/llvm/test/CodeGen/X86/llc-pipeline-npm.ll
@@ -55,6 +55,7 @@
 ; O0-NEXT: fentry-insert
 ; O0-NEXT: xray-instrumentation
 ; O0-NEXT: patchable-function
+; O0-NEXT: x86-indirect-branch-tracking
 ; O0-NEXT: x86-compress-evex
 ; O0-NEXT: FuncletLayoutPass
 ; O0-NEXT: remove-loads-into-fake-uses
@@ -163,6 +164,7 @@
 ; O2-NEXT: xray-instrumentation
 ; O2-NEXT: patchable-function
 ; O2-NEXT: BreakFalseDepsPass
+; O2-NEXT: x86-indirect-branch-tracking
 ; O2-NEXT: x86-fixup-bw-insts
 ; O2-NEXT: x86-fixup-leas
 ; O2-NEXT: x86-fixup-inst-tuning
@@ -227,6 +229,7 @@
 ; O0-WINDOWS-NEXT: fentry-insert
 ; O0-WINDOWS-NEXT: xray-instrumentation
 ; O0-WINDOWS-NEXT: patchable-function
+; O0-WINDOWS-NEXT: x86-indirect-branch-tracking
 ; O0-WINDOWS-NEXT: x86-compress-evex
 ; O0-WINDOWS-NEXT: FuncletLayoutPass
 ; O0-WINDOWS-NEXT: remove-loads-into-fake-uses
@@ -339,6 +342,7 @@
 ; O3-WINDOWS-NEXT: xray-instrumentation
 ; O3-WINDOWS-NEXT: patchable-function
 ; O3-WINDOWS-NEXT: BreakFalseDepsPass
+; O3-WINDOWS-NEXT: x86-indirect-branch-tracking
 ; O3-WINDOWS-NEXT: x86-fixup-bw-insts
 ; O3-WINDOWS-NEXT: x86-fixup-leas
 ; O3-WINDOWS-NEXT: x86-fixup-inst-tuning

>From 10859aec2058cfa0b32910882f63fe23b4eb4ddc Mon Sep 17 00:00:00 2001
From: Kyungtak Woo <kevinwkt at google.com>
Date: Thu, 5 Feb 2026 08:01:40 +0000
Subject: [PATCH 2/3] get rid of unsed var

---
 llvm/lib/Target/X86/X86IndirectBranchTracking.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp b/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp
index 1c9de4693e1da..a45a6623760c5 100644
--- a/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp
+++ b/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp
@@ -112,7 +112,7 @@ static bool needsPrologueENDBR(MachineFunction &MF, const Module *M) {
 }
 
 static bool runIndirectBranchTracking(MachineFunction &MF) {
-  const X86Subtarget &SubTarget = MF.getSubtarget<X86Subtarget>();
+
 
   const Module *M = MF.getFunction().getParent();
   // Check that the cf-protection-branch is enabled.

>From 2b77c029a7946f50be641a2bcdd6b11f8802e115 Mon Sep 17 00:00:00 2001
From: Kyungtak Woo <kevinwkt at google.com>
Date: Thu, 5 Feb 2026 08:08:37 +0000
Subject: [PATCH 3/3] not sure why my clang format behaves different

---
 llvm/lib/Target/X86/X86IndirectBranchTracking.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp b/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp
index a45a6623760c5..6ccad26a890dd 100644
--- a/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp
+++ b/llvm/lib/Target/X86/X86IndirectBranchTracking.cpp
@@ -112,8 +112,6 @@ static bool needsPrologueENDBR(MachineFunction &MF, const Module *M) {
 }
 
 static bool runIndirectBranchTracking(MachineFunction &MF) {
-
-
   const Module *M = MF.getFunction().getParent();
   // Check that the cf-protection-branch is enabled.
   Metadata *isCFProtectionSupported = M->getModuleFlag("cf-protection-branch");



More information about the llvm-commits mailing list