summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
authorRobin Morisset <morisset@google.com>2014-09-17 17:41:16 +0000
committerRobin Morisset <morisset@google.com>2014-09-17 17:41:16 +0000
commit1c8a457575512644a45253c7ea6ce47f987e72ce (patch)
tree9ebd796fca4261eadadde0ac0699b156518cd8cc /llvm/lib/Target
parent02dc26529e653854bd97dfb946e48199d449bd98 (diff)
downloadbcm5719-llvm-1c8a457575512644a45253c7ea6ce47f987e72ce.tar.gz
bcm5719-llvm-1c8a457575512644a45253c7ea6ce47f987e72ce.zip
[ARM, Fix] Fix emitLeading/TrailingFence on old ARM processors
Summary: I had only tested this code for ARMv7 and ARMv8. This patch adds several fallback paths if the processor does not support dmb ish: - dmb sy if a cortex-M with support for dmb - mcr p15, #0, r0, c7, c10, #5 for ARMv6 (special instruction equivalent to a DMB) These fallback paths were chosen based on the code for fence seq_cst. Thanks to luqmana for having noticed this bug. Test Plan: Added more cases to atomic-load-store.ll + make check-all Reviewers: jfb, t.p.northover, luqmana Subscribers: aemerson, llvm-commits Differential Revision: http://reviews.llvm.org/D5304 llvm-svn: 217965
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/ARM/ARMISelLowering.cpp30
-rw-r--r--llvm/lib/Target/ARM/ARMISelLowering.h1
2 files changed, 27 insertions, 4 deletions
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 4195b3bf0a4..b41d1e3e97a 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -10984,11 +10984,33 @@ bool ARMTargetLowering::shouldConvertConstantLoadToIntImm(const APInt &Imm,
bool ARMTargetLowering::hasLoadLinkedStoreConditional() const { return true; }
-static void makeDMB(IRBuilder<> &Builder, ARM_MB::MemBOpt Domain) {
+Instruction* ARMTargetLowering::makeDMB(IRBuilder<> &Builder,
+ ARM_MB::MemBOpt Domain) const {
Module *M = Builder.GetInsertBlock()->getParent()->getParent();
- Function *DMB = llvm::Intrinsic::getDeclaration(M, Intrinsic::arm_dmb);
- Constant *CDomain = Builder.getInt32(Domain);
- Builder.CreateCall(DMB, CDomain);
+
+ // First, if the target has no DMB, see what fallback we can use.
+ if (!Subtarget->hasDataBarrier()) {
+ // Some ARMv6 cpus can support data barriers with an mcr instruction.
+ // Thumb1 and pre-v6 ARM mode use a libcall instead and should never get
+ // here.
+ if (Subtarget->hasV6Ops() && !Subtarget->isThumb()) {
+ Function *MCR = llvm::Intrinsic::getDeclaration(M, Intrinsic::arm_mcr);
+ ArrayRef<Value*> args = {Builder.getInt32(15), Builder.getInt32(0),
+ Builder.getInt32(0), Builder.getInt32(7),
+ Builder.getInt32(10), Builder.getInt32(5)};
+ return Builder.CreateCall(MCR, args);
+ } else {
+ // Instead of using barriers, atomic accesses on these subtargets use
+ // libcalls.
+ llvm_unreachable("makeDMB on a target so old that it has no barriers");
+ }
+ } else {
+ Function *DMB = llvm::Intrinsic::getDeclaration(M, Intrinsic::arm_dmb);
+ // Only a full system barrier exists in the M-class architectures.
+ Domain = Subtarget->isMClass() ? ARM_MB::SY : Domain;
+ Constant *CDomain = Builder.getInt32(Domain);
+ return Builder.CreateCall(DMB, CDomain);
+ }
}
// Based on http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.h b/llvm/lib/Target/ARM/ARMISelLowering.h
index aa268f16498..d5483553898 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.h
+++ b/llvm/lib/Target/ARM/ARMISelLowering.h
@@ -393,6 +393,7 @@ namespace llvm {
Type *Ty, CallingConv::ID CallConv, bool isVarArg) const override;
bool hasLoadLinkedStoreConditional() const override;
+ Instruction *makeDMB(IRBuilder<> &Builder, ARM_MB::MemBOpt Domain) const;
Value *emitLoadLinked(IRBuilder<> &Builder, Value *Addr,
AtomicOrdering Ord) const override;
Value *emitStoreConditional(IRBuilder<> &Builder, Value *Val,
OpenPOWER on IntegriCloud