diff options
author | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2016-04-04 12:45:44 +0000 |
---|---|---|
committer | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2016-04-04 12:45:44 +0000 |
commit | a9ac6d6cc225a25eb55c7edd8825780c44ee351e (patch) | |
tree | 5ade5d942142285fcb628155f98ce498102c7120 | |
parent | f557d083252598cc42ce1b5409edaa91a305c9f9 (diff) | |
download | bcm5719-llvm-a9ac6d6cc225a25eb55c7edd8825780c44ee351e.tar.gz bcm5719-llvm-a9ac6d6cc225a25eb55c7edd8825780c44ee351e.zip |
[SystemZ] Support ATOMIC_FENCE
A cross-thread sequentially consistent fence should be lowered into
z/Architecture's BCR serialization instruction, instead of causing a
fatal error in the back-end.
Author: bryanpkc
Differential Revision: http://reviews.llvm.org/D18644
llvm-svn: 265292
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZISelLowering.cpp | 25 | ||||
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZISelLowering.h | 4 | ||||
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZInstrInfo.td | 4 | ||||
-rw-r--r-- | llvm/lib/Target/SystemZ/SystemZOperators.td | 2 | ||||
-rw-r--r-- | llvm/test/CodeGen/SystemZ/atomic-fence-01.ll | 16 | ||||
-rw-r--r-- | llvm/test/CodeGen/SystemZ/atomic-fence-02.ll | 13 |
7 files changed, 69 insertions, 0 deletions
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp index 75273114d62..be729d360e3 100644 --- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp +++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp @@ -260,6 +260,11 @@ void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) { .addImm(15).addReg(SystemZ::R0D); break; + // Emit nothing here but a comment if we can. + case SystemZ::MemBarrier: + OutStreamer->emitRawComment("MEMBARRIER"); + return; + default: Lower.lower(MI, LoweredMI); break; diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index 654f66a7966..9848c2a571a 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -216,6 +216,8 @@ SystemZTargetLowering::SystemZTargetLowering(const TargetMachine &TM, setOperationAction(ISD::ATOMIC_LOAD_UMAX, MVT::i32, Custom); setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32, Custom); + setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); + // z10 has instructions for signed but not unsigned FP conversion. // Handle unsigned 32-bit types as signed 64-bit types. if (!Subtarget.hasFPExtension()) { @@ -3118,6 +3120,25 @@ SDValue SystemZTargetLowering::lowerCTPOP(SDValue Op, return Op; } +SDValue SystemZTargetLowering::lowerATOMIC_FENCE(SDValue Op, + SelectionDAG &DAG) const { + SDLoc DL(Op); + AtomicOrdering FenceOrdering = static_cast<AtomicOrdering>( + cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue()); + SynchronizationScope FenceScope = static_cast<SynchronizationScope>( + cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue()); + + // The only fence that needs an instruction is a sequentially-consistent + // cross-thread fence. + if (FenceOrdering == SequentiallyConsistent && FenceScope == CrossThread) { + return SDValue(DAG.getMachineNode(SystemZ::Serialize, DL, MVT::Other, + Op.getOperand(0)), 0); + } + + // MEMBARRIER is a compiler barrier; it codegens to a no-op. + return DAG.getNode(SystemZISD::MEMBARRIER, DL, MVT::Other, Op.getOperand(0)); +} + // Op is an atomic load. Lower it into a normal volatile load. SDValue SystemZTargetLowering::lowerATOMIC_LOAD(SDValue Op, SelectionDAG &DAG) const { @@ -4444,6 +4465,8 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op, case ISD::CTTZ_ZERO_UNDEF: return DAG.getNode(ISD::CTTZ, SDLoc(Op), Op.getValueType(), Op.getOperand(0)); + case ISD::ATOMIC_FENCE: + return lowerATOMIC_FENCE(Op, DAG); case ISD::ATOMIC_SWAP: return lowerATOMIC_LOAD_OP(Op, DAG, SystemZISD::ATOMIC_SWAPW); case ISD::ATOMIC_STORE: @@ -4547,6 +4570,7 @@ const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const { OPCODE(SEARCH_STRING); OPCODE(IPM); OPCODE(SERIALIZE); + OPCODE(MEMBARRIER); OPCODE(TBEGIN); OPCODE(TBEGIN_NOFLOAT); OPCODE(TEND); @@ -5307,6 +5331,7 @@ SystemZTargetLowering::emitAtomicLoadMinMax(MachineInstr *MI, MachineBasicBlock * SystemZTargetLowering::emitAtomicCmpSwapW(MachineInstr *MI, MachineBasicBlock *MBB) const { + MachineFunction &MF = *MBB->getParent(); const SystemZInstrInfo *TII = static_cast<const SystemZInstrInfo *>(Subtarget.getInstrInfo()); diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.h b/llvm/lib/Target/SystemZ/SystemZISelLowering.h index af8c67d7849..e6e3e1701ae 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.h +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.h @@ -146,6 +146,9 @@ enum NodeType : unsigned { // Perform a serialization operation. (BCR 15,0 or BCR 14,0.) SERIALIZE, + // Compiler barrier only; generate a no-op. + MEMBARRIER, + // Transaction begin. The first operand is the chain, the second // the TDB pointer, and the third the immediate control field. // Returns chain and glue. @@ -479,6 +482,7 @@ private: SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const; SDValue lowerOR(SDValue Op, SelectionDAG &DAG) const; SDValue lowerCTPOP(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const; SDValue lowerATOMIC_LOAD(SDValue Op, SelectionDAG &DAG) const; SDValue lowerATOMIC_STORE(SDValue Op, SelectionDAG &DAG) const; SDValue lowerATOMIC_LOAD_OP(SDValue Op, SelectionDAG &DAG, diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td index 37ad8c7c282..65945204999 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.td @@ -1231,6 +1231,10 @@ def PFDRL : PrefetchRILPC<"pfdrl", 0xC62, z_prefetch>; let hasSideEffects = 1 in def Serialize : Alias<2, (outs), (ins), [(z_serialize)]>; +// A pseudo instruction that serves as a compiler barrier. +let hasSideEffects = 1 in +def MemBarrier : Pseudo<(outs), (ins), [(z_membarrier)]>; + let Predicates = [FeatureInterlockedAccess1], Defs = [CC] in { def LAA : LoadAndOpRSY<"laa", 0xEBF8, atomic_load_add_32, GR32>; def LAAG : LoadAndOpRSY<"laag", 0xEBE8, atomic_load_add_64, GR64>; diff --git a/llvm/lib/Target/SystemZ/SystemZOperators.td b/llvm/lib/Target/SystemZ/SystemZOperators.td index 3c95a1e11b4..730b9b31868 100644 --- a/llvm/lib/Target/SystemZ/SystemZOperators.td +++ b/llvm/lib/Target/SystemZ/SystemZOperators.td @@ -188,6 +188,8 @@ def z_udivrem64 : SDNode<"SystemZISD::UDIVREM64", SDT_ZGR128Binary64>; def z_serialize : SDNode<"SystemZISD::SERIALIZE", SDTNone, [SDNPHasChain, SDNPMayStore]>; +def z_membarrier : SDNode<"SystemZISD::MEMBARRIER", SDTNone, + [SDNPHasChain, SDNPSideEffect]>; // Defined because the index is an i32 rather than a pointer. def z_vector_insert : SDNode<"ISD::INSERT_VECTOR_ELT", diff --git a/llvm/test/CodeGen/SystemZ/atomic-fence-01.ll b/llvm/test/CodeGen/SystemZ/atomic-fence-01.ll new file mode 100644 index 00000000000..25566db9078 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/atomic-fence-01.ll @@ -0,0 +1,16 @@ +; Test (fast) serialization. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s --check-prefix=Z10 +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z196 | FileCheck %s --check-prefix=Z196 +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=zEC12 | FileCheck %s --check-prefix=ZEC12 +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 | FileCheck %s --check-prefix=Z13 + +define void @test() { +; Z10: bcr 15, %r0 +; Z196: bcr 14, %r0 +; ZEC12: bcr 14, %r0 +; Z13: bcr 14, %r0 + fence seq_cst + ret void +} + diff --git a/llvm/test/CodeGen/SystemZ/atomic-fence-02.ll b/llvm/test/CodeGen/SystemZ/atomic-fence-02.ll new file mode 100644 index 00000000000..4c4375ef669 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/atomic-fence-02.ll @@ -0,0 +1,13 @@ +; Serialization is emitted only for fence seq_cst. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s + +define void @test() { +; CHECK: #MEMBARRIER + fence acquire +; CHECK: #MEMBARRIER + fence release +; CHECK: #MEMBARRIER + fence acq_rel + ret void +} |