@@ -5213,6 +5213,136 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
5213
5213
Builder.SetInsertPoint(ContBB);
5214
5214
return RValue::get(nullptr);
5215
5215
}
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
+ }
5216
5346
5217
5347
case Builtin::BI__builtin_signbit:
5218
5348
case Builtin::BI__builtin_signbitf:
0 commit comments