forked from OSchip/llvm-project
21 Commits
Author | SHA1 | Message | Date |
---|---|---|---|
Ulrich Weigand | 57c85f53ba |
[SystemZ] Support transactional execution on zEC12
The zEC12 provides the transactional-execution facility. This is exposed to users via a set of builtin routines on other compilers. This patch adds LLVM support to enable those builtins. In partciular, the patch: - adds the transactional-execution and processor-assist facilities - adds MC support for all instructions provided by those facilities - adds LLVM intrinsics for those instructions and hooks them up for CodeGen - adds CodeGen support to optimize CC return value checking Since this is first use of target-specific intrinsics on the platform, the patch creates the include/llvm/IR/IntrinsicsSystemZ.td file and hooks it up in Intrinsics.td. I've also changed Triple::getArchTypePrefix to return "s390" instead of "systemz", since the naming convention for GCC intrinsics uses "s390" on the platform, and it neemed more straight- forward to use the same convention for LLVM IR intrinsics. An associated clang patch makes the intrinsics (and command line switches) available at the source-language level. For reference, the transactional-execution instructions are documented in the z/Architecture Principles of Operation for the zEC12: http://publibfp.boulder.ibm.com/cgi-bin/bookmgr/download/DZ9ZR009.pdf The associated builtins are documented in the GCC manual: http://gcc.gnu.org/onlinedocs/gcc/S_002f390-System-z-Built-in-Functions.html Index: llvm-head/lib/Target/SystemZ/SystemZOperators.td =================================================================== --- llvm-head.orig/lib/Target/SystemZ/SystemZOperators.td +++ llvm-head/lib/Target/SystemZ/SystemZOperators.td @@ -79,6 +79,9 @@ def SDT_ZI32Intrinsic : SDTypeProf def SDT_ZPrefetch : SDTypeProfile<0, 2, [SDTCisVT<0, i32>, SDTCisPtrTy<1>]>; +def SDT_ZTBegin : SDTypeProfile<0, 2, + [SDTCisPtrTy<0>, + SDTCisVT<1, i32>]>; //===----------------------------------------------------------------------===// // Node definitions @@ -180,6 +183,15 @@ def z_prefetch : SDNode<"System [SDNPHasChain, SDNPMayLoad, SDNPMayStore, SDNPMemOperand]>; +def z_tbegin : SDNode<"SystemZISD::TBEGIN", SDT_ZTBegin, + [SDNPHasChain, SDNPOutGlue, SDNPMayStore, + SDNPSideEffect]>; +def z_tbegin_nofloat : SDNode<"SystemZISD::TBEGIN_NOFLOAT", SDT_ZTBegin, + [SDNPHasChain, SDNPOutGlue, SDNPMayStore, + SDNPSideEffect]>; +def z_tend : SDNode<"SystemZISD::TEND", SDTNone, + [SDNPHasChain, SDNPOutGlue, SDNPSideEffect]>; + //===----------------------------------------------------------------------===// // Pattern fragments //===----------------------------------------------------------------------===// Index: llvm-head/lib/Target/SystemZ/SystemZInstrFormats.td =================================================================== --- llvm-head.orig/lib/Target/SystemZ/SystemZInstrFormats.td +++ llvm-head/lib/Target/SystemZ/SystemZInstrFormats.td @@ -473,6 +473,17 @@ class InstSS<bits<8> op, dag outs, dag i let Inst{15-0} = BD2; } +class InstS<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern> + : InstSystemZ<4, outs, ins, asmstr, pattern> { + field bits<32> Inst; + field bits<32> SoftFail = 0; + + bits<16> BD2; + + let Inst{31-16} = op; + let Inst{15-0} = BD2; +} + //===----------------------------------------------------------------------===// // Instruction definitions with semantics //===----------------------------------------------------------------------===// Index: llvm-head/lib/Target/SystemZ/SystemZInstrInfo.td =================================================================== --- llvm-head.orig/lib/Target/SystemZ/SystemZInstrInfo.td +++ llvm-head/lib/Target/SystemZ/SystemZInstrInfo.td @@ -1362,6 +1362,60 @@ let Defs = [CC] in { } //===----------------------------------------------------------------------===// +// Transactional execution +//===----------------------------------------------------------------------===// + +let Predicates = [FeatureTransactionalExecution] in { + // Transaction Begin + let hasSideEffects = 1, mayStore = 1, + usesCustomInserter = 1, Defs = [CC] in { + def TBEGIN : InstSIL<0xE560, + (outs), (ins bdaddr12only:$BD1, imm32zx16:$I2), + "tbegin\t$BD1, $I2", + [(z_tbegin bdaddr12only:$BD1, imm32zx16:$I2)]>; + def TBEGIN_nofloat : Pseudo<(outs), (ins bdaddr12only:$BD1, imm32zx16:$I2), + [(z_tbegin_nofloat bdaddr12only:$BD1, + imm32zx16:$I2)]>; + def TBEGINC : InstSIL<0xE561, + (outs), (ins bdaddr12only:$BD1, imm32zx16:$I2), + "tbeginc\t$BD1, $I2", + [(int_s390_tbeginc bdaddr12only:$BD1, + imm32zx16:$I2)]>; + } + + // Transaction End + let hasSideEffects = 1, Defs = [CC], BD2 = 0 in + def TEND : InstS<0xB2F8, (outs), (ins), "tend", [(z_tend)]>; + + // Transaction Abort + let hasSideEffects = 1, isTerminator = 1, isBarrier = 1 in + def TABORT : InstS<0xB2FC, (outs), (ins bdaddr12only:$BD2), + "tabort\t$BD2", + [(int_s390_tabort bdaddr12only:$BD2)]>; + + // Nontransactional Store + let hasSideEffects = 1 in + def NTSTG : StoreRXY<"ntstg", 0xE325, int_s390_ntstg, GR64, 8>; + + // Extract Transaction Nesting Depth + let hasSideEffects = 1 in + def ETND : InherentRRE<"etnd", 0xB2EC, GR32, (int_s390_etnd)>; +} + +//===----------------------------------------------------------------------===// +// Processor assist +//===----------------------------------------------------------------------===// + +let Predicates = [FeatureProcessorAssist] in { + let hasSideEffects = 1, R4 = 0 in + def PPA : InstRRF<0xB2E8, (outs), (ins GR64:$R1, GR64:$R2, imm32zx4:$R3), + "ppa\t$R1, $R2, $R3", []>; + def : Pat<(int_s390_ppa_txassist GR32:$src), + (PPA (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$src, subreg_l32), + 0, 1)>; +} + +//===----------------------------------------------------------------------===// // Miscellaneous Instructions. //===----------------------------------------------------------------------===// Index: llvm-head/lib/Target/SystemZ/SystemZProcessors.td =================================================================== --- llvm-head.orig/lib/Target/SystemZ/SystemZProcessors.td +++ llvm-head/lib/Target/SystemZ/SystemZProcessors.td @@ -60,6 +60,16 @@ def FeatureMiscellaneousExtensions : Sys "Assume that the miscellaneous-extensions facility is installed" >; +def FeatureTransactionalExecution : SystemZFeature< + "transactional-execution", "TransactionalExecution", + "Assume that the transactional-execution facility is installed" +>; + +def FeatureProcessorAssist : SystemZFeature< + "processor-assist", "ProcessorAssist", + "Assume that the processor-assist facility is installed" +>; + def : Processor<"generic", NoItineraries, []>; def : Processor<"z10", NoItineraries, []>; def : Processor<"z196", NoItineraries, @@ -70,4 +80,5 @@ def : Processor<"zEC12", NoItineraries, [FeatureDistinctOps, FeatureLoadStoreOnCond, FeatureHighWord, FeatureFPExtension, FeaturePopulationCount, FeatureFastSerialization, FeatureInterlockedAccess1, - FeatureMiscellaneousExtensions]>; + FeatureMiscellaneousExtensions, + FeatureTransactionalExecution, FeatureProcessorAssist]>; Index: llvm-head/lib/Target/SystemZ/SystemZSubtarget.cpp =================================================================== --- llvm-head.orig/lib/Target/SystemZ/SystemZSubtarget.cpp +++ llvm-head/lib/Target/SystemZ/SystemZSubtarget.cpp @@ -40,6 +40,7 @@ SystemZSubtarget::SystemZSubtarget(const HasLoadStoreOnCond(false), HasHighWord(false), HasFPExtension(false), HasPopulationCount(false), HasFastSerialization(false), HasInterlockedAccess1(false), HasMiscellaneousExtensions(false), + HasTransactionalExecution(false), HasProcessorAssist(false), TargetTriple(TT), InstrInfo(initializeSubtargetDependencies(CPU, FS)), TLInfo(TM, *this), TSInfo(*TM.getDataLayout()), FrameLowering() {} Index: llvm-head/lib/Target/SystemZ/SystemZSubtarget.h =================================================================== --- llvm-head.orig/lib/Target/SystemZ/SystemZSubtarget.h +++ llvm-head/lib/Target/SystemZ/SystemZSubtarget.h @@ -42,6 +42,8 @@ protected: bool HasFastSerialization; bool HasInterlockedAccess1; bool HasMiscellaneousExtensions; + bool HasTransactionalExecution; + bool HasProcessorAssist; private: Triple TargetTriple; @@ -102,6 +104,12 @@ public: return HasMiscellaneousExtensions; } + // Return true if the target has the transactional-execution facility. + bool hasTransactionalExecution() const { return HasTransactionalExecution; } + + // Return true if the target has the processor-assist facility. + bool hasProcessorAssist() const { return HasProcessorAssist; } + // Return true if GV can be accessed using LARL for reloc model RM // and code model CM. bool isPC32DBLSymbol(const GlobalValue *GV, Reloc::Model RM, Index: llvm-head/lib/Support/Triple.cpp =================================================================== --- llvm-head.orig/lib/Support/Triple.cpp +++ llvm-head/lib/Support/Triple.cpp @@ -92,7 +92,7 @@ const char *Triple::getArchTypePrefix(Ar case sparcv9: case sparc: return "sparc"; - case systemz: return "systemz"; + case systemz: return "s390"; case x86: case x86_64: return "x86"; Index: llvm-head/include/llvm/IR/Intrinsics.td =================================================================== --- llvm-head.orig/include/llvm/IR/Intrinsics.td +++ llvm-head/include/llvm/IR/Intrinsics.td @@ -634,3 +634,4 @@ include "llvm/IR/IntrinsicsNVVM.td" include "llvm/IR/IntrinsicsMips.td" include "llvm/IR/IntrinsicsR600.td" include "llvm/IR/IntrinsicsBPF.td" +include "llvm/IR/IntrinsicsSystemZ.td" Index: llvm-head/include/llvm/IR/IntrinsicsSystemZ.td =================================================================== --- /dev/null +++ llvm-head/include/llvm/IR/IntrinsicsSystemZ.td @@ -0,0 +1,46 @@ +//===- IntrinsicsSystemZ.td - Defines SystemZ intrinsics ---*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the SystemZ-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// +// Transactional-execution intrinsics +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "s390" in { + def int_s390_tbegin : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrNoDuplicate]>; + + def int_s390_tbegin_nofloat : Intrinsic<[llvm_i32_ty], + [llvm_ptr_ty, llvm_i32_ty], + [IntrNoDuplicate]>; + + def int_s390_tbeginc : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], + [IntrNoDuplicate]>; + + def int_s390_tabort : Intrinsic<[], [llvm_i64_ty], + [IntrNoReturn, Throws]>; + + def int_s390_tend : GCCBuiltin<"__builtin_tend">, + Intrinsic<[llvm_i32_ty], []>; + + def int_s390_etnd : GCCBuiltin<"__builtin_tx_nesting_depth">, + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>; + + def int_s390_ntstg : Intrinsic<[], [llvm_i64_ty, llvm_ptr64_ty], + [IntrReadWriteArgMem]>; + + def int_s390_ppa_txassist : GCCBuiltin<"__builtin_tx_assist">, + Intrinsic<[], [llvm_i32_ty]>; +} + Index: llvm-head/lib/Target/SystemZ/SystemZ.h =================================================================== --- llvm-head.orig/lib/Target/SystemZ/SystemZ.h +++ llvm-head/lib/Target/SystemZ/SystemZ.h @@ -68,6 +68,18 @@ const unsigned CCMASK_TM_MSB_0 = C const unsigned CCMASK_TM_MSB_1 = CCMASK_2 | CCMASK_3; const unsigned CCMASK_TM = CCMASK_ANY; +// Condition-code mask assignments for TRANSACTION_BEGIN. +const unsigned CCMASK_TBEGIN_STARTED = CCMASK_0; +const unsigned CCMASK_TBEGIN_INDETERMINATE = CCMASK_1; +const unsigned CCMASK_TBEGIN_TRANSIENT = CCMASK_2; +const unsigned CCMASK_TBEGIN_PERSISTENT = CCMASK_3; +const unsigned CCMASK_TBEGIN = CCMASK_ANY; + +// Condition-code mask assignments for TRANSACTION_END. +const unsigned CCMASK_TEND_TX = CCMASK_0; +const unsigned CCMASK_TEND_NOTX = CCMASK_2; +const unsigned CCMASK_TEND = CCMASK_TEND_TX | CCMASK_TEND_NOTX; + // The position of the low CC bit in an IPM result. const unsigned IPM_CC = 28; Index: llvm-head/lib/Target/SystemZ/SystemZISelLowering.h =================================================================== --- llvm-head.orig/lib/Target/SystemZ/SystemZISelLowering.h +++ llvm-head/lib/Target/SystemZ/SystemZISelLowering.h @@ -146,6 +146,15 @@ enum { // Perform a serialization operation. (BCR 15,0 or BCR 14,0.) SERIALIZE, + // Transaction begin. The first operand is the chain, the second + // the TDB pointer, and the third the immediate control field. + // Returns chain and glue. + TBEGIN, + TBEGIN_NOFLOAT, + + // Transaction end. Just the chain operand. Returns chain and glue. + TEND, + // Wrappers around the inner loop of an 8- or 16-bit ATOMIC_SWAP or // ATOMIC_LOAD_<op>. // @@ -318,6 +327,7 @@ private: SDValue lowerSTACKSAVE(SDValue Op, SelectionDAG &DAG) const; SDValue lowerSTACKRESTORE(SDValue Op, SelectionDAG &DAG) const; SDValue lowerPREFETCH(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const; // If the last instruction before MBBI in MBB was some form of COMPARE, // try to replace it with a COMPARE AND BRANCH just before MBBI. @@ -355,6 +365,10 @@ private: MachineBasicBlock *emitStringWrapper(MachineInstr *MI, MachineBasicBlock *BB, unsigned Opcode) const; + MachineBasicBlock *emitTransactionBegin(MachineInstr *MI, + MachineBasicBlock *MBB, + unsigned Opcode, + bool NoFloat) const; }; } // end namespace llvm Index: llvm-head/lib/Target/SystemZ/SystemZISelLowering.cpp =================================================================== --- llvm-head.orig/lib/Target/SystemZ/SystemZISelLowering.cpp +++ llvm-head/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -20,6 +20,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/IR/Intrinsics.h" #include <cctype> using namespace llvm; @@ -304,6 +305,9 @@ SystemZTargetLowering::SystemZTargetLowe // Codes for which we want to perform some z-specific combinations. setTargetDAGCombine(ISD::SIGN_EXTEND); + // Handle intrinsics. + setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom); + // We want to use MVC in preference to even a single load/store pair. MaxStoresPerMemcpy = 0; MaxStoresPerMemcpyOptSize = 0; @@ -1031,6 +1035,53 @@ prepareVolatileOrAtomicLoad(SDValue Chai return DAG.getNode(SystemZISD::SERIALIZE, DL, MVT::Other, Chain); } +// Return true if Op is an intrinsic node with chain that returns the CC value +// as its only (other) argument. Provide the associated SystemZISD opcode and +// the mask of valid CC values if so. +static bool isIntrinsicWithCCAndChain(SDValue Op, unsigned &Opcode, + unsigned &CCValid) { + unsigned Id = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue(); + switch (Id) { + case Intrinsic::s390_tbegin: + Opcode = SystemZISD::TBEGIN; + CCValid = SystemZ::CCMASK_TBEGIN; + return true; + + case Intrinsic::s390_tbegin_nofloat: + Opcode = SystemZISD::TBEGIN_NOFLOAT; + CCValid = SystemZ::CCMASK_TBEGIN; + return true; + + case Intrinsic::s390_tend: + Opcode = SystemZISD::TEND; + CCValid = SystemZ::CCMASK_TEND; + return true; + + default: + return false; + } +} + +// Emit an intrinsic with chain with a glued value instead of its CC result. +static SDValue emitIntrinsicWithChainAndGlue(SelectionDAG &DAG, SDValue Op, + unsigned Opcode) { + // Copy all operands except the intrinsic ID. + unsigned NumOps = Op.getNumOperands(); + SmallVector<SDValue, 6> Ops; + Ops.reserve(NumOps - 1); + Ops.push_back(Op.getOperand(0)); + for (unsigned I = 2; I < NumOps; ++I) + Ops.push_back(Op.getOperand(I)); + + assert(Op->getNumValues() == 2 && "Expected only CC result and chain"); + SDVTList RawVTs = DAG.getVTList(MVT::Other, MVT::Glue); + SDValue Intr = DAG.getNode(Opcode, SDLoc(Op), RawVTs, Ops); + SDValue OldChain = SDValue(Op.getNode(), 1); + SDValue NewChain = SDValue(Intr.getNode(), 0); + DAG.ReplaceAllUsesOfValueWith(OldChain, NewChain); + return Intr; +} + // CC is a comparison that will be implemented using an integer or // floating-point comparison. Return the condition code mask for // a branch on true. In the integer case, CCMASK_CMP_UO is set for @@ -1588,9 +1639,53 @@ static void adjustForTestUnderMask(Selec C.CCMask = NewCCMask; } +// Return a Comparison that tests the condition-code result of intrinsic +// node Call against constant integer CC using comparison code Cond. +// Opcode is the opcode of the SystemZISD operation for the intrinsic +// and CCValid is the set of possible condition-code results. +static Comparison getIntrinsicCmp(SelectionDAG &DAG, unsigned Opcode, + SDValue Call, unsigned CCValid, uint64_t CC, + ISD::CondCode Cond) { + Comparison C(Call, SDValue()); + C.Opcode = Opcode; + C.CCValid = CCValid; + if (Cond == ISD::SETEQ) + // bit 3 for CC==0, bit 0 for CC==3, always false for CC>3. + C.CCMask = CC < 4 ? 1 << (3 - CC) : 0; + else if (Cond == ISD::SETNE) + // ...and the inverse of that. + C.CCMask = CC < 4 ? ~(1 << (3 - CC)) : -1; + else if (Cond == ISD::SETLT || Cond == ISD::SETULT) + // bits above bit 3 for CC==0 (always false), bits above bit 0 for CC==3, + // always true for CC>3. + C.CCMask = CC < 4 ? -1 << (4 - CC) : -1; + else if (Cond == ISD::SETGE || Cond == ISD::SETUGE) + // ...and the inverse of that. + C.CCMask = CC < 4 ? ~(-1 << (4 - CC)) : 0; + else if (Cond == ISD::SETLE || Cond == ISD::SETULE) + // bit 3 and above for CC==0, bit 0 and above for CC==3 (always true), + // always true for CC>3. + C.CCMask = CC < 4 ? -1 << (3 - CC) : -1; + else if (Cond == ISD::SETGT || Cond == ISD::SETUGT) + // ...and the inverse of that. + C.CCMask = CC < 4 ? ~(-1 << (3 - CC)) : 0; + else + llvm_unreachable("Unexpected integer comparison type"); + C.CCMask &= CCValid; + return C; +} + // Decide how to implement a comparison of type Cond between CmpOp0 with CmpOp1. static Comparison getCmp(SelectionDAG &DAG, SDValue CmpOp0, SDValue CmpOp1, ISD::CondCode Cond) { + if (CmpOp1.getOpcode() == ISD::Constant) { + uint64_t Constant = cast<ConstantSDNode>(CmpOp1)->getZExtValue(); + unsigned Opcode, CCValid; + if (CmpOp0.getOpcode() == ISD::INTRINSIC_W_CHAIN && + CmpOp0.getResNo() == 0 && CmpOp0->hasNUsesOfValue(1, 0) && + isIntrinsicWithCCAndChain(CmpOp0, Opcode, CCValid)) + return getIntrinsicCmp(DAG, Opcode, CmpOp0, CCValid, Constant, Cond); + } Comparison C(CmpOp0, CmpOp1); C.CCMask = CCMaskForCondCode(Cond); if (C.Op0.getValueType().isFloatingPoint()) { @@ -1632,6 +1727,17 @@ static Comparison getCmp(SelectionDAG &D // Emit the comparison instruction described by C. static SDValue emitCmp(SelectionDAG &DAG, SDLoc DL, Comparison &C) { + if (!C.Op1.getNode()) { + SDValue Op; + switch (C.Op0.getOpcode()) { + case ISD::INTRINSIC_W_CHAIN: + Op = emitIntrinsicWithChainAndGlue(DAG, C.Op0, C.Opcode); + break; + default: + llvm_unreachable("Invalid comparison operands"); + } + return SDValue(Op.getNode(), Op->getNumValues() - 1); + } if (C.Opcode == SystemZISD::ICMP) return DAG.getNode(SystemZISD::ICMP, DL, MVT::Glue, C.Op0, C.Op1, DAG.getConstant(C.ICmpType, MVT::i32)); @@ -1713,7 +1819,6 @@ SDValue SystemZTargetLowering::lowerSETC } SDValue SystemZTargetLowering::lowerBR_CC(SDValue Op, SelectionDAG &DAG) const { - SDValue Chain = Op.getOperand(0); ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get(); SDValue CmpOp0 = Op.getOperand(2); SDValue CmpOp1 = Op.getOperand(3); @@ -1723,7 +1828,7 @@ SDValue SystemZTargetLowering::lowerBR_C Comparison C(getCmp(DAG, CmpOp0, CmpOp1, CC)); SDValue Glue = emitCmp(DAG, DL, C); return DAG.getNode(SystemZISD::BR_CCMASK, DL, Op.getValueType(), - Chain, DAG.getConstant(C.CCValid, MVT::i32), + Op.getOperand(0), DAG.getConstant(C.CCValid, MVT::i32), DAG.getConstant(C.CCMask, MVT::i32), Dest, Glue); } @@ -2561,6 +2666,30 @@ SDValue SystemZTargetLowering::lowerPREF Node->getMemoryVT(), Node->getMemOperand()); } +// Return an i32 that contains the value of CC immediately after After, +// whose final operand must be MVT::Glue. +static SDValue getCCResult(SelectionDAG &DAG, SDNode *After) { + SDValue Glue = SDValue(After, After->getNumValues() - 1); + SDValue IPM = DAG.getNode(SystemZISD::IPM, SDLoc(After), MVT::i32, Glue); + return DAG.getNode(ISD::SRL, SDLoc(After), MVT::i32, IPM, + DAG.getConstant(SystemZ::IPM_CC, MVT::i32)); +} + +SDValue +SystemZTargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op, + SelectionDAG &DAG) const { + unsigned Opcode, CCValid; + if (isIntrinsicWithCCAndChain(Op, Opcode, CCValid)) { + assert(Op->getNumValues() == 2 && "Expected only CC result and chain"); + SDValue Glued = emitIntrinsicWithChainAndGlue(DAG, Op, Opcode); + SDValue CC = getCCResult(DAG, Glued.getNode()); + DAG.ReplaceAllUsesOfValueWith(SDValue(Op.getNode(), 0), CC); + return SDValue(); + } + + return SDValue(); +} + SDValue SystemZTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { switch (Op.getOpcode()) { @@ -2634,6 +2763,8 @@ SDValue SystemZTargetLowering::LowerOper return lowerSTACKRESTORE(Op, DAG); case ISD::PREFETCH: return lowerPREFETCH(Op, DAG); + case ISD::INTRINSIC_W_CHAIN: + return lowerINTRINSIC_W_CHAIN(Op, DAG); default: llvm_unreachable("Unexpected node to lower"); } @@ -2674,6 +2805,9 @@ const char *SystemZTargetLowering::getTa OPCODE(SEARCH_STRING); OPCODE(IPM); OPCODE(SERIALIZE); + OPCODE(TBEGIN); + OPCODE(TBEGIN_NOFLOAT); + OPCODE(TEND); OPCODE(ATOMIC_SWAPW); OPCODE(ATOMIC_LOADW_ADD); OPCODE(ATOMIC_LOADW_SUB); @@ -3501,6 +3635,50 @@ SystemZTargetLowering::emitStringWrapper return DoneMBB; } +// Update TBEGIN instruction with final opcode and register clobbers. +MachineBasicBlock * +SystemZTargetLowering::emitTransactionBegin(MachineInstr *MI, + MachineBasicBlock *MBB, + unsigned Opcode, + bool NoFloat) const { + MachineFunction &MF = *MBB->getParent(); + const TargetFrameLowering *TFI = Subtarget.getFrameLowering(); + const SystemZInstrInfo *TII = Subtarget.getInstrInfo(); + + // Update opcode. + MI->setDesc(TII->get(Opcode)); + + // We cannot handle a TBEGIN that clobbers the stack or frame pointer. + // Make sure to add the corresponding GRSM bits if they are missing. + uint64_t Control = MI->getOperand(2).getImm(); + static const unsigned GPRControlBit[16] = { + 0x8000, 0x8000, 0x4000, 0x4000, 0x2000, 0x2000, 0x1000, 0x1000, + 0x0800, 0x0800, 0x0400, 0x0400, 0x0200, 0x0200, 0x0100, 0x0100 + }; + Control |= GPRControlBit[15]; + if (TFI->hasFP(MF)) + Control |= GPRControlBit[11]; + MI->getOperand(2).setImm(Control); + + // Add GPR clobbers. + for (int I = 0; I < 16; I++) { + if ((Control & GPRControlBit[I]) == 0) { + unsigned Reg = SystemZMC::GR64Regs[I]; + MI->addOperand(MachineOperand::CreateReg(Reg, true, true)); + } + } + + // Add FPR clobbers. + if (!NoFloat && (Control & 4) != 0) { + for (int I = 0; I < 16; I++) { + unsigned Reg = SystemZMC::FP64Regs[I]; + MI->addOperand(MachineOperand::CreateReg(Reg, true, true)); + } + } + + return MBB; +} + MachineBasicBlock *SystemZTargetLowering:: EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const { switch (MI->getOpcode()) { @@ -3742,6 +3920,12 @@ EmitInstrWithCustomInserter(MachineInstr return emitStringWrapper(MI, MBB, SystemZ::MVST); case SystemZ::SRSTLoop: return emitStringWrapper(MI, MBB, SystemZ::SRST); + case SystemZ::TBEGIN: + return emitTransactionBegin(MI, MBB, SystemZ::TBEGIN, false); + case SystemZ::TBEGIN_nofloat: + return emitTransactionBegin(MI, MBB, SystemZ::TBEGIN, true); + case SystemZ::TBEGINC: + return emitTransactionBegin(MI, MBB, SystemZ::TBEGINC, true); default: llvm_unreachable("Unexpected instr type to insert"); } Index: llvm-head/test/CodeGen/SystemZ/htm-intrinsics.ll =================================================================== --- /dev/null +++ llvm-head/test/CodeGen/SystemZ/htm-intrinsics.ll @@ -0,0 +1,352 @@ +; Test transactional-execution intrinsics. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=zEC12 | FileCheck %s + +declare i32 @llvm.s390.tbegin(i8 *, i32) +declare i32 @llvm.s390.tbegin.nofloat(i8 *, i32) +declare void @llvm.s390.tbeginc(i8 *, i32) +declare i32 @llvm.s390.tend() +declare void @llvm.s390.tabort(i64) +declare void @llvm.s390.ntstg(i64, i64 *) +declare i32 @llvm.s390.etnd() +declare void @llvm.s390.ppa.txassist(i32) + +; TBEGIN. +define void @test_tbegin() { +; CHECK-LABEL: test_tbegin: +; CHECK-NOT: stmg +; CHECK: std %f8, +; CHECK: std %f9, +; CHECK: std %f10, +; CHECK: std %f11, +; CHECK: std %f12, +; CHECK: std %f13, +; CHECK: std %f14, +; CHECK: std %f15, +; CHECK: tbegin 0, 65292 +; CHECK: ld %f8, +; CHECK: ld %f9, +; CHECK: ld %f10, +; CHECK: ld %f11, +; CHECK: ld %f12, +; CHECK: ld %f13, +; CHECK: ld %f14, +; CHECK: ld %f15, +; CHECK: br %r14 + call i32 @llvm.s390.tbegin(i8 *null, i32 65292) + ret void +} + +; TBEGIN (nofloat). +define void @test_tbegin_nofloat1() { +; CHECK-LABEL: test_tbegin_nofloat1: +; CHECK-NOT: stmg +; CHECK-NOT: std +; CHECK: tbegin 0, 65292 +; CHECK: br %r14 + call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 65292) + ret void +} + +; TBEGIN (nofloat) with integer CC return value. +define i32 @test_tbegin_nofloat2() { +; CHECK-LABEL: test_tbegin_nofloat2: +; CHECK-NOT: stmg +; CHECK-NOT: std +; CHECK: tbegin 0, 65292 +; CHECK: ipm %r2 +; CHECK: srl %r2, 28 +; CHECK: br %r14 + %res = call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 65292) + ret i32 %res +} + +; TBEGIN (nofloat) with implicit CC check. +define void @test_tbegin_nofloat3(i32 *%ptr) { +; CHECK-LABEL: test_tbegin_nofloat3: +; CHECK-NOT: stmg +; CHECK-NOT: std +; CHECK: tbegin 0, 65292 +; CHECK: jnh {{\.L*}} +; CHECK: mvhi 0(%r2), 0 +; CHECK: br %r14 + %res = call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 65292) + %cmp = icmp eq i32 %res, 2 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + store i32 0, i32* %ptr, align 4 + br label %if.end + +if.end: ; preds = %if.then, %entry + ret void +} + +; TBEGIN (nofloat) with dual CC use. +define i32 @test_tbegin_nofloat4(i32 %pad, i32 *%ptr) { +; CHECK-LABEL: test_tbegin_nofloat4: +; CHECK-NOT: stmg +; CHECK-NOT: std +; CHECK: tbegin 0, 65292 +; CHECK: ipm %r2 +; CHECK: srl %r2, 28 +; CHECK: cijlh %r2, 2, {{\.L*}} +; CHECK: mvhi 0(%r3), 0 +; CHECK: br %r14 + %res = call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 65292) + %cmp = icmp eq i32 %res, 2 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + store i32 0, i32* %ptr, align 4 + br label %if.end + +if.end: ; preds = %if.then, %entry + ret i32 %res +} + +; TBEGIN (nofloat) with register. +define void @test_tbegin_nofloat5(i8 *%ptr) { +; CHECK-LABEL: test_tbegin_nofloat5: +; CHECK-NOT: stmg +; CHECK-NOT: std +; CHECK: tbegin 0(%r2), 65292 +; CHECK: br %r14 + call i32 @llvm.s390.tbegin.nofloat(i8 *%ptr, i32 65292) + ret void +} + +; TBEGIN (nofloat) with GRSM 0x0f00. +define void @test_tbegin_nofloat6() { +; CHECK-LABEL: test_tbegin_nofloat6: +; CHECK: stmg %r6, %r15, +; CHECK-NOT: std +; CHECK: tbegin 0, 3840 +; CHECK: br %r14 + call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 3840) + ret void +} + +; TBEGIN (nofloat) with GRSM 0xf100. +define void @test_tbegin_nofloat7() { +; CHECK-LABEL: test_tbegin_nofloat7: +; CHECK: stmg %r8, %r15, +; CHECK-NOT: std +; CHECK: tbegin 0, 61696 +; CHECK: br %r14 + call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 61696) + ret void +} + +; TBEGIN (nofloat) with GRSM 0xfe00 -- stack pointer added automatically. +define void @test_tbegin_nofloat8() { +; CHECK-LABEL: test_tbegin_nofloat8: +; CHECK-NOT: stmg +; CHECK-NOT: std +; CHECK: tbegin 0, 65280 +; CHECK: br %r14 + call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 65024) + ret void +} + +; TBEGIN (nofloat) with GRSM 0xfb00 -- no frame pointer needed. +define void @test_tbegin_nofloat9() { +; CHECK-LABEL: test_tbegin_nofloat9: +; CHECK: stmg %r10, %r15, +; CHECK-NOT: std +; CHECK: tbegin 0, 64256 +; CHECK: br %r14 + call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 64256) + ret void +} + +; TBEGIN (nofloat) with GRSM 0xfb00 -- frame pointer added automatically. +define void @test_tbegin_nofloat10(i64 %n) { +; CHECK-LABEL: test_tbegin_nofloat10: +; CHECK: stmg %r11, %r15, +; CHECK-NOT: std +; CHECK: tbegin 0, 65280 +; CHECK: br %r14 + %buf = alloca i8, i64 %n + call i32 @llvm.s390.tbegin.nofloat(i8 *null, i32 64256) + ret void +} + +; TBEGINC. +define void @test_tbeginc() { +; CHECK-LABEL: test_tbeginc: +; CHECK-NOT: stmg +; CHECK-NOT: std +; CHECK: tbeginc 0, 65288 +; CHECK: br %r14 + call void @llvm.s390.tbeginc(i8 *null, i32 65288) + ret void +} + +; TEND with integer CC return value. +define i32 @test_tend1() { +; CHECK-LABEL: test_tend1: +; CHECK: tend +; CHECK: ipm %r2 +; CHECK: srl %r2, 28 +; CHECK: br %r14 + %res = call i32 @llvm.s390.tend() + ret i32 %res +} + +; TEND with implicit CC check. +define void @test_tend3(i32 *%ptr) { +; CHECK-LABEL: test_tend3: +; CHECK: tend +; CHECK: je {{\.L*}} +; CHECK: mvhi 0(%r2), 0 +; CHECK: br %r14 + %res = call i32 @llvm.s390.tend() + %cmp = icmp eq i32 %res, 2 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + store i32 0, i32* %ptr, align 4 + br label %if.end + +if.end: ; preds = %if.then, %entry + ret void +} + +; TEND with dual CC use. +define i32 @test_tend2(i32 %pad, i32 *%ptr) { +; CHECK-LABEL: test_tend2: +; CHECK: tend +; CHECK: ipm %r2 +; CHECK: srl %r2, 28 +; CHECK: cijlh %r2, 2, {{\.L*}} +; CHECK: mvhi 0(%r3), 0 +; CHECK: br %r14 + %res = call i32 @llvm.s390.tend() + %cmp = icmp eq i32 %res, 2 + br i1 %cmp, label %if.then, label %if.end + +if.then: ; preds = %entry + store i32 0, i32* %ptr, align 4 + br label %if.end + +if.end: ; preds = %if.then, %entry + ret i32 %res +} + +; TABORT with register only. +define void @test_tabort1(i64 %val) { +; CHECK-LABEL: test_tabort1: +; CHECK: tabort 0(%r2) +; CHECK: br %r14 + call void @llvm.s390.tabort(i64 %val) + ret void +} + +; TABORT with immediate only. +define void @test_tabort2(i64 %val) { +; CHECK-LABEL: test_tabort2: +; CHECK: tabort 1234 +; CHECK: br %r14 + call void @llvm.s390.tabort(i64 1234) + ret void +} + +; TABORT with register + immediate. +define void @test_tabort3(i64 %val) { +; CHECK-LABEL: test_tabort3: +; CHECK: tabort 1234(%r2) +; CHECK: br %r14 + %sum = add i64 %val, 1234 + call void @llvm.s390.tabort(i64 %sum) + ret void +} + +; TABORT with out-of-range immediate. +define void @test_tabort4(i64 %val) { +; CHECK-LABEL: test_tabort4: +; CHECK: tabort 0({{%r[1-5]}}) +; CHECK: br %r14 + call void @llvm.s390.tabort(i64 4096) + ret void +} + +; NTSTG with base pointer only. +define void @test_ntstg1(i64 *%ptr, i64 %val) { +; CHECK-LABEL: test_ntstg1: +; CHECK: ntstg %r3, 0(%r2) +; CHECK: br %r14 + call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) + ret void +} + +; NTSTG with base and index. +; Check that VSTL doesn't allow an index. +define void @test_ntstg2(i64 *%base, i64 %index, i64 %val) { +; CHECK-LABEL: test_ntstg2: +; CHECK: sllg [[REG:%r[1-5]]], %r3, 3 +; CHECK: ntstg %r4, 0([[REG]],%r2) +; CHECK: br %r14 + %ptr = getelementptr i64, i64 *%base, i64 %index + call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) + ret void +} + +; NTSTG with the highest in-range displacement. +define void @test_ntstg3(i64 *%base, i64 %val) { +; CHECK-LABEL: test_ntstg3: +; CHECK: ntstg %r3, 524280(%r2) +; CHECK: br %r14 + %ptr = getelementptr i64, i64 *%base, i64 65535 + call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) + ret void +} + +; NTSTG with an out-of-range positive displacement. +define void @test_ntstg4(i64 *%base, i64 %val) { +; CHECK-LABEL: test_ntstg4: +; CHECK: ntstg %r3, 0({{%r[1-5]}}) +; CHECK: br %r14 + %ptr = getelementptr i64, i64 *%base, i64 65536 + call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) + ret void +} + +; NTSTG with the lowest in-range displacement. +define void @test_ntstg5(i64 *%base, i64 %val) { +; CHECK-LABEL: test_ntstg5: +; CHECK: ntstg %r3, -524288(%r2) +; CHECK: br %r14 + %ptr = getelementptr i64, i64 *%base, i64 -65536 + call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) + ret void +} + +; NTSTG with an out-of-range negative displacement. +define void @test_ntstg6(i64 *%base, i64 %val) { +; CHECK-LABEL: test_ntstg6: +; CHECK: ntstg %r3, 0({{%r[1-5]}}) +; CHECK: br %r14 + %ptr = getelementptr i64, i64 *%base, i64 -65537 + call void @llvm.s390.ntstg(i64 %val, i64 *%ptr) + ret void +} + +; ETND. +define i32 @test_etnd() { +; CHECK-LABEL: test_etnd: +; CHECK: etnd %r2 +; CHECK: br %r14 + %res = call i32 @llvm.s390.etnd() + ret i32 %res +} + +; PPA (Transaction-Abort Assist) +define void @test_ppa_txassist(i32 %val) { +; CHECK-LABEL: test_ppa_txassist: +; CHECK: ppa %r2, 0, 1 +; CHECK: br %r14 + call void @llvm.s390.ppa.txassist(i32 %val) + ret void +} + Index: llvm-head/test/MC/SystemZ/insn-bad-zEC12.s =================================================================== --- llvm-head.orig/test/MC/SystemZ/insn-bad-zEC12.s +++ llvm-head/test/MC/SystemZ/insn-bad-zEC12.s @@ -3,6 +3,22 @@ # RUN: FileCheck < %t %s #CHECK: error: invalid operand +#CHECK: ntstg %r0, -524289 +#CHECK: error: invalid operand +#CHECK: ntstg %r0, 524288 + + ntstg %r0, -524289 + ntstg %r0, 524288 + +#CHECK: error: invalid operand +#CHECK: ppa %r0, %r0, -1 +#CHECK: error: invalid operand +#CHECK: ppa %r0, %r0, 16 + + ppa %r0, %r0, -1 + ppa %r0, %r0, 16 + +#CHECK: error: invalid operand #CHECK: risbgn %r0,%r0,0,0,-1 #CHECK: error: invalid operand #CHECK: risbgn %r0,%r0,0,0,64 @@ -22,3 +38,47 @@ risbgn %r0,%r0,-1,0,0 risbgn %r0,%r0,256,0,0 +#CHECK: error: invalid operand +#CHECK: tabort -1 +#CHECK: error: invalid operand +#CHECK: tabort 4096 +#CHECK: error: invalid use of indexed addressing +#CHECK: tabort 0(%r1,%r2) + + tabort -1 + tabort 4096 + tabort 0(%r1,%r2) + +#CHECK: error: invalid operand +#CHECK: tbegin -1, 0 +#CHECK: error: invalid operand +#CHECK: tbegin 4096, 0 +#CHECK: error: invalid use of indexed addressing +#CHECK: tbegin 0(%r1,%r2), 0 +#CHECK: error: invalid operand +#CHECK: tbegin 0, -1 +#CHECK: error: invalid operand +#CHECK: tbegin 0, 65536 + + tbegin -1, 0 + tbegin 4096, 0 + tbegin 0(%r1,%r2), 0 + tbegin 0, -1 + tbegin 0, 65536 + +#CHECK: error: invalid operand +#CHECK: tbeginc -1, 0 +#CHECK: error: invalid operand +#CHECK: tbeginc 4096, 0 +#CHECK: error: invalid use of indexed addressing +#CHECK: tbeginc 0(%r1,%r2), 0 +#CHECK: error: invalid operand +#CHECK: tbeginc 0, -1 +#CHECK: error: invalid operand +#CHECK: tbeginc 0, 65536 + + tbeginc -1, 0 + tbeginc 4096, 0 + tbeginc 0(%r1,%r2), 0 + tbeginc 0, -1 + tbeginc 0, 65536 Index: llvm-head/test/MC/SystemZ/insn-good-zEC12.s =================================================================== --- llvm-head.orig/test/MC/SystemZ/insn-good-zEC12.s +++ llvm-head/test/MC/SystemZ/insn-good-zEC12.s @@ -1,6 +1,48 @@ # For zEC12 and above. # RUN: llvm-mc -triple s390x-linux-gnu -mcpu=zEC12 -show-encoding %s | FileCheck %s +#CHECK: etnd %r0 # encoding: [0xb2,0xec,0x00,0x00] +#CHECK: etnd %r15 # encoding: [0xb2,0xec,0x00,0xf0] +#CHECK: etnd %r7 # encoding: [0xb2,0xec,0x00,0x70] + + etnd %r0 + etnd %r15 + etnd %r7 + +#CHECK: ntstg %r0, -524288 # encoding: [0xe3,0x00,0x00,0x00,0x80,0x25] +#CHECK: ntstg %r0, -1 # encoding: [0xe3,0x00,0x0f,0xff,0xff,0x25] +#CHECK: ntstg %r0, 0 # encoding: [0xe3,0x00,0x00,0x00,0x00,0x25] +#CHECK: ntstg %r0, 1 # encoding: [0xe3,0x00,0x00,0x01,0x00,0x25] +#CHECK: ntstg %r0, 524287 # encoding: [0xe3,0x00,0x0f,0xff,0x7f,0x25] +#CHECK: ntstg %r0, 0(%r1) # encoding: [0xe3,0x00,0x10,0x00,0x00,0x25] +#CHECK: ntstg %r0, 0(%r15) # encoding: [0xe3,0x00,0xf0,0x00,0x00,0x25] +#CHECK: ntstg %r0, 524287(%r1,%r15) # encoding: [0xe3,0x01,0xff,0xff,0x7f,0x25] +#CHECK: ntstg %r0, 524287(%r15,%r1) # encoding: [0xe3,0x0f,0x1f,0xff,0x7f,0x25] +#CHECK: ntstg %r15, 0 # encoding: [0xe3,0xf0,0x00,0x00,0x00,0x25] + + ntstg %r0, -524288 + ntstg %r0, -1 + ntstg %r0, 0 + ntstg %r0, 1 + ntstg %r0, 524287 + ntstg %r0, 0(%r1) + ntstg %r0, 0(%r15) + ntstg %r0, 524287(%r1,%r15) + ntstg %r0, 524287(%r15,%r1) + ntstg %r15, 0 + +#CHECK: ppa %r0, %r0, 0 # encoding: [0xb2,0xe8,0x00,0x00] +#CHECK: ppa %r0, %r0, 15 # encoding: [0xb2,0xe8,0xf0,0x00] +#CHECK: ppa %r0, %r15, 0 # encoding: [0xb2,0xe8,0x00,0x0f] +#CHECK: ppa %r4, %r6, 7 # encoding: [0xb2,0xe8,0x70,0x46] +#CHECK: ppa %r15, %r0, 0 # encoding: [0xb2,0xe8,0x00,0xf0] + + ppa %r0, %r0, 0 + ppa %r0, %r0, 15 + ppa %r0, %r15, 0 + ppa %r4, %r6, 7 + ppa %r15, %r0, 0 + #CHECK: risbgn %r0, %r0, 0, 0, 0 # encoding: [0xec,0x00,0x00,0x00,0x00,0x59] #CHECK: risbgn %r0, %r0, 0, 0, 63 # encoding: [0xec,0x00,0x00,0x00,0x3f,0x59] #CHECK: risbgn %r0, %r0, 0, 255, 0 # encoding: [0xec,0x00,0x00,0xff,0x00,0x59] @@ -17,3 +59,68 @@ risbgn %r15,%r0,0,0,0 risbgn %r4,%r5,6,7,8 +#CHECK: tabort 0 # encoding: [0xb2,0xfc,0x00,0x00] +#CHECK: tabort 0(%r1) # encoding: [0xb2,0xfc,0x10,0x00] +#CHECK: tabort 0(%r15) # encoding: [0xb2,0xfc,0xf0,0x00] +#CHECK: tabort 4095 # encoding: [0xb2,0xfc,0x0f,0xff] +#CHECK: tabort 4095(%r1) # encoding: [0xb2,0xfc,0x1f,0xff] +#CHECK: tabort 4095(%r15) # encoding: [0xb2,0xfc,0xff,0xff] + + tabort 0 + tabort 0(%r1) + tabort 0(%r15) + tabort 4095 + tabort 4095(%r1) + tabort 4095(%r15) + +#CHECK: tbegin 0, 0 # encoding: [0xe5,0x60,0x00,0x00,0x00,0x00] +#CHECK: tbegin 4095, 0 # encoding: [0xe5,0x60,0x0f,0xff,0x00,0x00] +#CHECK: tbegin 0, 0 # encoding: [0xe5,0x60,0x00,0x00,0x00,0x00] +#CHECK: tbegin 0, 1 # encoding: [0xe5,0x60,0x00,0x00,0x00,0x01] +#CHECK: tbegin 0, 32767 # encoding: [0xe5,0x60,0x00,0x00,0x7f,0xff] +#CHECK: tbegin 0, 32768 # encoding: [0xe5,0x60,0x00,0x00,0x80,0x00] +#CHECK: tbegin 0, 65535 # encoding: [0xe5,0x60,0x00,0x00,0xff,0xff] +#CHECK: tbegin 0(%r1), 42 # encoding: [0xe5,0x60,0x10,0x00,0x00,0x2a] +#CHECK: tbegin 0(%r15), 42 # encoding: [0xe5,0x60,0xf0,0x00,0x00,0x2a] +#CHECK: tbegin 4095(%r1), 42 # encoding: [0xe5,0x60,0x1f,0xff,0x00,0x2a] +#CHECK: tbegin 4095(%r15), 42 # encoding: [0xe5,0x60,0xff,0xff,0x00,0x2a] + + tbegin 0, 0 + tbegin 4095, 0 + tbegin 0, 0 + tbegin 0, 1 + tbegin 0, 32767 + tbegin 0, 32768 + tbegin 0, 65535 + tbegin 0(%r1), 42 + tbegin 0(%r15), 42 + tbegin 4095(%r1), 42 + tbegin 4095(%r15), 42 + +#CHECK: tbeginc 0, 0 # encoding: [0xe5,0x61,0x00,0x00,0x00,0x00] +#CHECK: tbeginc 4095, 0 # encoding: [0xe5,0x61,0x0f,0xff,0x00,0x00] +#CHECK: tbeginc 0, 0 # encoding: [0xe5,0x61,0x00,0x00,0x00,0x00] +#CHECK: tbeginc 0, 1 # encoding: [0xe5,0x61,0x00,0x00,0x00,0x01] +#CHECK: tbeginc 0, 32767 # encoding: [0xe5,0x61,0x00,0x00,0x7f,0xff] +#CHECK: tbeginc 0, 32768 # encoding: [0xe5,0x61,0x00,0x00,0x80,0x00] +#CHECK: tbeginc 0, 65535 # encoding: [0xe5,0x61,0x00,0x00,0xff,0xff] +#CHECK: tbeginc 0(%r1), 42 # encoding: [0xe5,0x61,0x10,0x00,0x00,0x2a] +#CHECK: tbeginc 0(%r15), 42 # encoding: [0xe5,0x61,0xf0,0x00,0x00,0x2a] +#CHECK: tbeginc 4095(%r1), 42 # encoding: [0xe5,0x61,0x1f,0xff,0x00,0x2a] +#CHECK: tbeginc 4095(%r15), 42 # encoding: [0xe5,0x61,0xff,0xff,0x00,0x2a] + + tbeginc 0, 0 + tbeginc 4095, 0 + tbeginc 0, 0 + tbeginc 0, 1 + tbeginc 0, 32767 + tbeginc 0, 32768 + tbeginc 0, 65535 + tbeginc 0(%r1), 42 + tbeginc 0(%r15), 42 + tbeginc 4095(%r1), 42 + tbeginc 4095(%r15), 42 + +#CHECK: tend # encoding: [0xb2,0xf8,0x00,0x00] + + tend Index: llvm-head/test/MC/SystemZ/insn-bad-z196.s =================================================================== --- llvm-head.orig/test/MC/SystemZ/insn-bad-z196.s +++ llvm-head/test/MC/SystemZ/insn-bad-z196.s @@ -244,6 +244,11 @@ cxlgbr %f0, 16, %r0, 0 cxlgbr %f2, 0, %r0, 0 +#CHECK: error: {{(instruction requires: transactional-execution)?}} +#CHECK: etnd %r7 + + etnd %r7 + #CHECK: error: invalid operand #CHECK: fidbra %f0, 0, %f0, -1 #CHECK: error: invalid operand @@ -546,6 +551,16 @@ locr %r0,%r0,-1 locr %r0,%r0,16 +#CHECK: error: {{(instruction requires: transactional-execution)?}} +#CHECK: ntstg %r0, 524287(%r1,%r15) + + ntstg %r0, 524287(%r1,%r15) + +#CHECK: error: {{(instruction requires: processor-assist)?}} +#CHECK: ppa %r4, %r6, 7 + + ppa %r4, %r6, 7 + #CHECK: error: {{(instruction requires: miscellaneous-extensions)?}} #CHECK: risbgn %r1, %r2, 0, 0, 0 @@ -690,3 +705,24 @@ stocg %r0,-524289,1 stocg %r0,524288,1 stocg %r0,0(%r1,%r2),1 + +#CHECK: error: {{(instruction requires: transactional-execution)?}} +#CHECK: tabort 4095(%r1) + + tabort 4095(%r1) + +#CHECK: error: {{(instruction requires: transactional-execution)?}} +#CHECK: tbegin 4095(%r1), 42 + + tbegin 4095(%r1), 42 + +#CHECK: error: {{(instruction requires: transactional-execution)?}} +#CHECK: tbeginc 4095(%r1), 42 + + tbeginc 4095(%r1), 42 + +#CHECK: error: {{(instruction requires: transactional-execution)?}} +#CHECK: tend + + tend + Index: llvm-head/test/MC/Disassembler/SystemZ/insns.txt =================================================================== --- llvm-head.orig/test/MC/Disassembler/SystemZ/insns.txt +++ llvm-head/test/MC/Disassembler/SystemZ/insns.txt @@ -2503,6 +2503,15 @@ # CHECK: ear %r15, %a15 0xb2 0x4f 0x00 0xff +# CHECK: etnd %r0 +0xb2 0xec 0x00 0x00 + +# CHECK: etnd %r15 +0xb2 0xec 0x00 0xf0 + +# CHECK: etnd %r7 +0xb2 0xec 0x00 0x70 + # CHECK: fidbr %f0, 0, %f0 0xb3 0x5f 0x00 0x00 @@ -6034,6 +6043,36 @@ # CHECK: ny %r15, 0 0xe3 0xf0 0x00 0x00 0x00 0x54 +# CHECK: ntstg %r0, -524288 +0xe3 0x00 0x00 0x00 0x80 0x25 + +# CHECK: ntstg %r0, -1 +0xe3 0x00 0x0f 0xff 0xff 0x25 + +# CHECK: ntstg %r0, 0 +0xe3 0x00 0x00 0x00 0x00 0x25 + +# CHECK: ntstg %r0, 1 +0xe3 0x00 0x00 0x01 0x00 0x25 + +# CHECK: ntstg %r0, 524287 +0xe3 0x00 0x0f 0xff 0x7f 0x25 + +# CHECK: ntstg %r0, 0(%r1) +0xe3 0x00 0x10 0x00 0x00 0x25 + +# CHECK: ntstg %r0, 0(%r15) +0xe3 0x00 0xf0 0x00 0x00 0x25 + +# CHECK: ntstg %r0, 524287(%r1,%r15) +0xe3 0x01 0xff 0xff 0x7f 0x25 + +# CHECK: ntstg %r0, 524287(%r15,%r1) +0xe3 0x0f 0x1f 0xff 0x7f 0x25 + +# CHECK: ntstg %r15, 0 +0xe3 0xf0 0x00 0x00 0x00 0x25 + # CHECK: oc 0(1), 0 0xd6 0x00 0x00 0x00 0x00 0x00 @@ -6346,6 +6385,21 @@ # CHECK: popcnt %r7, %r8 0xb9 0xe1 0x00 0x78 +# CHECK: ppa %r0, %r0, 0 +0xb2 0xe8 0x00 0x00 + +# CHECK: ppa %r0, %r0, 15 +0xb2 0xe8 0xf0 0x00 + +# CHECK: ppa %r0, %r15, 0 +0xb2 0xe8 0x00 0x0f + +# CHECK: ppa %r4, %r6, 7 +0xb2 0xe8 0x70 0x46 + +# CHECK: ppa %r15, %r0, 0 +0xb2 0xe8 0x00 0xf0 + # CHECK: risbg %r0, %r0, 0, 0, 0 0xec 0x00 0x00 0x00 0x00 0x55 @@ -8062,6 +8116,93 @@ # CHECK: sy %r15, 0 0xe3 0xf0 0x00 0x00 0x00 0x5b +# CHECK: tabort 0 +0xb2 0xfc 0x00 0x00 + +# CHECK: tabort 0(%r1) +0xb2 0xfc 0x10 0x00 + +# CHECK: tabort 0(%r15) +0xb2 0xfc 0xf0 0x00 + +# CHECK: tabort 4095 +0xb2 0xfc 0x0f 0xff + +# CHECK: tabort 4095(%r1) +0xb2 0xfc 0x1f 0xff + +# CHECK: tabort 4095(%r15) +0xb2 0xfc 0xff 0xff + +# CHECK: tbegin 0, 0 +0xe5 0x60 0x00 0x00 0x00 0x00 + +# CHECK: tbegin 4095, 0 +0xe5 0x60 0x0f 0xff 0x00 0x00 + +# CHECK: tbegin 0, 0 +0xe5 0x60 0x00 0x00 0x00 0x00 + +# CHECK: tbegin 0, 1 +0xe5 0x60 0x00 0x00 0x00 0x01 + +# CHECK: tbegin 0, 32767 +0xe5 0x60 0x00 0x00 0x7f 0xff + +# CHECK: tbegin 0, 32768 +0xe5 0x60 0x00 0x00 0x80 0x00 + +# CHECK: tbegin 0, 65535 +0xe5 0x60 0x00 0x00 0xff 0xff + +# CHECK: tbegin 0(%r1), 42 +0xe5 0x60 0x10 0x00 0x00 0x2a + +# CHECK: tbegin 0(%r15), 42 +0xe5 0x60 0xf0 0x00 0x00 0x2a + +# CHECK: tbegin 4095(%r1), 42 +0xe5 0x60 0x1f 0xff 0x00 0x2a + +# CHECK: tbegin 4095(%r15), 42 +0xe5 0x60 0xff 0xff 0x00 0x2a + +# CHECK: tbeginc 0, 0 +0xe5 0x61 0x00 0x00 0x00 0x00 + +# CHECK: tbeginc 4095, 0 +0xe5 0x61 0x0f 0xff 0x00 0x00 + +# CHECK: tbeginc 0, 0 +0xe5 0x61 0x00 0x00 0x00 0x00 + +# CHECK: tbeginc 0, 1 +0xe5 0x61 0x00 0x00 0x00 0x01 + +# CHECK: tbeginc 0, 32767 +0xe5 0x61 0x00 0x00 0x7f 0xff + +# CHECK: tbeginc 0, 32768 +0xe5 0x61 0x00 0x00 0x80 0x00 + +# CHECK: tbeginc 0, 65535 +0xe5 0x61 0x00 0x00 0xff 0xff + +# CHECK: tbeginc 0(%r1), 42 +0xe5 0x61 0x10 0x00 0x00 0x2a + +# CHECK: tbeginc 0(%r15), 42 +0xe5 0x61 0xf0 0x00 0x00 0x2a + +# CHECK: tbeginc 4095(%r1), 42 +0xe5 0x61 0x1f 0xff 0x00 0x2a + +# CHECK: tbeginc 4095(%r15), 42 +0xe5 0x61 0xff 0xff 0x00 0x2a + +# CHECK: tend +0xb2 0xf8 0x00 0x00 + # CHECK: tm 0, 0 0x91 0x00 0x00 0x00 llvm-svn: 233803 |
|
Ulrich Weigand | 371d10a4eb |
[SystemZ] Support RISBGN instruction on zEC12
So far, we do not yet support any instruction specific to zEC12. Most of the facilities added with zEC12 are indeed not very useful to compiler code generation, but there is one exception: the miscellaneous-extensions facility provides the RISBGN instruction, which is a variant of RISBG that does not set the condition code. Add support for this facility, MC support for RISBGN, and CodeGen support for prefering RISBGN over RISBG on zEC12, unless we can actually make use of the condition code set by RISBG. llvm-svn: 233690 |
|
Richard Sandiford | e66e8c8b66 |
[SystemZ] Add MC support for LEDBRA, LEXBRA and LDXBRA
These instructions aren't used for codegen since the original L*DB instructions are suitable for fround. llvm-svn: 212703 |
|
Richard Sandiford | dc6c2c953d |
[SystemZ] Add support for z196 float<->unsigned conversions
These complement the older float<->signed instructions. llvm-svn: 204451 |
|
Richard Sandiford | 45645a2c1c |
[SystemZ] Add MC support for interlocked-access 1 instructions
llvm-svn: 197984 |
|
Richard Sandiford | b63e300b67 |
[SystemZ] Add comparisons of high words and memory
llvm-svn: 191777 |
|
Richard Sandiford | a9ac0e0f75 |
[SystemZ] Add comparisons of large immediates using high words
There are no corresponding patterns for small immediates because they would prevent the use of fused compare-and-branch instructions. llvm-svn: 191775 |
|
Richard Sandiford | 42a694f44e |
[SystemZ] Add immediate addition involving high words
llvm-svn: 191774 |
|
Richard Sandiford | 5469c39a26 |
[SystemZ] Add truncating high-word stores (STCH and STHH)
llvm-svn: 191743 |
|
Richard Sandiford | 0d46b1a30f |
[SystemZ] Add zero-extending high-word loads (LLCH and LLHH)
llvm-svn: 191742 |
|
Richard Sandiford | 89e160d975 |
[SystemZ] Add sign-extending high-word loads (LBH and LHH)
llvm-svn: 191740 |
|
Richard Sandiford | a26a4b4f60 |
[SystemZ] Reapply: Add definitions of LFH and STFH
Originally committed as r191661, but reverted because it changed the matching order of comparisons on some hosts. That should have been fixed by r191735. llvm-svn: 191738 |
|
Richard Sandiford | a25f268c25 |
[SystemZ] Revert r191661: Add definitions of LFH and STFH
For some reason, adding definitions for these load and store instructions changed whether some of the build bots matched comparisons as signed or unsigned. llvm-svn: 191663 |
|
Richard Sandiford | d30ac3a125 |
[SystemZ] Add definitions of LFH and STFH
llvm-svn: 191661 |
|
Richard Sandiford | 8e92c389e4 |
[SystemZ] Add FI[EDX]BRA
These are extensions of the existing FI[EDX]BR instructions, but use a spare bit to suppress inexact conditions. llvm-svn: 188894 |
|
Richard Sandiford | 6cf80b3ec0 |
[SystemZ] Add RISBLG and RISBHG instruction definitions
The next patch will make use of RISBLG for codegen. llvm-svn: 187490 |
|
Richard Sandiford | f2404164ba |
[SystemZ] Add LOCR and LOCGR
llvm-svn: 187113 |
|
Richard Sandiford | 09a8cf3604 |
[SystemZ] Add LOC and LOCG
As with the stores, these instructions can trap when the condition is false, so they are only used for things like (cond ? x : *ptr). llvm-svn: 187112 |
|
Richard Sandiford | a68e6f5660 |
[SystemZ] Add STOC and STOCG
These instructions are allowed to trap even if the condition is false, so for now they are only used for "*ptr = (cond ? x : *ptr)"-style constructs. llvm-svn: 187111 |
|
Richard Sandiford | 7d6a453623 |
[SystemZ] Add AHIK and AGHIK
I did these as a separate patch because it uses a slightly different form of RIE layout. llvm-svn: 186687 |
|
Richard Sandiford | 27d1cfe3d4 |
[SystemZ] Start adding z196 and zEC12 support
This first step just adds definitions for SLLK, SRLK and SRAK. The next patch will actually make use of them during codegen. insn-bad.s tests that some form of error is reported when using these instructions on z10. More work is needed to get the "instruction requires: distinct-ops" that we'd ideally like, so I've stubbed that part out for now. I'll come back and make it mandatory once the necessary changes are in. llvm-svn: 186680 |