Support s390x atomic fence

This commit is contained in:
Josh Stone 2017-01-06 17:20:50 -08:00
parent 3c6edb0d6b
commit 74fef128e4
2 changed files with 177 additions and 1 deletions

View file

@ -0,0 +1,169 @@
Index: llvm/trunk/lib/Target/SystemZ/SystemZAsmPrinter.cpp
===================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ llvm/trunk/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -260,6 +260,11 @@
.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;
Index: llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.h
===================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.h
+++ llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.h
@@ -146,6 +146,9 @@
// 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 @@
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,
Index: llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp
===================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ llvm/trunk/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -216,6 +216,8 @@
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 @@
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 @@
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 @@
OPCODE(SEARCH_STRING);
OPCODE(IPM);
OPCODE(SERIALIZE);
+ OPCODE(MEMBARRIER);
OPCODE(TBEGIN);
OPCODE(TBEGIN_NOFLOAT);
OPCODE(TEND);
@@ -5307,6 +5331,7 @@
MachineBasicBlock *
SystemZTargetLowering::emitAtomicCmpSwapW(MachineInstr *MI,
MachineBasicBlock *MBB) const {
+
MachineFunction &MF = *MBB->getParent();
const SystemZInstrInfo *TII =
static_cast<const SystemZInstrInfo *>(Subtarget.getInstrInfo());
Index: llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td
===================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td
+++ llvm/trunk/lib/Target/SystemZ/SystemZInstrInfo.td
@@ -1231,6 +1231,10 @@
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>;
Index: llvm/trunk/lib/Target/SystemZ/SystemZOperators.td
===================================================================
--- llvm/trunk/lib/Target/SystemZ/SystemZOperators.td
+++ llvm/trunk/lib/Target/SystemZ/SystemZOperators.td
@@ -188,6 +188,8 @@
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",
Index: llvm/trunk/test/CodeGen/SystemZ/atomic-fence-01.ll
===================================================================
--- llvm/trunk/test/CodeGen/SystemZ/atomic-fence-01.ll
+++ llvm/trunk/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
+}
+
Index: llvm/trunk/test/CodeGen/SystemZ/atomic-fence-02.ll
===================================================================
--- llvm/trunk/test/CodeGen/SystemZ/atomic-fence-02.ll
+++ llvm/trunk/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
+}

View file

@ -7,7 +7,7 @@
Name: llvm
Version: 3.8.1
Release: 1%{?dist}
Release: 2%{?dist}
Summary: The Low Level Virtual Machine
License: NCSA
@ -19,6 +19,9 @@ Source100: llvm-config.h
# recognize s390 as SystemZ when configuring build
Patch0: llvm-3.7.1-cmake-s390.patch
# backport D18644 [SystemZ] Support ATOMIC_FENCE
Patch1: llvm-d18644-systemz-atomic-fence.patch
BuildRequires: cmake
BuildRequires: zlib-devel
BuildRequires: libffi-devel
@ -70,6 +73,7 @@ Static libraries for the LLVM compiler infrastructure.
%prep
%setup -q -n %{name}-%{version}.src
%patch0 -p1 -b .s390
%patch1 -p2 -b .s390-fence
%build
mkdir -p _build
@ -185,6 +189,9 @@ make check-all || :
%{_libdir}/*.a
%changelog
* Sat Jan 07 2017 Josh Stone <jistone@redhat.com> - 3.8.1-2
- Support s390x atomic fence
* Wed Jul 13 2016 Adam Jackson <ajax@redhat.com> - 3.8.1-1
- llvm 3.8.1
- Add mips target