diff --git a/llvm/lib/Target/XCore/XCoreISelLowering.cpp b/llvm/lib/Target/XCore/XCoreISelLowering.cpp index b3dd4de2a769c..80edad58985b9 100644 --- a/llvm/lib/Target/XCore/XCoreISelLowering.cpp +++ b/llvm/lib/Target/XCore/XCoreISelLowering.cpp @@ -147,12 +147,7 @@ XCoreTargetLowering::XCoreTargetLowering(const TargetMachine &TM, setOperationAction(ISD::EH_RETURN, MVT::Other, Custom); setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i32, Custom); - // Atomic operations - // We request a fence for ATOMIC_* instructions, to reduce them to Monotonic. - // As we are always Sequential Consistent, an ATOMIC_FENCE becomes a no OP. setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom); - setOperationAction(ISD::ATOMIC_LOAD, MVT::i32, Custom); - setOperationAction(ISD::ATOMIC_STORE, MVT::i32, Custom); // TRAMPOLINE is custom lowered. setOperationAction(ISD::INIT_TRAMPOLINE, MVT::Other, Custom); @@ -171,6 +166,9 @@ XCoreTargetLowering::XCoreTargetLowering(const TargetMachine &TM, setMinFunctionAlignment(Align(2)); setPrefFunctionAlignment(Align(4)); + + // This target doesn't implement native atomics. + setMaxAtomicSizeInBitsSupported(0); } bool XCoreTargetLowering::isZExtFree(SDValue Val, EVT VT2) const { @@ -215,9 +213,8 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const { case ISD::INIT_TRAMPOLINE: return LowerINIT_TRAMPOLINE(Op, DAG); case ISD::ADJUST_TRAMPOLINE: return LowerADJUST_TRAMPOLINE(Op, DAG); case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); - case ISD::ATOMIC_FENCE: return LowerATOMIC_FENCE(Op, DAG); - case ISD::ATOMIC_LOAD: return LowerATOMIC_LOAD(Op, DAG); - case ISD::ATOMIC_STORE: return LowerATOMIC_STORE(Op, DAG); + case ISD::ATOMIC_FENCE: + return LowerATOMIC_FENCE(Op, DAG); default: llvm_unreachable("unimplemented operand"); } @@ -928,88 +925,6 @@ LowerATOMIC_FENCE(SDValue Op, SelectionDAG &DAG) const { return DAG.getNode(ISD::MEMBARRIER, DL, MVT::Other, Op.getOperand(0)); } -SDValue XCoreTargetLowering:: -LowerATOMIC_LOAD(SDValue Op, SelectionDAG &DAG) const { - AtomicSDNode *N = cast(Op); - assert(N->getOpcode() == ISD::ATOMIC_LOAD && "Bad Atomic OP"); - assert((N->getSuccessOrdering() == AtomicOrdering::Unordered || - N->getSuccessOrdering() == AtomicOrdering::Monotonic) && - "shouldInsertFencesForAtomic(true) expects unordered / monotonic"); - if (N->getMemoryVT() == MVT::i32) { - if (N->getAlign() < Align(4)) - report_fatal_error("atomic load must be aligned"); - return DAG.getLoad(getPointerTy(DAG.getDataLayout()), SDLoc(Op), - N->getChain(), N->getBasePtr(), N->getPointerInfo(), - N->getAlign(), N->getMemOperand()->getFlags(), - N->getAAInfo(), N->getRanges()); - } - if (N->getMemoryVT() == MVT::i16) { - if (N->getAlign() < Align(2)) - report_fatal_error("atomic load must be aligned"); - return DAG.getExtLoad(ISD::EXTLOAD, SDLoc(Op), MVT::i32, N->getChain(), - N->getBasePtr(), N->getPointerInfo(), MVT::i16, - N->getAlign(), N->getMemOperand()->getFlags(), - N->getAAInfo()); - } - if (N->getMemoryVT() == MVT::i8) - return DAG.getExtLoad(ISD::EXTLOAD, SDLoc(Op), MVT::i32, N->getChain(), - N->getBasePtr(), N->getPointerInfo(), MVT::i8, - N->getAlign(), N->getMemOperand()->getFlags(), - N->getAAInfo()); - return SDValue(); -} - -SDValue XCoreTargetLowering:: -LowerATOMIC_STORE(SDValue Op, SelectionDAG &DAG) const { - AtomicSDNode *N = cast(Op); - assert(N->getOpcode() == ISD::ATOMIC_STORE && "Bad Atomic OP"); - assert((N->getSuccessOrdering() == AtomicOrdering::Unordered || - N->getSuccessOrdering() == AtomicOrdering::Monotonic) && - "shouldInsertFencesForAtomic(true) expects unordered / monotonic"); - if (N->getMemoryVT() == MVT::i32) { - if (N->getAlign() < Align(4)) - report_fatal_error("atomic store must be aligned"); - return DAG.getStore(N->getChain(), SDLoc(Op), N->getVal(), N->getBasePtr(), - N->getPointerInfo(), N->getAlign(), - N->getMemOperand()->getFlags(), N->getAAInfo()); - } - if (N->getMemoryVT() == MVT::i16) { - if (N->getAlign() < Align(2)) - report_fatal_error("atomic store must be aligned"); - return DAG.getTruncStore(N->getChain(), SDLoc(Op), N->getVal(), - N->getBasePtr(), N->getPointerInfo(), MVT::i16, - N->getAlign(), N->getMemOperand()->getFlags(), - N->getAAInfo()); - } - if (N->getMemoryVT() == MVT::i8) - return DAG.getTruncStore(N->getChain(), SDLoc(Op), N->getVal(), - N->getBasePtr(), N->getPointerInfo(), MVT::i8, - N->getAlign(), N->getMemOperand()->getFlags(), - N->getAAInfo()); - return SDValue(); -} - -MachineMemOperand::Flags -XCoreTargetLowering::getTargetMMOFlags(const Instruction &I) const { - // Because of how we convert atomic_load and atomic_store to normal loads and - // stores in the DAG, we need to ensure that the MMOs are marked volatile - // since DAGCombine hasn't been updated to account for atomic, but non - // volatile loads. (See D57601) - if (auto *SI = dyn_cast(&I)) - if (SI->isAtomic()) - return MachineMemOperand::MOVolatile; - if (auto *LI = dyn_cast(&I)) - if (LI->isAtomic()) - return MachineMemOperand::MOVolatile; - if (auto *AI = dyn_cast(&I)) - if (AI->isAtomic()) - return MachineMemOperand::MOVolatile; - if (auto *AI = dyn_cast(&I)) - if (AI->isAtomic()) - return MachineMemOperand::MOVolatile; - return MachineMemOperand::MONone; -} - //===----------------------------------------------------------------------===// // Calling Convention Implementation //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/XCore/XCoreISelLowering.h b/llvm/lib/Target/XCore/XCoreISelLowering.h index cfd0619cba8fd..eaa36d40cba92 100644 --- a/llvm/lib/Target/XCore/XCoreISelLowering.h +++ b/llvm/lib/Target/XCore/XCoreISelLowering.h @@ -181,11 +181,6 @@ namespace llvm { SDValue LowerADJUST_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const; SDValue LowerINTRINSIC_WO_CHAIN(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; - - MachineMemOperand::Flags getTargetMMOFlags( - const Instruction &I) const override; // Inline asm support std::pair @@ -219,14 +214,10 @@ namespace llvm { const SmallVectorImpl &OutVals, const SDLoc &dl, SelectionDAG &DAG) const override; - bool - CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, - bool isVarArg, - const SmallVectorImpl &ArgsFlags, - LLVMContext &Context) const override; - bool shouldInsertFencesForAtomic(const Instruction *I) const override { - return true; - } + bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, + bool isVarArg, + const SmallVectorImpl &ArgsFlags, + LLVMContext &Context) const override; }; } diff --git a/llvm/test/CodeGen/XCore/atomic.ll b/llvm/test/CodeGen/XCore/atomic.ll index 02cef0722fc01..8c11e43f52acb 100644 --- a/llvm/test/CodeGen/XCore/atomic.ll +++ b/llvm/test/CodeGen/XCore/atomic.ll @@ -21,71 +21,23 @@ define void @atomicloadstore() nounwind { entry: ; CHECK-LABEL: atomicloadstore -; CHECK: ldw r[[R0:[0-9]+]], dp[pool] -; CHECK-NEXT: ldaw r[[R1:[0-9]+]], dp[pool] -; CHECK-NEXT: #MEMBARRIER -; CHECK-NEXT: ldc r[[R2:[0-9]+]], 0 - %0 = load atomic i32, ptr @pool acquire, align 4 +; CHECK: __atomic_load_4 + %0 = load atomic i32, ptr @pool seq_cst, align 4 -; CHECK-NEXT: ld16s r3, r[[R1]][r[[R2]]] -; CHECK-NEXT: #MEMBARRIER - %1 = load atomic i16, ptr @pool acquire, align 2 +; CHECK: __atomic_load_2 + %1 = load atomic i16, ptr @pool seq_cst, align 2 -; CHECK-NEXT: ld8u r11, r[[R1]][r[[R2]]] -; CHECK-NEXT: #MEMBARRIER - %2 = load atomic i8, ptr @pool acquire, align 1 +; CHECK: __atomic_load_1 + %2 = load atomic i8, ptr @pool seq_cst, align 1 -; CHECK-NEXT: ldw r4, dp[pool] -; CHECK-NEXT: #MEMBARRIER - %3 = load atomic i32, ptr @pool seq_cst, align 4 +; CHECK: __atomic_store_4 + store atomic i32 %0, ptr @pool seq_cst, align 4 -; CHECK-NEXT: ld16s r5, r[[R1]][r[[R2]]] -; CHECK-NEXT: #MEMBARRIER - %4 = load atomic i16, ptr @pool seq_cst, align 2 +; CHECK: __atomic_store_2 + store atomic i16 %1, ptr @pool seq_cst, align 2 -; CHECK-NEXT: ld8u r6, r[[R1]][r[[R2]]] -; CHECK-NEXT: #MEMBARRIER - %5 = load atomic i8, ptr @pool seq_cst, align 1 - -; CHECK-NEXT: #MEMBARRIER -; CHECK-NEXT: stw r[[R0]], dp[pool] - store atomic i32 %0, ptr @pool release, align 4 - -; CHECK-NEXT: #MEMBARRIER -; CHECK-NEXT: st16 r3, r[[R1]][r[[R2]]] - store atomic i16 %1, ptr @pool release, align 2 - -; CHECK-NEXT: #MEMBARRIER -; CHECK-NEXT: st8 r11, r[[R1]][r[[R2]]] - store atomic i8 %2, ptr @pool release, align 1 - -; CHECK-NEXT: #MEMBARRIER -; CHECK-NEXT: stw r4, dp[pool] -; CHECK-NEXT: #MEMBARRIER - store atomic i32 %3, ptr @pool seq_cst, align 4 - -; CHECK-NEXT: #MEMBARRIER -; CHECK-NEXT: st16 r5, r[[R1]][r[[R2]]] -; CHECK-NEXT: #MEMBARRIER - store atomic i16 %4, ptr @pool seq_cst, align 2 - -; CHECK-NEXT: #MEMBARRIER -; CHECK-NEXT: st8 r6, r[[R1]][r[[R2]]] -; CHECK-NEXT: #MEMBARRIER - store atomic i8 %5, ptr @pool seq_cst, align 1 - -; CHECK-NEXT: ldw r[[R0]], dp[pool] -; CHECK-NEXT: stw r[[R0]], dp[pool] -; CHECK-NEXT: ld16s r[[R0]], r[[R1]][r[[R2]]] -; CHECK-NEXT: st16 r[[R0]], r[[R1]][r[[R2]]] -; CHECK-NEXT: ld8u r[[R0]], r[[R1]][r[[R2]]] -; CHECK-NEXT: st8 r[[R0]], r[[R1]][r[[R2]]] - %6 = load atomic i32, ptr @pool monotonic, align 4 - store atomic i32 %6, ptr @pool monotonic, align 4 - %7 = load atomic i16, ptr @pool monotonic, align 2 - store atomic i16 %7, ptr @pool monotonic, align 2 - %8 = load atomic i8, ptr @pool monotonic, align 1 - store atomic i8 %8, ptr @pool monotonic, align 1 +; CHECK: __atomic_store_1 + store atomic i8 %2, ptr @pool seq_cst, align 1 ret void }