Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -8388,14 +8388,18 @@ - min - umax - umin +- fadd +- fsub -The type of '' 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. The type of the '````' 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 `. + +For most of these operations, the type of '' 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 fadd/fsub, +this must be a floating point type. The type of the '````' +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 `. A ``atomicrmw`` instruction can also take an optional ":ref:`syncscope `" argument. @@ -8421,6 +8425,8 @@ comparison) - umin: ``*ptr = *ptr < val ? *ptr : val`` (using an unsigned comparison) +- fadd: ``*ptr = *ptr + val`` (using floating point rules) +- fsub: ``*ptr = *ptr - val`` (using floating point rules) Example: """""""" Index: include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- include/llvm/Bitcode/LLVMBitCodes.h +++ include/llvm/Bitcode/LLVMBitCodes.h @@ -407,7 +407,9 @@ 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 Index: include/llvm/IR/Instructions.h =================================================================== --- include/llvm/IR/Instructions.h +++ include/llvm/IR/Instructions.h @@ -714,8 +714,14 @@ /// *p = old 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; Index: lib/AsmParser/LLParser.cpp =================================================================== --- lib/AsmParser/LLParser.cpp +++ lib/AsmParser/LLParser.cpp @@ -6765,6 +6765,7 @@ AtomicOrdering Ordering = AtomicOrdering::NotAtomic; SyncScope::ID SSID = SyncScope::System; bool isVolatile = false; + bool IsFP = false; AtomicRMWInst::BinOp Operation; if (EatIfPresent(lltok::kw_volatile)) @@ -6783,6 +6784,14 @@ 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. @@ -6799,18 +6808,25 @@ if (cast(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(); Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -1030,6 +1030,8 @@ 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; } } Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -560,6 +560,8 @@ 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; } } Index: lib/CodeGen/AtomicExpandPass.cpp =================================================================== --- lib/CodeGen/AtomicExpandPass.cpp +++ lib/CodeGen/AtomicExpandPass.cpp @@ -1519,6 +1519,8 @@ case AtomicRMWInst::UMin: // No atomic libcalls are available for max/min/umax/umin. return {}; + default: + llvm_unreachable("unhandled operation"); } llvm_unreachable("Unexpected AtomicRMW operation."); } Index: lib/IR/Instructions.cpp =================================================================== --- lib/IR/Instructions.cpp +++ lib/IR/Instructions.cpp @@ -1354,6 +1354,10 @@ return "umax"; case AtomicRMWInst::UMin: return "umin"; + case AtomicRMWInst::FAdd: + return "fadd"; + case AtomicRMWInst::FSub: + return "fsub"; case AtomicRMWInst::BAD_BINOP: return ""; } Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -3391,6 +3391,11 @@ 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) + Index: test/Assembler/atomic.ll =================================================================== --- test/Assembler/atomic.ll +++ test/Assembler/atomic.ll @@ -39,3 +39,13 @@ 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 +} Index: test/Assembler/invalid-atomicrmw-fadd-must-be-fp-type.ll =================================================================== --- /dev/null +++ test/Assembler/invalid-atomicrmw-fadd-must-be-fp-type.ll @@ -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 +} Index: test/Assembler/invalid-atomicrmw-fsub-must-be-fp-type.ll =================================================================== --- /dev/null +++ test/Assembler/invalid-atomicrmw-fsub-must-be-fp-type.ll @@ -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 +} Index: test/Bitcode/compatibility.ll =================================================================== --- test/Bitcode/compatibility.ll +++ test/Bitcode/compatibility.ll @@ -764,6 +764,13 @@ 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 }