xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/CodeGen/CGAtomic.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===--- CGAtomic.cpp - Emit LLVM IR for atomic operations ----------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file contains the code for emitting atomic operations.
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg 
137330f729Sjoerg #include "CGCall.h"
147330f729Sjoerg #include "CGRecordLayout.h"
157330f729Sjoerg #include "CodeGenFunction.h"
167330f729Sjoerg #include "CodeGenModule.h"
177330f729Sjoerg #include "TargetInfo.h"
187330f729Sjoerg #include "clang/AST/ASTContext.h"
197330f729Sjoerg #include "clang/CodeGen/CGFunctionInfo.h"
207330f729Sjoerg #include "clang/Frontend/FrontendDiagnostic.h"
217330f729Sjoerg #include "llvm/ADT/DenseMap.h"
227330f729Sjoerg #include "llvm/IR/DataLayout.h"
237330f729Sjoerg #include "llvm/IR/Intrinsics.h"
247330f729Sjoerg #include "llvm/IR/Operator.h"
257330f729Sjoerg 
267330f729Sjoerg using namespace clang;
277330f729Sjoerg using namespace CodeGen;
287330f729Sjoerg 
297330f729Sjoerg namespace {
307330f729Sjoerg   class AtomicInfo {
317330f729Sjoerg     CodeGenFunction &CGF;
327330f729Sjoerg     QualType AtomicTy;
337330f729Sjoerg     QualType ValueTy;
347330f729Sjoerg     uint64_t AtomicSizeInBits;
357330f729Sjoerg     uint64_t ValueSizeInBits;
367330f729Sjoerg     CharUnits AtomicAlign;
377330f729Sjoerg     CharUnits ValueAlign;
387330f729Sjoerg     TypeEvaluationKind EvaluationKind;
397330f729Sjoerg     bool UseLibcall;
407330f729Sjoerg     LValue LVal;
417330f729Sjoerg     CGBitFieldInfo BFI;
427330f729Sjoerg   public:
AtomicInfo(CodeGenFunction & CGF,LValue & lvalue)437330f729Sjoerg     AtomicInfo(CodeGenFunction &CGF, LValue &lvalue)
447330f729Sjoerg         : CGF(CGF), AtomicSizeInBits(0), ValueSizeInBits(0),
457330f729Sjoerg           EvaluationKind(TEK_Scalar), UseLibcall(true) {
467330f729Sjoerg       assert(!lvalue.isGlobalReg());
477330f729Sjoerg       ASTContext &C = CGF.getContext();
487330f729Sjoerg       if (lvalue.isSimple()) {
497330f729Sjoerg         AtomicTy = lvalue.getType();
507330f729Sjoerg         if (auto *ATy = AtomicTy->getAs<AtomicType>())
517330f729Sjoerg           ValueTy = ATy->getValueType();
527330f729Sjoerg         else
537330f729Sjoerg           ValueTy = AtomicTy;
547330f729Sjoerg         EvaluationKind = CGF.getEvaluationKind(ValueTy);
557330f729Sjoerg 
567330f729Sjoerg         uint64_t ValueAlignInBits;
577330f729Sjoerg         uint64_t AtomicAlignInBits;
587330f729Sjoerg         TypeInfo ValueTI = C.getTypeInfo(ValueTy);
597330f729Sjoerg         ValueSizeInBits = ValueTI.Width;
607330f729Sjoerg         ValueAlignInBits = ValueTI.Align;
617330f729Sjoerg 
627330f729Sjoerg         TypeInfo AtomicTI = C.getTypeInfo(AtomicTy);
637330f729Sjoerg         AtomicSizeInBits = AtomicTI.Width;
647330f729Sjoerg         AtomicAlignInBits = AtomicTI.Align;
657330f729Sjoerg 
667330f729Sjoerg         assert(ValueSizeInBits <= AtomicSizeInBits);
677330f729Sjoerg         assert(ValueAlignInBits <= AtomicAlignInBits);
687330f729Sjoerg 
697330f729Sjoerg         AtomicAlign = C.toCharUnitsFromBits(AtomicAlignInBits);
707330f729Sjoerg         ValueAlign = C.toCharUnitsFromBits(ValueAlignInBits);
717330f729Sjoerg         if (lvalue.getAlignment().isZero())
727330f729Sjoerg           lvalue.setAlignment(AtomicAlign);
737330f729Sjoerg 
747330f729Sjoerg         LVal = lvalue;
757330f729Sjoerg       } else if (lvalue.isBitField()) {
767330f729Sjoerg         ValueTy = lvalue.getType();
777330f729Sjoerg         ValueSizeInBits = C.getTypeSize(ValueTy);
787330f729Sjoerg         auto &OrigBFI = lvalue.getBitFieldInfo();
797330f729Sjoerg         auto Offset = OrigBFI.Offset % C.toBits(lvalue.getAlignment());
807330f729Sjoerg         AtomicSizeInBits = C.toBits(
817330f729Sjoerg             C.toCharUnitsFromBits(Offset + OrigBFI.Size + C.getCharWidth() - 1)
827330f729Sjoerg                 .alignTo(lvalue.getAlignment()));
837330f729Sjoerg         auto VoidPtrAddr = CGF.EmitCastToVoidPtr(lvalue.getBitFieldPointer());
847330f729Sjoerg         auto OffsetInChars =
857330f729Sjoerg             (C.toCharUnitsFromBits(OrigBFI.Offset) / lvalue.getAlignment()) *
867330f729Sjoerg             lvalue.getAlignment();
877330f729Sjoerg         VoidPtrAddr = CGF.Builder.CreateConstGEP1_64(
887330f729Sjoerg             VoidPtrAddr, OffsetInChars.getQuantity());
897330f729Sjoerg         auto Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
907330f729Sjoerg             VoidPtrAddr,
917330f729Sjoerg             CGF.Builder.getIntNTy(AtomicSizeInBits)->getPointerTo(),
927330f729Sjoerg             "atomic_bitfield_base");
937330f729Sjoerg         BFI = OrigBFI;
947330f729Sjoerg         BFI.Offset = Offset;
957330f729Sjoerg         BFI.StorageSize = AtomicSizeInBits;
967330f729Sjoerg         BFI.StorageOffset += OffsetInChars;
977330f729Sjoerg         LVal = LValue::MakeBitfield(Address(Addr, lvalue.getAlignment()),
987330f729Sjoerg                                     BFI, lvalue.getType(), lvalue.getBaseInfo(),
997330f729Sjoerg                                     lvalue.getTBAAInfo());
1007330f729Sjoerg         AtomicTy = C.getIntTypeForBitwidth(AtomicSizeInBits, OrigBFI.IsSigned);
1017330f729Sjoerg         if (AtomicTy.isNull()) {
1027330f729Sjoerg           llvm::APInt Size(
1037330f729Sjoerg               /*numBits=*/32,
1047330f729Sjoerg               C.toCharUnitsFromBits(AtomicSizeInBits).getQuantity());
1057330f729Sjoerg           AtomicTy =
1067330f729Sjoerg               C.getConstantArrayType(C.CharTy, Size, nullptr, ArrayType::Normal,
1077330f729Sjoerg                                      /*IndexTypeQuals=*/0);
1087330f729Sjoerg         }
1097330f729Sjoerg         AtomicAlign = ValueAlign = lvalue.getAlignment();
1107330f729Sjoerg       } else if (lvalue.isVectorElt()) {
1117330f729Sjoerg         ValueTy = lvalue.getType()->castAs<VectorType>()->getElementType();
1127330f729Sjoerg         ValueSizeInBits = C.getTypeSize(ValueTy);
1137330f729Sjoerg         AtomicTy = lvalue.getType();
1147330f729Sjoerg         AtomicSizeInBits = C.getTypeSize(AtomicTy);
1157330f729Sjoerg         AtomicAlign = ValueAlign = lvalue.getAlignment();
1167330f729Sjoerg         LVal = lvalue;
1177330f729Sjoerg       } else {
1187330f729Sjoerg         assert(lvalue.isExtVectorElt());
1197330f729Sjoerg         ValueTy = lvalue.getType();
1207330f729Sjoerg         ValueSizeInBits = C.getTypeSize(ValueTy);
1217330f729Sjoerg         AtomicTy = ValueTy = CGF.getContext().getExtVectorType(
122*e038c9c4Sjoerg             lvalue.getType(), cast<llvm::FixedVectorType>(
123*e038c9c4Sjoerg                                   lvalue.getExtVectorAddress().getElementType())
124*e038c9c4Sjoerg                                   ->getNumElements());
1257330f729Sjoerg         AtomicSizeInBits = C.getTypeSize(AtomicTy);
1267330f729Sjoerg         AtomicAlign = ValueAlign = lvalue.getAlignment();
1277330f729Sjoerg         LVal = lvalue;
1287330f729Sjoerg       }
1297330f729Sjoerg       UseLibcall = !C.getTargetInfo().hasBuiltinAtomic(
1307330f729Sjoerg           AtomicSizeInBits, C.toBits(lvalue.getAlignment()));
1317330f729Sjoerg     }
1327330f729Sjoerg 
getAtomicType() const1337330f729Sjoerg     QualType getAtomicType() const { return AtomicTy; }
getValueType() const1347330f729Sjoerg     QualType getValueType() const { return ValueTy; }
getAtomicAlignment() const1357330f729Sjoerg     CharUnits getAtomicAlignment() const { return AtomicAlign; }
getAtomicSizeInBits() const1367330f729Sjoerg     uint64_t getAtomicSizeInBits() const { return AtomicSizeInBits; }
getValueSizeInBits() const1377330f729Sjoerg     uint64_t getValueSizeInBits() const { return ValueSizeInBits; }
getEvaluationKind() const1387330f729Sjoerg     TypeEvaluationKind getEvaluationKind() const { return EvaluationKind; }
shouldUseLibcall() const1397330f729Sjoerg     bool shouldUseLibcall() const { return UseLibcall; }
getAtomicLValue() const1407330f729Sjoerg     const LValue &getAtomicLValue() const { return LVal; }
getAtomicPointer() const1417330f729Sjoerg     llvm::Value *getAtomicPointer() const {
1427330f729Sjoerg       if (LVal.isSimple())
143*e038c9c4Sjoerg         return LVal.getPointer(CGF);
1447330f729Sjoerg       else if (LVal.isBitField())
1457330f729Sjoerg         return LVal.getBitFieldPointer();
1467330f729Sjoerg       else if (LVal.isVectorElt())
1477330f729Sjoerg         return LVal.getVectorPointer();
1487330f729Sjoerg       assert(LVal.isExtVectorElt());
1497330f729Sjoerg       return LVal.getExtVectorPointer();
1507330f729Sjoerg     }
getAtomicAddress() const1517330f729Sjoerg     Address getAtomicAddress() const {
1527330f729Sjoerg       return Address(getAtomicPointer(), getAtomicAlignment());
1537330f729Sjoerg     }
1547330f729Sjoerg 
getAtomicAddressAsAtomicIntPointer() const1557330f729Sjoerg     Address getAtomicAddressAsAtomicIntPointer() const {
1567330f729Sjoerg       return emitCastToAtomicIntPointer(getAtomicAddress());
1577330f729Sjoerg     }
1587330f729Sjoerg 
1597330f729Sjoerg     /// Is the atomic size larger than the underlying value type?
1607330f729Sjoerg     ///
1617330f729Sjoerg     /// Note that the absence of padding does not mean that atomic
1627330f729Sjoerg     /// objects are completely interchangeable with non-atomic
1637330f729Sjoerg     /// objects: we might have promoted the alignment of a type
1647330f729Sjoerg     /// without making it bigger.
hasPadding() const1657330f729Sjoerg     bool hasPadding() const {
1667330f729Sjoerg       return (ValueSizeInBits != AtomicSizeInBits);
1677330f729Sjoerg     }
1687330f729Sjoerg 
1697330f729Sjoerg     bool emitMemSetZeroIfNecessary() const;
1707330f729Sjoerg 
getAtomicSizeValue() const1717330f729Sjoerg     llvm::Value *getAtomicSizeValue() const {
1727330f729Sjoerg       CharUnits size = CGF.getContext().toCharUnitsFromBits(AtomicSizeInBits);
1737330f729Sjoerg       return CGF.CGM.getSize(size);
1747330f729Sjoerg     }
1757330f729Sjoerg 
1767330f729Sjoerg     /// Cast the given pointer to an integer pointer suitable for atomic
1777330f729Sjoerg     /// operations if the source.
1787330f729Sjoerg     Address emitCastToAtomicIntPointer(Address Addr) const;
1797330f729Sjoerg 
1807330f729Sjoerg     /// If Addr is compatible with the iN that will be used for an atomic
1817330f729Sjoerg     /// operation, bitcast it. Otherwise, create a temporary that is suitable
1827330f729Sjoerg     /// and copy the value across.
1837330f729Sjoerg     Address convertToAtomicIntPointer(Address Addr) const;
1847330f729Sjoerg 
1857330f729Sjoerg     /// Turn an atomic-layout object into an r-value.
1867330f729Sjoerg     RValue convertAtomicTempToRValue(Address addr, AggValueSlot resultSlot,
1877330f729Sjoerg                                      SourceLocation loc, bool AsValue) const;
1887330f729Sjoerg 
1897330f729Sjoerg     /// Converts a rvalue to integer value.
1907330f729Sjoerg     llvm::Value *convertRValueToInt(RValue RVal) const;
1917330f729Sjoerg 
1927330f729Sjoerg     RValue ConvertIntToValueOrAtomic(llvm::Value *IntVal,
1937330f729Sjoerg                                      AggValueSlot ResultSlot,
1947330f729Sjoerg                                      SourceLocation Loc, bool AsValue) const;
1957330f729Sjoerg 
1967330f729Sjoerg     /// Copy an atomic r-value into atomic-layout memory.
1977330f729Sjoerg     void emitCopyIntoMemory(RValue rvalue) const;
1987330f729Sjoerg 
1997330f729Sjoerg     /// Project an l-value down to the value field.
projectValue() const2007330f729Sjoerg     LValue projectValue() const {
2017330f729Sjoerg       assert(LVal.isSimple());
2027330f729Sjoerg       Address addr = getAtomicAddress();
2037330f729Sjoerg       if (hasPadding())
2047330f729Sjoerg         addr = CGF.Builder.CreateStructGEP(addr, 0);
2057330f729Sjoerg 
2067330f729Sjoerg       return LValue::MakeAddr(addr, getValueType(), CGF.getContext(),
2077330f729Sjoerg                               LVal.getBaseInfo(), LVal.getTBAAInfo());
2087330f729Sjoerg     }
2097330f729Sjoerg 
2107330f729Sjoerg     /// Emits atomic load.
2117330f729Sjoerg     /// \returns Loaded value.
2127330f729Sjoerg     RValue EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc,
2137330f729Sjoerg                           bool AsValue, llvm::AtomicOrdering AO,
2147330f729Sjoerg                           bool IsVolatile);
2157330f729Sjoerg 
2167330f729Sjoerg     /// Emits atomic compare-and-exchange sequence.
2177330f729Sjoerg     /// \param Expected Expected value.
2187330f729Sjoerg     /// \param Desired Desired value.
2197330f729Sjoerg     /// \param Success Atomic ordering for success operation.
2207330f729Sjoerg     /// \param Failure Atomic ordering for failed operation.
2217330f729Sjoerg     /// \param IsWeak true if atomic operation is weak, false otherwise.
2227330f729Sjoerg     /// \returns Pair of values: previous value from storage (value type) and
2237330f729Sjoerg     /// boolean flag (i1 type) with true if success and false otherwise.
2247330f729Sjoerg     std::pair<RValue, llvm::Value *>
2257330f729Sjoerg     EmitAtomicCompareExchange(RValue Expected, RValue Desired,
2267330f729Sjoerg                               llvm::AtomicOrdering Success =
2277330f729Sjoerg                                   llvm::AtomicOrdering::SequentiallyConsistent,
2287330f729Sjoerg                               llvm::AtomicOrdering Failure =
2297330f729Sjoerg                                   llvm::AtomicOrdering::SequentiallyConsistent,
2307330f729Sjoerg                               bool IsWeak = false);
2317330f729Sjoerg 
2327330f729Sjoerg     /// Emits atomic update.
2337330f729Sjoerg     /// \param AO Atomic ordering.
2347330f729Sjoerg     /// \param UpdateOp Update operation for the current lvalue.
2357330f729Sjoerg     void EmitAtomicUpdate(llvm::AtomicOrdering AO,
2367330f729Sjoerg                           const llvm::function_ref<RValue(RValue)> &UpdateOp,
2377330f729Sjoerg                           bool IsVolatile);
2387330f729Sjoerg     /// Emits atomic update.
2397330f729Sjoerg     /// \param AO Atomic ordering.
2407330f729Sjoerg     void EmitAtomicUpdate(llvm::AtomicOrdering AO, RValue UpdateRVal,
2417330f729Sjoerg                           bool IsVolatile);
2427330f729Sjoerg 
2437330f729Sjoerg     /// Materialize an atomic r-value in atomic-layout memory.
2447330f729Sjoerg     Address materializeRValue(RValue rvalue) const;
2457330f729Sjoerg 
2467330f729Sjoerg     /// Creates temp alloca for intermediate operations on atomic value.
2477330f729Sjoerg     Address CreateTempAlloca() const;
2487330f729Sjoerg   private:
2497330f729Sjoerg     bool requiresMemSetZero(llvm::Type *type) const;
2507330f729Sjoerg 
2517330f729Sjoerg 
2527330f729Sjoerg     /// Emits atomic load as a libcall.
2537330f729Sjoerg     void EmitAtomicLoadLibcall(llvm::Value *AddForLoaded,
2547330f729Sjoerg                                llvm::AtomicOrdering AO, bool IsVolatile);
2557330f729Sjoerg     /// Emits atomic load as LLVM instruction.
2567330f729Sjoerg     llvm::Value *EmitAtomicLoadOp(llvm::AtomicOrdering AO, bool IsVolatile);
2577330f729Sjoerg     /// Emits atomic compare-and-exchange op as a libcall.
2587330f729Sjoerg     llvm::Value *EmitAtomicCompareExchangeLibcall(
2597330f729Sjoerg         llvm::Value *ExpectedAddr, llvm::Value *DesiredAddr,
2607330f729Sjoerg         llvm::AtomicOrdering Success =
2617330f729Sjoerg             llvm::AtomicOrdering::SequentiallyConsistent,
2627330f729Sjoerg         llvm::AtomicOrdering Failure =
2637330f729Sjoerg             llvm::AtomicOrdering::SequentiallyConsistent);
2647330f729Sjoerg     /// Emits atomic compare-and-exchange op as LLVM instruction.
2657330f729Sjoerg     std::pair<llvm::Value *, llvm::Value *> EmitAtomicCompareExchangeOp(
2667330f729Sjoerg         llvm::Value *ExpectedVal, llvm::Value *DesiredVal,
2677330f729Sjoerg         llvm::AtomicOrdering Success =
2687330f729Sjoerg             llvm::AtomicOrdering::SequentiallyConsistent,
2697330f729Sjoerg         llvm::AtomicOrdering Failure =
2707330f729Sjoerg             llvm::AtomicOrdering::SequentiallyConsistent,
2717330f729Sjoerg         bool IsWeak = false);
2727330f729Sjoerg     /// Emit atomic update as libcalls.
2737330f729Sjoerg     void
2747330f729Sjoerg     EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO,
2757330f729Sjoerg                             const llvm::function_ref<RValue(RValue)> &UpdateOp,
2767330f729Sjoerg                             bool IsVolatile);
2777330f729Sjoerg     /// Emit atomic update as LLVM instructions.
2787330f729Sjoerg     void EmitAtomicUpdateOp(llvm::AtomicOrdering AO,
2797330f729Sjoerg                             const llvm::function_ref<RValue(RValue)> &UpdateOp,
2807330f729Sjoerg                             bool IsVolatile);
2817330f729Sjoerg     /// Emit atomic update as libcalls.
2827330f729Sjoerg     void EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO, RValue UpdateRVal,
2837330f729Sjoerg                                  bool IsVolatile);
2847330f729Sjoerg     /// Emit atomic update as LLVM instructions.
2857330f729Sjoerg     void EmitAtomicUpdateOp(llvm::AtomicOrdering AO, RValue UpdateRal,
2867330f729Sjoerg                             bool IsVolatile);
2877330f729Sjoerg   };
2887330f729Sjoerg }
2897330f729Sjoerg 
CreateTempAlloca() const2907330f729Sjoerg Address AtomicInfo::CreateTempAlloca() const {
2917330f729Sjoerg   Address TempAlloca = CGF.CreateMemTemp(
2927330f729Sjoerg       (LVal.isBitField() && ValueSizeInBits > AtomicSizeInBits) ? ValueTy
2937330f729Sjoerg                                                                 : AtomicTy,
2947330f729Sjoerg       getAtomicAlignment(),
2957330f729Sjoerg       "atomic-temp");
2967330f729Sjoerg   // Cast to pointer to value type for bitfields.
2977330f729Sjoerg   if (LVal.isBitField())
2987330f729Sjoerg     return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(
2997330f729Sjoerg         TempAlloca, getAtomicAddress().getType());
3007330f729Sjoerg   return TempAlloca;
3017330f729Sjoerg }
3027330f729Sjoerg 
emitAtomicLibcall(CodeGenFunction & CGF,StringRef fnName,QualType resultType,CallArgList & args)3037330f729Sjoerg static RValue emitAtomicLibcall(CodeGenFunction &CGF,
3047330f729Sjoerg                                 StringRef fnName,
3057330f729Sjoerg                                 QualType resultType,
3067330f729Sjoerg                                 CallArgList &args) {
3077330f729Sjoerg   const CGFunctionInfo &fnInfo =
3087330f729Sjoerg     CGF.CGM.getTypes().arrangeBuiltinFunctionCall(resultType, args);
3097330f729Sjoerg   llvm::FunctionType *fnTy = CGF.CGM.getTypes().GetFunctionType(fnInfo);
310*e038c9c4Sjoerg   llvm::AttrBuilder fnAttrB;
311*e038c9c4Sjoerg   fnAttrB.addAttribute(llvm::Attribute::NoUnwind);
312*e038c9c4Sjoerg   fnAttrB.addAttribute(llvm::Attribute::WillReturn);
313*e038c9c4Sjoerg   llvm::AttributeList fnAttrs = llvm::AttributeList::get(
314*e038c9c4Sjoerg       CGF.getLLVMContext(), llvm::AttributeList::FunctionIndex, fnAttrB);
315*e038c9c4Sjoerg 
316*e038c9c4Sjoerg   llvm::FunctionCallee fn =
317*e038c9c4Sjoerg       CGF.CGM.CreateRuntimeFunction(fnTy, fnName, fnAttrs);
3187330f729Sjoerg   auto callee = CGCallee::forDirect(fn);
3197330f729Sjoerg   return CGF.EmitCall(fnInfo, callee, ReturnValueSlot(), args);
3207330f729Sjoerg }
3217330f729Sjoerg 
3227330f729Sjoerg /// Does a store of the given IR type modify the full expected width?
isFullSizeType(CodeGenModule & CGM,llvm::Type * type,uint64_t expectedSize)3237330f729Sjoerg static bool isFullSizeType(CodeGenModule &CGM, llvm::Type *type,
3247330f729Sjoerg                            uint64_t expectedSize) {
3257330f729Sjoerg   return (CGM.getDataLayout().getTypeStoreSize(type) * 8 == expectedSize);
3267330f729Sjoerg }
3277330f729Sjoerg 
3287330f729Sjoerg /// Does the atomic type require memsetting to zero before initialization?
3297330f729Sjoerg ///
3307330f729Sjoerg /// The IR type is provided as a way of making certain queries faster.
requiresMemSetZero(llvm::Type * type) const3317330f729Sjoerg bool AtomicInfo::requiresMemSetZero(llvm::Type *type) const {
3327330f729Sjoerg   // If the atomic type has size padding, we definitely need a memset.
3337330f729Sjoerg   if (hasPadding()) return true;
3347330f729Sjoerg 
3357330f729Sjoerg   // Otherwise, do some simple heuristics to try to avoid it:
3367330f729Sjoerg   switch (getEvaluationKind()) {
3377330f729Sjoerg   // For scalars and complexes, check whether the store size of the
3387330f729Sjoerg   // type uses the full size.
3397330f729Sjoerg   case TEK_Scalar:
3407330f729Sjoerg     return !isFullSizeType(CGF.CGM, type, AtomicSizeInBits);
3417330f729Sjoerg   case TEK_Complex:
3427330f729Sjoerg     return !isFullSizeType(CGF.CGM, type->getStructElementType(0),
3437330f729Sjoerg                            AtomicSizeInBits / 2);
3447330f729Sjoerg 
3457330f729Sjoerg   // Padding in structs has an undefined bit pattern.  User beware.
3467330f729Sjoerg   case TEK_Aggregate:
3477330f729Sjoerg     return false;
3487330f729Sjoerg   }
3497330f729Sjoerg   llvm_unreachable("bad evaluation kind");
3507330f729Sjoerg }
3517330f729Sjoerg 
emitMemSetZeroIfNecessary() const3527330f729Sjoerg bool AtomicInfo::emitMemSetZeroIfNecessary() const {
3537330f729Sjoerg   assert(LVal.isSimple());
354*e038c9c4Sjoerg   llvm::Value *addr = LVal.getPointer(CGF);
3557330f729Sjoerg   if (!requiresMemSetZero(addr->getType()->getPointerElementType()))
3567330f729Sjoerg     return false;
3577330f729Sjoerg 
3587330f729Sjoerg   CGF.Builder.CreateMemSet(
3597330f729Sjoerg       addr, llvm::ConstantInt::get(CGF.Int8Ty, 0),
3607330f729Sjoerg       CGF.getContext().toCharUnitsFromBits(AtomicSizeInBits).getQuantity(),
361*e038c9c4Sjoerg       LVal.getAlignment().getAsAlign());
3627330f729Sjoerg   return true;
3637330f729Sjoerg }
3647330f729Sjoerg 
emitAtomicCmpXchg(CodeGenFunction & CGF,AtomicExpr * E,bool IsWeak,Address Dest,Address Ptr,Address Val1,Address Val2,uint64_t Size,llvm::AtomicOrdering SuccessOrder,llvm::AtomicOrdering FailureOrder,llvm::SyncScope::ID Scope)3657330f729Sjoerg static void emitAtomicCmpXchg(CodeGenFunction &CGF, AtomicExpr *E, bool IsWeak,
3667330f729Sjoerg                               Address Dest, Address Ptr,
3677330f729Sjoerg                               Address Val1, Address Val2,
3687330f729Sjoerg                               uint64_t Size,
3697330f729Sjoerg                               llvm::AtomicOrdering SuccessOrder,
3707330f729Sjoerg                               llvm::AtomicOrdering FailureOrder,
3717330f729Sjoerg                               llvm::SyncScope::ID Scope) {
3727330f729Sjoerg   // Note that cmpxchg doesn't support weak cmpxchg, at least at the moment.
3737330f729Sjoerg   llvm::Value *Expected = CGF.Builder.CreateLoad(Val1);
3747330f729Sjoerg   llvm::Value *Desired = CGF.Builder.CreateLoad(Val2);
3757330f729Sjoerg 
3767330f729Sjoerg   llvm::AtomicCmpXchgInst *Pair = CGF.Builder.CreateAtomicCmpXchg(
3777330f729Sjoerg       Ptr.getPointer(), Expected, Desired, SuccessOrder, FailureOrder,
3787330f729Sjoerg       Scope);
3797330f729Sjoerg   Pair->setVolatile(E->isVolatile());
3807330f729Sjoerg   Pair->setWeak(IsWeak);
3817330f729Sjoerg 
3827330f729Sjoerg   // Cmp holds the result of the compare-exchange operation: true on success,
3837330f729Sjoerg   // false on failure.
3847330f729Sjoerg   llvm::Value *Old = CGF.Builder.CreateExtractValue(Pair, 0);
3857330f729Sjoerg   llvm::Value *Cmp = CGF.Builder.CreateExtractValue(Pair, 1);
3867330f729Sjoerg 
3877330f729Sjoerg   // This basic block is used to hold the store instruction if the operation
3887330f729Sjoerg   // failed.
3897330f729Sjoerg   llvm::BasicBlock *StoreExpectedBB =
3907330f729Sjoerg       CGF.createBasicBlock("cmpxchg.store_expected", CGF.CurFn);
3917330f729Sjoerg 
3927330f729Sjoerg   // This basic block is the exit point of the operation, we should end up
3937330f729Sjoerg   // here regardless of whether or not the operation succeeded.
3947330f729Sjoerg   llvm::BasicBlock *ContinueBB =
3957330f729Sjoerg       CGF.createBasicBlock("cmpxchg.continue", CGF.CurFn);
3967330f729Sjoerg 
3977330f729Sjoerg   // Update Expected if Expected isn't equal to Old, otherwise branch to the
3987330f729Sjoerg   // exit point.
3997330f729Sjoerg   CGF.Builder.CreateCondBr(Cmp, ContinueBB, StoreExpectedBB);
4007330f729Sjoerg 
4017330f729Sjoerg   CGF.Builder.SetInsertPoint(StoreExpectedBB);
4027330f729Sjoerg   // Update the memory at Expected with Old's value.
4037330f729Sjoerg   CGF.Builder.CreateStore(Old, Val1);
4047330f729Sjoerg   // Finally, branch to the exit point.
4057330f729Sjoerg   CGF.Builder.CreateBr(ContinueBB);
4067330f729Sjoerg 
4077330f729Sjoerg   CGF.Builder.SetInsertPoint(ContinueBB);
4087330f729Sjoerg   // Update the memory at Dest with Cmp's value.
4097330f729Sjoerg   CGF.EmitStoreOfScalar(Cmp, CGF.MakeAddrLValue(Dest, E->getType()));
4107330f729Sjoerg }
4117330f729Sjoerg 
4127330f729Sjoerg /// Given an ordering required on success, emit all possible cmpxchg
4137330f729Sjoerg /// instructions to cope with the provided (but possibly only dynamically known)
4147330f729Sjoerg /// FailureOrder.
emitAtomicCmpXchgFailureSet(CodeGenFunction & CGF,AtomicExpr * E,bool IsWeak,Address Dest,Address Ptr,Address Val1,Address Val2,llvm::Value * FailureOrderVal,uint64_t Size,llvm::AtomicOrdering SuccessOrder,llvm::SyncScope::ID Scope)4157330f729Sjoerg static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,
4167330f729Sjoerg                                         bool IsWeak, Address Dest, Address Ptr,
4177330f729Sjoerg                                         Address Val1, Address Val2,
4187330f729Sjoerg                                         llvm::Value *FailureOrderVal,
4197330f729Sjoerg                                         uint64_t Size,
4207330f729Sjoerg                                         llvm::AtomicOrdering SuccessOrder,
4217330f729Sjoerg                                         llvm::SyncScope::ID Scope) {
4227330f729Sjoerg   llvm::AtomicOrdering FailureOrder;
4237330f729Sjoerg   if (llvm::ConstantInt *FO = dyn_cast<llvm::ConstantInt>(FailureOrderVal)) {
4247330f729Sjoerg     auto FOS = FO->getSExtValue();
4257330f729Sjoerg     if (!llvm::isValidAtomicOrderingCABI(FOS))
4267330f729Sjoerg       FailureOrder = llvm::AtomicOrdering::Monotonic;
4277330f729Sjoerg     else
4287330f729Sjoerg       switch ((llvm::AtomicOrderingCABI)FOS) {
4297330f729Sjoerg       case llvm::AtomicOrderingCABI::relaxed:
430*e038c9c4Sjoerg       // 31.7.2.18: "The failure argument shall not be memory_order_release
431*e038c9c4Sjoerg       // nor memory_order_acq_rel". Fallback to monotonic.
4327330f729Sjoerg       case llvm::AtomicOrderingCABI::release:
4337330f729Sjoerg       case llvm::AtomicOrderingCABI::acq_rel:
4347330f729Sjoerg         FailureOrder = llvm::AtomicOrdering::Monotonic;
4357330f729Sjoerg         break;
4367330f729Sjoerg       case llvm::AtomicOrderingCABI::consume:
4377330f729Sjoerg       case llvm::AtomicOrderingCABI::acquire:
4387330f729Sjoerg         FailureOrder = llvm::AtomicOrdering::Acquire;
4397330f729Sjoerg         break;
4407330f729Sjoerg       case llvm::AtomicOrderingCABI::seq_cst:
4417330f729Sjoerg         FailureOrder = llvm::AtomicOrdering::SequentiallyConsistent;
4427330f729Sjoerg         break;
4437330f729Sjoerg       }
444*e038c9c4Sjoerg     // Prior to c++17, "the failure argument shall be no stronger than the
445*e038c9c4Sjoerg     // success argument". This condition has been lifted and the only
446*e038c9c4Sjoerg     // precondition is 31.7.2.18. Effectively treat this as a DR and skip
447*e038c9c4Sjoerg     // language version checks.
4487330f729Sjoerg     emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, SuccessOrder,
4497330f729Sjoerg                       FailureOrder, Scope);
4507330f729Sjoerg     return;
4517330f729Sjoerg   }
4527330f729Sjoerg 
4537330f729Sjoerg   // Create all the relevant BB's
454*e038c9c4Sjoerg   auto *MonotonicBB = CGF.createBasicBlock("monotonic_fail", CGF.CurFn);
455*e038c9c4Sjoerg   auto *AcquireBB = CGF.createBasicBlock("acquire_fail", CGF.CurFn);
456*e038c9c4Sjoerg   auto *SeqCstBB = CGF.createBasicBlock("seqcst_fail", CGF.CurFn);
457*e038c9c4Sjoerg   auto *ContBB = CGF.createBasicBlock("atomic.continue", CGF.CurFn);
4587330f729Sjoerg 
4597330f729Sjoerg   // MonotonicBB is arbitrarily chosen as the default case; in practice, this
4607330f729Sjoerg   // doesn't matter unless someone is crazy enough to use something that
4617330f729Sjoerg   // doesn't fold to a constant for the ordering.
462*e038c9c4Sjoerg   llvm::SwitchInst *SI = CGF.Builder.CreateSwitch(FailureOrderVal, MonotonicBB);
463*e038c9c4Sjoerg   // Implemented as acquire, since it's the closest in LLVM.
464*e038c9c4Sjoerg   SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::consume),
465*e038c9c4Sjoerg               AcquireBB);
466*e038c9c4Sjoerg   SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::acquire),
467*e038c9c4Sjoerg               AcquireBB);
468*e038c9c4Sjoerg   SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::seq_cst),
469*e038c9c4Sjoerg               SeqCstBB);
470*e038c9c4Sjoerg 
471*e038c9c4Sjoerg   // Emit all the different atomics
4727330f729Sjoerg   CGF.Builder.SetInsertPoint(MonotonicBB);
4737330f729Sjoerg   emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2,
4747330f729Sjoerg                     Size, SuccessOrder, llvm::AtomicOrdering::Monotonic, Scope);
4757330f729Sjoerg   CGF.Builder.CreateBr(ContBB);
4767330f729Sjoerg 
4777330f729Sjoerg   CGF.Builder.SetInsertPoint(AcquireBB);
478*e038c9c4Sjoerg   emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, SuccessOrder,
479*e038c9c4Sjoerg                     llvm::AtomicOrdering::Acquire, Scope);
4807330f729Sjoerg   CGF.Builder.CreateBr(ContBB);
481*e038c9c4Sjoerg 
4827330f729Sjoerg   CGF.Builder.SetInsertPoint(SeqCstBB);
4837330f729Sjoerg   emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, SuccessOrder,
4847330f729Sjoerg                     llvm::AtomicOrdering::SequentiallyConsistent, Scope);
4857330f729Sjoerg   CGF.Builder.CreateBr(ContBB);
4867330f729Sjoerg 
4877330f729Sjoerg   CGF.Builder.SetInsertPoint(ContBB);
4887330f729Sjoerg }
4897330f729Sjoerg 
490*e038c9c4Sjoerg /// Duplicate the atomic min/max operation in conventional IR for the builtin
491*e038c9c4Sjoerg /// variants that return the new rather than the original value.
EmitPostAtomicMinMax(CGBuilderTy & Builder,AtomicExpr::AtomicOp Op,bool IsSigned,llvm::Value * OldVal,llvm::Value * RHS)492*e038c9c4Sjoerg static llvm::Value *EmitPostAtomicMinMax(CGBuilderTy &Builder,
493*e038c9c4Sjoerg                                          AtomicExpr::AtomicOp Op,
494*e038c9c4Sjoerg                                          bool IsSigned,
495*e038c9c4Sjoerg                                          llvm::Value *OldVal,
496*e038c9c4Sjoerg                                          llvm::Value *RHS) {
497*e038c9c4Sjoerg   llvm::CmpInst::Predicate Pred;
498*e038c9c4Sjoerg   switch (Op) {
499*e038c9c4Sjoerg   default:
500*e038c9c4Sjoerg     llvm_unreachable("Unexpected min/max operation");
501*e038c9c4Sjoerg   case AtomicExpr::AO__atomic_max_fetch:
502*e038c9c4Sjoerg     Pred = IsSigned ? llvm::CmpInst::ICMP_SGT : llvm::CmpInst::ICMP_UGT;
503*e038c9c4Sjoerg     break;
504*e038c9c4Sjoerg   case AtomicExpr::AO__atomic_min_fetch:
505*e038c9c4Sjoerg     Pred = IsSigned ? llvm::CmpInst::ICMP_SLT : llvm::CmpInst::ICMP_ULT;
506*e038c9c4Sjoerg     break;
507*e038c9c4Sjoerg   }
508*e038c9c4Sjoerg   llvm::Value *Cmp = Builder.CreateICmp(Pred, OldVal, RHS, "tst");
509*e038c9c4Sjoerg   return Builder.CreateSelect(Cmp, OldVal, RHS, "newval");
510*e038c9c4Sjoerg }
511*e038c9c4Sjoerg 
EmitAtomicOp(CodeGenFunction & CGF,AtomicExpr * E,Address Dest,Address Ptr,Address Val1,Address Val2,llvm::Value * IsWeak,llvm::Value * FailureOrder,uint64_t Size,llvm::AtomicOrdering Order,llvm::SyncScope::ID Scope)5127330f729Sjoerg static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,
5137330f729Sjoerg                          Address Ptr, Address Val1, Address Val2,
5147330f729Sjoerg                          llvm::Value *IsWeak, llvm::Value *FailureOrder,
5157330f729Sjoerg                          uint64_t Size, llvm::AtomicOrdering Order,
5167330f729Sjoerg                          llvm::SyncScope::ID Scope) {
5177330f729Sjoerg   llvm::AtomicRMWInst::BinOp Op = llvm::AtomicRMWInst::Add;
518*e038c9c4Sjoerg   bool PostOpMinMax = false;
519*e038c9c4Sjoerg   unsigned PostOp = 0;
5207330f729Sjoerg 
5217330f729Sjoerg   switch (E->getOp()) {
5227330f729Sjoerg   case AtomicExpr::AO__c11_atomic_init:
5237330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_init:
5247330f729Sjoerg     llvm_unreachable("Already handled!");
5257330f729Sjoerg 
5267330f729Sjoerg   case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
5277330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
5287330f729Sjoerg     emitAtomicCmpXchgFailureSet(CGF, E, false, Dest, Ptr, Val1, Val2,
5297330f729Sjoerg                                 FailureOrder, Size, Order, Scope);
5307330f729Sjoerg     return;
5317330f729Sjoerg   case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
5327330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
5337330f729Sjoerg     emitAtomicCmpXchgFailureSet(CGF, E, true, Dest, Ptr, Val1, Val2,
5347330f729Sjoerg                                 FailureOrder, Size, Order, Scope);
5357330f729Sjoerg     return;
5367330f729Sjoerg   case AtomicExpr::AO__atomic_compare_exchange:
5377330f729Sjoerg   case AtomicExpr::AO__atomic_compare_exchange_n: {
5387330f729Sjoerg     if (llvm::ConstantInt *IsWeakC = dyn_cast<llvm::ConstantInt>(IsWeak)) {
5397330f729Sjoerg       emitAtomicCmpXchgFailureSet(CGF, E, IsWeakC->getZExtValue(), Dest, Ptr,
5407330f729Sjoerg                                   Val1, Val2, FailureOrder, Size, Order, Scope);
5417330f729Sjoerg     } else {
5427330f729Sjoerg       // Create all the relevant BB's
5437330f729Sjoerg       llvm::BasicBlock *StrongBB =
5447330f729Sjoerg           CGF.createBasicBlock("cmpxchg.strong", CGF.CurFn);
5457330f729Sjoerg       llvm::BasicBlock *WeakBB = CGF.createBasicBlock("cmxchg.weak", CGF.CurFn);
5467330f729Sjoerg       llvm::BasicBlock *ContBB =
5477330f729Sjoerg           CGF.createBasicBlock("cmpxchg.continue", CGF.CurFn);
5487330f729Sjoerg 
5497330f729Sjoerg       llvm::SwitchInst *SI = CGF.Builder.CreateSwitch(IsWeak, WeakBB);
5507330f729Sjoerg       SI->addCase(CGF.Builder.getInt1(false), StrongBB);
5517330f729Sjoerg 
5527330f729Sjoerg       CGF.Builder.SetInsertPoint(StrongBB);
5537330f729Sjoerg       emitAtomicCmpXchgFailureSet(CGF, E, false, Dest, Ptr, Val1, Val2,
5547330f729Sjoerg                                   FailureOrder, Size, Order, Scope);
5557330f729Sjoerg       CGF.Builder.CreateBr(ContBB);
5567330f729Sjoerg 
5577330f729Sjoerg       CGF.Builder.SetInsertPoint(WeakBB);
5587330f729Sjoerg       emitAtomicCmpXchgFailureSet(CGF, E, true, Dest, Ptr, Val1, Val2,
5597330f729Sjoerg                                   FailureOrder, Size, Order, Scope);
5607330f729Sjoerg       CGF.Builder.CreateBr(ContBB);
5617330f729Sjoerg 
5627330f729Sjoerg       CGF.Builder.SetInsertPoint(ContBB);
5637330f729Sjoerg     }
5647330f729Sjoerg     return;
5657330f729Sjoerg   }
5667330f729Sjoerg   case AtomicExpr::AO__c11_atomic_load:
5677330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_load:
5687330f729Sjoerg   case AtomicExpr::AO__atomic_load_n:
5697330f729Sjoerg   case AtomicExpr::AO__atomic_load: {
5707330f729Sjoerg     llvm::LoadInst *Load = CGF.Builder.CreateLoad(Ptr);
5717330f729Sjoerg     Load->setAtomic(Order, Scope);
5727330f729Sjoerg     Load->setVolatile(E->isVolatile());
5737330f729Sjoerg     CGF.Builder.CreateStore(Load, Dest);
5747330f729Sjoerg     return;
5757330f729Sjoerg   }
5767330f729Sjoerg 
5777330f729Sjoerg   case AtomicExpr::AO__c11_atomic_store:
5787330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_store:
5797330f729Sjoerg   case AtomicExpr::AO__atomic_store:
5807330f729Sjoerg   case AtomicExpr::AO__atomic_store_n: {
5817330f729Sjoerg     llvm::Value *LoadVal1 = CGF.Builder.CreateLoad(Val1);
5827330f729Sjoerg     llvm::StoreInst *Store = CGF.Builder.CreateStore(LoadVal1, Ptr);
5837330f729Sjoerg     Store->setAtomic(Order, Scope);
5847330f729Sjoerg     Store->setVolatile(E->isVolatile());
5857330f729Sjoerg     return;
5867330f729Sjoerg   }
5877330f729Sjoerg 
5887330f729Sjoerg   case AtomicExpr::AO__c11_atomic_exchange:
5897330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_exchange:
5907330f729Sjoerg   case AtomicExpr::AO__atomic_exchange_n:
5917330f729Sjoerg   case AtomicExpr::AO__atomic_exchange:
5927330f729Sjoerg     Op = llvm::AtomicRMWInst::Xchg;
5937330f729Sjoerg     break;
5947330f729Sjoerg 
5957330f729Sjoerg   case AtomicExpr::AO__atomic_add_fetch:
596*e038c9c4Sjoerg     PostOp = E->getValueType()->isFloatingType() ? llvm::Instruction::FAdd
597*e038c9c4Sjoerg                                                  : llvm::Instruction::Add;
5987330f729Sjoerg     LLVM_FALLTHROUGH;
5997330f729Sjoerg   case AtomicExpr::AO__c11_atomic_fetch_add:
6007330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_fetch_add:
6017330f729Sjoerg   case AtomicExpr::AO__atomic_fetch_add:
602*e038c9c4Sjoerg     Op = E->getValueType()->isFloatingType() ? llvm::AtomicRMWInst::FAdd
603*e038c9c4Sjoerg                                              : llvm::AtomicRMWInst::Add;
6047330f729Sjoerg     break;
6057330f729Sjoerg 
6067330f729Sjoerg   case AtomicExpr::AO__atomic_sub_fetch:
607*e038c9c4Sjoerg     PostOp = E->getValueType()->isFloatingType() ? llvm::Instruction::FSub
608*e038c9c4Sjoerg                                                  : llvm::Instruction::Sub;
6097330f729Sjoerg     LLVM_FALLTHROUGH;
6107330f729Sjoerg   case AtomicExpr::AO__c11_atomic_fetch_sub:
6117330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_fetch_sub:
6127330f729Sjoerg   case AtomicExpr::AO__atomic_fetch_sub:
613*e038c9c4Sjoerg     Op = E->getValueType()->isFloatingType() ? llvm::AtomicRMWInst::FSub
614*e038c9c4Sjoerg                                              : llvm::AtomicRMWInst::Sub;
6157330f729Sjoerg     break;
6167330f729Sjoerg 
617*e038c9c4Sjoerg   case AtomicExpr::AO__atomic_min_fetch:
618*e038c9c4Sjoerg     PostOpMinMax = true;
619*e038c9c4Sjoerg     LLVM_FALLTHROUGH;
620*e038c9c4Sjoerg   case AtomicExpr::AO__c11_atomic_fetch_min:
6217330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_fetch_min:
6227330f729Sjoerg   case AtomicExpr::AO__atomic_fetch_min:
6237330f729Sjoerg     Op = E->getValueType()->isSignedIntegerType() ? llvm::AtomicRMWInst::Min
6247330f729Sjoerg                                                   : llvm::AtomicRMWInst::UMin;
6257330f729Sjoerg     break;
6267330f729Sjoerg 
627*e038c9c4Sjoerg   case AtomicExpr::AO__atomic_max_fetch:
628*e038c9c4Sjoerg     PostOpMinMax = true;
629*e038c9c4Sjoerg     LLVM_FALLTHROUGH;
630*e038c9c4Sjoerg   case AtomicExpr::AO__c11_atomic_fetch_max:
6317330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_fetch_max:
6327330f729Sjoerg   case AtomicExpr::AO__atomic_fetch_max:
6337330f729Sjoerg     Op = E->getValueType()->isSignedIntegerType() ? llvm::AtomicRMWInst::Max
6347330f729Sjoerg                                                   : llvm::AtomicRMWInst::UMax;
6357330f729Sjoerg     break;
6367330f729Sjoerg 
6377330f729Sjoerg   case AtomicExpr::AO__atomic_and_fetch:
6387330f729Sjoerg     PostOp = llvm::Instruction::And;
6397330f729Sjoerg     LLVM_FALLTHROUGH;
6407330f729Sjoerg   case AtomicExpr::AO__c11_atomic_fetch_and:
6417330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_fetch_and:
6427330f729Sjoerg   case AtomicExpr::AO__atomic_fetch_and:
6437330f729Sjoerg     Op = llvm::AtomicRMWInst::And;
6447330f729Sjoerg     break;
6457330f729Sjoerg 
6467330f729Sjoerg   case AtomicExpr::AO__atomic_or_fetch:
6477330f729Sjoerg     PostOp = llvm::Instruction::Or;
6487330f729Sjoerg     LLVM_FALLTHROUGH;
6497330f729Sjoerg   case AtomicExpr::AO__c11_atomic_fetch_or:
6507330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_fetch_or:
6517330f729Sjoerg   case AtomicExpr::AO__atomic_fetch_or:
6527330f729Sjoerg     Op = llvm::AtomicRMWInst::Or;
6537330f729Sjoerg     break;
6547330f729Sjoerg 
6557330f729Sjoerg   case AtomicExpr::AO__atomic_xor_fetch:
6567330f729Sjoerg     PostOp = llvm::Instruction::Xor;
6577330f729Sjoerg     LLVM_FALLTHROUGH;
6587330f729Sjoerg   case AtomicExpr::AO__c11_atomic_fetch_xor:
6597330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_fetch_xor:
6607330f729Sjoerg   case AtomicExpr::AO__atomic_fetch_xor:
6617330f729Sjoerg     Op = llvm::AtomicRMWInst::Xor;
6627330f729Sjoerg     break;
6637330f729Sjoerg 
6647330f729Sjoerg   case AtomicExpr::AO__atomic_nand_fetch:
6657330f729Sjoerg     PostOp = llvm::Instruction::And; // the NOT is special cased below
6667330f729Sjoerg     LLVM_FALLTHROUGH;
6677330f729Sjoerg   case AtomicExpr::AO__atomic_fetch_nand:
6687330f729Sjoerg     Op = llvm::AtomicRMWInst::Nand;
6697330f729Sjoerg     break;
6707330f729Sjoerg   }
6717330f729Sjoerg 
6727330f729Sjoerg   llvm::Value *LoadVal1 = CGF.Builder.CreateLoad(Val1);
6737330f729Sjoerg   llvm::AtomicRMWInst *RMWI =
6747330f729Sjoerg       CGF.Builder.CreateAtomicRMW(Op, Ptr.getPointer(), LoadVal1, Order, Scope);
6757330f729Sjoerg   RMWI->setVolatile(E->isVolatile());
6767330f729Sjoerg 
6777330f729Sjoerg   // For __atomic_*_fetch operations, perform the operation again to
6787330f729Sjoerg   // determine the value which was written.
6797330f729Sjoerg   llvm::Value *Result = RMWI;
680*e038c9c4Sjoerg   if (PostOpMinMax)
681*e038c9c4Sjoerg     Result = EmitPostAtomicMinMax(CGF.Builder, E->getOp(),
682*e038c9c4Sjoerg                                   E->getValueType()->isSignedIntegerType(),
683*e038c9c4Sjoerg                                   RMWI, LoadVal1);
684*e038c9c4Sjoerg   else if (PostOp)
685*e038c9c4Sjoerg     Result = CGF.Builder.CreateBinOp((llvm::Instruction::BinaryOps)PostOp, RMWI,
686*e038c9c4Sjoerg                                      LoadVal1);
6877330f729Sjoerg   if (E->getOp() == AtomicExpr::AO__atomic_nand_fetch)
6887330f729Sjoerg     Result = CGF.Builder.CreateNot(Result);
6897330f729Sjoerg   CGF.Builder.CreateStore(Result, Dest);
6907330f729Sjoerg }
6917330f729Sjoerg 
6927330f729Sjoerg // This function emits any expression (scalar, complex, or aggregate)
6937330f729Sjoerg // into a temporary alloca.
6947330f729Sjoerg static Address
EmitValToTemp(CodeGenFunction & CGF,Expr * E)6957330f729Sjoerg EmitValToTemp(CodeGenFunction &CGF, Expr *E) {
6967330f729Sjoerg   Address DeclPtr = CGF.CreateMemTemp(E->getType(), ".atomictmp");
6977330f729Sjoerg   CGF.EmitAnyExprToMem(E, DeclPtr, E->getType().getQualifiers(),
6987330f729Sjoerg                        /*Init*/ true);
6997330f729Sjoerg   return DeclPtr;
7007330f729Sjoerg }
7017330f729Sjoerg 
EmitAtomicOp(CodeGenFunction & CGF,AtomicExpr * Expr,Address Dest,Address Ptr,Address Val1,Address Val2,llvm::Value * IsWeak,llvm::Value * FailureOrder,uint64_t Size,llvm::AtomicOrdering Order,llvm::Value * Scope)7027330f729Sjoerg static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *Expr, Address Dest,
7037330f729Sjoerg                          Address Ptr, Address Val1, Address Val2,
7047330f729Sjoerg                          llvm::Value *IsWeak, llvm::Value *FailureOrder,
7057330f729Sjoerg                          uint64_t Size, llvm::AtomicOrdering Order,
7067330f729Sjoerg                          llvm::Value *Scope) {
7077330f729Sjoerg   auto ScopeModel = Expr->getScopeModel();
7087330f729Sjoerg 
7097330f729Sjoerg   // LLVM atomic instructions always have synch scope. If clang atomic
7107330f729Sjoerg   // expression has no scope operand, use default LLVM synch scope.
7117330f729Sjoerg   if (!ScopeModel) {
7127330f729Sjoerg     EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, IsWeak, FailureOrder, Size,
7137330f729Sjoerg                  Order, CGF.CGM.getLLVMContext().getOrInsertSyncScopeID(""));
7147330f729Sjoerg     return;
7157330f729Sjoerg   }
7167330f729Sjoerg 
7177330f729Sjoerg   // Handle constant scope.
7187330f729Sjoerg   if (auto SC = dyn_cast<llvm::ConstantInt>(Scope)) {
7197330f729Sjoerg     auto SCID = CGF.getTargetHooks().getLLVMSyncScopeID(
7207330f729Sjoerg         CGF.CGM.getLangOpts(), ScopeModel->map(SC->getZExtValue()),
7217330f729Sjoerg         Order, CGF.CGM.getLLVMContext());
7227330f729Sjoerg     EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, IsWeak, FailureOrder, Size,
7237330f729Sjoerg                  Order, SCID);
7247330f729Sjoerg     return;
7257330f729Sjoerg   }
7267330f729Sjoerg 
7277330f729Sjoerg   // Handle non-constant scope.
7287330f729Sjoerg   auto &Builder = CGF.Builder;
7297330f729Sjoerg   auto Scopes = ScopeModel->getRuntimeValues();
7307330f729Sjoerg   llvm::DenseMap<unsigned, llvm::BasicBlock *> BB;
7317330f729Sjoerg   for (auto S : Scopes)
7327330f729Sjoerg     BB[S] = CGF.createBasicBlock(getAsString(ScopeModel->map(S)), CGF.CurFn);
7337330f729Sjoerg 
7347330f729Sjoerg   llvm::BasicBlock *ContBB =
7357330f729Sjoerg       CGF.createBasicBlock("atomic.scope.continue", CGF.CurFn);
7367330f729Sjoerg 
7377330f729Sjoerg   auto *SC = Builder.CreateIntCast(Scope, Builder.getInt32Ty(), false);
7387330f729Sjoerg   // If unsupported synch scope is encountered at run time, assume a fallback
7397330f729Sjoerg   // synch scope value.
7407330f729Sjoerg   auto FallBack = ScopeModel->getFallBackValue();
7417330f729Sjoerg   llvm::SwitchInst *SI = Builder.CreateSwitch(SC, BB[FallBack]);
7427330f729Sjoerg   for (auto S : Scopes) {
7437330f729Sjoerg     auto *B = BB[S];
7447330f729Sjoerg     if (S != FallBack)
7457330f729Sjoerg       SI->addCase(Builder.getInt32(S), B);
7467330f729Sjoerg 
7477330f729Sjoerg     Builder.SetInsertPoint(B);
7487330f729Sjoerg     EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, IsWeak, FailureOrder, Size,
7497330f729Sjoerg                  Order,
7507330f729Sjoerg                  CGF.getTargetHooks().getLLVMSyncScopeID(CGF.CGM.getLangOpts(),
7517330f729Sjoerg                                                          ScopeModel->map(S),
7527330f729Sjoerg                                                          Order,
7537330f729Sjoerg                                                          CGF.getLLVMContext()));
7547330f729Sjoerg     Builder.CreateBr(ContBB);
7557330f729Sjoerg   }
7567330f729Sjoerg 
7577330f729Sjoerg   Builder.SetInsertPoint(ContBB);
7587330f729Sjoerg }
7597330f729Sjoerg 
7607330f729Sjoerg static void
AddDirectArgument(CodeGenFunction & CGF,CallArgList & Args,bool UseOptimizedLibcall,llvm::Value * Val,QualType ValTy,SourceLocation Loc,CharUnits SizeInChars)7617330f729Sjoerg AddDirectArgument(CodeGenFunction &CGF, CallArgList &Args,
7627330f729Sjoerg                   bool UseOptimizedLibcall, llvm::Value *Val, QualType ValTy,
7637330f729Sjoerg                   SourceLocation Loc, CharUnits SizeInChars) {
7647330f729Sjoerg   if (UseOptimizedLibcall) {
7657330f729Sjoerg     // Load value and pass it to the function directly.
7667330f729Sjoerg     CharUnits Align = CGF.getContext().getTypeAlignInChars(ValTy);
7677330f729Sjoerg     int64_t SizeInBits = CGF.getContext().toBits(SizeInChars);
7687330f729Sjoerg     ValTy =
7697330f729Sjoerg         CGF.getContext().getIntTypeForBitwidth(SizeInBits, /*Signed=*/false);
7707330f729Sjoerg     llvm::Type *IPtrTy = llvm::IntegerType::get(CGF.getLLVMContext(),
7717330f729Sjoerg                                                 SizeInBits)->getPointerTo();
7727330f729Sjoerg     Address Ptr = Address(CGF.Builder.CreateBitCast(Val, IPtrTy), Align);
7737330f729Sjoerg     Val = CGF.EmitLoadOfScalar(Ptr, false,
7747330f729Sjoerg                                CGF.getContext().getPointerType(ValTy),
7757330f729Sjoerg                                Loc);
7767330f729Sjoerg     // Coerce the value into an appropriately sized integer type.
7777330f729Sjoerg     Args.add(RValue::get(Val), ValTy);
7787330f729Sjoerg   } else {
7797330f729Sjoerg     // Non-optimized functions always take a reference.
7807330f729Sjoerg     Args.add(RValue::get(CGF.EmitCastToVoidPtr(Val)),
7817330f729Sjoerg                          CGF.getContext().VoidPtrTy);
7827330f729Sjoerg   }
7837330f729Sjoerg }
7847330f729Sjoerg 
EmitAtomicExpr(AtomicExpr * E)7857330f729Sjoerg RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {
7867330f729Sjoerg   QualType AtomicTy = E->getPtr()->getType()->getPointeeType();
7877330f729Sjoerg   QualType MemTy = AtomicTy;
7887330f729Sjoerg   if (const AtomicType *AT = AtomicTy->getAs<AtomicType>())
7897330f729Sjoerg     MemTy = AT->getValueType();
7907330f729Sjoerg   llvm::Value *IsWeak = nullptr, *OrderFail = nullptr;
7917330f729Sjoerg 
7927330f729Sjoerg   Address Val1 = Address::invalid();
7937330f729Sjoerg   Address Val2 = Address::invalid();
7947330f729Sjoerg   Address Dest = Address::invalid();
7957330f729Sjoerg   Address Ptr = EmitPointerWithAlignment(E->getPtr());
7967330f729Sjoerg 
7977330f729Sjoerg   if (E->getOp() == AtomicExpr::AO__c11_atomic_init ||
7987330f729Sjoerg       E->getOp() == AtomicExpr::AO__opencl_atomic_init) {
7997330f729Sjoerg     LValue lvalue = MakeAddrLValue(Ptr, AtomicTy);
8007330f729Sjoerg     EmitAtomicInit(E->getVal1(), lvalue);
8017330f729Sjoerg     return RValue::get(nullptr);
8027330f729Sjoerg   }
8037330f729Sjoerg 
804*e038c9c4Sjoerg   auto TInfo = getContext().getTypeInfoInChars(AtomicTy);
805*e038c9c4Sjoerg   uint64_t Size = TInfo.Width.getQuantity();
8067330f729Sjoerg   unsigned MaxInlineWidthInBits = getTarget().getMaxAtomicInlineWidth();
8077330f729Sjoerg 
808*e038c9c4Sjoerg   bool Oversized = getContext().toBits(TInfo.Width) > MaxInlineWidthInBits;
809*e038c9c4Sjoerg   bool Misaligned = (Ptr.getAlignment() % TInfo.Width) != 0;
8107330f729Sjoerg   bool UseLibcall = Misaligned | Oversized;
811*e038c9c4Sjoerg   bool ShouldCastToIntPtrTy = true;
8127330f729Sjoerg 
813*e038c9c4Sjoerg   CharUnits MaxInlineWidth =
814*e038c9c4Sjoerg       getContext().toCharUnitsFromBits(MaxInlineWidthInBits);
815*e038c9c4Sjoerg 
816*e038c9c4Sjoerg   DiagnosticsEngine &Diags = CGM.getDiags();
817*e038c9c4Sjoerg 
818*e038c9c4Sjoerg   if (Misaligned) {
819*e038c9c4Sjoerg     Diags.Report(E->getBeginLoc(), diag::warn_atomic_op_misaligned)
820*e038c9c4Sjoerg         << (int)TInfo.Width.getQuantity()
821*e038c9c4Sjoerg         << (int)Ptr.getAlignment().getQuantity();
822*e038c9c4Sjoerg   }
823*e038c9c4Sjoerg 
824*e038c9c4Sjoerg   if (Oversized) {
825*e038c9c4Sjoerg     Diags.Report(E->getBeginLoc(), diag::warn_atomic_op_oversized)
826*e038c9c4Sjoerg         << (int)TInfo.Width.getQuantity() << (int)MaxInlineWidth.getQuantity();
8277330f729Sjoerg   }
8287330f729Sjoerg 
8297330f729Sjoerg   llvm::Value *Order = EmitScalarExpr(E->getOrder());
8307330f729Sjoerg   llvm::Value *Scope =
8317330f729Sjoerg       E->getScopeModel() ? EmitScalarExpr(E->getScope()) : nullptr;
8327330f729Sjoerg 
8337330f729Sjoerg   switch (E->getOp()) {
8347330f729Sjoerg   case AtomicExpr::AO__c11_atomic_init:
8357330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_init:
8367330f729Sjoerg     llvm_unreachable("Already handled above with EmitAtomicInit!");
8377330f729Sjoerg 
8387330f729Sjoerg   case AtomicExpr::AO__c11_atomic_load:
8397330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_load:
8407330f729Sjoerg   case AtomicExpr::AO__atomic_load_n:
8417330f729Sjoerg     break;
8427330f729Sjoerg 
8437330f729Sjoerg   case AtomicExpr::AO__atomic_load:
8447330f729Sjoerg     Dest = EmitPointerWithAlignment(E->getVal1());
8457330f729Sjoerg     break;
8467330f729Sjoerg 
8477330f729Sjoerg   case AtomicExpr::AO__atomic_store:
8487330f729Sjoerg     Val1 = EmitPointerWithAlignment(E->getVal1());
8497330f729Sjoerg     break;
8507330f729Sjoerg 
8517330f729Sjoerg   case AtomicExpr::AO__atomic_exchange:
8527330f729Sjoerg     Val1 = EmitPointerWithAlignment(E->getVal1());
8537330f729Sjoerg     Dest = EmitPointerWithAlignment(E->getVal2());
8547330f729Sjoerg     break;
8557330f729Sjoerg 
8567330f729Sjoerg   case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
8577330f729Sjoerg   case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
8587330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
8597330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
8607330f729Sjoerg   case AtomicExpr::AO__atomic_compare_exchange_n:
8617330f729Sjoerg   case AtomicExpr::AO__atomic_compare_exchange:
8627330f729Sjoerg     Val1 = EmitPointerWithAlignment(E->getVal1());
8637330f729Sjoerg     if (E->getOp() == AtomicExpr::AO__atomic_compare_exchange)
8647330f729Sjoerg       Val2 = EmitPointerWithAlignment(E->getVal2());
8657330f729Sjoerg     else
8667330f729Sjoerg       Val2 = EmitValToTemp(*this, E->getVal2());
8677330f729Sjoerg     OrderFail = EmitScalarExpr(E->getOrderFail());
8687330f729Sjoerg     if (E->getOp() == AtomicExpr::AO__atomic_compare_exchange_n ||
8697330f729Sjoerg         E->getOp() == AtomicExpr::AO__atomic_compare_exchange)
8707330f729Sjoerg       IsWeak = EmitScalarExpr(E->getWeak());
8717330f729Sjoerg     break;
8727330f729Sjoerg 
8737330f729Sjoerg   case AtomicExpr::AO__c11_atomic_fetch_add:
8747330f729Sjoerg   case AtomicExpr::AO__c11_atomic_fetch_sub:
8757330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_fetch_add:
8767330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_fetch_sub:
8777330f729Sjoerg     if (MemTy->isPointerType()) {
8787330f729Sjoerg       // For pointer arithmetic, we're required to do a bit of math:
8797330f729Sjoerg       // adding 1 to an int* is not the same as adding 1 to a uintptr_t.
8807330f729Sjoerg       // ... but only for the C11 builtins. The GNU builtins expect the
8817330f729Sjoerg       // user to multiply by sizeof(T).
8827330f729Sjoerg       QualType Val1Ty = E->getVal1()->getType();
8837330f729Sjoerg       llvm::Value *Val1Scalar = EmitScalarExpr(E->getVal1());
8847330f729Sjoerg       CharUnits PointeeIncAmt =
8857330f729Sjoerg           getContext().getTypeSizeInChars(MemTy->getPointeeType());
8867330f729Sjoerg       Val1Scalar = Builder.CreateMul(Val1Scalar, CGM.getSize(PointeeIncAmt));
8877330f729Sjoerg       auto Temp = CreateMemTemp(Val1Ty, ".atomictmp");
8887330f729Sjoerg       Val1 = Temp;
8897330f729Sjoerg       EmitStoreOfScalar(Val1Scalar, MakeAddrLValue(Temp, Val1Ty));
8907330f729Sjoerg       break;
8917330f729Sjoerg     }
8927330f729Sjoerg     LLVM_FALLTHROUGH;
8937330f729Sjoerg   case AtomicExpr::AO__atomic_fetch_add:
8947330f729Sjoerg   case AtomicExpr::AO__atomic_fetch_sub:
8957330f729Sjoerg   case AtomicExpr::AO__atomic_add_fetch:
8967330f729Sjoerg   case AtomicExpr::AO__atomic_sub_fetch:
897*e038c9c4Sjoerg     ShouldCastToIntPtrTy = !MemTy->isFloatingType();
898*e038c9c4Sjoerg     LLVM_FALLTHROUGH;
899*e038c9c4Sjoerg 
9007330f729Sjoerg   case AtomicExpr::AO__c11_atomic_store:
9017330f729Sjoerg   case AtomicExpr::AO__c11_atomic_exchange:
9027330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_store:
9037330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_exchange:
9047330f729Sjoerg   case AtomicExpr::AO__atomic_store_n:
9057330f729Sjoerg   case AtomicExpr::AO__atomic_exchange_n:
9067330f729Sjoerg   case AtomicExpr::AO__c11_atomic_fetch_and:
9077330f729Sjoerg   case AtomicExpr::AO__c11_atomic_fetch_or:
9087330f729Sjoerg   case AtomicExpr::AO__c11_atomic_fetch_xor:
909*e038c9c4Sjoerg   case AtomicExpr::AO__c11_atomic_fetch_max:
910*e038c9c4Sjoerg   case AtomicExpr::AO__c11_atomic_fetch_min:
9117330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_fetch_and:
9127330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_fetch_or:
9137330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_fetch_xor:
9147330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_fetch_min:
9157330f729Sjoerg   case AtomicExpr::AO__opencl_atomic_fetch_max:
9167330f729Sjoerg   case AtomicExpr::AO__atomic_fetch_and:
9177330f729Sjoerg   case AtomicExpr::AO__atomic_fetch_or:
9187330f729Sjoerg   case AtomicExpr::AO__atomic_fetch_xor:
9197330f729Sjoerg   case AtomicExpr::AO__atomic_fetch_nand:
9207330f729Sjoerg   case AtomicExpr::AO__atomic_and_fetch:
9217330f729Sjoerg   case AtomicExpr::AO__atomic_or_fetch:
9227330f729Sjoerg   case AtomicExpr::AO__atomic_xor_fetch:
9237330f729Sjoerg   case AtomicExpr::AO__atomic_nand_fetch:
924*e038c9c4Sjoerg   case AtomicExpr::AO__atomic_max_fetch:
925*e038c9c4Sjoerg   case AtomicExpr::AO__atomic_min_fetch:
9267330f729Sjoerg   case AtomicExpr::AO__atomic_fetch_max:
927*e038c9c4Sjoerg   case AtomicExpr::AO__atomic_fetch_min:
9287330f729Sjoerg     Val1 = EmitValToTemp(*this, E->getVal1());
9297330f729Sjoerg     break;
9307330f729Sjoerg   }
9317330f729Sjoerg 
9327330f729Sjoerg   QualType RValTy = E->getType().getUnqualifiedType();
9337330f729Sjoerg 
9347330f729Sjoerg   // The inlined atomics only function on iN types, where N is a power of 2. We
9357330f729Sjoerg   // need to make sure (via temporaries if necessary) that all incoming values
9367330f729Sjoerg   // are compatible.
9377330f729Sjoerg   LValue AtomicVal = MakeAddrLValue(Ptr, AtomicTy);
9387330f729Sjoerg   AtomicInfo Atomics(*this, AtomicVal);
9397330f729Sjoerg 
940*e038c9c4Sjoerg   if (ShouldCastToIntPtrTy) {
9417330f729Sjoerg     Ptr = Atomics.emitCastToAtomicIntPointer(Ptr);
942*e038c9c4Sjoerg     if (Val1.isValid())
943*e038c9c4Sjoerg       Val1 = Atomics.convertToAtomicIntPointer(Val1);
944*e038c9c4Sjoerg     if (Val2.isValid())
945*e038c9c4Sjoerg       Val2 = Atomics.convertToAtomicIntPointer(Val2);
946*e038c9c4Sjoerg   }
947*e038c9c4Sjoerg   if (Dest.isValid()) {
948*e038c9c4Sjoerg     if (ShouldCastToIntPtrTy)
9497330f729Sjoerg       Dest = Atomics.emitCastToAtomicIntPointer(Dest);
950*e038c9c4Sjoerg   } else if (E->isCmpXChg())
9517330f729Sjoerg     Dest = CreateMemTemp(RValTy, "cmpxchg.bool");
952*e038c9c4Sjoerg   else if (!RValTy->isVoidType()) {
953*e038c9c4Sjoerg     Dest = Atomics.CreateTempAlloca();
954*e038c9c4Sjoerg     if (ShouldCastToIntPtrTy)
955*e038c9c4Sjoerg       Dest = Atomics.emitCastToAtomicIntPointer(Dest);
956*e038c9c4Sjoerg   }
9577330f729Sjoerg 
9587330f729Sjoerg   // Use a library call.  See: http://gcc.gnu.org/wiki/Atomic/GCCMM/LIbrary .
9597330f729Sjoerg   if (UseLibcall) {
9607330f729Sjoerg     bool UseOptimizedLibcall = false;
9617330f729Sjoerg     switch (E->getOp()) {
9627330f729Sjoerg     case AtomicExpr::AO__c11_atomic_init:
9637330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_init:
9647330f729Sjoerg       llvm_unreachable("Already handled above with EmitAtomicInit!");
9657330f729Sjoerg 
9667330f729Sjoerg     case AtomicExpr::AO__c11_atomic_fetch_add:
9677330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_fetch_add:
9687330f729Sjoerg     case AtomicExpr::AO__atomic_fetch_add:
9697330f729Sjoerg     case AtomicExpr::AO__c11_atomic_fetch_and:
9707330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_fetch_and:
9717330f729Sjoerg     case AtomicExpr::AO__atomic_fetch_and:
9727330f729Sjoerg     case AtomicExpr::AO__c11_atomic_fetch_or:
9737330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_fetch_or:
9747330f729Sjoerg     case AtomicExpr::AO__atomic_fetch_or:
9757330f729Sjoerg     case AtomicExpr::AO__atomic_fetch_nand:
9767330f729Sjoerg     case AtomicExpr::AO__c11_atomic_fetch_sub:
9777330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_fetch_sub:
9787330f729Sjoerg     case AtomicExpr::AO__atomic_fetch_sub:
9797330f729Sjoerg     case AtomicExpr::AO__c11_atomic_fetch_xor:
9807330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_fetch_xor:
9817330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_fetch_min:
9827330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_fetch_max:
9837330f729Sjoerg     case AtomicExpr::AO__atomic_fetch_xor:
984*e038c9c4Sjoerg     case AtomicExpr::AO__c11_atomic_fetch_max:
985*e038c9c4Sjoerg     case AtomicExpr::AO__c11_atomic_fetch_min:
9867330f729Sjoerg     case AtomicExpr::AO__atomic_add_fetch:
9877330f729Sjoerg     case AtomicExpr::AO__atomic_and_fetch:
9887330f729Sjoerg     case AtomicExpr::AO__atomic_nand_fetch:
9897330f729Sjoerg     case AtomicExpr::AO__atomic_or_fetch:
9907330f729Sjoerg     case AtomicExpr::AO__atomic_sub_fetch:
9917330f729Sjoerg     case AtomicExpr::AO__atomic_xor_fetch:
9927330f729Sjoerg     case AtomicExpr::AO__atomic_fetch_max:
993*e038c9c4Sjoerg     case AtomicExpr::AO__atomic_fetch_min:
994*e038c9c4Sjoerg     case AtomicExpr::AO__atomic_max_fetch:
995*e038c9c4Sjoerg     case AtomicExpr::AO__atomic_min_fetch:
9967330f729Sjoerg       // For these, only library calls for certain sizes exist.
9977330f729Sjoerg       UseOptimizedLibcall = true;
9987330f729Sjoerg       break;
9997330f729Sjoerg 
10007330f729Sjoerg     case AtomicExpr::AO__atomic_load:
10017330f729Sjoerg     case AtomicExpr::AO__atomic_store:
10027330f729Sjoerg     case AtomicExpr::AO__atomic_exchange:
10037330f729Sjoerg     case AtomicExpr::AO__atomic_compare_exchange:
10047330f729Sjoerg       // Use the generic version if we don't know that the operand will be
10057330f729Sjoerg       // suitably aligned for the optimized version.
10067330f729Sjoerg       if (Misaligned)
10077330f729Sjoerg         break;
10087330f729Sjoerg       LLVM_FALLTHROUGH;
10097330f729Sjoerg     case AtomicExpr::AO__c11_atomic_load:
10107330f729Sjoerg     case AtomicExpr::AO__c11_atomic_store:
10117330f729Sjoerg     case AtomicExpr::AO__c11_atomic_exchange:
10127330f729Sjoerg     case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
10137330f729Sjoerg     case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
10147330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_load:
10157330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_store:
10167330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_exchange:
10177330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
10187330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
10197330f729Sjoerg     case AtomicExpr::AO__atomic_load_n:
10207330f729Sjoerg     case AtomicExpr::AO__atomic_store_n:
10217330f729Sjoerg     case AtomicExpr::AO__atomic_exchange_n:
10227330f729Sjoerg     case AtomicExpr::AO__atomic_compare_exchange_n:
10237330f729Sjoerg       // Only use optimized library calls for sizes for which they exist.
10247330f729Sjoerg       // FIXME: Size == 16 optimized library functions exist too.
10257330f729Sjoerg       if (Size == 1 || Size == 2 || Size == 4 || Size == 8)
10267330f729Sjoerg         UseOptimizedLibcall = true;
10277330f729Sjoerg       break;
10287330f729Sjoerg     }
10297330f729Sjoerg 
10307330f729Sjoerg     CallArgList Args;
10317330f729Sjoerg     if (!UseOptimizedLibcall) {
10327330f729Sjoerg       // For non-optimized library calls, the size is the first parameter
10337330f729Sjoerg       Args.add(RValue::get(llvm::ConstantInt::get(SizeTy, Size)),
10347330f729Sjoerg                getContext().getSizeType());
10357330f729Sjoerg     }
10367330f729Sjoerg     // Atomic address is the first or second parameter
10377330f729Sjoerg     // The OpenCL atomic library functions only accept pointer arguments to
10387330f729Sjoerg     // generic address space.
10397330f729Sjoerg     auto CastToGenericAddrSpace = [&](llvm::Value *V, QualType PT) {
10407330f729Sjoerg       if (!E->isOpenCL())
10417330f729Sjoerg         return V;
10427330f729Sjoerg       auto AS = PT->castAs<PointerType>()->getPointeeType().getAddressSpace();
10437330f729Sjoerg       if (AS == LangAS::opencl_generic)
10447330f729Sjoerg         return V;
10457330f729Sjoerg       auto DestAS = getContext().getTargetAddressSpace(LangAS::opencl_generic);
10467330f729Sjoerg       auto T = V->getType();
10477330f729Sjoerg       auto *DestType = T->getPointerElementType()->getPointerTo(DestAS);
10487330f729Sjoerg 
10497330f729Sjoerg       return getTargetHooks().performAddrSpaceCast(
10507330f729Sjoerg           *this, V, AS, LangAS::opencl_generic, DestType, false);
10517330f729Sjoerg     };
10527330f729Sjoerg 
10537330f729Sjoerg     Args.add(RValue::get(CastToGenericAddrSpace(
10547330f729Sjoerg                  EmitCastToVoidPtr(Ptr.getPointer()), E->getPtr()->getType())),
10557330f729Sjoerg              getContext().VoidPtrTy);
10567330f729Sjoerg 
10577330f729Sjoerg     std::string LibCallName;
10587330f729Sjoerg     QualType LoweredMemTy =
10597330f729Sjoerg       MemTy->isPointerType() ? getContext().getIntPtrType() : MemTy;
10607330f729Sjoerg     QualType RetTy;
10617330f729Sjoerg     bool HaveRetTy = false;
10627330f729Sjoerg     llvm::Instruction::BinaryOps PostOp = (llvm::Instruction::BinaryOps)0;
1063*e038c9c4Sjoerg     bool PostOpMinMax = false;
10647330f729Sjoerg     switch (E->getOp()) {
10657330f729Sjoerg     case AtomicExpr::AO__c11_atomic_init:
10667330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_init:
10677330f729Sjoerg       llvm_unreachable("Already handled!");
10687330f729Sjoerg 
10697330f729Sjoerg     // There is only one libcall for compare an exchange, because there is no
10707330f729Sjoerg     // optimisation benefit possible from a libcall version of a weak compare
10717330f729Sjoerg     // and exchange.
10727330f729Sjoerg     // bool __atomic_compare_exchange(size_t size, void *mem, void *expected,
10737330f729Sjoerg     //                                void *desired, int success, int failure)
10747330f729Sjoerg     // bool __atomic_compare_exchange_N(T *mem, T *expected, T desired,
10757330f729Sjoerg     //                                  int success, int failure)
10767330f729Sjoerg     case AtomicExpr::AO__c11_atomic_compare_exchange_weak:
10777330f729Sjoerg     case AtomicExpr::AO__c11_atomic_compare_exchange_strong:
10787330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:
10797330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:
10807330f729Sjoerg     case AtomicExpr::AO__atomic_compare_exchange:
10817330f729Sjoerg     case AtomicExpr::AO__atomic_compare_exchange_n:
10827330f729Sjoerg       LibCallName = "__atomic_compare_exchange";
10837330f729Sjoerg       RetTy = getContext().BoolTy;
10847330f729Sjoerg       HaveRetTy = true;
10857330f729Sjoerg       Args.add(
10867330f729Sjoerg           RValue::get(CastToGenericAddrSpace(
10877330f729Sjoerg               EmitCastToVoidPtr(Val1.getPointer()), E->getVal1()->getType())),
10887330f729Sjoerg           getContext().VoidPtrTy);
10897330f729Sjoerg       AddDirectArgument(*this, Args, UseOptimizedLibcall, Val2.getPointer(),
1090*e038c9c4Sjoerg                         MemTy, E->getExprLoc(), TInfo.Width);
10917330f729Sjoerg       Args.add(RValue::get(Order), getContext().IntTy);
10927330f729Sjoerg       Order = OrderFail;
10937330f729Sjoerg       break;
10947330f729Sjoerg     // void __atomic_exchange(size_t size, void *mem, void *val, void *return,
10957330f729Sjoerg     //                        int order)
10967330f729Sjoerg     // T __atomic_exchange_N(T *mem, T val, int order)
10977330f729Sjoerg     case AtomicExpr::AO__c11_atomic_exchange:
10987330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_exchange:
10997330f729Sjoerg     case AtomicExpr::AO__atomic_exchange_n:
11007330f729Sjoerg     case AtomicExpr::AO__atomic_exchange:
11017330f729Sjoerg       LibCallName = "__atomic_exchange";
11027330f729Sjoerg       AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
1103*e038c9c4Sjoerg                         MemTy, E->getExprLoc(), TInfo.Width);
11047330f729Sjoerg       break;
11057330f729Sjoerg     // void __atomic_store(size_t size, void *mem, void *val, int order)
11067330f729Sjoerg     // void __atomic_store_N(T *mem, T val, int order)
11077330f729Sjoerg     case AtomicExpr::AO__c11_atomic_store:
11087330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_store:
11097330f729Sjoerg     case AtomicExpr::AO__atomic_store:
11107330f729Sjoerg     case AtomicExpr::AO__atomic_store_n:
11117330f729Sjoerg       LibCallName = "__atomic_store";
11127330f729Sjoerg       RetTy = getContext().VoidTy;
11137330f729Sjoerg       HaveRetTy = true;
11147330f729Sjoerg       AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
1115*e038c9c4Sjoerg                         MemTy, E->getExprLoc(), TInfo.Width);
11167330f729Sjoerg       break;
11177330f729Sjoerg     // void __atomic_load(size_t size, void *mem, void *return, int order)
11187330f729Sjoerg     // T __atomic_load_N(T *mem, int order)
11197330f729Sjoerg     case AtomicExpr::AO__c11_atomic_load:
11207330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_load:
11217330f729Sjoerg     case AtomicExpr::AO__atomic_load:
11227330f729Sjoerg     case AtomicExpr::AO__atomic_load_n:
11237330f729Sjoerg       LibCallName = "__atomic_load";
11247330f729Sjoerg       break;
11257330f729Sjoerg     // T __atomic_add_fetch_N(T *mem, T val, int order)
11267330f729Sjoerg     // T __atomic_fetch_add_N(T *mem, T val, int order)
11277330f729Sjoerg     case AtomicExpr::AO__atomic_add_fetch:
11287330f729Sjoerg       PostOp = llvm::Instruction::Add;
11297330f729Sjoerg       LLVM_FALLTHROUGH;
11307330f729Sjoerg     case AtomicExpr::AO__c11_atomic_fetch_add:
11317330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_fetch_add:
11327330f729Sjoerg     case AtomicExpr::AO__atomic_fetch_add:
11337330f729Sjoerg       LibCallName = "__atomic_fetch_add";
11347330f729Sjoerg       AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
1135*e038c9c4Sjoerg                         LoweredMemTy, E->getExprLoc(), TInfo.Width);
11367330f729Sjoerg       break;
11377330f729Sjoerg     // T __atomic_and_fetch_N(T *mem, T val, int order)
11387330f729Sjoerg     // T __atomic_fetch_and_N(T *mem, T val, int order)
11397330f729Sjoerg     case AtomicExpr::AO__atomic_and_fetch:
11407330f729Sjoerg       PostOp = llvm::Instruction::And;
11417330f729Sjoerg       LLVM_FALLTHROUGH;
11427330f729Sjoerg     case AtomicExpr::AO__c11_atomic_fetch_and:
11437330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_fetch_and:
11447330f729Sjoerg     case AtomicExpr::AO__atomic_fetch_and:
11457330f729Sjoerg       LibCallName = "__atomic_fetch_and";
11467330f729Sjoerg       AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
1147*e038c9c4Sjoerg                         MemTy, E->getExprLoc(), TInfo.Width);
11487330f729Sjoerg       break;
11497330f729Sjoerg     // T __atomic_or_fetch_N(T *mem, T val, int order)
11507330f729Sjoerg     // T __atomic_fetch_or_N(T *mem, T val, int order)
11517330f729Sjoerg     case AtomicExpr::AO__atomic_or_fetch:
11527330f729Sjoerg       PostOp = llvm::Instruction::Or;
11537330f729Sjoerg       LLVM_FALLTHROUGH;
11547330f729Sjoerg     case AtomicExpr::AO__c11_atomic_fetch_or:
11557330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_fetch_or:
11567330f729Sjoerg     case AtomicExpr::AO__atomic_fetch_or:
11577330f729Sjoerg       LibCallName = "__atomic_fetch_or";
11587330f729Sjoerg       AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
1159*e038c9c4Sjoerg                         MemTy, E->getExprLoc(), TInfo.Width);
11607330f729Sjoerg       break;
11617330f729Sjoerg     // T __atomic_sub_fetch_N(T *mem, T val, int order)
11627330f729Sjoerg     // T __atomic_fetch_sub_N(T *mem, T val, int order)
11637330f729Sjoerg     case AtomicExpr::AO__atomic_sub_fetch:
11647330f729Sjoerg       PostOp = llvm::Instruction::Sub;
11657330f729Sjoerg       LLVM_FALLTHROUGH;
11667330f729Sjoerg     case AtomicExpr::AO__c11_atomic_fetch_sub:
11677330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_fetch_sub:
11687330f729Sjoerg     case AtomicExpr::AO__atomic_fetch_sub:
11697330f729Sjoerg       LibCallName = "__atomic_fetch_sub";
11707330f729Sjoerg       AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
1171*e038c9c4Sjoerg                         LoweredMemTy, E->getExprLoc(), TInfo.Width);
11727330f729Sjoerg       break;
11737330f729Sjoerg     // T __atomic_xor_fetch_N(T *mem, T val, int order)
11747330f729Sjoerg     // T __atomic_fetch_xor_N(T *mem, T val, int order)
11757330f729Sjoerg     case AtomicExpr::AO__atomic_xor_fetch:
11767330f729Sjoerg       PostOp = llvm::Instruction::Xor;
11777330f729Sjoerg       LLVM_FALLTHROUGH;
11787330f729Sjoerg     case AtomicExpr::AO__c11_atomic_fetch_xor:
11797330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_fetch_xor:
11807330f729Sjoerg     case AtomicExpr::AO__atomic_fetch_xor:
11817330f729Sjoerg       LibCallName = "__atomic_fetch_xor";
11827330f729Sjoerg       AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
1183*e038c9c4Sjoerg                         MemTy, E->getExprLoc(), TInfo.Width);
11847330f729Sjoerg       break;
1185*e038c9c4Sjoerg     case AtomicExpr::AO__atomic_min_fetch:
1186*e038c9c4Sjoerg       PostOpMinMax = true;
1187*e038c9c4Sjoerg       LLVM_FALLTHROUGH;
1188*e038c9c4Sjoerg     case AtomicExpr::AO__c11_atomic_fetch_min:
11897330f729Sjoerg     case AtomicExpr::AO__atomic_fetch_min:
11907330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_fetch_min:
11917330f729Sjoerg       LibCallName = E->getValueType()->isSignedIntegerType()
11927330f729Sjoerg                         ? "__atomic_fetch_min"
11937330f729Sjoerg                         : "__atomic_fetch_umin";
11947330f729Sjoerg       AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
1195*e038c9c4Sjoerg                         LoweredMemTy, E->getExprLoc(), TInfo.Width);
11967330f729Sjoerg       break;
1197*e038c9c4Sjoerg     case AtomicExpr::AO__atomic_max_fetch:
1198*e038c9c4Sjoerg       PostOpMinMax = true;
1199*e038c9c4Sjoerg       LLVM_FALLTHROUGH;
1200*e038c9c4Sjoerg     case AtomicExpr::AO__c11_atomic_fetch_max:
12017330f729Sjoerg     case AtomicExpr::AO__atomic_fetch_max:
12027330f729Sjoerg     case AtomicExpr::AO__opencl_atomic_fetch_max:
12037330f729Sjoerg       LibCallName = E->getValueType()->isSignedIntegerType()
12047330f729Sjoerg                         ? "__atomic_fetch_max"
12057330f729Sjoerg                         : "__atomic_fetch_umax";
12067330f729Sjoerg       AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
1207*e038c9c4Sjoerg                         LoweredMemTy, E->getExprLoc(), TInfo.Width);
12087330f729Sjoerg       break;
12097330f729Sjoerg     // T __atomic_nand_fetch_N(T *mem, T val, int order)
12107330f729Sjoerg     // T __atomic_fetch_nand_N(T *mem, T val, int order)
12117330f729Sjoerg     case AtomicExpr::AO__atomic_nand_fetch:
12127330f729Sjoerg       PostOp = llvm::Instruction::And; // the NOT is special cased below
12137330f729Sjoerg       LLVM_FALLTHROUGH;
12147330f729Sjoerg     case AtomicExpr::AO__atomic_fetch_nand:
12157330f729Sjoerg       LibCallName = "__atomic_fetch_nand";
12167330f729Sjoerg       AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),
1217*e038c9c4Sjoerg                         MemTy, E->getExprLoc(), TInfo.Width);
12187330f729Sjoerg       break;
12197330f729Sjoerg     }
12207330f729Sjoerg 
12217330f729Sjoerg     if (E->isOpenCL()) {
12227330f729Sjoerg       LibCallName = std::string("__opencl") +
12237330f729Sjoerg           StringRef(LibCallName).drop_front(1).str();
12247330f729Sjoerg 
12257330f729Sjoerg     }
12267330f729Sjoerg     // Optimized functions have the size in their name.
12277330f729Sjoerg     if (UseOptimizedLibcall)
12287330f729Sjoerg       LibCallName += "_" + llvm::utostr(Size);
12297330f729Sjoerg     // By default, assume we return a value of the atomic type.
12307330f729Sjoerg     if (!HaveRetTy) {
12317330f729Sjoerg       if (UseOptimizedLibcall) {
12327330f729Sjoerg         // Value is returned directly.
12337330f729Sjoerg         // The function returns an appropriately sized integer type.
12347330f729Sjoerg         RetTy = getContext().getIntTypeForBitwidth(
1235*e038c9c4Sjoerg             getContext().toBits(TInfo.Width), /*Signed=*/false);
12367330f729Sjoerg       } else {
12377330f729Sjoerg         // Value is returned through parameter before the order.
12387330f729Sjoerg         RetTy = getContext().VoidTy;
12397330f729Sjoerg         Args.add(RValue::get(EmitCastToVoidPtr(Dest.getPointer())),
12407330f729Sjoerg                  getContext().VoidPtrTy);
12417330f729Sjoerg       }
12427330f729Sjoerg     }
12437330f729Sjoerg     // order is always the last parameter
12447330f729Sjoerg     Args.add(RValue::get(Order),
12457330f729Sjoerg              getContext().IntTy);
12467330f729Sjoerg     if (E->isOpenCL())
12477330f729Sjoerg       Args.add(RValue::get(Scope), getContext().IntTy);
12487330f729Sjoerg 
12497330f729Sjoerg     // PostOp is only needed for the atomic_*_fetch operations, and
12507330f729Sjoerg     // thus is only needed for and implemented in the
12517330f729Sjoerg     // UseOptimizedLibcall codepath.
1252*e038c9c4Sjoerg     assert(UseOptimizedLibcall || (!PostOp && !PostOpMinMax));
12537330f729Sjoerg 
12547330f729Sjoerg     RValue Res = emitAtomicLibcall(*this, LibCallName, RetTy, Args);
12557330f729Sjoerg     // The value is returned directly from the libcall.
12567330f729Sjoerg     if (E->isCmpXChg())
12577330f729Sjoerg       return Res;
12587330f729Sjoerg 
12597330f729Sjoerg     // The value is returned directly for optimized libcalls but the expr
12607330f729Sjoerg     // provided an out-param.
12617330f729Sjoerg     if (UseOptimizedLibcall && Res.getScalarVal()) {
12627330f729Sjoerg       llvm::Value *ResVal = Res.getScalarVal();
1263*e038c9c4Sjoerg       if (PostOpMinMax) {
1264*e038c9c4Sjoerg         llvm::Value *LoadVal1 = Args[1].getRValue(*this).getScalarVal();
1265*e038c9c4Sjoerg         ResVal = EmitPostAtomicMinMax(Builder, E->getOp(),
1266*e038c9c4Sjoerg                                       E->getValueType()->isSignedIntegerType(),
1267*e038c9c4Sjoerg                                       ResVal, LoadVal1);
1268*e038c9c4Sjoerg       } else if (PostOp) {
12697330f729Sjoerg         llvm::Value *LoadVal1 = Args[1].getRValue(*this).getScalarVal();
12707330f729Sjoerg         ResVal = Builder.CreateBinOp(PostOp, ResVal, LoadVal1);
12717330f729Sjoerg       }
12727330f729Sjoerg       if (E->getOp() == AtomicExpr::AO__atomic_nand_fetch)
12737330f729Sjoerg         ResVal = Builder.CreateNot(ResVal);
12747330f729Sjoerg 
12757330f729Sjoerg       Builder.CreateStore(
12767330f729Sjoerg           ResVal,
12777330f729Sjoerg           Builder.CreateBitCast(Dest, ResVal->getType()->getPointerTo()));
12787330f729Sjoerg     }
12797330f729Sjoerg 
12807330f729Sjoerg     if (RValTy->isVoidType())
12817330f729Sjoerg       return RValue::get(nullptr);
12827330f729Sjoerg 
12837330f729Sjoerg     return convertTempToRValue(
12847330f729Sjoerg         Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo()),
12857330f729Sjoerg         RValTy, E->getExprLoc());
12867330f729Sjoerg   }
12877330f729Sjoerg 
12887330f729Sjoerg   bool IsStore = E->getOp() == AtomicExpr::AO__c11_atomic_store ||
12897330f729Sjoerg                  E->getOp() == AtomicExpr::AO__opencl_atomic_store ||
12907330f729Sjoerg                  E->getOp() == AtomicExpr::AO__atomic_store ||
12917330f729Sjoerg                  E->getOp() == AtomicExpr::AO__atomic_store_n;
12927330f729Sjoerg   bool IsLoad = E->getOp() == AtomicExpr::AO__c11_atomic_load ||
12937330f729Sjoerg                 E->getOp() == AtomicExpr::AO__opencl_atomic_load ||
12947330f729Sjoerg                 E->getOp() == AtomicExpr::AO__atomic_load ||
12957330f729Sjoerg                 E->getOp() == AtomicExpr::AO__atomic_load_n;
12967330f729Sjoerg 
12977330f729Sjoerg   if (isa<llvm::ConstantInt>(Order)) {
12987330f729Sjoerg     auto ord = cast<llvm::ConstantInt>(Order)->getZExtValue();
12997330f729Sjoerg     // We should not ever get to a case where the ordering isn't a valid C ABI
13007330f729Sjoerg     // value, but it's hard to enforce that in general.
13017330f729Sjoerg     if (llvm::isValidAtomicOrderingCABI(ord))
13027330f729Sjoerg       switch ((llvm::AtomicOrderingCABI)ord) {
13037330f729Sjoerg       case llvm::AtomicOrderingCABI::relaxed:
13047330f729Sjoerg         EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
13057330f729Sjoerg                      llvm::AtomicOrdering::Monotonic, Scope);
13067330f729Sjoerg         break;
13077330f729Sjoerg       case llvm::AtomicOrderingCABI::consume:
13087330f729Sjoerg       case llvm::AtomicOrderingCABI::acquire:
13097330f729Sjoerg         if (IsStore)
13107330f729Sjoerg           break; // Avoid crashing on code with undefined behavior
13117330f729Sjoerg         EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
13127330f729Sjoerg                      llvm::AtomicOrdering::Acquire, Scope);
13137330f729Sjoerg         break;
13147330f729Sjoerg       case llvm::AtomicOrderingCABI::release:
13157330f729Sjoerg         if (IsLoad)
13167330f729Sjoerg           break; // Avoid crashing on code with undefined behavior
13177330f729Sjoerg         EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
13187330f729Sjoerg                      llvm::AtomicOrdering::Release, Scope);
13197330f729Sjoerg         break;
13207330f729Sjoerg       case llvm::AtomicOrderingCABI::acq_rel:
13217330f729Sjoerg         if (IsLoad || IsStore)
13227330f729Sjoerg           break; // Avoid crashing on code with undefined behavior
13237330f729Sjoerg         EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
13247330f729Sjoerg                      llvm::AtomicOrdering::AcquireRelease, Scope);
13257330f729Sjoerg         break;
13267330f729Sjoerg       case llvm::AtomicOrderingCABI::seq_cst:
13277330f729Sjoerg         EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
13287330f729Sjoerg                      llvm::AtomicOrdering::SequentiallyConsistent, Scope);
13297330f729Sjoerg         break;
13307330f729Sjoerg       }
13317330f729Sjoerg     if (RValTy->isVoidType())
13327330f729Sjoerg       return RValue::get(nullptr);
13337330f729Sjoerg 
13347330f729Sjoerg     return convertTempToRValue(
13357330f729Sjoerg         Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo(
13367330f729Sjoerg                                         Dest.getAddressSpace())),
13377330f729Sjoerg         RValTy, E->getExprLoc());
13387330f729Sjoerg   }
13397330f729Sjoerg 
13407330f729Sjoerg   // Long case, when Order isn't obviously constant.
13417330f729Sjoerg 
13427330f729Sjoerg   // Create all the relevant BB's
13437330f729Sjoerg   llvm::BasicBlock *MonotonicBB = nullptr, *AcquireBB = nullptr,
13447330f729Sjoerg                    *ReleaseBB = nullptr, *AcqRelBB = nullptr,
13457330f729Sjoerg                    *SeqCstBB = nullptr;
13467330f729Sjoerg   MonotonicBB = createBasicBlock("monotonic", CurFn);
13477330f729Sjoerg   if (!IsStore)
13487330f729Sjoerg     AcquireBB = createBasicBlock("acquire", CurFn);
13497330f729Sjoerg   if (!IsLoad)
13507330f729Sjoerg     ReleaseBB = createBasicBlock("release", CurFn);
13517330f729Sjoerg   if (!IsLoad && !IsStore)
13527330f729Sjoerg     AcqRelBB = createBasicBlock("acqrel", CurFn);
13537330f729Sjoerg   SeqCstBB = createBasicBlock("seqcst", CurFn);
13547330f729Sjoerg   llvm::BasicBlock *ContBB = createBasicBlock("atomic.continue", CurFn);
13557330f729Sjoerg 
13567330f729Sjoerg   // Create the switch for the split
13577330f729Sjoerg   // MonotonicBB is arbitrarily chosen as the default case; in practice, this
13587330f729Sjoerg   // doesn't matter unless someone is crazy enough to use something that
13597330f729Sjoerg   // doesn't fold to a constant for the ordering.
13607330f729Sjoerg   Order = Builder.CreateIntCast(Order, Builder.getInt32Ty(), false);
13617330f729Sjoerg   llvm::SwitchInst *SI = Builder.CreateSwitch(Order, MonotonicBB);
13627330f729Sjoerg 
13637330f729Sjoerg   // Emit all the different atomics
13647330f729Sjoerg   Builder.SetInsertPoint(MonotonicBB);
13657330f729Sjoerg   EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
13667330f729Sjoerg                llvm::AtomicOrdering::Monotonic, Scope);
13677330f729Sjoerg   Builder.CreateBr(ContBB);
13687330f729Sjoerg   if (!IsStore) {
13697330f729Sjoerg     Builder.SetInsertPoint(AcquireBB);
13707330f729Sjoerg     EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
13717330f729Sjoerg                  llvm::AtomicOrdering::Acquire, Scope);
13727330f729Sjoerg     Builder.CreateBr(ContBB);
13737330f729Sjoerg     SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::consume),
13747330f729Sjoerg                 AcquireBB);
13757330f729Sjoerg     SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::acquire),
13767330f729Sjoerg                 AcquireBB);
13777330f729Sjoerg   }
13787330f729Sjoerg   if (!IsLoad) {
13797330f729Sjoerg     Builder.SetInsertPoint(ReleaseBB);
13807330f729Sjoerg     EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
13817330f729Sjoerg                  llvm::AtomicOrdering::Release, Scope);
13827330f729Sjoerg     Builder.CreateBr(ContBB);
13837330f729Sjoerg     SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::release),
13847330f729Sjoerg                 ReleaseBB);
13857330f729Sjoerg   }
13867330f729Sjoerg   if (!IsLoad && !IsStore) {
13877330f729Sjoerg     Builder.SetInsertPoint(AcqRelBB);
13887330f729Sjoerg     EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
13897330f729Sjoerg                  llvm::AtomicOrdering::AcquireRelease, Scope);
13907330f729Sjoerg     Builder.CreateBr(ContBB);
13917330f729Sjoerg     SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::acq_rel),
13927330f729Sjoerg                 AcqRelBB);
13937330f729Sjoerg   }
13947330f729Sjoerg   Builder.SetInsertPoint(SeqCstBB);
13957330f729Sjoerg   EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size,
13967330f729Sjoerg                llvm::AtomicOrdering::SequentiallyConsistent, Scope);
13977330f729Sjoerg   Builder.CreateBr(ContBB);
13987330f729Sjoerg   SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::seq_cst),
13997330f729Sjoerg               SeqCstBB);
14007330f729Sjoerg 
14017330f729Sjoerg   // Cleanup and return
14027330f729Sjoerg   Builder.SetInsertPoint(ContBB);
14037330f729Sjoerg   if (RValTy->isVoidType())
14047330f729Sjoerg     return RValue::get(nullptr);
14057330f729Sjoerg 
14067330f729Sjoerg   assert(Atomics.getValueSizeInBits() <= Atomics.getAtomicSizeInBits());
14077330f729Sjoerg   return convertTempToRValue(
14087330f729Sjoerg       Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo(
14097330f729Sjoerg                                       Dest.getAddressSpace())),
14107330f729Sjoerg       RValTy, E->getExprLoc());
14117330f729Sjoerg }
14127330f729Sjoerg 
emitCastToAtomicIntPointer(Address addr) const14137330f729Sjoerg Address AtomicInfo::emitCastToAtomicIntPointer(Address addr) const {
14147330f729Sjoerg   unsigned addrspace =
14157330f729Sjoerg     cast<llvm::PointerType>(addr.getPointer()->getType())->getAddressSpace();
14167330f729Sjoerg   llvm::IntegerType *ty =
14177330f729Sjoerg     llvm::IntegerType::get(CGF.getLLVMContext(), AtomicSizeInBits);
14187330f729Sjoerg   return CGF.Builder.CreateBitCast(addr, ty->getPointerTo(addrspace));
14197330f729Sjoerg }
14207330f729Sjoerg 
convertToAtomicIntPointer(Address Addr) const14217330f729Sjoerg Address AtomicInfo::convertToAtomicIntPointer(Address Addr) const {
14227330f729Sjoerg   llvm::Type *Ty = Addr.getElementType();
14237330f729Sjoerg   uint64_t SourceSizeInBits = CGF.CGM.getDataLayout().getTypeSizeInBits(Ty);
14247330f729Sjoerg   if (SourceSizeInBits != AtomicSizeInBits) {
14257330f729Sjoerg     Address Tmp = CreateTempAlloca();
14267330f729Sjoerg     CGF.Builder.CreateMemCpy(Tmp, Addr,
14277330f729Sjoerg                              std::min(AtomicSizeInBits, SourceSizeInBits) / 8);
14287330f729Sjoerg     Addr = Tmp;
14297330f729Sjoerg   }
14307330f729Sjoerg 
14317330f729Sjoerg   return emitCastToAtomicIntPointer(Addr);
14327330f729Sjoerg }
14337330f729Sjoerg 
convertAtomicTempToRValue(Address addr,AggValueSlot resultSlot,SourceLocation loc,bool asValue) const14347330f729Sjoerg RValue AtomicInfo::convertAtomicTempToRValue(Address addr,
14357330f729Sjoerg                                              AggValueSlot resultSlot,
14367330f729Sjoerg                                              SourceLocation loc,
14377330f729Sjoerg                                              bool asValue) const {
14387330f729Sjoerg   if (LVal.isSimple()) {
14397330f729Sjoerg     if (EvaluationKind == TEK_Aggregate)
14407330f729Sjoerg       return resultSlot.asRValue();
14417330f729Sjoerg 
14427330f729Sjoerg     // Drill into the padding structure if we have one.
14437330f729Sjoerg     if (hasPadding())
14447330f729Sjoerg       addr = CGF.Builder.CreateStructGEP(addr, 0);
14457330f729Sjoerg 
14467330f729Sjoerg     // Otherwise, just convert the temporary to an r-value using the
14477330f729Sjoerg     // normal conversion routine.
14487330f729Sjoerg     return CGF.convertTempToRValue(addr, getValueType(), loc);
14497330f729Sjoerg   }
14507330f729Sjoerg   if (!asValue)
14517330f729Sjoerg     // Get RValue from temp memory as atomic for non-simple lvalues
14527330f729Sjoerg     return RValue::get(CGF.Builder.CreateLoad(addr));
14537330f729Sjoerg   if (LVal.isBitField())
14547330f729Sjoerg     return CGF.EmitLoadOfBitfieldLValue(
14557330f729Sjoerg         LValue::MakeBitfield(addr, LVal.getBitFieldInfo(), LVal.getType(),
14567330f729Sjoerg                              LVal.getBaseInfo(), TBAAAccessInfo()), loc);
14577330f729Sjoerg   if (LVal.isVectorElt())
14587330f729Sjoerg     return CGF.EmitLoadOfLValue(
14597330f729Sjoerg         LValue::MakeVectorElt(addr, LVal.getVectorIdx(), LVal.getType(),
14607330f729Sjoerg                               LVal.getBaseInfo(), TBAAAccessInfo()), loc);
14617330f729Sjoerg   assert(LVal.isExtVectorElt());
14627330f729Sjoerg   return CGF.EmitLoadOfExtVectorElementLValue(LValue::MakeExtVectorElt(
14637330f729Sjoerg       addr, LVal.getExtVectorElts(), LVal.getType(),
14647330f729Sjoerg       LVal.getBaseInfo(), TBAAAccessInfo()));
14657330f729Sjoerg }
14667330f729Sjoerg 
ConvertIntToValueOrAtomic(llvm::Value * IntVal,AggValueSlot ResultSlot,SourceLocation Loc,bool AsValue) const14677330f729Sjoerg RValue AtomicInfo::ConvertIntToValueOrAtomic(llvm::Value *IntVal,
14687330f729Sjoerg                                              AggValueSlot ResultSlot,
14697330f729Sjoerg                                              SourceLocation Loc,
14707330f729Sjoerg                                              bool AsValue) const {
14717330f729Sjoerg   // Try not to in some easy cases.
14727330f729Sjoerg   assert(IntVal->getType()->isIntegerTy() && "Expected integer value");
14737330f729Sjoerg   if (getEvaluationKind() == TEK_Scalar &&
14747330f729Sjoerg       (((!LVal.isBitField() ||
14757330f729Sjoerg          LVal.getBitFieldInfo().Size == ValueSizeInBits) &&
14767330f729Sjoerg         !hasPadding()) ||
14777330f729Sjoerg        !AsValue)) {
14787330f729Sjoerg     auto *ValTy = AsValue
14797330f729Sjoerg                       ? CGF.ConvertTypeForMem(ValueTy)
14807330f729Sjoerg                       : getAtomicAddress().getType()->getPointerElementType();
14817330f729Sjoerg     if (ValTy->isIntegerTy()) {
14827330f729Sjoerg       assert(IntVal->getType() == ValTy && "Different integer types.");
14837330f729Sjoerg       return RValue::get(CGF.EmitFromMemory(IntVal, ValueTy));
14847330f729Sjoerg     } else if (ValTy->isPointerTy())
14857330f729Sjoerg       return RValue::get(CGF.Builder.CreateIntToPtr(IntVal, ValTy));
14867330f729Sjoerg     else if (llvm::CastInst::isBitCastable(IntVal->getType(), ValTy))
14877330f729Sjoerg       return RValue::get(CGF.Builder.CreateBitCast(IntVal, ValTy));
14887330f729Sjoerg   }
14897330f729Sjoerg 
14907330f729Sjoerg   // Create a temporary.  This needs to be big enough to hold the
14917330f729Sjoerg   // atomic integer.
14927330f729Sjoerg   Address Temp = Address::invalid();
14937330f729Sjoerg   bool TempIsVolatile = false;
14947330f729Sjoerg   if (AsValue && getEvaluationKind() == TEK_Aggregate) {
14957330f729Sjoerg     assert(!ResultSlot.isIgnored());
14967330f729Sjoerg     Temp = ResultSlot.getAddress();
14977330f729Sjoerg     TempIsVolatile = ResultSlot.isVolatile();
14987330f729Sjoerg   } else {
14997330f729Sjoerg     Temp = CreateTempAlloca();
15007330f729Sjoerg   }
15017330f729Sjoerg 
15027330f729Sjoerg   // Slam the integer into the temporary.
15037330f729Sjoerg   Address CastTemp = emitCastToAtomicIntPointer(Temp);
15047330f729Sjoerg   CGF.Builder.CreateStore(IntVal, CastTemp)
15057330f729Sjoerg       ->setVolatile(TempIsVolatile);
15067330f729Sjoerg 
15077330f729Sjoerg   return convertAtomicTempToRValue(Temp, ResultSlot, Loc, AsValue);
15087330f729Sjoerg }
15097330f729Sjoerg 
EmitAtomicLoadLibcall(llvm::Value * AddForLoaded,llvm::AtomicOrdering AO,bool)15107330f729Sjoerg void AtomicInfo::EmitAtomicLoadLibcall(llvm::Value *AddForLoaded,
15117330f729Sjoerg                                        llvm::AtomicOrdering AO, bool) {
15127330f729Sjoerg   // void __atomic_load(size_t size, void *mem, void *return, int order);
15137330f729Sjoerg   CallArgList Args;
15147330f729Sjoerg   Args.add(RValue::get(getAtomicSizeValue()), CGF.getContext().getSizeType());
15157330f729Sjoerg   Args.add(RValue::get(CGF.EmitCastToVoidPtr(getAtomicPointer())),
15167330f729Sjoerg            CGF.getContext().VoidPtrTy);
15177330f729Sjoerg   Args.add(RValue::get(CGF.EmitCastToVoidPtr(AddForLoaded)),
15187330f729Sjoerg            CGF.getContext().VoidPtrTy);
15197330f729Sjoerg   Args.add(
15207330f729Sjoerg       RValue::get(llvm::ConstantInt::get(CGF.IntTy, (int)llvm::toCABI(AO))),
15217330f729Sjoerg       CGF.getContext().IntTy);
15227330f729Sjoerg   emitAtomicLibcall(CGF, "__atomic_load", CGF.getContext().VoidTy, Args);
15237330f729Sjoerg }
15247330f729Sjoerg 
EmitAtomicLoadOp(llvm::AtomicOrdering AO,bool IsVolatile)15257330f729Sjoerg llvm::Value *AtomicInfo::EmitAtomicLoadOp(llvm::AtomicOrdering AO,
15267330f729Sjoerg                                           bool IsVolatile) {
15277330f729Sjoerg   // Okay, we're doing this natively.
15287330f729Sjoerg   Address Addr = getAtomicAddressAsAtomicIntPointer();
15297330f729Sjoerg   llvm::LoadInst *Load = CGF.Builder.CreateLoad(Addr, "atomic-load");
15307330f729Sjoerg   Load->setAtomic(AO);
15317330f729Sjoerg 
15327330f729Sjoerg   // Other decoration.
15337330f729Sjoerg   if (IsVolatile)
15347330f729Sjoerg     Load->setVolatile(true);
15357330f729Sjoerg   CGF.CGM.DecorateInstructionWithTBAA(Load, LVal.getTBAAInfo());
15367330f729Sjoerg   return Load;
15377330f729Sjoerg }
15387330f729Sjoerg 
15397330f729Sjoerg /// An LValue is a candidate for having its loads and stores be made atomic if
15407330f729Sjoerg /// we are operating under /volatile:ms *and* the LValue itself is volatile and
15417330f729Sjoerg /// performing such an operation can be performed without a libcall.
LValueIsSuitableForInlineAtomic(LValue LV)15427330f729Sjoerg bool CodeGenFunction::LValueIsSuitableForInlineAtomic(LValue LV) {
15437330f729Sjoerg   if (!CGM.getCodeGenOpts().MSVolatile) return false;
15447330f729Sjoerg   AtomicInfo AI(*this, LV);
15457330f729Sjoerg   bool IsVolatile = LV.isVolatile() || hasVolatileMember(LV.getType());
15467330f729Sjoerg   // An atomic is inline if we don't need to use a libcall.
15477330f729Sjoerg   bool AtomicIsInline = !AI.shouldUseLibcall();
15487330f729Sjoerg   // MSVC doesn't seem to do this for types wider than a pointer.
15497330f729Sjoerg   if (getContext().getTypeSize(LV.getType()) >
15507330f729Sjoerg       getContext().getTypeSize(getContext().getIntPtrType()))
15517330f729Sjoerg     return false;
15527330f729Sjoerg   return IsVolatile && AtomicIsInline;
15537330f729Sjoerg }
15547330f729Sjoerg 
EmitAtomicLoad(LValue LV,SourceLocation SL,AggValueSlot Slot)15557330f729Sjoerg RValue CodeGenFunction::EmitAtomicLoad(LValue LV, SourceLocation SL,
15567330f729Sjoerg                                        AggValueSlot Slot) {
15577330f729Sjoerg   llvm::AtomicOrdering AO;
15587330f729Sjoerg   bool IsVolatile = LV.isVolatileQualified();
15597330f729Sjoerg   if (LV.getType()->isAtomicType()) {
15607330f729Sjoerg     AO = llvm::AtomicOrdering::SequentiallyConsistent;
15617330f729Sjoerg   } else {
15627330f729Sjoerg     AO = llvm::AtomicOrdering::Acquire;
15637330f729Sjoerg     IsVolatile = true;
15647330f729Sjoerg   }
15657330f729Sjoerg   return EmitAtomicLoad(LV, SL, AO, IsVolatile, Slot);
15667330f729Sjoerg }
15677330f729Sjoerg 
EmitAtomicLoad(AggValueSlot ResultSlot,SourceLocation Loc,bool AsValue,llvm::AtomicOrdering AO,bool IsVolatile)15687330f729Sjoerg RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc,
15697330f729Sjoerg                                   bool AsValue, llvm::AtomicOrdering AO,
15707330f729Sjoerg                                   bool IsVolatile) {
15717330f729Sjoerg   // Check whether we should use a library call.
15727330f729Sjoerg   if (shouldUseLibcall()) {
15737330f729Sjoerg     Address TempAddr = Address::invalid();
15747330f729Sjoerg     if (LVal.isSimple() && !ResultSlot.isIgnored()) {
15757330f729Sjoerg       assert(getEvaluationKind() == TEK_Aggregate);
15767330f729Sjoerg       TempAddr = ResultSlot.getAddress();
15777330f729Sjoerg     } else
15787330f729Sjoerg       TempAddr = CreateTempAlloca();
15797330f729Sjoerg 
15807330f729Sjoerg     EmitAtomicLoadLibcall(TempAddr.getPointer(), AO, IsVolatile);
15817330f729Sjoerg 
15827330f729Sjoerg     // Okay, turn that back into the original value or whole atomic (for
15837330f729Sjoerg     // non-simple lvalues) type.
15847330f729Sjoerg     return convertAtomicTempToRValue(TempAddr, ResultSlot, Loc, AsValue);
15857330f729Sjoerg   }
15867330f729Sjoerg 
15877330f729Sjoerg   // Okay, we're doing this natively.
15887330f729Sjoerg   auto *Load = EmitAtomicLoadOp(AO, IsVolatile);
15897330f729Sjoerg 
15907330f729Sjoerg   // If we're ignoring an aggregate return, don't do anything.
15917330f729Sjoerg   if (getEvaluationKind() == TEK_Aggregate && ResultSlot.isIgnored())
15927330f729Sjoerg     return RValue::getAggregate(Address::invalid(), false);
15937330f729Sjoerg 
15947330f729Sjoerg   // Okay, turn that back into the original value or atomic (for non-simple
15957330f729Sjoerg   // lvalues) type.
15967330f729Sjoerg   return ConvertIntToValueOrAtomic(Load, ResultSlot, Loc, AsValue);
15977330f729Sjoerg }
15987330f729Sjoerg 
15997330f729Sjoerg /// Emit a load from an l-value of atomic type.  Note that the r-value
16007330f729Sjoerg /// we produce is an r-value of the atomic *value* type.
EmitAtomicLoad(LValue src,SourceLocation loc,llvm::AtomicOrdering AO,bool IsVolatile,AggValueSlot resultSlot)16017330f729Sjoerg RValue CodeGenFunction::EmitAtomicLoad(LValue src, SourceLocation loc,
16027330f729Sjoerg                                        llvm::AtomicOrdering AO, bool IsVolatile,
16037330f729Sjoerg                                        AggValueSlot resultSlot) {
16047330f729Sjoerg   AtomicInfo Atomics(*this, src);
16057330f729Sjoerg   return Atomics.EmitAtomicLoad(resultSlot, loc, /*AsValue=*/true, AO,
16067330f729Sjoerg                                 IsVolatile);
16077330f729Sjoerg }
16087330f729Sjoerg 
16097330f729Sjoerg /// Copy an r-value into memory as part of storing to an atomic type.
16107330f729Sjoerg /// This needs to create a bit-pattern suitable for atomic operations.
emitCopyIntoMemory(RValue rvalue) const16117330f729Sjoerg void AtomicInfo::emitCopyIntoMemory(RValue rvalue) const {
16127330f729Sjoerg   assert(LVal.isSimple());
16137330f729Sjoerg   // If we have an r-value, the rvalue should be of the atomic type,
16147330f729Sjoerg   // which means that the caller is responsible for having zeroed
16157330f729Sjoerg   // any padding.  Just do an aggregate copy of that type.
16167330f729Sjoerg   if (rvalue.isAggregate()) {
16177330f729Sjoerg     LValue Dest = CGF.MakeAddrLValue(getAtomicAddress(), getAtomicType());
16187330f729Sjoerg     LValue Src = CGF.MakeAddrLValue(rvalue.getAggregateAddress(),
16197330f729Sjoerg                                     getAtomicType());
16207330f729Sjoerg     bool IsVolatile = rvalue.isVolatileQualified() ||
16217330f729Sjoerg                       LVal.isVolatileQualified();
16227330f729Sjoerg     CGF.EmitAggregateCopy(Dest, Src, getAtomicType(),
16237330f729Sjoerg                           AggValueSlot::DoesNotOverlap, IsVolatile);
16247330f729Sjoerg     return;
16257330f729Sjoerg   }
16267330f729Sjoerg 
16277330f729Sjoerg   // Okay, otherwise we're copying stuff.
16287330f729Sjoerg 
16297330f729Sjoerg   // Zero out the buffer if necessary.
16307330f729Sjoerg   emitMemSetZeroIfNecessary();
16317330f729Sjoerg 
16327330f729Sjoerg   // Drill past the padding if present.
16337330f729Sjoerg   LValue TempLVal = projectValue();
16347330f729Sjoerg 
16357330f729Sjoerg   // Okay, store the rvalue in.
16367330f729Sjoerg   if (rvalue.isScalar()) {
16377330f729Sjoerg     CGF.EmitStoreOfScalar(rvalue.getScalarVal(), TempLVal, /*init*/ true);
16387330f729Sjoerg   } else {
16397330f729Sjoerg     CGF.EmitStoreOfComplex(rvalue.getComplexVal(), TempLVal, /*init*/ true);
16407330f729Sjoerg   }
16417330f729Sjoerg }
16427330f729Sjoerg 
16437330f729Sjoerg 
16447330f729Sjoerg /// Materialize an r-value into memory for the purposes of storing it
16457330f729Sjoerg /// to an atomic type.
materializeRValue(RValue rvalue) const16467330f729Sjoerg Address AtomicInfo::materializeRValue(RValue rvalue) const {
16477330f729Sjoerg   // Aggregate r-values are already in memory, and EmitAtomicStore
16487330f729Sjoerg   // requires them to be values of the atomic type.
16497330f729Sjoerg   if (rvalue.isAggregate())
16507330f729Sjoerg     return rvalue.getAggregateAddress();
16517330f729Sjoerg 
16527330f729Sjoerg   // Otherwise, make a temporary and materialize into it.
16537330f729Sjoerg   LValue TempLV = CGF.MakeAddrLValue(CreateTempAlloca(), getAtomicType());
16547330f729Sjoerg   AtomicInfo Atomics(CGF, TempLV);
16557330f729Sjoerg   Atomics.emitCopyIntoMemory(rvalue);
1656*e038c9c4Sjoerg   return TempLV.getAddress(CGF);
16577330f729Sjoerg }
16587330f729Sjoerg 
convertRValueToInt(RValue RVal) const16597330f729Sjoerg llvm::Value *AtomicInfo::convertRValueToInt(RValue RVal) const {
16607330f729Sjoerg   // If we've got a scalar value of the right size, try to avoid going
16617330f729Sjoerg   // through memory.
16627330f729Sjoerg   if (RVal.isScalar() && (!hasPadding() || !LVal.isSimple())) {
16637330f729Sjoerg     llvm::Value *Value = RVal.getScalarVal();
16647330f729Sjoerg     if (isa<llvm::IntegerType>(Value->getType()))
16657330f729Sjoerg       return CGF.EmitToMemory(Value, ValueTy);
16667330f729Sjoerg     else {
16677330f729Sjoerg       llvm::IntegerType *InputIntTy = llvm::IntegerType::get(
16687330f729Sjoerg           CGF.getLLVMContext(),
16697330f729Sjoerg           LVal.isSimple() ? getValueSizeInBits() : getAtomicSizeInBits());
16707330f729Sjoerg       if (isa<llvm::PointerType>(Value->getType()))
16717330f729Sjoerg         return CGF.Builder.CreatePtrToInt(Value, InputIntTy);
16727330f729Sjoerg       else if (llvm::BitCastInst::isBitCastable(Value->getType(), InputIntTy))
16737330f729Sjoerg         return CGF.Builder.CreateBitCast(Value, InputIntTy);
16747330f729Sjoerg     }
16757330f729Sjoerg   }
16767330f729Sjoerg   // Otherwise, we need to go through memory.
16777330f729Sjoerg   // Put the r-value in memory.
16787330f729Sjoerg   Address Addr = materializeRValue(RVal);
16797330f729Sjoerg 
16807330f729Sjoerg   // Cast the temporary to the atomic int type and pull a value out.
16817330f729Sjoerg   Addr = emitCastToAtomicIntPointer(Addr);
16827330f729Sjoerg   return CGF.Builder.CreateLoad(Addr);
16837330f729Sjoerg }
16847330f729Sjoerg 
EmitAtomicCompareExchangeOp(llvm::Value * ExpectedVal,llvm::Value * DesiredVal,llvm::AtomicOrdering Success,llvm::AtomicOrdering Failure,bool IsWeak)16857330f729Sjoerg std::pair<llvm::Value *, llvm::Value *> AtomicInfo::EmitAtomicCompareExchangeOp(
16867330f729Sjoerg     llvm::Value *ExpectedVal, llvm::Value *DesiredVal,
16877330f729Sjoerg     llvm::AtomicOrdering Success, llvm::AtomicOrdering Failure, bool IsWeak) {
16887330f729Sjoerg   // Do the atomic store.
16897330f729Sjoerg   Address Addr = getAtomicAddressAsAtomicIntPointer();
16907330f729Sjoerg   auto *Inst = CGF.Builder.CreateAtomicCmpXchg(Addr.getPointer(),
16917330f729Sjoerg                                                ExpectedVal, DesiredVal,
16927330f729Sjoerg                                                Success, Failure);
16937330f729Sjoerg   // Other decoration.
16947330f729Sjoerg   Inst->setVolatile(LVal.isVolatileQualified());
16957330f729Sjoerg   Inst->setWeak(IsWeak);
16967330f729Sjoerg 
16977330f729Sjoerg   // Okay, turn that back into the original value type.
16987330f729Sjoerg   auto *PreviousVal = CGF.Builder.CreateExtractValue(Inst, /*Idxs=*/0);
16997330f729Sjoerg   auto *SuccessFailureVal = CGF.Builder.CreateExtractValue(Inst, /*Idxs=*/1);
17007330f729Sjoerg   return std::make_pair(PreviousVal, SuccessFailureVal);
17017330f729Sjoerg }
17027330f729Sjoerg 
17037330f729Sjoerg llvm::Value *
EmitAtomicCompareExchangeLibcall(llvm::Value * ExpectedAddr,llvm::Value * DesiredAddr,llvm::AtomicOrdering Success,llvm::AtomicOrdering Failure)17047330f729Sjoerg AtomicInfo::EmitAtomicCompareExchangeLibcall(llvm::Value *ExpectedAddr,
17057330f729Sjoerg                                              llvm::Value *DesiredAddr,
17067330f729Sjoerg                                              llvm::AtomicOrdering Success,
17077330f729Sjoerg                                              llvm::AtomicOrdering Failure) {
17087330f729Sjoerg   // bool __atomic_compare_exchange(size_t size, void *obj, void *expected,
17097330f729Sjoerg   // void *desired, int success, int failure);
17107330f729Sjoerg   CallArgList Args;
17117330f729Sjoerg   Args.add(RValue::get(getAtomicSizeValue()), CGF.getContext().getSizeType());
17127330f729Sjoerg   Args.add(RValue::get(CGF.EmitCastToVoidPtr(getAtomicPointer())),
17137330f729Sjoerg            CGF.getContext().VoidPtrTy);
17147330f729Sjoerg   Args.add(RValue::get(CGF.EmitCastToVoidPtr(ExpectedAddr)),
17157330f729Sjoerg            CGF.getContext().VoidPtrTy);
17167330f729Sjoerg   Args.add(RValue::get(CGF.EmitCastToVoidPtr(DesiredAddr)),
17177330f729Sjoerg            CGF.getContext().VoidPtrTy);
17187330f729Sjoerg   Args.add(RValue::get(
17197330f729Sjoerg                llvm::ConstantInt::get(CGF.IntTy, (int)llvm::toCABI(Success))),
17207330f729Sjoerg            CGF.getContext().IntTy);
17217330f729Sjoerg   Args.add(RValue::get(
17227330f729Sjoerg                llvm::ConstantInt::get(CGF.IntTy, (int)llvm::toCABI(Failure))),
17237330f729Sjoerg            CGF.getContext().IntTy);
17247330f729Sjoerg   auto SuccessFailureRVal = emitAtomicLibcall(CGF, "__atomic_compare_exchange",
17257330f729Sjoerg                                               CGF.getContext().BoolTy, Args);
17267330f729Sjoerg 
17277330f729Sjoerg   return SuccessFailureRVal.getScalarVal();
17287330f729Sjoerg }
17297330f729Sjoerg 
EmitAtomicCompareExchange(RValue Expected,RValue Desired,llvm::AtomicOrdering Success,llvm::AtomicOrdering Failure,bool IsWeak)17307330f729Sjoerg std::pair<RValue, llvm::Value *> AtomicInfo::EmitAtomicCompareExchange(
17317330f729Sjoerg     RValue Expected, RValue Desired, llvm::AtomicOrdering Success,
17327330f729Sjoerg     llvm::AtomicOrdering Failure, bool IsWeak) {
17337330f729Sjoerg   if (isStrongerThan(Failure, Success))
17347330f729Sjoerg     // Don't assert on undefined behavior "failure argument shall be no stronger
17357330f729Sjoerg     // than the success argument".
17367330f729Sjoerg     Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(Success);
17377330f729Sjoerg 
17387330f729Sjoerg   // Check whether we should use a library call.
17397330f729Sjoerg   if (shouldUseLibcall()) {
17407330f729Sjoerg     // Produce a source address.
17417330f729Sjoerg     Address ExpectedAddr = materializeRValue(Expected);
17427330f729Sjoerg     Address DesiredAddr = materializeRValue(Desired);
17437330f729Sjoerg     auto *Res = EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(),
17447330f729Sjoerg                                                  DesiredAddr.getPointer(),
17457330f729Sjoerg                                                  Success, Failure);
17467330f729Sjoerg     return std::make_pair(
17477330f729Sjoerg         convertAtomicTempToRValue(ExpectedAddr, AggValueSlot::ignored(),
17487330f729Sjoerg                                   SourceLocation(), /*AsValue=*/false),
17497330f729Sjoerg         Res);
17507330f729Sjoerg   }
17517330f729Sjoerg 
17527330f729Sjoerg   // If we've got a scalar value of the right size, try to avoid going
17537330f729Sjoerg   // through memory.
17547330f729Sjoerg   auto *ExpectedVal = convertRValueToInt(Expected);
17557330f729Sjoerg   auto *DesiredVal = convertRValueToInt(Desired);
17567330f729Sjoerg   auto Res = EmitAtomicCompareExchangeOp(ExpectedVal, DesiredVal, Success,
17577330f729Sjoerg                                          Failure, IsWeak);
17587330f729Sjoerg   return std::make_pair(
17597330f729Sjoerg       ConvertIntToValueOrAtomic(Res.first, AggValueSlot::ignored(),
17607330f729Sjoerg                                 SourceLocation(), /*AsValue=*/false),
17617330f729Sjoerg       Res.second);
17627330f729Sjoerg }
17637330f729Sjoerg 
17647330f729Sjoerg static void
EmitAtomicUpdateValue(CodeGenFunction & CGF,AtomicInfo & Atomics,RValue OldRVal,const llvm::function_ref<RValue (RValue)> & UpdateOp,Address DesiredAddr)17657330f729Sjoerg EmitAtomicUpdateValue(CodeGenFunction &CGF, AtomicInfo &Atomics, RValue OldRVal,
17667330f729Sjoerg                       const llvm::function_ref<RValue(RValue)> &UpdateOp,
17677330f729Sjoerg                       Address DesiredAddr) {
17687330f729Sjoerg   RValue UpRVal;
17697330f729Sjoerg   LValue AtomicLVal = Atomics.getAtomicLValue();
17707330f729Sjoerg   LValue DesiredLVal;
17717330f729Sjoerg   if (AtomicLVal.isSimple()) {
17727330f729Sjoerg     UpRVal = OldRVal;
17737330f729Sjoerg     DesiredLVal = CGF.MakeAddrLValue(DesiredAddr, AtomicLVal.getType());
17747330f729Sjoerg   } else {
17757330f729Sjoerg     // Build new lvalue for temp address.
17767330f729Sjoerg     Address Ptr = Atomics.materializeRValue(OldRVal);
17777330f729Sjoerg     LValue UpdateLVal;
17787330f729Sjoerg     if (AtomicLVal.isBitField()) {
17797330f729Sjoerg       UpdateLVal =
17807330f729Sjoerg           LValue::MakeBitfield(Ptr, AtomicLVal.getBitFieldInfo(),
17817330f729Sjoerg                                AtomicLVal.getType(),
17827330f729Sjoerg                                AtomicLVal.getBaseInfo(),
17837330f729Sjoerg                                AtomicLVal.getTBAAInfo());
17847330f729Sjoerg       DesiredLVal =
17857330f729Sjoerg           LValue::MakeBitfield(DesiredAddr, AtomicLVal.getBitFieldInfo(),
17867330f729Sjoerg                                AtomicLVal.getType(), AtomicLVal.getBaseInfo(),
17877330f729Sjoerg                                AtomicLVal.getTBAAInfo());
17887330f729Sjoerg     } else if (AtomicLVal.isVectorElt()) {
17897330f729Sjoerg       UpdateLVal = LValue::MakeVectorElt(Ptr, AtomicLVal.getVectorIdx(),
17907330f729Sjoerg                                          AtomicLVal.getType(),
17917330f729Sjoerg                                          AtomicLVal.getBaseInfo(),
17927330f729Sjoerg                                          AtomicLVal.getTBAAInfo());
17937330f729Sjoerg       DesiredLVal = LValue::MakeVectorElt(
17947330f729Sjoerg           DesiredAddr, AtomicLVal.getVectorIdx(), AtomicLVal.getType(),
17957330f729Sjoerg           AtomicLVal.getBaseInfo(), AtomicLVal.getTBAAInfo());
17967330f729Sjoerg     } else {
17977330f729Sjoerg       assert(AtomicLVal.isExtVectorElt());
17987330f729Sjoerg       UpdateLVal = LValue::MakeExtVectorElt(Ptr, AtomicLVal.getExtVectorElts(),
17997330f729Sjoerg                                             AtomicLVal.getType(),
18007330f729Sjoerg                                             AtomicLVal.getBaseInfo(),
18017330f729Sjoerg                                             AtomicLVal.getTBAAInfo());
18027330f729Sjoerg       DesiredLVal = LValue::MakeExtVectorElt(
18037330f729Sjoerg           DesiredAddr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(),
18047330f729Sjoerg           AtomicLVal.getBaseInfo(), AtomicLVal.getTBAAInfo());
18057330f729Sjoerg     }
18067330f729Sjoerg     UpRVal = CGF.EmitLoadOfLValue(UpdateLVal, SourceLocation());
18077330f729Sjoerg   }
18087330f729Sjoerg   // Store new value in the corresponding memory area.
18097330f729Sjoerg   RValue NewRVal = UpdateOp(UpRVal);
18107330f729Sjoerg   if (NewRVal.isScalar()) {
18117330f729Sjoerg     CGF.EmitStoreThroughLValue(NewRVal, DesiredLVal);
18127330f729Sjoerg   } else {
18137330f729Sjoerg     assert(NewRVal.isComplex());
18147330f729Sjoerg     CGF.EmitStoreOfComplex(NewRVal.getComplexVal(), DesiredLVal,
18157330f729Sjoerg                            /*isInit=*/false);
18167330f729Sjoerg   }
18177330f729Sjoerg }
18187330f729Sjoerg 
EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO,const llvm::function_ref<RValue (RValue)> & UpdateOp,bool IsVolatile)18197330f729Sjoerg void AtomicInfo::EmitAtomicUpdateLibcall(
18207330f729Sjoerg     llvm::AtomicOrdering AO, const llvm::function_ref<RValue(RValue)> &UpdateOp,
18217330f729Sjoerg     bool IsVolatile) {
18227330f729Sjoerg   auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO);
18237330f729Sjoerg 
18247330f729Sjoerg   Address ExpectedAddr = CreateTempAlloca();
18257330f729Sjoerg 
18267330f729Sjoerg   EmitAtomicLoadLibcall(ExpectedAddr.getPointer(), AO, IsVolatile);
18277330f729Sjoerg   auto *ContBB = CGF.createBasicBlock("atomic_cont");
18287330f729Sjoerg   auto *ExitBB = CGF.createBasicBlock("atomic_exit");
18297330f729Sjoerg   CGF.EmitBlock(ContBB);
18307330f729Sjoerg   Address DesiredAddr = CreateTempAlloca();
18317330f729Sjoerg   if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) ||
18327330f729Sjoerg       requiresMemSetZero(getAtomicAddress().getElementType())) {
18337330f729Sjoerg     auto *OldVal = CGF.Builder.CreateLoad(ExpectedAddr);
18347330f729Sjoerg     CGF.Builder.CreateStore(OldVal, DesiredAddr);
18357330f729Sjoerg   }
18367330f729Sjoerg   auto OldRVal = convertAtomicTempToRValue(ExpectedAddr,
18377330f729Sjoerg                                            AggValueSlot::ignored(),
18387330f729Sjoerg                                            SourceLocation(), /*AsValue=*/false);
18397330f729Sjoerg   EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, DesiredAddr);
18407330f729Sjoerg   auto *Res =
18417330f729Sjoerg       EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(),
18427330f729Sjoerg                                        DesiredAddr.getPointer(),
18437330f729Sjoerg                                        AO, Failure);
18447330f729Sjoerg   CGF.Builder.CreateCondBr(Res, ExitBB, ContBB);
18457330f729Sjoerg   CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
18467330f729Sjoerg }
18477330f729Sjoerg 
EmitAtomicUpdateOp(llvm::AtomicOrdering AO,const llvm::function_ref<RValue (RValue)> & UpdateOp,bool IsVolatile)18487330f729Sjoerg void AtomicInfo::EmitAtomicUpdateOp(
18497330f729Sjoerg     llvm::AtomicOrdering AO, const llvm::function_ref<RValue(RValue)> &UpdateOp,
18507330f729Sjoerg     bool IsVolatile) {
18517330f729Sjoerg   auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO);
18527330f729Sjoerg 
18537330f729Sjoerg   // Do the atomic load.
1854*e038c9c4Sjoerg   auto *OldVal = EmitAtomicLoadOp(Failure, IsVolatile);
18557330f729Sjoerg   // For non-simple lvalues perform compare-and-swap procedure.
18567330f729Sjoerg   auto *ContBB = CGF.createBasicBlock("atomic_cont");
18577330f729Sjoerg   auto *ExitBB = CGF.createBasicBlock("atomic_exit");
18587330f729Sjoerg   auto *CurBB = CGF.Builder.GetInsertBlock();
18597330f729Sjoerg   CGF.EmitBlock(ContBB);
18607330f729Sjoerg   llvm::PHINode *PHI = CGF.Builder.CreatePHI(OldVal->getType(),
18617330f729Sjoerg                                              /*NumReservedValues=*/2);
18627330f729Sjoerg   PHI->addIncoming(OldVal, CurBB);
18637330f729Sjoerg   Address NewAtomicAddr = CreateTempAlloca();
18647330f729Sjoerg   Address NewAtomicIntAddr = emitCastToAtomicIntPointer(NewAtomicAddr);
18657330f729Sjoerg   if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) ||
18667330f729Sjoerg       requiresMemSetZero(getAtomicAddress().getElementType())) {
18677330f729Sjoerg     CGF.Builder.CreateStore(PHI, NewAtomicIntAddr);
18687330f729Sjoerg   }
18697330f729Sjoerg   auto OldRVal = ConvertIntToValueOrAtomic(PHI, AggValueSlot::ignored(),
18707330f729Sjoerg                                            SourceLocation(), /*AsValue=*/false);
18717330f729Sjoerg   EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, NewAtomicAddr);
18727330f729Sjoerg   auto *DesiredVal = CGF.Builder.CreateLoad(NewAtomicIntAddr);
18737330f729Sjoerg   // Try to write new value using cmpxchg operation.
18747330f729Sjoerg   auto Res = EmitAtomicCompareExchangeOp(PHI, DesiredVal, AO, Failure);
18757330f729Sjoerg   PHI->addIncoming(Res.first, CGF.Builder.GetInsertBlock());
18767330f729Sjoerg   CGF.Builder.CreateCondBr(Res.second, ExitBB, ContBB);
18777330f729Sjoerg   CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
18787330f729Sjoerg }
18797330f729Sjoerg 
EmitAtomicUpdateValue(CodeGenFunction & CGF,AtomicInfo & Atomics,RValue UpdateRVal,Address DesiredAddr)18807330f729Sjoerg static void EmitAtomicUpdateValue(CodeGenFunction &CGF, AtomicInfo &Atomics,
18817330f729Sjoerg                                   RValue UpdateRVal, Address DesiredAddr) {
18827330f729Sjoerg   LValue AtomicLVal = Atomics.getAtomicLValue();
18837330f729Sjoerg   LValue DesiredLVal;
18847330f729Sjoerg   // Build new lvalue for temp address.
18857330f729Sjoerg   if (AtomicLVal.isBitField()) {
18867330f729Sjoerg     DesiredLVal =
18877330f729Sjoerg         LValue::MakeBitfield(DesiredAddr, AtomicLVal.getBitFieldInfo(),
18887330f729Sjoerg                              AtomicLVal.getType(), AtomicLVal.getBaseInfo(),
18897330f729Sjoerg                              AtomicLVal.getTBAAInfo());
18907330f729Sjoerg   } else if (AtomicLVal.isVectorElt()) {
18917330f729Sjoerg     DesiredLVal =
18927330f729Sjoerg         LValue::MakeVectorElt(DesiredAddr, AtomicLVal.getVectorIdx(),
18937330f729Sjoerg                               AtomicLVal.getType(), AtomicLVal.getBaseInfo(),
18947330f729Sjoerg                               AtomicLVal.getTBAAInfo());
18957330f729Sjoerg   } else {
18967330f729Sjoerg     assert(AtomicLVal.isExtVectorElt());
18977330f729Sjoerg     DesiredLVal = LValue::MakeExtVectorElt(
18987330f729Sjoerg         DesiredAddr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(),
18997330f729Sjoerg         AtomicLVal.getBaseInfo(), AtomicLVal.getTBAAInfo());
19007330f729Sjoerg   }
19017330f729Sjoerg   // Store new value in the corresponding memory area.
19027330f729Sjoerg   assert(UpdateRVal.isScalar());
19037330f729Sjoerg   CGF.EmitStoreThroughLValue(UpdateRVal, DesiredLVal);
19047330f729Sjoerg }
19057330f729Sjoerg 
EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO,RValue UpdateRVal,bool IsVolatile)19067330f729Sjoerg void AtomicInfo::EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO,
19077330f729Sjoerg                                          RValue UpdateRVal, bool IsVolatile) {
19087330f729Sjoerg   auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO);
19097330f729Sjoerg 
19107330f729Sjoerg   Address ExpectedAddr = CreateTempAlloca();
19117330f729Sjoerg 
19127330f729Sjoerg   EmitAtomicLoadLibcall(ExpectedAddr.getPointer(), AO, IsVolatile);
19137330f729Sjoerg   auto *ContBB = CGF.createBasicBlock("atomic_cont");
19147330f729Sjoerg   auto *ExitBB = CGF.createBasicBlock("atomic_exit");
19157330f729Sjoerg   CGF.EmitBlock(ContBB);
19167330f729Sjoerg   Address DesiredAddr = CreateTempAlloca();
19177330f729Sjoerg   if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) ||
19187330f729Sjoerg       requiresMemSetZero(getAtomicAddress().getElementType())) {
19197330f729Sjoerg     auto *OldVal = CGF.Builder.CreateLoad(ExpectedAddr);
19207330f729Sjoerg     CGF.Builder.CreateStore(OldVal, DesiredAddr);
19217330f729Sjoerg   }
19227330f729Sjoerg   EmitAtomicUpdateValue(CGF, *this, UpdateRVal, DesiredAddr);
19237330f729Sjoerg   auto *Res =
19247330f729Sjoerg       EmitAtomicCompareExchangeLibcall(ExpectedAddr.getPointer(),
19257330f729Sjoerg                                        DesiredAddr.getPointer(),
19267330f729Sjoerg                                        AO, Failure);
19277330f729Sjoerg   CGF.Builder.CreateCondBr(Res, ExitBB, ContBB);
19287330f729Sjoerg   CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
19297330f729Sjoerg }
19307330f729Sjoerg 
EmitAtomicUpdateOp(llvm::AtomicOrdering AO,RValue UpdateRVal,bool IsVolatile)19317330f729Sjoerg void AtomicInfo::EmitAtomicUpdateOp(llvm::AtomicOrdering AO, RValue UpdateRVal,
19327330f729Sjoerg                                     bool IsVolatile) {
19337330f729Sjoerg   auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO);
19347330f729Sjoerg 
19357330f729Sjoerg   // Do the atomic load.
1936*e038c9c4Sjoerg   auto *OldVal = EmitAtomicLoadOp(Failure, IsVolatile);
19377330f729Sjoerg   // For non-simple lvalues perform compare-and-swap procedure.
19387330f729Sjoerg   auto *ContBB = CGF.createBasicBlock("atomic_cont");
19397330f729Sjoerg   auto *ExitBB = CGF.createBasicBlock("atomic_exit");
19407330f729Sjoerg   auto *CurBB = CGF.Builder.GetInsertBlock();
19417330f729Sjoerg   CGF.EmitBlock(ContBB);
19427330f729Sjoerg   llvm::PHINode *PHI = CGF.Builder.CreatePHI(OldVal->getType(),
19437330f729Sjoerg                                              /*NumReservedValues=*/2);
19447330f729Sjoerg   PHI->addIncoming(OldVal, CurBB);
19457330f729Sjoerg   Address NewAtomicAddr = CreateTempAlloca();
19467330f729Sjoerg   Address NewAtomicIntAddr = emitCastToAtomicIntPointer(NewAtomicAddr);
19477330f729Sjoerg   if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) ||
19487330f729Sjoerg       requiresMemSetZero(getAtomicAddress().getElementType())) {
19497330f729Sjoerg     CGF.Builder.CreateStore(PHI, NewAtomicIntAddr);
19507330f729Sjoerg   }
19517330f729Sjoerg   EmitAtomicUpdateValue(CGF, *this, UpdateRVal, NewAtomicAddr);
19527330f729Sjoerg   auto *DesiredVal = CGF.Builder.CreateLoad(NewAtomicIntAddr);
19537330f729Sjoerg   // Try to write new value using cmpxchg operation.
19547330f729Sjoerg   auto Res = EmitAtomicCompareExchangeOp(PHI, DesiredVal, AO, Failure);
19557330f729Sjoerg   PHI->addIncoming(Res.first, CGF.Builder.GetInsertBlock());
19567330f729Sjoerg   CGF.Builder.CreateCondBr(Res.second, ExitBB, ContBB);
19577330f729Sjoerg   CGF.EmitBlock(ExitBB, /*IsFinished=*/true);
19587330f729Sjoerg }
19597330f729Sjoerg 
EmitAtomicUpdate(llvm::AtomicOrdering AO,const llvm::function_ref<RValue (RValue)> & UpdateOp,bool IsVolatile)19607330f729Sjoerg void AtomicInfo::EmitAtomicUpdate(
19617330f729Sjoerg     llvm::AtomicOrdering AO, const llvm::function_ref<RValue(RValue)> &UpdateOp,
19627330f729Sjoerg     bool IsVolatile) {
19637330f729Sjoerg   if (shouldUseLibcall()) {
19647330f729Sjoerg     EmitAtomicUpdateLibcall(AO, UpdateOp, IsVolatile);
19657330f729Sjoerg   } else {
19667330f729Sjoerg     EmitAtomicUpdateOp(AO, UpdateOp, IsVolatile);
19677330f729Sjoerg   }
19687330f729Sjoerg }
19697330f729Sjoerg 
EmitAtomicUpdate(llvm::AtomicOrdering AO,RValue UpdateRVal,bool IsVolatile)19707330f729Sjoerg void AtomicInfo::EmitAtomicUpdate(llvm::AtomicOrdering AO, RValue UpdateRVal,
19717330f729Sjoerg                                   bool IsVolatile) {
19727330f729Sjoerg   if (shouldUseLibcall()) {
19737330f729Sjoerg     EmitAtomicUpdateLibcall(AO, UpdateRVal, IsVolatile);
19747330f729Sjoerg   } else {
19757330f729Sjoerg     EmitAtomicUpdateOp(AO, UpdateRVal, IsVolatile);
19767330f729Sjoerg   }
19777330f729Sjoerg }
19787330f729Sjoerg 
EmitAtomicStore(RValue rvalue,LValue lvalue,bool isInit)19797330f729Sjoerg void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue lvalue,
19807330f729Sjoerg                                       bool isInit) {
19817330f729Sjoerg   bool IsVolatile = lvalue.isVolatileQualified();
19827330f729Sjoerg   llvm::AtomicOrdering AO;
19837330f729Sjoerg   if (lvalue.getType()->isAtomicType()) {
19847330f729Sjoerg     AO = llvm::AtomicOrdering::SequentiallyConsistent;
19857330f729Sjoerg   } else {
19867330f729Sjoerg     AO = llvm::AtomicOrdering::Release;
19877330f729Sjoerg     IsVolatile = true;
19887330f729Sjoerg   }
19897330f729Sjoerg   return EmitAtomicStore(rvalue, lvalue, AO, IsVolatile, isInit);
19907330f729Sjoerg }
19917330f729Sjoerg 
19927330f729Sjoerg /// Emit a store to an l-value of atomic type.
19937330f729Sjoerg ///
19947330f729Sjoerg /// Note that the r-value is expected to be an r-value *of the atomic
19957330f729Sjoerg /// type*; this means that for aggregate r-values, it should include
19967330f729Sjoerg /// storage for any padding that was necessary.
EmitAtomicStore(RValue rvalue,LValue dest,llvm::AtomicOrdering AO,bool IsVolatile,bool isInit)19977330f729Sjoerg void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest,
19987330f729Sjoerg                                       llvm::AtomicOrdering AO, bool IsVolatile,
19997330f729Sjoerg                                       bool isInit) {
20007330f729Sjoerg   // If this is an aggregate r-value, it should agree in type except
20017330f729Sjoerg   // maybe for address-space qualification.
20027330f729Sjoerg   assert(!rvalue.isAggregate() ||
2003*e038c9c4Sjoerg          rvalue.getAggregateAddress().getElementType() ==
2004*e038c9c4Sjoerg              dest.getAddress(*this).getElementType());
20057330f729Sjoerg 
20067330f729Sjoerg   AtomicInfo atomics(*this, dest);
20077330f729Sjoerg   LValue LVal = atomics.getAtomicLValue();
20087330f729Sjoerg 
20097330f729Sjoerg   // If this is an initialization, just put the value there normally.
20107330f729Sjoerg   if (LVal.isSimple()) {
20117330f729Sjoerg     if (isInit) {
20127330f729Sjoerg       atomics.emitCopyIntoMemory(rvalue);
20137330f729Sjoerg       return;
20147330f729Sjoerg     }
20157330f729Sjoerg 
20167330f729Sjoerg     // Check whether we should use a library call.
20177330f729Sjoerg     if (atomics.shouldUseLibcall()) {
20187330f729Sjoerg       // Produce a source address.
20197330f729Sjoerg       Address srcAddr = atomics.materializeRValue(rvalue);
20207330f729Sjoerg 
20217330f729Sjoerg       // void __atomic_store(size_t size, void *mem, void *val, int order)
20227330f729Sjoerg       CallArgList args;
20237330f729Sjoerg       args.add(RValue::get(atomics.getAtomicSizeValue()),
20247330f729Sjoerg                getContext().getSizeType());
20257330f729Sjoerg       args.add(RValue::get(EmitCastToVoidPtr(atomics.getAtomicPointer())),
20267330f729Sjoerg                getContext().VoidPtrTy);
20277330f729Sjoerg       args.add(RValue::get(EmitCastToVoidPtr(srcAddr.getPointer())),
20287330f729Sjoerg                getContext().VoidPtrTy);
20297330f729Sjoerg       args.add(
20307330f729Sjoerg           RValue::get(llvm::ConstantInt::get(IntTy, (int)llvm::toCABI(AO))),
20317330f729Sjoerg           getContext().IntTy);
20327330f729Sjoerg       emitAtomicLibcall(*this, "__atomic_store", getContext().VoidTy, args);
20337330f729Sjoerg       return;
20347330f729Sjoerg     }
20357330f729Sjoerg 
20367330f729Sjoerg     // Okay, we're doing this natively.
20377330f729Sjoerg     llvm::Value *intValue = atomics.convertRValueToInt(rvalue);
20387330f729Sjoerg 
20397330f729Sjoerg     // Do the atomic store.
20407330f729Sjoerg     Address addr =
20417330f729Sjoerg         atomics.emitCastToAtomicIntPointer(atomics.getAtomicAddress());
20427330f729Sjoerg     intValue = Builder.CreateIntCast(
20437330f729Sjoerg         intValue, addr.getElementType(), /*isSigned=*/false);
20447330f729Sjoerg     llvm::StoreInst *store = Builder.CreateStore(intValue, addr);
20457330f729Sjoerg 
2046*e038c9c4Sjoerg     if (AO == llvm::AtomicOrdering::Acquire)
2047*e038c9c4Sjoerg       AO = llvm::AtomicOrdering::Monotonic;
2048*e038c9c4Sjoerg     else if (AO == llvm::AtomicOrdering::AcquireRelease)
2049*e038c9c4Sjoerg       AO = llvm::AtomicOrdering::Release;
20507330f729Sjoerg     // Initializations don't need to be atomic.
20517330f729Sjoerg     if (!isInit)
20527330f729Sjoerg       store->setAtomic(AO);
20537330f729Sjoerg 
20547330f729Sjoerg     // Other decoration.
20557330f729Sjoerg     if (IsVolatile)
20567330f729Sjoerg       store->setVolatile(true);
20577330f729Sjoerg     CGM.DecorateInstructionWithTBAA(store, dest.getTBAAInfo());
20587330f729Sjoerg     return;
20597330f729Sjoerg   }
20607330f729Sjoerg 
20617330f729Sjoerg   // Emit simple atomic update operation.
20627330f729Sjoerg   atomics.EmitAtomicUpdate(AO, rvalue, IsVolatile);
20637330f729Sjoerg }
20647330f729Sjoerg 
20657330f729Sjoerg /// Emit a compare-and-exchange op for atomic type.
20667330f729Sjoerg ///
EmitAtomicCompareExchange(LValue Obj,RValue Expected,RValue Desired,SourceLocation Loc,llvm::AtomicOrdering Success,llvm::AtomicOrdering Failure,bool IsWeak,AggValueSlot Slot)20677330f729Sjoerg std::pair<RValue, llvm::Value *> CodeGenFunction::EmitAtomicCompareExchange(
20687330f729Sjoerg     LValue Obj, RValue Expected, RValue Desired, SourceLocation Loc,
20697330f729Sjoerg     llvm::AtomicOrdering Success, llvm::AtomicOrdering Failure, bool IsWeak,
20707330f729Sjoerg     AggValueSlot Slot) {
20717330f729Sjoerg   // If this is an aggregate r-value, it should agree in type except
20727330f729Sjoerg   // maybe for address-space qualification.
20737330f729Sjoerg   assert(!Expected.isAggregate() ||
20747330f729Sjoerg          Expected.getAggregateAddress().getElementType() ==
2075*e038c9c4Sjoerg              Obj.getAddress(*this).getElementType());
20767330f729Sjoerg   assert(!Desired.isAggregate() ||
20777330f729Sjoerg          Desired.getAggregateAddress().getElementType() ==
2078*e038c9c4Sjoerg              Obj.getAddress(*this).getElementType());
20797330f729Sjoerg   AtomicInfo Atomics(*this, Obj);
20807330f729Sjoerg 
20817330f729Sjoerg   return Atomics.EmitAtomicCompareExchange(Expected, Desired, Success, Failure,
20827330f729Sjoerg                                            IsWeak);
20837330f729Sjoerg }
20847330f729Sjoerg 
EmitAtomicUpdate(LValue LVal,llvm::AtomicOrdering AO,const llvm::function_ref<RValue (RValue)> & UpdateOp,bool IsVolatile)20857330f729Sjoerg void CodeGenFunction::EmitAtomicUpdate(
20867330f729Sjoerg     LValue LVal, llvm::AtomicOrdering AO,
20877330f729Sjoerg     const llvm::function_ref<RValue(RValue)> &UpdateOp, bool IsVolatile) {
20887330f729Sjoerg   AtomicInfo Atomics(*this, LVal);
20897330f729Sjoerg   Atomics.EmitAtomicUpdate(AO, UpdateOp, IsVolatile);
20907330f729Sjoerg }
20917330f729Sjoerg 
EmitAtomicInit(Expr * init,LValue dest)20927330f729Sjoerg void CodeGenFunction::EmitAtomicInit(Expr *init, LValue dest) {
20937330f729Sjoerg   AtomicInfo atomics(*this, dest);
20947330f729Sjoerg 
20957330f729Sjoerg   switch (atomics.getEvaluationKind()) {
20967330f729Sjoerg   case TEK_Scalar: {
20977330f729Sjoerg     llvm::Value *value = EmitScalarExpr(init);
20987330f729Sjoerg     atomics.emitCopyIntoMemory(RValue::get(value));
20997330f729Sjoerg     return;
21007330f729Sjoerg   }
21017330f729Sjoerg 
21027330f729Sjoerg   case TEK_Complex: {
21037330f729Sjoerg     ComplexPairTy value = EmitComplexExpr(init);
21047330f729Sjoerg     atomics.emitCopyIntoMemory(RValue::getComplex(value));
21057330f729Sjoerg     return;
21067330f729Sjoerg   }
21077330f729Sjoerg 
21087330f729Sjoerg   case TEK_Aggregate: {
21097330f729Sjoerg     // Fix up the destination if the initializer isn't an expression
21107330f729Sjoerg     // of atomic type.
21117330f729Sjoerg     bool Zeroed = false;
21127330f729Sjoerg     if (!init->getType()->isAtomicType()) {
21137330f729Sjoerg       Zeroed = atomics.emitMemSetZeroIfNecessary();
21147330f729Sjoerg       dest = atomics.projectValue();
21157330f729Sjoerg     }
21167330f729Sjoerg 
21177330f729Sjoerg     // Evaluate the expression directly into the destination.
2118*e038c9c4Sjoerg     AggValueSlot slot = AggValueSlot::forLValue(
2119*e038c9c4Sjoerg         dest, *this, AggValueSlot::IsNotDestructed,
2120*e038c9c4Sjoerg         AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased,
21217330f729Sjoerg         AggValueSlot::DoesNotOverlap,
2122*e038c9c4Sjoerg         Zeroed ? AggValueSlot::IsZeroed : AggValueSlot::IsNotZeroed);
21237330f729Sjoerg 
21247330f729Sjoerg     EmitAggExpr(init, slot);
21257330f729Sjoerg     return;
21267330f729Sjoerg   }
21277330f729Sjoerg   }
21287330f729Sjoerg   llvm_unreachable("bad evaluation kind");
21297330f729Sjoerg }
2130