[llvm] r351778 - IR: Add fp operations to atomicrmw

Chandler Carruth via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 22 02:30:03 PST 2019


On Mon, Jan 21, 2019 at 7:32 PM Matt Arsenault via llvm-commits <
llvm-commits at lists.llvm.org> wrote:

> Author: arsenm
> Date: Mon Jan 21 19:32:36 2019
> New Revision: 351778
>
> URL: http://llvm.org/viewvc/llvm-project?rev=351778&view=rev
> Log:
> IR: Add fp operations to atomicrmw
>
> Add just fadd/fsub for now.
>
> Added:
>     llvm/trunk/test/Assembler/invalid-atomicrmw-fadd-must-be-fp-type.ll
>     llvm/trunk/test/Assembler/invalid-atomicrmw-fsub-must-be-fp-type.ll
>     llvm/trunk/test/Transforms/AtomicExpand/AArch64/atomicrmw-fp.ll
>     llvm/trunk/test/Transforms/AtomicExpand/ARM/atomicrmw-fp.ll
>     llvm/trunk/test/Transforms/AtomicExpand/Hexagon/
>     llvm/trunk/test/Transforms/AtomicExpand/Hexagon/atomicrmw-fp.ll
>     llvm/trunk/test/Transforms/AtomicExpand/Hexagon/lit.local.cfg
>     llvm/trunk/test/Transforms/AtomicExpand/Mips/
>     llvm/trunk/test/Transforms/AtomicExpand/Mips/atomicrmw-fp.ll
>     llvm/trunk/test/Transforms/AtomicExpand/Mips/lit.local.cfg
>     llvm/trunk/test/Transforms/AtomicExpand/RISCV/
>     llvm/trunk/test/Transforms/AtomicExpand/RISCV/atomicrmw-fp.ll
>     llvm/trunk/test/Transforms/AtomicExpand/RISCV/lit.local.cfg
>

When changing RISCV, its important to enable the target as the bots won't.
The `atomicrmw-fp.ll` test fails here but only when asserts are enabled.
Plus the build had an issue that Alex fixed in r351782. I've had to revert
all of this because after several attempts to make this test pass reliably
I couldn't do so... It only fails with asserts enabled, and the generated
code is non-trivially different between the asserts and non-asserts build
making it largely impossible to update the test cleanly. And since the
patch actually changes RISCV, it seems bad to just disable testing here. So
ultimately, I'm reverting to green in r351796.


> Modified:
>     llvm/trunk/docs/LangRef.rst
>     llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
>     llvm/trunk/include/llvm/CodeGen/TargetLowering.h
>     llvm/trunk/include/llvm/IR/Instructions.h
>     llvm/trunk/lib/AsmParser/LLParser.cpp
>     llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
>     llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
>     llvm/trunk/lib/CodeGen/AtomicExpandPass.cpp
>     llvm/trunk/lib/IR/Instructions.cpp
>     llvm/trunk/lib/IR/Verifier.cpp
>     llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp
>     llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
>     llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp
>     llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp
>     llvm/trunk/test/Assembler/atomic.ll
>     llvm/trunk/test/Bitcode/compatibility.ll
>
> Modified: llvm/trunk/docs/LangRef.rst
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=351778&r1=351777&r2=351778&view=diff
>
> ==============================================================================
> --- llvm/trunk/docs/LangRef.rst (original)
> +++ llvm/trunk/docs/LangRef.rst Mon Jan 21 19:32:36 2019
> @@ -8667,15 +8667,18 @@ operation. The operation must be one of
>  -  min
>  -  umax
>  -  umin
> +-  fadd
> +-  fsub
>
>  For most of these operations, the type of '<value>' must be an integer
>  type whose bit width is a power of two greater than or equal to eight
>  and less than or equal to a target-specific size limit. For xchg, this
>  may also be a floating point type with the same size constraints as
> -integers. The type of the '``<pointer>``' operand must be a pointer to
> -that type. If the ``atomicrmw`` is marked as ``volatile``, then the
> -optimizer is not allowed to modify the number or order of execution of
> -this ``atomicrmw`` with other :ref:`volatile operations <volatile>`.
> +integers.  For fadd/fsub, this must be a floating point type.  The
> +type of the '``<pointer>``' operand must be a pointer to that type. If
> +the ``atomicrmw`` is marked as ``volatile``, then the optimizer is not
> +allowed to modify the number or order of execution of this
> +``atomicrmw`` with other :ref:`volatile operations <volatile>`.
>
>  A ``atomicrmw`` instruction can also take an optional
>  ":ref:`syncscope <syncscope>`" argument.
> @@ -8701,6 +8704,8 @@ operation argument:
>     comparison)
>  -  umin: ``*ptr = *ptr < val ? *ptr : val`` (using an unsigned
>     comparison)
> +- fadd: ``*ptr = *ptr + val`` (using floating point arithmetic)
> +- fsub: ``*ptr = *ptr - val`` (using floating point arithmetic)
>
>  Example:
>  """"""""
>
> Modified: llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h?rev=351778&r1=351777&r2=351778&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h (original)
> +++ llvm/trunk/include/llvm/Bitcode/LLVMBitCodes.h Mon Jan 21 19:32:36 2019
> @@ -406,7 +406,9 @@ enum RMWOperations {
>    RMW_MAX = 7,
>    RMW_MIN = 8,
>    RMW_UMAX = 9,
> -  RMW_UMIN = 10
> +  RMW_UMIN = 10,
> +  RMW_FADD = 11,
> +  RMW_FSUB = 12
>  };
>
>  /// OverflowingBinaryOperatorOptionalFlags - Flags for serializing
>
> Modified: llvm/trunk/include/llvm/CodeGen/TargetLowering.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/TargetLowering.h?rev=351778&r1=351777&r2=351778&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/TargetLowering.h (original)
> +++ llvm/trunk/include/llvm/CodeGen/TargetLowering.h Mon Jan 21 19:32:36
> 2019
> @@ -1715,8 +1715,9 @@ public:
>
>    /// Returns how the IR-level AtomicExpand pass should expand the given
>    /// AtomicRMW, if at all. Default is to never expand.
> -  virtual AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst *)
> const {
> -    return AtomicExpansionKind::None;
> +  virtual AtomicExpansionKind shouldExpandAtomicRMWInIR(AtomicRMWInst
> *RMW) const {
> +    return RMW->isFloatingPointOperation() ?
> +      AtomicExpansionKind::CmpXChg : AtomicExpansionKind::None;
>    }
>
>    /// On some platforms, an AtomicRMW that never actually modifies the
> value
>
> Modified: llvm/trunk/include/llvm/IR/Instructions.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Instructions.h?rev=351778&r1=351777&r2=351778&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/IR/Instructions.h (original)
> +++ llvm/trunk/include/llvm/IR/Instructions.h Mon Jan 21 19:32:36 2019
> @@ -724,8 +724,14 @@ public:
>      /// *p = old <unsigned v ? old : v
>      UMin,
>
> +    /// *p = old + v
> +    FAdd,
> +
> +    /// *p = old - v
> +    FSub,
> +
>      FIRST_BINOP = Xchg,
> -    LAST_BINOP = UMin,
> +    LAST_BINOP = FSub,
>      BAD_BINOP
>    };
>
> @@ -747,6 +753,16 @@ public:
>
>    static StringRef getOperationName(BinOp Op);
>
> +  static bool isFPOperation(BinOp Op) {
> +    switch (Op) {
> +    case AtomicRMWInst::FAdd:
> +    case AtomicRMWInst::FSub:
> +      return true;
> +    default:
> +      return false;
> +    }
> +  }
> +
>    void setOperation(BinOp Operation) {
>      unsigned short SubclassData = getSubclassDataFromInstruction();
>      setInstructionSubclassData((SubclassData & 31) |
> @@ -804,6 +820,10 @@ public:
>      return getPointerOperand()->getType()->getPointerAddressSpace();
>    }
>
> +  bool isFloatingPointOperation() const {
> +    return isFPOperation(getOperation());
> +  }
> +
>    // Methods for support type inquiry through isa, cast, and dyn_cast:
>    static bool classof(const Instruction *I) {
>      return I->getOpcode() == Instruction::AtomicRMW;
>
> Modified: llvm/trunk/lib/AsmParser/LLParser.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=351778&r1=351777&r2=351778&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/AsmParser/LLParser.cpp (original)
> +++ llvm/trunk/lib/AsmParser/LLParser.cpp Mon Jan 21 19:32:36 2019
> @@ -6815,6 +6815,7 @@ int LLParser::ParseAtomicRMW(Instruction
>    AtomicOrdering Ordering = AtomicOrdering::NotAtomic;
>    SyncScope::ID SSID = SyncScope::System;
>    bool isVolatile = false;
> +  bool IsFP = false;
>    AtomicRMWInst::BinOp Operation;
>
>    if (EatIfPresent(lltok::kw_volatile))
> @@ -6833,6 +6834,14 @@ int LLParser::ParseAtomicRMW(Instruction
>    case lltok::kw_min: Operation = AtomicRMWInst::Min; break;
>    case lltok::kw_umax: Operation = AtomicRMWInst::UMax; break;
>    case lltok::kw_umin: Operation = AtomicRMWInst::UMin; break;
> +  case lltok::kw_fadd:
> +    Operation = AtomicRMWInst::FAdd;
> +    IsFP = true;
> +    break;
> +  case lltok::kw_fsub:
> +    Operation = AtomicRMWInst::FSub;
> +    IsFP = true;
> +    break;
>    }
>    Lex.Lex();  // Eat the operation.
>
> @@ -6849,18 +6858,25 @@ int LLParser::ParseAtomicRMW(Instruction
>    if (cast<PointerType>(Ptr->getType())->getElementType() !=
> Val->getType())
>      return Error(ValLoc, "atomicrmw value and pointer type do not match");
>
> -  if (Operation != AtomicRMWInst::Xchg && !Val->getType()->isIntegerTy())
> {
> -    return Error(ValLoc, "atomicrmw " +
> -                 AtomicRMWInst::getOperationName(Operation) +
> -                 " operand must be an integer");
> -  }
> -
> -  if (Operation == AtomicRMWInst::Xchg &&
> -      !Val->getType()->isIntegerTy() &&
> -      !Val->getType()->isFloatingPointTy()) {
> -    return Error(ValLoc, "atomicrmw " +
> -                 AtomicRMWInst::getOperationName(Operation) +
> -                 " operand must be an integer or floating point type");
> +  if (Operation == AtomicRMWInst::Xchg) {
> +    if (!Val->getType()->isIntegerTy() &&
> +        !Val->getType()->isFloatingPointTy()) {
> +      return Error(ValLoc, "atomicrmw " +
> +                   AtomicRMWInst::getOperationName(Operation) +
> +                   " operand must be an integer or floating point type");
> +    }
> +  } else if (IsFP) {
> +    if (!Val->getType()->isFloatingPointTy()) {
> +      return Error(ValLoc, "atomicrmw " +
> +                   AtomicRMWInst::getOperationName(Operation) +
> +                   " operand must be a floating point type");
> +    }
> +  } else {
> +    if (!Val->getType()->isIntegerTy()) {
> +      return Error(ValLoc, "atomicrmw " +
> +                   AtomicRMWInst::getOperationName(Operation) +
> +                   " operand must be an integer");
> +    }
>    }
>
>    unsigned Size = Val->getType()->getPrimitiveSizeInBits();
>
> Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=351778&r1=351777&r2=351778&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
> +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Mon Jan 21 19:32:36
> 2019
> @@ -1034,6 +1034,8 @@ static AtomicRMWInst::BinOp getDecodedRM
>    case bitc::RMW_MIN: return AtomicRMWInst::Min;
>    case bitc::RMW_UMAX: return AtomicRMWInst::UMax;
>    case bitc::RMW_UMIN: return AtomicRMWInst::UMin;
> +  case bitc::RMW_FADD: return AtomicRMWInst::FAdd;
> +  case bitc::RMW_FSUB: return AtomicRMWInst::FSub;
>    }
>  }
>
>
> Modified: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp?rev=351778&r1=351777&r2=351778&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp (original)
> +++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp Mon Jan 21 19:32:36
> 2019
> @@ -559,6 +559,8 @@ static unsigned getEncodedRMWOperation(A
>    case AtomicRMWInst::Min: return bitc::RMW_MIN;
>    case AtomicRMWInst::UMax: return bitc::RMW_UMAX;
>    case AtomicRMWInst::UMin: return bitc::RMW_UMIN;
> +  case AtomicRMWInst::FAdd: return bitc::RMW_FADD;
> +  case AtomicRMWInst::FSub: return bitc::RMW_FSUB;
>    }
>  }
>
>
> Modified: llvm/trunk/lib/CodeGen/AtomicExpandPass.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AtomicExpandPass.cpp?rev=351778&r1=351777&r2=351778&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/AtomicExpandPass.cpp (original)
> +++ llvm/trunk/lib/CodeGen/AtomicExpandPass.cpp Mon Jan 21 19:32:36 2019
> @@ -549,6 +549,10 @@ static Value *performAtomicOp(AtomicRMWI
>    case AtomicRMWInst::UMin:
>      NewVal = Builder.CreateICmpULE(Loaded, Inc);
>      return Builder.CreateSelect(NewVal, Loaded, Inc, "new");
> +  case AtomicRMWInst::FAdd:
> +    return Builder.CreateFAdd(Loaded, Inc, "new");
> +  case AtomicRMWInst::FSub:
> +    return Builder.CreateFSub(Loaded, Inc, "new");
>    default:
>      llvm_unreachable("Unknown atomic op");
>    }
> @@ -1547,6 +1551,8 @@ static ArrayRef<RTLIB::Libcall> GetRMWLi
>    case AtomicRMWInst::Min:
>    case AtomicRMWInst::UMax:
>    case AtomicRMWInst::UMin:
> +  case AtomicRMWInst::FAdd:
> +  case AtomicRMWInst::FSub:
>      // No atomic libcalls are available for max/min/umax/umin.
>      return {};
>    }
>
> Modified: llvm/trunk/lib/IR/Instructions.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Instructions.cpp?rev=351778&r1=351777&r2=351778&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/IR/Instructions.cpp (original)
> +++ llvm/trunk/lib/IR/Instructions.cpp Mon Jan 21 19:32:36 2019
> @@ -1407,6 +1407,10 @@ StringRef AtomicRMWInst::getOperationNam
>      return "umax";
>    case AtomicRMWInst::UMin:
>      return "umin";
> +  case AtomicRMWInst::FAdd:
> +    return "fadd";
> +  case AtomicRMWInst::FSub:
> +    return "fsub";
>    case AtomicRMWInst::BAD_BINOP:
>      return "<invalid operation>";
>    }
>
> Modified: llvm/trunk/lib/IR/Verifier.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=351778&r1=351777&r2=351778&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/IR/Verifier.cpp (original)
> +++ llvm/trunk/lib/IR/Verifier.cpp Mon Jan 21 19:32:36 2019
> @@ -3435,6 +3435,11 @@ void Verifier::visitAtomicRMWInst(Atomic
>             AtomicRMWInst::getOperationName(Op) +
>             " operand must have integer or floating point type!",
>             &RMWI, ElTy);
> +  } else if (AtomicRMWInst::isFPOperation(Op)) {
> +    Assert(ElTy->isFloatingPointTy(), "atomicrmw " +
> +           AtomicRMWInst::getOperationName(Op) +
> +           " operand must have floating point type!",
> +           &RMWI, ElTy);
>    } else {
>      Assert(ElTy->isIntegerTy(), "atomicrmw " +
>             AtomicRMWInst::getOperationName(Op) +
>
> Modified: llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp?rev=351778&r1=351777&r2=351778&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp (original)
> +++ llvm/trunk/lib/Target/AArch64/AArch64ISelLowering.cpp Mon Jan 21
> 19:32:36 2019
> @@ -11600,6 +11600,9 @@ AArch64TargetLowering::shouldExpandAtomi
>  // For the real atomic operations, we have ldxr/stxr up to 128 bits,
>  TargetLowering::AtomicExpansionKind
>  AArch64TargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const
> {
> +  if (AI->isFloatingPointOperation())
> +    return AtomicExpansionKind::CmpXChg;
> +
>    unsigned Size = AI->getType()->getPrimitiveSizeInBits();
>    if (Size > 128) return AtomicExpansionKind::None;
>    // Nand not supported in LSE.
>
> Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=351778&r1=351777&r2=351778&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
> +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Mon Jan 21 19:32:36 2019
> @@ -14645,6 +14645,9 @@ ARMTargetLowering::shouldExpandAtomicLoa
>  // and up to 64 bits on the non-M profiles
>  TargetLowering::AtomicExpansionKind
>  ARMTargetLowering::shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const {
> +  if (AI->isFloatingPointOperation())
> +    return AtomicExpansionKind::CmpXChg;
> +
>    unsigned Size = AI->getType()->getPrimitiveSizeInBits();
>    bool hasAtomicRMW = !Subtarget->isThumb() ||
> Subtarget->hasV8MBaselineOps();
>    return (Size <= (Subtarget->isMClass() ? 32U : 64U) && hasAtomicRMW)
>
> Modified: llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp?rev=351778&r1=351777&r2=351778&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp (original)
> +++ llvm/trunk/lib/Target/Hexagon/HexagonISelLowering.cpp Mon Jan 21
> 19:32:36 2019
> @@ -3110,13 +3110,21 @@ Value *HexagonTargetLowering::emitLoadLi
>        AtomicOrdering Ord) const {
>    BasicBlock *BB = Builder.GetInsertBlock();
>    Module *M = BB->getParent()->getParent();
> -  Type *Ty = cast<PointerType>(Addr->getType())->getElementType();
> +  auto PT = cast<PointerType>(Addr->getType());
> +  Type *Ty = PT->getElementType();
>    unsigned SZ = Ty->getPrimitiveSizeInBits();
>    assert((SZ == 32 || SZ == 64) && "Only 32/64-bit atomic loads
> supported");
>    Intrinsic::ID IntID = (SZ == 32) ? Intrinsic::hexagon_L2_loadw_locked
>                                     : Intrinsic::hexagon_L4_loadd_locked;
> +
> +  PointerType *NewPtrTy
> +    = Builder.getIntNTy(SZ)->getPointerTo(PT->getAddressSpace());
> +  Addr = Builder.CreateBitCast(Addr, NewPtrTy);
> +
>    Value *Fn = Intrinsic::getDeclaration(M, IntID);
> -  return Builder.CreateCall(Fn, Addr, "larx");
> +  Value *Call = Builder.CreateCall(Fn, Addr, "larx");
> +
> +  return Builder.CreateBitCast(Call, Ty);
>  }
>
>  /// Perform a store-conditional operation to Addr. Return the status of
> the
> @@ -3127,10 +3135,17 @@ Value *HexagonTargetLowering::emitStoreC
>    Module *M = BB->getParent()->getParent();
>    Type *Ty = Val->getType();
>    unsigned SZ = Ty->getPrimitiveSizeInBits();
> +
> +  Type *CastTy = Builder.getIntNTy(SZ);
>    assert((SZ == 32 || SZ == 64) && "Only 32/64-bit atomic stores
> supported");
>    Intrinsic::ID IntID = (SZ == 32) ? Intrinsic::hexagon_S2_storew_locked
>                                     : Intrinsic::hexagon_S4_stored_locked;
>    Value *Fn = Intrinsic::getDeclaration(M, IntID);
> +
> +  unsigned AS = Addr->getType()->getPointerAddressSpace();
> +  Addr = Builder.CreateBitCast(Addr, CastTy->getPointerTo(AS));
> +  Val = Builder.CreateBitCast(Val, CastTy);
> +
>    Value *Call = Builder.CreateCall(Fn, {Addr, Val}, "stcx");
>    Value *Cmp = Builder.CreateICmpEQ(Call, Builder.getInt32(0), "");
>    Value *Ext = Builder.CreateZExt(Cmp, Type::getInt32Ty(M->getContext()));
>
> Modified: llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp?rev=351778&r1=351777&r2=351778&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp (original)
> +++ llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp Mon Jan 21 19:32:36
> 2019
> @@ -1823,6 +1823,9 @@ Value *RISCVTargetLowering::emitMaskedAt
>  TargetLowering::AtomicExpansionKind
>  RISCVTargetLowering::shouldExpandAtomicCmpXchgInIR(
>      AtomicCmpXchgInst *CI) const {
> +  if (CI->isFloatingPointOperation())
> +    return AtomicExpansionKind::CmpXChg;
> +
>    unsigned Size =
> CI->getCompareOperand()->getType()->getPrimitiveSizeInBits();
>    if (Size == 8 || Size == 16)
>      return AtomicExpansionKind::MaskedIntrinsic;
>
> Modified: llvm/trunk/test/Assembler/atomic.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/atomic.ll?rev=351778&r1=351777&r2=351778&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Assembler/atomic.ll (original)
> +++ llvm/trunk/test/Assembler/atomic.ll Mon Jan 21 19:32:36 2019
> @@ -39,3 +39,13 @@ define void @f(i32* %x) {
>    fence syncscope("device") seq_cst
>    ret void
>  }
> +
> +define void @fp_atomics(float* %x) {
> + ; CHECK: atomicrmw fadd float* %x, float 1.000000e+00 seq_cst
> +  atomicrmw fadd float* %x, float 1.0 seq_cst
> +
> +  ; CHECK: atomicrmw volatile fadd float* %x, float 1.000000e+00 seq_cst
> +  atomicrmw volatile fadd float* %x, float 1.0 seq_cst
> +
> +  ret void
> +}
>
> Added: llvm/trunk/test/Assembler/invalid-atomicrmw-fadd-must-be-fp-type.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/invalid-atomicrmw-fadd-must-be-fp-type.ll?rev=351778&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/Assembler/invalid-atomicrmw-fadd-must-be-fp-type.ll
> (added)
> +++ llvm/trunk/test/Assembler/invalid-atomicrmw-fadd-must-be-fp-type.ll
> Mon Jan 21 19:32:36 2019
> @@ -0,0 +1,7 @@
> +; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
> +
> +; CHECK: error: atomicrmw fadd operand must be a floating point type
> +define void @f(i32* %ptr) {
> +  atomicrmw fadd i32* %ptr, i32 2 seq_cst
> +  ret void
> +}
>
> Added: llvm/trunk/test/Assembler/invalid-atomicrmw-fsub-must-be-fp-type.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Assembler/invalid-atomicrmw-fsub-must-be-fp-type.ll?rev=351778&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/Assembler/invalid-atomicrmw-fsub-must-be-fp-type.ll
> (added)
> +++ llvm/trunk/test/Assembler/invalid-atomicrmw-fsub-must-be-fp-type.ll
> Mon Jan 21 19:32:36 2019
> @@ -0,0 +1,7 @@
> +; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
> +
> +; CHECK: error: atomicrmw fsub operand must be a floating point type
> +define void @f(i32* %ptr) {
> +  atomicrmw fsub i32* %ptr, i32 2 seq_cst
> +  ret void
> +}
>
> Modified: llvm/trunk/test/Bitcode/compatibility.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/compatibility.ll?rev=351778&r1=351777&r2=351778&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/Bitcode/compatibility.ll (original)
> +++ llvm/trunk/test/Bitcode/compatibility.ll Mon Jan 21 19:32:36 2019
> @@ -764,6 +764,13 @@ define void @atomics(i32* %word) {
>  define void @fp_atomics(float* %word) {
>  ; CHECK: %atomicrmw.xchg = atomicrmw xchg float* %word, float
> 1.000000e+00 monotonic
>    %atomicrmw.xchg = atomicrmw xchg float* %word, float 1.0 monotonic
> +
> +; CHECK: %atomicrmw.fadd = atomicrmw fadd float* %word, float
> 1.000000e+00 monotonic
> +  %atomicrmw.fadd = atomicrmw fadd float* %word, float 1.0 monotonic
> +
> +; CHECK: %atomicrmw.fsub = atomicrmw fsub float* %word, float
> 1.000000e+00 monotonic
> +  %atomicrmw.fsub = atomicrmw fsub float* %word, float 1.0 monotonic
> +
>    ret void
>  }
>
>
> Added: llvm/trunk/test/Transforms/AtomicExpand/AArch64/atomicrmw-fp.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/AtomicExpand/AArch64/atomicrmw-fp.ll?rev=351778&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/AtomicExpand/AArch64/atomicrmw-fp.ll (added)
> +++ llvm/trunk/test/Transforms/AtomicExpand/AArch64/atomicrmw-fp.ll Mon
> Jan 21 19:32:36 2019
> @@ -0,0 +1,47 @@
> +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
> +; RUN: opt -S -mtriple=aarch64-linux-gnu -atomic-expand %s | FileCheck %s
> +
> +define float @test_atomicrmw_fadd_f32(float* %ptr, float %value) {
> +; CHECK-LABEL: @test_atomicrmw_fadd_f32(
> +; CHECK-NEXT:    [[TMP1:%.*]] = load float, float* [[PTR:%.*]], align 4
> +; CHECK-NEXT:    br label [[ATOMICRMW_START:%.*]]
> +; CHECK:       atomicrmw.start:
> +; CHECK-NEXT:    [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [
> [[TMP6:%.*]], [[ATOMICRMW_START]] ]
> +; CHECK-NEXT:    [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]]
> +; CHECK-NEXT:    [[TMP2:%.*]] = bitcast float* [[PTR]] to i32*
> +; CHECK-NEXT:    [[TMP3:%.*]] = bitcast float [[NEW]] to i32
> +; CHECK-NEXT:    [[TMP4:%.*]] = bitcast float [[LOADED]] to i32
> +; CHECK-NEXT:    [[TMP5:%.*]] = cmpxchg i32* [[TMP2]], i32 [[TMP4]], i32
> [[TMP3]] seq_cst seq_cst
> +; CHECK-NEXT:    [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
> +; CHECK-NEXT:    [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
> +; CHECK-NEXT:    [[TMP6]] = bitcast i32 [[NEWLOADED]] to float
> +; CHECK-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label
> [[ATOMICRMW_START]]
> +; CHECK:       atomicrmw.end:
> +; CHECK-NEXT:    ret float [[TMP6]]
> +;
> +  %res = atomicrmw fadd float* %ptr, float %value seq_cst
> +  ret float %res
> +}
> +
> +define float @test_atomicrmw_fsub_f32(float* %ptr, float %value) {
> +; CHECK-LABEL: @test_atomicrmw_fsub_f32(
> +; CHECK-NEXT:    [[TMP1:%.*]] = load float, float* [[PTR:%.*]], align 4
> +; CHECK-NEXT:    br label [[ATOMICRMW_START:%.*]]
> +; CHECK:       atomicrmw.start:
> +; CHECK-NEXT:    [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [
> [[TMP6:%.*]], [[ATOMICRMW_START]] ]
> +; CHECK-NEXT:    [[NEW:%.*]] = fsub float [[LOADED]], [[VALUE:%.*]]
> +; CHECK-NEXT:    [[TMP2:%.*]] = bitcast float* [[PTR]] to i32*
> +; CHECK-NEXT:    [[TMP3:%.*]] = bitcast float [[NEW]] to i32
> +; CHECK-NEXT:    [[TMP4:%.*]] = bitcast float [[LOADED]] to i32
> +; CHECK-NEXT:    [[TMP5:%.*]] = cmpxchg i32* [[TMP2]], i32 [[TMP4]], i32
> [[TMP3]] seq_cst seq_cst
> +; CHECK-NEXT:    [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
> +; CHECK-NEXT:    [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
> +; CHECK-NEXT:    [[TMP6]] = bitcast i32 [[NEWLOADED]] to float
> +; CHECK-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label
> [[ATOMICRMW_START]]
> +; CHECK:       atomicrmw.end:
> +; CHECK-NEXT:    ret float [[TMP6]]
> +;
> +  %res = atomicrmw fsub float* %ptr, float %value seq_cst
> +  ret float %res
> +}
> +
>
> Added: llvm/trunk/test/Transforms/AtomicExpand/ARM/atomicrmw-fp.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/AtomicExpand/ARM/atomicrmw-fp.ll?rev=351778&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/AtomicExpand/ARM/atomicrmw-fp.ll (added)
> +++ llvm/trunk/test/Transforms/AtomicExpand/ARM/atomicrmw-fp.ll Mon Jan 21
> 19:32:36 2019
> @@ -0,0 +1,51 @@
> +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
> +; RUN: opt -S -mtriple=armv7-apple-ios7.0 -atomic-expand %s | FileCheck %s
> +
> +define float @test_atomicrmw_fadd_f32(float* %ptr, float %value) {
> +; CHECK-LABEL: @test_atomicrmw_fadd_f32(
> +; CHECK-NEXT:    call void @llvm.arm.dmb(i32 11)
> +; CHECK-NEXT:    [[TMP1:%.*]] = load float, float* [[PTR:%.*]], align 4
> +; CHECK-NEXT:    br label [[ATOMICRMW_START:%.*]]
> +; CHECK:       atomicrmw.start:
> +; CHECK-NEXT:    [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [
> [[TMP6:%.*]], [[ATOMICRMW_START]] ]
> +; CHECK-NEXT:    [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]]
> +; CHECK-NEXT:    [[TMP2:%.*]] = bitcast float* [[PTR]] to i32*
> +; CHECK-NEXT:    [[TMP3:%.*]] = bitcast float [[NEW]] to i32
> +; CHECK-NEXT:    [[TMP4:%.*]] = bitcast float [[LOADED]] to i32
> +; CHECK-NEXT:    [[TMP5:%.*]] = cmpxchg i32* [[TMP2]], i32 [[TMP4]], i32
> [[TMP3]] monotonic monotonic
> +; CHECK-NEXT:    [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
> +; CHECK-NEXT:    [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
> +; CHECK-NEXT:    [[TMP6]] = bitcast i32 [[NEWLOADED]] to float
> +; CHECK-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label
> [[ATOMICRMW_START]]
> +; CHECK:       atomicrmw.end:
> +; CHECK-NEXT:    call void @llvm.arm.dmb(i32 11)
> +; CHECK-NEXT:    ret float [[TMP6]]
> +;
> +  %res = atomicrmw fadd float* %ptr, float %value seq_cst
> +  ret float %res
> +}
> +
> +define float @test_atomicrmw_fsub_f32(float* %ptr, float %value) {
> +; CHECK-LABEL: @test_atomicrmw_fsub_f32(
> +; CHECK-NEXT:    call void @llvm.arm.dmb(i32 11)
> +; CHECK-NEXT:    [[TMP1:%.*]] = load float, float* [[PTR:%.*]], align 4
> +; CHECK-NEXT:    br label [[ATOMICRMW_START:%.*]]
> +; CHECK:       atomicrmw.start:
> +; CHECK-NEXT:    [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [
> [[TMP6:%.*]], [[ATOMICRMW_START]] ]
> +; CHECK-NEXT:    [[NEW:%.*]] = fsub float [[LOADED]], [[VALUE:%.*]]
> +; CHECK-NEXT:    [[TMP2:%.*]] = bitcast float* [[PTR]] to i32*
> +; CHECK-NEXT:    [[TMP3:%.*]] = bitcast float [[NEW]] to i32
> +; CHECK-NEXT:    [[TMP4:%.*]] = bitcast float [[LOADED]] to i32
> +; CHECK-NEXT:    [[TMP5:%.*]] = cmpxchg i32* [[TMP2]], i32 [[TMP4]], i32
> [[TMP3]] monotonic monotonic
> +; CHECK-NEXT:    [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
> +; CHECK-NEXT:    [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
> +; CHECK-NEXT:    [[TMP6]] = bitcast i32 [[NEWLOADED]] to float
> +; CHECK-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label
> [[ATOMICRMW_START]]
> +; CHECK:       atomicrmw.end:
> +; CHECK-NEXT:    call void @llvm.arm.dmb(i32 11)
> +; CHECK-NEXT:    ret float [[TMP6]]
> +;
> +  %res = atomicrmw fsub float* %ptr, float %value seq_cst
> +  ret float %res
> +}
> +
>
> Added: llvm/trunk/test/Transforms/AtomicExpand/Hexagon/atomicrmw-fp.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/AtomicExpand/Hexagon/atomicrmw-fp.ll?rev=351778&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/AtomicExpand/Hexagon/atomicrmw-fp.ll (added)
> +++ llvm/trunk/test/Transforms/AtomicExpand/Hexagon/atomicrmw-fp.ll Mon
> Jan 21 19:32:36 2019
> @@ -0,0 +1,47 @@
> +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
> +; RUN: opt -S -mtriple=hexagon-- -atomic-expand %s | FileCheck %s
> +
> +define float @test_atomicrmw_fadd_f32(float* %ptr, float %value) {
> +; CHECK-LABEL: @test_atomicrmw_fadd_f32(
> +; CHECK-NEXT:    br label [[ATOMICRMW_START:%.*]]
> +; CHECK:       atomicrmw.start:
> +; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float* [[PTR:%.*]] to i32*
> +; CHECK-NEXT:    [[LARX:%.*]] = call i32
> @llvm.hexagon.L2.loadw.locked(i32* [[TMP1]])
> +; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i32 [[LARX]] to float
> +; CHECK-NEXT:    [[NEW:%.*]] = fadd float [[TMP2]], [[VALUE:%.*]]
> +; CHECK-NEXT:    [[TMP3:%.*]] = bitcast float* [[PTR]] to i32*
> +; CHECK-NEXT:    [[TMP4:%.*]] = bitcast float [[NEW]] to i32
> +; CHECK-NEXT:    [[STCX:%.*]] = call i32
> @llvm.hexagon.S2.storew.locked(i32* [[TMP3]], i32 [[TMP4]])
> +; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[STCX]], 0
> +; CHECK-NEXT:    [[TMP6:%.*]] = zext i1 [[TMP5]] to i32
> +; CHECK-NEXT:    [[TRYAGAIN:%.*]] = icmp ne i32 [[TMP6]], 0
> +; CHECK-NEXT:    br i1 [[TRYAGAIN]], label [[ATOMICRMW_START]], label
> [[ATOMICRMW_END:%.*]]
> +; CHECK:       atomicrmw.end:
> +; CHECK-NEXT:    ret float [[TMP2]]
> +;
> +  %res = atomicrmw fadd float* %ptr, float %value seq_cst
> +  ret float %res
> +}
> +
> +define float @test_atomicrmw_fsub_f32(float* %ptr, float %value) {
> +; CHECK-LABEL: @test_atomicrmw_fsub_f32(
> +; CHECK-NEXT:    br label [[ATOMICRMW_START:%.*]]
> +; CHECK:       atomicrmw.start:
> +; CHECK-NEXT:    [[TMP1:%.*]] = bitcast float* [[PTR:%.*]] to i32*
> +; CHECK-NEXT:    [[LARX:%.*]] = call i32
> @llvm.hexagon.L2.loadw.locked(i32* [[TMP1]])
> +; CHECK-NEXT:    [[TMP2:%.*]] = bitcast i32 [[LARX]] to float
> +; CHECK-NEXT:    [[NEW:%.*]] = fsub float [[TMP2]], [[VALUE:%.*]]
> +; CHECK-NEXT:    [[TMP3:%.*]] = bitcast float* [[PTR]] to i32*
> +; CHECK-NEXT:    [[TMP4:%.*]] = bitcast float [[NEW]] to i32
> +; CHECK-NEXT:    [[STCX:%.*]] = call i32
> @llvm.hexagon.S2.storew.locked(i32* [[TMP3]], i32 [[TMP4]])
> +; CHECK-NEXT:    [[TMP5:%.*]] = icmp eq i32 [[STCX]], 0
> +; CHECK-NEXT:    [[TMP6:%.*]] = zext i1 [[TMP5]] to i32
> +; CHECK-NEXT:    [[TRYAGAIN:%.*]] = icmp ne i32 [[TMP6]], 0
> +; CHECK-NEXT:    br i1 [[TRYAGAIN]], label [[ATOMICRMW_START]], label
> [[ATOMICRMW_END:%.*]]
> +; CHECK:       atomicrmw.end:
> +; CHECK-NEXT:    ret float [[TMP2]]
> +;
> +  %res = atomicrmw fsub float* %ptr, float %value seq_cst
> +  ret float %res
> +}
> +
>
> Added: llvm/trunk/test/Transforms/AtomicExpand/Hexagon/lit.local.cfg
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/AtomicExpand/Hexagon/lit.local.cfg?rev=351778&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/AtomicExpand/Hexagon/lit.local.cfg (added)
> +++ llvm/trunk/test/Transforms/AtomicExpand/Hexagon/lit.local.cfg Mon Jan
> 21 19:32:36 2019
> @@ -0,0 +1,2 @@
> +if not 'Hexagon' in config.root.targets:
> +    config.unsupported = True
>
> Added: llvm/trunk/test/Transforms/AtomicExpand/Mips/atomicrmw-fp.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/AtomicExpand/Mips/atomicrmw-fp.ll?rev=351778&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/AtomicExpand/Mips/atomicrmw-fp.ll (added)
> +++ llvm/trunk/test/Transforms/AtomicExpand/Mips/atomicrmw-fp.ll Mon Jan
> 21 19:32:36 2019
> @@ -0,0 +1,51 @@
> +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
> +; RUN: opt -S -mtriple=mips64-mti-linux-gnu -atomic-expand %s | FileCheck
> %s
> +
> +define float @test_atomicrmw_fadd_f32(float* %ptr, float %value) {
> +; CHECK-LABEL: @test_atomicrmw_fadd_f32(
> +; CHECK-NEXT:    fence seq_cst
> +; CHECK-NEXT:    [[TMP1:%.*]] = load float, float* [[PTR:%.*]], align 4
> +; CHECK-NEXT:    br label [[ATOMICRMW_START:%.*]]
> +; CHECK:       atomicrmw.start:
> +; CHECK-NEXT:    [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [
> [[TMP6:%.*]], [[ATOMICRMW_START]] ]
> +; CHECK-NEXT:    [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]]
> +; CHECK-NEXT:    [[TMP2:%.*]] = bitcast float* [[PTR]] to i32*
> +; CHECK-NEXT:    [[TMP3:%.*]] = bitcast float [[NEW]] to i32
> +; CHECK-NEXT:    [[TMP4:%.*]] = bitcast float [[LOADED]] to i32
> +; CHECK-NEXT:    [[TMP5:%.*]] = cmpxchg i32* [[TMP2]], i32 [[TMP4]], i32
> [[TMP3]] monotonic monotonic
> +; CHECK-NEXT:    [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
> +; CHECK-NEXT:    [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
> +; CHECK-NEXT:    [[TMP6]] = bitcast i32 [[NEWLOADED]] to float
> +; CHECK-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label
> [[ATOMICRMW_START]]
> +; CHECK:       atomicrmw.end:
> +; CHECK-NEXT:    fence seq_cst
> +; CHECK-NEXT:    ret float [[TMP6]]
> +;
> +  %res = atomicrmw fadd float* %ptr, float %value seq_cst
> +  ret float %res
> +}
> +
> +define float @test_atomicrmw_fsub_f32(float* %ptr, float %value) {
> +; CHECK-LABEL: @test_atomicrmw_fsub_f32(
> +; CHECK-NEXT:    fence seq_cst
> +; CHECK-NEXT:    [[TMP1:%.*]] = load float, float* [[PTR:%.*]], align 4
> +; CHECK-NEXT:    br label [[ATOMICRMW_START:%.*]]
> +; CHECK:       atomicrmw.start:
> +; CHECK-NEXT:    [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [
> [[TMP6:%.*]], [[ATOMICRMW_START]] ]
> +; CHECK-NEXT:    [[NEW:%.*]] = fsub float [[LOADED]], [[VALUE:%.*]]
> +; CHECK-NEXT:    [[TMP2:%.*]] = bitcast float* [[PTR]] to i32*
> +; CHECK-NEXT:    [[TMP3:%.*]] = bitcast float [[NEW]] to i32
> +; CHECK-NEXT:    [[TMP4:%.*]] = bitcast float [[LOADED]] to i32
> +; CHECK-NEXT:    [[TMP5:%.*]] = cmpxchg i32* [[TMP2]], i32 [[TMP4]], i32
> [[TMP3]] monotonic monotonic
> +; CHECK-NEXT:    [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
> +; CHECK-NEXT:    [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
> +; CHECK-NEXT:    [[TMP6]] = bitcast i32 [[NEWLOADED]] to float
> +; CHECK-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label
> [[ATOMICRMW_START]]
> +; CHECK:       atomicrmw.end:
> +; CHECK-NEXT:    fence seq_cst
> +; CHECK-NEXT:    ret float [[TMP6]]
> +;
> +  %res = atomicrmw fsub float* %ptr, float %value seq_cst
> +  ret float %res
> +}
> +
>
> Added: llvm/trunk/test/Transforms/AtomicExpand/Mips/lit.local.cfg
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/AtomicExpand/Mips/lit.local.cfg?rev=351778&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/AtomicExpand/Mips/lit.local.cfg (added)
> +++ llvm/trunk/test/Transforms/AtomicExpand/Mips/lit.local.cfg Mon Jan 21
> 19:32:36 2019
> @@ -0,0 +1,2 @@
> +if not 'Mips' in config.root.targets:
> +    config.unsupported = True
>
> Added: llvm/trunk/test/Transforms/AtomicExpand/RISCV/atomicrmw-fp.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/AtomicExpand/RISCV/atomicrmw-fp.ll?rev=351778&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/AtomicExpand/RISCV/atomicrmw-fp.ll (added)
> +++ llvm/trunk/test/Transforms/AtomicExpand/RISCV/atomicrmw-fp.ll Mon Jan
> 21 19:32:36 2019
> @@ -0,0 +1,47 @@
> +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
> +; RUN: opt -S -mtriple=riscv32-- -atomic-expand %s | FileCheck %s
> +
> +define float @test_atomicrmw_fadd_f32(float* %ptr, float %value) {
> +; CHECK-LABEL: @test_atomicrmw_fadd_f32(
> +; CHECK-NEXT:    [[TMP1:%.*]] = load float, float* [[PTR:%.*]], align 4
> +; CHECK-NEXT:    br label [[ATOMICRMW_START:%.*]]
> +; CHECK:       atomicrmw.start:
> +; CHECK-NEXT:    [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [
> [[TMP6:%.*]], [[ATOMICRMW_START]] ]
> +; CHECK-NEXT:    [[NEW:%.*]] = fadd float [[LOADED]], [[VALUE:%.*]]
> +; CHECK-NEXT:    [[TMP2:%.*]] = bitcast float* [[PTR]] to i32*
> +; CHECK-NEXT:    [[TMP3:%.*]] = bitcast float [[NEW]] to i32
> +; CHECK-NEXT:    [[TMP4:%.*]] = bitcast float [[LOADED]] to i32
> +; CHECK-NEXT:    [[TMP5:%.*]] = cmpxchg i32* [[TMP2]], i32 [[TMP4]], i32
> [[TMP3]] seq_cst seq_cst
> +; CHECK-NEXT:    [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
> +; CHECK-NEXT:    [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
> +; CHECK-NEXT:    [[TMP6]] = bitcast i32 [[NEWLOADED]] to float
> +; CHECK-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label
> [[ATOMICRMW_START]]
> +; CHECK:       atomicrmw.end:
> +; CHECK-NEXT:    ret float [[TMP6]]
> +;
> +  %res = atomicrmw fadd float* %ptr, float %value seq_cst
> +  ret float %res
> +}
> +
> +define float @test_atomicrmw_fsub_f32(float* %ptr, float %value) {
> +; CHECK-LABEL: @test_atomicrmw_fsub_f32(
> +; CHECK-NEXT:    [[TMP1:%.*]] = load float, float* [[PTR:%.*]], align 4
> +; CHECK-NEXT:    br label [[ATOMIxbCRMW_START:%.*]]
> +; CHECK:       atomicrmw.start:
> +; CHECK-NEXT:    [[LOADED:%.*]] = phi float [ [[TMP1]], [[TMP0:%.*]] ], [
> [[TMP6:%.*]], [[ATOMICRMW_START]] ]
> +; CHECK-NEXT:    [[NEW:%.*]] = fsub float [[LOADED]], [[VALUE:%.*]]
> +; CHECK-NEXT:    [[TMP2:%.*]] = bitcast float* [[PTR]] to i32*
> +; CHECK-NEXT:    [[TMP3:%.*]] = bitcast float [[NEW]] to i32
> +; CHECK-NEXT:    [[TMP4:%.*]] = bitcast float [[LOADED]] to i32
> +; CHECK-NEXT:    [[TMP5:%.*]] = cmpxchg i32* [[TMP2]], i32 [[TMP4]], i32
> [[TMP3]] seq_cst seq_cst
> +; CHECK-NEXT:    [[SUCCESS:%.*]] = extractvalue { i32, i1 } [[TMP5]], 1
> +; CHECK-NEXT:    [[NEWLOADED:%.*]] = extractvalue { i32, i1 } [[TMP5]], 0
> +; CHECK-NEXT:    [[TMP6]] = bitcast i32 [[NEWLOADED]] to float
> +; CHECK-NEXT:    br i1 [[SUCCESS]], label [[ATOMICRMW_END:%.*]], label
> [[ATOMICRMW_START]]
> +; CHECK:       atomicrmw.end:
> +; CHECK-NEXT:    ret float [[TMP6]]
> +;
> +  %res = atomicrmw fsub float* %ptr, float %value seq_cst
> +  ret float %res
> +}
> +
>
> Added: llvm/trunk/test/Transforms/AtomicExpand/RISCV/lit.local.cfg
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/AtomicExpand/RISCV/lit.local.cfg?rev=351778&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/Transforms/AtomicExpand/RISCV/lit.local.cfg (added)
> +++ llvm/trunk/test/Transforms/AtomicExpand/RISCV/lit.local.cfg Mon Jan 21
> 19:32:36 2019
> @@ -0,0 +1,5 @@
> +config.suffixes = ['.ll']
> +
> +targets = set(config.root.targets_to_build.split())
> +if not 'RISCV' in targets:
> +    config.unsupported = True
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190122/41d46bea/attachment-0001.html>


More information about the llvm-commits mailing list