Skip to content

Commit ca75a57

Browse files
committed
[CIR][CIRGen] Support for builtin __atomic_thread_fence
Resolves #1274 Implements atomic thread fence synchronization primitive corresponding to `atomic.thread_fence` CIR.
1 parent 3c3b096 commit ca75a57

File tree

3 files changed

+113
-1
lines changed

3 files changed

+113
-1
lines changed

clang/include/clang/CIR/Dialect/IR/CIROps.td

+41
Original file line numberDiff line numberDiff line change
@@ -5409,6 +5409,47 @@ def AtomicCmpXchg : CIR_Op<"atomic.cmp_xchg",
54095409
let hasVerifier = 0;
54105410
}
54115411

5412+
def MemScope_SingleThread : I32EnumAttrCase<"MemScope_SingleThread",
5413+
0, "single_thread">;
5414+
def MemScope_System : I32EnumAttrCase<"MemScope_System",
5415+
1, "system">;
5416+
5417+
def MemScopeKind : I32EnumAttr<
5418+
"MemScopeKind",
5419+
"Memory Scope Enumeration",
5420+
[MemScope_SingleThread, MemScope_System]> {
5421+
let cppNamespace = "::cir";
5422+
}
5423+
5424+
def AtomicFence : CIR_Op<"atomic.fence"> {
5425+
let summary = "Atomic thread fence";
5426+
let description = [{
5427+
C/C++ Atomic thread fence synchronization primitive. Implements the builtin
5428+
`__atomic_thread_fence` which enforces memory ordering constraints across
5429+
threads within the specified synchronization scope.
5430+
5431+
This handles all variations including:
5432+
- `__atomic_thread_fence`
5433+
- `__atomic_signal_fence`
5434+
- `__c11_atomic_thread_fence`
5435+
- `__c11_atomic_signal_fence`
5436+
5437+
Example:
5438+
5439+
5440+
}];
5441+
let results = (outs);
5442+
let arguments = (ins Arg<MemScopeKind, "sync scope">:$sync_scope,
5443+
Arg<MemOrder, "memory order">:$ordering);
5444+
5445+
let assemblyFormat = [{
5446+
`(` `sync_scope` `=` $sync_scope `,`
5447+
`ordering` `=` $ordering `)` attr-dict
5448+
}];
5449+
5450+
let hasVerifier = 0;
5451+
}
5452+
54125453
def SignBitOp : CIR_Op<"signbit", [Pure]> {
54135454
let summary = "Checks the sign of a floating-point number";
54145455
let description = [{

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

+61-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@
1616
#include "CIRGenCstEmitter.h"
1717
#include "CIRGenFunction.h"
1818
#include "CIRGenModule.h"
19+
#include "CIRGenValue.h"
1920
#include "TargetInfo.h"
21+
#include "clang/AST/Expr.h"
22+
#include "clang/CIR/Dialect/IR/CIROpsEnums.h"
2023
#include "clang/CIR/MissingFeatures.h"
2124

2225
// TODO(cir): we shouldn't need this but we currently reuse intrinsic IDs for
@@ -30,6 +33,7 @@
3033
#include "clang/Frontend/FrontendDiagnostic.h"
3134

3235
#include "mlir/Dialect/Func/IR/FuncOps.h"
36+
#include "mlir/IR/BuiltinAttributes.h"
3337
#include "mlir/IR/Value.h"
3438
#include "clang/CIR/Dialect/IR/CIRDialect.h"
3539
#include "llvm/Support/ErrorHandling.h"
@@ -330,6 +334,58 @@ static mlir::Value MakeAtomicCmpXchgValue(CIRGenFunction &cgf,
330334
return returnBool ? op.getResult(1) : op.getResult(0);
331335
}
332336

337+
static mlir::Value MakeAtomicFenceValue(CIRGenFunction &cgf,
338+
const CallExpr *expr,
339+
cir::MemScopeKind syncScope) {
340+
QualType typ = expr->getType();
341+
auto &builder = cgf.getBuilder();
342+
343+
auto intType =
344+
expr->getArg(0)->getType()->getPointeeType()->isUnsignedIntegerType()
345+
? builder.getUIntNTy(cgf.getContext().getTypeSize(typ))
346+
: builder.getSIntNTy(cgf.getContext().getTypeSize(typ));
347+
348+
auto orderingVal =
349+
emitToInt(cgf, cgf.emitScalarExpr(expr->getArg(1)), typ, intType);
350+
auto orderingAttr =
351+
orderingVal.getDefiningOp()->getAttrOfType<mlir::IntegerAttr>("value");
352+
353+
cir::MemOrder ordering;
354+
switch (orderingAttr.getInt()) {
355+
case 0: {
356+
ordering = cir::MemOrder::Relaxed;
357+
break;
358+
}
359+
case 1: {
360+
ordering = cir::MemOrder::Consume;
361+
break;
362+
}
363+
case 2: {
364+
ordering = cir::MemOrder::Acquire;
365+
break;
366+
}
367+
case 3: {
368+
ordering = cir::MemOrder::Release;
369+
break;
370+
}
371+
case 4: {
372+
ordering = cir::MemOrder::AcquireRelease;
373+
break;
374+
}
375+
case 5: {
376+
ordering = cir::MemOrder::SequentiallyConsistent;
377+
break;
378+
}
379+
default:
380+
llvm_unreachable("invalid memory ordering scope");
381+
}
382+
383+
builder.create<cir::AtomicFence>(cgf.getLoc(expr->getSourceRange()),
384+
syncScope, ordering);
385+
386+
return mlir::Value();
387+
}
388+
333389
static bool
334390
typeRequiresBuiltinLaunderImp(const ASTContext &astContext, QualType ty,
335391
llvm::SmallPtrSetImpl<const Decl *> &seen) {
@@ -1840,10 +1896,14 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
18401896
llvm_unreachable("BI__atomic_clear NYI");
18411897

18421898
case Builtin::BI__atomic_thread_fence:
1899+
return RValue::get(
1900+
MakeAtomicFenceValue(*this, E, cir::MemScopeKind::MemScope_System));
18431901
case Builtin::BI__atomic_signal_fence:
1902+
return RValue::get(MakeAtomicFenceValue(
1903+
*this, E, cir::MemScopeKind::MemScope_SingleThread));
18441904
case Builtin::BI__c11_atomic_thread_fence:
18451905
case Builtin::BI__c11_atomic_signal_fence:
1846-
llvm_unreachable("BI__atomic_thread_fence like NYI");
1906+
llvm_unreachable("BI__c11_atomic_thread_fence like NYI");
18471907

18481908
case Builtin::BI__builtin_signbit:
18491909
case Builtin::BI__builtin_signbitf:

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h

+11
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "mlir/IR/MLIRContext.h"
1717
#include "mlir/Interfaces/DataLayoutInterfaces.h"
1818
#include "mlir/Transforms/DialectConversion.h"
19+
#include "clang/CIR/Dialect/IR/CIRDialect.h"
1920

2021
namespace cir {
2122
namespace direct {
@@ -820,6 +821,16 @@ class CIRToLLVMAtomicFetchLowering
820821
mlir::ConversionPatternRewriter &) const override;
821822
};
822823

824+
// class CIRToLLVMAtomicFenceLowering
825+
// : public mlir::OpConversionPattern<cir::AtomicFence> {
826+
// public:
827+
// using mlir::OpConversionPattern<cir::AtomicFence>::OpConversionPattern;
828+
//
829+
// mlir::LogicalResult
830+
// matchAndRewrite(cir::AtomicFence op, OpAdaptor,
831+
// mlir::ConversionPatternRewriter &) const override;
832+
// };
833+
823834
class CIRToLLVMByteswapOpLowering
824835
: public mlir::OpConversionPattern<cir::ByteswapOp> {
825836
public:

0 commit comments

Comments
 (0)