From f4f312b7da08e4859b5107a0698578c9b32ab98e Mon Sep 17 00:00:00 2001 From: Gergely Balint Date: Thu, 28 Aug 2025 12:32:37 +0000 Subject: [PATCH 1/2] [BOLT][BTI] Add MCPlusBuilder::isBTILandingPad - takes both implicit and explicit BTIs into account - fix related comment in AArch64BranchTargets.cpp --- bolt/include/bolt/Core/MCPlusBuilder.h | 14 ++++++++++++++ .../Target/AArch64/AArch64MCPlusBuilder.cpp | 18 ++++++++++++++++++ bolt/unittests/Core/MCPlusBuilder.cpp | 17 +++++++++++++++++ .../Target/AArch64/AArch64BranchTargets.cpp | 6 ++++-- 4 files changed, 53 insertions(+), 2 deletions(-) diff --git a/bolt/include/bolt/Core/MCPlusBuilder.h b/bolt/include/bolt/Core/MCPlusBuilder.h index f8a88e764307f..fe7905c33080f 100644 --- a/bolt/include/bolt/Core/MCPlusBuilder.h +++ b/bolt/include/bolt/Core/MCPlusBuilder.h @@ -1869,6 +1869,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 CallTarget, + bool JumpTarget) 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 CallTarget, bool JumpTarget) const { llvm_unreachable("not implemented"); diff --git a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp index 9bc3445ee2ca6..f1291f676f1b5 100644 --- a/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp +++ b/bolt/lib/Target/AArch64/AArch64MCPlusBuilder.cpp @@ -2782,6 +2782,24 @@ class AArch64MCPlusBuilder : public MCPlusBuilder { Inst.addOperand(MCOperand::createImm(HintNum)); } + bool isBTILandingPad(MCInst &Inst, bool CallTarget, + bool JumpTarget) const override { + unsigned HintNum = getBTIHintNum(CallTarget, JumpTarget); + 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; + } + InstructionListType materializeAddress(const MCSymbol *Target, MCContext *Ctx, MCPhysReg RegName, int64_t Addend = 0) const override { 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)) From 6ee53c808f86e33c8c4b36b4da2a6b7b090eb3d8 Mon Sep 17 00:00:00 2001 From: Gergely Balint Date: Tue, 25 Nov 2025 15:23:49 +0000 Subject: [PATCH 2/2] Fix comment --- llvm/lib/Target/AArch64/AArch64BranchTargets.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp b/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp index ea7de840faf92..57934ae2da1cd 100644 --- a/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp +++ b/llvm/lib/Target/AArch64/AArch64BranchTargets.cpp @@ -150,10 +150,9 @@ void AArch64BranchTargets::addBTI(MachineBasicBlock &MBB, bool CouldCall, ++MBBI) ; - // 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. + // PACI[AB]SP are implicitly BTI c so insertion of a BTI can be skipped in + // this case. Depending on the runtime value of SCTLR_EL1.BT[01], they are not + // equivalent to a BTI jc, which still requires an additional BTI. if (MBBI != MBB.end() && ((HintNum & BTIMask) == BTIC) && (MBBI->getOpcode() == AArch64::PACIASP || MBBI->getOpcode() == AArch64::PACIBSP))