Index: llvm/include/llvm/Support/TargetOpcodes.def =================================================================== --- llvm/include/llvm/Support/TargetOpcodes.def +++ llvm/include/llvm/Support/TargetOpcodes.def @@ -222,6 +222,10 @@ HANDLE_TARGET_OPCODE(ICALL_BRANCH_FUNNEL) +// This is a fence with the singlethread scope. It represents a compiler memory +// barrier, but does not correspond to any generated instruction. +HANDLE_TARGET_OPCODE(MEMBARRIER) + /// The following generic opcodes are not supposed to appear after ISel. /// This is something we might want to relax, but for now, this is convenient /// to produce diagnostics. Index: llvm/include/llvm/Target/Target.td =================================================================== --- llvm/include/llvm/Target/Target.td +++ llvm/include/llvm/Target/Target.td @@ -1432,6 +1432,14 @@ let AsmString = ""; let hasSideEffects = true; } +def MEMBARRIER : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins); + let AsmString = ""; + let hasSideEffects = true; + let Size = 0; + let isMeta = true; +} // Generic opcodes used in GlobalISel. include "llvm/Target/GenericOpcodes.td" Index: llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1653,6 +1653,9 @@ if (isVerbose()) OutStreamer->emitRawComment("ARITH_FENCE"); break; + case TargetOpcode::MEMBARRIER: + OutStreamer->emitRawComment("MEMBARRIER"); + break; default: emitInstruction(&MI); if (CanDoExtraAnalysis) { Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -2899,6 +2899,12 @@ case ISD::ARITH_FENCE: Select_ARITH_FENCE(NodeToMatch); return; + case ISD::MEMBARRIER: + // TODO: Factor out routine - and generalize op types? + // @Reviewers - Surely there's a pattern mechanism for this? + CurDAG->SelectNodeTo(NodeToMatch, TargetOpcode::MEMBARRIER, MVT::Other, + NodeToMatch->getOperand(0)); + return; case ISD::STACKMAP: Select_STACKMAP(NodeToMatch); return; Index: llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp =================================================================== --- llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp +++ llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp @@ -530,11 +530,6 @@ .addImm(15).addReg(SystemZ::R0D); break; - // Emit nothing here but a comment if we can. - case SystemZ::MemBarrier: - OutStreamer->emitRawComment("MEMBARRIER"); - return; - // We want to emit "j .+2" for traps, jumping to the relative immediate field // of the jump instruction, which is an illegal instruction. We cannot emit a // "." symbol, so create and emit a temp label before the instruction and use Index: llvm/lib/Target/SystemZ/SystemZInstrInfo.td =================================================================== --- llvm/lib/Target/SystemZ/SystemZInstrInfo.td +++ llvm/lib/Target/SystemZ/SystemZInstrInfo.td @@ -1716,10 +1716,6 @@ let hasSideEffects = 1 in def Serialize : Alias<2, (outs), (ins), []>; -// A pseudo instruction that serves as a compiler barrier. -let hasSideEffects = 1, hasNoSchedulingInfo = 1 in -def MemBarrier : Pseudo<(outs), (ins), [(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/lib/Target/SystemZ/SystemZLongBranch.cpp =================================================================== --- llvm/lib/Target/SystemZ/SystemZLongBranch.cpp +++ llvm/lib/Target/SystemZ/SystemZLongBranch.cpp @@ -217,7 +217,7 @@ assert((Size || // These do not have a size: MI.isDebugOrPseudoInstr() || MI.isPosition() || MI.isKill() || - MI.isImplicitDef() || MI.getOpcode() == SystemZ::MemBarrier || + MI.isImplicitDef() || MI.getOpcode() == TargetOpcode::MEMBARRIER || // These have a size that may be zero: MI.isInlineAsm() || MI.getOpcode() == SystemZ::STACKMAP || MI.getOpcode() == SystemZ::PATCHPOINT) && Index: llvm/lib/Target/VE/VEInstrInfo.td =================================================================== --- llvm/lib/Target/VE/VEInstrInfo.td +++ llvm/lib/Target/VE/VEInstrInfo.td @@ -2018,10 +2018,6 @@ "# GET STACK TOP", [(set iPTR:$dst, (GetStackTop))]>; -// MEMBARRIER -let hasSideEffects = 1 in -def MEMBARRIER : Pseudo<(outs), (ins), "# MEMBARRIER", [(membarrier)] >; - //===----------------------------------------------------------------------===// // Other patterns //===----------------------------------------------------------------------===// Index: llvm/lib/Target/X86/X86InstrCompiler.td =================================================================== --- llvm/lib/Target/X86/X86InstrCompiler.td +++ llvm/lib/Target/X86/X86InstrCompiler.td @@ -681,11 +681,6 @@ Requires<[Not64BitMode]>, OpSize32, LOCK, Sched<[WriteALURMW]>; -let hasSideEffects = 1, isMeta = 1 in -def Int_MemBarrier : I<0, Pseudo, (outs), (ins), - "#MEMBARRIER", - [(membarrier)]>, Sched<[WriteLoad]>; - // RegOpc corresponds to the mr version of the instruction // ImmOpc corresponds to the mi version of the instruction // ImmOpc8 corresponds to the mi8 version of the instruction Index: llvm/lib/Target/X86/X86MCInstLower.cpp =================================================================== --- llvm/lib/Target/X86/X86MCInstLower.cpp +++ llvm/lib/Target/X86/X86MCInstLower.cpp @@ -2506,11 +2506,6 @@ case TargetOpcode::DBG_VALUE: llvm_unreachable("Should be handled target independently"); - // Emit nothing here but a comment if we can. - case X86::Int_MemBarrier: - OutStreamer->emitRawComment("MEMBARRIER"); - return; - case X86::EH_RETURN: case X86::EH_RETURN64: { // Lower these as normal, but add some comments. Index: llvm/lib/Target/XCore/XCoreInstrInfo.td =================================================================== --- llvm/lib/Target/XCore/XCoreInstrInfo.td +++ llvm/lib/Target/XCore/XCoreInstrInfo.td @@ -358,10 +358,6 @@ (select GRRegs:$cond, GRRegs:$T, GRRegs:$F))]>; } -let hasSideEffects = 1, isMeta = 1 in -def Int_MemBarrier : PseudoInstXCore<(outs), (ins), "#MEMBARRIER", - [(membarrier)]>; - //===----------------------------------------------------------------------===// // Instructions //===----------------------------------------------------------------------===// Index: llvm/test/CodeGen/X86/atomic-idempotent.ll =================================================================== --- llvm/test/CodeGen/X86/atomic-idempotent.ll +++ llvm/test/CodeGen/X86/atomic-idempotent.ll @@ -359,6 +359,8 @@ ; X86-ATOM-NEXT: nop ; X86-ATOM-NEXT: nop ; X86-ATOM-NEXT: nop +; X86-ATOM-NEXT: nop +; X86-ATOM-NEXT: nop ; X86-ATOM-NEXT: retl atomicrmw or ptr %p, i32 0 monotonic ret void @@ -385,6 +387,8 @@ ; X86-ATOM-NEXT: nop ; X86-ATOM-NEXT: nop ; X86-ATOM-NEXT: nop +; X86-ATOM-NEXT: nop +; X86-ATOM-NEXT: nop ; X86-ATOM-NEXT: retl atomicrmw or ptr %p, i32 0 acquire ret void @@ -410,6 +414,8 @@ ; X86-ATOM-NEXT: nop ; X86-ATOM-NEXT: nop ; X86-ATOM-NEXT: nop +; X86-ATOM-NEXT: nop +; X86-ATOM-NEXT: nop ; X86-ATOM-NEXT: retl atomicrmw or ptr %p, i32 0 release ret void @@ -435,6 +441,8 @@ ; X86-ATOM-NEXT: nop ; X86-ATOM-NEXT: nop ; X86-ATOM-NEXT: nop +; X86-ATOM-NEXT: nop +; X86-ATOM-NEXT: nop ; X86-ATOM-NEXT: retl atomicrmw or ptr %p, i32 0 acq_rel ret void Index: llvm/unittests/MIR/MachineMetadata.cpp =================================================================== --- llvm/unittests/MIR/MachineMetadata.cpp +++ llvm/unittests/MIR/MachineMetadata.cpp @@ -334,7 +334,7 @@ LIFETIME_END 0 PSEUDO_PROBE 6699318081062747564, 1, 0, 0 $xmm0 = ARITH_FENCE $xmm0 - Int_MemBarrier + MEMBARRIER ... )MIR";