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))