Index: llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp =================================================================== --- llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp +++ llvm/trunk/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -5330,6 +5330,14 @@ MI.modifiesRegister(AArch64::W30, &getRegisterInfo())) return outliner::InstrType::Illegal; + // Don't outline BTI instructions, because that will prevent the outlining + // site from being indirectly callable. + if (MI.getOpcode() == AArch64::HINT) { + int64_t Imm = MI.getOperand(0).getImm(); + if (Imm == 32 || Imm == 34 || Imm == 36 || Imm == 38) + return outliner::InstrType::Illegal; + } + return outliner::InstrType::Legal; } Index: llvm/trunk/test/CodeGen/AArch64/machine-outliner-outline-bti.ll =================================================================== --- llvm/trunk/test/CodeGen/AArch64/machine-outliner-outline-bti.ll +++ llvm/trunk/test/CodeGen/AArch64/machine-outliner-outline-bti.ll @@ -0,0 +1,22 @@ +; RUN: llc -mtriple aarch64--none-eabi < %s | FileCheck %s + +; The BTI instruction cannot be outlined, because it needs to be the very first +; instruction executed after an indirect call. + +@g = hidden global i32 0, align 4 + +define hidden void @foo() minsize "branch-target-enforcement" { +entry: +; CHECK: hint #34 +; CHECK: b OUTLINED_FUNCTION_0 + store volatile i32 1, i32* @g, align 4 + ret void +} + +define hidden void @bar() minsize "branch-target-enforcement" { +entry: +; CHECK: hint #34 +; CHECK: b OUTLINED_FUNCTION_0 + store volatile i32 1, i32* @g, align 4 + ret void +}