Skip to content

Conversation

@bgergely0
Copy link
Contributor

@bgergely0 bgergely0 commented Nov 10, 2025

  • takes both implicit and explicit BTIs into account
  • fix related comment in
    llvm/lib/Target/AArch64/AArch64BranchTargets.cpp

Copy link
Contributor Author

bgergely0 commented Nov 10, 2025

@llvmbot
Copy link
Member

llvmbot commented Nov 19, 2025

@llvm/pr-subscribers-bolt

Author: Gergely Bálint (bgergely0)

Changes
  • takes both implicit and explicit BTIs into account
  • fix related comment in AArch64BranchTargets.cpp

Full diff: https://github.com/llvm/llvm-project/pull/167306.diff

4 Files Affected:

  • (modified) bolt/include/bolt/Core/MCPlusBuilder.h (+14)
  • (modified) bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp (+18)
  • (modified) bolt/unittests/Core/MCPlusBuilder.cpp (+17)
  • (modified) llvm/lib/Target/AArch64/AArch64BranchTargets.cpp (+4-2)
diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h
index 9cbff02619bd2..6760586876d94 100644
--- a/bolt/include/bolt/Core/MCPlusBuilder.h
+++ b/bolt/include/bolt/Core/MCPlusBuilder.h
@@ -1865,6 +1865,20 @@ class MCPlusBuilder {
     llvm_unreachable("not implemented");
   }
 
+  /// Check if an Instruction is a BTI landing pad with the required properties.
+  /// Takes both explicit and implicit BTIs into account.
+  virtual bool isBTILandingPad(MCInst &Inst, bool CouldCall,
+                               bool CouldJump) const {
+    llvm_unreachable("not implemented");
+    return false;
+  }
+
+  /// Check if an Instruction is an implicit BTI c landing pad.
+  virtual bool isImplicitBTIC(MCInst &Inst) const {
+    llvm_unreachable("not implemented");
+    return false;
+  }
+
   /// Create a BTI landing pad instruction.
   virtual void createBTI(MCInst &Inst, bool CouldCall, bool CouldJump) const {
     llvm_unreachable("not implemented");
diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
index 8cfde5701ee7f..0cf3db8a6fc2a 100644
--- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
+++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
@@ -2706,6 +2706,24 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
     return Insts;
   }
 
+  bool isBTILandingPad(MCInst &Inst, bool CouldCall,
+                       bool CouldJump) const override {
+    unsigned HintNum = getBTIHintNum(CouldCall, CouldJump);
+    bool IsExplicitBTI =
+        Inst.getOpcode() == AArch64::HINT && Inst.getNumOperands() == 1 &&
+        Inst.getOperand(0).isImm() && Inst.getOperand(0).getImm() == HintNum;
+
+    bool IsImplicitBTI = HintNum == 34 && isImplicitBTIC(Inst);
+    return IsExplicitBTI || IsImplicitBTI;
+  }
+
+  bool isImplicitBTIC(MCInst &Inst) const override {
+    // PACI[AB]SP are always implicitly BTI C, independently of
+    // SCTLR_EL1.BT[01].
+    return Inst.getOpcode() == AArch64::PACIASP ||
+           Inst.getOpcode() == AArch64::PACIBSP;
+  }
+
   void createBTI(MCInst &Inst, bool CouldCall, bool CouldJump) const override {
     Inst.setOpcode(AArch64::HINT);
     unsigned HintNum = getBTIHintNum(CouldCall, CouldJump);
diff --git a/bolt/unittests/Core/MCPlusBuilder.cpp b/bolt/unittests/Core/MCPlusBuilder.cpp
index 33389bca8b21e..439d72a343ce8 100644
--- a/bolt/unittests/Core/MCPlusBuilder.cpp
+++ b/bolt/unittests/Core/MCPlusBuilder.cpp
@@ -155,22 +155,39 @@ TEST_P(MCPlusBuilderTester, AArch64_BTI) {
   auto II = BB->begin();
   ASSERT_EQ(II->getOpcode(), AArch64::HINT);
   ASSERT_EQ(II->getOperand(0).getImm(), 38);
+  ASSERT_TRUE(BC->MIB->isBTILandingPad(*II, true, true));
 
   MCInst BTIj;
   BC->MIB->createBTI(BTIj, false, true);
   II = BB->addInstruction(BTIj);
   ASSERT_EQ(II->getOpcode(), AArch64::HINT);
   ASSERT_EQ(II->getOperand(0).getImm(), 36);
+  ASSERT_TRUE(BC->MIB->isBTILandingPad(*II, false, true));
 
   MCInst BTIc;
   BC->MIB->createBTI(BTIc, true, false);
   II = BB->addInstruction(BTIc);
   ASSERT_EQ(II->getOpcode(), AArch64::HINT);
   ASSERT_EQ(II->getOperand(0).getImm(), 34);
+  ASSERT_TRUE(BC->MIB->isBTILandingPad(*II, true, false));
 
   MCInst BTIinvalid;
   ASSERT_DEATH(BC->MIB->createBTI(BTIinvalid, false, false),
                "No target kinds!");
+
+  MCInst Paciasp = MCInstBuilder(AArch64::PACIASP);
+  II = BB->addInstruction(Paciasp);
+  ASSERT_TRUE(BC->MIB->isBTILandingPad(*II, true, false));
+  ASSERT_FALSE(BC->MIB->isBTILandingPad(*II, true, true));
+  ASSERT_FALSE(BC->MIB->isBTILandingPad(*II, false, true));
+  ASSERT_TRUE(BC->MIB->isImplicitBTIC(*II));
+
+  MCInst Pacibsp = MCInstBuilder(AArch64::PACIBSP);
+  II = BB->addInstruction(Pacibsp);
+  ASSERT_TRUE(BC->MIB->isBTILandingPad(*II, true, false));
+  ASSERT_FALSE(BC->MIB->isBTILandingPad(*II, true, true));
+  ASSERT_FALSE(BC->MIB->isBTILandingPad(*II, false, true));
+  ASSERT_TRUE(BC->MIB->isImplicitBTIC(*II));
 }
 
 TEST_P(MCPlusBuilderTester, AArch64_CmpJNE) {
diff --git a/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp b/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp
index b6f3e56c3a18f..ea7de840faf92 100644
--- a/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp
+++ b/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp
@@ -150,8 +150,10 @@ void AArch64BranchTargets::addBTI(MachineBasicBlock &MBB, bool CouldCall,
        ++MBBI)
     ;
 
-  // SCTLR_EL1.BT[01] is set to 0 by default which means
-  // PACI[AB]SP are implicitly BTI C so no BTI C instruction is needed there.
+  // PACI[AB]SP are compatible with BTI c, independently of SCTLR_EL1.BT[01].
+  // If SCTLR_EL1.BT[01] is set to 1, they are compatible with BTI jc, but we
+  // cannot rely on that it compile time. Therefore, we can only skip adding a
+  // BTI c for these.
   if (MBBI != MBB.end() && ((HintNum & BTIMask) == BTIC) &&
       (MBBI->getOpcode() == AArch64::PACIASP ||
        MBBI->getOpcode() == AArch64::PACIBSP))

@llvmbot
Copy link
Member

llvmbot commented Nov 19, 2025

@llvm/pr-subscribers-backend-aarch64

Author: Gergely Bálint (bgergely0)

Changes
  • takes both implicit and explicit BTIs into account
  • fix related comment in AArch64BranchTargets.cpp

Full diff: https://github.com/llvm/llvm-project/pull/167306.diff

4 Files Affected:

  • (modified) bolt/include/bolt/Core/MCPlusBuilder.h (+14)
  • (modified) bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp (+18)
  • (modified) bolt/unittests/Core/MCPlusBuilder.cpp (+17)
  • (modified) llvm/lib/Target/AArch64/AArch64BranchTargets.cpp (+4-2)
diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h
index 9cbff02619bd2..6760586876d94 100644
--- a/bolt/include/bolt/Core/MCPlusBuilder.h
+++ b/bolt/include/bolt/Core/MCPlusBuilder.h
@@ -1865,6 +1865,20 @@ class MCPlusBuilder {
     llvm_unreachable("not implemented");
   }
 
+  /// Check if an Instruction is a BTI landing pad with the required properties.
+  /// Takes both explicit and implicit BTIs into account.
+  virtual bool isBTILandingPad(MCInst &Inst, bool CouldCall,
+                               bool CouldJump) const {
+    llvm_unreachable("not implemented");
+    return false;
+  }
+
+  /// Check if an Instruction is an implicit BTI c landing pad.
+  virtual bool isImplicitBTIC(MCInst &Inst) const {
+    llvm_unreachable("not implemented");
+    return false;
+  }
+
   /// Create a BTI landing pad instruction.
   virtual void createBTI(MCInst &Inst, bool CouldCall, bool CouldJump) const {
     llvm_unreachable("not implemented");
diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
index 8cfde5701ee7f..0cf3db8a6fc2a 100644
--- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
+++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp
@@ -2706,6 +2706,24 @@ class AArch64MCPlusBuilder : public MCPlusBuilder {
     return Insts;
   }
 
+  bool isBTILandingPad(MCInst &Inst, bool CouldCall,
+                       bool CouldJump) const override {
+    unsigned HintNum = getBTIHintNum(CouldCall, CouldJump);
+    bool IsExplicitBTI =
+        Inst.getOpcode() == AArch64::HINT && Inst.getNumOperands() == 1 &&
+        Inst.getOperand(0).isImm() && Inst.getOperand(0).getImm() == HintNum;
+
+    bool IsImplicitBTI = HintNum == 34 && isImplicitBTIC(Inst);
+    return IsExplicitBTI || IsImplicitBTI;
+  }
+
+  bool isImplicitBTIC(MCInst &Inst) const override {
+    // PACI[AB]SP are always implicitly BTI C, independently of
+    // SCTLR_EL1.BT[01].
+    return Inst.getOpcode() == AArch64::PACIASP ||
+           Inst.getOpcode() == AArch64::PACIBSP;
+  }
+
   void createBTI(MCInst &Inst, bool CouldCall, bool CouldJump) const override {
     Inst.setOpcode(AArch64::HINT);
     unsigned HintNum = getBTIHintNum(CouldCall, CouldJump);
diff --git a/bolt/unittests/Core/MCPlusBuilder.cpp b/bolt/unittests/Core/MCPlusBuilder.cpp
index 33389bca8b21e..439d72a343ce8 100644
--- a/bolt/unittests/Core/MCPlusBuilder.cpp
+++ b/bolt/unittests/Core/MCPlusBuilder.cpp
@@ -155,22 +155,39 @@ TEST_P(MCPlusBuilderTester, AArch64_BTI) {
   auto II = BB->begin();
   ASSERT_EQ(II->getOpcode(), AArch64::HINT);
   ASSERT_EQ(II->getOperand(0).getImm(), 38);
+  ASSERT_TRUE(BC->MIB->isBTILandingPad(*II, true, true));
 
   MCInst BTIj;
   BC->MIB->createBTI(BTIj, false, true);
   II = BB->addInstruction(BTIj);
   ASSERT_EQ(II->getOpcode(), AArch64::HINT);
   ASSERT_EQ(II->getOperand(0).getImm(), 36);
+  ASSERT_TRUE(BC->MIB->isBTILandingPad(*II, false, true));
 
   MCInst BTIc;
   BC->MIB->createBTI(BTIc, true, false);
   II = BB->addInstruction(BTIc);
   ASSERT_EQ(II->getOpcode(), AArch64::HINT);
   ASSERT_EQ(II->getOperand(0).getImm(), 34);
+  ASSERT_TRUE(BC->MIB->isBTILandingPad(*II, true, false));
 
   MCInst BTIinvalid;
   ASSERT_DEATH(BC->MIB->createBTI(BTIinvalid, false, false),
                "No target kinds!");
+
+  MCInst Paciasp = MCInstBuilder(AArch64::PACIASP);
+  II = BB->addInstruction(Paciasp);
+  ASSERT_TRUE(BC->MIB->isBTILandingPad(*II, true, false));
+  ASSERT_FALSE(BC->MIB->isBTILandingPad(*II, true, true));
+  ASSERT_FALSE(BC->MIB->isBTILandingPad(*II, false, true));
+  ASSERT_TRUE(BC->MIB->isImplicitBTIC(*II));
+
+  MCInst Pacibsp = MCInstBuilder(AArch64::PACIBSP);
+  II = BB->addInstruction(Pacibsp);
+  ASSERT_TRUE(BC->MIB->isBTILandingPad(*II, true, false));
+  ASSERT_FALSE(BC->MIB->isBTILandingPad(*II, true, true));
+  ASSERT_FALSE(BC->MIB->isBTILandingPad(*II, false, true));
+  ASSERT_TRUE(BC->MIB->isImplicitBTIC(*II));
 }
 
 TEST_P(MCPlusBuilderTester, AArch64_CmpJNE) {
diff --git a/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp b/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp
index b6f3e56c3a18f..ea7de840faf92 100644
--- a/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp
+++ b/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp
@@ -150,8 +150,10 @@ void AArch64BranchTargets::addBTI(MachineBasicBlock &MBB, bool CouldCall,
        ++MBBI)
     ;
 
-  // SCTLR_EL1.BT[01] is set to 0 by default which means
-  // PACI[AB]SP are implicitly BTI C so no BTI C instruction is needed there.
+  // PACI[AB]SP are compatible with BTI c, independently of SCTLR_EL1.BT[01].
+  // If SCTLR_EL1.BT[01] is set to 1, they are compatible with BTI jc, but we
+  // cannot rely on that it compile time. Therefore, we can only skip adding a
+  // BTI c for these.
   if (MBBI != MBB.end() && ((HintNum & BTIMask) == BTIC) &&
       (MBBI->getOpcode() == AArch64::PACIASP ||
        MBBI->getOpcode() == AArch64::PACIBSP))

@bgergely0 bgergely0 force-pushed the users/bgergely0/bolt-is-bti-landing-pad branch from f1cc15e to ebaccb2 Compare November 20, 2025 11:58
@bgergely0 bgergely0 force-pushed the users/bgergely0/bolt-createbti branch from 5cbe1e3 to f26be06 Compare November 20, 2025 11:58
@bgergely0 bgergely0 force-pushed the users/bgergely0/bolt-is-bti-landing-pad branch 2 times, most recently from d054c47 to ee348f3 Compare November 24, 2025 09:21
@bgergely0 bgergely0 force-pushed the users/bgergely0/bolt-createbti branch from c508aac to 9d76fb3 Compare November 24, 2025 09:21
@github-actions
Copy link

github-actions bot commented Nov 24, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@bgergely0 bgergely0 force-pushed the users/bgergely0/bolt-is-bti-landing-pad branch from ee348f3 to 90d940e Compare November 24, 2025 09:46
Base automatically changed from users/bgergely0/bolt-createbti to main November 25, 2025 08:51
- takes both implicit and explicit BTIs into account
- fix related comment in AArch64BranchTargets.cpp
@bgergely0 bgergely0 force-pushed the users/bgergely0/bolt-is-bti-landing-pad branch from 90d940e to f4f312b Compare November 25, 2025 08:53
@bgergely0 bgergely0 merged commit 4533699 into main Nov 25, 2025
10 checks passed
@bgergely0 bgergely0 deleted the users/bgergely0/bolt-is-bti-landing-pad branch November 25, 2025 17:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants