@@ -5213,6 +5213,136 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
52135213 Builder.SetInsertPoint(ContBB);
52145214 return RValue::get(nullptr);
52155215 }
5216+ case Builtin::BI__scoped_atomic_thread_fence: {
5217+ auto ScopeModel = AtomicScopeModel::create(AtomicScopeModelKind::Generic);
5218+
5219+ Value *Order = EmitScalarExpr(E->getArg(0));
5220+ Value *Scope = EmitScalarExpr(E->getArg(1));
5221+ auto Ord = dyn_cast<llvm::ConstantInt>(Order);
5222+ auto Scp = dyn_cast<llvm::ConstantInt>(Scope);
5223+ if (Ord && Scp) {
5224+ SyncScope SS = ScopeModel->isValid(Scp->getZExtValue())
5225+ ? ScopeModel->map(Scp->getZExtValue())
5226+ : ScopeModel->map(ScopeModel->getFallBackValue());
5227+ switch (Ord->getZExtValue()) {
5228+ case 0: // memory_order_relaxed
5229+ default: // invalid order
5230+ break;
5231+ case 1: // memory_order_consume
5232+ case 2: // memory_order_acquire
5233+ Builder.CreateFence(
5234+ llvm::AtomicOrdering::Acquire,
5235+ getTargetHooks().getLLVMSyncScopeID(getLangOpts(), SS,
5236+ llvm::AtomicOrdering::Acquire,
5237+ getLLVMContext()));
5238+ break;
5239+ case 3: // memory_order_release
5240+ Builder.CreateFence(
5241+ llvm::AtomicOrdering::Release,
5242+ getTargetHooks().getLLVMSyncScopeID(getLangOpts(), SS,
5243+ llvm::AtomicOrdering::Release,
5244+ getLLVMContext()));
5245+ break;
5246+ case 4: // memory_order_acq_rel
5247+ Builder.CreateFence(llvm::AtomicOrdering::AcquireRelease,
5248+ getTargetHooks().getLLVMSyncScopeID(
5249+ getLangOpts(), SS,
5250+ llvm::AtomicOrdering::AcquireRelease,
5251+ getLLVMContext()));
5252+ break;
5253+ case 5: // memory_order_seq_cst
5254+ Builder.CreateFence(llvm::AtomicOrdering::SequentiallyConsistent,
5255+ getTargetHooks().getLLVMSyncScopeID(
5256+ getLangOpts(), SS,
5257+ llvm::AtomicOrdering::SequentiallyConsistent,
5258+ getLLVMContext()));
5259+ break;
5260+ }
5261+ return RValue::get(nullptr);
5262+ }
5263+
5264+ llvm::BasicBlock *ContBB = createBasicBlock("atomic.scope.continue", CurFn);
5265+
5266+ llvm::SmallVector<std::pair<llvm::BasicBlock *, llvm::AtomicOrdering>>
5267+ OrderBBs;
5268+ if (Ord) {
5269+ switch (Ord->getZExtValue()) {
5270+ case 0: // memory_order_relaxed
5271+ default: // invalid order
5272+ ContBB->eraseFromParent();
5273+ return RValue::get(nullptr);
5274+ case 1: // memory_order_consume
5275+ case 2: // memory_order_acquire
5276+ OrderBBs.emplace_back(Builder.GetInsertBlock(),
5277+ llvm::AtomicOrdering::Acquire);
5278+ break;
5279+ case 3: // memory_order_release
5280+ OrderBBs.emplace_back(Builder.GetInsertBlock(),
5281+ llvm::AtomicOrdering::Release);
5282+ break;
5283+ case 4: // memory_order_acq_rel
5284+ OrderBBs.emplace_back(Builder.GetInsertBlock(),
5285+ llvm::AtomicOrdering::AcquireRelease);
5286+ break;
5287+ case 5: // memory_order_seq_cst
5288+ OrderBBs.emplace_back(Builder.GetInsertBlock(),
5289+ llvm::AtomicOrdering::SequentiallyConsistent);
5290+ break;
5291+ }
5292+ } else {
5293+ llvm::BasicBlock *AcquireBB = createBasicBlock("acquire", CurFn);
5294+ llvm::BasicBlock *ReleaseBB = createBasicBlock("release", CurFn);
5295+ llvm::BasicBlock *AcqRelBB = createBasicBlock("acqrel", CurFn);
5296+ llvm::BasicBlock *SeqCstBB = createBasicBlock("seqcst", CurFn);
5297+
5298+ Order = Builder.CreateIntCast(Order, Builder.getInt32Ty(), false);
5299+ llvm::SwitchInst *SI = Builder.CreateSwitch(Order, ContBB);
5300+ SI->addCase(Builder.getInt32(1), AcquireBB);
5301+ SI->addCase(Builder.getInt32(2), AcquireBB);
5302+ SI->addCase(Builder.getInt32(3), ReleaseBB);
5303+ SI->addCase(Builder.getInt32(4), AcqRelBB);
5304+ SI->addCase(Builder.getInt32(5), SeqCstBB);
5305+
5306+ OrderBBs.emplace_back(AcquireBB, llvm::AtomicOrdering::Acquire);
5307+ OrderBBs.emplace_back(ReleaseBB, llvm::AtomicOrdering::Release);
5308+ OrderBBs.emplace_back(AcqRelBB, llvm::AtomicOrdering::AcquireRelease);
5309+ OrderBBs.emplace_back(SeqCstBB,
5310+ llvm::AtomicOrdering::SequentiallyConsistent);
5311+ }
5312+
5313+ for (auto &[OrderBB, Ordering] : OrderBBs) {
5314+ Builder.SetInsertPoint(OrderBB);
5315+ if (Scp) {
5316+ SyncScope SS = ScopeModel->isValid(Scp->getZExtValue())
5317+ ? ScopeModel->map(Scp->getZExtValue())
5318+ : ScopeModel->map(ScopeModel->getFallBackValue());
5319+ Builder.CreateFence(Ordering,
5320+ getTargetHooks().getLLVMSyncScopeID(
5321+ getLangOpts(), SS, Ordering, getLLVMContext()));
5322+ Builder.CreateBr(ContBB);
5323+ } else {
5324+ llvm::DenseMap<unsigned, llvm::BasicBlock *> BBs;
5325+ for (unsigned Scp : ScopeModel->getRuntimeValues())
5326+ BBs[Scp] = createBasicBlock(getAsString(ScopeModel->map(Scp)), CurFn);
5327+
5328+ auto *SC = Builder.CreateIntCast(Scope, Builder.getInt32Ty(), false);
5329+ llvm::SwitchInst *SI = Builder.CreateSwitch(SC, ContBB);
5330+ for (unsigned Scp : ScopeModel->getRuntimeValues()) {
5331+ auto *B = BBs[Scp];
5332+ SI->addCase(Builder.getInt32(Scp), B);
5333+
5334+ Builder.SetInsertPoint(B);
5335+ Builder.CreateFence(Ordering, getTargetHooks().getLLVMSyncScopeID(
5336+ getLangOpts(), ScopeModel->map(Scp),
5337+ Ordering, getLLVMContext()));
5338+ Builder.CreateBr(ContBB);
5339+ }
5340+ }
5341+ }
5342+
5343+ Builder.SetInsertPoint(ContBB);
5344+ return RValue::get(nullptr);
5345+ }
52165346
52175347 case Builtin::BI__builtin_signbit:
52185348 case Builtin::BI__builtin_signbitf:
0 commit comments