diff --git a/llvm/lib/Target/ARM/ARM.h b/llvm/lib/Target/ARM/ARM.h --- a/llvm/lib/Target/ARM/ARM.h +++ b/llvm/lib/Target/ARM/ARM.h @@ -50,6 +50,7 @@ FunctionPass *createARMOptimizeBarriersPass(); FunctionPass *createThumb2SizeReductionPass( std::function Ftor = nullptr); +FunctionPass *createMcountLoweringPass(); InstructionSelector * createARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget &STI, const ARMRegisterBankInfo &RBI); diff --git a/llvm/lib/Target/ARM/ARMTargetMachine.cpp b/llvm/lib/Target/ARM/ARMTargetMachine.cpp --- a/llvm/lib/Target/ARM/ARMTargetMachine.cpp +++ b/llvm/lib/Target/ARM/ARMTargetMachine.cpp @@ -518,6 +518,7 @@ } void ARMPassConfig::addPreEmitPass() { + addPass(createMcountLoweringPass()); addPass(createThumb2SizeReductionPass()); // Constant island pass work on unbundled instructions. diff --git a/llvm/lib/Target/ARM/CMakeLists.txt b/llvm/lib/Target/ARM/CMakeLists.txt --- a/llvm/lib/Target/ARM/CMakeLists.txt +++ b/llvm/lib/Target/ARM/CMakeLists.txt @@ -51,6 +51,7 @@ ARMTargetMachine.cpp ARMTargetObjectFile.cpp ARMTargetTransformInfo.cpp + CustomCallLoweringPass.cpp MLxExpansionPass.cpp Thumb1FrameLowering.cpp Thumb1InstrInfo.cpp diff --git a/llvm/lib/Target/ARM/CustomCallLoweringPass.cpp b/llvm/lib/Target/ARM/CustomCallLoweringPass.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Target/ARM/CustomCallLoweringPass.cpp @@ -0,0 +1,60 @@ +#include "ARM.h" +#include "ARMBaseInstrInfo.h" +#include "ARMSubtarget.h" +#include "llvm/Pass.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Support/raw_ostream.h" + +#define DEBUG_TYPE "arm-custom-call-lowering" + +using namespace llvm; + +namespace { +class McountLoweringPass : public MachineFunctionPass { + public: + static char ID; + + McountLoweringPass() : MachineFunctionPass(ID) {} + + virtual bool runOnMachineFunction(MachineFunction &MF) { + + + LLVM_DEBUG(dbgs() << MF.getName() << "\n"); + for (MachineFunction::iterator FI = MF.begin(), FE = MF.end(); FI != FE; ++FI) { + for (MachineBasicBlock::iterator BBI = FI->begin(), BBE = FI->end(); BBI != BBE; ++BBI) { + if (BBI->isCall()) { + LLVM_DEBUG(dbgs() << *BBI << "\n"); + for (MachineInstr::const_mop_iterator II = BBI->operands_begin(), IE = BBI->operands_end(); II != IE; ++II ) + if (II->isGlobal() && II->getGlobal()->getName() == "\01__gnu_mcount_nc") { + const ARMSubtarget &ST = MF.getSubtarget(); + const ARMBaseInstrInfo &TII = *ST.getInstrInfo(); + DebugLoc DL; + if (ST.isThumb()) { + BuildMI(*FI, BBI, DL, TII.get(ARM::tPUSH)) + .add(predOps(ARMCC::AL)) + .addReg(ARM::LR); + } else { + BuildMI(*FI, BBI, DL, TII.get(ARM::STMDB_UPD)) + .addReg(ARM::SP, RegState::Define) + .addReg(ARM::SP) + .add(predOps(ARMCC::AL)) + .addReg(ARM::LR); + } + return true; + } + } + } + } + return false; + } +}; +} + +FunctionPass *llvm::createMcountLoweringPass() { + return new McountLoweringPass(); +} + +char McountLoweringPass::ID = 0; +static RegisterPass X ("arm-mcount-lowering", "ARM mcount Call Lowering Pass"); diff --git a/llvm/test/CodeGen/ARM/mcount.ll b/llvm/test/CodeGen/ARM/mcount.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/ARM/mcount.ll @@ -0,0 +1,14 @@ +; RUN: llc -mtriple=armv7a-linux-gnueabihf %s -o - | FileCheck %s --check-prefix=CHECK-ARM +; RUN: llc -mtriple=thumbv7a-linux-gnueabihf %s -o - | FileCheck %s --check-prefix=CHECK-THUMB + +define dso_local i32 @foo(i64) local_unnamed_addr #0 { +; CHECK-ARM: stmdb sp!, {lr} +; CHECK-ARM-NEXT: bl __gnu_mcount_nc +; CHECK-THUMB: push {lr} +; CHECK-THUMB-NEXT: bl __gnu_mcount_nc + %2 = mul nsw i64 %0, %0 + %3 = trunc i64 %2 to i32 + ret i32 %3 +} + +attributes #0 = { nofree nounwind "instrument-function-entry-inlined"="\01__gnu_mcount_nc" }