Index: llvm/trunk/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp =================================================================== --- llvm/trunk/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp @@ -57,15 +57,23 @@ } /// Return true if the given instruction always produces a value in memory -/// equivelent to its value operand. +/// equivalent to its value operand. bool isSaturating(AtomicRMWInst& RMWI) { + if (auto CF = dyn_cast(RMWI.getValOperand())) + switch(RMWI.getOperation()) { + case AtomicRMWInst::FAdd: + case AtomicRMWInst::FSub: + return CF->isNaN(); + default: + return false; + }; + auto C = dyn_cast(RMWI.getValOperand()); if(!C) return false; switch(RMWI.getOperation()) { default: - // TODO: fadd, fsub w/Nan return false; case AtomicRMWInst::Xchg: return true; Index: llvm/trunk/test/Transforms/InstCombine/atomicrmw.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/atomicrmw.ll +++ llvm/trunk/test/Transforms/InstCombine/atomicrmw.ll @@ -214,7 +214,7 @@ } ; CHECK-LABEL: sat_fadd_nan -; CHECK-NEXT: %res = atomicrmw fadd double* %addr, double 0x7FF00000FFFFFFFF release +; CHECK-NEXT: %res = atomicrmw xchg double* %addr, double 0x7FF00000FFFFFFFF release ; CHECK-NEXT: ret double %res define double @sat_fadd_nan(double* %addr) { %res = atomicrmw fadd double* %addr, double 0x7FF00000FFFFFFFF release @@ -222,7 +222,7 @@ } ; CHECK-LABEL: sat_fsub_nan -; CHECK-NEXT: %res = atomicrmw fsub double* %addr, double 0x7FF00000FFFFFFFF release +; CHECK-NEXT: %res = atomicrmw xchg double* %addr, double 0x7FF00000FFFFFFFF release ; CHECK-NEXT: ret double %res define double @sat_fsub_nan(double* %addr) { %res = atomicrmw fsub double* %addr, double 0x7FF00000FFFFFFFF release @@ -230,7 +230,7 @@ } ; CHECK-LABEL: sat_fsub_nan_unused -; CHECK-NEXT: atomicrmw fsub double* %addr, double 0x7FF00000FFFFFFFF monotonic +; CHECK-NEXT: store atomic double 0x7FF00000FFFFFFFF, double* %addr monotonic, align 8 ; CHECK-NEXT: ret void define void @sat_fsub_nan_unused(double* %addr) { atomicrmw fsub double* %addr, double 0x7FF00000FFFFFFFF monotonic