summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
authorIgor Laevsky <igmyrj@gmail.com>2016-12-29 14:31:07 +0000
committerIgor Laevsky <igmyrj@gmail.com>2016-12-29 14:31:07 +0000
commit4f31e52f9456a78d579506736cd6620d3370fcd8 (patch)
tree7ff965b4319d7d2322df6adfd72fbc7777930eb1 /llvm/lib/CodeGen
parent17b5568bc7b7cd79dc80a8e359cf39e3a8e5a31a (diff)
downloadbcm5719-llvm-4f31e52f9456a78d579506736cd6620d3370fcd8.tar.gz
bcm5719-llvm-4f31e52f9456a78d579506736cd6620d3370fcd8.zip
Introduce element-wise atomic memcpy intrinsic
This change adds a new intrinsic which is intended to provide memcpy functionality with additional atomicity guarantees. Please refer to the review thread or language reference for further details. Differential Revision: https://reviews.llvm.org/D27133 llvm-svn: 290708
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp45
-rw-r--r--llvm/lib/CodeGen/TargetLoweringBase.cpp23
2 files changed, 68 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index da68fe87a32..cb803585282 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -4896,6 +4896,51 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
updateDAGForMaybeTailCall(MM);
return nullptr;
}
+ case Intrinsic::memcpy_element_atomic: {
+ SDValue Dst = getValue(I.getArgOperand(0));
+ SDValue Src = getValue(I.getArgOperand(1));
+ SDValue NumElements = getValue(I.getArgOperand(2));
+ SDValue ElementSize = getValue(I.getArgOperand(3));
+
+ // Emit a library call.
+ TargetLowering::ArgListTy Args;
+ TargetLowering::ArgListEntry Entry;
+ Entry.Ty = DAG.getDataLayout().getIntPtrType(*DAG.getContext());
+ Entry.Node = Dst;
+ Args.push_back(Entry);
+
+ Entry.Node = Src;
+ Args.push_back(Entry);
+
+ Entry.Ty = I.getArgOperand(2)->getType();
+ Entry.Node = NumElements;
+ Args.push_back(Entry);
+
+ Entry.Ty = Type::getInt32Ty(*DAG.getContext());
+ Entry.Node = ElementSize;
+ Args.push_back(Entry);
+
+ uint64_t ElementSizeConstant =
+ cast<ConstantInt>(I.getArgOperand(3))->getZExtValue();
+ RTLIB::Libcall LibraryCall =
+ RTLIB::getMEMCPY_ELEMENT_ATOMIC(ElementSizeConstant);
+ if (LibraryCall == RTLIB::UNKNOWN_LIBCALL)
+ report_fatal_error("Unsupported element size");
+
+ TargetLowering::CallLoweringInfo CLI(DAG);
+ CLI.setDebugLoc(sdl)
+ .setChain(getRoot())
+ .setCallee(TLI.getLibcallCallingConv(LibraryCall),
+ Type::getVoidTy(*DAG.getContext()),
+ DAG.getExternalSymbol(
+ TLI.getLibcallName(LibraryCall),
+ TLI.getPointerTy(DAG.getDataLayout())),
+ std::move(Args));
+
+ std::pair<SDValue, SDValue> CallResult = TLI.LowerCallTo(CLI);
+ DAG.setRoot(CallResult.second);
+ return nullptr;
+ }
case Intrinsic::dbg_declare: {
const DbgDeclareInst &DI = cast<DbgDeclareInst>(I);
DILocalVariable *Variable = DI.getVariable();
diff --git a/llvm/lib/CodeGen/TargetLoweringBase.cpp b/llvm/lib/CodeGen/TargetLoweringBase.cpp
index afa3fa98ad8..003311b157f 100644
--- a/llvm/lib/CodeGen/TargetLoweringBase.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringBase.cpp
@@ -361,6 +361,11 @@ static void InitLibcallNames(const char **Names, const Triple &TT) {
Names[RTLIB::MEMCPY] = "memcpy";
Names[RTLIB::MEMMOVE] = "memmove";
Names[RTLIB::MEMSET] = "memset";
+ Names[RTLIB::MEMCPY_ELEMENT_ATOMIC_1] = "__llvm_memcpy_element_atomic_1";
+ Names[RTLIB::MEMCPY_ELEMENT_ATOMIC_2] = "__llvm_memcpy_element_atomic_2";
+ Names[RTLIB::MEMCPY_ELEMENT_ATOMIC_4] = "__llvm_memcpy_element_atomic_4";
+ Names[RTLIB::MEMCPY_ELEMENT_ATOMIC_8] = "__llvm_memcpy_element_atomic_8";
+ Names[RTLIB::MEMCPY_ELEMENT_ATOMIC_16] = "__llvm_memcpy_element_atomic_16";
Names[RTLIB::UNWIND_RESUME] = "_Unwind_Resume";
Names[RTLIB::SYNC_VAL_COMPARE_AND_SWAP_1] = "__sync_val_compare_and_swap_1";
Names[RTLIB::SYNC_VAL_COMPARE_AND_SWAP_2] = "__sync_val_compare_and_swap_2";
@@ -763,6 +768,24 @@ RTLIB::Libcall RTLIB::getSYNC(unsigned Opc, MVT VT) {
return UNKNOWN_LIBCALL;
}
+RTLIB::Libcall RTLIB::getMEMCPY_ELEMENT_ATOMIC(uint64_t ElementSize) {
+ switch (ElementSize) {
+ case 1:
+ return MEMCPY_ELEMENT_ATOMIC_1;
+ case 2:
+ return MEMCPY_ELEMENT_ATOMIC_2;
+ case 4:
+ return MEMCPY_ELEMENT_ATOMIC_4;
+ case 8:
+ return MEMCPY_ELEMENT_ATOMIC_8;
+ case 16:
+ return MEMCPY_ELEMENT_ATOMIC_16;
+ default:
+ return UNKNOWN_LIBCALL;
+ }
+
+}
+
/// InitCmpLibcallCCs - Set default comparison libcall CC.
///
static void InitCmpLibcallCCs(ISD::CondCode *CCs) {
OpenPOWER on IntegriCloud