brintos

brintos / llvm-project-archived public Read only

0
0
Text · 90.7 KiB · 0a76d04 Raw
2194 lines · cpp
1//===--- CGAtomic.cpp - Emit LLVM IR for atomic operations ----------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains the code for emitting atomic operations.10//11//===----------------------------------------------------------------------===//12 13#include "CGCall.h"14#include "CGRecordLayout.h"15#include "CodeGenFunction.h"16#include "CodeGenModule.h"17#include "TargetInfo.h"18#include "clang/AST/ASTContext.h"19#include "clang/Basic/DiagnosticFrontend.h"20#include "clang/CodeGen/CGFunctionInfo.h"21#include "llvm/ADT/DenseMap.h"22#include "llvm/IR/DataLayout.h"23#include "llvm/IR/Intrinsics.h"24 25using namespace clang;26using namespace CodeGen;27 28namespace {29  class AtomicInfo {30    CodeGenFunction &CGF;31    QualType AtomicTy;32    QualType ValueTy;33    uint64_t AtomicSizeInBits;34    uint64_t ValueSizeInBits;35    CharUnits AtomicAlign;36    CharUnits ValueAlign;37    TypeEvaluationKind EvaluationKind;38    bool UseLibcall;39    LValue LVal;40    CGBitFieldInfo BFI;41  public:42    AtomicInfo(CodeGenFunction &CGF, LValue &lvalue)43        : CGF(CGF), AtomicSizeInBits(0), ValueSizeInBits(0),44          EvaluationKind(TEK_Scalar), UseLibcall(true) {45      assert(!lvalue.isGlobalReg());46      ASTContext &C = CGF.getContext();47      if (lvalue.isSimple()) {48        AtomicTy = lvalue.getType();49        if (auto *ATy = AtomicTy->getAs<AtomicType>())50          ValueTy = ATy->getValueType();51        else52          ValueTy = AtomicTy;53        EvaluationKind = CGF.getEvaluationKind(ValueTy);54 55        uint64_t ValueAlignInBits;56        uint64_t AtomicAlignInBits;57        TypeInfo ValueTI = C.getTypeInfo(ValueTy);58        ValueSizeInBits = ValueTI.Width;59        ValueAlignInBits = ValueTI.Align;60 61        TypeInfo AtomicTI = C.getTypeInfo(AtomicTy);62        AtomicSizeInBits = AtomicTI.Width;63        AtomicAlignInBits = AtomicTI.Align;64 65        assert(ValueSizeInBits <= AtomicSizeInBits);66        assert(ValueAlignInBits <= AtomicAlignInBits);67 68        AtomicAlign = C.toCharUnitsFromBits(AtomicAlignInBits);69        ValueAlign = C.toCharUnitsFromBits(ValueAlignInBits);70        if (lvalue.getAlignment().isZero())71          lvalue.setAlignment(AtomicAlign);72 73        LVal = lvalue;74      } else if (lvalue.isBitField()) {75        ValueTy = lvalue.getType();76        ValueSizeInBits = C.getTypeSize(ValueTy);77        auto &OrigBFI = lvalue.getBitFieldInfo();78        auto Offset = OrigBFI.Offset % C.toBits(lvalue.getAlignment());79        AtomicSizeInBits = C.toBits(80            C.toCharUnitsFromBits(Offset + OrigBFI.Size + C.getCharWidth() - 1)81                .alignTo(lvalue.getAlignment()));82        llvm::Value *BitFieldPtr = lvalue.getRawBitFieldPointer(CGF);83        auto OffsetInChars =84            (C.toCharUnitsFromBits(OrigBFI.Offset) / lvalue.getAlignment()) *85            lvalue.getAlignment();86        llvm::Value *StoragePtr = CGF.Builder.CreateConstGEP1_64(87            CGF.Int8Ty, BitFieldPtr, OffsetInChars.getQuantity());88        StoragePtr = CGF.Builder.CreateAddrSpaceCast(89            StoragePtr, CGF.DefaultPtrTy, "atomic_bitfield_base");90        BFI = OrigBFI;91        BFI.Offset = Offset;92        BFI.StorageSize = AtomicSizeInBits;93        BFI.StorageOffset += OffsetInChars;94        llvm::Type *StorageTy = CGF.Builder.getIntNTy(AtomicSizeInBits);95        LVal = LValue::MakeBitfield(96            Address(StoragePtr, StorageTy, lvalue.getAlignment()), BFI,97            lvalue.getType(), lvalue.getBaseInfo(), lvalue.getTBAAInfo());98        AtomicTy = C.getIntTypeForBitwidth(AtomicSizeInBits, OrigBFI.IsSigned);99        if (AtomicTy.isNull()) {100          llvm::APInt Size(101              /*numBits=*/32,102              C.toCharUnitsFromBits(AtomicSizeInBits).getQuantity());103          AtomicTy = C.getConstantArrayType(C.CharTy, Size, nullptr,104                                            ArraySizeModifier::Normal,105                                            /*IndexTypeQuals=*/0);106        }107        AtomicAlign = ValueAlign = lvalue.getAlignment();108      } else if (lvalue.isVectorElt()) {109        ValueTy = lvalue.getType()->castAs<VectorType>()->getElementType();110        ValueSizeInBits = C.getTypeSize(ValueTy);111        AtomicTy = lvalue.getType();112        AtomicSizeInBits = C.getTypeSize(AtomicTy);113        AtomicAlign = ValueAlign = lvalue.getAlignment();114        LVal = lvalue;115      } else {116        assert(lvalue.isExtVectorElt());117        ValueTy = lvalue.getType();118        ValueSizeInBits = C.getTypeSize(ValueTy);119        AtomicTy = ValueTy = CGF.getContext().getExtVectorType(120            lvalue.getType(), cast<llvm::FixedVectorType>(121                                  lvalue.getExtVectorAddress().getElementType())122                                  ->getNumElements());123        AtomicSizeInBits = C.getTypeSize(AtomicTy);124        AtomicAlign = ValueAlign = lvalue.getAlignment();125        LVal = lvalue;126      }127      UseLibcall = !C.getTargetInfo().hasBuiltinAtomic(128          AtomicSizeInBits, C.toBits(lvalue.getAlignment()));129    }130 131    QualType getAtomicType() const { return AtomicTy; }132    QualType getValueType() const { return ValueTy; }133    CharUnits getAtomicAlignment() const { return AtomicAlign; }134    uint64_t getAtomicSizeInBits() const { return AtomicSizeInBits; }135    uint64_t getValueSizeInBits() const { return ValueSizeInBits; }136    TypeEvaluationKind getEvaluationKind() const { return EvaluationKind; }137    bool shouldUseLibcall() const { return UseLibcall; }138    const LValue &getAtomicLValue() const { return LVal; }139    llvm::Value *getAtomicPointer() const {140      if (LVal.isSimple())141        return LVal.emitRawPointer(CGF);142      else if (LVal.isBitField())143        return LVal.getRawBitFieldPointer(CGF);144      else if (LVal.isVectorElt())145        return LVal.getRawVectorPointer(CGF);146      assert(LVal.isExtVectorElt());147      return LVal.getRawExtVectorPointer(CGF);148    }149    Address getAtomicAddress() const {150      llvm::Type *ElTy;151      if (LVal.isSimple())152        ElTy = LVal.getAddress().getElementType();153      else if (LVal.isBitField())154        ElTy = LVal.getBitFieldAddress().getElementType();155      else if (LVal.isVectorElt())156        ElTy = LVal.getVectorAddress().getElementType();157      else158        ElTy = LVal.getExtVectorAddress().getElementType();159      return Address(getAtomicPointer(), ElTy, getAtomicAlignment());160    }161 162    Address getAtomicAddressAsAtomicIntPointer() const {163      return castToAtomicIntPointer(getAtomicAddress());164    }165 166    /// Is the atomic size larger than the underlying value type?167    ///168    /// Note that the absence of padding does not mean that atomic169    /// objects are completely interchangeable with non-atomic170    /// objects: we might have promoted the alignment of a type171    /// without making it bigger.172    bool hasPadding() const {173      return (ValueSizeInBits != AtomicSizeInBits);174    }175 176    bool emitMemSetZeroIfNecessary() const;177 178    llvm::Value *getAtomicSizeValue() const {179      CharUnits size = CGF.getContext().toCharUnitsFromBits(AtomicSizeInBits);180      return CGF.CGM.getSize(size);181    }182 183    /// Cast the given pointer to an integer pointer suitable for atomic184    /// operations if the source.185    Address castToAtomicIntPointer(Address Addr) const;186 187    /// If Addr is compatible with the iN that will be used for an atomic188    /// operation, bitcast it. Otherwise, create a temporary that is suitable189    /// and copy the value across.190    Address convertToAtomicIntPointer(Address Addr) const;191 192    /// Turn an atomic-layout object into an r-value.193    RValue convertAtomicTempToRValue(Address addr, AggValueSlot resultSlot,194                                     SourceLocation loc, bool AsValue) const;195 196    llvm::Value *getScalarRValValueOrNull(RValue RVal) const;197 198    /// Converts an rvalue to integer value if needed.199    llvm::Value *convertRValueToInt(RValue RVal, bool CmpXchg = false) const;200 201    RValue ConvertToValueOrAtomic(llvm::Value *IntVal, AggValueSlot ResultSlot,202                                  SourceLocation Loc, bool AsValue,203                                  bool CmpXchg = false) const;204 205    /// Copy an atomic r-value into atomic-layout memory.206    void emitCopyIntoMemory(RValue rvalue) const;207 208    /// Project an l-value down to the value field.209    LValue projectValue() const {210      assert(LVal.isSimple());211      Address addr = getAtomicAddress();212      if (hasPadding())213        addr = CGF.Builder.CreateStructGEP(addr, 0);214 215      return LValue::MakeAddr(addr, getValueType(), CGF.getContext(),216                              LVal.getBaseInfo(), LVal.getTBAAInfo());217    }218 219    /// Emits atomic load.220    /// \returns Loaded value.221    RValue EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc,222                          bool AsValue, llvm::AtomicOrdering AO,223                          bool IsVolatile);224 225    /// Emits atomic compare-and-exchange sequence.226    /// \param Expected Expected value.227    /// \param Desired Desired value.228    /// \param Success Atomic ordering for success operation.229    /// \param Failure Atomic ordering for failed operation.230    /// \param IsWeak true if atomic operation is weak, false otherwise.231    /// \returns Pair of values: previous value from storage (value type) and232    /// boolean flag (i1 type) with true if success and false otherwise.233    std::pair<RValue, llvm::Value *>234    EmitAtomicCompareExchange(RValue Expected, RValue Desired,235                              llvm::AtomicOrdering Success =236                                  llvm::AtomicOrdering::SequentiallyConsistent,237                              llvm::AtomicOrdering Failure =238                                  llvm::AtomicOrdering::SequentiallyConsistent,239                              bool IsWeak = false);240 241    /// Emits atomic update.242    /// \param AO Atomic ordering.243    /// \param UpdateOp Update operation for the current lvalue.244    void EmitAtomicUpdate(llvm::AtomicOrdering AO,245                          const llvm::function_ref<RValue(RValue)> &UpdateOp,246                          bool IsVolatile);247    /// Emits atomic update.248    /// \param AO Atomic ordering.249    void EmitAtomicUpdate(llvm::AtomicOrdering AO, RValue UpdateRVal,250                          bool IsVolatile);251 252    /// Materialize an atomic r-value in atomic-layout memory.253    Address materializeRValue(RValue rvalue) const;254 255    /// Creates temp alloca for intermediate operations on atomic value.256    Address CreateTempAlloca() const;257  private:258    bool requiresMemSetZero(llvm::Type *type) const;259 260 261    /// Emits atomic load as a libcall.262    void EmitAtomicLoadLibcall(llvm::Value *AddForLoaded,263                               llvm::AtomicOrdering AO, bool IsVolatile);264    /// Emits atomic load as LLVM instruction.265    llvm::Value *EmitAtomicLoadOp(llvm::AtomicOrdering AO, bool IsVolatile,266                                  bool CmpXchg = false);267    /// Emits atomic compare-and-exchange op as a libcall.268    llvm::Value *EmitAtomicCompareExchangeLibcall(269        llvm::Value *ExpectedAddr, llvm::Value *DesiredAddr,270        llvm::AtomicOrdering Success =271            llvm::AtomicOrdering::SequentiallyConsistent,272        llvm::AtomicOrdering Failure =273            llvm::AtomicOrdering::SequentiallyConsistent);274    /// Emits atomic compare-and-exchange op as LLVM instruction.275    std::pair<llvm::Value *, llvm::Value *> EmitAtomicCompareExchangeOp(276        llvm::Value *ExpectedVal, llvm::Value *DesiredVal,277        llvm::AtomicOrdering Success =278            llvm::AtomicOrdering::SequentiallyConsistent,279        llvm::AtomicOrdering Failure =280            llvm::AtomicOrdering::SequentiallyConsistent,281        bool IsWeak = false);282    /// Emit atomic update as libcalls.283    void284    EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO,285                            const llvm::function_ref<RValue(RValue)> &UpdateOp,286                            bool IsVolatile);287    /// Emit atomic update as LLVM instructions.288    void EmitAtomicUpdateOp(llvm::AtomicOrdering AO,289                            const llvm::function_ref<RValue(RValue)> &UpdateOp,290                            bool IsVolatile);291    /// Emit atomic update as libcalls.292    void EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO, RValue UpdateRVal,293                                 bool IsVolatile);294    /// Emit atomic update as LLVM instructions.295    void EmitAtomicUpdateOp(llvm::AtomicOrdering AO, RValue UpdateRal,296                            bool IsVolatile);297  };298}299 300Address AtomicInfo::CreateTempAlloca() const {301  Address TempAlloca = CGF.CreateMemTemp(302      (LVal.isBitField() && ValueSizeInBits > AtomicSizeInBits) ? ValueTy303                                                                : AtomicTy,304      getAtomicAlignment(),305      "atomic-temp");306  // Cast to pointer to value type for bitfields.307  if (LVal.isBitField())308    return CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(309        TempAlloca, getAtomicAddress().getType(),310        getAtomicAddress().getElementType());311  return TempAlloca;312}313 314static RValue emitAtomicLibcall(CodeGenFunction &CGF,315                                StringRef fnName,316                                QualType resultType,317                                CallArgList &args) {318  const CGFunctionInfo &fnInfo =319    CGF.CGM.getTypes().arrangeBuiltinFunctionCall(resultType, args);320  llvm::FunctionType *fnTy = CGF.CGM.getTypes().GetFunctionType(fnInfo);321  llvm::AttrBuilder fnAttrB(CGF.getLLVMContext());322  fnAttrB.addAttribute(llvm::Attribute::NoUnwind);323  fnAttrB.addAttribute(llvm::Attribute::WillReturn);324  llvm::AttributeList fnAttrs = llvm::AttributeList::get(325      CGF.getLLVMContext(), llvm::AttributeList::FunctionIndex, fnAttrB);326 327  llvm::FunctionCallee fn =328      CGF.CGM.CreateRuntimeFunction(fnTy, fnName, fnAttrs);329  auto callee = CGCallee::forDirect(fn);330  return CGF.EmitCall(fnInfo, callee, ReturnValueSlot(), args);331}332 333/// Does a store of the given IR type modify the full expected width?334static bool isFullSizeType(CodeGenModule &CGM, llvm::Type *type,335                           uint64_t expectedSize) {336  return (CGM.getDataLayout().getTypeStoreSize(type) * 8 == expectedSize);337}338 339/// Does the atomic type require memsetting to zero before initialization?340///341/// The IR type is provided as a way of making certain queries faster.342bool AtomicInfo::requiresMemSetZero(llvm::Type *type) const {343  // If the atomic type has size padding, we definitely need a memset.344  if (hasPadding()) return true;345 346  // Otherwise, do some simple heuristics to try to avoid it:347  switch (getEvaluationKind()) {348  // For scalars and complexes, check whether the store size of the349  // type uses the full size.350  case TEK_Scalar:351    return !isFullSizeType(CGF.CGM, type, AtomicSizeInBits);352  case TEK_Complex:353    return !isFullSizeType(CGF.CGM, type->getStructElementType(0),354                           AtomicSizeInBits / 2);355 356  // Padding in structs has an undefined bit pattern.  User beware.357  case TEK_Aggregate:358    return false;359  }360  llvm_unreachable("bad evaluation kind");361}362 363bool AtomicInfo::emitMemSetZeroIfNecessary() const {364  assert(LVal.isSimple());365  Address addr = LVal.getAddress();366  if (!requiresMemSetZero(addr.getElementType()))367    return false;368 369  CGF.Builder.CreateMemSet(370      addr.emitRawPointer(CGF), llvm::ConstantInt::get(CGF.Int8Ty, 0),371      CGF.getContext().toCharUnitsFromBits(AtomicSizeInBits).getQuantity(),372      LVal.getAlignment().getAsAlign());373  return true;374}375 376static void emitAtomicCmpXchg(CodeGenFunction &CGF, AtomicExpr *E, bool IsWeak,377                              Address Dest, Address Ptr, Address Val1,378                              Address Val2, Address ExpectedResult,379                              uint64_t Size, llvm::AtomicOrdering SuccessOrder,380                              llvm::AtomicOrdering FailureOrder,381                              llvm::SyncScope::ID Scope) {382  // Note that cmpxchg doesn't support weak cmpxchg, at least at the moment.383  llvm::Value *Expected = CGF.Builder.CreateLoad(Val1);384  llvm::Value *Desired = CGF.Builder.CreateLoad(Val2);385 386  llvm::AtomicCmpXchgInst *Pair = CGF.Builder.CreateAtomicCmpXchg(387      Ptr, Expected, Desired, SuccessOrder, FailureOrder, Scope);388  Pair->setVolatile(E->isVolatile());389  Pair->setWeak(IsWeak);390  CGF.getTargetHooks().setTargetAtomicMetadata(CGF, *Pair, E);391 392  // Cmp holds the result of the compare-exchange operation: true on success,393  // false on failure.394  llvm::Value *Old = CGF.Builder.CreateExtractValue(Pair, 0);395  llvm::Value *Cmp = CGF.Builder.CreateExtractValue(Pair, 1);396 397  // This basic block is used to hold the store instruction if the operation398  // failed.399  llvm::BasicBlock *StoreExpectedBB =400      CGF.createBasicBlock("cmpxchg.store_expected", CGF.CurFn);401 402  // This basic block is the exit point of the operation, we should end up403  // here regardless of whether or not the operation succeeded.404  llvm::BasicBlock *ContinueBB =405      CGF.createBasicBlock("cmpxchg.continue", CGF.CurFn);406 407  // Update Expected if Expected isn't equal to Old, otherwise branch to the408  // exit point.409  CGF.Builder.CreateCondBr(Cmp, ContinueBB, StoreExpectedBB);410 411  CGF.Builder.SetInsertPoint(StoreExpectedBB);412  // Update the memory at Expected with Old's value.413  llvm::Type *ExpectedType = ExpectedResult.getElementType();414  const llvm::DataLayout &DL = CGF.CGM.getDataLayout();415  uint64_t ExpectedSizeInBytes = DL.getTypeStoreSize(ExpectedType);416 417  if (ExpectedSizeInBytes == Size) {418    // Sizes match: store directly419    auto *I = CGF.Builder.CreateStore(Old, ExpectedResult);420    CGF.addInstToCurrentSourceAtom(I, Old);421  } else {422    // store only the first ExpectedSizeInBytes bytes of Old423    llvm::Type *OldType = Old->getType();424 425    // Allocate temporary storage for Old value426    Address OldTmp =427        CGF.CreateTempAlloca(OldType, Ptr.getAlignment(), "old.tmp");428 429    // Store Old into this temporary430    auto *I = CGF.Builder.CreateStore(Old, OldTmp);431    CGF.addInstToCurrentSourceAtom(I, Old);432 433    // Perform memcpy for first ExpectedSizeInBytes bytes434    CGF.Builder.CreateMemCpy(ExpectedResult, OldTmp, ExpectedSizeInBytes,435                             /*isVolatile=*/false);436  }437 438  // Finally, branch to the exit point.439  CGF.Builder.CreateBr(ContinueBB);440 441  CGF.Builder.SetInsertPoint(ContinueBB);442  // Update the memory at Dest with Cmp's value.443  CGF.EmitStoreOfScalar(Cmp, CGF.MakeAddrLValue(Dest, E->getType()));444}445 446/// Given an ordering required on success, emit all possible cmpxchg447/// instructions to cope with the provided (but possibly only dynamically known)448/// FailureOrder.449static void emitAtomicCmpXchgFailureSet(450    CodeGenFunction &CGF, AtomicExpr *E, bool IsWeak, Address Dest, Address Ptr,451    Address Val1, Address Val2, Address ExpectedResult,452    llvm::Value *FailureOrderVal, uint64_t Size,453    llvm::AtomicOrdering SuccessOrder, llvm::SyncScope::ID Scope) {454  llvm::AtomicOrdering FailureOrder;455  if (llvm::ConstantInt *FO = dyn_cast<llvm::ConstantInt>(FailureOrderVal)) {456    auto FOS = FO->getSExtValue();457    if (!llvm::isValidAtomicOrderingCABI(FOS))458      FailureOrder = llvm::AtomicOrdering::Monotonic;459    else460      switch ((llvm::AtomicOrderingCABI)FOS) {461      case llvm::AtomicOrderingCABI::relaxed:462      // 31.7.2.18: "The failure argument shall not be memory_order_release463      // nor memory_order_acq_rel". Fallback to monotonic.464      case llvm::AtomicOrderingCABI::release:465      case llvm::AtomicOrderingCABI::acq_rel:466        FailureOrder = llvm::AtomicOrdering::Monotonic;467        break;468      case llvm::AtomicOrderingCABI::consume:469      case llvm::AtomicOrderingCABI::acquire:470        FailureOrder = llvm::AtomicOrdering::Acquire;471        break;472      case llvm::AtomicOrderingCABI::seq_cst:473        FailureOrder = llvm::AtomicOrdering::SequentiallyConsistent;474        break;475      }476    // Prior to c++17, "the failure argument shall be no stronger than the477    // success argument". This condition has been lifted and the only478    // precondition is 31.7.2.18. Effectively treat this as a DR and skip479    // language version checks.480    emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, ExpectedResult,481                      Size, SuccessOrder, FailureOrder, Scope);482    return;483  }484 485  // Create all the relevant BB's486  auto *MonotonicBB = CGF.createBasicBlock("monotonic_fail", CGF.CurFn);487  auto *AcquireBB = CGF.createBasicBlock("acquire_fail", CGF.CurFn);488  auto *SeqCstBB = CGF.createBasicBlock("seqcst_fail", CGF.CurFn);489  auto *ContBB = CGF.createBasicBlock("atomic.continue", CGF.CurFn);490 491  // MonotonicBB is arbitrarily chosen as the default case; in practice, this492  // doesn't matter unless someone is crazy enough to use something that493  // doesn't fold to a constant for the ordering.494  llvm::SwitchInst *SI = CGF.Builder.CreateSwitch(FailureOrderVal, MonotonicBB);495  // Implemented as acquire, since it's the closest in LLVM.496  SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::consume),497              AcquireBB);498  SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::acquire),499              AcquireBB);500  SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::seq_cst),501              SeqCstBB);502 503  // Emit all the different atomics504  CGF.Builder.SetInsertPoint(MonotonicBB);505  emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, ExpectedResult, Size,506                    SuccessOrder, llvm::AtomicOrdering::Monotonic, Scope);507  CGF.Builder.CreateBr(ContBB);508 509  CGF.Builder.SetInsertPoint(AcquireBB);510  emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, ExpectedResult, Size,511                    SuccessOrder, llvm::AtomicOrdering::Acquire, Scope);512  CGF.Builder.CreateBr(ContBB);513 514  CGF.Builder.SetInsertPoint(SeqCstBB);515  emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, ExpectedResult, Size,516                    SuccessOrder, llvm::AtomicOrdering::SequentiallyConsistent,517                    Scope);518  CGF.Builder.CreateBr(ContBB);519 520  CGF.Builder.SetInsertPoint(ContBB);521}522 523/// Duplicate the atomic min/max operation in conventional IR for the builtin524/// variants that return the new rather than the original value.525static llvm::Value *EmitPostAtomicMinMax(CGBuilderTy &Builder,526                                         AtomicExpr::AtomicOp Op,527                                         bool IsSigned,528                                         llvm::Value *OldVal,529                                         llvm::Value *RHS) {530  const bool IsFP = OldVal->getType()->isFloatingPointTy();531 532  if (IsFP) {533    llvm::Intrinsic::ID IID = (Op == AtomicExpr::AO__atomic_max_fetch ||534                               Op == AtomicExpr::AO__scoped_atomic_max_fetch)535                                  ? llvm::Intrinsic::maxnum536                                  : llvm::Intrinsic::minnum;537 538    return Builder.CreateBinaryIntrinsic(IID, OldVal, RHS, llvm::FMFSource(),539                                         "newval");540  }541 542  llvm::CmpInst::Predicate Pred;543  switch (Op) {544  default:545    llvm_unreachable("Unexpected min/max operation");546  case AtomicExpr::AO__atomic_max_fetch:547  case AtomicExpr::AO__scoped_atomic_max_fetch:548    Pred = IsSigned ? llvm::CmpInst::ICMP_SGT : llvm::CmpInst::ICMP_UGT;549    break;550  case AtomicExpr::AO__atomic_min_fetch:551  case AtomicExpr::AO__scoped_atomic_min_fetch:552    Pred = IsSigned ? llvm::CmpInst::ICMP_SLT : llvm::CmpInst::ICMP_ULT;553    break;554  }555  llvm::Value *Cmp = Builder.CreateICmp(Pred, OldVal, RHS, "tst");556  return Builder.CreateSelect(Cmp, OldVal, RHS, "newval");557}558 559static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,560                         Address Ptr, Address Val1, Address Val2,561                         Address ExpectedResult, llvm::Value *IsWeak,562                         llvm::Value *FailureOrder, uint64_t Size,563                         llvm::AtomicOrdering Order,564                         llvm::SyncScope::ID Scope) {565  llvm::AtomicRMWInst::BinOp Op = llvm::AtomicRMWInst::Add;566  bool PostOpMinMax = false;567  unsigned PostOp = 0;568 569  switch (E->getOp()) {570  case AtomicExpr::AO__c11_atomic_init:571  case AtomicExpr::AO__opencl_atomic_init:572    llvm_unreachable("Already handled!");573 574  case AtomicExpr::AO__c11_atomic_compare_exchange_strong:575  case AtomicExpr::AO__hip_atomic_compare_exchange_strong:576  case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:577    emitAtomicCmpXchgFailureSet(CGF, E, false, Dest, Ptr, Val1, Val2,578                                ExpectedResult, FailureOrder, Size, Order,579                                Scope);580    return;581  case AtomicExpr::AO__c11_atomic_compare_exchange_weak:582  case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:583  case AtomicExpr::AO__hip_atomic_compare_exchange_weak:584    emitAtomicCmpXchgFailureSet(CGF, E, true, Dest, Ptr, Val1, Val2,585                                ExpectedResult, FailureOrder, Size, Order,586                                Scope);587    return;588  case AtomicExpr::AO__atomic_compare_exchange:589  case AtomicExpr::AO__atomic_compare_exchange_n:590  case AtomicExpr::AO__scoped_atomic_compare_exchange:591  case AtomicExpr::AO__scoped_atomic_compare_exchange_n: {592    if (llvm::ConstantInt *IsWeakC = dyn_cast<llvm::ConstantInt>(IsWeak)) {593      emitAtomicCmpXchgFailureSet(CGF, E, IsWeakC->getZExtValue(), Dest, Ptr,594                                  Val1, Val2, ExpectedResult, FailureOrder,595                                  Size, Order, Scope);596    } else {597      // Create all the relevant BB's598      llvm::BasicBlock *StrongBB =599          CGF.createBasicBlock("cmpxchg.strong", CGF.CurFn);600      llvm::BasicBlock *WeakBB = CGF.createBasicBlock("cmxchg.weak", CGF.CurFn);601      llvm::BasicBlock *ContBB =602          CGF.createBasicBlock("cmpxchg.continue", CGF.CurFn);603 604      llvm::SwitchInst *SI = CGF.Builder.CreateSwitch(IsWeak, WeakBB);605      SI->addCase(CGF.Builder.getInt1(false), StrongBB);606 607      CGF.Builder.SetInsertPoint(StrongBB);608      emitAtomicCmpXchgFailureSet(CGF, E, false, Dest, Ptr, Val1, Val2,609                                  ExpectedResult, FailureOrder, Size, Order,610                                  Scope);611      CGF.Builder.CreateBr(ContBB);612 613      CGF.Builder.SetInsertPoint(WeakBB);614      emitAtomicCmpXchgFailureSet(CGF, E, true, Dest, Ptr, Val1, Val2,615                                  ExpectedResult, FailureOrder, Size, Order,616                                  Scope);617      CGF.Builder.CreateBr(ContBB);618 619      CGF.Builder.SetInsertPoint(ContBB);620    }621    return;622  }623  case AtomicExpr::AO__c11_atomic_load:624  case AtomicExpr::AO__opencl_atomic_load:625  case AtomicExpr::AO__hip_atomic_load:626  case AtomicExpr::AO__atomic_load_n:627  case AtomicExpr::AO__atomic_load:628  case AtomicExpr::AO__scoped_atomic_load_n:629  case AtomicExpr::AO__scoped_atomic_load: {630    llvm::LoadInst *Load = CGF.Builder.CreateLoad(Ptr);631    Load->setAtomic(Order, Scope);632    Load->setVolatile(E->isVolatile());633    CGF.maybeAttachRangeForLoad(Load, E->getValueType(), E->getExprLoc());634    auto *I = CGF.Builder.CreateStore(Load, Dest);635    CGF.addInstToCurrentSourceAtom(I, Load);636    return;637  }638 639  case AtomicExpr::AO__c11_atomic_store:640  case AtomicExpr::AO__opencl_atomic_store:641  case AtomicExpr::AO__hip_atomic_store:642  case AtomicExpr::AO__atomic_store:643  case AtomicExpr::AO__atomic_store_n:644  case AtomicExpr::AO__scoped_atomic_store:645  case AtomicExpr::AO__scoped_atomic_store_n: {646    llvm::Value *LoadVal1 = CGF.Builder.CreateLoad(Val1);647    llvm::StoreInst *Store = CGF.Builder.CreateStore(LoadVal1, Ptr);648    Store->setAtomic(Order, Scope);649    Store->setVolatile(E->isVolatile());650    CGF.addInstToCurrentSourceAtom(Store, LoadVal1);651    return;652  }653 654  case AtomicExpr::AO__c11_atomic_exchange:655  case AtomicExpr::AO__hip_atomic_exchange:656  case AtomicExpr::AO__opencl_atomic_exchange:657  case AtomicExpr::AO__atomic_exchange_n:658  case AtomicExpr::AO__atomic_exchange:659  case AtomicExpr::AO__scoped_atomic_exchange_n:660  case AtomicExpr::AO__scoped_atomic_exchange:661    Op = llvm::AtomicRMWInst::Xchg;662    break;663 664  case AtomicExpr::AO__atomic_add_fetch:665  case AtomicExpr::AO__scoped_atomic_add_fetch:666    PostOp = E->getValueType()->isFloatingType() ? llvm::Instruction::FAdd667                                                 : llvm::Instruction::Add;668    [[fallthrough]];669  case AtomicExpr::AO__c11_atomic_fetch_add:670  case AtomicExpr::AO__hip_atomic_fetch_add:671  case AtomicExpr::AO__opencl_atomic_fetch_add:672  case AtomicExpr::AO__atomic_fetch_add:673  case AtomicExpr::AO__scoped_atomic_fetch_add:674    Op = E->getValueType()->isFloatingType() ? llvm::AtomicRMWInst::FAdd675                                             : llvm::AtomicRMWInst::Add;676    break;677 678  case AtomicExpr::AO__atomic_sub_fetch:679  case AtomicExpr::AO__scoped_atomic_sub_fetch:680    PostOp = E->getValueType()->isFloatingType() ? llvm::Instruction::FSub681                                                 : llvm::Instruction::Sub;682    [[fallthrough]];683  case AtomicExpr::AO__c11_atomic_fetch_sub:684  case AtomicExpr::AO__hip_atomic_fetch_sub:685  case AtomicExpr::AO__opencl_atomic_fetch_sub:686  case AtomicExpr::AO__atomic_fetch_sub:687  case AtomicExpr::AO__scoped_atomic_fetch_sub:688    Op = E->getValueType()->isFloatingType() ? llvm::AtomicRMWInst::FSub689                                             : llvm::AtomicRMWInst::Sub;690    break;691 692  case AtomicExpr::AO__atomic_min_fetch:693  case AtomicExpr::AO__scoped_atomic_min_fetch:694    PostOpMinMax = true;695    [[fallthrough]];696  case AtomicExpr::AO__c11_atomic_fetch_min:697  case AtomicExpr::AO__hip_atomic_fetch_min:698  case AtomicExpr::AO__opencl_atomic_fetch_min:699  case AtomicExpr::AO__atomic_fetch_min:700  case AtomicExpr::AO__scoped_atomic_fetch_min:701    Op = E->getValueType()->isFloatingType()702             ? llvm::AtomicRMWInst::FMin703             : (E->getValueType()->isSignedIntegerType()704                    ? llvm::AtomicRMWInst::Min705                    : llvm::AtomicRMWInst::UMin);706    break;707 708  case AtomicExpr::AO__atomic_max_fetch:709  case AtomicExpr::AO__scoped_atomic_max_fetch:710    PostOpMinMax = true;711    [[fallthrough]];712  case AtomicExpr::AO__c11_atomic_fetch_max:713  case AtomicExpr::AO__hip_atomic_fetch_max:714  case AtomicExpr::AO__opencl_atomic_fetch_max:715  case AtomicExpr::AO__atomic_fetch_max:716  case AtomicExpr::AO__scoped_atomic_fetch_max:717    Op = E->getValueType()->isFloatingType()718             ? llvm::AtomicRMWInst::FMax719             : (E->getValueType()->isSignedIntegerType()720                    ? llvm::AtomicRMWInst::Max721                    : llvm::AtomicRMWInst::UMax);722    break;723 724  case AtomicExpr::AO__atomic_and_fetch:725  case AtomicExpr::AO__scoped_atomic_and_fetch:726    PostOp = llvm::Instruction::And;727    [[fallthrough]];728  case AtomicExpr::AO__c11_atomic_fetch_and:729  case AtomicExpr::AO__hip_atomic_fetch_and:730  case AtomicExpr::AO__opencl_atomic_fetch_and:731  case AtomicExpr::AO__atomic_fetch_and:732  case AtomicExpr::AO__scoped_atomic_fetch_and:733    Op = llvm::AtomicRMWInst::And;734    break;735 736  case AtomicExpr::AO__atomic_or_fetch:737  case AtomicExpr::AO__scoped_atomic_or_fetch:738    PostOp = llvm::Instruction::Or;739    [[fallthrough]];740  case AtomicExpr::AO__c11_atomic_fetch_or:741  case AtomicExpr::AO__hip_atomic_fetch_or:742  case AtomicExpr::AO__opencl_atomic_fetch_or:743  case AtomicExpr::AO__atomic_fetch_or:744  case AtomicExpr::AO__scoped_atomic_fetch_or:745    Op = llvm::AtomicRMWInst::Or;746    break;747 748  case AtomicExpr::AO__atomic_xor_fetch:749  case AtomicExpr::AO__scoped_atomic_xor_fetch:750    PostOp = llvm::Instruction::Xor;751    [[fallthrough]];752  case AtomicExpr::AO__c11_atomic_fetch_xor:753  case AtomicExpr::AO__hip_atomic_fetch_xor:754  case AtomicExpr::AO__opencl_atomic_fetch_xor:755  case AtomicExpr::AO__atomic_fetch_xor:756  case AtomicExpr::AO__scoped_atomic_fetch_xor:757    Op = llvm::AtomicRMWInst::Xor;758    break;759 760  case AtomicExpr::AO__atomic_nand_fetch:761  case AtomicExpr::AO__scoped_atomic_nand_fetch:762    PostOp = llvm::Instruction::And; // the NOT is special cased below763    [[fallthrough]];764  case AtomicExpr::AO__c11_atomic_fetch_nand:765  case AtomicExpr::AO__atomic_fetch_nand:766  case AtomicExpr::AO__scoped_atomic_fetch_nand:767    Op = llvm::AtomicRMWInst::Nand;768    break;769 770  case AtomicExpr::AO__scoped_atomic_uinc_wrap:771    Op = llvm::AtomicRMWInst::UIncWrap;772    break;773  case AtomicExpr::AO__scoped_atomic_udec_wrap:774    Op = llvm::AtomicRMWInst::UDecWrap;775    break;776 777  case AtomicExpr::AO__atomic_test_and_set: {778    llvm::AtomicRMWInst *RMWI =779        CGF.emitAtomicRMWInst(llvm::AtomicRMWInst::Xchg, Ptr,780                              CGF.Builder.getInt8(1), Order, Scope, E);781    RMWI->setVolatile(E->isVolatile());782    llvm::Value *Result = CGF.EmitToMemory(783        CGF.Builder.CreateIsNotNull(RMWI, "tobool"), E->getType());784    auto *I = CGF.Builder.CreateStore(Result, Dest);785    CGF.addInstToCurrentSourceAtom(I, Result);786    return;787  }788 789  case AtomicExpr::AO__atomic_clear: {790    llvm::StoreInst *Store =791        CGF.Builder.CreateStore(CGF.Builder.getInt8(0), Ptr);792    Store->setAtomic(Order, Scope);793    Store->setVolatile(E->isVolatile());794    CGF.addInstToCurrentSourceAtom(Store, nullptr);795    return;796  }797  }798 799  llvm::Value *LoadVal1 = CGF.Builder.CreateLoad(Val1);800  llvm::AtomicRMWInst *RMWI =801      CGF.emitAtomicRMWInst(Op, Ptr, LoadVal1, Order, Scope, E);802  RMWI->setVolatile(E->isVolatile());803 804  // For __atomic_*_fetch operations, perform the operation again to805  // determine the value which was written.806  llvm::Value *Result = RMWI;807  if (PostOpMinMax)808    Result = EmitPostAtomicMinMax(CGF.Builder, E->getOp(),809                                  E->getValueType()->isSignedIntegerType(),810                                  RMWI, LoadVal1);811  else if (PostOp)812    Result = CGF.Builder.CreateBinOp((llvm::Instruction::BinaryOps)PostOp, RMWI,813                                     LoadVal1);814  if (E->getOp() == AtomicExpr::AO__atomic_nand_fetch ||815      E->getOp() == AtomicExpr::AO__scoped_atomic_nand_fetch)816    Result = CGF.Builder.CreateNot(Result);817  auto *I = CGF.Builder.CreateStore(Result, Dest);818  CGF.addInstToCurrentSourceAtom(I, Result);819}820 821// This function emits any expression (scalar, complex, or aggregate)822// into a temporary alloca.823static Address824EmitValToTemp(CodeGenFunction &CGF, Expr *E) {825  Address DeclPtr = CGF.CreateMemTemp(E->getType(), ".atomictmp");826  CGF.EmitAnyExprToMem(E, DeclPtr, E->getType().getQualifiers(),827                       /*Init*/ true);828  return DeclPtr;829}830 831static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *Expr, Address Dest,832                         Address Ptr, Address Val1, Address Val2,833                         Address OriginalVal1, llvm::Value *IsWeak,834                         llvm::Value *FailureOrder, uint64_t Size,835                         llvm::AtomicOrdering Order, llvm::Value *Scope) {836  auto ScopeModel = Expr->getScopeModel();837 838  // LLVM atomic instructions always have sync scope. If clang atomic839  // expression has no scope operand, use default LLVM sync scope.840  if (!ScopeModel) {841    llvm::SyncScope::ID SS;842    if (CGF.getLangOpts().OpenCL)843      // OpenCL approach is: "The functions that do not have memory_scope844      // argument have the same semantics as the corresponding functions with845      // the memory_scope argument set to memory_scope_device." See ref.:846      // https://registry.khronos.org/OpenCL/specs/3.0-unified/html/OpenCL_C.html#atomic-functions847      SS = CGF.getTargetHooks().getLLVMSyncScopeID(CGF.getLangOpts(),848                                                   SyncScope::OpenCLDevice,849                                                   Order, CGF.getLLVMContext());850    else851      SS = llvm::SyncScope::System;852    EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak,853                 FailureOrder, Size, Order, SS);854    return;855  }856 857  // Handle constant scope.858  if (auto SC = dyn_cast<llvm::ConstantInt>(Scope)) {859    auto SCID = CGF.getTargetHooks().getLLVMSyncScopeID(860        CGF.CGM.getLangOpts(), ScopeModel->map(SC->getZExtValue()),861        Order, CGF.CGM.getLLVMContext());862    EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak,863                 FailureOrder, Size, Order, SCID);864    return;865  }866 867  // Handle non-constant scope.868  auto &Builder = CGF.Builder;869  auto Scopes = ScopeModel->getRuntimeValues();870  llvm::DenseMap<unsigned, llvm::BasicBlock *> BB;871  for (auto S : Scopes)872    BB[S] = CGF.createBasicBlock(getAsString(ScopeModel->map(S)), CGF.CurFn);873 874  llvm::BasicBlock *ContBB =875      CGF.createBasicBlock("atomic.scope.continue", CGF.CurFn);876 877  auto *SC = Builder.CreateIntCast(Scope, Builder.getInt32Ty(), false);878  // If unsupported sync scope is encountered at run time, assume a fallback879  // sync scope value.880  auto FallBack = ScopeModel->getFallBackValue();881  llvm::SwitchInst *SI = Builder.CreateSwitch(SC, BB[FallBack]);882  for (auto S : Scopes) {883    auto *B = BB[S];884    if (S != FallBack)885      SI->addCase(Builder.getInt32(S), B);886 887    Builder.SetInsertPoint(B);888    EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak,889                 FailureOrder, Size, Order,890                 CGF.getTargetHooks().getLLVMSyncScopeID(891                     CGF.CGM.getLangOpts(), ScopeModel->map(S), Order,892                     CGF.getLLVMContext()));893    Builder.CreateBr(ContBB);894  }895 896  Builder.SetInsertPoint(ContBB);897}898 899RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {900  ApplyAtomGroup Grp(getDebugInfo());901 902  QualType AtomicTy = E->getPtr()->getType()->getPointeeType();903  QualType MemTy = AtomicTy;904  if (const AtomicType *AT = AtomicTy->getAs<AtomicType>())905    MemTy = AT->getValueType();906  llvm::Value *IsWeak = nullptr, *OrderFail = nullptr;907 908  Address Val1 = Address::invalid();909  Address Val2 = Address::invalid();910  Address Dest = Address::invalid();911  Address Ptr = EmitPointerWithAlignment(E->getPtr());912 913  if (E->getOp() == AtomicExpr::AO__c11_atomic_init ||914      E->getOp() == AtomicExpr::AO__opencl_atomic_init) {915    LValue lvalue = MakeAddrLValue(Ptr, AtomicTy);916    EmitAtomicInit(E->getVal1(), lvalue);917    return RValue::get(nullptr);918  }919 920  auto TInfo = getContext().getTypeInfoInChars(AtomicTy);921  uint64_t Size = TInfo.Width.getQuantity();922  unsigned MaxInlineWidthInBits = getTarget().getMaxAtomicInlineWidth();923 924  CharUnits MaxInlineWidth =925      getContext().toCharUnitsFromBits(MaxInlineWidthInBits);926  DiagnosticsEngine &Diags = CGM.getDiags();927  bool Misaligned = !Ptr.getAlignment().isMultipleOf(TInfo.Width);928  bool Oversized = getContext().toBits(TInfo.Width) > MaxInlineWidthInBits;929  if (Misaligned) {930    Diags.Report(E->getBeginLoc(), diag::warn_atomic_op_misaligned)931        << (int)TInfo.Width.getQuantity()932        << (int)Ptr.getAlignment().getQuantity();933  }934  if (Oversized) {935    Diags.Report(E->getBeginLoc(), diag::warn_atomic_op_oversized)936        << (int)TInfo.Width.getQuantity() << (int)MaxInlineWidth.getQuantity();937  }938 939  llvm::Value *Order = EmitScalarExpr(E->getOrder());940  llvm::Value *Scope =941      E->getScopeModel() ? EmitScalarExpr(E->getScope()) : nullptr;942  bool ShouldCastToIntPtrTy = true;943 944  switch (E->getOp()) {945  case AtomicExpr::AO__c11_atomic_init:946  case AtomicExpr::AO__opencl_atomic_init:947    llvm_unreachable("Already handled above with EmitAtomicInit!");948 949  case AtomicExpr::AO__atomic_load_n:950  case AtomicExpr::AO__scoped_atomic_load_n:951  case AtomicExpr::AO__c11_atomic_load:952  case AtomicExpr::AO__opencl_atomic_load:953  case AtomicExpr::AO__hip_atomic_load:954  case AtomicExpr::AO__atomic_test_and_set:955  case AtomicExpr::AO__atomic_clear:956    break;957 958  case AtomicExpr::AO__atomic_load:959  case AtomicExpr::AO__scoped_atomic_load:960    Dest = EmitPointerWithAlignment(E->getVal1());961    break;962 963  case AtomicExpr::AO__atomic_store:964  case AtomicExpr::AO__scoped_atomic_store:965    Val1 = EmitPointerWithAlignment(E->getVal1());966    break;967 968  case AtomicExpr::AO__atomic_exchange:969  case AtomicExpr::AO__scoped_atomic_exchange:970    Val1 = EmitPointerWithAlignment(E->getVal1());971    Dest = EmitPointerWithAlignment(E->getVal2());972    break;973 974  case AtomicExpr::AO__atomic_compare_exchange:975  case AtomicExpr::AO__atomic_compare_exchange_n:976  case AtomicExpr::AO__c11_atomic_compare_exchange_weak:977  case AtomicExpr::AO__c11_atomic_compare_exchange_strong:978  case AtomicExpr::AO__hip_atomic_compare_exchange_weak:979  case AtomicExpr::AO__hip_atomic_compare_exchange_strong:980  case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:981  case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:982  case AtomicExpr::AO__scoped_atomic_compare_exchange:983  case AtomicExpr::AO__scoped_atomic_compare_exchange_n:984    Val1 = EmitPointerWithAlignment(E->getVal1());985    if (E->getOp() == AtomicExpr::AO__atomic_compare_exchange ||986        E->getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange)987      Val2 = EmitPointerWithAlignment(E->getVal2());988    else989      Val2 = EmitValToTemp(*this, E->getVal2());990    OrderFail = EmitScalarExpr(E->getOrderFail());991    if (E->getOp() == AtomicExpr::AO__atomic_compare_exchange_n ||992        E->getOp() == AtomicExpr::AO__atomic_compare_exchange ||993        E->getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange_n ||994        E->getOp() == AtomicExpr::AO__scoped_atomic_compare_exchange)995      IsWeak = EmitScalarExpr(E->getWeak());996    break;997 998  case AtomicExpr::AO__c11_atomic_fetch_add:999  case AtomicExpr::AO__c11_atomic_fetch_sub:1000  case AtomicExpr::AO__hip_atomic_fetch_add:1001  case AtomicExpr::AO__hip_atomic_fetch_sub:1002  case AtomicExpr::AO__opencl_atomic_fetch_add:1003  case AtomicExpr::AO__opencl_atomic_fetch_sub:1004    if (MemTy->isPointerType()) {1005      // For pointer arithmetic, we're required to do a bit of math:1006      // adding 1 to an int* is not the same as adding 1 to a uintptr_t.1007      // ... but only for the C11 builtins. The GNU builtins expect the1008      // user to multiply by sizeof(T).1009      QualType Val1Ty = E->getVal1()->getType();1010      llvm::Value *Val1Scalar = EmitScalarExpr(E->getVal1());1011      CharUnits PointeeIncAmt =1012          getContext().getTypeSizeInChars(MemTy->getPointeeType());1013      Val1Scalar = Builder.CreateMul(Val1Scalar, CGM.getSize(PointeeIncAmt));1014      auto Temp = CreateMemTemp(Val1Ty, ".atomictmp");1015      Val1 = Temp;1016      EmitStoreOfScalar(Val1Scalar, MakeAddrLValue(Temp, Val1Ty));1017      break;1018    }1019    [[fallthrough]];1020  case AtomicExpr::AO__atomic_fetch_add:1021  case AtomicExpr::AO__atomic_fetch_max:1022  case AtomicExpr::AO__atomic_fetch_min:1023  case AtomicExpr::AO__atomic_fetch_sub:1024  case AtomicExpr::AO__atomic_add_fetch:1025  case AtomicExpr::AO__atomic_max_fetch:1026  case AtomicExpr::AO__atomic_min_fetch:1027  case AtomicExpr::AO__atomic_sub_fetch:1028  case AtomicExpr::AO__c11_atomic_fetch_max:1029  case AtomicExpr::AO__c11_atomic_fetch_min:1030  case AtomicExpr::AO__opencl_atomic_fetch_max:1031  case AtomicExpr::AO__opencl_atomic_fetch_min:1032  case AtomicExpr::AO__hip_atomic_fetch_max:1033  case AtomicExpr::AO__hip_atomic_fetch_min:1034  case AtomicExpr::AO__scoped_atomic_fetch_add:1035  case AtomicExpr::AO__scoped_atomic_fetch_max:1036  case AtomicExpr::AO__scoped_atomic_fetch_min:1037  case AtomicExpr::AO__scoped_atomic_fetch_sub:1038  case AtomicExpr::AO__scoped_atomic_add_fetch:1039  case AtomicExpr::AO__scoped_atomic_max_fetch:1040  case AtomicExpr::AO__scoped_atomic_min_fetch:1041  case AtomicExpr::AO__scoped_atomic_sub_fetch:1042    ShouldCastToIntPtrTy = !MemTy->isFloatingType();1043    [[fallthrough]];1044 1045  case AtomicExpr::AO__atomic_fetch_and:1046  case AtomicExpr::AO__atomic_fetch_nand:1047  case AtomicExpr::AO__atomic_fetch_or:1048  case AtomicExpr::AO__atomic_fetch_xor:1049  case AtomicExpr::AO__atomic_and_fetch:1050  case AtomicExpr::AO__atomic_nand_fetch:1051  case AtomicExpr::AO__atomic_or_fetch:1052  case AtomicExpr::AO__atomic_xor_fetch:1053  case AtomicExpr::AO__atomic_store_n:1054  case AtomicExpr::AO__atomic_exchange_n:1055  case AtomicExpr::AO__c11_atomic_fetch_and:1056  case AtomicExpr::AO__c11_atomic_fetch_nand:1057  case AtomicExpr::AO__c11_atomic_fetch_or:1058  case AtomicExpr::AO__c11_atomic_fetch_xor:1059  case AtomicExpr::AO__c11_atomic_store:1060  case AtomicExpr::AO__c11_atomic_exchange:1061  case AtomicExpr::AO__hip_atomic_fetch_and:1062  case AtomicExpr::AO__hip_atomic_fetch_or:1063  case AtomicExpr::AO__hip_atomic_fetch_xor:1064  case AtomicExpr::AO__hip_atomic_store:1065  case AtomicExpr::AO__hip_atomic_exchange:1066  case AtomicExpr::AO__opencl_atomic_fetch_and:1067  case AtomicExpr::AO__opencl_atomic_fetch_or:1068  case AtomicExpr::AO__opencl_atomic_fetch_xor:1069  case AtomicExpr::AO__opencl_atomic_store:1070  case AtomicExpr::AO__opencl_atomic_exchange:1071  case AtomicExpr::AO__scoped_atomic_fetch_and:1072  case AtomicExpr::AO__scoped_atomic_fetch_nand:1073  case AtomicExpr::AO__scoped_atomic_fetch_or:1074  case AtomicExpr::AO__scoped_atomic_fetch_xor:1075  case AtomicExpr::AO__scoped_atomic_and_fetch:1076  case AtomicExpr::AO__scoped_atomic_nand_fetch:1077  case AtomicExpr::AO__scoped_atomic_or_fetch:1078  case AtomicExpr::AO__scoped_atomic_xor_fetch:1079  case AtomicExpr::AO__scoped_atomic_store_n:1080  case AtomicExpr::AO__scoped_atomic_exchange_n:1081  case AtomicExpr::AO__scoped_atomic_uinc_wrap:1082  case AtomicExpr::AO__scoped_atomic_udec_wrap:1083    Val1 = EmitValToTemp(*this, E->getVal1());1084    break;1085  }1086 1087  QualType RValTy = E->getType().getUnqualifiedType();1088 1089  // The inlined atomics only function on iN types, where N is a power of 2. We1090  // need to make sure (via temporaries if necessary) that all incoming values1091  // are compatible.1092  LValue AtomicVal = MakeAddrLValue(Ptr, AtomicTy);1093  AtomicInfo Atomics(*this, AtomicVal);1094 1095  Address OriginalVal1 = Val1;1096  if (ShouldCastToIntPtrTy) {1097    Ptr = Atomics.castToAtomicIntPointer(Ptr);1098    if (Val1.isValid())1099      Val1 = Atomics.convertToAtomicIntPointer(Val1);1100    if (Val2.isValid())1101      Val2 = Atomics.convertToAtomicIntPointer(Val2);1102  }1103  if (Dest.isValid()) {1104    if (ShouldCastToIntPtrTy)1105      Dest = Atomics.castToAtomicIntPointer(Dest);1106  } else if (E->isCmpXChg())1107    Dest = CreateMemTemp(RValTy, "cmpxchg.bool");1108  else if (!RValTy->isVoidType()) {1109    Dest = Atomics.CreateTempAlloca();1110    if (ShouldCastToIntPtrTy)1111      Dest = Atomics.castToAtomicIntPointer(Dest);1112  }1113 1114  bool PowerOf2Size = (Size & (Size - 1)) == 0;1115  bool UseLibcall = !PowerOf2Size || (Size > 16);1116 1117  // For atomics larger than 16 bytes, emit a libcall from the frontend. This1118  // avoids the overhead of dealing with excessively-large value types in IR.1119  // Non-power-of-2 values also lower to libcall here, as they are not currently1120  // permitted in IR instructions (although that constraint could be relaxed in1121  // the future). For other cases where a libcall is required on a given1122  // platform, we let the backend handle it (this includes handling for all of1123  // the size-optimized libcall variants, which are only valid up to 16 bytes.)1124  //1125  // See: https://llvm.org/docs/Atomics.html#libcalls-atomic1126  if (UseLibcall) {1127    CallArgList Args;1128    // For non-optimized library calls, the size is the first parameter.1129    Args.add(RValue::get(llvm::ConstantInt::get(SizeTy, Size)),1130             getContext().getSizeType());1131 1132    // The atomic address is the second parameter.1133    // The OpenCL atomic library functions only accept pointer arguments to1134    // generic address space.1135    auto CastToGenericAddrSpace = [&](llvm::Value *V, QualType PT) {1136      if (!E->isOpenCL())1137        return V;1138      auto AS = PT->castAs<PointerType>()->getPointeeType().getAddressSpace();1139      if (AS == LangAS::opencl_generic)1140        return V;1141      auto DestAS = getContext().getTargetAddressSpace(LangAS::opencl_generic);1142      auto *DestType = llvm::PointerType::get(getLLVMContext(), DestAS);1143 1144      return getTargetHooks().performAddrSpaceCast(*this, V, AS, DestType,1145                                                   false);1146    };1147 1148    Args.add(RValue::get(CastToGenericAddrSpace(Ptr.emitRawPointer(*this),1149                                                E->getPtr()->getType())),1150             getContext().VoidPtrTy);1151 1152    // The next 1-3 parameters are op-dependent.1153    std::string LibCallName;1154    QualType RetTy;1155    bool HaveRetTy = false;1156    switch (E->getOp()) {1157    case AtomicExpr::AO__c11_atomic_init:1158    case AtomicExpr::AO__opencl_atomic_init:1159      llvm_unreachable("Already handled!");1160 1161    // There is only one libcall for compare an exchange, because there is no1162    // optimisation benefit possible from a libcall version of a weak compare1163    // and exchange.1164    // bool __atomic_compare_exchange(size_t size, void *mem, void *expected,1165    //                                void *desired, int success, int failure)1166    case AtomicExpr::AO__atomic_compare_exchange:1167    case AtomicExpr::AO__atomic_compare_exchange_n:1168    case AtomicExpr::AO__c11_atomic_compare_exchange_weak:1169    case AtomicExpr::AO__c11_atomic_compare_exchange_strong:1170    case AtomicExpr::AO__hip_atomic_compare_exchange_weak:1171    case AtomicExpr::AO__hip_atomic_compare_exchange_strong:1172    case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:1173    case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:1174    case AtomicExpr::AO__scoped_atomic_compare_exchange:1175    case AtomicExpr::AO__scoped_atomic_compare_exchange_n:1176      LibCallName = "__atomic_compare_exchange";1177      RetTy = getContext().BoolTy;1178      HaveRetTy = true;1179      Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this),1180                                                  E->getVal1()->getType())),1181               getContext().VoidPtrTy);1182      Args.add(RValue::get(CastToGenericAddrSpace(Val2.emitRawPointer(*this),1183                                                  E->getVal2()->getType())),1184               getContext().VoidPtrTy);1185      Args.add(RValue::get(Order), getContext().IntTy);1186      Order = OrderFail;1187      break;1188    // void __atomic_exchange(size_t size, void *mem, void *val, void *return,1189    //                        int order)1190    case AtomicExpr::AO__atomic_exchange:1191    case AtomicExpr::AO__atomic_exchange_n:1192    case AtomicExpr::AO__c11_atomic_exchange:1193    case AtomicExpr::AO__hip_atomic_exchange:1194    case AtomicExpr::AO__opencl_atomic_exchange:1195    case AtomicExpr::AO__scoped_atomic_exchange:1196    case AtomicExpr::AO__scoped_atomic_exchange_n:1197      LibCallName = "__atomic_exchange";1198      Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this),1199                                                  E->getVal1()->getType())),1200               getContext().VoidPtrTy);1201      break;1202    // void __atomic_store(size_t size, void *mem, void *val, int order)1203    case AtomicExpr::AO__atomic_store:1204    case AtomicExpr::AO__atomic_store_n:1205    case AtomicExpr::AO__c11_atomic_store:1206    case AtomicExpr::AO__hip_atomic_store:1207    case AtomicExpr::AO__opencl_atomic_store:1208    case AtomicExpr::AO__scoped_atomic_store:1209    case AtomicExpr::AO__scoped_atomic_store_n:1210      LibCallName = "__atomic_store";1211      RetTy = getContext().VoidTy;1212      HaveRetTy = true;1213      Args.add(RValue::get(CastToGenericAddrSpace(Val1.emitRawPointer(*this),1214                                                  E->getVal1()->getType())),1215               getContext().VoidPtrTy);1216      break;1217    // void __atomic_load(size_t size, void *mem, void *return, int order)1218    case AtomicExpr::AO__atomic_load:1219    case AtomicExpr::AO__atomic_load_n:1220    case AtomicExpr::AO__c11_atomic_load:1221    case AtomicExpr::AO__hip_atomic_load:1222    case AtomicExpr::AO__opencl_atomic_load:1223    case AtomicExpr::AO__scoped_atomic_load:1224    case AtomicExpr::AO__scoped_atomic_load_n:1225      LibCallName = "__atomic_load";1226      break;1227    case AtomicExpr::AO__atomic_add_fetch:1228    case AtomicExpr::AO__scoped_atomic_add_fetch:1229    case AtomicExpr::AO__atomic_fetch_add:1230    case AtomicExpr::AO__c11_atomic_fetch_add:1231    case AtomicExpr::AO__hip_atomic_fetch_add:1232    case AtomicExpr::AO__opencl_atomic_fetch_add:1233    case AtomicExpr::AO__scoped_atomic_fetch_add:1234    case AtomicExpr::AO__atomic_and_fetch:1235    case AtomicExpr::AO__scoped_atomic_and_fetch:1236    case AtomicExpr::AO__atomic_fetch_and:1237    case AtomicExpr::AO__c11_atomic_fetch_and:1238    case AtomicExpr::AO__hip_atomic_fetch_and:1239    case AtomicExpr::AO__opencl_atomic_fetch_and:1240    case AtomicExpr::AO__scoped_atomic_fetch_and:1241    case AtomicExpr::AO__atomic_or_fetch:1242    case AtomicExpr::AO__scoped_atomic_or_fetch:1243    case AtomicExpr::AO__atomic_fetch_or:1244    case AtomicExpr::AO__c11_atomic_fetch_or:1245    case AtomicExpr::AO__hip_atomic_fetch_or:1246    case AtomicExpr::AO__opencl_atomic_fetch_or:1247    case AtomicExpr::AO__scoped_atomic_fetch_or:1248    case AtomicExpr::AO__atomic_sub_fetch:1249    case AtomicExpr::AO__scoped_atomic_sub_fetch:1250    case AtomicExpr::AO__atomic_fetch_sub:1251    case AtomicExpr::AO__c11_atomic_fetch_sub:1252    case AtomicExpr::AO__hip_atomic_fetch_sub:1253    case AtomicExpr::AO__opencl_atomic_fetch_sub:1254    case AtomicExpr::AO__scoped_atomic_fetch_sub:1255    case AtomicExpr::AO__atomic_xor_fetch:1256    case AtomicExpr::AO__scoped_atomic_xor_fetch:1257    case AtomicExpr::AO__atomic_fetch_xor:1258    case AtomicExpr::AO__c11_atomic_fetch_xor:1259    case AtomicExpr::AO__hip_atomic_fetch_xor:1260    case AtomicExpr::AO__opencl_atomic_fetch_xor:1261    case AtomicExpr::AO__scoped_atomic_fetch_xor:1262    case AtomicExpr::AO__atomic_nand_fetch:1263    case AtomicExpr::AO__atomic_fetch_nand:1264    case AtomicExpr::AO__c11_atomic_fetch_nand:1265    case AtomicExpr::AO__scoped_atomic_fetch_nand:1266    case AtomicExpr::AO__scoped_atomic_nand_fetch:1267    case AtomicExpr::AO__atomic_min_fetch:1268    case AtomicExpr::AO__atomic_fetch_min:1269    case AtomicExpr::AO__c11_atomic_fetch_min:1270    case AtomicExpr::AO__hip_atomic_fetch_min:1271    case AtomicExpr::AO__opencl_atomic_fetch_min:1272    case AtomicExpr::AO__scoped_atomic_fetch_min:1273    case AtomicExpr::AO__scoped_atomic_min_fetch:1274    case AtomicExpr::AO__atomic_max_fetch:1275    case AtomicExpr::AO__atomic_fetch_max:1276    case AtomicExpr::AO__c11_atomic_fetch_max:1277    case AtomicExpr::AO__hip_atomic_fetch_max:1278    case AtomicExpr::AO__opencl_atomic_fetch_max:1279    case AtomicExpr::AO__scoped_atomic_fetch_max:1280    case AtomicExpr::AO__scoped_atomic_max_fetch:1281    case AtomicExpr::AO__scoped_atomic_uinc_wrap:1282    case AtomicExpr::AO__scoped_atomic_udec_wrap:1283    case AtomicExpr::AO__atomic_test_and_set:1284    case AtomicExpr::AO__atomic_clear:1285      llvm_unreachable("Integral atomic operations always become atomicrmw!");1286    }1287 1288    if (E->isOpenCL()) {1289      LibCallName =1290          std::string("__opencl") + StringRef(LibCallName).drop_front(1).str();1291    }1292    // By default, assume we return a value of the atomic type.1293    if (!HaveRetTy) {1294      // Value is returned through parameter before the order.1295      RetTy = getContext().VoidTy;1296      Args.add(RValue::get(1297                   CastToGenericAddrSpace(Dest.emitRawPointer(*this), RetTy)),1298               getContext().VoidPtrTy);1299    }1300    // Order is always the last parameter.1301    Args.add(RValue::get(Order),1302             getContext().IntTy);1303    if (E->isOpenCL())1304      Args.add(RValue::get(Scope), getContext().IntTy);1305 1306    RValue Res = emitAtomicLibcall(*this, LibCallName, RetTy, Args);1307    // The value is returned directly from the libcall.1308    if (E->isCmpXChg())1309      return Res;1310 1311    if (RValTy->isVoidType())1312      return RValue::get(nullptr);1313 1314    return convertTempToRValue(Dest.withElementType(ConvertTypeForMem(RValTy)),1315                               RValTy, E->getExprLoc());1316  }1317 1318  bool IsStore = E->getOp() == AtomicExpr::AO__c11_atomic_store ||1319                 E->getOp() == AtomicExpr::AO__opencl_atomic_store ||1320                 E->getOp() == AtomicExpr::AO__hip_atomic_store ||1321                 E->getOp() == AtomicExpr::AO__atomic_store ||1322                 E->getOp() == AtomicExpr::AO__atomic_store_n ||1323                 E->getOp() == AtomicExpr::AO__scoped_atomic_store ||1324                 E->getOp() == AtomicExpr::AO__scoped_atomic_store_n ||1325                 E->getOp() == AtomicExpr::AO__atomic_clear;1326  bool IsLoad = E->getOp() == AtomicExpr::AO__c11_atomic_load ||1327                E->getOp() == AtomicExpr::AO__opencl_atomic_load ||1328                E->getOp() == AtomicExpr::AO__hip_atomic_load ||1329                E->getOp() == AtomicExpr::AO__atomic_load ||1330                E->getOp() == AtomicExpr::AO__atomic_load_n ||1331                E->getOp() == AtomicExpr::AO__scoped_atomic_load ||1332                E->getOp() == AtomicExpr::AO__scoped_atomic_load_n;1333 1334  if (isa<llvm::ConstantInt>(Order)) {1335    auto ord = cast<llvm::ConstantInt>(Order)->getZExtValue();1336    // We should not ever get to a case where the ordering isn't a valid C ABI1337    // value, but it's hard to enforce that in general.1338    if (llvm::isValidAtomicOrderingCABI(ord))1339      switch ((llvm::AtomicOrderingCABI)ord) {1340      case llvm::AtomicOrderingCABI::relaxed:1341        EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak,1342                     OrderFail, Size, llvm::AtomicOrdering::Monotonic, Scope);1343        break;1344      case llvm::AtomicOrderingCABI::consume:1345      case llvm::AtomicOrderingCABI::acquire:1346        if (IsStore)1347          break; // Avoid crashing on code with undefined behavior1348        EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak,1349                     OrderFail, Size, llvm::AtomicOrdering::Acquire, Scope);1350        break;1351      case llvm::AtomicOrderingCABI::release:1352        if (IsLoad)1353          break; // Avoid crashing on code with undefined behavior1354        EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak,1355                     OrderFail, Size, llvm::AtomicOrdering::Release, Scope);1356        break;1357      case llvm::AtomicOrderingCABI::acq_rel:1358        if (IsLoad || IsStore)1359          break; // Avoid crashing on code with undefined behavior1360        EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak,1361                     OrderFail, Size, llvm::AtomicOrdering::AcquireRelease,1362                     Scope);1363        break;1364      case llvm::AtomicOrderingCABI::seq_cst:1365        EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak,1366                     OrderFail, Size,1367                     llvm::AtomicOrdering::SequentiallyConsistent, Scope);1368        break;1369      }1370    if (RValTy->isVoidType())1371      return RValue::get(nullptr);1372 1373    return convertTempToRValue(Dest.withElementType(ConvertTypeForMem(RValTy)),1374                               RValTy, E->getExprLoc());1375  }1376 1377  // Long case, when Order isn't obviously constant.1378 1379  // Create all the relevant BB's1380  llvm::BasicBlock *MonotonicBB = nullptr, *AcquireBB = nullptr,1381                   *ReleaseBB = nullptr, *AcqRelBB = nullptr,1382                   *SeqCstBB = nullptr;1383  MonotonicBB = createBasicBlock("monotonic", CurFn);1384  if (!IsStore)1385    AcquireBB = createBasicBlock("acquire", CurFn);1386  if (!IsLoad)1387    ReleaseBB = createBasicBlock("release", CurFn);1388  if (!IsLoad && !IsStore)1389    AcqRelBB = createBasicBlock("acqrel", CurFn);1390  SeqCstBB = createBasicBlock("seqcst", CurFn);1391  llvm::BasicBlock *ContBB = createBasicBlock("atomic.continue", CurFn);1392 1393  // Create the switch for the split1394  // MonotonicBB is arbitrarily chosen as the default case; in practice, this1395  // doesn't matter unless someone is crazy enough to use something that1396  // doesn't fold to a constant for the ordering.1397  Order = Builder.CreateIntCast(Order, Builder.getInt32Ty(), false);1398  llvm::SwitchInst *SI = Builder.CreateSwitch(Order, MonotonicBB);1399 1400  // Emit all the different atomics1401  Builder.SetInsertPoint(MonotonicBB);1402  EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak, OrderFail,1403               Size, llvm::AtomicOrdering::Monotonic, Scope);1404  Builder.CreateBr(ContBB);1405  if (!IsStore) {1406    Builder.SetInsertPoint(AcquireBB);1407    EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak,1408                 OrderFail, Size, llvm::AtomicOrdering::Acquire, Scope);1409    Builder.CreateBr(ContBB);1410    SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::consume),1411                AcquireBB);1412    SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::acquire),1413                AcquireBB);1414  }1415  if (!IsLoad) {1416    Builder.SetInsertPoint(ReleaseBB);1417    EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak,1418                 OrderFail, Size, llvm::AtomicOrdering::Release, Scope);1419    Builder.CreateBr(ContBB);1420    SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::release),1421                ReleaseBB);1422  }1423  if (!IsLoad && !IsStore) {1424    Builder.SetInsertPoint(AcqRelBB);1425    EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak,1426                 OrderFail, Size, llvm::AtomicOrdering::AcquireRelease, Scope);1427    Builder.CreateBr(ContBB);1428    SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::acq_rel),1429                AcqRelBB);1430  }1431  Builder.SetInsertPoint(SeqCstBB);1432  EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, OriginalVal1, IsWeak, OrderFail,1433               Size, llvm::AtomicOrdering::SequentiallyConsistent, Scope);1434  Builder.CreateBr(ContBB);1435  SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::seq_cst),1436              SeqCstBB);1437 1438  // Cleanup and return1439  Builder.SetInsertPoint(ContBB);1440  if (RValTy->isVoidType())1441    return RValue::get(nullptr);1442 1443  assert(Atomics.getValueSizeInBits() <= Atomics.getAtomicSizeInBits());1444  return convertTempToRValue(Dest.withElementType(ConvertTypeForMem(RValTy)),1445                             RValTy, E->getExprLoc());1446}1447 1448Address AtomicInfo::castToAtomicIntPointer(Address addr) const {1449  llvm::IntegerType *ty =1450    llvm::IntegerType::get(CGF.getLLVMContext(), AtomicSizeInBits);1451  return addr.withElementType(ty);1452}1453 1454Address AtomicInfo::convertToAtomicIntPointer(Address Addr) const {1455  llvm::Type *Ty = Addr.getElementType();1456  uint64_t SourceSizeInBits = CGF.CGM.getDataLayout().getTypeSizeInBits(Ty);1457  if (SourceSizeInBits != AtomicSizeInBits) {1458    Address Tmp = CreateTempAlloca();1459    CGF.Builder.CreateMemSet(1460        Tmp.emitRawPointer(CGF), llvm::ConstantInt::get(CGF.Int8Ty, 0),1461        CGF.getContext().toCharUnitsFromBits(AtomicSizeInBits).getQuantity(),1462        Tmp.getAlignment().getAsAlign());1463 1464    CGF.Builder.CreateMemCpy(Tmp, Addr,1465                             std::min(AtomicSizeInBits, SourceSizeInBits) / 8);1466    Addr = Tmp;1467  }1468 1469  return castToAtomicIntPointer(Addr);1470}1471 1472RValue AtomicInfo::convertAtomicTempToRValue(Address addr,1473                                             AggValueSlot resultSlot,1474                                             SourceLocation loc,1475                                             bool asValue) const {1476  if (LVal.isSimple()) {1477    if (EvaluationKind == TEK_Aggregate)1478      return resultSlot.asRValue();1479 1480    // Drill into the padding structure if we have one.1481    if (hasPadding())1482      addr = CGF.Builder.CreateStructGEP(addr, 0);1483 1484    // Otherwise, just convert the temporary to an r-value using the1485    // normal conversion routine.1486    return CGF.convertTempToRValue(addr, getValueType(), loc);1487  }1488  if (!asValue)1489    // Get RValue from temp memory as atomic for non-simple lvalues1490    return RValue::get(CGF.Builder.CreateLoad(addr));1491  if (LVal.isBitField())1492    return CGF.EmitLoadOfBitfieldLValue(1493        LValue::MakeBitfield(addr, LVal.getBitFieldInfo(), LVal.getType(),1494                             LVal.getBaseInfo(), TBAAAccessInfo()), loc);1495  if (LVal.isVectorElt())1496    return CGF.EmitLoadOfLValue(1497        LValue::MakeVectorElt(addr, LVal.getVectorIdx(), LVal.getType(),1498                              LVal.getBaseInfo(), TBAAAccessInfo()), loc);1499  assert(LVal.isExtVectorElt());1500  return CGF.EmitLoadOfExtVectorElementLValue(LValue::MakeExtVectorElt(1501      addr, LVal.getExtVectorElts(), LVal.getType(),1502      LVal.getBaseInfo(), TBAAAccessInfo()));1503}1504 1505/// Return true if \param ValTy is a type that should be casted to integer1506/// around the atomic memory operation. If \param CmpXchg is true, then the1507/// cast of a floating point type is made as that instruction can not have1508/// floating point operands.  TODO: Allow compare-and-exchange and FP - see1509/// comment in AtomicExpandPass.cpp.1510static bool shouldCastToInt(llvm::Type *ValTy, bool CmpXchg) {1511  if (ValTy->isFloatingPointTy())1512    return ValTy->isX86_FP80Ty() || CmpXchg;1513  return !ValTy->isIntegerTy() && !ValTy->isPointerTy();1514}1515 1516RValue AtomicInfo::ConvertToValueOrAtomic(llvm::Value *Val,1517                                          AggValueSlot ResultSlot,1518                                          SourceLocation Loc, bool AsValue,1519                                          bool CmpXchg) const {1520  // Try not to in some easy cases.1521  assert((Val->getType()->isIntegerTy() || Val->getType()->isPointerTy() ||1522          Val->getType()->isIEEELikeFPTy()) &&1523         "Expected integer, pointer or floating point value when converting "1524         "result.");1525  if (getEvaluationKind() == TEK_Scalar &&1526      (((!LVal.isBitField() ||1527         LVal.getBitFieldInfo().Size == ValueSizeInBits) &&1528        !hasPadding()) ||1529       !AsValue)) {1530    auto *ValTy = AsValue1531                      ? CGF.ConvertTypeForMem(ValueTy)1532                      : getAtomicAddress().getElementType();1533    if (!shouldCastToInt(ValTy, CmpXchg)) {1534      assert((!ValTy->isIntegerTy() || Val->getType() == ValTy) &&1535             "Different integer types.");1536      return RValue::get(CGF.EmitFromMemory(Val, ValueTy));1537    }1538    if (llvm::CastInst::isBitCastable(Val->getType(), ValTy))1539      return RValue::get(CGF.Builder.CreateBitCast(Val, ValTy));1540  }1541 1542  // Create a temporary.  This needs to be big enough to hold the1543  // atomic integer.1544  Address Temp = Address::invalid();1545  bool TempIsVolatile = false;1546  if (AsValue && getEvaluationKind() == TEK_Aggregate) {1547    assert(!ResultSlot.isIgnored());1548    Temp = ResultSlot.getAddress();1549    TempIsVolatile = ResultSlot.isVolatile();1550  } else {1551    Temp = CreateTempAlloca();1552  }1553 1554  // Slam the integer into the temporary.1555  Address CastTemp = castToAtomicIntPointer(Temp);1556  CGF.Builder.CreateStore(Val, CastTemp)->setVolatile(TempIsVolatile);1557 1558  return convertAtomicTempToRValue(Temp, ResultSlot, Loc, AsValue);1559}1560 1561void AtomicInfo::EmitAtomicLoadLibcall(llvm::Value *AddForLoaded,1562                                       llvm::AtomicOrdering AO, bool) {1563  // void __atomic_load(size_t size, void *mem, void *return, int order);1564  CallArgList Args;1565  Args.add(RValue::get(getAtomicSizeValue()), CGF.getContext().getSizeType());1566  Args.add(RValue::get(getAtomicPointer()), CGF.getContext().VoidPtrTy);1567  Args.add(RValue::get(AddForLoaded), CGF.getContext().VoidPtrTy);1568  Args.add(1569      RValue::get(llvm::ConstantInt::get(CGF.IntTy, (int)llvm::toCABI(AO))),1570      CGF.getContext().IntTy);1571  emitAtomicLibcall(CGF, "__atomic_load", CGF.getContext().VoidTy, Args);1572}1573 1574llvm::Value *AtomicInfo::EmitAtomicLoadOp(llvm::AtomicOrdering AO,1575                                          bool IsVolatile, bool CmpXchg) {1576  // Okay, we're doing this natively.1577  Address Addr = getAtomicAddress();1578  if (shouldCastToInt(Addr.getElementType(), CmpXchg))1579    Addr = castToAtomicIntPointer(Addr);1580  llvm::LoadInst *Load = CGF.Builder.CreateLoad(Addr, "atomic-load");1581  Load->setAtomic(AO);1582 1583  // Other decoration.1584  if (IsVolatile)1585    Load->setVolatile(true);1586  CGF.CGM.DecorateInstructionWithTBAA(Load, LVal.getTBAAInfo());1587  return Load;1588}1589 1590/// An LValue is a candidate for having its loads and stores be made atomic if1591/// we are operating under /volatile:ms *and* the LValue itself is volatile and1592/// performing such an operation can be performed without a libcall.1593bool CodeGenFunction::LValueIsSuitableForInlineAtomic(LValue LV) {1594  if (!CGM.getLangOpts().MSVolatile) return false;1595  AtomicInfo AI(*this, LV);1596  bool IsVolatile = LV.isVolatile() || hasVolatileMember(LV.getType());1597  // An atomic is inline if we don't need to use a libcall.1598  bool AtomicIsInline = !AI.shouldUseLibcall();1599  // MSVC doesn't seem to do this for types wider than a pointer.1600  if (getContext().getTypeSize(LV.getType()) >1601      getContext().getTypeSize(getContext().getIntPtrType()))1602    return false;1603  return IsVolatile && AtomicIsInline;1604}1605 1606RValue CodeGenFunction::EmitAtomicLoad(LValue LV, SourceLocation SL,1607                                       AggValueSlot Slot) {1608  llvm::AtomicOrdering AO;1609  bool IsVolatile = LV.isVolatileQualified();1610  if (LV.getType()->isAtomicType()) {1611    AO = llvm::AtomicOrdering::SequentiallyConsistent;1612  } else {1613    AO = llvm::AtomicOrdering::Acquire;1614    IsVolatile = true;1615  }1616  return EmitAtomicLoad(LV, SL, AO, IsVolatile, Slot);1617}1618 1619RValue AtomicInfo::EmitAtomicLoad(AggValueSlot ResultSlot, SourceLocation Loc,1620                                  bool AsValue, llvm::AtomicOrdering AO,1621                                  bool IsVolatile) {1622  // Check whether we should use a library call.1623  if (shouldUseLibcall()) {1624    Address TempAddr = Address::invalid();1625    if (LVal.isSimple() && !ResultSlot.isIgnored()) {1626      assert(getEvaluationKind() == TEK_Aggregate);1627      TempAddr = ResultSlot.getAddress();1628    } else1629      TempAddr = CreateTempAlloca();1630 1631    EmitAtomicLoadLibcall(TempAddr.emitRawPointer(CGF), AO, IsVolatile);1632 1633    // Okay, turn that back into the original value or whole atomic (for1634    // non-simple lvalues) type.1635    return convertAtomicTempToRValue(TempAddr, ResultSlot, Loc, AsValue);1636  }1637 1638  // Okay, we're doing this natively.1639  auto *Load = EmitAtomicLoadOp(AO, IsVolatile);1640 1641  // If we're ignoring an aggregate return, don't do anything.1642  if (getEvaluationKind() == TEK_Aggregate && ResultSlot.isIgnored())1643    return RValue::getAggregate(Address::invalid(), false);1644 1645  // Okay, turn that back into the original value or atomic (for non-simple1646  // lvalues) type.1647  return ConvertToValueOrAtomic(Load, ResultSlot, Loc, AsValue);1648}1649 1650/// Emit a load from an l-value of atomic type.  Note that the r-value1651/// we produce is an r-value of the atomic *value* type.1652RValue CodeGenFunction::EmitAtomicLoad(LValue src, SourceLocation loc,1653                                       llvm::AtomicOrdering AO, bool IsVolatile,1654                                       AggValueSlot resultSlot) {1655  AtomicInfo Atomics(*this, src);1656  return Atomics.EmitAtomicLoad(resultSlot, loc, /*AsValue=*/true, AO,1657                                IsVolatile);1658}1659 1660/// Copy an r-value into memory as part of storing to an atomic type.1661/// This needs to create a bit-pattern suitable for atomic operations.1662void AtomicInfo::emitCopyIntoMemory(RValue rvalue) const {1663  assert(LVal.isSimple());1664  // If we have an r-value, the rvalue should be of the atomic type,1665  // which means that the caller is responsible for having zeroed1666  // any padding.  Just do an aggregate copy of that type.1667  if (rvalue.isAggregate()) {1668    LValue Dest = CGF.MakeAddrLValue(getAtomicAddress(), getAtomicType());1669    LValue Src = CGF.MakeAddrLValue(rvalue.getAggregateAddress(),1670                                    getAtomicType());1671    bool IsVolatile = rvalue.isVolatileQualified() ||1672                      LVal.isVolatileQualified();1673    CGF.EmitAggregateCopy(Dest, Src, getAtomicType(),1674                          AggValueSlot::DoesNotOverlap, IsVolatile);1675    return;1676  }1677 1678  // Okay, otherwise we're copying stuff.1679 1680  // Zero out the buffer if necessary.1681  emitMemSetZeroIfNecessary();1682 1683  // Drill past the padding if present.1684  LValue TempLVal = projectValue();1685 1686  // Okay, store the rvalue in.1687  if (rvalue.isScalar()) {1688    CGF.EmitStoreOfScalar(rvalue.getScalarVal(), TempLVal, /*init*/ true);1689  } else {1690    CGF.EmitStoreOfComplex(rvalue.getComplexVal(), TempLVal, /*init*/ true);1691  }1692}1693 1694 1695/// Materialize an r-value into memory for the purposes of storing it1696/// to an atomic type.1697Address AtomicInfo::materializeRValue(RValue rvalue) const {1698  // Aggregate r-values are already in memory, and EmitAtomicStore1699  // requires them to be values of the atomic type.1700  if (rvalue.isAggregate())1701    return rvalue.getAggregateAddress();1702 1703  // Otherwise, make a temporary and materialize into it.1704  LValue TempLV = CGF.MakeAddrLValue(CreateTempAlloca(), getAtomicType());1705  AtomicInfo Atomics(CGF, TempLV);1706  Atomics.emitCopyIntoMemory(rvalue);1707  return TempLV.getAddress();1708}1709 1710llvm::Value *AtomicInfo::getScalarRValValueOrNull(RValue RVal) const {1711  if (RVal.isScalar() && (!hasPadding() || !LVal.isSimple()))1712    return RVal.getScalarVal();1713  return nullptr;1714}1715 1716llvm::Value *AtomicInfo::convertRValueToInt(RValue RVal, bool CmpXchg) const {1717  // If we've got a scalar value of the right size, try to avoid going1718  // through memory. Floats get casted if needed by AtomicExpandPass.1719  if (llvm::Value *Value = getScalarRValValueOrNull(RVal)) {1720    if (!shouldCastToInt(Value->getType(), CmpXchg))1721      return CGF.EmitToMemory(Value, ValueTy);1722    else {1723      llvm::IntegerType *InputIntTy = llvm::IntegerType::get(1724          CGF.getLLVMContext(),1725          LVal.isSimple() ? getValueSizeInBits() : getAtomicSizeInBits());1726      if (llvm::BitCastInst::isBitCastable(Value->getType(), InputIntTy))1727        return CGF.Builder.CreateBitCast(Value, InputIntTy);1728    }1729  }1730  // Otherwise, we need to go through memory.1731  // Put the r-value in memory.1732  Address Addr = materializeRValue(RVal);1733 1734  // Cast the temporary to the atomic int type and pull a value out.1735  Addr = castToAtomicIntPointer(Addr);1736  return CGF.Builder.CreateLoad(Addr);1737}1738 1739std::pair<llvm::Value *, llvm::Value *> AtomicInfo::EmitAtomicCompareExchangeOp(1740    llvm::Value *ExpectedVal, llvm::Value *DesiredVal,1741    llvm::AtomicOrdering Success, llvm::AtomicOrdering Failure, bool IsWeak) {1742  // Do the atomic store.1743  Address Addr = getAtomicAddressAsAtomicIntPointer();1744  auto *Inst = CGF.Builder.CreateAtomicCmpXchg(Addr, ExpectedVal, DesiredVal,1745                                               Success, Failure);1746  // Other decoration.1747  Inst->setVolatile(LVal.isVolatileQualified());1748  Inst->setWeak(IsWeak);1749 1750  // Okay, turn that back into the original value type.1751  auto *PreviousVal = CGF.Builder.CreateExtractValue(Inst, /*Idxs=*/0);1752  auto *SuccessFailureVal = CGF.Builder.CreateExtractValue(Inst, /*Idxs=*/1);1753  return std::make_pair(PreviousVal, SuccessFailureVal);1754}1755 1756llvm::Value *1757AtomicInfo::EmitAtomicCompareExchangeLibcall(llvm::Value *ExpectedAddr,1758                                             llvm::Value *DesiredAddr,1759                                             llvm::AtomicOrdering Success,1760                                             llvm::AtomicOrdering Failure) {1761  // bool __atomic_compare_exchange(size_t size, void *obj, void *expected,1762  // void *desired, int success, int failure);1763  CallArgList Args;1764  Args.add(RValue::get(getAtomicSizeValue()), CGF.getContext().getSizeType());1765  Args.add(RValue::get(getAtomicPointer()), CGF.getContext().VoidPtrTy);1766  Args.add(RValue::get(ExpectedAddr), CGF.getContext().VoidPtrTy);1767  Args.add(RValue::get(DesiredAddr), CGF.getContext().VoidPtrTy);1768  Args.add(RValue::get(1769               llvm::ConstantInt::get(CGF.IntTy, (int)llvm::toCABI(Success))),1770           CGF.getContext().IntTy);1771  Args.add(RValue::get(1772               llvm::ConstantInt::get(CGF.IntTy, (int)llvm::toCABI(Failure))),1773           CGF.getContext().IntTy);1774  auto SuccessFailureRVal = emitAtomicLibcall(CGF, "__atomic_compare_exchange",1775                                              CGF.getContext().BoolTy, Args);1776 1777  return SuccessFailureRVal.getScalarVal();1778}1779 1780std::pair<RValue, llvm::Value *> AtomicInfo::EmitAtomicCompareExchange(1781    RValue Expected, RValue Desired, llvm::AtomicOrdering Success,1782    llvm::AtomicOrdering Failure, bool IsWeak) {1783  // Check whether we should use a library call.1784  if (shouldUseLibcall()) {1785    // Produce a source address.1786    Address ExpectedAddr = materializeRValue(Expected);1787    llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF);1788    llvm::Value *DesiredPtr = materializeRValue(Desired).emitRawPointer(CGF);1789    auto *Res = EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr,1790                                                 Success, Failure);1791    return std::make_pair(1792        convertAtomicTempToRValue(ExpectedAddr, AggValueSlot::ignored(),1793                                  SourceLocation(), /*AsValue=*/false),1794        Res);1795  }1796 1797  // If we've got a scalar value of the right size, try to avoid going1798  // through memory.1799  auto *ExpectedVal = convertRValueToInt(Expected, /*CmpXchg=*/true);1800  auto *DesiredVal = convertRValueToInt(Desired, /*CmpXchg=*/true);1801  auto Res = EmitAtomicCompareExchangeOp(ExpectedVal, DesiredVal, Success,1802                                         Failure, IsWeak);1803  return std::make_pair(1804      ConvertToValueOrAtomic(Res.first, AggValueSlot::ignored(),1805                             SourceLocation(), /*AsValue=*/false,1806                             /*CmpXchg=*/true),1807      Res.second);1808}1809 1810static void1811EmitAtomicUpdateValue(CodeGenFunction &CGF, AtomicInfo &Atomics, RValue OldRVal,1812                      const llvm::function_ref<RValue(RValue)> &UpdateOp,1813                      Address DesiredAddr) {1814  RValue UpRVal;1815  LValue AtomicLVal = Atomics.getAtomicLValue();1816  LValue DesiredLVal;1817  if (AtomicLVal.isSimple()) {1818    UpRVal = OldRVal;1819    DesiredLVal = CGF.MakeAddrLValue(DesiredAddr, AtomicLVal.getType());1820  } else {1821    // Build new lvalue for temp address.1822    Address Ptr = Atomics.materializeRValue(OldRVal);1823    LValue UpdateLVal;1824    if (AtomicLVal.isBitField()) {1825      UpdateLVal =1826          LValue::MakeBitfield(Ptr, AtomicLVal.getBitFieldInfo(),1827                               AtomicLVal.getType(),1828                               AtomicLVal.getBaseInfo(),1829                               AtomicLVal.getTBAAInfo());1830      DesiredLVal =1831          LValue::MakeBitfield(DesiredAddr, AtomicLVal.getBitFieldInfo(),1832                               AtomicLVal.getType(), AtomicLVal.getBaseInfo(),1833                               AtomicLVal.getTBAAInfo());1834    } else if (AtomicLVal.isVectorElt()) {1835      UpdateLVal = LValue::MakeVectorElt(Ptr, AtomicLVal.getVectorIdx(),1836                                         AtomicLVal.getType(),1837                                         AtomicLVal.getBaseInfo(),1838                                         AtomicLVal.getTBAAInfo());1839      DesiredLVal = LValue::MakeVectorElt(1840          DesiredAddr, AtomicLVal.getVectorIdx(), AtomicLVal.getType(),1841          AtomicLVal.getBaseInfo(), AtomicLVal.getTBAAInfo());1842    } else {1843      assert(AtomicLVal.isExtVectorElt());1844      UpdateLVal = LValue::MakeExtVectorElt(Ptr, AtomicLVal.getExtVectorElts(),1845                                            AtomicLVal.getType(),1846                                            AtomicLVal.getBaseInfo(),1847                                            AtomicLVal.getTBAAInfo());1848      DesiredLVal = LValue::MakeExtVectorElt(1849          DesiredAddr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(),1850          AtomicLVal.getBaseInfo(), AtomicLVal.getTBAAInfo());1851    }1852    UpRVal = CGF.EmitLoadOfLValue(UpdateLVal, SourceLocation());1853  }1854  // Store new value in the corresponding memory area.1855  RValue NewRVal = UpdateOp(UpRVal);1856  if (NewRVal.isScalar()) {1857    CGF.EmitStoreThroughLValue(NewRVal, DesiredLVal);1858  } else {1859    assert(NewRVal.isComplex());1860    CGF.EmitStoreOfComplex(NewRVal.getComplexVal(), DesiredLVal,1861                           /*isInit=*/false);1862  }1863}1864 1865void AtomicInfo::EmitAtomicUpdateLibcall(1866    llvm::AtomicOrdering AO, const llvm::function_ref<RValue(RValue)> &UpdateOp,1867    bool IsVolatile) {1868  auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO);1869 1870  Address ExpectedAddr = CreateTempAlloca();1871 1872  EmitAtomicLoadLibcall(ExpectedAddr.emitRawPointer(CGF), AO, IsVolatile);1873  auto *ContBB = CGF.createBasicBlock("atomic_cont");1874  auto *ExitBB = CGF.createBasicBlock("atomic_exit");1875  CGF.EmitBlock(ContBB);1876  Address DesiredAddr = CreateTempAlloca();1877  if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) ||1878      requiresMemSetZero(getAtomicAddress().getElementType())) {1879    auto *OldVal = CGF.Builder.CreateLoad(ExpectedAddr);1880    CGF.Builder.CreateStore(OldVal, DesiredAddr);1881  }1882  auto OldRVal = convertAtomicTempToRValue(ExpectedAddr,1883                                           AggValueSlot::ignored(),1884                                           SourceLocation(), /*AsValue=*/false);1885  EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, DesiredAddr);1886  llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF);1887  llvm::Value *DesiredPtr = DesiredAddr.emitRawPointer(CGF);1888  auto *Res =1889      EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, AO, Failure);1890  CGF.Builder.CreateCondBr(Res, ExitBB, ContBB);1891  CGF.EmitBlock(ExitBB, /*IsFinished=*/true);1892}1893 1894void AtomicInfo::EmitAtomicUpdateOp(1895    llvm::AtomicOrdering AO, const llvm::function_ref<RValue(RValue)> &UpdateOp,1896    bool IsVolatile) {1897  auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO);1898 1899  // Do the atomic load.1900  auto *OldVal = EmitAtomicLoadOp(Failure, IsVolatile, /*CmpXchg=*/true);1901  // For non-simple lvalues perform compare-and-swap procedure.1902  auto *ContBB = CGF.createBasicBlock("atomic_cont");1903  auto *ExitBB = CGF.createBasicBlock("atomic_exit");1904  auto *CurBB = CGF.Builder.GetInsertBlock();1905  CGF.EmitBlock(ContBB);1906  llvm::PHINode *PHI = CGF.Builder.CreatePHI(OldVal->getType(),1907                                             /*NumReservedValues=*/2);1908  PHI->addIncoming(OldVal, CurBB);1909  Address NewAtomicAddr = CreateTempAlloca();1910  Address NewAtomicIntAddr =1911      shouldCastToInt(NewAtomicAddr.getElementType(), /*CmpXchg=*/true)1912          ? castToAtomicIntPointer(NewAtomicAddr)1913          : NewAtomicAddr;1914 1915  if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) ||1916      requiresMemSetZero(getAtomicAddress().getElementType())) {1917    CGF.Builder.CreateStore(PHI, NewAtomicIntAddr);1918  }1919  auto OldRVal = ConvertToValueOrAtomic(PHI, AggValueSlot::ignored(),1920                                        SourceLocation(), /*AsValue=*/false,1921                                        /*CmpXchg=*/true);1922  EmitAtomicUpdateValue(CGF, *this, OldRVal, UpdateOp, NewAtomicAddr);1923  auto *DesiredVal = CGF.Builder.CreateLoad(NewAtomicIntAddr);1924  // Try to write new value using cmpxchg operation.1925  auto Res = EmitAtomicCompareExchangeOp(PHI, DesiredVal, AO, Failure);1926  PHI->addIncoming(Res.first, CGF.Builder.GetInsertBlock());1927  CGF.Builder.CreateCondBr(Res.second, ExitBB, ContBB);1928  CGF.EmitBlock(ExitBB, /*IsFinished=*/true);1929}1930 1931static void EmitAtomicUpdateValue(CodeGenFunction &CGF, AtomicInfo &Atomics,1932                                  RValue UpdateRVal, Address DesiredAddr) {1933  LValue AtomicLVal = Atomics.getAtomicLValue();1934  LValue DesiredLVal;1935  // Build new lvalue for temp address.1936  if (AtomicLVal.isBitField()) {1937    DesiredLVal =1938        LValue::MakeBitfield(DesiredAddr, AtomicLVal.getBitFieldInfo(),1939                             AtomicLVal.getType(), AtomicLVal.getBaseInfo(),1940                             AtomicLVal.getTBAAInfo());1941  } else if (AtomicLVal.isVectorElt()) {1942    DesiredLVal =1943        LValue::MakeVectorElt(DesiredAddr, AtomicLVal.getVectorIdx(),1944                              AtomicLVal.getType(), AtomicLVal.getBaseInfo(),1945                              AtomicLVal.getTBAAInfo());1946  } else {1947    assert(AtomicLVal.isExtVectorElt());1948    DesiredLVal = LValue::MakeExtVectorElt(1949        DesiredAddr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(),1950        AtomicLVal.getBaseInfo(), AtomicLVal.getTBAAInfo());1951  }1952  // Store new value in the corresponding memory area.1953  assert(UpdateRVal.isScalar());1954  CGF.EmitStoreThroughLValue(UpdateRVal, DesiredLVal);1955}1956 1957void AtomicInfo::EmitAtomicUpdateLibcall(llvm::AtomicOrdering AO,1958                                         RValue UpdateRVal, bool IsVolatile) {1959  auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO);1960 1961  Address ExpectedAddr = CreateTempAlloca();1962 1963  EmitAtomicLoadLibcall(ExpectedAddr.emitRawPointer(CGF), AO, IsVolatile);1964  auto *ContBB = CGF.createBasicBlock("atomic_cont");1965  auto *ExitBB = CGF.createBasicBlock("atomic_exit");1966  CGF.EmitBlock(ContBB);1967  Address DesiredAddr = CreateTempAlloca();1968  if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) ||1969      requiresMemSetZero(getAtomicAddress().getElementType())) {1970    auto *OldVal = CGF.Builder.CreateLoad(ExpectedAddr);1971    CGF.Builder.CreateStore(OldVal, DesiredAddr);1972  }1973  EmitAtomicUpdateValue(CGF, *this, UpdateRVal, DesiredAddr);1974  llvm::Value *ExpectedPtr = ExpectedAddr.emitRawPointer(CGF);1975  llvm::Value *DesiredPtr = DesiredAddr.emitRawPointer(CGF);1976  auto *Res =1977      EmitAtomicCompareExchangeLibcall(ExpectedPtr, DesiredPtr, AO, Failure);1978  CGF.Builder.CreateCondBr(Res, ExitBB, ContBB);1979  CGF.EmitBlock(ExitBB, /*IsFinished=*/true);1980}1981 1982void AtomicInfo::EmitAtomicUpdateOp(llvm::AtomicOrdering AO, RValue UpdateRVal,1983                                    bool IsVolatile) {1984  auto Failure = llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(AO);1985 1986  // Do the atomic load.1987  auto *OldVal = EmitAtomicLoadOp(Failure, IsVolatile, /*CmpXchg=*/true);1988  // For non-simple lvalues perform compare-and-swap procedure.1989  auto *ContBB = CGF.createBasicBlock("atomic_cont");1990  auto *ExitBB = CGF.createBasicBlock("atomic_exit");1991  auto *CurBB = CGF.Builder.GetInsertBlock();1992  CGF.EmitBlock(ContBB);1993  llvm::PHINode *PHI = CGF.Builder.CreatePHI(OldVal->getType(),1994                                             /*NumReservedValues=*/2);1995  PHI->addIncoming(OldVal, CurBB);1996  Address NewAtomicAddr = CreateTempAlloca();1997  Address NewAtomicIntAddr = castToAtomicIntPointer(NewAtomicAddr);1998  if ((LVal.isBitField() && BFI.Size != ValueSizeInBits) ||1999      requiresMemSetZero(getAtomicAddress().getElementType())) {2000    CGF.Builder.CreateStore(PHI, NewAtomicIntAddr);2001  }2002  EmitAtomicUpdateValue(CGF, *this, UpdateRVal, NewAtomicAddr);2003  auto *DesiredVal = CGF.Builder.CreateLoad(NewAtomicIntAddr);2004  // Try to write new value using cmpxchg operation.2005  auto Res = EmitAtomicCompareExchangeOp(PHI, DesiredVal, AO, Failure);2006  PHI->addIncoming(Res.first, CGF.Builder.GetInsertBlock());2007  CGF.Builder.CreateCondBr(Res.second, ExitBB, ContBB);2008  CGF.EmitBlock(ExitBB, /*IsFinished=*/true);2009}2010 2011void AtomicInfo::EmitAtomicUpdate(2012    llvm::AtomicOrdering AO, const llvm::function_ref<RValue(RValue)> &UpdateOp,2013    bool IsVolatile) {2014  if (shouldUseLibcall()) {2015    EmitAtomicUpdateLibcall(AO, UpdateOp, IsVolatile);2016  } else {2017    EmitAtomicUpdateOp(AO, UpdateOp, IsVolatile);2018  }2019}2020 2021void AtomicInfo::EmitAtomicUpdate(llvm::AtomicOrdering AO, RValue UpdateRVal,2022                                  bool IsVolatile) {2023  if (shouldUseLibcall()) {2024    EmitAtomicUpdateLibcall(AO, UpdateRVal, IsVolatile);2025  } else {2026    EmitAtomicUpdateOp(AO, UpdateRVal, IsVolatile);2027  }2028}2029 2030void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue lvalue,2031                                      bool isInit) {2032  bool IsVolatile = lvalue.isVolatileQualified();2033  llvm::AtomicOrdering AO;2034  if (lvalue.getType()->isAtomicType()) {2035    AO = llvm::AtomicOrdering::SequentiallyConsistent;2036  } else {2037    AO = llvm::AtomicOrdering::Release;2038    IsVolatile = true;2039  }2040  return EmitAtomicStore(rvalue, lvalue, AO, IsVolatile, isInit);2041}2042 2043/// Emit a store to an l-value of atomic type.2044///2045/// Note that the r-value is expected to be an r-value *of the atomic2046/// type*; this means that for aggregate r-values, it should include2047/// storage for any padding that was necessary.2048void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest,2049                                      llvm::AtomicOrdering AO, bool IsVolatile,2050                                      bool isInit) {2051  // If this is an aggregate r-value, it should agree in type except2052  // maybe for address-space qualification.2053  assert(!rvalue.isAggregate() ||2054         rvalue.getAggregateAddress().getElementType() ==2055             dest.getAddress().getElementType());2056 2057  AtomicInfo atomics(*this, dest);2058  LValue LVal = atomics.getAtomicLValue();2059 2060  // If this is an initialization, just put the value there normally.2061  if (LVal.isSimple()) {2062    if (isInit) {2063      atomics.emitCopyIntoMemory(rvalue);2064      return;2065    }2066 2067    // Check whether we should use a library call.2068    if (atomics.shouldUseLibcall()) {2069      // Produce a source address.2070      Address srcAddr = atomics.materializeRValue(rvalue);2071 2072      // void __atomic_store(size_t size, void *mem, void *val, int order)2073      CallArgList args;2074      args.add(RValue::get(atomics.getAtomicSizeValue()),2075               getContext().getSizeType());2076      args.add(RValue::get(atomics.getAtomicPointer()), getContext().VoidPtrTy);2077      args.add(RValue::get(srcAddr.emitRawPointer(*this)),2078               getContext().VoidPtrTy);2079      args.add(2080          RValue::get(llvm::ConstantInt::get(IntTy, (int)llvm::toCABI(AO))),2081          getContext().IntTy);2082      emitAtomicLibcall(*this, "__atomic_store", getContext().VoidTy, args);2083      return;2084    }2085 2086    // Okay, we're doing this natively.2087    llvm::Value *ValToStore = atomics.convertRValueToInt(rvalue);2088 2089    // Do the atomic store.2090    Address Addr = atomics.getAtomicAddress();2091    if (llvm::Value *Value = atomics.getScalarRValValueOrNull(rvalue))2092      if (shouldCastToInt(Value->getType(), /*CmpXchg=*/false)) {2093        Addr = atomics.castToAtomicIntPointer(Addr);2094        ValToStore = Builder.CreateIntCast(ValToStore, Addr.getElementType(),2095                                           /*isSigned=*/false);2096      }2097    llvm::StoreInst *store = Builder.CreateStore(ValToStore, Addr);2098 2099    if (AO == llvm::AtomicOrdering::Acquire)2100      AO = llvm::AtomicOrdering::Monotonic;2101    else if (AO == llvm::AtomicOrdering::AcquireRelease)2102      AO = llvm::AtomicOrdering::Release;2103    // Initializations don't need to be atomic.2104    if (!isInit)2105      store->setAtomic(AO);2106 2107    // Other decoration.2108    if (IsVolatile)2109      store->setVolatile(true);2110    CGM.DecorateInstructionWithTBAA(store, dest.getTBAAInfo());2111    return;2112  }2113 2114  // Emit simple atomic update operation.2115  atomics.EmitAtomicUpdate(AO, rvalue, IsVolatile);2116}2117 2118/// Emit a compare-and-exchange op for atomic type.2119///2120std::pair<RValue, llvm::Value *> CodeGenFunction::EmitAtomicCompareExchange(2121    LValue Obj, RValue Expected, RValue Desired, SourceLocation Loc,2122    llvm::AtomicOrdering Success, llvm::AtomicOrdering Failure, bool IsWeak,2123    AggValueSlot Slot) {2124  // If this is an aggregate r-value, it should agree in type except2125  // maybe for address-space qualification.2126  assert(!Expected.isAggregate() ||2127         Expected.getAggregateAddress().getElementType() ==2128             Obj.getAddress().getElementType());2129  assert(!Desired.isAggregate() ||2130         Desired.getAggregateAddress().getElementType() ==2131             Obj.getAddress().getElementType());2132  AtomicInfo Atomics(*this, Obj);2133 2134  return Atomics.EmitAtomicCompareExchange(Expected, Desired, Success, Failure,2135                                           IsWeak);2136}2137 2138llvm::AtomicRMWInst *2139CodeGenFunction::emitAtomicRMWInst(llvm::AtomicRMWInst::BinOp Op, Address Addr,2140                                   llvm::Value *Val, llvm::AtomicOrdering Order,2141                                   llvm::SyncScope::ID SSID,2142                                   const AtomicExpr *AE) {2143  llvm::AtomicRMWInst *RMW =2144      Builder.CreateAtomicRMW(Op, Addr, Val, Order, SSID);2145  getTargetHooks().setTargetAtomicMetadata(*this, *RMW, AE);2146  return RMW;2147}2148 2149void CodeGenFunction::EmitAtomicUpdate(2150    LValue LVal, llvm::AtomicOrdering AO,2151    const llvm::function_ref<RValue(RValue)> &UpdateOp, bool IsVolatile) {2152  AtomicInfo Atomics(*this, LVal);2153  Atomics.EmitAtomicUpdate(AO, UpdateOp, IsVolatile);2154}2155 2156void CodeGenFunction::EmitAtomicInit(Expr *init, LValue dest) {2157  AtomicInfo atomics(*this, dest);2158 2159  switch (atomics.getEvaluationKind()) {2160  case TEK_Scalar: {2161    llvm::Value *value = EmitScalarExpr(init);2162    atomics.emitCopyIntoMemory(RValue::get(value));2163    return;2164  }2165 2166  case TEK_Complex: {2167    ComplexPairTy value = EmitComplexExpr(init);2168    atomics.emitCopyIntoMemory(RValue::getComplex(value));2169    return;2170  }2171 2172  case TEK_Aggregate: {2173    // Fix up the destination if the initializer isn't an expression2174    // of atomic type.2175    bool Zeroed = false;2176    if (!init->getType()->isAtomicType()) {2177      Zeroed = atomics.emitMemSetZeroIfNecessary();2178      dest = atomics.projectValue();2179    }2180 2181    // Evaluate the expression directly into the destination.2182    AggValueSlot slot = AggValueSlot::forLValue(2183        dest, AggValueSlot::IsNotDestructed,2184        AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased,2185        AggValueSlot::DoesNotOverlap,2186        Zeroed ? AggValueSlot::IsZeroed : AggValueSlot::IsNotZeroed);2187 2188    EmitAggExpr(init, slot);2189    return;2190  }2191  }2192  llvm_unreachable("bad evaluation kind");2193}2194