Skip to content

Commit 13fc799

Browse files
authored
Merge branch 'main' into xegpu-pass-layout
2 parents 235f205 + ee77c58 commit 13fc799

File tree

131 files changed

+2977
-1438
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

131 files changed

+2977
-1438
lines changed

clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,14 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
331331
return cir::StoreOp::create(*this, loc, val, dst, isVolatile, align, order);
332332
}
333333

334+
/// Emit a load from an boolean flag variable.
335+
cir::LoadOp createFlagLoad(mlir::Location loc, mlir::Value addr) {
336+
mlir::Type boolTy = getBoolTy();
337+
if (boolTy != mlir::cast<cir::PointerType>(addr.getType()).getPointee())
338+
addr = createPtrBitcast(addr, boolTy);
339+
return createLoad(loc, addr, /*isVolatile=*/false, /*alignment=*/1);
340+
}
341+
334342
cir::StoreOp createFlagStore(mlir::Location loc, bool val, mlir::Value dst) {
335343
mlir::Value flag = getBool(val, loc);
336344
return CIRBaseBuilderTy::createStore(loc, flag, dst);

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

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1492,6 +1492,55 @@ def CIR_BrCondOp : CIR_Op<"brcond", [
14921492
}];
14931493
}
14941494

1495+
//===----------------------------------------------------------------------===//
1496+
// IndirectBrOp
1497+
//===----------------------------------------------------------------------===//
1498+
1499+
def CIR_IndirectBrOp : CIR_Op<"indirect_br", [
1500+
DeclareOpInterfaceMethods<BranchOpInterface>,
1501+
SameVariadicOperandSize, Terminator, Pure
1502+
]> {
1503+
let summary = "Indirect branch";
1504+
let description = [{
1505+
The `cir.indirectbr` operation represents an indirect branch to one of
1506+
several possible successor blocks. The target block is computed from
1507+
the value of the given address operand.
1508+
1509+
This operation is typically generated when handling constructs like
1510+
the GCC extension `&&label` combined with an indirect `goto *ptr;`.
1511+
1512+
The `poison` attribute is used to mark an `indirectbr` that was created
1513+
but is known to be invalid, for instance when a label address was
1514+
taken but no indirect branch was ever emitted.
1515+
1516+
Example:
1517+
1518+
```mlir
1519+
%0 = cir.block_address <@A, "A"> : !cir.ptr<!void>
1520+
cir.indirectbr %0 poison : <!void>, [
1521+
^bb1
1522+
]
1523+
```
1524+
}];
1525+
1526+
let arguments = (ins
1527+
CIR_VoidPtrType:$addr,
1528+
UnitAttr:$poison,
1529+
VariadicOfVariadic<AnyType, "operand_segments">:$succ_operands,
1530+
DenseI32ArrayAttr:$operand_segments
1531+
);
1532+
1533+
let successors = (successor VariadicSuccessor<AnySuccessor>:$successors);
1534+
let assemblyFormat = [{
1535+
$addr ( `poison` $poison^ )? `:` qualified(type($addr)) `,`
1536+
custom<IndirectBrOpSucessors>(ref(type($addr)),
1537+
$successors,
1538+
$succ_operands,
1539+
type($succ_operands))
1540+
attr-dict
1541+
}];
1542+
}
1543+
14951544
//===----------------------------------------------------------------------===//
14961545
// Common loop op definitions
14971546
//===----------------------------------------------------------------------===//
@@ -5188,6 +5237,11 @@ def CIR_AtomicFetchKind : CIR_I32EnumAttr<
51885237
I32EnumAttrCase<"Min", 7, "min">
51895238
]>;
51905239

5240+
def CIR_SyncScopeKind : CIR_I32EnumAttr<"SyncScopeKind", "sync scope kind", [
5241+
I32EnumAttrCase<"SingleThread", 0, "single_thread">,
5242+
I32EnumAttrCase<"System", 1, "system">
5243+
]>;
5244+
51915245
def CIR_AtomicFetchOp : CIR_Op<"atomic.fetch", [
51925246
AllTypesMatch<["result", "val"]>,
51935247
TypesMatchWith<"type of 'val' must match the pointee type of 'ptr'",
@@ -5411,6 +5465,36 @@ def CIR_AtomicClearOp : CIR_Op<"atomic.clear"> {
54115465
}];
54125466
}
54135467

5468+
def CIR_AtomicFence : CIR_Op<"atomic.fence"> {
5469+
let summary = "Atomic thread fence";
5470+
let description = [{
5471+
C/C++ Atomic thread fence synchronization primitive. Implements the builtin
5472+
`__atomic_thread_fence` which enforces memory ordering constraints across
5473+
threads within the specified synchronization scope.
5474+
5475+
This handles all variations including:
5476+
- `__atomic_thread_fence`
5477+
- `__atomic_signal_fence`
5478+
- `__c11_atomic_thread_fence`
5479+
- `__c11_atomic_signal_fence`
5480+
5481+
Example:
5482+
```mlir
5483+
cir.atomic.fence syncscope(system) seq_cst
5484+
cir.atomic.fence syncscope(single_thread) seq_cst
5485+
```
5486+
}];
5487+
5488+
let arguments = (ins
5489+
Arg<CIR_MemOrder, "memory order">:$ordering,
5490+
OptionalAttr<CIR_SyncScopeKind>:$syncscope
5491+
);
5492+
5493+
let assemblyFormat = [{
5494+
(`syncscope` `(` $syncscope^ `)`)? $ordering attr-dict
5495+
}];
5496+
}
5497+
54145498
//===----------------------------------------------------------------------===//
54155499
// BlockAddressOp
54165500
//===----------------------------------------------------------------------===//

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,6 @@ struct MissingFeatures {
227227
static bool countedBySize() { return false; }
228228
static bool cgFPOptionsRAII() { return false; }
229229
static bool checkBitfieldClipping() { return false; }
230-
static bool cleanupDestroyNRVOVariable() { return false; }
231230
static bool cirgenABIInfo() { return false; }
232231
static bool cleanupAfterErrorDiags() { return false; }
233232
static bool cleanupAppendInsts() { return false; }

clang/include/clang/DependencyScanning/DependencyScanningWorker.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ class DependencyScanningWorker {
100100
/// \returns false if clang errors occurred (with diagnostics reported to
101101
/// \c DiagConsumer), true otherwise.
102102
bool computeDependencies(
103-
StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
103+
StringRef WorkingDirectory, ArrayRef<std::string> CommandLine,
104104
DependencyConsumer &DepConsumer, DependencyActionController &Controller,
105105
DiagnosticConsumer &DiagConsumer,
106106
std::optional<llvm::MemoryBufferRef> TUBuffer = std::nullopt);
@@ -111,7 +111,7 @@ class DependencyScanningWorker {
111111
/// \returns A \c StringError with the diagnostic output if clang errors
112112
/// occurred, success otherwise.
113113
llvm::Error computeDependencies(
114-
StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
114+
StringRef WorkingDirectory, ArrayRef<std::string> CommandLine,
115115
DependencyConsumer &Consumer, DependencyActionController &Controller,
116116
std::optional<llvm::MemoryBufferRef> TUBuffer = std::nullopt);
117117

@@ -125,7 +125,7 @@ class DependencyScanningWorker {
125125
/// @param CommandLine The commandline used for the scan.
126126
/// @return Error if the initializaiton fails.
127127
llvm::Error initializeCompilerInstanceWithContextOrError(
128-
StringRef CWD, const std::vector<std::string> &CommandLine);
128+
StringRef CWD, ArrayRef<std::string> CommandLine);
129129

130130
/// @brief Performaces dependency scanning for the module whose name is
131131
/// specified.
@@ -147,9 +147,9 @@ class DependencyScanningWorker {
147147
/// three methods return a flag to indicate if the call is successful.
148148
/// The initialization function asks the client for a DiagnosticsConsumer
149149
/// that it direct the diagnostics to.
150-
bool initializeCompilerInstanceWithContext(
151-
StringRef CWD, const std::vector<std::string> &CommandLine,
152-
DiagnosticConsumer *DC = nullptr);
150+
bool initializeCompilerInstanceWithContext(StringRef CWD,
151+
ArrayRef<std::string> CommandLine,
152+
DiagnosticConsumer *DC = nullptr);
153153
bool
154154
computeDependenciesByNameWithContext(StringRef ModuleName,
155155
DependencyConsumer &Consumer,
@@ -172,7 +172,7 @@ class DependencyScanningWorker {
172172
/// Actually carries out the scan. If \c OverlayFS is provided, it must be
173173
/// based on top of DepFS.
174174
bool scanDependencies(
175-
StringRef WorkingDirectory, const std::vector<std::string> &CommandLine,
175+
StringRef WorkingDirectory, ArrayRef<std::string> CommandLine,
176176
DependencyConsumer &Consumer, DependencyActionController &Controller,
177177
DiagnosticConsumer &DC,
178178
IntrusiveRefCntPtr<llvm::vfs::FileSystem> OverlayFS = nullptr);

clang/include/clang/Tooling/DependencyScanningTool.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class DependencyScanningTool {
4747
/// \returns A \c StringError with the diagnostic output if clang errors
4848
/// occurred, dependency file contents otherwise.
4949
llvm::Expected<std::string>
50-
getDependencyFile(const std::vector<std::string> &CommandLine, StringRef CWD);
50+
getDependencyFile(ArrayRef<std::string> CommandLine, StringRef CWD);
5151

5252
/// Collect the module dependency in P1689 format for C++20 named modules.
5353
///
@@ -92,7 +92,7 @@ class DependencyScanningTool {
9292
/// occurred, \c TranslationUnitDeps otherwise.
9393
llvm::Expected<dependencies::TranslationUnitDeps>
9494
getTranslationUnitDependencies(
95-
const std::vector<std::string> &CommandLine, StringRef CWD,
95+
ArrayRef<std::string> CommandLine, StringRef CWD,
9696
const llvm::DenseSet<dependencies::ModuleID> &AlreadySeen,
9797
dependencies::LookupModuleOutputCallback LookupModuleOutput,
9898
std::optional<llvm::MemoryBufferRef> TUBuffer = std::nullopt);
@@ -104,8 +104,8 @@ class DependencyScanningTool {
104104
/// CompilerInstanceWithContext. We are keeping it here so that it is easier
105105
/// to coordinate with Swift and C-API changes.
106106
llvm::Expected<dependencies::TranslationUnitDeps> getModuleDependencies(
107-
StringRef ModuleName, const std::vector<std::string> &CommandLine,
108-
StringRef CWD, const llvm::DenseSet<dependencies::ModuleID> &AlreadySeen,
107+
StringRef ModuleName, ArrayRef<std::string> CommandLine, StringRef CWD,
108+
const llvm::DenseSet<dependencies::ModuleID> &AlreadySeen,
109109
dependencies::LookupModuleOutputCallback LookupModuleOutput);
110110

111111
/// The following three methods provide a new interface to perform
@@ -119,8 +119,9 @@ class DependencyScanningTool {
119119
/// @param CWD The current working directory used during the scan.
120120
/// @param CommandLine The commandline used for the scan.
121121
/// @return Error if the initializaiton fails.
122-
llvm::Error initializeCompilerInstanceWithContext(
123-
StringRef CWD, const std::vector<std::string> &CommandLine);
122+
llvm::Error
123+
initializeCompilerInstanceWithContext(StringRef CWD,
124+
ArrayRef<std::string> CommandLine);
124125

125126
/// @brief Computes the dependeny for the module named ModuleName.
126127
/// @param ModuleName The name of the module for which this method computes

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,33 @@ static RValue emitBuiltinBitOp(CIRGenFunction &cgf, const CallExpr *e,
6060
return RValue::get(result);
6161
}
6262

63+
static mlir::Value makeAtomicFenceValue(CIRGenFunction &cgf,
64+
const CallExpr *expr,
65+
cir::SyncScopeKind syncScope) {
66+
CIRGenBuilderTy &builder = cgf.getBuilder();
67+
mlir::Value orderingVal = cgf.emitScalarExpr(expr->getArg(0));
68+
69+
auto constOrdering = orderingVal.getDefiningOp<cir::ConstantOp>();
70+
71+
if (!constOrdering) {
72+
// TODO(cir): Emit code to switch on `orderingVal`,
73+
// and creating the fence op for valid values.
74+
cgf.cgm.errorNYI("Variable atomic fence ordering");
75+
return {};
76+
}
77+
78+
auto constOrderingAttr = constOrdering.getValueAttr<cir::IntAttr>();
79+
assert(constOrderingAttr && "Expected integer constant for ordering");
80+
81+
auto ordering = static_cast<cir::MemOrder>(constOrderingAttr.getUInt());
82+
83+
cir::AtomicFence::create(
84+
builder, cgf.getLoc(expr->getSourceRange()), ordering,
85+
cir::SyncScopeKindAttr::get(&cgf.getMLIRContext(), syncScope));
86+
87+
return {};
88+
}
89+
6390
namespace {
6491
struct WidthAndSignedness {
6592
unsigned width;
@@ -982,8 +1009,13 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
9821009
case Builtin::BI__atomic_is_lock_free:
9831010
case Builtin::BI__atomic_test_and_set:
9841011
case Builtin::BI__atomic_clear:
1012+
return errorBuiltinNYI(*this, e, builtinID);
9851013
case Builtin::BI__atomic_thread_fence:
1014+
return RValue::get(
1015+
makeAtomicFenceValue(*this, e, cir::SyncScopeKind::System));
9861016
case Builtin::BI__atomic_signal_fence:
1017+
return RValue::get(
1018+
makeAtomicFenceValue(*this, e, cir::SyncScopeKind::SingleThread));
9871019
case Builtin::BI__c11_atomic_thread_fence:
9881020
case Builtin::BI__c11_atomic_signal_fence:
9891021
case Builtin::BI__scoped_atomic_thread_fence:

clang/lib/CIR/CodeGen/CIRGenDecl.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ CIRGenFunction::emitAutoVarAlloca(const VarDecl &d,
106106
cir::ConstantOp falseNVRO = builder.getFalse(loc);
107107
Address nrvoFlag = createTempAlloca(falseNVRO.getType(),
108108
CharUnits::One(), loc, "nrvo",
109-
/*arraySize=*/nullptr, &address);
109+
/*arraySize=*/nullptr);
110110
assert(builder.getInsertionBlock());
111111
builder.createStore(loc, falseNVRO, nrvoFlag);
112112

@@ -835,7 +835,24 @@ template <class Derived> struct DestroyNRVOVariable : EHScopeStack::Cleanup {
835835
QualType ty;
836836

837837
void emit(CIRGenFunction &cgf, Flags flags) override {
838-
assert(!cir::MissingFeatures::cleanupDestroyNRVOVariable());
838+
// Along the exceptions path we always execute the dtor.
839+
bool nrvo = flags.isForNormalCleanup() && nrvoFlag;
840+
841+
CIRGenBuilderTy &builder = cgf.getBuilder();
842+
mlir::OpBuilder::InsertionGuard guard(builder);
843+
if (nrvo) {
844+
// If we exited via NRVO, we skip the destructor call.
845+
mlir::Location loc = addr.getPointer().getLoc();
846+
mlir::Value didNRVO = builder.createFlagLoad(loc, nrvoFlag);
847+
mlir::Value notNRVO = builder.createNot(didNRVO);
848+
cir::IfOp::create(builder, loc, notNRVO, /*withElseRegion=*/false,
849+
[&](mlir::OpBuilder &b, mlir::Location) {
850+
static_cast<Derived *>(this)->emitDestructorCall(cgf);
851+
builder.createYield(loc);
852+
});
853+
} else {
854+
static_cast<Derived *>(this)->emitDestructorCall(cgf);
855+
}
839856
}
840857

841858
virtual ~DestroyNRVOVariable() = default;
@@ -851,7 +868,9 @@ struct DestroyNRVOVariableCXX final
851868
const CXXDestructorDecl *dtor;
852869

853870
void emitDestructorCall(CIRGenFunction &cgf) {
854-
assert(!cir::MissingFeatures::cleanupDestroyNRVOVariable());
871+
cgf.emitCXXDestructorCall(dtor, Dtor_Complete,
872+
/*forVirtualBase=*/false,
873+
/*delegating=*/false, addr, ty);
855874
}
856875
};
857876

clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -174,11 +174,22 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
174174

175175
mlir::Value VisitAddrLabelExpr(const AddrLabelExpr *e) {
176176
auto func = cast<cir::FuncOp>(cgf.curFn);
177-
auto blockInfoAttr = cir::BlockAddrInfoAttr::get(
177+
cir::BlockAddrInfoAttr blockInfoAttr = cir::BlockAddrInfoAttr::get(
178178
&cgf.getMLIRContext(), func.getSymName(), e->getLabel()->getName());
179-
return cir::BlockAddressOp::create(builder, cgf.getLoc(e->getSourceRange()),
180-
cgf.convertType(e->getType()),
181-
blockInfoAttr);
179+
cir::BlockAddressOp blockAddressOp = cir::BlockAddressOp::create(
180+
builder, cgf.getLoc(e->getSourceRange()), cgf.convertType(e->getType()),
181+
blockInfoAttr);
182+
cir::LabelOp resolvedLabel = cgf.cgm.lookupBlockAddressInfo(blockInfoAttr);
183+
if (!resolvedLabel) {
184+
cgf.cgm.mapUnresolvedBlockAddress(blockAddressOp);
185+
// Still add the op to maintain insertion order it will be resolved in
186+
// resolveBlockAddresses
187+
cgf.cgm.mapResolvedBlockAddress(blockAddressOp, nullptr);
188+
} else {
189+
cgf.cgm.mapResolvedBlockAddress(blockAddressOp, resolvedLabel);
190+
}
191+
cgf.instantiateIndirectGotoBlock();
192+
return blockAddressOp;
182193
}
183194

184195
mlir::Value VisitIntegerLiteral(const IntegerLiteral *e) {

0 commit comments

Comments
 (0)