mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-01 09:18:30 +00:00
Code generation for 'fence' instruction.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@136283 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
144da2c8f0
commit
1464846801
@ -592,6 +592,11 @@ namespace ISD {
|
||||
// and produces an output chain.
|
||||
MEMBARRIER,
|
||||
|
||||
// OUTCHAIN = ATOMIC_FENCE(INCHAIN, ordering, scope)
|
||||
// This corresponds to the fence instruction. It takes an input chain, and
|
||||
// two integer constants: an AtomicOrdering and a SynchronizationScope.
|
||||
ATOMIC_FENCE,
|
||||
|
||||
// Val, OUTCHAIN = ATOMIC_CMP_SWAP(INCHAIN, ptr, cmp, swap)
|
||||
// this corresponds to the atomic.lcs intrinsic.
|
||||
// cmp is compared to *ptr, and if equal, swap is stored in *ptr.
|
||||
|
@ -205,6 +205,9 @@ def SDTMemBarrier : SDTypeProfile<0, 5, [ // memory barier
|
||||
SDTCisSameAs<0,1>, SDTCisSameAs<0,2>, SDTCisSameAs<0,3>, SDTCisSameAs<0,4>,
|
||||
SDTCisInt<0>
|
||||
]>;
|
||||
def SDTAtomicFence : SDTypeProfile<0, 2, [
|
||||
SDTCisSameAs<0,1>, SDTCisPtrTy<0>
|
||||
]>;
|
||||
def SDTAtomic3 : SDTypeProfile<1, 3, [
|
||||
SDTCisSameAs<0,2>, SDTCisSameAs<0,3>, SDTCisInt<0>, SDTCisPtrTy<1>
|
||||
]>;
|
||||
@ -397,6 +400,9 @@ def prefetch : SDNode<"ISD::PREFETCH" , SDTPrefetch,
|
||||
def membarrier : SDNode<"ISD::MEMBARRIER" , SDTMemBarrier,
|
||||
[SDNPHasChain, SDNPSideEffect]>;
|
||||
|
||||
def atomic_fence : SDNode<"ISD::ATOMIC_FENCE" , SDTAtomicFence,
|
||||
[SDNPHasChain, SDNPSideEffect]>;
|
||||
|
||||
def atomic_cmp_swap : SDNode<"ISD::ATOMIC_CMP_SWAP" , SDTAtomic3,
|
||||
[SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>;
|
||||
def atomic_load_add : SDNode<"ISD::ATOMIC_LOAD_ADD" , SDTAtomic2,
|
||||
|
@ -2955,8 +2955,10 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
|
||||
Results.push_back(DAG.getConstant(0, MVT::i32));
|
||||
Results.push_back(Node->getOperand(0));
|
||||
break;
|
||||
case ISD::ATOMIC_FENCE:
|
||||
case ISD::MEMBARRIER: {
|
||||
// If the target didn't lower this, lower it to '__sync_synchronize()' call
|
||||
// FIXME: handle "fence singlethread" more efficiently.
|
||||
TargetLowering::ArgListTy Args;
|
||||
std::pair<SDValue, SDValue> CallResult =
|
||||
TLI.LowerCallTo(Node->getOperand(0), Type::getVoidTy(*DAG.getContext()),
|
||||
|
@ -5769,6 +5769,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
|
||||
#endif
|
||||
case ISD::PREFETCH: return "Prefetch";
|
||||
case ISD::MEMBARRIER: return "MemBarrier";
|
||||
case ISD::ATOMIC_FENCE: return "AtomicFence";
|
||||
case ISD::ATOMIC_CMP_SWAP: return "AtomicCmpSwap";
|
||||
case ISD::ATOMIC_SWAP: return "AtomicSwap";
|
||||
case ISD::ATOMIC_LOAD_ADD: return "AtomicLoadAdd";
|
||||
|
@ -3221,7 +3221,12 @@ void SelectionDAGBuilder::visitStore(const StoreInst &I) {
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::visitFence(const FenceInst &I) {
|
||||
llvm_unreachable("Not implemented yet");
|
||||
DebugLoc dl = getCurDebugLoc();
|
||||
SDValue Ops[3];
|
||||
Ops[0] = getRoot();
|
||||
Ops[1] = DAG.getConstant(I.getOrdering(), TLI.getPointerTy());
|
||||
Ops[2] = DAG.getConstant(I.getSynchScope(), TLI.getPointerTy());
|
||||
DAG.setRoot(DAG.getNode(ISD::ATOMIC_FENCE, dl, MVT::Other, Ops, 3));
|
||||
}
|
||||
|
||||
/// visitTargetIntrinsic - Lower a call of a target intrinsic to an INTRINSIC
|
||||
|
@ -601,9 +601,11 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
|
||||
// membarrier needs custom lowering; the rest are legal and handled
|
||||
// normally.
|
||||
setOperationAction(ISD::MEMBARRIER, MVT::Other, Custom);
|
||||
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
|
||||
} else {
|
||||
// Set them all for expansion, which will force libcalls.
|
||||
setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
|
||||
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand);
|
||||
setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i8, Expand);
|
||||
setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i16, Expand);
|
||||
setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32, Expand);
|
||||
@ -2277,6 +2279,33 @@ static SDValue LowerMEMBARRIER(SDValue Op, SelectionDAG &DAG,
|
||||
DAG.getConstant(DMBOpt, MVT::i32));
|
||||
}
|
||||
|
||||
|
||||
static SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG,
|
||||
const ARMSubtarget *Subtarget) {
|
||||
// FIXME: handle "fence singlethread" more efficiently.
|
||||
DebugLoc dl = Op.getDebugLoc();
|
||||
if (!Subtarget->hasDataBarrier()) {
|
||||
// Some ARMv6 cpus can support data barriers with an mcr instruction.
|
||||
// Thumb1 and pre-v6 ARM mode use a libcall instead and should never get
|
||||
// here.
|
||||
assert(Subtarget->hasV6Ops() && !Subtarget->isThumb() &&
|
||||
"Unexpected ISD::MEMBARRIER encountered. Should be libcall!");
|
||||
return DAG.getNode(ARMISD::MEMBARRIER_MCR, dl, MVT::Other, Op.getOperand(0),
|
||||
DAG.getConstant(0, MVT::i32));
|
||||
}
|
||||
|
||||
AtomicOrdering FenceOrdering = static_cast<AtomicOrdering>(
|
||||
cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue());
|
||||
|
||||
ARM_MB::MemBOpt DMBOpt;
|
||||
if (FenceOrdering == Release)
|
||||
DMBOpt = ARM_MB::ISHST;
|
||||
else
|
||||
DMBOpt = ARM_MB::ISH;
|
||||
return DAG.getNode(ARMISD::MEMBARRIER, dl, MVT::Other, Op.getOperand(0),
|
||||
DAG.getConstant(DMBOpt, MVT::i32));
|
||||
}
|
||||
|
||||
static SDValue LowerPREFETCH(SDValue Op, SelectionDAG &DAG,
|
||||
const ARMSubtarget *Subtarget) {
|
||||
// ARM pre v5TE and Thumb1 does not have preload instructions.
|
||||
@ -4834,6 +4863,7 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
||||
case ISD::BR_JT: return LowerBR_JT(Op, DAG);
|
||||
case ISD::VASTART: return LowerVASTART(Op, DAG);
|
||||
case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG, Subtarget);
|
||||
case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG, Subtarget);
|
||||
case ISD::PREFETCH: return LowerPREFETCH(Op, DAG, Subtarget);
|
||||
case ISD::SINT_TO_FP:
|
||||
case ISD::UINT_TO_FP: return LowerINT_TO_FP(Op, DAG);
|
||||
|
@ -607,6 +607,8 @@ def : Pat<(membarrier (i64 imm), (i64 imm), (i64 imm), (i64 1), (i64 imm)),
|
||||
def : Pat<(membarrier (i64 imm), (i64 imm), (i64 imm), (i64 imm), (i64 imm)),
|
||||
(MB)>;
|
||||
|
||||
def : Pat<(atomic_fence (imm), (imm)), (MB)>;
|
||||
|
||||
//Basic Floating point ops
|
||||
|
||||
//Floats
|
||||
|
@ -99,6 +99,7 @@ BlackfinTargetLowering::BlackfinTargetLowering(TargetMachine &TM)
|
||||
|
||||
// Blackfin has no intrinsics for these particular operations.
|
||||
setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
|
||||
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand);
|
||||
setOperationAction(ISD::BSWAP, MVT::i32, Expand);
|
||||
|
||||
setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand);
|
||||
|
@ -174,6 +174,7 @@ SPUTargetLowering::SPUTargetLowering(SPUTargetMachine &TM)
|
||||
|
||||
// SPU has no intrinsics for these particular operations:
|
||||
setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
|
||||
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand);
|
||||
|
||||
// SPU has no division/remainder instructions
|
||||
setOperationAction(ISD::SREM, MVT::i8, Expand);
|
||||
|
@ -877,6 +877,9 @@ def : Pat<(zextloadi8 xaddr:$addr), (i32 (LBU xaddr:$addr))>;
|
||||
// Peepholes
|
||||
def : Pat<(store (i32 0), iaddr:$dst), (SWI (i32 R0), iaddr:$dst)>;
|
||||
|
||||
// Atomic fence
|
||||
def : Pat<(atomic_fence (imm), (imm)), (MEMBARRIER)>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Floating Point Support
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -160,7 +160,9 @@ MipsTargetLowering(MipsTargetMachine &TM)
|
||||
// Use the default for now
|
||||
setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
|
||||
setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
|
||||
|
||||
setOperationAction(ISD::MEMBARRIER, MVT::Other, Custom);
|
||||
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
|
||||
|
||||
if (Subtarget->isSingleFloat())
|
||||
setOperationAction(ISD::SELECT_CC, MVT::f64, Expand);
|
||||
@ -529,6 +531,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const
|
||||
case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG);
|
||||
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
|
||||
case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG);
|
||||
case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG);
|
||||
}
|
||||
return SDValue();
|
||||
}
|
||||
@ -1536,6 +1539,16 @@ SDValue MipsTargetLowering::LowerMEMBARRIER(SDValue Op,
|
||||
DAG.getConstant(SType, MVT::i32));
|
||||
}
|
||||
|
||||
SDValue MipsTargetLowering::LowerATOMIC_FENCE(SDValue Op,
|
||||
SelectionDAG& DAG) const {
|
||||
// FIXME: Need pseudo-fence for 'singlethread' fences
|
||||
// FIXME: Set SType for weaker fences where supported/appropriate.
|
||||
unsigned SType = 0;
|
||||
DebugLoc dl = Op.getDebugLoc();
|
||||
return DAG.getNode(MipsISD::Sync, dl, MVT::Other, Op.getOperand(0),
|
||||
DAG.getConstant(SType, MVT::i32));
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Calling Convention Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -131,6 +131,7 @@ namespace llvm {
|
||||
SDValue LowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerMEMBARRIER(SDValue Op, SelectionDAG& DAG) const;
|
||||
SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const;
|
||||
|
||||
virtual SDValue
|
||||
LowerFormalArguments(SDValue Chain,
|
||||
|
@ -1472,5 +1472,7 @@ def : Pat<(membarrier (i32 imm /*ll*/),
|
||||
(i32 imm /*device*/)),
|
||||
(SYNC)>;
|
||||
|
||||
def : Pat<(atomic_fence (imm), (imm)), (SYNC)>;
|
||||
|
||||
include "PPCInstrAltivec.td"
|
||||
include "PPCInstr64Bit.td"
|
||||
|
@ -748,8 +748,10 @@ SparcTargetLowering::SparcTargetLowering(TargetMachine &TM)
|
||||
setOperationAction(ISD::SELECT_CC, MVT::f32, Custom);
|
||||
setOperationAction(ISD::SELECT_CC, MVT::f64, Custom);
|
||||
|
||||
// SPARC has no intrinsics for these particular operations.
|
||||
// FIXME: There are instructions available for ATOMIC_FENCE
|
||||
// on SparcV8 and later.
|
||||
setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
|
||||
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand);
|
||||
|
||||
setOperationAction(ISD::FSIN , MVT::f64, Expand);
|
||||
setOperationAction(ISD::FCOS , MVT::f64, Expand);
|
||||
|
@ -449,8 +449,8 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
|
||||
if (Subtarget->hasXMM())
|
||||
setOperationAction(ISD::PREFETCH , MVT::Other, Legal);
|
||||
|
||||
// We may not have a libcall for MEMBARRIER so we should lower this.
|
||||
setOperationAction(ISD::MEMBARRIER , MVT::Other, Custom);
|
||||
setOperationAction(ISD::ATOMIC_FENCE , MVT::Other, Custom);
|
||||
|
||||
// On X86 and X86-64, atomic operations are lowered to locked instructions.
|
||||
// Locked instructions, in turn, have implicit fence semantics (all memory
|
||||
@ -9407,6 +9407,45 @@ SDValue X86TargetLowering::LowerMEMBARRIER(SDValue Op, SelectionDAG &DAG) const{
|
||||
return DAG.getNode(X86ISD::MFENCE, dl, MVT::Other, Op.getOperand(0));
|
||||
}
|
||||
|
||||
SDValue X86TargetLowering::LowerATOMIC_FENCE(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
DebugLoc dl = Op.getDebugLoc();
|
||||
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) {
|
||||
// Use mfence if we have SSE2 or we're on x86-64 (even if we asked for
|
||||
// no-sse2). There isn't any reason to disable it if the target processor
|
||||
// supports it.
|
||||
if (Subtarget->hasSSE2() || Subtarget->is64Bit())
|
||||
return DAG.getNode(X86ISD::MFENCE, dl, MVT::Other, Op.getOperand(0));
|
||||
|
||||
SDValue Chain = Op.getOperand(0);
|
||||
SDValue Zero = DAG.getConstant(0, MVT::i32);
|
||||
SDValue Ops[] = {
|
||||
DAG.getRegister(X86::ESP, MVT::i32), // Base
|
||||
DAG.getTargetConstant(1, MVT::i8), // Scale
|
||||
DAG.getRegister(0, MVT::i32), // Index
|
||||
DAG.getTargetConstant(0, MVT::i32), // Disp
|
||||
DAG.getRegister(0, MVT::i32), // Segment.
|
||||
Zero,
|
||||
Chain
|
||||
};
|
||||
SDNode *Res =
|
||||
DAG.getMachineNode(X86::OR32mrLocked, dl, MVT::Other, Ops,
|
||||
array_lengthof(Ops));
|
||||
return SDValue(Res, 0);
|
||||
}
|
||||
|
||||
// MEMBARRIER is a compiler barrier; it codegens to a no-op.
|
||||
return DAG.getNode(X86ISD::MEMBARRIER, dl, MVT::Other, Op.getOperand(0));
|
||||
}
|
||||
|
||||
|
||||
SDValue X86TargetLowering::LowerCMP_SWAP(SDValue Op, SelectionDAG &DAG) const {
|
||||
EVT T = Op.getValueType();
|
||||
DebugLoc DL = Op.getDebugLoc();
|
||||
@ -9526,6 +9565,7 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
||||
default: llvm_unreachable("Should not custom lower this!");
|
||||
case ISD::SIGN_EXTEND_INREG: return LowerSIGN_EXTEND_INREG(Op,DAG);
|
||||
case ISD::MEMBARRIER: return LowerMEMBARRIER(Op,DAG);
|
||||
case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op,DAG);
|
||||
case ISD::ATOMIC_CMP_SWAP: return LowerCMP_SWAP(Op,DAG);
|
||||
case ISD::ATOMIC_LOAD_SUB: return LowerLOAD_SUB(Op,DAG);
|
||||
case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG);
|
||||
@ -9849,6 +9889,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case X86ISD::VASTART_SAVE_XMM_REGS: return "X86ISD::VASTART_SAVE_XMM_REGS";
|
||||
case X86ISD::VAARG_64: return "X86ISD::VAARG_64";
|
||||
case X86ISD::WIN_ALLOCA: return "X86ISD::WIN_ALLOCA";
|
||||
case X86ISD::MEMBARRIER: return "X86ISD::MEMBARRIER";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -829,6 +829,7 @@ namespace llvm {
|
||||
SDValue LowerLOAD_SUB(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerREADCYCLECOUNTER(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerMEMBARRIER(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const;
|
||||
SDValue LowerSIGN_EXTEND_INREG(SDValue Op, SelectionDAG &DAG) const;
|
||||
|
||||
// Utility functions to help LowerVECTOR_SHUFFLE
|
||||
|
Loading…
Reference in New Issue
Block a user