From: Eli Friedman Date: Wed, 24 Aug 2011 22:33:28 +0000 (+0000) Subject: Hook up 64-bit atomic load/store on x86-32. I plan to write more efficient implement... X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=f8f90f01747b9c7f6c332d8ec12c92fc5158af96;p=oota-llvm.git Hook up 64-bit atomic load/store on x86-32. I plan to write more efficient implementations eventually. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@138505 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 022fa05f2a9..cbc72808feb 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -468,6 +468,7 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) } if (!Subtarget->is64Bit()) { + setOperationAction(ISD::ATOMIC_LOAD, MVT::i64, Custom); setOperationAction(ISD::ATOMIC_LOAD_ADD, MVT::i64, Custom); setOperationAction(ISD::ATOMIC_LOAD_SUB, MVT::i64, Custom); setOperationAction(ISD::ATOMIC_LOAD_AND, MVT::i64, Custom); @@ -10003,15 +10004,20 @@ SDValue X86TargetLowering::LowerLOAD_SUB(SDValue Op, SelectionDAG &DAG) const { static SDValue LowerATOMIC_STORE(SDValue Op, SelectionDAG &DAG) { SDNode *Node = Op.getNode(); DebugLoc dl = Node->getDebugLoc(); + EVT VT = cast(Node)->getMemoryVT(); // Convert seq_cst store -> xchg - if (cast(Node)->getOrdering() == SequentiallyConsistent) { + // Convert wide store -> swap (-> cmpxchg8b/cmpxchg16b) + // FIXME: On 32-bit, store -> fist or movq would be more efficient + // (The only way to get a 16-byte store is cmpxchg16b) + // FIXME: 16-byte ATOMIC_SWAP isn't actually hooked up at the moment. + if (cast(Node)->getOrdering() == SequentiallyConsistent || + !DAG.getTargetLoweringInfo().isTypeLegal(VT)) { SDValue Swap = DAG.getAtomic(ISD::ATOMIC_SWAP, dl, cast(Node)->getMemoryVT(), Node->getOperand(0), Node->getOperand(1), Node->getOperand(2), - cast(Node)->getSrcValue(), - cast(Node)->getAlignment(), + cast(Node)->getMemOperand(), cast(Node)->getOrdering(), cast(Node)->getSynchScope()); return Swap.getValue(1); @@ -10121,6 +10127,28 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { } } +static void ReplaceATOMIC_LOAD(SDNode *Node, + SmallVectorImpl &Results, + SelectionDAG &DAG) { + DebugLoc dl = Node->getDebugLoc(); + EVT VT = cast(Node)->getMemoryVT(); + + // Convert wide load -> cmpxchg8b/cmpxchg16b + // FIXME: On 32-bit, load -> fild or movq would be more efficient + // (The only way to get a 16-byte load is cmpxchg16b) + // FIXME: 16-byte ATOMIC_CMP_SWAP isn't actually hooked up at the moment. + SDValue Zero = DAG.getConstant(0, cast(Node)->getMemoryVT()); + SDValue Swap = DAG.getAtomic(ISD::ATOMIC_CMP_SWAP, dl, + cast(Node)->getMemoryVT(), + Node->getOperand(0), + Node->getOperand(1), Zero, Zero, + cast(Node)->getMemOperand(), + cast(Node)->getOrdering(), + cast(Node)->getSynchScope()); + Results.push_back(Swap.getValue(0)); + Results.push_back(Swap.getValue(1)); +} + void X86TargetLowering:: ReplaceATOMIC_BINARY_64(SDNode *Node, SmallVectorImpl&Results, SelectionDAG &DAG, unsigned NewOp) const { @@ -10244,6 +10272,8 @@ void X86TargetLowering::ReplaceNodeResults(SDNode *N, case ISD::ATOMIC_SWAP: ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMSWAP64_DAG); return; + case ISD::ATOMIC_LOAD: + ReplaceATOMIC_LOAD(N, Results, DAG); } } diff --git a/test/CodeGen/X86/atomic-load-store-wide.ll b/test/CodeGen/X86/atomic-load-store-wide.ll new file mode 100644 index 00000000000..227883e5592 --- /dev/null +++ b/test/CodeGen/X86/atomic-load-store-wide.ll @@ -0,0 +1,19 @@ +; RUN: llc < %s -march=x86 | FileCheck %s + +; 64-bit load/store on x86-32 +; FIXME: The generated code can be substantially improved. + +define void @test1(i64* %ptr, i64 %val1) { +; CHECK: test1 +; CHECK: cmpxchg8b +; CHECK-NEXT: jne + store atomic i64 %val1, i64* %ptr seq_cst, align 4 + ret void +} + +define i64 @test2(i64* %ptr) { +; CHECK: test2 +; CHECK: cmpxchg8b + %val = load atomic i64* %ptr seq_cst, align 4 + ret i64 %val +}