[Mlir-commits] [mlir] 3d02144 - [CIR] Add 'loop-id' to loop and branch types. (#235052)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Fri Oct 23 15:58:06 PDT 2026
Author: Erich Keane
Date: 2026-10-23T15:58:02-07:00
New Revision: 3d021445d21578878b79332029190e517498494b
URL: https://github.com/llvm/llvm-project/commit/3d021445d21578878b79332029190e517498494b
DIFF: https://github.com/llvm/llvm-project/commit/3d021445d21578878b79332029190e517498494b.diff
LOG: [CIR] Add 'loop-id' to loop and branch types. (#235052)
While working through the loop-hints lowering, I discovered that we need
a way to make each loop get a 'distinct' loop-annotation in LLVM-IR.
This relationship is lost during FlattenCFG when it splits to multiple
branches. #233890 adds this to the LLVM-IR dialect.
I considered/had a patch to do this to FlattenCFG as well, however when
working on further loop hints (parallel in particular), we need to be
able to spread this value inside of the loop itself, so it makes more
sense to generate the ID from the start.
I suspect this ID will come in handy outside of the loop-hints, so it is
left as a separate attribute.
Added:
clang/test/CIR/Transforms/flatten-loop-id.cir
Modified:
clang/include/clang/CIR/Dialect/IR/CIROps.td
clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.td
clang/lib/CIR/CodeGen/CIRGenStmt.cpp
clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp
clang/test/CIR/CodeGen/loop-hints-stds.cpp
clang/test/CIR/CodeGen/loop-hints.c
clang/test/CIR/CodeGen/loop-hints.cpp
clang/test/CIR/CodeGenHLSL/loop-hints.hlsl
clang/test/CIR/CodeGenOpenACC/loop.cpp
clang/test/CIR/CodeGenOpenCL/loop-hints.cl
clang/test/CIR/IR/invalid-loop-hints.cir
clang/test/CIR/IR/loop-hints.cir
clang/test/CIR/Transforms/flatten-loop-cleanup.cir
mlir/include/mlir/IR/CommonAttrConstraints.td
Removed:
################################################################################
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index f22c15aea680a7..5411e89c9df7a0 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -172,6 +172,14 @@ class HasAtMostOneOfAttrs<list<string> names> : PredOpTrait<
HasAtMostOneOfAttrsPred<!foreach(name, names, "$" # name)>
>;
+// The loop_hints lowering requires a loop_id, to identify the branches that get
+// created during flatten. Predicate makes sure the loop_id is available to
+// loop_hints.
+def LoopHintsRequireLoopId : PredOpTrait<
+ "'loop_hints' requires a 'loop_id'",
+ CPred<"!$loop_hints || $loop_id">
+>;
+
// Like `SameTypeOperands`, but the operands are pointers that are only required
// to share the same pointee type; they may still
diff er in address space (e.g.
// a `cir.copy` that assigns through an address-space-qualified pointer).
@@ -1895,7 +1903,7 @@ def CIR_SwitchFlatOp : CIR_Op<"switch.flat", [
def CIR_BrOp : CIR_Op<"br",[
DeclareOpInterfaceMethods<BranchOpInterface, ["getSuccessorForOperands"]>,
- Pure, Terminator
+ Pure, Terminator, LoopHintsRequireLoopId
]> {
let summary = "Unconditional branch";
let description = [{
@@ -1905,8 +1913,9 @@ def CIR_BrOp : CIR_Op<"br",[
Note that for source level `goto`'s crossing scope boundaries, those are
usually represented with the "symbolic" `cir.goto` operation.
- When a loop is flattened, the optional `loop_hints` attribute is placed on
- the branches that form the loop's back edge (see `cir.brcond`).
+ When a loop is flattened, the optional `loop_id` and `loop_hints`
+ attributes are placed on the branches that form the loop's back edge (see
+ `cir.brcond`).
Example:
@@ -1927,11 +1936,12 @@ def CIR_BrOp : CIR_Op<"br",[
];
let arguments = (ins Variadic<CIR_AnyType>:$destOperands,
+ OptionalAttr<AnyDistinctAttr>:$loop_id,
OptionalAttr<CIR_LoopHintAttr>:$loop_hints);
let successors = (successor AnySuccessor:$dest);
let assemblyFormat = [{
$dest (`(` $destOperands^ `:` type($destOperands) `)`)?
- (`loop_hints` $loop_hints^)? attr-dict
+ (`loop_id` $loop_id^)? (`loop_hints` $loop_hints^)? attr-dict
}];
let hasCanonicalizeMethod = 1;
@@ -2235,7 +2245,7 @@ def CIR_FreezeOp : CIR_Op<"freeze", [Pure, SameOperandsAndResultType]> {
def CIR_BrCondOp : CIR_Op<"brcond", [
DeclareOpInterfaceMethods<BranchOpInterface, ["getSuccessorForOperands"]>,
- Pure, Terminator, AttrSizedOperandSegments
+ Pure, Terminator, AttrSizedOperandSegments, LoopHintsRequireLoopId
]> {
let summary = "Conditional branch";
let description = [{
@@ -2243,9 +2253,12 @@ def CIR_BrCondOp : CIR_Op<"brcond", [
%cond (which must be a !cir.bool type) evaluates to true, otherwise
it branches to 'bb1'.
- The optional `loop_hints` attribute is attached by CFG flattening to
- branches that target a loop header (i.e. the loop's back edge), carrying
- the `#cir.loop_hint` of the original loop op.
+ The optional `loop_id` and `loop_hints` attributes are attached to the
+ `cir.br` and `cir.brcond` attributes during CFG flattening, which takes the
+ hints/id from the original loop and applies it to the branch that targets
+ the loop header. `loop_id` is a distinct attribute per-loop, so we can
+ identify which branches come from the same loop. At the moment, the id is
+ only used/generated for `loop_hints`, but is likely independently useful.
Example:
@@ -2260,17 +2273,20 @@ def CIR_BrCondOp : CIR_Op<"brcond", [
}];
let builders = [
- OpBuilder<(ins "mlir::Value":$cond, "mlir::Block *":$destTrue, "mlir::Block *":$destFalse,
+ OpBuilder<(ins "mlir::Value":$cond, "mlir::Block *":$destTrue,
+ "mlir::Block *":$destFalse,
CArg<"mlir::ValueRange", "{}">:$destOperandsTrue,
CArg<"mlir::ValueRange", "{}">:$destOperandsFalse), [{
build($_builder, $_state, cond, destOperandsTrue,
- destOperandsFalse, /*loop_hints=*/nullptr, destTrue, destFalse);
+ destOperandsFalse, /*loop_id=*/nullptr, /*loop_hints=*/nullptr,
+ destTrue, destFalse);
}]>
];
let arguments = (ins CIR_BoolType:$cond,
Variadic<CIR_AnyType>:$destOperandsTrue,
Variadic<CIR_AnyType>:$destOperandsFalse,
+ OptionalAttr<AnyDistinctAttr>:$loop_id,
OptionalAttr<CIR_LoopHintAttr>:$loop_hints);
let successors = (successor AnySuccessor:$destTrue, AnySuccessor:$destFalse);
let assemblyFormat = [{
@@ -2278,7 +2294,7 @@ def CIR_BrCondOp : CIR_Op<"brcond", [
$destTrue (`(` $destOperandsTrue^ `:` type($destOperandsTrue) `)`)?
`,`
$destFalse (`(` $destOperandsFalse^ `:` type($destOperandsFalse) `)`)?
- (`loop_hints` $loop_hints^)? attr-dict
+ (`loop_id` $loop_id^)? (`loop_hints` $loop_hints^)? attr-dict
}];
}
@@ -2336,7 +2352,7 @@ def CIR_IndirectBrOp : CIR_Op<"indirect_br", [
//===----------------------------------------------------------------------===//
class CIR_LoopOpBase<string mnemonic> : CIR_Op<mnemonic, [
- LoopOpInterface, NoRegionArguments
+ LoopOpInterface, NoRegionArguments, LoopHintsRequireLoopId
]> {
let extraClassDefinition = [{
void $cppClass::getSuccessorRegions(
@@ -2380,12 +2396,13 @@ class CIR_WhileOpBase<string mnemonic> : CIR_LoopOpBase<mnemonic> {
def CIR_WhileOp : CIR_WhileOpBase<"while"> {
let arguments = (ins OptionalAttr<CIR_CleanupKindAttr>:$cleanupKind,
+ OptionalAttr<AnyDistinctAttr>:$loop_id,
OptionalAttr<CIR_LoopHintAttr>:$loop_hints);
let regions = (region MinSizedRegion<1>:$cond, MinSizedRegion<1>:$body,
MaxSizedRegion<1>:$cleanup);
let assemblyFormat = [{
$cond `do` $body (`cleanup` enum($cleanupKind) $cleanup^)?
- (`loop_hints` $loop_hints^)? attr-dict
+ (`loop_id` $loop_id^)? (`loop_hints` $loop_hints^)? attr-dict
}];
let description = [{
@@ -2461,10 +2478,12 @@ def CIR_WhileOp : CIR_WhileOpBase<"while"> {
}
def CIR_DoWhileOp : CIR_WhileOpBase<"do"> {
- let arguments = (ins OptionalAttr<CIR_LoopHintAttr>:$loop_hints);
+ let arguments = (ins OptionalAttr<AnyDistinctAttr>:$loop_id,
+ OptionalAttr<CIR_LoopHintAttr>:$loop_hints);
let regions = (region MinSizedRegion<1>:$body, MinSizedRegion<1>:$cond);
let assemblyFormat = [{
- $body `while` $cond (`loop_hints` $loop_hints^)? attr-dict
+ $body `while` $cond (`loop_id` $loop_id^)? (`loop_hints` $loop_hints^)?
+ attr-dict
}];
let extraClassDeclaration = [{
@@ -2540,6 +2559,7 @@ def CIR_ForOp : CIR_LoopOpBase<"for"> {
}];
let arguments = (ins OptionalAttr<CIR_CleanupKindAttr>:$cleanupKind,
+ OptionalAttr<AnyDistinctAttr>:$loop_id,
OptionalAttr<CIR_LoopHintAttr>:$loop_hints);
let regions = (region MinSizedRegion<1>:$cond,
MinSizedRegion<1>:$body,
@@ -2550,6 +2570,7 @@ def CIR_ForOp : CIR_LoopOpBase<"for"> {
`body` $body
`step` $step
(`cleanup` enum($cleanupKind) $cleanup^)?
+ (`loop_id` $loop_id^)?
(`loop_hints` $loop_hints^)?
attr-dict
}];
diff --git a/clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.td b/clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.td
index 030269fc043996..51636f7bcf7aba 100644
--- a/clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.td
+++ b/clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.td
@@ -79,6 +79,31 @@ def LoopOpInterface : OpInterface<"LoopOpInterface", [
/*methodBody=*/"",
/*defaultImplementation=*/"return {};"
>,
+ InterfaceMethod<[{
+ Returns the loop's id, a `distinct` attribute that identifies the loop
+ (and, once the loop is flattened, the branches that belong to it), or a
+ null attribute if the loop has none.
+ }],
+ /*retTy=*/"::mlir::DistinctAttr",
+ /*methodName=*/"getLoopIdAttr",
+ /*args=*/(ins),
+ /*methodBody=*/"",
+ /*defaultImplementation=*/"return {};"
+ >,
+ InterfaceMethod<[{
+ Sets the loop's `#cir.loop_hint` attribute.
+ }],
+ /*retTy=*/"void",
+ /*methodName=*/"setLoopHintsAttr",
+ /*args=*/(ins "::cir::LoopHintAttr":$hints)
+ >,
+ InterfaceMethod<[{
+ Sets the loop's id, see `getLoopIdAttr`.
+ }],
+ /*retTy=*/"void",
+ /*methodName=*/"setLoopIdAttr",
+ /*args=*/(ins "::mlir::DistinctAttr":$id)
+ >,
InterfaceMethod<[{
Returns the first region to be executed in the loop.
}],
diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
index 5f308751f6f54e..021148a4739773 100644
--- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
@@ -1064,6 +1064,15 @@ cir::LoopHintAttr CIRGenFunction::getLoopHints(ArrayRef<const Attr *> attrs,
return hints;
}
+static void setLoopHints(cir::LoopOpInterface loopOp,
+ cir::LoopHintAttr loopHints) {
+ if (!loopHints)
+ return;
+ loopOp.setLoopHintsAttr(loopHints);
+ loopOp.setLoopIdAttr(
+ mlir::DistinctAttr::create(mlir::UnitAttr::get(loopOp->getContext())));
+}
+
mlir::LogicalResult
CIRGenFunction::emitCXXForRangeStmt(const CXXForRangeStmt &s,
ArrayRef<const Attr *> forAttrs) {
@@ -1116,7 +1125,7 @@ CIRGenFunction::emitCXXForRangeStmt(const CXXForRangeStmt &s,
loopRes = mlir::failure();
builder.createYield(loc);
});
- forOp.setLoopHintsAttr(loopHints);
+ setLoopHints(forOp, loopHints);
return loopRes;
};
@@ -1221,7 +1230,7 @@ mlir::LogicalResult CIRGenFunction::emitForStmt(const ForStmt &s,
bodyBuilder, stepBuilder);
}
- forOp.setLoopHintsAttr(loopHints);
+ setLoopHints(forOp, loopHints);
return loopRes;
};
@@ -1271,7 +1280,7 @@ mlir::LogicalResult CIRGenFunction::emitDoStmt(const DoStmt &s,
loopRes = mlir::failure();
emitStopPoint(&s);
});
- doWhileOp.setLoopHintsAttr(loopHints);
+ setLoopHints(doWhileOp, loopHints);
return loopRes;
};
@@ -1355,7 +1364,7 @@ CIRGenFunction::emitWhileStmt(const WhileStmt &s,
whileOp = builder.createWhile(getLoc(s.getSourceRange()), condBuilder,
bodyBuilder);
}
- whileOp.setLoopHintsAttr(loopHints);
+ setLoopHints(whileOp, loopHints);
return loopRes;
};
diff --git a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
index c68b6b05a328e1..ca7c749de0a4b5 100644
--- a/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CXXABILowering.cpp
@@ -66,6 +66,11 @@ bool isCXXABIAttributeLegal(const mlir::TypeConverter &tc,
>(attr))
return true;
+ // A distinct attribute (such as the id of a loop) is only an identity, so
+ // there is nothing in it to lower.
+ if (isa<mlir::DistinctAttr>(attr))
+ return true;
+
// Data Member and method are ALWAYS illegal.
if (isa<cir::DataMemberAttr, cir::DataMemberOffsetAttr, cir::MethodAttr>(
attr))
diff --git a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
index 713d235772771a..4215f84319e484 100644
--- a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
@@ -688,10 +688,11 @@ mlir::LogicalResult ItaniumEHLowering::lowerEhInitiate(
}
if (changed) {
builder.setInsertionPoint(op);
- // We shouldn't get any hints here.
- assert(!op.getLoopHintsAttr());
+ // We shouldn't get any loop information here.
+ assert(!op.getLoopIdAttr() && !op.getLoopHintsAttr());
cir::BrOp::create(builder, op.getLoc(), newOperands,
- /*loop_hints=*/nullptr, op.getDest());
+ /*loop_id=*/nullptr, /*loop_hints=*/nullptr,
+ op.getDest());
op.erase();
}
}
diff --git a/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp b/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp
index 0bcdb90571f272..8a54faaee5129b 100644
--- a/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/FlattenCFG.cpp
@@ -40,12 +40,13 @@ namespace {
/// Lowers operations with the terminator trait that have a single successor.
void lowerTerminator(mlir::Operation *op, mlir::Block *dest,
mlir::PatternRewriter &rewriter,
+ mlir::DistinctAttr loopId = {},
cir::LoopHintAttr loopHints = {}) {
assert(op->hasTrait<mlir::OpTrait::IsTerminator>() && "not a terminator");
mlir::OpBuilder::InsertionGuard guard(rewriter);
rewriter.setInsertionPoint(op);
- rewriter.replaceOpWithNewOp<cir::BrOp>(op, mlir::ValueRange{}, loopHints,
- dest);
+ rewriter.replaceOpWithNewOp<cir::BrOp>(op, mlir::ValueRange{}, loopId,
+ loopHints, dest);
}
/// Walks a region while skipping operations of type `Ops`. This ensures the
@@ -113,7 +114,8 @@ rewriteRegionExitToContinue(mlir::PatternRewriter &rewriter,
rewriter.setInsertionPointToEnd(®ion.back());
if (auto yieldOp = mlir::dyn_cast<cir::YieldOp>(terminator)) {
rewriter.replaceOpWithNewOp<cir::BrOp>(
- yieldOp, yieldOp.getArgs(), /*loop_hints=*/nullptr, continueBlock);
+ yieldOp, yieldOp.getArgs(), /*loop_id=*/nullptr, /*loop_hints=*/nullptr,
+ continueBlock);
return mlir::success();
}
if (isNonReturningTerminator(terminator))
@@ -157,9 +159,9 @@ struct CIRIfFlattening : public mlir::OpRewritePattern<cir::IfOp> {
rewriter.setInsertionPointToEnd(thenAfterBody);
if (auto thenYieldOp =
dyn_cast<cir::YieldOp>(thenAfterBody->getTerminator())) {
- rewriter.replaceOpWithNewOp<cir::BrOp>(thenYieldOp, thenYieldOp.getArgs(),
- /*loop_hints=*/nullptr,
- continueBlock);
+ rewriter.replaceOpWithNewOp<cir::BrOp>(
+ thenYieldOp, thenYieldOp.getArgs(),
+ /*loop_id=*/nullptr, /*loop_hints=*/nullptr, continueBlock);
}
rewriter.setInsertionPointToEnd(continueBlock);
@@ -184,8 +186,8 @@ struct CIRIfFlattening : public mlir::OpRewritePattern<cir::IfOp> {
if (auto elseYieldOP =
dyn_cast<cir::YieldOp>(elseAfterBody->getTerminator())) {
rewriter.replaceOpWithNewOp<cir::BrOp>(
- elseYieldOP, elseYieldOP.getArgs(), /*loop_hints=*/nullptr,
- continueBlock);
+ elseYieldOP, elseYieldOP.getArgs(), /*loop_id=*/nullptr,
+ /*loop_hints=*/nullptr, continueBlock);
}
}
@@ -231,16 +233,16 @@ class CIRScopeOpFlattening : public mlir::OpRewritePattern<cir::ScopeOp> {
// Save stack and then branch into the body of the region.
rewriter.setInsertionPointToEnd(currentBlock);
assert(!cir::MissingFeatures::stackSaveOp());
- cir::BrOp::create(rewriter, loc, mlir::ValueRange(), /*loop_hints=*/nullptr,
- beforeBody);
+ cir::BrOp::create(rewriter, loc, mlir::ValueRange(), /*loop_id=*/nullptr,
+ /*loop_hints=*/nullptr, beforeBody);
// Replace the scopeop return with a branch that jumps out of the body.
// Stack restore before leaving the body region.
rewriter.setInsertionPointToEnd(afterBody);
if (auto yieldOp = dyn_cast<cir::YieldOp>(afterBody->getTerminator())) {
- rewriter.replaceOpWithNewOp<cir::BrOp>(yieldOp, yieldOp.getArgs(),
- /*loop_hints=*/nullptr,
- continueBlock);
+ rewriter.replaceOpWithNewOp<cir::BrOp>(
+ yieldOp, yieldOp.getArgs(),
+ /*loop_id=*/nullptr, /*loop_hints=*/nullptr, continueBlock);
}
// Replace the op with values return from the body region.
@@ -259,6 +261,7 @@ class CIRSwitchOpFlattening : public mlir::OpRewritePattern<cir::SwitchOp> {
mlir::Block *destination) const {
rewriter.setInsertionPoint(yieldOp);
rewriter.replaceOpWithNewOp<cir::BrOp>(yieldOp, yieldOp.getOperands(),
+ /*loop_id=*/nullptr,
/*loop_hints=*/nullptr, destination);
}
@@ -434,7 +437,8 @@ class CIRSwitchOpFlattening : public mlir::OpRewritePattern<cir::SwitchOp> {
rewriter.splitBlock(oldBlock, nextOp->getIterator());
rewriter.setInsertionPointToEnd(oldBlock);
cir::BrOp::create(rewriter, nextOp->getLoc(), mlir::ValueRange(),
- /*loop_hints=*/nullptr, newBlock);
+ /*loop_id=*/nullptr, /*loop_hints=*/nullptr,
+ newBlock);
rewriteYieldOp(rewriter, yieldOp, newBlock);
}
}
@@ -518,11 +522,12 @@ class CIRLoopOpInterfaceFlattening
inline void lowerConditionOp(cir::ConditionOp op, mlir::Block *body,
mlir::Block *exit,
mlir::PatternRewriter &rewriter,
+ mlir::DistinctAttr loopId = {},
cir::LoopHintAttr loopHints = {}) const {
mlir::OpBuilder::InsertionGuard guard(rewriter);
rewriter.setInsertionPoint(op);
rewriter.replaceOpWithNewOp<cir::BrCondOp>(
- op, op.getCondition(), mlir::ValueRange{}, mlir::ValueRange{},
+ op, op.getCondition(), mlir::ValueRange{}, mlir::ValueRange{}, loopId,
loopHints, body, exit);
}
@@ -712,8 +717,13 @@ class CIRLoopOpInterfaceFlattening
// We attach the op's loop hints to the ops that break back to the
// 'beginning' of the operation. For a while/for it is the condition block,
- // for a do-while it is the top of the body.
+ // for a do-while it is the top of the body. All of those ops also get the
+ // loop's id, so that they can be told apart from other loops' hints.
cir::LoopHintAttr loopHints = op.getLoopHintsAttr();
+ mlir::DistinctAttr loopId = op.getLoopIdAttr();
+ auto idFor = [&](mlir::Block *target) {
+ return target == firstBlock ? loopId : mlir::DistinctAttr{};
+ };
auto hintsFor = [&](mlir::Block *target) {
return target == firstBlock ? loopHints : cir::LoopHintAttr{};
};
@@ -724,7 +734,8 @@ class CIRLoopOpInterfaceFlattening
// ConditionOp is always the terminator of the last block.
auto conditionOp =
cast<cir::ConditionOp>(op.getCond().back().getTerminator());
- lowerConditionOp(conditionOp, body, exit, rewriter, hintsFor(body));
+ lowerConditionOp(conditionOp, body, exit, rewriter, idFor(body),
+ hintsFor(body));
// TODO(cir): Remove the walks below. It visits operations unnecessarily.
// However, to solve this we would likely need a custom DialectConversion
@@ -736,7 +747,7 @@ class CIRLoopOpInterfaceFlattening
if (!isa<cir::ContinueOp>(op))
return mlir::WalkResult::advance();
- lowerTerminator(op, dest, rewriter, hintsFor(dest));
+ lowerTerminator(op, dest, rewriter, idFor(dest), hintsFor(dest));
return mlir::WalkResult::skip();
});
@@ -754,7 +765,7 @@ class CIRLoopOpInterfaceFlattening
for (mlir::Block &blk : op.getBody().getBlocks()) {
auto bodyYield = dyn_cast<cir::YieldOp>(blk.getTerminator());
if (bodyYield)
- lowerTerminator(bodyYield, dest, rewriter, hintsFor(dest));
+ lowerTerminator(bodyYield, dest, rewriter, idFor(dest), hintsFor(dest));
}
// Lower mandatory step region yield. Like the condition region, the
@@ -763,7 +774,7 @@ class CIRLoopOpInterfaceFlattening
if (step)
lowerTerminator(
cast<cir::YieldOp>(op.maybeGetStep()->back().getTerminator()), cond,
- rewriter, hintsFor(cond));
+ rewriter, idFor(cond), hintsFor(cond));
// Move region contents out of the loop op.
rewriter.inlineRegionBefore(op.getCond(), exit);
@@ -957,7 +968,7 @@ static mlir::Block *buildUnwindBlock(mlir::Block *dest, bool isCleanupOnly,
auto ehInitiate =
cir::EhInitiateOp::create(rewriter, loc, /*cleanup=*/isCleanupOnly);
cir::BrOp::create(rewriter, loc, mlir::ValueRange{ehInitiate.getEhToken()},
- /*loop_hints=*/nullptr, dest);
+ /*loop_id=*/nullptr, /*loop_hints=*/nullptr, dest);
return unwindBlock;
}
@@ -1710,8 +1721,8 @@ class CIRCleanupScopeOpFlattening
mlir::Value ehToken = resumeOp.getEhToken();
rewriter.setInsertionPoint(resumeOp);
rewriter.replaceOpWithNewOp<cir::BrOp>(
- resumeOp, mlir::ValueRange{ehToken}, /*loop_hints=*/nullptr,
- ehCleanupEntry);
+ resumeOp, mlir::ValueRange{ehToken}, /*loop_id=*/nullptr,
+ /*loop_hints=*/nullptr, ehCleanupEntry);
}
}
@@ -2129,8 +2140,8 @@ class CIRTryOpFlattening : public mlir::OpRewritePattern<cir::TryOp> {
mlir::Value ehToken = resumeOp.getEhToken();
rewriter.setInsertionPoint(resumeOp);
rewriter.replaceOpWithNewOp<cir::BrOp>(
- resumeOp, mlir::ValueRange{ehToken}, /*loop_hints=*/nullptr,
- dispatchBlock);
+ resumeOp, mlir::ValueRange{ehToken}, /*loop_id=*/nullptr,
+ /*loop_hints=*/nullptr, dispatchBlock);
}
// Finally, erase the original try op ----
diff --git a/clang/test/CIR/CodeGen/loop-hints-stds.cpp b/clang/test/CIR/CodeGen/loop-hints-stds.cpp
index b67b155f6170b3..ea4f3c2bb68b76 100644
--- a/clang/test/CIR/CodeGen/loop-hints-stds.cpp
+++ b/clang/test/CIR/CodeGen/loop-hints-stds.cpp
@@ -13,31 +13,31 @@ void hints(int n) {
#pragma GCC unroll 4
for (int i = 0; i < n; ++i)
use(i);
-// CXX17: } loop_hints < must_progress unroll_count = 4>
-// CXX98: } loop_hints < unroll_count = 4>
+// CXX17: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll_count = 4>
+// CXX98: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < unroll_count = 4>
#pragma clang loop unroll(disable)
for (int i = 0; i < n; ++i)
use(i);
-// CXX17: } loop_hints < must_progress unroll = disable>
-// CXX98: } loop_hints < unroll = disable>
+// CXX17: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable>
+// CXX98: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < unroll = disable>
#pragma clang loop unroll(enable)
for (int i = 0; i < n; ++i)
use(i);
-// CXX17: } loop_hints < must_progress unroll = enable>
-// CXX98: } loop_hints < unroll = enable>
+// CXX17: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = enable>
+// CXX98: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < unroll = enable>
#pragma clang loop interleave(enable)
for (int i = 0; i < n; ++i)
use(i);
-// CXX17: } loop_hints < must_progress vectorize_enable>
-// CXX98: } loop_hints < vectorize_enable>
+// CXX17: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_enable>
+// CXX98: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < vectorize_enable>
#pragma clang loop vectorize_width(4) unroll_count(2)
for (int i = 0; i < n; ++i)
use(i);
-// CXX17: } loop_hints < must_progress vectorize_width = 4 vectorize_scalable = false unroll_count = 2>
-// CXX98: } loop_hints < vectorize_width = 4 vectorize_scalable = false unroll_count = 2>
+// CXX17: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_width = 4 vectorize_scalable = false unroll_count = 2>
+// CXX98: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < vectorize_width = 4 vectorize_scalable = false unroll_count = 2>
for (int i = 0; i < n; ++i)
use(i);
-// CXX17: } loop_hints < must_progress>
+// CXX17: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
// CXX98-NOT: loop_hints
// CIR: cir.return
@@ -51,11 +51,11 @@ void nested(int n) {
#pragma clang loop vectorize(enable)
for (int j = 0; j < n; ++j)
use(j);
-// CXX17: } loop_hints < must_progress vectorize_enable>
-// CXX98: } loop_hints < vectorize_enable>
+// CXX17: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_enable>
+// CXX98: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < vectorize_enable>
}
-// CXX17: } loop_hints < must_progress unroll = full>
-// CXX98: } loop_hints < unroll = full>
+// CXX17: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = full>
+// CXX98: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < unroll = full>
}
@@ -68,8 +68,8 @@ template <typename T> void tmpl(T n) {
void instantiate() {
tmpl(4);
// CIR-LABEL: cir.func {{.*}} @_Z4tmplIiEvT_
-// CXX17: } loop_hints < must_progress unroll_count = 3>
-// CXX98: } loop_hints < unroll_count = 3>
+// CXX17: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll_count = 3>
+// CXX98: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < unroll_count = 3>
auto l = [](int n) {
#pragma nounroll
do {
@@ -78,7 +78,7 @@ void instantiate() {
};
l(2);
// CIR-LABEL: cir.func {{.*}} @_ZZ11instantiatevENK3$_0clEi
-// CXX17: } loop_hints < must_progress unroll = disable>
-// CXX98: } loop_hints < unroll = disable>
+// CXX17: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable>
+// CXX98: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < unroll = disable>
}
diff --git a/clang/test/CIR/CodeGen/loop-hints.c b/clang/test/CIR/CodeGen/loop-hints.c
index 7dbbdaf84311ba..356345e4ed445f 100644
--- a/clang/test/CIR/CodeGen/loop-hints.c
+++ b/clang/test/CIR/CodeGen/loop-hints.c
@@ -19,38 +19,40 @@ void f(int n) {
for (int i = 0; i < n; ++i)
use(i);
// C99-NOT: loop_hints
- // C11: } loop_hints < must_progress>
- // FINITE: } loop_hints < must_progress>
+ // C11: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
+ // FINITE: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
// NOFINITE-NOT: loop_hints
// CIR: cir.while
while (n)
--n;
- // C11: } loop_hints < must_progress>
- // FINITE: } loop_hints < must_progress>
+ // C11: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
+ // FINITE: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
// CIR: cir.do
do {
--n;
} while (n > 0);
- // C11: } loop_hints < must_progress>
- // FINITE: } loop_hints < must_progress>
+ // C11: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
+ // FINITE: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
// With a constant condition, only -ffinite-loops marks the loops, unless they
// are trivially empty.
// CIR: cir.while
while (1)
use(n);
- // FINITE: } loop_hints < must_progress>
+ // FINITE: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
// CIR: cir.for
for (;;)
use(n);
- // FINITE: } loop_hints < must_progress>
+ // FINITE: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
// CIR: cir.while
while (1) {
}
+ // A loop without any hints doesn't have a loop id either.
+ // CIR-NOT: loop_id
// CIR-NOT: loop_hints
// CIR: cir.return
}
diff --git a/clang/test/CIR/CodeGen/loop-hints.cpp b/clang/test/CIR/CodeGen/loop-hints.cpp
index dd134cb8a31c0f..b1ec0898f762f3 100644
--- a/clang/test/CIR/CodeGen/loop-hints.cpp
+++ b/clang/test/CIR/CodeGen/loop-hints.cpp
@@ -15,8 +15,8 @@ void must_progress_for(int n) {
// BEFORE: cir.for : cond {
// BEFORE: } body {
// BEFORE: } step {
- // BEFORE-NOOPT: } loop_hints < must_progress>
- // BEFORE-OPT: } loop_hints < must_progress unroll = disable code_align = 32>
+ // BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
+ // BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable code_align = 32>
// BEFORE: cir.return
// AFTER: cir.br ^[[INIT:.*]]{{$}}
@@ -41,7 +41,7 @@ void must_progress_for(int n) {
// AFTER-NEXT: cir.load
// AFTER-NEXT: cir.inc
// AFTER-NEXT: cir.store
- // AFTER-NEXT: cir.br ^[[COND]] loop_hints < must_progress>
+ // AFTER-NEXT: cir.br ^[[COND]] loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
// AFTER: ^[[END]]:
// Note: There is a dead-branch here happening too, omitted for brevity.
@@ -55,8 +55,8 @@ void must_progress_while(int n) {
// BEFORE: cir.while {
// BEFORE: } do {
- // BEFORE-NOOPT: } loop_hints < must_progress>
- // BEFORE-OPT: } loop_hints < must_progress unroll = disable code_align = 32>
+ // BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
+ // BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable code_align = 32>
// BEFORE: cir.return
// AFTER: cir.br ^[[START:.*]]{{$}}
@@ -74,7 +74,7 @@ void must_progress_while(int n) {
// AFTER: ^[[BODY]]:
// AFTER-NEXT: cir.load
// AFTER-NEXT: cir.call @_Z3usei
- // AFTER-NEXT: cir.br ^[[COND]] loop_hints < must_progress>
+ // AFTER-NEXT: cir.br ^[[COND]] loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
// AFTER: ^[[END]]:
// Note: There is a dead-branch here happening too, omitted for brevity.
@@ -89,8 +89,8 @@ void must_progress_do_while(int n) {
} while (n > 0);
// BEFORE: cir.do {
// BEFORE: } while {
- // BEFORE-NOOPT: } loop_hints < must_progress>
- // BEFORE-OPT: } loop_hints < must_progress unroll = disable code_align = 32>
+ // BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
+ // BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable code_align = 32>
// BEFORE: cir.return
// AFTER: cir.br ^[[START:.*]]{{$}}
@@ -102,7 +102,7 @@ void must_progress_do_while(int n) {
// AFTER-NEXT: cir.load
// AFTER-NEXT: cir.const #cir.int<0> : !s32i
// AFTER-NEXT: %[[CMP:.*]] = cir.cmp
- // AFTER-NEXT: cir.brcond %[[CMP]] ^[[NEXT_ITR:.*]], ^[[END:.*]] loop_hints < must_progress>
+ // AFTER-NEXT: cir.brcond %[[CMP]] ^[[NEXT_ITR:.*]], ^[[END:.*]] loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
// AFTER: ^[[NEXT_ITR]]:
// AFTER-NEXT: cir.br ^[[BODY:.*]]{{$}}
@@ -175,7 +175,7 @@ void must_progress_inf_for() {
// BEFORE: } body {
// BEFORE: } step {
// BEFORE-NOOPT: } loc
- // BEFORE-OPT: } loop_hints < unroll = disable code_align = 32>
+ // BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < unroll = disable code_align = 32>
// BEFORE: } loc
// BEFORE: cir.return
@@ -209,8 +209,8 @@ void continue_break_in_for(int n) {
// BEFORE: cir.for : cond {
// BEFORE: } body {
// BEFORE: } step {
- // BEFORE-NOOPT: } loop_hints < must_progress>
- // BEFORE-OPT: } loop_hints < must_progress unroll = disable code_align = 32>
+ // BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
+ // BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable code_align = 32>
// BEFORE: cir.return
// AFTER: cir.br ^[[INIT:.*]]{{$}}
@@ -272,7 +272,7 @@ void continue_break_in_for(int n) {
// AFTER-NEXT: cir.load
// AFTER-NEXT: cir.inc
// AFTER-NEXT: cir.store
- // AFTER-NEXT: cir.br ^[[COND]] loop_hints < must_progress>
+ // AFTER-NEXT: cir.br ^[[COND]] loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
// AFTER: ^[[END]]:
// Note: There is a dead-branch here happening too, omitted for brevity.
@@ -294,8 +294,8 @@ void continue_in_while(int n) {
// BEFORE: } loc
// BEFORE: } loc
// BEFORE: } loc
- // BEFORE-NOOPT: } loop_hints < must_progress>
- // BEFORE-OPT: } loop_hints < must_progress unroll = disable code_align = 32>
+ // BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
+ // BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable code_align = 32>
// BEFORE: cir.return
// AFTER: cir.br ^[[START:.*]]{{$}}
@@ -323,7 +323,7 @@ void continue_in_while(int n) {
// AFTER-NEXT: cir.brcond %[[AND]] ^[[CONTINUE:.*]], ^[[NO_CONTINUE:.*]]{{$}}
// AFTER: ^[[CONTINUE]]:
- // AFTER-NEXT: cir.br ^[[COND]] loop_hints < must_progress>
+ // AFTER-NEXT: cir.br ^[[COND]] loop_id distinct{{\[}}[[LOOP_ID:[0-9]+]]{{\]}}<> loop_hints < must_progress>
// AFTER: ^[[NO_CONTINUE]]:
// AFTER-NEXT: cir.br ^[[BODY_REST:.*]]{{$}}
@@ -334,7 +334,7 @@ void continue_in_while(int n) {
// AFTER-NEXT: cir.br ^[[NEXT_ITR:.*]]{{$}}
// AFTER: ^[[NEXT_ITR]]:
- // AFTER-NEXT: cir.br ^[[COND]] loop_hints < must_progress>
+ // AFTER-NEXT: cir.br ^[[COND]] loop_id distinct{{\[}}[[LOOP_ID]]{{\]}}<> loop_hints < must_progress>
// AFTER: ^[[END]]:
// Note: There is a dead-branch here happening too, omitted for brevity.
@@ -351,8 +351,8 @@ void continue_in_do_while(int n) {
// BEFORE: cir.do {
// BEFORE: } while {
- // BEFORE-NOOPT: } loop_hints < must_progress>
- // BEFORE-OPT:} loop_hints < must_progress unroll = disable code_align = 32>
+ // BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
+ // BEFORE-OPT:} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable code_align = 32>
// BEFORE: cir.return
// AFTER: cir.br ^[[START]]
@@ -365,7 +365,7 @@ void continue_in_do_while(int n) {
// AFTER-NEXT: cir.dec nsw
// AFTER-NEXT: cir.store
// AFTER-NEXT: %[[AFTER_DEC:.*]] = cir.cast int_to_bool
- // AFTER-NEXT: cir.brcond %[[AFTER_DEC]] ^[[BODY_START:.*]], ^[[END:.*]] loop_hints < must_progress>
+ // AFTER-NEXT: cir.brcond %[[AFTER_DEC]] ^[[BODY_START:.*]], ^[[END:.*]] loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
// AFTER: ^[[BODY_START]]:
// AFTER-NEXT: cir.br ^[[BODY_START_2:.*]]{{$}}
@@ -405,129 +405,129 @@ void pragmas(int n) {
#pragma clang loop unroll_count(4) vectorize(enable) interleave_count(2)
for (int i = 0; i < n; ++i)
use(i);
-// BEFORE-NOOPT: } loop_hints < must_progress vectorize_enable interleave_count = 2 unroll_count = 4>
-// BEFORE-OPT: } loop_hints < must_progress vectorize_enable interleave_count = 2 unroll_count = 4 code_align = 32>
-// AFTER: cir.br ^{{.*}} loop_hints < must_progress vectorize_enable interleave_count = 2 unroll_count = 4>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_enable interleave_count = 2 unroll_count = 4>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_enable interleave_count = 2 unroll_count = 4 code_align = 32>
+// AFTER: cir.br ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_enable interleave_count = 2 unroll_count = 4>
#pragma nounroll
while (n)
--n;
-// BEFORE-NOOPT: } loop_hints < must_progress unroll = disable>
-// BEFORE-OPT: } loop_hints < must_progress unroll = disable code_align = 32>
-// AFTER: cir.br ^{{.*}} loop_hints < must_progress unroll = disable>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable code_align = 32>
+// AFTER: cir.br ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable>
#pragma unroll
do {
--n;
} while (n > 0);
-// BEFORE-NOOPT: } loop_hints < must_progress unroll = enable>
-// BEFORE-OPT: } loop_hints < must_progress unroll = enable code_align = 32>
-// AFTER: cir.brcond %{{.*}} ^{{.*}}, ^{{.*}} loop_hints < must_progress unroll = enable>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = enable>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = enable code_align = 32>
+// AFTER: cir.brcond %{{.*}} ^{{.*}}, ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = enable>
#pragma unroll 8
for (int i = 0; i < n; ++i)
use(i);
-// BEFORE-NOOPT: } loop_hints < must_progress unroll_count = 8>
-// BEFORE-OPT: } loop_hints < must_progress unroll_count = 8 code_align = 32>
-// AFTER: cir.br ^{{.*}} loop_hints < must_progress unroll_count = 8>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll_count = 8>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll_count = 8 code_align = 32>
+// AFTER: cir.br ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll_count = 8>
#pragma clang loop unroll(full)
for (int i = 0; i < 4; ++i)
use(i);
-// BEFORE-NOOPT: } loop_hints < must_progress unroll = full>
-// BEFORE-OPT: } loop_hints < must_progress unroll = full code_align = 32>
-// AFTER: cir.br ^{{.*}} loop_hints < must_progress unroll = full>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = full>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = full code_align = 32>
+// AFTER: cir.br ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = full>
#pragma clang loop vectorize(disable) interleave(disable)
for (int i = 0; i < n; ++i)
use(i);
-// BEFORE-NOOPT: } loop_hints < must_progress vectorize_width = 1 vectorize_scalable = false interleave_count = 1>
-// BEFORE-OPT: } loop_hints < must_progress vectorize_width = 1 vectorize_scalable = false interleave_count = 1 unroll = disable code_align = 32>
-// AFTER: cir.br ^{{.*}} loop_hints < must_progress vectorize_width = 1 vectorize_scalable = false interleave_count = 1>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_width = 1 vectorize_scalable = false interleave_count = 1>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_width = 1 vectorize_scalable = false interleave_count = 1 unroll = disable code_align = 32>
+// AFTER: cir.br ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_width = 1 vectorize_scalable = false interleave_count = 1>
#pragma clang loop vectorize_width(8)
for (int x : arr)
use(x);
-// BEFORE-NOOPT: } loop_hints < vectorize_width = 8 vectorize_scalable = false>
-// BEFORE-OPT: } loop_hints < vectorize_width = 8 vectorize_scalable = false unroll = disable code_align = 32>
-// AFTER: cir.br ^{{.*}} loop_hints < vectorize_width = 8 vectorize_scalable = false>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < vectorize_width = 8 vectorize_scalable = false>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < vectorize_width = 8 vectorize_scalable = false unroll = disable code_align = 32>
+// AFTER: cir.br ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < vectorize_width = 8 vectorize_scalable = false>
#pragma clang loop vectorize_width(4, scalable)
for (int i = 0; i < n; ++i)
use(i);
-// BEFORE-NOOPT: } loop_hints < must_progress vectorize_width = 4 vectorize_scalable = true>
-// BEFORE-OPT: } loop_hints < must_progress vectorize_width = 4 vectorize_scalable = true unroll = disable code_align = 32>
-// AFTER: cir.br ^{{.*}} loop_hints < must_progress vectorize_width = 4 vectorize_scalable = true>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_width = 4 vectorize_scalable = true>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_width = 4 vectorize_scalable = true unroll = disable code_align = 32>
+// AFTER: cir.br ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_width = 4 vectorize_scalable = true>
#pragma clang loop vectorize_width(4, fixed)
for (int i = 0; i < n; ++i)
use(i);
-// BEFORE-NOOPT: } loop_hints < must_progress vectorize_width = 4 vectorize_scalable = false>
-// BEFORE-OPT: } loop_hints < must_progress vectorize_width = 4 vectorize_scalable = false unroll = disable code_align = 32>
-// AFTER: cir.br ^{{.*}} loop_hints < must_progress vectorize_width = 4 vectorize_scalable = false>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_width = 4 vectorize_scalable = false>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_width = 4 vectorize_scalable = false unroll = disable code_align = 32>
+// AFTER: cir.br ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_width = 4 vectorize_scalable = false>
#pragma clang loop vectorize(assume_safety)
for (int i = 0; i < n; ++i)
use(i);
-// BEFORE-NOOPT: } loop_hints < must_progress vectorize_enable parallel>
-// BEFORE-OPT: } loop_hints < must_progress vectorize_enable unroll = disable parallel code_align = 32>
-// AFTER: cir.br ^{{.*}} loop_hints < must_progress vectorize_enable parallel>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_enable parallel>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_enable unroll = disable parallel code_align = 32>
+// AFTER: cir.br ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_enable parallel>
#pragma clang loop vectorize_predicate(enable)
for (int i = 0; i < n; ++i)
use(i);
-// BEFORE-NOOPT: } loop_hints < must_progress vectorize_predicate = true>
-// BEFORE-OPT: } loop_hints < must_progress vectorize_predicate = true unroll = disable code_align = 32>
-// AFTER: cir.br ^{{.*}} loop_hints < must_progress vectorize_predicate = true>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_predicate = true>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_predicate = true unroll = disable code_align = 32>
+// AFTER: cir.br ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_predicate = true>
#pragma clang loop vectorize_predicate(disable)
for (int i = 0; i < n; ++i)
use(i);
-// BEFORE-NOOPT: } loop_hints < must_progress vectorize_predicate = false>
-// BEFORE-OPT: } loop_hints < must_progress vectorize_predicate = false unroll = disable code_align = 32>
-// AFTER: cir.br ^{{.*}} loop_hints < must_progress vectorize_predicate = false>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_predicate = false>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_predicate = false unroll = disable code_align = 32>
+// AFTER: cir.br ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_predicate = false>
#pragma clang loop distribute(enable)
for (int i = 0; i < n; ++i)
use(i);
-// BEFORE-NOOPT: } loop_hints < must_progress distribute = true>
-// BEFORE-OPT: } loop_hints < must_progress unroll = disable distribute = true code_align = 32>
-// AFTER: cir.br ^{{.*}} loop_hints < must_progress distribute = true>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress distribute = true>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable distribute = true code_align = 32>
+// AFTER: cir.br ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress distribute = true>
#pragma clang loop distribute(disable)
for (int i = 0; i < n; ++i)
use(i);
-// BEFORE-NOOPT: } loop_hints < must_progress distribute = false>
-// BEFORE-OPT: } loop_hints < must_progress unroll = disable distribute = false code_align = 32>
-// AFTER: cir.br ^{{.*}} loop_hints < must_progress distribute = false>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress distribute = false>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable distribute = false code_align = 32>
+// AFTER: cir.br ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress distribute = false>
#pragma unroll_and_jam
for (int i = 0; i < n; ++i)
use(i);
-// BEFORE-NOOPT: } loop_hints < must_progress unroll_and_jam = enable>
-// BEFORE-OPT: } loop_hints < must_progress unroll = disable unroll_and_jam = enable code_align = 32>
-// AFTER: cir.br ^{{.*}} loop_hints < must_progress unroll_and_jam = enable>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll_and_jam = enable>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable unroll_and_jam = enable code_align = 32>
+// AFTER: cir.br ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll_and_jam = enable>
#pragma nounroll_and_jam
for (int i = 0; i < n; ++i)
use(i);
-// BEFORE-NOOPT: } loop_hints < must_progress unroll_and_jam = disable>
-// BEFORE-OPT: } loop_hints < must_progress unroll = disable unroll_and_jam = disable code_align = 32>
-// AFTER: cir.br ^{{.*}} loop_hints < must_progress unroll_and_jam = disable>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll_and_jam = disable>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable unroll_and_jam = disable code_align = 32>
+// AFTER: cir.br ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll_and_jam = disable>
#pragma unroll_and_jam(4)
for (int i = 0; i < n; ++i)
use(i);
-// BEFORE-NOOPT: } loop_hints < must_progress unroll_and_jam_count = 4>
-// BEFORE-OPT: } loop_hints < must_progress unroll = disable unroll_and_jam_count = 4 code_align = 32>
-// AFTER: cir.br ^{{.*}} loop_hints < must_progress unroll_and_jam_count = 4>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll_and_jam_count = 4>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable unroll_and_jam_count = 4 code_align = 32>
+// AFTER: cir.br ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll_and_jam_count = 4>
#pragma clang loop pipeline(disable)
for (int i = 0; i < n; ++i)
use(i);
-// BEFORE-NOOPT: } loop_hints < must_progress pipeline_disabled>
-// BEFORE-OPT: } loop_hints < must_progress unroll = disable pipeline_disabled code_align = 32>
-// AFTER: cir.br ^{{.*}} loop_hints < must_progress pipeline_disabled>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress pipeline_disabled>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable pipeline_disabled code_align = 32>
+// AFTER: cir.br ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress pipeline_disabled>
#pragma clang loop pipeline_initiation_interval(3)
for (int i = 0; i < n; ++i)
use(i);
-// BEFORE-NOOPT: } loop_hints < must_progress pipeline_initiation_interval = 3>
-// BEFORE-OPT: } loop_hints < must_progress unroll = disable pipeline_initiation_interval = 3 code_align = 32>
-// AFTER: cir.br ^{{.*}} loop_hints < must_progress pipeline_initiation_interval = 3>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress pipeline_initiation_interval = 3>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable pipeline_initiation_interval = 3 code_align = 32>
+// AFTER: cir.br ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress pipeline_initiation_interval = 3>
#pragma clang loop licm(disable)
for (int i = 0; i < n; ++i)
use(i);
-// BEFORE-NOOPT: } loop_hints < must_progress licm_disabled>
-// BEFORE-OPT: } loop_hints < must_progress unroll = disable licm_disabled code_align = 32>
-// AFTER: cir.br ^{{.*}} loop_hints < must_progress licm_disabled>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress licm_disabled>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable licm_disabled code_align = 32>
+// AFTER: cir.br ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress licm_disabled>
[[clang::code_align(16)]]
for (int i = 0; i < n; ++i)
use(i);
-// BEFORE-NOOPT: } loop_hints < must_progress code_align = 16>
-// BEFORE-OPT: } loop_hints < must_progress unroll = disable code_align = 16>
-// AFTER: cir.br ^{{.*}} loop_hints < must_progress code_align = 16>
+// BEFORE-NOOPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress code_align = 16>
+// BEFORE-OPT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable code_align = 16>
+// AFTER: cir.br ^{{.*}} loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress code_align = 16>
}
diff --git a/clang/test/CIR/CodeGenHLSL/loop-hints.hlsl b/clang/test/CIR/CodeGenHLSL/loop-hints.hlsl
index 4aa683b00dd5ec..ac438dec826aa8 100644
--- a/clang/test/CIR/CodeGenHLSL/loop-hints.hlsl
+++ b/clang/test/CIR/CodeGenHLSL/loop-hints.hlsl
@@ -11,6 +11,6 @@ void use(int);
}
// CHECK-LABEL: cir.func {{.*}} @_Z4mainv
-// CHECK: } loop_hints < must_progress unroll = enable>
-// CHECK: } loop_hints < must_progress unroll_count = 4>
-// CHECK: } loop_hints < must_progress unroll = disable>
+// CHECK: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = enable>
+// CHECK: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll_count = 4>
+// CHECK: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress unroll = disable>
diff --git a/clang/test/CIR/CodeGenOpenACC/loop.cpp b/clang/test/CIR/CodeGenOpenACC/loop.cpp
index b0feb82387a501..d472b2e325ff92 100644
--- a/clang/test/CIR/CodeGenOpenACC/loop.cpp
+++ b/clang/test/CIR/CodeGenOpenACC/loop.cpp
@@ -26,7 +26,7 @@ extern "C" void acc_loop(int *A, int *B, int *C, int N) {
// CHECK-NEXT: cir.yield
// CHECK-NEXT: } step {
// CHECK: cir.yield
- // CHECK-NEXT: } loop_hints < must_progress> loc
+ // CHECK-NEXT: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress> loc
// CHECK-NEXT: } loc
// CHECK-NEXT: acc.yield
// CHECK-NEXT: } independent loc
diff --git a/clang/test/CIR/CodeGenOpenCL/loop-hints.cl b/clang/test/CIR/CodeGenOpenCL/loop-hints.cl
index dcf1ec86bc68e1..7a63e9e9646d7f 100644
--- a/clang/test/CIR/CodeGenOpenCL/loop-hints.cl
+++ b/clang/test/CIR/CodeGenOpenCL/loop-hints.cl
@@ -13,6 +13,6 @@ kernel void k(int n) {
}
// CHECK-LABEL: cir.func {{.*}} @k
-// CHECK: } loop_hints < unroll = enable>
-// CHECK: } loop_hints < unroll = disable>
-// CHECK: } loop_hints < unroll_count = 8>
+// CHECK: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < unroll = enable>
+// CHECK: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < unroll = disable>
+// CHECK: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < unroll_count = 8>
diff --git a/clang/test/CIR/IR/invalid-loop-hints.cir b/clang/test/CIR/IR/invalid-loop-hints.cir
index 2f09d8a26d96e1..1eb49060507238 100644
--- a/clang/test/CIR/IR/invalid-loop-hints.cir
+++ b/clang/test/CIR/IR/invalid-loop-hints.cir
@@ -71,3 +71,71 @@ cir.func @repeated(%c: !cir.bool) {
} loop_hints < must_progress must_progress>
cir.return
}
+
+// -----
+
+cir.func @br_hints_without_id() {
+ // expected-error at +1 {{failed to verify that 'loop_hints' requires a 'loop_id'}}
+ cir.br ^bb1 loop_hints < must_progress>
+^bb1:
+ cir.return
+}
+
+// -----
+
+cir.func @brcond_hints_without_id(%c: !cir.bool) {
+ // expected-error at +1 {{failed to verify that 'loop_hints' requires a 'loop_id'}}
+ cir.brcond %c ^bb1, ^bb1 loop_hints < must_progress>
+^bb1:
+ cir.return
+}
+
+// -----
+
+cir.func @while_hints_without_id(%c: !cir.bool) {
+ // expected-error at +1 {{failed to verify that 'loop_hints' requires a 'loop_id'}}
+ cir.while {
+ cir.condition(%c)
+ } do {
+ cir.yield
+ } loop_hints < must_progress>
+ cir.return
+}
+
+// -----
+
+cir.func @do_hints_without_id(%c: !cir.bool) {
+ // expected-error at +1 {{failed to verify that 'loop_hints' requires a 'loop_id'}}
+ cir.do {
+ cir.yield
+ } while {
+ cir.condition(%c)
+ } loop_hints < must_progress>
+ cir.return
+}
+
+// -----
+
+cir.func @for_hints_without_id(%c: !cir.bool) {
+ // expected-error at +1 {{failed to verify that 'loop_hints' requires a 'loop_id'}}
+ cir.for : cond {
+ cir.condition(%c)
+ } body {
+ cir.yield
+ } step {
+ cir.yield
+ } loop_hints < must_progress>
+ cir.return
+}
+
+// -----
+
+cir.func @loop_id_not_distinct(%c: !cir.bool) {
+ cir.while {
+ cir.condition(%c)
+ } do {
+ cir.yield
+ // expected-error at +1 {{invalid kind of attribute specified}}
+ } loop_id 4 : i32
+ cir.return
+}
diff --git a/clang/test/CIR/IR/loop-hints.cir b/clang/test/CIR/IR/loop-hints.cir
index 3653d7d1b172be..c0ce4726b260d6 100644
--- a/clang/test/CIR/IR/loop-hints.cir
+++ b/clang/test/CIR/IR/loop-hints.cir
@@ -6,16 +6,16 @@ cir.func @loops(%c: !cir.bool) {
cir.condition(%c)
} do {
cir.yield
- // CHECK: } loop_hints < must_progress>
- } loop_hints < must_progress>
+ // CHECK: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
+ } loop_id distinct[2]<> loop_hints < must_progress>
// CHECK: cir.do {
cir.do {
cir.yield
} while {
cir.condition(%c)
- // CHECK: } loop_hints <>
- } loop_hints <>
+ // CHECK: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints <>
+ } loop_id distinct[3]<> loop_hints <>
// CHECK: cir.for : cond {
cir.for : cond {
@@ -24,8 +24,8 @@ cir.func @loops(%c: !cir.bool) {
cir.yield
} step {
cir.yield
- // CHECK: } loop_hints < must_progress vectorize_enable vectorize_width = 4 vectorize_scalable = true vectorize_predicate = false interleave_count = 2 unroll = enable unroll_count = 8 distribute = true>
- } loop_hints < must_progress vectorize_enable vectorize_width = 4 vectorize_scalable = true vectorize_predicate = false interleave_count = 2 unroll = enable unroll_count = 8 distribute = true>
+ // CHECK: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress vectorize_enable vectorize_width = 4 vectorize_scalable = true vectorize_predicate = false interleave_count = 2 unroll = enable unroll_count = 8 distribute = true>
+ } loop_id distinct[4]<> loop_hints < must_progress vectorize_enable vectorize_width = 4 vectorize_scalable = true vectorize_predicate = false interleave_count = 2 unroll = enable unroll_count = 8 distribute = true>
// CHECK: cir.for : cond {
cir.for : cond {
@@ -34,7 +34,45 @@ cir.func @loops(%c: !cir.bool) {
cir.yield
} step {
cir.yield
- // CHECK: } loop_hints < unroll = disable unroll_and_jam = full unroll_and_jam_count = 2 pipeline_disabled pipeline_initiation_interval = 3 licm_disabled parallel code_align = 64>
- } loop_hints < unroll = disable unroll_and_jam = full unroll_and_jam_count = 2 pipeline_disabled pipeline_initiation_interval = 3 licm_disabled parallel code_align = 64>
+ // CHECK: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < unroll = disable unroll_and_jam = full unroll_and_jam_count = 2 pipeline_disabled pipeline_initiation_interval = 3 licm_disabled parallel code_align = 64>
+ } loop_id distinct[5]<> loop_hints < unroll = disable unroll_and_jam = full unroll_and_jam_count = 2 pipeline_disabled pipeline_initiation_interval = 3 licm_disabled parallel code_align = 64>
+
+ // A loop can have a loop_id without any loop_hints.
+ // CHECK: cir.while {
+ cir.while {
+ cir.condition(%c)
+ } do {
+ cir.yield
+ // CHECK: } loop_id distinct{{\[[0-9]+\]}}<>{{$}}
+ } loop_id distinct[6]<>
+
+ // CHECK: cir.for : cond {
+ cir.for : cond {
+ cir.condition(%c)
+ } body {
+ cir.yield
+ } step {
+ cir.yield
+ // CHECK: } cleanup normal {
+ } cleanup normal {
+ cir.yield
+ // CHECK: } loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
+ } loop_id distinct[7]<> loop_hints < must_progress>
+ cir.return
+}
+
+cir.func @branches(%c: !cir.bool) {
+ // CHECK: cir.br ^bb1 loop_id distinct[[[ID0:[0-9]+]]]<> loop_hints < must_progress unroll_count = 4>
+ cir.br ^bb1 loop_id distinct[0]<> loop_hints < must_progress unroll_count = 4>
+^bb1:
+ // CHECK: cir.brcond %{{.*}} ^bb1, ^bb2 loop_id distinct[[[ID0]]]<> loop_hints < must_progress unroll_count = 4>
+ cir.brcond %c ^bb1, ^bb2 loop_id distinct[0]<> loop_hints < must_progress unroll_count = 4>
+^bb2:
+ // CHECK: cir.br ^bb3 loop_id distinct[[[ID1:[0-9]+]]]<>{{$}}
+ cir.br ^bb3 loop_id distinct[1]<>
+^bb3:
+ // CHECK: cir.brcond %{{.*}} ^bb3, ^bb4 loop_id distinct[[[ID1]]]<>{{$}}
+ cir.brcond %c ^bb3, ^bb4 loop_id distinct[1]<>
+^bb4:
cir.return
}
diff --git a/clang/test/CIR/Transforms/flatten-loop-cleanup.cir b/clang/test/CIR/Transforms/flatten-loop-cleanup.cir
index 694d8feaf1eb9a..5dbbc51337568d 100644
--- a/clang/test/CIR/Transforms/flatten-loop-cleanup.cir
+++ b/clang/test/CIR/Transforms/flatten-loop-cleanup.cir
@@ -34,7 +34,7 @@ module {
} cleanup normal {
cir.call @dtor(%s) nothrow : (!cir.ptr<!rec_S>) -> ()
cir.yield
- } loop_hints < must_progress>
+ } loop_id distinct[0]<> loop_hints < must_progress>
cir.return
}
@@ -72,7 +72,7 @@ module {
// CHECK: ^[[UNREACHABLE]]:
// CHECK: cir.unreachable
// CHECK: ^[[LATCH]]:
- // CHECK-NEXT: cir.br ^[[HEADER]] loop_hints < must_progress>
+ // CHECK-NEXT: cir.br ^[[HEADER]] loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
// CHECK: ^[[EXIT]]:
// CHECK: cir.return
@@ -91,7 +91,7 @@ module {
} cleanup normal {
cir.call @dtor(%s) nothrow : (!cir.ptr<!rec_S>) -> ()
cir.yield
- } loop_hints < must_progress>
+ } loop_id distinct[1]<> loop_hints < must_progress>
cir.return
}
@@ -134,7 +134,7 @@ module {
// CHECK: ^[[FORWARD]]:
// CHECK: cir.br ^[[LATCH:bb[0-9]+]]
// CHECK: ^[[LATCH]]:
- // CHECK-NEXT: cir.br ^[[HEADER]] loop_hints < must_progress>
+ // CHECK-NEXT: cir.br ^[[HEADER]] loop_id distinct{{\[[0-9]+\]}}<> loop_hints < must_progress>
// CHECK: ^[[EXIT]]:
// CHECK: cir.return
diff --git a/clang/test/CIR/Transforms/flatten-loop-id.cir b/clang/test/CIR/Transforms/flatten-loop-id.cir
new file mode 100644
index 00000000000000..9ff6ff5653e952
--- /dev/null
+++ b/clang/test/CIR/Transforms/flatten-loop-id.cir
@@ -0,0 +1,131 @@
+// RUN: cir-opt %s -cir-flatten-cfg -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s
+
+module {
+ cir.func private @body()
+
+ // CHECK-LABEL: cir.func @for_loop
+ // The step branches back to the condition.
+ // CHECK: cir.br ^[[COND:bb[0-9]+]]
+ // CHECK: ^[[COND]]:
+ // CHECK: cir.brcond {{.*}} ^[[BODY:bb[0-9]+]], ^[[EXIT:bb[0-9]+]]
+ // CHECK: ^[[BODY]]:
+ // CHECK: cir.br ^[[STEP:bb[0-9]+]]
+ // CHECK: ^[[STEP]]:
+ // CHECK-NEXT: cir.br ^[[COND]] loop_id distinct[[[ID:[0-9]+]]]<> loop_hints < must_progress>
+ // CHECK: ^[[EXIT]]:
+ // CHECK: cir.return
+ cir.func @for_loop(%c: !cir.bool) {
+ cir.for : cond {
+ cir.condition(%c)
+ } body {
+ cir.call @body() : () -> ()
+ cir.yield
+ } step {
+ cir.yield
+ } loop_id distinct[0]<> loop_hints < must_progress>
+ cir.return
+ }
+
+ // The back edge of a 'while' is the end of the body.
+ // CHECK-LABEL: cir.func @while_loop
+ // CHECK: cir.br ^[[COND:bb[0-9]+]]
+ // CHECK: ^[[COND]]:
+ // CHECK: cir.brcond {{.*}} ^[[BODY:bb[0-9]+]], ^[[EXIT:bb[0-9]+]]
+ // CHECK: ^[[BODY]]:
+ // CHECK-NEXT: cir.call @body()
+ // CHECK-NEXT: cir.br ^[[COND]] loop_id distinct[[[ID:[0-9]+]]]<> loop_hints < unroll = enable>
+ cir.func @while_loop(%c: !cir.bool) {
+ cir.while {
+ cir.condition(%c)
+ } do {
+ cir.call @body() : () -> ()
+ cir.yield
+ } loop_id distinct[1]<> loop_hints < unroll = enable>
+ cir.return
+ }
+
+ // The back edge of a 'do' is the condition, which branches to the top of the
+ // body.
+ // CHECK-LABEL: cir.func @do_loop
+ // CHECK: cir.br ^[[BODY:bb[0-9]+]]
+ // CHECK: cir.brcond {{.*}} ^[[BODY]], ^[[EXIT:bb[0-9]+]] loop_id distinct[[[ID:[0-9]+]]]<> loop_hints < unroll = disable>
+ cir.func @do_loop(%c: !cir.bool) {
+ cir.do {
+ cir.call @body() : () -> ()
+ cir.yield
+ } while {
+ cir.condition(%c)
+ } loop_id distinct[2]<> loop_hints < unroll = disable>
+ cir.return
+ }
+
+ // A 'continue' branches back to the top of the loop too, so it also gets the
+ // loop's id and hints.
+ // CHECK-LABEL: cir.func @loop_continue
+ // CHECK: cir.br ^[[COND:bb[0-9]+]]
+ // CHECK: ^[[COND]]:
+ // CHECK: cir.brcond {{.*}} ^[[BODY:bb[0-9]+]], ^[[EXIT:bb[0-9]+]]
+ // CHECK: ^[[BODY]]:
+ // CHECK: cir.br ^[[COND]] loop_id distinct[[[ID:[0-9]+]]]<> loop_hints < must_progress>
+ // CHECK: cir.br ^[[COND]] loop_id distinct[[[ID]]]<> loop_hints < must_progress>
+ cir.func @loop_continue(%c: !cir.bool) {
+ cir.while {
+ cir.condition(%c)
+ } do {
+ cir.if %c {
+ cir.continue
+ }
+ cir.yield
+ } loop_id distinct[3]<> loop_hints < must_progress>
+ cir.return
+ }
+
+ // Each loop has its own id. The outer loop's id is on the branch that ends
+ // the outer loop's body, and the inner loop's id is on the branch that ends
+ // the inner loop's body.
+ // CHECK-LABEL: cir.func @nested_loops
+ // CHECK: cir.br ^[[INNER_COND:bb[0-9]+]] loop_id distinct[[[INNER:[0-9]+]]]<> loop_hints < unroll = enable>
+ // CHECK: cir.br ^[[OUTER_COND:bb[0-9]+]] loop_id distinct[[[OUTER:[0-9]+]]]<> loop_hints < must_progress>
+ cir.func @nested_loops(%c: !cir.bool) {
+ cir.while {
+ cir.condition(%c)
+ } do {
+ cir.while {
+ cir.condition(%c)
+ } do {
+ cir.call @body() : () -> ()
+ cir.yield
+ } loop_id distinct[5]<> loop_hints < unroll = enable>
+ cir.yield
+ } loop_id distinct[4]<> loop_hints < must_progress>
+ cir.return
+ }
+
+ // Loops without any hints don't have a loop id, nor get one when flattened.
+ // CHECK-LABEL: cir.func @no_hints
+ // CHECK-NOT: loop_id
+ // CHECK-NOT: loop_hints
+ cir.func @no_hints(%c: !cir.bool) {
+ cir.while {
+ cir.condition(%c)
+ } do {
+ cir.call @body() : () -> ()
+ cir.yield
+ }
+ cir.return
+ }
+
+ // A loop can have an id without having any hints. It is still copied.
+ // CHECK-LABEL: cir.func @id_without_hints
+ // CHECK: cir.br ^{{.*}} loop_id distinct[[[ID:[0-9]+]]]<>{{$}}
+ cir.func @id_without_hints(%c: !cir.bool) {
+ cir.while {
+ cir.condition(%c)
+ } do {
+ cir.call @body() : () -> ()
+ cir.yield
+ } loop_id distinct[6]<>
+ cir.return
+ }
+}
diff --git a/mlir/include/mlir/IR/CommonAttrConstraints.td b/mlir/include/mlir/IR/CommonAttrConstraints.td
index ba6cf55a8fb9e9..3ddb0deb14bea7 100644
--- a/mlir/include/mlir/IR/CommonAttrConstraints.td
+++ b/mlir/include/mlir/IR/CommonAttrConstraints.td
@@ -195,6 +195,14 @@ def LocationAttr : Attr<CPred<"::llvm::isa<::mlir::LocationAttr>($_self)">,
let constBuilderCall = "(::mlir::LocationAttr)$0";
}
+// Any distinct attribute.
+def AnyDistinctAttr : Attr<CPred<"::llvm::isa<::mlir::DistinctAttr>($_self)">,
+ "distinct attribute"> {
+ let storageType = "::mlir::DistinctAttr";
+ let returnType = "::mlir::DistinctAttr";
+ let convertFromStorage = "$_self";
+}
+
def BoolAttr : Attr<CPred<"::llvm::isa<::mlir::BoolAttr>($_self)">, "bool attribute"> {
let storageType = [{ ::mlir::BoolAttr }];
let returnType = [{ bool }];
More information about the Mlir-commits
mailing list