diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -248,6 +248,8 @@ /// w.r.t. what they should expand to. enum class AtomicExpansionKind { None, // Don't expand the instruction. + CastToInteger, // Cast the atomic instruction to another type, e.g. from + // floating-point to integer type. LLSC, // Expand the instruction into loadlinked/storeconditional; used // by ARM/AArch64. LLOnly, // Expand the (load) instruction into just a load-linked, which has @@ -2045,6 +2047,14 @@ return AtomicExpansionKind::None; } + /// Returns how the given (atomic) load should be cast by the IR-level + /// AtomicExpand pass. + virtual AtomicExpansionKind shouldCastAtomicLoadInIR(LoadInst *LI) const { + if (LI->getType()->isFloatingPointTy()) + return AtomicExpansionKind::CastToInteger; + return AtomicExpansionKind::None; + } + /// Returns how the given (atomic) store should be expanded by the IR-level /// AtomicExpand pass into. For instance AtomicExpansionKind::Expand will try /// to use an atomicrmw xchg. @@ -2052,6 +2062,15 @@ return AtomicExpansionKind::None; } + /// Returns how the given (atomic) store should be cast by the IR-level + /// AtomicExpand pass into. For instance AtomicExpansionKind::CastToInteger + /// will try to cast the operands to integer values. + virtual AtomicExpansionKind shouldCastAtomicStoreInIR(StoreInst *SI) const { + if (SI->getValueOperand()->getType()->isFloatingPointTy()) + return AtomicExpansionKind::CastToInteger; + return AtomicExpansionKind::None; + } + /// Returns how the given atomic cmpxchg should be expanded by the IR-level /// AtomicExpand pass. virtual AtomicExpansionKind @@ -2066,6 +2085,17 @@ AtomicExpansionKind::CmpXChg : AtomicExpansionKind::None; } + /// Returns how the given atomic atomicrmw should be cast by the IR-level + /// AtomicExpand pass. + virtual AtomicExpansionKind + shouldCastAtomicRMWIInIR(AtomicRMWInst *RMWI) const { + if (RMWI->getOperation() == AtomicRMWInst::Xchg && + RMWI->getValOperand()->getType()->isFloatingPointTy()) + return AtomicExpansionKind::CastToInteger; + + return AtomicExpansionKind::None; + } + /// On some platforms, an AtomicRMW that never actually modifies the value /// (such as fetch_add of 0) can be turned into a fence followed by an /// atomic load. This may sound useless, but it makes it possible for the diff --git a/llvm/lib/CodeGen/AtomicExpandPass.cpp b/llvm/lib/CodeGen/AtomicExpandPass.cpp --- a/llvm/lib/CodeGen/AtomicExpandPass.cpp +++ b/llvm/lib/CodeGen/AtomicExpandPass.cpp @@ -254,7 +254,8 @@ } if (LI) { - if (LI->getType()->isFloatingPointTy()) { + if (TLI->shouldCastAtomicLoadInIR(LI) == + TargetLoweringBase::AtomicExpansionKind::CastToInteger) { // TODO: add a TLI hook to control this so that each target can // convert to lowering the original type one at a time. LI = convertAtomicLoadToIntegerType(LI); @@ -264,7 +265,8 @@ MadeChange |= tryExpandAtomicLoad(LI); } else if (SI) { - if (SI->getValueOperand()->getType()->isFloatingPointTy()) { + if (TLI->shouldCastAtomicStoreInIR(SI) == + TargetLoweringBase::AtomicExpansionKind::CastToInteger) { // TODO: add a TLI hook to control this so that each target can // convert to lowering the original type one at a time. SI = convertAtomicStoreToIntegerType(SI); @@ -285,8 +287,8 @@ MadeChange = true; } else { AtomicRMWInst::BinOp Op = RMWI->getOperation(); - if (Op == AtomicRMWInst::Xchg && - RMWI->getValOperand()->getType()->isFloatingPointTy()) { + if (TLI->shouldCastAtomicRMWIInIR(RMWI) == + TargetLoweringBase::AtomicExpansionKind::CastToInteger) { // TODO: add a TLI hook to control this so that each target can // convert to lowering the original type one at a time. RMWI = convertAtomicXchgToIntegerType(RMWI);