blob: 9f7ae5c24123346b55aa3e541d8832ce75ca440f [file] [log] [blame]
From 16fa8b09702378bacfa3d07081afe6b353b99e60 Mon Sep 17 00:00:00 2001
From: Jian Cai <caij2003@gmail.com>
Date: Fri, 16 Aug 2019 23:30:16 +0000
Subject: [PATCH] Reland "[ARM] push LR before __gnu_mcount_nc"
This relands r369147 with fixes to unit tests.
https://reviews.llvm.org/D65019
llvm-svn: 369173
---
clang/lib/Basic/Targets/ARM.cpp | 2 +-
clang/test/Frontend/gnu-mcount.c | 2 +-
llvm/include/llvm/IR/IntrinsicsARM.td | 5 +++
llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp | 31 +++++++++++++
llvm/lib/Target/ARM/ARMISelLowering.cpp | 44 +++++++++++++++++++
llvm/lib/Target/ARM/ARMISelLowering.h | 2 +
llvm/lib/Target/ARM/ARMInstrInfo.td | 6 +++
llvm/lib/Target/ARM/ARMInstrThumb.td | 7 +++
.../Utils/EntryExitInstrumenter.cpp | 2 +-
llvm/test/CodeGen/ARM/gnu_mcount_nc.ll | 41 +++++++++++++++++
.../EntryExitInstrumenter/mcount.ll | 4 +-
11 files changed, 141 insertions(+), 5 deletions(-)
create mode 100644 llvm/test/CodeGen/ARM/gnu_mcount_nc.ll
diff --git a/clang/lib/Basic/Targets/ARM.cpp b/clang/lib/Basic/Targets/ARM.cpp
index 3ae2091f4a0..b234f013485 100644
--- a/clang/lib/Basic/Targets/ARM.cpp
+++ b/clang/lib/Basic/Targets/ARM.cpp
@@ -322,7 +322,7 @@ ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
if (Triple.getOS() == llvm::Triple::Linux ||
Triple.getOS() == llvm::Triple::UnknownOS)
this->MCountName = Opts.EABIVersion == llvm::EABI::GNU
- ? "\01__gnu_mcount_nc"
+ ? "llvm.arm.gnu.eabi.mcount"
: "\01mcount";
SoftFloatABI = llvm::is_contained(Opts.FeaturesAsWritten, "+soft-float-abi");
diff --git a/clang/test/Frontend/gnu-mcount.c b/clang/test/Frontend/gnu-mcount.c
index baac555d139..6e89dfefb75 100644
--- a/clang/test/Frontend/gnu-mcount.c
+++ b/clang/test/Frontend/gnu-mcount.c
@@ -66,7 +66,7 @@ int f() {
// CHECK-ARM64-EABI-OPENBSD: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="__mcount"{{.*}} }
// CHECK-ARM64-EABI-OPENBSD-NOT: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="\01__gnu_mcount_nc"{{.*}} }
// CHECK-ARM-EABI-MEABI-GNU-NOT: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="mcount"{{.*}} }
-// CHECK-ARM-EABI-MEABI-GNU: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="\01__gnu_mcount_nc"{{.*}} }
+// CHECK-ARM-EABI-MEABI-GNU: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="llvm.arm.gnu.eabi.mcount"{{.*}} }
// CHECK-ARM-EABI-RTEMS: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="mcount"{{.*}} }
// CHECK-ARM-EABI-RTEMS-NOT: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="\01__gnu_mcount_nc"{{.*}} }
// CHECK-ARM64-EABI-RTEMS: attributes #{{[0-9]+}} = { {{.*}}"instrument-function-entry-inlined"="mcount"{{.*}} }
diff --git a/llvm/include/llvm/IR/IntrinsicsARM.td b/llvm/include/llvm/IR/IntrinsicsARM.td
index 4792af097d9..4da29ee600f 100644
--- a/llvm/include/llvm/IR/IntrinsicsARM.td
+++ b/llvm/include/llvm/IR/IntrinsicsARM.td
@@ -778,4 +778,9 @@ def int_arm_neon_udot : Neon_Dot_Intrinsic;
def int_arm_neon_sdot : Neon_Dot_Intrinsic;
+// GNU eabi mcount
+def int_arm_gnu_eabi_mcount : Intrinsic<[],
+ [],
+ [IntrReadMem, IntrWriteMem]>;
+
} // end TargetPrefix
diff --git a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp
index bd4ca3828fc..73ebe0940f3 100644
--- a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp
@@ -1916,6 +1916,37 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB,
case ARM::CMP_SWAP_64:
return ExpandCMP_SWAP_64(MBB, MBBI, NextMBBI);
+
+ case ARM::tBL_PUSHLR:
+ case ARM::BL_PUSHLR: {
+ const bool Thumb = Opcode == ARM::tBL_PUSHLR;
+ Register Reg = MI.getOperand(0).getReg();
+ assert(Reg == ARM::LR && "expect LR register!");
+ MachineInstrBuilder MIB;
+ if (Thumb) {
+ // push {lr}
+ BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::tPUSH))
+ .add(predOps(ARMCC::AL))
+ .addReg(Reg);
+
+ // bl __gnu_mcount_nc
+ MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::tBL));
+ } else {
+ // stmdb sp!, {lr}
+ BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::STMDB_UPD))
+ .addReg(ARM::SP, RegState::Define)
+ .addReg(ARM::SP)
+ .add(predOps(ARMCC::AL))
+ .addReg(Reg);
+
+ // bl __gnu_mcount_nc
+ MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::BL));
+ }
+ MIB.cloneMemRefs(MI);
+ for (unsigned i = 1; i < MI.getNumOperands(); ++i) MIB.add(MI.getOperand(i));
+ MI.eraseFromParent();
+ return true;
+ }
}
}
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 9bf44580192..63b8f2acd3a 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -1017,6 +1017,7 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom);
setOperationAction(ISD::SRL, MVT::i64, Custom);
setOperationAction(ISD::SRA, MVT::i64, Custom);
+ setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom);
setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i64, Custom);
// MVE lowers 64 bit shifts to lsll and lsrl
@@ -3544,6 +3545,48 @@ SDValue ARMTargetLowering::LowerEH_SJLJ_SETUP_DISPATCH(SDValue Op,
Op.getOperand(0));
}
+SDValue ARMTargetLowering::LowerINTRINSIC_VOID(
+ SDValue Op, SelectionDAG &DAG, const ARMSubtarget *Subtarget) const {
+ unsigned IntNo =
+ cast<ConstantSDNode>(
+ Op.getOperand(Op.getOperand(0).getValueType() == MVT::Other))
+ ->getZExtValue();
+ switch (IntNo) {
+ default:
+ return SDValue(); // Don't custom lower most intrinsics.
+ case Intrinsic::arm_gnu_eabi_mcount: {
+ MachineFunction &MF = DAG.getMachineFunction();
+ EVT PtrVT = getPointerTy(DAG.getDataLayout());
+ SDLoc dl(Op);
+ SDValue Chain = Op.getOperand(0);
+ // call "\01__gnu_mcount_nc"
+ const ARMBaseRegisterInfo *ARI = Subtarget->getRegisterInfo();
+ const uint32_t *Mask =
+ ARI->getCallPreservedMask(DAG.getMachineFunction(), CallingConv::C);
+ assert(Mask && "Missing call preserved mask for calling convention");
+ // Mark LR an implicit live-in.
+ unsigned Reg = MF.addLiveIn(ARM::LR, getRegClassFor(MVT::i32));
+ SDValue ReturnAddress =
+ DAG.getCopyFromReg(DAG.getEntryNode(), dl, Reg, PtrVT);
+ std::vector<EVT> ResultTys = {MVT::Other, MVT::Glue};
+ SDValue Callee =
+ DAG.getTargetExternalSymbol("\01__gnu_mcount_nc", PtrVT, 0);
+ SDValue RegisterMask = DAG.getRegisterMask(Mask);
+ if (Subtarget->isThumb())
+ return SDValue(
+ DAG.getMachineNode(
+ ARM::tBL_PUSHLR, dl, ResultTys,
+ {ReturnAddress, DAG.getTargetConstant(ARMCC::AL, dl, PtrVT),
+ DAG.getRegister(0, PtrVT), Callee, RegisterMask, Chain}),
+ 0);
+ return SDValue(
+ DAG.getMachineNode(ARM::BL_PUSHLR, dl, ResultTys,
+ {ReturnAddress, Callee, RegisterMask, Chain}),
+ 0);
+ }
+ }
+}
+
SDValue
ARMTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG,
const ARMSubtarget *Subtarget) const {
@@ -8835,6 +8878,7 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::EH_SJLJ_SETJMP: return LowerEH_SJLJ_SETJMP(Op, DAG);
case ISD::EH_SJLJ_LONGJMP: return LowerEH_SJLJ_LONGJMP(Op, DAG);
case ISD::EH_SJLJ_SETUP_DISPATCH: return LowerEH_SJLJ_SETUP_DISPATCH(Op, DAG);
+ case ISD::INTRINSIC_VOID: return LowerINTRINSIC_VOID(Op, DAG, Subtarget);
case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG,
Subtarget);
case ISD::BITCAST: return ExpandBITCAST(Op.getNode(), DAG, Subtarget);
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.h b/llvm/lib/Target/ARM/ARMISelLowering.h
index 15dcd9d8db2..d84a235b8b2 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.h
+++ b/llvm/lib/Target/ARM/ARMISelLowering.h
@@ -667,6 +667,8 @@ class VectorType;
SDValue LowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerEH_SJLJ_SETUP_DISPATCH(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG,
+ const ARMSubtarget *Subtarget) const;
SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG,
const ARMSubtarget *Subtarget) const;
SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td
index 7783bedc210..ac1be46447f 100644
--- a/llvm/lib/Target/ARM/ARMInstrInfo.td
+++ b/llvm/lib/Target/ARM/ARMInstrInfo.td
@@ -2370,6 +2370,12 @@ let isCall = 1,
def BMOVPCB_CALL : ARMPseudoInst<(outs), (ins arm_bl_target:$func),
8, IIC_Br, [(ARMcall_nolink tglobaladdr:$func)]>,
Requires<[IsARM]>, Sched<[WriteBr]>;
+
+ // push lr before the call
+ def BL_PUSHLR : ARMPseudoInst<(outs), (ins GPRlr:$ra, arm_bl_target:$func),
+ 4, IIC_Br,
+ []>,
+ Requires<[IsARM]>, Sched<[WriteBr]>;
}
let isBranch = 1, isTerminator = 1 in {
diff --git a/llvm/lib/Target/ARM/ARMInstrThumb.td b/llvm/lib/Target/ARM/ARMInstrThumb.td
index ef2814be2ce..18bcbda4458 100644
--- a/llvm/lib/Target/ARM/ARMInstrThumb.td
+++ b/llvm/lib/Target/ARM/ARMInstrThumb.td
@@ -565,6 +565,13 @@ let isCall = 1,
4, IIC_Br,
[(ARMcall_nolink tGPR:$func)]>,
Requires<[IsThumb, IsThumb1Only]>, Sched<[WriteBr]>;
+
+ // Also used for Thumb2
+ // push lr before the call
+ def tBL_PUSHLR : tPseudoInst<(outs), (ins GPRlr:$ra, pred:$p, thumb_bl_target:$func),
+ 4, IIC_Br,
+ []>,
+ Requires<[IsThumb]>, Sched<[WriteBr]>;
}
let isBranch = 1, isTerminator = 1, isBarrier = 1 in {
diff --git a/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp b/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp
index 4aa40eeadda..57e2ff0251a 100644
--- a/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp
+++ b/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp
@@ -24,7 +24,7 @@ static void insertCall(Function &CurFn, StringRef Func,
if (Func == "mcount" ||
Func == ".mcount" ||
- Func == "\01__gnu_mcount_nc" ||
+ Func == "llvm.arm.gnu.eabi.mcount" ||
Func == "\01_mcount" ||
Func == "\01mcount" ||
Func == "__mcount" ||
diff --git a/llvm/test/CodeGen/ARM/gnu_mcount_nc.ll b/llvm/test/CodeGen/ARM/gnu_mcount_nc.ll
new file mode 100644
index 00000000000..c36991f879a
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/gnu_mcount_nc.ll
@@ -0,0 +1,41 @@
+; RUN: llc -mtriple=armv7a-linux-gnueabihf -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK-ARM
+; RUN: llc -mtriple=armv7a-linux-gnueabihf -verify-machineinstrs -fast-isel %s -o - | FileCheck %s --check-prefix=CHECK-ARM-FAST-ISEL
+; RUN: llc -mtriple=armv7a-linux-gnueabihf -verify-machineinstrs -global-isel -global-isel-abort=2 %s -o - | FileCheck %s --check-prefix=CHECK-ARM-GLOBAL-ISEL
+; RUN: llc -mtriple=thumbv7a-linux-gnueabihf -verify-machineinstrs %s -o - | FileCheck %s --check-prefix=CHECK-THUMB
+; RUN: llc -mtriple=thumbv7a-linux-gnueabihf -verify-machineinstrs -fast-isel %s -o - | FileCheck %s --check-prefix=CHECK-THUMB-FAST-ISEL
+; RUN: llc -mtriple=thumbv7a-linux-gnueabihf -verify-machineinstrs -global-isel -global-isel-abort=2 %s -o - | FileCheck %s --check-prefix=CHECK-THUMB-GLOBAL-ISEL
+
+define dso_local void @callee() #0 {
+; CHECK-ARM: stmdb sp!, {lr}
+; CHECK-ARM-NEXT: bl __gnu_mcount_nc
+; CHECK-ARM-FAST-ISEL: stmdb sp!, {lr}
+; CHECK-ARM-FAST-ISEL-NEXT: bl __gnu_mcount_nc
+; CHECK-ARM-GLOBAL-ISEL: stmdb sp!, {lr}
+; CHECK-ARM-GLOBAL-ISEL-NEXT: bl __gnu_mcount_nc
+; CHECK-THUMB: push {lr}
+; CHECK-THUMB-NEXT: bl __gnu_mcount_nc
+; CHECK-THUMB-FAST-ISEL: push {lr}
+; CHECK-THUMB-FAST-ISEL-NEXT: bl __gnu_mcount_nc
+; CHECK-THUMB-GLOBAL-ISEL: push {lr}
+; CHECK-THUMB-GLOBAL-ISEL-NEXT: bl __gnu_mcount_nc
+ ret void
+}
+
+define dso_local void @caller() #0 {
+; CHECK-ARM: stmdb sp!, {lr}
+; CHECK-ARM-NEXT: bl __gnu_mcount_nc
+; CHECK-ARM-FAST-ISEL: stmdb sp!, {lr}
+; CHECK-ARM-FAST-ISEL-NEXT: bl __gnu_mcount_nc
+; CHECK-ARM-GLOBAL-ISEL: stmdb sp!, {lr}
+; CHECK-ARM-GLOBAL-ISEL-NEXT: bl __gnu_mcount_nc
+; CHECK-THUMB: push {lr}
+; CHECK-THUMB-NEXT: bl __gnu_mcount_nc
+; CHECK-THUMB-FAST-ISEL: push {lr}
+; CHECK-THUMB-FAST-ISEL-NEXT: bl __gnu_mcount_nc
+; CHECK-THUMB-GLOBAL-ISEL: push {lr}
+; CHECK-THUMB-GLOBAL-ISEL-NEXT: bl __gnu_mcount_nc
+ call void @callee()
+ ret void
+}
+
+attributes #0 = { nofree nounwind "instrument-function-entry-inlined"="llvm.arm.gnu.eabi.mcount" }
diff --git a/llvm/test/Transforms/EntryExitInstrumenter/mcount.ll b/llvm/test/Transforms/EntryExitInstrumenter/mcount.ll
index 30483606caf..56c8b53aa45 100644
--- a/llvm/test/Transforms/EntryExitInstrumenter/mcount.ll
+++ b/llvm/test/Transforms/EntryExitInstrumenter/mcount.ll
@@ -54,7 +54,7 @@ define void @f1() #1 { entry: ret void }
define void @f2() #2 { entry: ret void }
; CHECK-LABEL: define void @f2
-; CHECK: call void @"\01__gnu_mcount_nc"
+; CHECK: call void @llvm.arm.gnu.eabi.mcount
define void @f3() #3 { entry: ret void }
; CHECK-LABEL: define void @f3
@@ -105,7 +105,7 @@ define i8* @tailcaller2() #8 {
attributes #0 = { "instrument-function-entry-inlined"="mcount" "instrument-function-entry"="__cyg_profile_func_enter" "instrument-function-exit"="__cyg_profile_func_exit" }
attributes #1 = { "instrument-function-entry-inlined"=".mcount" }
-attributes #2 = { "instrument-function-entry-inlined"="\01__gnu_mcount_nc" }
+attributes #2 = { "instrument-function-entry-inlined"="llvm.arm.gnu.eabi.mcount" }
attributes #3 = { "instrument-function-entry-inlined"="\01_mcount" }
attributes #4 = { "instrument-function-entry-inlined"="\01mcount" }
attributes #5 = { "instrument-function-entry-inlined"="__mcount" }
--
2.23.0.rc1.153.gdeed80330f-goog