diff options
Diffstat (limited to 'lib/CodeGen/CGAtomic.cpp')
| -rw-r--r-- | lib/CodeGen/CGAtomic.cpp | 306 | 
1 files changed, 235 insertions, 71 deletions
| diff --git a/lib/CodeGen/CGAtomic.cpp b/lib/CodeGen/CGAtomic.cpp index a6e6fec206d5..d90c3a53a635 100644 --- a/lib/CodeGen/CGAtomic.cpp +++ b/lib/CodeGen/CGAtomic.cpp @@ -15,8 +15,10 @@  #include "CGRecordLayout.h"  #include "CodeGenFunction.h"  #include "CodeGenModule.h" +#include "TargetInfo.h"  #include "clang/AST/ASTContext.h"  #include "clang/CodeGen/CGFunctionInfo.h" +#include "llvm/ADT/DenseMap.h"  #include "llvm/IR/DataLayout.h"  #include "llvm/IR/Intrinsics.h"  #include "llvm/IR/Operator.h" @@ -94,9 +96,8 @@ namespace {          BFI.StorageSize = AtomicSizeInBits;          BFI.StorageOffset += OffsetInChars;          LVal = LValue::MakeBitfield(Address(Addr, lvalue.getAlignment()), -                                    BFI, lvalue.getType(), -                                    lvalue.getBaseInfo()); -        LVal.setTBAAInfo(lvalue.getTBAAInfo()); +                                    BFI, lvalue.getType(), lvalue.getBaseInfo(), +                                    lvalue.getTBAAInfo());          AtomicTy = C.getIntTypeForBitwidth(AtomicSizeInBits, OrigBFI.IsSigned);          if (AtomicTy.isNull()) {            llvm::APInt Size( @@ -359,13 +360,15 @@ static void emitAtomicCmpXchg(CodeGenFunction &CGF, AtomicExpr *E, bool IsWeak,                                Address Val1, Address Val2,                                uint64_t Size,                                llvm::AtomicOrdering SuccessOrder, -                              llvm::AtomicOrdering FailureOrder) { +                              llvm::AtomicOrdering FailureOrder, +                              llvm::SyncScope::ID Scope) {    // Note that cmpxchg doesn't support weak cmpxchg, at least at the moment.    llvm::Value *Expected = CGF.Builder.CreateLoad(Val1);    llvm::Value *Desired = CGF.Builder.CreateLoad(Val2);    llvm::AtomicCmpXchgInst *Pair = CGF.Builder.CreateAtomicCmpXchg( -      Ptr.getPointer(), Expected, Desired, SuccessOrder, FailureOrder); +      Ptr.getPointer(), Expected, Desired, SuccessOrder, FailureOrder, +      Scope);    Pair->setVolatile(E->isVolatile());    Pair->setWeak(IsWeak); @@ -407,7 +410,8 @@ static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,                                          Address Val1, Address Val2,                                          llvm::Value *FailureOrderVal,                                          uint64_t Size, -                                        llvm::AtomicOrdering SuccessOrder) { +                                        llvm::AtomicOrdering SuccessOrder, +                                        llvm::SyncScope::ID Scope) {    llvm::AtomicOrdering FailureOrder;    if (llvm::ConstantInt *FO = dyn_cast<llvm::ConstantInt>(FailureOrderVal)) {      auto FOS = FO->getSExtValue(); @@ -435,7 +439,7 @@ static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,            llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(SuccessOrder);      }      emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, SuccessOrder, -                      FailureOrder); +                      FailureOrder, Scope);      return;    } @@ -460,13 +464,13 @@ static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,    // doesn't fold to a constant for the ordering.    CGF.Builder.SetInsertPoint(MonotonicBB);    emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, -                    Size, SuccessOrder, llvm::AtomicOrdering::Monotonic); +                    Size, SuccessOrder, llvm::AtomicOrdering::Monotonic, Scope);    CGF.Builder.CreateBr(ContBB);    if (AcquireBB) {      CGF.Builder.SetInsertPoint(AcquireBB);      emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, -                      Size, SuccessOrder, llvm::AtomicOrdering::Acquire); +                      Size, SuccessOrder, llvm::AtomicOrdering::Acquire, Scope);      CGF.Builder.CreateBr(ContBB);      SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::consume),                  AcquireBB); @@ -476,7 +480,7 @@ static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,    if (SeqCstBB) {      CGF.Builder.SetInsertPoint(SeqCstBB);      emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, SuccessOrder, -                      llvm::AtomicOrdering::SequentiallyConsistent); +                      llvm::AtomicOrdering::SequentiallyConsistent, Scope);      CGF.Builder.CreateBr(ContBB);      SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::seq_cst),                  SeqCstBB); @@ -488,27 +492,31 @@ static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E,  static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,                           Address Ptr, Address Val1, Address Val2,                           llvm::Value *IsWeak, llvm::Value *FailureOrder, -                         uint64_t Size, llvm::AtomicOrdering Order) { +                         uint64_t Size, llvm::AtomicOrdering Order, +                         llvm::SyncScope::ID Scope) {    llvm::AtomicRMWInst::BinOp Op = llvm::AtomicRMWInst::Add;    llvm::Instruction::BinaryOps PostOp = (llvm::Instruction::BinaryOps)0;    switch (E->getOp()) {    case AtomicExpr::AO__c11_atomic_init: +  case AtomicExpr::AO__opencl_atomic_init:      llvm_unreachable("Already handled!");    case AtomicExpr::AO__c11_atomic_compare_exchange_strong: +  case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:      emitAtomicCmpXchgFailureSet(CGF, E, false, Dest, Ptr, Val1, Val2, -                                FailureOrder, Size, Order); +                                FailureOrder, Size, Order, Scope);      return;    case AtomicExpr::AO__c11_atomic_compare_exchange_weak: +  case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:      emitAtomicCmpXchgFailureSet(CGF, E, true, Dest, Ptr, Val1, Val2, -                                FailureOrder, Size, Order); +                                FailureOrder, Size, Order, Scope);      return;    case AtomicExpr::AO__atomic_compare_exchange:    case AtomicExpr::AO__atomic_compare_exchange_n: {      if (llvm::ConstantInt *IsWeakC = dyn_cast<llvm::ConstantInt>(IsWeak)) {        emitAtomicCmpXchgFailureSet(CGF, E, IsWeakC->getZExtValue(), Dest, Ptr, -                                  Val1, Val2, FailureOrder, Size, Order); +                                  Val1, Val2, FailureOrder, Size, Order, Scope);      } else {        // Create all the relevant BB's        llvm::BasicBlock *StrongBB = @@ -522,12 +530,12 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,        CGF.Builder.SetInsertPoint(StrongBB);        emitAtomicCmpXchgFailureSet(CGF, E, false, Dest, Ptr, Val1, Val2, -                                  FailureOrder, Size, Order); +                                  FailureOrder, Size, Order, Scope);        CGF.Builder.CreateBr(ContBB);        CGF.Builder.SetInsertPoint(WeakBB);        emitAtomicCmpXchgFailureSet(CGF, E, true, Dest, Ptr, Val1, Val2, -                                  FailureOrder, Size, Order); +                                  FailureOrder, Size, Order, Scope);        CGF.Builder.CreateBr(ContBB);        CGF.Builder.SetInsertPoint(ContBB); @@ -535,26 +543,29 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,      return;    }    case AtomicExpr::AO__c11_atomic_load: +  case AtomicExpr::AO__opencl_atomic_load:    case AtomicExpr::AO__atomic_load_n:    case AtomicExpr::AO__atomic_load: {      llvm::LoadInst *Load = CGF.Builder.CreateLoad(Ptr); -    Load->setAtomic(Order); +    Load->setAtomic(Order, Scope);      Load->setVolatile(E->isVolatile());      CGF.Builder.CreateStore(Load, Dest);      return;    }    case AtomicExpr::AO__c11_atomic_store: +  case AtomicExpr::AO__opencl_atomic_store:    case AtomicExpr::AO__atomic_store:    case AtomicExpr::AO__atomic_store_n: {      llvm::Value *LoadVal1 = CGF.Builder.CreateLoad(Val1);      llvm::StoreInst *Store = CGF.Builder.CreateStore(LoadVal1, Ptr); -    Store->setAtomic(Order); +    Store->setAtomic(Order, Scope);      Store->setVolatile(E->isVolatile());      return;    }    case AtomicExpr::AO__c11_atomic_exchange: +  case AtomicExpr::AO__opencl_atomic_exchange:    case AtomicExpr::AO__atomic_exchange_n:    case AtomicExpr::AO__atomic_exchange:      Op = llvm::AtomicRMWInst::Xchg; @@ -564,6 +575,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,      PostOp = llvm::Instruction::Add;      // Fall through.    case AtomicExpr::AO__c11_atomic_fetch_add: +  case AtomicExpr::AO__opencl_atomic_fetch_add:    case AtomicExpr::AO__atomic_fetch_add:      Op = llvm::AtomicRMWInst::Add;      break; @@ -572,14 +584,26 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,      PostOp = llvm::Instruction::Sub;      // Fall through.    case AtomicExpr::AO__c11_atomic_fetch_sub: +  case AtomicExpr::AO__opencl_atomic_fetch_sub:    case AtomicExpr::AO__atomic_fetch_sub:      Op = llvm::AtomicRMWInst::Sub;      break; +  case AtomicExpr::AO__opencl_atomic_fetch_min: +    Op = E->getValueType()->isSignedIntegerType() ? llvm::AtomicRMWInst::Min +                                                  : llvm::AtomicRMWInst::UMin; +    break; + +  case AtomicExpr::AO__opencl_atomic_fetch_max: +    Op = E->getValueType()->isSignedIntegerType() ? llvm::AtomicRMWInst::Max +                                                  : llvm::AtomicRMWInst::UMax; +    break; +    case AtomicExpr::AO__atomic_and_fetch:      PostOp = llvm::Instruction::And;      // Fall through.    case AtomicExpr::AO__c11_atomic_fetch_and: +  case AtomicExpr::AO__opencl_atomic_fetch_and:    case AtomicExpr::AO__atomic_fetch_and:      Op = llvm::AtomicRMWInst::And;      break; @@ -588,6 +612,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,      PostOp = llvm::Instruction::Or;      // Fall through.    case AtomicExpr::AO__c11_atomic_fetch_or: +  case AtomicExpr::AO__opencl_atomic_fetch_or:    case AtomicExpr::AO__atomic_fetch_or:      Op = llvm::AtomicRMWInst::Or;      break; @@ -596,6 +621,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,      PostOp = llvm::Instruction::Xor;      // Fall through.    case AtomicExpr::AO__c11_atomic_fetch_xor: +  case AtomicExpr::AO__opencl_atomic_fetch_xor:    case AtomicExpr::AO__atomic_fetch_xor:      Op = llvm::AtomicRMWInst::Xor;      break; @@ -610,7 +636,7 @@ static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *E, Address Dest,    llvm::Value *LoadVal1 = CGF.Builder.CreateLoad(Val1);    llvm::AtomicRMWInst *RMWI = -      CGF.Builder.CreateAtomicRMW(Op, Ptr.getPointer(), LoadVal1, Order); +      CGF.Builder.CreateAtomicRMW(Op, Ptr.getPointer(), LoadVal1, Order, Scope);    RMWI->setVolatile(E->isVolatile());    // For __atomic_*_fetch operations, perform the operation again to @@ -633,6 +659,61 @@ EmitValToTemp(CodeGenFunction &CGF, Expr *E) {    return DeclPtr;  } +static void EmitAtomicOp(CodeGenFunction &CGF, AtomicExpr *Expr, Address Dest, +                         Address Ptr, Address Val1, Address Val2, +                         llvm::Value *IsWeak, llvm::Value *FailureOrder, +                         uint64_t Size, llvm::AtomicOrdering Order, +                         llvm::Value *Scope) { +  auto ScopeModel = Expr->getScopeModel(); + +  // LLVM atomic instructions always have synch scope. If clang atomic +  // expression has no scope operand, use default LLVM synch scope. +  if (!ScopeModel) { +    EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, IsWeak, FailureOrder, Size, +                 Order, CGF.CGM.getLLVMContext().getOrInsertSyncScopeID("")); +    return; +  } + +  // Handle constant scope. +  if (auto SC = dyn_cast<llvm::ConstantInt>(Scope)) { +    auto SCID = CGF.getTargetHooks().getLLVMSyncScopeID( +        ScopeModel->map(SC->getZExtValue()), CGF.CGM.getLLVMContext()); +    EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, IsWeak, FailureOrder, Size, +                 Order, SCID); +    return; +  } + +  // Handle non-constant scope. +  auto &Builder = CGF.Builder; +  auto Scopes = ScopeModel->getRuntimeValues(); +  llvm::DenseMap<unsigned, llvm::BasicBlock *> BB; +  for (auto S : Scopes) +    BB[S] = CGF.createBasicBlock(getAsString(ScopeModel->map(S)), CGF.CurFn); + +  llvm::BasicBlock *ContBB = +      CGF.createBasicBlock("atomic.scope.continue", CGF.CurFn); + +  auto *SC = Builder.CreateIntCast(Scope, Builder.getInt32Ty(), false); +  // If unsupported synch scope is encountered at run time, assume a fallback +  // synch scope value. +  auto FallBack = ScopeModel->getFallBackValue(); +  llvm::SwitchInst *SI = Builder.CreateSwitch(SC, BB[FallBack]); +  for (auto S : Scopes) { +    auto *B = BB[S]; +    if (S != FallBack) +      SI->addCase(Builder.getInt32(S), B); + +    Builder.SetInsertPoint(B); +    EmitAtomicOp(CGF, Expr, Dest, Ptr, Val1, Val2, IsWeak, FailureOrder, Size, +                 Order, +                 CGF.getTargetHooks().getLLVMSyncScopeID(ScopeModel->map(S), +                                                         CGF.getLLVMContext())); +    Builder.CreateBr(ContBB); +  } + +  Builder.SetInsertPoint(ContBB); +} +  static void  AddDirectArgument(CodeGenFunction &CGF, CallArgList &Args,                    bool UseOptimizedLibcall, llvm::Value *Val, QualType ValTy, @@ -663,33 +744,38 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {    QualType MemTy = AtomicTy;    if (const AtomicType *AT = AtomicTy->getAs<AtomicType>())      MemTy = AT->getValueType(); -  CharUnits sizeChars, alignChars; -  std::tie(sizeChars, alignChars) = getContext().getTypeInfoInChars(AtomicTy); -  uint64_t Size = sizeChars.getQuantity(); -  unsigned MaxInlineWidthInBits = getTarget().getMaxAtomicInlineWidth(); -  bool UseLibcall = (sizeChars != alignChars || -                     getContext().toBits(sizeChars) > MaxInlineWidthInBits); -    llvm::Value *IsWeak = nullptr, *OrderFail = nullptr;    Address Val1 = Address::invalid();    Address Val2 = Address::invalid();    Address Dest = Address::invalid(); -  Address Ptr(EmitScalarExpr(E->getPtr()), alignChars); +  Address Ptr = EmitPointerWithAlignment(E->getPtr()); + +  CharUnits sizeChars, alignChars; +  std::tie(sizeChars, alignChars) = getContext().getTypeInfoInChars(AtomicTy); +  uint64_t Size = sizeChars.getQuantity(); +  unsigned MaxInlineWidthInBits = getTarget().getMaxAtomicInlineWidth(); +  bool UseLibcall = ((Ptr.getAlignment() % sizeChars) != 0 || +                     getContext().toBits(sizeChars) > MaxInlineWidthInBits); -  if (E->getOp() == AtomicExpr::AO__c11_atomic_init) { +  if (E->getOp() == AtomicExpr::AO__c11_atomic_init || +      E->getOp() == AtomicExpr::AO__opencl_atomic_init) {      LValue lvalue = MakeAddrLValue(Ptr, AtomicTy);      EmitAtomicInit(E->getVal1(), lvalue);      return RValue::get(nullptr);    }    llvm::Value *Order = EmitScalarExpr(E->getOrder()); +  llvm::Value *Scope = +      E->getScopeModel() ? EmitScalarExpr(E->getScope()) : nullptr;    switch (E->getOp()) {    case AtomicExpr::AO__c11_atomic_init: +  case AtomicExpr::AO__opencl_atomic_init:      llvm_unreachable("Already handled above with EmitAtomicInit!");    case AtomicExpr::AO__c11_atomic_load: +  case AtomicExpr::AO__opencl_atomic_load:    case AtomicExpr::AO__atomic_load_n:      break; @@ -708,6 +794,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {    case AtomicExpr::AO__c11_atomic_compare_exchange_strong:    case AtomicExpr::AO__c11_atomic_compare_exchange_weak: +  case AtomicExpr::AO__opencl_atomic_compare_exchange_strong: +  case AtomicExpr::AO__opencl_atomic_compare_exchange_weak:    case AtomicExpr::AO__atomic_compare_exchange_n:    case AtomicExpr::AO__atomic_compare_exchange:      Val1 = EmitPointerWithAlignment(E->getVal1()); @@ -716,12 +804,15 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {      else        Val2 = EmitValToTemp(*this, E->getVal2());      OrderFail = EmitScalarExpr(E->getOrderFail()); -    if (E->getNumSubExprs() == 6) +    if (E->getOp() == AtomicExpr::AO__atomic_compare_exchange_n || +        E->getOp() == AtomicExpr::AO__atomic_compare_exchange)        IsWeak = EmitScalarExpr(E->getWeak());      break;    case AtomicExpr::AO__c11_atomic_fetch_add:    case AtomicExpr::AO__c11_atomic_fetch_sub: +  case AtomicExpr::AO__opencl_atomic_fetch_add: +  case AtomicExpr::AO__opencl_atomic_fetch_sub:      if (MemTy->isPointerType()) {        // For pointer arithmetic, we're required to do a bit of math:        // adding 1 to an int* is not the same as adding 1 to a uintptr_t. @@ -744,11 +835,18 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {    case AtomicExpr::AO__atomic_sub_fetch:    case AtomicExpr::AO__c11_atomic_store:    case AtomicExpr::AO__c11_atomic_exchange: +  case AtomicExpr::AO__opencl_atomic_store: +  case AtomicExpr::AO__opencl_atomic_exchange:    case AtomicExpr::AO__atomic_store_n:    case AtomicExpr::AO__atomic_exchange_n:    case AtomicExpr::AO__c11_atomic_fetch_and:    case AtomicExpr::AO__c11_atomic_fetch_or:    case AtomicExpr::AO__c11_atomic_fetch_xor: +  case AtomicExpr::AO__opencl_atomic_fetch_and: +  case AtomicExpr::AO__opencl_atomic_fetch_or: +  case AtomicExpr::AO__opencl_atomic_fetch_xor: +  case AtomicExpr::AO__opencl_atomic_fetch_min: +  case AtomicExpr::AO__opencl_atomic_fetch_max:    case AtomicExpr::AO__atomic_fetch_and:    case AtomicExpr::AO__atomic_fetch_or:    case AtomicExpr::AO__atomic_fetch_xor: @@ -784,18 +882,26 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {      bool UseOptimizedLibcall = false;      switch (E->getOp()) {      case AtomicExpr::AO__c11_atomic_init: +    case AtomicExpr::AO__opencl_atomic_init:        llvm_unreachable("Already handled above with EmitAtomicInit!");      case AtomicExpr::AO__c11_atomic_fetch_add: +    case AtomicExpr::AO__opencl_atomic_fetch_add:      case AtomicExpr::AO__atomic_fetch_add:      case AtomicExpr::AO__c11_atomic_fetch_and: +    case AtomicExpr::AO__opencl_atomic_fetch_and:      case AtomicExpr::AO__atomic_fetch_and:      case AtomicExpr::AO__c11_atomic_fetch_or: +    case AtomicExpr::AO__opencl_atomic_fetch_or:      case AtomicExpr::AO__atomic_fetch_or:      case AtomicExpr::AO__atomic_fetch_nand:      case AtomicExpr::AO__c11_atomic_fetch_sub: +    case AtomicExpr::AO__opencl_atomic_fetch_sub:      case AtomicExpr::AO__atomic_fetch_sub:      case AtomicExpr::AO__c11_atomic_fetch_xor: +    case AtomicExpr::AO__opencl_atomic_fetch_xor: +    case AtomicExpr::AO__opencl_atomic_fetch_min: +    case AtomicExpr::AO__opencl_atomic_fetch_max:      case AtomicExpr::AO__atomic_fetch_xor:      case AtomicExpr::AO__atomic_add_fetch:      case AtomicExpr::AO__atomic_and_fetch: @@ -812,6 +918,11 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {      case AtomicExpr::AO__c11_atomic_exchange:      case AtomicExpr::AO__c11_atomic_compare_exchange_weak:      case AtomicExpr::AO__c11_atomic_compare_exchange_strong: +    case AtomicExpr::AO__opencl_atomic_load: +    case AtomicExpr::AO__opencl_atomic_store: +    case AtomicExpr::AO__opencl_atomic_exchange: +    case AtomicExpr::AO__opencl_atomic_compare_exchange_weak: +    case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:      case AtomicExpr::AO__atomic_load_n:      case AtomicExpr::AO__atomic_load:      case AtomicExpr::AO__atomic_store_n: @@ -833,7 +944,24 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {                 getContext().getSizeType());      }      // Atomic address is the first or second parameter -    Args.add(RValue::get(EmitCastToVoidPtr(Ptr.getPointer())), +    // The OpenCL atomic library functions only accept pointer arguments to +    // generic address space. +    auto CastToGenericAddrSpace = [&](llvm::Value *V, QualType PT) { +      if (!E->isOpenCL()) +        return V; +      auto AS = PT->getAs<PointerType>()->getPointeeType().getAddressSpace(); +      if (AS == LangAS::opencl_generic) +        return V; +      auto DestAS = getContext().getTargetAddressSpace(LangAS::opencl_generic); +      auto T = V->getType(); +      auto *DestType = T->getPointerElementType()->getPointerTo(DestAS); + +      return getTargetHooks().performAddrSpaceCast( +          *this, V, AS, LangAS::opencl_generic, DestType, false); +    }; + +    Args.add(RValue::get(CastToGenericAddrSpace( +                 EmitCastToVoidPtr(Ptr.getPointer()), E->getPtr()->getType())),               getContext().VoidPtrTy);      std::string LibCallName; @@ -844,6 +972,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {      llvm::Instruction::BinaryOps PostOp = (llvm::Instruction::BinaryOps)0;      switch (E->getOp()) {      case AtomicExpr::AO__c11_atomic_init: +    case AtomicExpr::AO__opencl_atomic_init:        llvm_unreachable("Already handled!");      // There is only one libcall for compare an exchange, because there is no @@ -855,13 +984,17 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {      //                                  int success, int failure)      case AtomicExpr::AO__c11_atomic_compare_exchange_weak:      case AtomicExpr::AO__c11_atomic_compare_exchange_strong: +    case AtomicExpr::AO__opencl_atomic_compare_exchange_weak: +    case AtomicExpr::AO__opencl_atomic_compare_exchange_strong:      case AtomicExpr::AO__atomic_compare_exchange:      case AtomicExpr::AO__atomic_compare_exchange_n:        LibCallName = "__atomic_compare_exchange";        RetTy = getContext().BoolTy;        HaveRetTy = true; -      Args.add(RValue::get(EmitCastToVoidPtr(Val1.getPointer())), -               getContext().VoidPtrTy); +      Args.add( +          RValue::get(CastToGenericAddrSpace( +              EmitCastToVoidPtr(Val1.getPointer()), E->getVal1()->getType())), +          getContext().VoidPtrTy);        AddDirectArgument(*this, Args, UseOptimizedLibcall, Val2.getPointer(),                          MemTy, E->getExprLoc(), sizeChars);        Args.add(RValue::get(Order), getContext().IntTy); @@ -871,6 +1004,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {      //                        int order)      // T __atomic_exchange_N(T *mem, T val, int order)      case AtomicExpr::AO__c11_atomic_exchange: +    case AtomicExpr::AO__opencl_atomic_exchange:      case AtomicExpr::AO__atomic_exchange_n:      case AtomicExpr::AO__atomic_exchange:        LibCallName = "__atomic_exchange"; @@ -880,6 +1014,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {      // void __atomic_store(size_t size, void *mem, void *val, int order)      // void __atomic_store_N(T *mem, T val, int order)      case AtomicExpr::AO__c11_atomic_store: +    case AtomicExpr::AO__opencl_atomic_store:      case AtomicExpr::AO__atomic_store:      case AtomicExpr::AO__atomic_store_n:        LibCallName = "__atomic_store"; @@ -891,6 +1026,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {      // void __atomic_load(size_t size, void *mem, void *return, int order)      // T __atomic_load_N(T *mem, int order)      case AtomicExpr::AO__c11_atomic_load: +    case AtomicExpr::AO__opencl_atomic_load:      case AtomicExpr::AO__atomic_load:      case AtomicExpr::AO__atomic_load_n:        LibCallName = "__atomic_load"; @@ -901,6 +1037,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {        PostOp = llvm::Instruction::Add;      // Fall through.      case AtomicExpr::AO__c11_atomic_fetch_add: +    case AtomicExpr::AO__opencl_atomic_fetch_add:      case AtomicExpr::AO__atomic_fetch_add:        LibCallName = "__atomic_fetch_add";        AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), @@ -912,6 +1049,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {        PostOp = llvm::Instruction::And;      // Fall through.      case AtomicExpr::AO__c11_atomic_fetch_and: +    case AtomicExpr::AO__opencl_atomic_fetch_and:      case AtomicExpr::AO__atomic_fetch_and:        LibCallName = "__atomic_fetch_and";        AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), @@ -923,6 +1061,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {        PostOp = llvm::Instruction::Or;      // Fall through.      case AtomicExpr::AO__c11_atomic_fetch_or: +    case AtomicExpr::AO__opencl_atomic_fetch_or:      case AtomicExpr::AO__atomic_fetch_or:        LibCallName = "__atomic_fetch_or";        AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), @@ -934,6 +1073,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {        PostOp = llvm::Instruction::Sub;      // Fall through.      case AtomicExpr::AO__c11_atomic_fetch_sub: +    case AtomicExpr::AO__opencl_atomic_fetch_sub:      case AtomicExpr::AO__atomic_fetch_sub:        LibCallName = "__atomic_fetch_sub";        AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), @@ -945,11 +1085,26 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {        PostOp = llvm::Instruction::Xor;      // Fall through.      case AtomicExpr::AO__c11_atomic_fetch_xor: +    case AtomicExpr::AO__opencl_atomic_fetch_xor:      case AtomicExpr::AO__atomic_fetch_xor:        LibCallName = "__atomic_fetch_xor";        AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(),                          MemTy, E->getExprLoc(), sizeChars);        break; +    case AtomicExpr::AO__opencl_atomic_fetch_min: +      LibCallName = E->getValueType()->isSignedIntegerType() +                        ? "__atomic_fetch_min" +                        : "__atomic_fetch_umin"; +      AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), +                        LoweredMemTy, E->getExprLoc(), sizeChars); +      break; +    case AtomicExpr::AO__opencl_atomic_fetch_max: +      LibCallName = E->getValueType()->isSignedIntegerType() +                        ? "__atomic_fetch_max" +                        : "__atomic_fetch_umax"; +      AddDirectArgument(*this, Args, UseOptimizedLibcall, Val1.getPointer(), +                        LoweredMemTy, E->getExprLoc(), sizeChars); +      break;      // T __atomic_nand_fetch_N(T *mem, T val, int order)      // T __atomic_fetch_nand_N(T *mem, T val, int order)      case AtomicExpr::AO__atomic_nand_fetch: @@ -962,6 +1117,11 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {        break;      } +    if (E->isOpenCL()) { +      LibCallName = std::string("__opencl") + +          StringRef(LibCallName).drop_front(1).str(); + +    }      // Optimized functions have the size in their name.      if (UseOptimizedLibcall)        LibCallName += "_" + llvm::utostr(Size); @@ -982,6 +1142,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {      // order is always the last parameter      Args.add(RValue::get(Order),               getContext().IntTy); +    if (E->isOpenCL()) +      Args.add(RValue::get(Scope), getContext().IntTy);      // PostOp is only needed for the atomic_*_fetch operations, and      // thus is only needed for and implemented in the @@ -1018,9 +1180,11 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {    }    bool IsStore = E->getOp() == AtomicExpr::AO__c11_atomic_store || +                 E->getOp() == AtomicExpr::AO__opencl_atomic_store ||                   E->getOp() == AtomicExpr::AO__atomic_store ||                   E->getOp() == AtomicExpr::AO__atomic_store_n;    bool IsLoad = E->getOp() == AtomicExpr::AO__c11_atomic_load || +                E->getOp() == AtomicExpr::AO__opencl_atomic_load ||                  E->getOp() == AtomicExpr::AO__atomic_load ||                  E->getOp() == AtomicExpr::AO__atomic_load_n; @@ -1032,37 +1196,38 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {        switch ((llvm::AtomicOrderingCABI)ord) {        case llvm::AtomicOrderingCABI::relaxed:          EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, -                     llvm::AtomicOrdering::Monotonic); +                     llvm::AtomicOrdering::Monotonic, Scope);          break;        case llvm::AtomicOrderingCABI::consume:        case llvm::AtomicOrderingCABI::acquire:          if (IsStore)            break; // Avoid crashing on code with undefined behavior          EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, -                     llvm::AtomicOrdering::Acquire); +                     llvm::AtomicOrdering::Acquire, Scope);          break;        case llvm::AtomicOrderingCABI::release:          if (IsLoad)            break; // Avoid crashing on code with undefined behavior          EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, -                     llvm::AtomicOrdering::Release); +                     llvm::AtomicOrdering::Release, Scope);          break;        case llvm::AtomicOrderingCABI::acq_rel:          if (IsLoad || IsStore)            break; // Avoid crashing on code with undefined behavior          EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, -                     llvm::AtomicOrdering::AcquireRelease); +                     llvm::AtomicOrdering::AcquireRelease, Scope);          break;        case llvm::AtomicOrderingCABI::seq_cst:          EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, -                     llvm::AtomicOrdering::SequentiallyConsistent); +                     llvm::AtomicOrdering::SequentiallyConsistent, Scope);          break;        }      if (RValTy->isVoidType())        return RValue::get(nullptr);      return convertTempToRValue( -        Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo()), +        Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo( +                                        Dest.getAddressSpace())),          RValTy, E->getExprLoc());    } @@ -1091,13 +1256,13 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {    // Emit all the different atomics    Builder.SetInsertPoint(MonotonicBB); -  EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, -               Size, llvm::AtomicOrdering::Monotonic); +  EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, +               llvm::AtomicOrdering::Monotonic, Scope);    Builder.CreateBr(ContBB);    if (!IsStore) {      Builder.SetInsertPoint(AcquireBB); -    EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, -                 Size, llvm::AtomicOrdering::Acquire); +    EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, +                 llvm::AtomicOrdering::Acquire, Scope);      Builder.CreateBr(ContBB);      SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::consume),                  AcquireBB); @@ -1106,23 +1271,23 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {    }    if (!IsLoad) {      Builder.SetInsertPoint(ReleaseBB); -    EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, -                 Size, llvm::AtomicOrdering::Release); +    EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, +                 llvm::AtomicOrdering::Release, Scope);      Builder.CreateBr(ContBB);      SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::release),                  ReleaseBB);    }    if (!IsLoad && !IsStore) {      Builder.SetInsertPoint(AcqRelBB); -    EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, -                 Size, llvm::AtomicOrdering::AcquireRelease); +    EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, +                 llvm::AtomicOrdering::AcquireRelease, Scope);      Builder.CreateBr(ContBB);      SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::acq_rel),                  AcqRelBB);    }    Builder.SetInsertPoint(SeqCstBB); -  EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, -               Size, llvm::AtomicOrdering::SequentiallyConsistent); +  EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, +               llvm::AtomicOrdering::SequentiallyConsistent, Scope);    Builder.CreateBr(ContBB);    SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::seq_cst),                SeqCstBB); @@ -1134,7 +1299,8 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) {    assert(Atomics.getValueSizeInBits() <= Atomics.getAtomicSizeInBits());    return convertTempToRValue( -      Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo()), +      Builder.CreateBitCast(Dest, ConvertTypeForMem(RValTy)->getPointerTo( +                                      Dest.getAddressSpace())),        RValTy, E->getExprLoc());  } @@ -1181,15 +1347,15 @@ RValue AtomicInfo::convertAtomicTempToRValue(Address addr,    if (LVal.isBitField())      return CGF.EmitLoadOfBitfieldLValue(          LValue::MakeBitfield(addr, LVal.getBitFieldInfo(), LVal.getType(), -                             LVal.getBaseInfo()), loc); +                             LVal.getBaseInfo(), TBAAAccessInfo()), loc);    if (LVal.isVectorElt())      return CGF.EmitLoadOfLValue(          LValue::MakeVectorElt(addr, LVal.getVectorIdx(), LVal.getType(), -                              LVal.getBaseInfo()), loc); +                              LVal.getBaseInfo(), TBAAAccessInfo()), loc);    assert(LVal.isExtVectorElt());    return CGF.EmitLoadOfExtVectorElementLValue(LValue::MakeExtVectorElt(        addr, LVal.getExtVectorElts(), LVal.getType(), -      LVal.getBaseInfo())); +      LVal.getBaseInfo(), TBAAAccessInfo()));  }  RValue AtomicInfo::ConvertIntToValueOrAtomic(llvm::Value *IntVal, @@ -1260,8 +1426,7 @@ llvm::Value *AtomicInfo::EmitAtomicLoadOp(llvm::AtomicOrdering AO,    // Other decoration.    if (IsVolatile)      Load->setVolatile(true); -  if (LVal.getTBAAInfo()) -    CGF.CGM.DecorateInstructionWithTBAA(Load, LVal.getTBAAInfo()); +  CGF.CGM.DecorateInstructionWithTBAA(Load, LVal.getTBAAInfo());    return Load;  } @@ -1506,29 +1671,30 @@ EmitAtomicUpdateValue(CodeGenFunction &CGF, AtomicInfo &Atomics, RValue OldRVal,        UpdateLVal =            LValue::MakeBitfield(Ptr, AtomicLVal.getBitFieldInfo(),                                 AtomicLVal.getType(), -                               AtomicLVal.getBaseInfo()); +                               AtomicLVal.getBaseInfo(), +                               AtomicLVal.getTBAAInfo());        DesiredLVal =            LValue::MakeBitfield(DesiredAddr, AtomicLVal.getBitFieldInfo(), -                               AtomicLVal.getType(), -                               AtomicLVal.getBaseInfo()); +                               AtomicLVal.getType(), AtomicLVal.getBaseInfo(), +                               AtomicLVal.getTBAAInfo());      } else if (AtomicLVal.isVectorElt()) {        UpdateLVal = LValue::MakeVectorElt(Ptr, AtomicLVal.getVectorIdx(),                                           AtomicLVal.getType(), -                                         AtomicLVal.getBaseInfo()); +                                         AtomicLVal.getBaseInfo(), +                                         AtomicLVal.getTBAAInfo());        DesiredLVal = LValue::MakeVectorElt(            DesiredAddr, AtomicLVal.getVectorIdx(), AtomicLVal.getType(), -          AtomicLVal.getBaseInfo()); +          AtomicLVal.getBaseInfo(), AtomicLVal.getTBAAInfo());      } else {        assert(AtomicLVal.isExtVectorElt());        UpdateLVal = LValue::MakeExtVectorElt(Ptr, AtomicLVal.getExtVectorElts(),                                              AtomicLVal.getType(), -                                            AtomicLVal.getBaseInfo()); +                                            AtomicLVal.getBaseInfo(), +                                            AtomicLVal.getTBAAInfo());        DesiredLVal = LValue::MakeExtVectorElt(            DesiredAddr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(), -          AtomicLVal.getBaseInfo()); +          AtomicLVal.getBaseInfo(), AtomicLVal.getTBAAInfo());      } -    UpdateLVal.setTBAAInfo(AtomicLVal.getTBAAInfo()); -    DesiredLVal.setTBAAInfo(AtomicLVal.getTBAAInfo());      UpRVal = CGF.EmitLoadOfLValue(UpdateLVal, SourceLocation());    }    // Store new value in the corresponding memory area @@ -1611,20 +1777,19 @@ static void EmitAtomicUpdateValue(CodeGenFunction &CGF, AtomicInfo &Atomics,    if (AtomicLVal.isBitField()) {      DesiredLVal =          LValue::MakeBitfield(DesiredAddr, AtomicLVal.getBitFieldInfo(), -                             AtomicLVal.getType(), -                             AtomicLVal.getBaseInfo()); +                             AtomicLVal.getType(), AtomicLVal.getBaseInfo(), +                             AtomicLVal.getTBAAInfo());    } else if (AtomicLVal.isVectorElt()) {      DesiredLVal =          LValue::MakeVectorElt(DesiredAddr, AtomicLVal.getVectorIdx(), -                              AtomicLVal.getType(), -                              AtomicLVal.getBaseInfo()); +                              AtomicLVal.getType(), AtomicLVal.getBaseInfo(), +                              AtomicLVal.getTBAAInfo());    } else {      assert(AtomicLVal.isExtVectorElt());      DesiredLVal = LValue::MakeExtVectorElt(          DesiredAddr, AtomicLVal.getExtVectorElts(), AtomicLVal.getType(), -        AtomicLVal.getBaseInfo()); +        AtomicLVal.getBaseInfo(), AtomicLVal.getTBAAInfo());    } -  DesiredLVal.setTBAAInfo(AtomicLVal.getTBAAInfo());    // Store new value in the corresponding memory area    assert(UpdateRVal.isScalar());    CGF.EmitStoreThroughLValue(UpdateRVal, DesiredLVal); @@ -1777,8 +1942,7 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest,      // Other decoration.      if (IsVolatile)        store->setVolatile(true); -    if (dest.getTBAAInfo()) -      CGM.DecorateInstructionWithTBAA(store, dest.getTBAAInfo()); +    CGM.DecorateInstructionWithTBAA(store, dest.getTBAAInfo());      return;    } | 
