diff --git a/.github/workflows/pr-code-format.yml b/.github/workflows/pr-code-format.yml index 5223089ee8a9..a3171eda6224 100644 --- a/.github/workflows/pr-code-format.yml +++ b/.github/workflows/pr-code-format.yml @@ -6,7 +6,7 @@ permissions: jobs: code_formatter: runs-on: ubuntu-latest - if: github.repository == 'llvm/llvm-project' + if: github.repository == 'llvm/clangir' steps: - name: Fetch LLVM sources uses: actions/checkout@v4 diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h index 191910c2749b..47f80cc8a635 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h +++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h @@ -18,9 +18,9 @@ #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/Dialect.h" #include "mlir/IR/OpDefinition.h" -#include "mlir/Interfaces/FunctionInterfaces.h" #include "mlir/Interfaces/CallInterfaces.h" #include "mlir/Interfaces/ControlFlowInterfaces.h" +#include "mlir/Interfaces/FunctionInterfaces.h" #include "mlir/Interfaces/InferTypeOpInterface.h" #include "mlir/Interfaces/LoopLikeInterface.h" #include "mlir/Interfaces/SideEffectInterfaces.h" diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 7903161b7abf..7fdd2313ab2d 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -582,6 +582,25 @@ def TernaryOp : CIR_Op<"ternary", }]; } +//===----------------------------------------------------------------------===// +// ConditionOp +//===----------------------------------------------------------------------===// + +def ConditionOp : CIR_Op<"condition", [ + Terminator, + DeclareOpInterfaceMethods +]> { + let summary = "Loop continuation condition."; + let description = [{ + The `cir.condition` termintes loop's conditional regions. It takes a single + `cir.bool` operand. if the operand is true, the loop continues, otherwise + it terminates. + }]; + let arguments = (ins CIR_BoolType:$condition); + let assemblyFormat = " `(` $condition `)` attr-dict "; +} + //===----------------------------------------------------------------------===// // YieldOp //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypesDetails.h b/clang/include/clang/CIR/Dialect/IR/CIRTypesDetails.h index ae9e97ce3cab..5eba4ac460a7 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRTypesDetails.h +++ b/clang/include/clang/CIR/Dialect/IR/CIRTypesDetails.h @@ -1,4 +1,4 @@ -//===- CIRTypesDetails.h - Details of CIR dialect types -----------*- C++ -*-===// +//===- CIRTypesDetails.h - Details of CIR dialect types ---------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/clang/lib/CIR/CodeGen/CIRAsm.cpp b/clang/lib/CIR/CodeGen/CIRAsm.cpp index 91d3f5420a77..bf184a3d4f07 100644 --- a/clang/lib/CIR/CodeGen/CIRAsm.cpp +++ b/clang/lib/CIR/CodeGen/CIRAsm.cpp @@ -41,8 +41,8 @@ mlir::LogicalResult CIRGenFunction::buildAsmStmt(const AsmStmt &S) { AsmDialect AsmDialect = inferDialect(CGM, S); - builder.create( - getLoc(S.getAsmLoc()), ResultType, AsmString, AsmDialect); + builder.create(getLoc(S.getAsmLoc()), ResultType, + AsmString, AsmDialect); return mlir::success(); } \ No newline at end of file diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h index 7b2b87bdf4fd..26d81622f54c 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h @@ -578,6 +578,11 @@ class CIRGenBuilderTy : public CIRBaseBuilderTy { return create(dst.getLoc(), dst, src); } + /// Create a loop condition. + mlir::cir::ConditionOp createCondition(mlir::Value condition) { + return create(condition.getLoc(), condition); + } + mlir::cir::MemCpyOp createMemCpy(mlir::Location loc, mlir::Value dst, mlir::Value src, mlir::Value len) { return create(loc, dst, src, len); @@ -787,10 +792,10 @@ class CIRGenBuilderTy : public CIRBaseBuilderTy { return create(loc, ty); } - mlir::cir::StackRestoreOp createStackRestore(mlir::Location loc, mlir::Value v) { + mlir::cir::StackRestoreOp createStackRestore(mlir::Location loc, + mlir::Value v) { return create(loc, v); } - }; } // namespace cir diff --git a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp index 98e1f9281a33..1c05018b535d 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCoroutine.cpp @@ -194,10 +194,9 @@ CIRGenFunction::buildCoroAllocBuiltinCall(mlir::Location loc) { mlir::cir::FuncOp fnOp; if (!builtin) { - fnOp = CGM.createCIRFunction( - loc, CGM.builtinCoroAlloc, - mlir::cir::FuncType::get({int32Ty}, boolTy), - /*FD=*/nullptr); + fnOp = CGM.createCIRFunction(loc, CGM.builtinCoroAlloc, + mlir::cir::FuncType::get({int32Ty}, boolTy), + /*FD=*/nullptr); assert(fnOp && "should always succeed"); fnOp.setBuiltinAttr(mlir::UnitAttr::get(builder.getContext())); } else @@ -217,8 +216,7 @@ CIRGenFunction::buildCoroBeginBuiltinCall(mlir::Location loc, if (!builtin) { fnOp = CGM.createCIRFunction( loc, CGM.builtinCoroBegin, - mlir::cir::FuncType::get({int32Ty, VoidPtrTy}, - VoidPtrTy), + mlir::cir::FuncType::get({int32Ty, VoidPtrTy}, VoidPtrTy), /*FD=*/nullptr); assert(fnOp && "should always succeed"); fnOp.setBuiltinAttr(mlir::UnitAttr::get(builder.getContext())); diff --git a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp index 77dae8cfb878..662d24cd63a9 100644 --- a/clang/lib/CIR/CodeGen/CIRGenDecl.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenDecl.cpp @@ -892,7 +892,7 @@ struct CallCleanupFunction final : EHScopeStack::Cleanup { /// Push the standard destructor for the given type as /// at least a normal cleanup. void CIRGenFunction::pushDestroy(QualType::DestructionKind dtorKind, - Address addr, QualType type) { + Address addr, QualType type) { assert(dtorKind && "cannot push destructor for trivial type"); CleanupKind cleanupKind = getCleanupKind(dtorKind); diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 7bc4f713a944..206f68965152 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -234,8 +234,8 @@ Address CIRGenFunction::getAddrOfBitFieldStorage(LValue base, auto fieldPtr = mlir::cir::PointerType::get(getBuilder().getContext(), fieldType); - auto sea = getBuilder().createGetMember( - loc, fieldPtr, base.getPointer(), field->getName(), index); + auto sea = getBuilder().createGetMember(loc, fieldPtr, base.getPointer(), + field->getName(), index); return Address(sea, CharUnits::One()); } @@ -341,7 +341,7 @@ LValue CIRGenFunction::buildLValueForField(LValue base, if (!IsInPreservedAIRegion && (!getDebugInfo() || !rec->hasAttr())) { llvm::StringRef fieldName = field->getName(); - auto& layout = CGM.getTypes().getCIRGenRecordLayout(field->getParent()); + auto &layout = CGM.getTypes().getCIRGenRecordLayout(field->getParent()); unsigned fieldIndex = layout.getCIRFieldNo(field); if (CGM.LambdaFieldToName.count(field)) @@ -396,7 +396,7 @@ LValue CIRGenFunction::buildLValueForFieldInitialization( if (!FieldType->isReferenceType()) return buildLValueForField(Base, Field); - auto& layout = CGM.getTypes().getCIRGenRecordLayout(Field->getParent()); + auto &layout = CGM.getTypes().getCIRGenRecordLayout(Field->getParent()); unsigned FieldIndex = layout.getCIRFieldNo(Field); Address V = buildAddrOfFieldStorage(*this, Base.getAddress(), Field, diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp index 755d16004a55..445cb57824e3 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp @@ -60,37 +60,36 @@ static bool isBlockVarRef(const Expr *E) { // FIXME: pointer arithmetic? return false; - // Check both sides of a conditional operator. - } else if (const AbstractConditionalOperator *op - = dyn_cast(E)) { - return isBlockVarRef(op->getTrueExpr()) - || isBlockVarRef(op->getFalseExpr()); - - // OVEs are required to support BinaryConditionalOperators. - } else if (const OpaqueValueExpr *op - = dyn_cast(E)) { + // Check both sides of a conditional operator. + } else if (const AbstractConditionalOperator *op = + dyn_cast(E)) { + return isBlockVarRef(op->getTrueExpr()) || + isBlockVarRef(op->getFalseExpr()); + + // OVEs are required to support BinaryConditionalOperators. + } else if (const OpaqueValueExpr *op = dyn_cast(E)) { if (const Expr *src = op->getSourceExpr()) return isBlockVarRef(src); - // Casts are necessary to get things like (*(int*)&var) = foo(). - // We don't really care about the kind of cast here, except - // we don't want to look through l2r casts, because it's okay - // to get the *value* in a __block variable. + // Casts are necessary to get things like (*(int*)&var) = foo(). + // We don't really care about the kind of cast here, except + // we don't want to look through l2r casts, because it's okay + // to get the *value* in a __block variable. } else if (const CastExpr *cast = dyn_cast(E)) { if (cast->getCastKind() == CK_LValueToRValue) return false; return isBlockVarRef(cast->getSubExpr()); - // Handle unary operators. Again, just aggressively look through - // it, ignoring the operation. + // Handle unary operators. Again, just aggressively look through + // it, ignoring the operation. } else if (const UnaryOperator *uop = dyn_cast(E)) { return isBlockVarRef(uop->getSubExpr()); - // Look into the base of a field access. + // Look into the base of a field access. } else if (const MemberExpr *mem = dyn_cast(E)) { return isBlockVarRef(mem->getBase()); - // Look into the base of a subscript. + // Look into the base of a subscript. } else if (const ArraySubscriptExpr *sub = dyn_cast(E)) { return isBlockVarRef(sub->getBase()); } @@ -113,7 +112,8 @@ class AggExprEmitter : public StmtVisitor { llvm::function_ref Fn); AggValueSlot EnsureSlot(mlir::Location loc, QualType T) { - if (!Dest.isIgnored()) return Dest; + if (!Dest.isIgnored()) + return Dest; return CGF.CreateAggTemp(T, loc, "agg.tmp.ensured"); } @@ -213,11 +213,11 @@ class AggExprEmitter : public StmtVisitor { // For an assignment to work, the value on the right has // to be compatible with the value on the left. assert(CGF.getContext().hasSameUnqualifiedType(E->getLHS()->getType(), - E->getRHS()->getType()) - && "Invalid assignment"); + E->getRHS()->getType()) && + "Invalid assignment"); if (isBlockVarRef(E->getLHS()) && - E->getRHS()->HasSideEffects(CGF.getContext())) { + E->getRHS()->HasSideEffects(CGF.getContext())) { llvm_unreachable("NYI"); } @@ -233,12 +233,11 @@ class AggExprEmitter : public StmtVisitor { // Codegen the RHS so that it stores directly into the LHS. AggValueSlot lhsSlot = AggValueSlot::forLValue( - lhs, AggValueSlot::IsDestructed, AggValueSlot::DoesNotNeedGCBarriers, - AggValueSlot::IsAliased, AggValueSlot::MayOverlap); + lhs, AggValueSlot::IsDestructed, AggValueSlot::DoesNotNeedGCBarriers, + AggValueSlot::IsAliased, AggValueSlot::MayOverlap); // A non-volatile aggregate destination might have volatile member. - if (!lhsSlot.isVolatile() && - CGF.hasVolatileMember(E->getLHS()->getType())) + if (!lhsSlot.isVolatile() && CGF.hasVolatileMember(E->getLHS()->getType())) assert(!UnimplementedFeature::atomicTypes()); CGF.buildAggExpr(E->getRHS(), lhsSlot); @@ -247,10 +246,10 @@ class AggExprEmitter : public StmtVisitor { buildFinalDestCopy(E->getType(), lhs); if (!Dest.isIgnored() && !Dest.isExternallyDestructed() && - E->getType().isDestructedType() == QualType::DK_nontrivial_c_struct) + E->getType().isDestructedType() == QualType::DK_nontrivial_c_struct) CGF.pushDestroy(QualType::DK_nontrivial_c_struct, Dest.getAddress(), - E->getType()); - } + E->getType()); + } void VisitBinComma(const BinaryOperator *E) { llvm_unreachable("NYI"); } void VisitBinCmp(const BinaryOperator *E) { llvm_unreachable("NYI"); } @@ -356,8 +355,8 @@ void AggExprEmitter::buildFinalDestCopy(QualType type, const LValue &src, assert(!UnimplementedFeature::volatileTypes()); if (SrcValueKind == EVK_RValue) { - if (type.isNonTrivialToPrimitiveDestructiveMove() == QualType::PCK_Struct) { - llvm_unreachable("move assignment/move ctor for rvalue is NYI"); + if (type.isNonTrivialToPrimitiveDestructiveMove() == QualType::PCK_Struct) { + llvm_unreachable("move assignment/move ctor for rvalue is NYI"); } } else { if (type.isNonTrivialToPrimitiveCopy() == QualType::PCK_Struct) @@ -672,8 +671,8 @@ void AggExprEmitter::VisitLambdaExpr(LambdaExpr *E) { } // Emit initialization - LValue LV = CGF.buildLValueForFieldInitialization( - SlotLV, *CurField, fieldName); + LValue LV = + CGF.buildLValueForFieldInitialization(SlotLV, *CurField, fieldName); if (CurField->hasCapturedVLAType()) { llvm_unreachable("NYI"); } @@ -820,8 +819,8 @@ void AggExprEmitter::withReturnValueSlot( if (!UseTemp) { RetAddr = Dest.getAddress(); } else { - RetAddr = CGF.CreateMemTemp(RetTy, CGF.getLoc(E->getSourceRange()), - "tmp", &RetAddr); + RetAddr = CGF.CreateMemTemp(RetTy, CGF.getLoc(E->getSourceRange()), "tmp", + &RetAddr); assert(!UnimplementedFeature::shouldEmitLifetimeMarkers() && "NYI"); } @@ -940,8 +939,8 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr( if (curInitIndex == NumInitElements && Dest.isZeroed() && CGF.getTypes().isZeroInitializable(ExprToVisit->getType())) break; - LValue LV = CGF.buildLValueForFieldInitialization( - DestLV, field, field->getName()); + LValue LV = + CGF.buildLValueForFieldInitialization(DestLV, field, field->getName()); // We never generate write-barries for initialized fields. assert(!UnimplementedFeature::setNonGC()); diff --git a/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp b/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp index af4e93487451..bfd5f4bd50ce 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp @@ -907,7 +907,7 @@ class ConstExprEmitter // Look through the temporary; it's just converting the value to an lvalue // to pass it to the constructor. if (auto *MTE = dyn_cast(Arg)) - return Visit(MTE->getSubExpr(), Ty); + return Visit(MTE->getSubExpr(), Ty); // Don't try to support arbitrary lvalue-to-rvalue conversions for now. return nullptr; } @@ -1074,8 +1074,7 @@ class ConstantLValueEmitter ConstantLValue applyOffset(ConstantLValue &C) { // Handle attribute constant LValues. - if (auto Attr = - C.Value.dyn_cast()) { + if (auto Attr = C.Value.dyn_cast()) { if (auto GV = Attr.dyn_cast()) { auto baseTy = GV.getType().cast().getPointee(); auto destTy = CGM.getTypes().convertTypeForMem(DestType); @@ -1338,7 +1337,7 @@ mlir::Attribute ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &D) { } InConstantContext = D.hasConstantInitialization(); - const Expr * E = D.getInit(); + const Expr *E = D.getInit(); assert(E && "No initializer to emit"); QualType destType = D.getType(); diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 29bfd2c24c44..2d56b33dc823 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -771,7 +771,7 @@ class CIRGenFunction : public CIRGenTypeCache { /// Create a check for a function parameter that may potentially be /// declared as non-null. void buildNonNullArgCheck(RValue RV, QualType ArgType, SourceLocation ArgLoc, - AbstractCallee AC, unsigned ParmNum); + AbstractCallee AC, unsigned ParmNum); void buildCallArg(CallArgList &args, const clang::Expr *E, clang::QualType ArgType); @@ -1364,7 +1364,7 @@ class CIRGenFunction : public CIRGenTypeCache { AggValueSlot::Overlap_t getOverlapForFieldInit(const FieldDecl *FD); LValue buildLValueForField(LValue Base, const clang::FieldDecl *Field); LValue buildLValueForBitField(LValue base, const FieldDecl *field); - + /// Like buildLValueForField, excpet that if the Field is a reference, this /// will return the address of the reference and not the address of the value /// stored in the reference. @@ -1522,8 +1522,8 @@ class CIRGenFunction : public CIRGenTypeCache { static Destroyer destroyCXXObject; - void pushDestroy(QualType::DestructionKind dtorKind, - Address addr, QualType type); + void pushDestroy(QualType::DestructionKind dtorKind, Address addr, + QualType type); void pushDestroy(CleanupKind kind, Address addr, QualType type, Destroyer *destroyer, bool useEHCleanupForArray); diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.cpp b/clang/lib/CIR/CodeGen/CIRGenModule.cpp index 16445dddb4cf..7eab7323d70f 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenModule.cpp @@ -100,10 +100,10 @@ CIRGenModule::CIRGenModule(mlir::MLIRContext &context, const clang::CodeGenOptions &CGO, DiagnosticsEngine &Diags) : builder(context, *this), astCtx(astctx), langOpts(astctx.getLangOpts()), - codeGenOpts(CGO), theModule{mlir::ModuleOp::create( - builder.getUnknownLoc())}, - Diags(Diags), target(astCtx.getTargetInfo()), - ABI(createCXXABI(*this)), genTypes{*this}, VTables{*this} { + codeGenOpts(CGO), + theModule{mlir::ModuleOp::create(builder.getUnknownLoc())}, Diags(Diags), + target(astCtx.getTargetInfo()), ABI(createCXXABI(*this)), genTypes{*this}, + VTables{*this} { // Initialize CIR signed integer types cache. SInt8Ty = diff --git a/clang/lib/CIR/CodeGen/CIRGenModule.h b/clang/lib/CIR/CodeGen/CIRGenModule.h index a0b30e7464ab..e468c53e58d4 100644 --- a/clang/lib/CIR/CodeGen/CIRGenModule.h +++ b/clang/lib/CIR/CodeGen/CIRGenModule.h @@ -196,7 +196,7 @@ class CIRGenModule : public CIRGenTypeCache { mlir::cir::GlobalOp getOrCreateStaticVarDecl(const VarDecl &D, - mlir::cir::GlobalLinkageKind Linkage); + mlir::cir::GlobalLinkageKind Linkage); mlir::cir::GlobalOp buildGlobal(const VarDecl *D, mlir::Type Ty, ForDefinition_t IsForDefinition); @@ -239,7 +239,7 @@ class CIRGenModule : public CIRGenTypeCache { ForDefinition_t IsForDefinition = NotForDefinition); /// Get a reference to the target of VD. - mlir::Operation* getWeakRefReference(const ValueDecl *VD); + mlir::Operation *getWeakRefReference(const ValueDecl *VD); CharUnits computeNonVirtualBaseClassOffset(const CXXRecordDecl *DerivedClass, @@ -509,7 +509,7 @@ class CIRGenModule : public CIRGenTypeCache { /// Emit the function that initializes the specified global void buildGlobalVarDeclInit(const VarDecl *D, mlir::cir::GlobalOp Addr, - bool PerformInit); + bool PerformInit); void addDeferredVTable(const CXXRecordDecl *RD) { DeferredVTables.push_back(RD); diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp index 73916054aeb2..6c93e9f0cd5b 100644 --- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp @@ -647,26 +647,6 @@ CIRGenFunction::buildDefaultStmt(const DefaultStmt &S, mlir::Type condType, return buildCaseDefaultCascade(&S, condType, caseAttrs, os); } -static mlir::LogicalResult buildLoopCondYield(mlir::OpBuilder &builder, - mlir::Location loc, - mlir::Value cond) { - mlir::Block *trueBB = nullptr, *falseBB = nullptr; - { - mlir::OpBuilder::InsertionGuard guard(builder); - trueBB = builder.createBlock(builder.getBlock()->getParent()); - builder.create(loc, YieldOpKind::Continue); - } - { - mlir::OpBuilder::InsertionGuard guard(builder); - falseBB = builder.createBlock(builder.getBlock()->getParent()); - builder.create(loc); - } - - assert((trueBB && falseBB) && "expected both blocks to exist"); - builder.create(loc, cond, trueBB, falseBB); - return mlir::success(); -} - mlir::LogicalResult CIRGenFunction::buildCXXForRangeStmt(const CXXForRangeStmt &S, ArrayRef ForAttrs) { @@ -700,8 +680,7 @@ CIRGenFunction::buildCXXForRangeStmt(const CXXForRangeStmt &S, assert(!UnimplementedFeature::createProfileWeightsForLoop()); assert(!UnimplementedFeature::emitCondLikelihoodViaExpectIntrinsic()); mlir::Value condVal = evaluateExprAsBool(S.getCond()); - if (buildLoopCondYield(b, loc, condVal).failed()) - loopRes = mlir::failure(); + builder.createCondition(condVal); }, /*bodyBuilder=*/ [&](mlir::OpBuilder &b, mlir::Location loc) { @@ -783,8 +762,7 @@ mlir::LogicalResult CIRGenFunction::buildForStmt(const ForStmt &S) { loc, boolTy, mlir::cir::BoolAttr::get(b.getContext(), boolTy, true)); } - if (buildLoopCondYield(b, loc, condVal).failed()) - loopRes = mlir::failure(); + builder.createCondition(condVal); }, /*bodyBuilder=*/ [&](mlir::OpBuilder &b, mlir::Location loc) { @@ -847,8 +825,7 @@ mlir::LogicalResult CIRGenFunction::buildDoStmt(const DoStmt &S) { // expression compares unequal to 0. The condition must be a // scalar type. mlir::Value condVal = evaluateExprAsBool(S.getCond()); - if (buildLoopCondYield(b, loc, condVal).failed()) - loopRes = mlir::failure(); + builder.createCondition(condVal); }, /*bodyBuilder=*/ [&](mlir::OpBuilder &b, mlir::Location loc) { @@ -907,8 +884,7 @@ mlir::LogicalResult CIRGenFunction::buildWhileStmt(const WhileStmt &S) { // expression compares unequal to 0. The condition must be a // scalar type. condVal = evaluateExprAsBool(S.getCond()); - if (buildLoopCondYield(b, loc, condVal).failed()) - loopRes = mlir::failure(); + builder.createCondition(condVal); }, /*bodyBuilder=*/ [&](mlir::OpBuilder &b, mlir::Location loc) { diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp index 07535d459d34..1513b7003fb6 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp @@ -631,7 +631,7 @@ mlir::Type CIRGenTypes::ConvertType(QualType T) { SkippedLayout = true; ResultType = Builder.getUInt8Ty(); } - ResultType = Builder.getArrayType(ResultType, 0); + ResultType = Builder.getArrayType(ResultType, 0); break; } case Type::ConstantArray: { diff --git a/clang/lib/CIR/CodeGen/CIRGenVTables.cpp b/clang/lib/CIR/CodeGen/CIRGenVTables.cpp index 72a7f01b6200..332e4ab21b41 100644 --- a/clang/lib/CIR/CodeGen/CIRGenVTables.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenVTables.cpp @@ -434,8 +434,7 @@ getAddrOfVTTVTable(CIRGenVTables &CGVT, CIRGenModule &CGM, llvm_unreachable("generateConstructionVTable NYI"); } -mlir::cir::GlobalOp CIRGenVTables::getAddrOfVTT(const CXXRecordDecl *RD) -{ +mlir::cir::GlobalOp CIRGenVTables::getAddrOfVTT(const CXXRecordDecl *RD) { assert(RD->getNumVBases() && "Only classes with virtual bases need a VTT"); SmallString<256> OutName; diff --git a/clang/lib/CIR/CodeGen/CIRRecordLayoutBuilder.cpp b/clang/lib/CIR/CodeGen/CIRRecordLayoutBuilder.cpp index effad38412a5..066906c1adc4 100644 --- a/clang/lib/CIR/CodeGen/CIRRecordLayoutBuilder.cpp +++ b/clang/lib/CIR/CodeGen/CIRRecordLayoutBuilder.cpp @@ -215,8 +215,8 @@ CIRRecordLowering::CIRRecordLowering(CIRGenTypes &cirGenTypes, cxxRecordDecl{llvm::dyn_cast(recordDecl)}, astRecordLayout{cirGenTypes.getContext().getASTRecordLayout(recordDecl)}, dataLayout{cirGenTypes.getModule().getModule()}, - IsZeroInitializable(true), - IsZeroInitializableAsBase(true), isPacked{isPacked} {} + IsZeroInitializable(true), IsZeroInitializableAsBase(true), + isPacked{isPacked} {} void CIRRecordLowering::setBitFieldInfo(const FieldDecl *FD, CharUnits StartOffset, @@ -227,7 +227,7 @@ void CIRRecordLowering::setBitFieldInfo(const FieldDecl *FD, (unsigned)(getFieldBitOffset(FD) - astContext.toBits(StartOffset)); Info.Size = FD->getBitWidthValue(astContext); Info.StorageSize = getSizeInBits(StorageType).getQuantity(); - Info.StorageOffset = StartOffset; + Info.StorageOffset = StartOffset; Info.Name = FD->getName(); if (Info.Size > Info.StorageSize) diff --git a/clang/lib/CIR/CodeGen/EHScopeStack.h b/clang/lib/CIR/CodeGen/EHScopeStack.h index 8711cd3c232e..5ab356df319f 100644 --- a/clang/lib/CIR/CodeGen/EHScopeStack.h +++ b/clang/lib/CIR/CodeGen/EHScopeStack.h @@ -73,7 +73,7 @@ struct DominatingPointer; template struct DominatingPointer : InvariantValue {}; // template struct DominatingPointer at end of file -template struct DominatingValue : DominatingPointer {}; +template struct DominatingValue : DominatingPointer {}; enum CleanupKind : unsigned { /// Denotes a cleanup that should run when a scope is exited using exceptional @@ -268,9 +268,9 @@ class EHScopeStack { public: EHScopeStack() - : StartOfBuffer(nullptr), EndOfBuffer(nullptr), StartOfData(nullptr), - InnermostNormalCleanup(stable_end()), InnermostEHScope(stable_end()), - CGF(nullptr) {} + : StartOfBuffer(nullptr), EndOfBuffer(nullptr), StartOfData(nullptr), + InnermostNormalCleanup(stable_end()), InnermostEHScope(stable_end()), + CGF(nullptr) {} ~EHScopeStack() { delete[] StartOfBuffer; } /// Push a lazily-created cleanup on the stack. @@ -279,7 +279,7 @@ class EHScopeStack { "Cleanup's alignment is too large."); void *Buffer = pushCleanup(Kind, sizeof(T)); Cleanup *Obj = new (Buffer) T(A...); - (void) Obj; + (void)Obj; } /// Push a lazily-created cleanup on the stack. Tuple version. @@ -289,7 +289,7 @@ class EHScopeStack { "Cleanup's alignment is too large."); void *Buffer = pushCleanup(Kind, sizeof(T)); Cleanup *Obj = new (Buffer) T(std::move(A)); - (void) Obj; + (void)Obj; } // Feel free to add more variants of the following: @@ -364,10 +364,7 @@ class EHScopeStack { } stable_iterator getInnermostActiveNormalCleanup() const; - stable_iterator getInnermostEHScope() const { - return InnermostEHScope; - } - + stable_iterator getInnermostEHScope() const { return InnermostEHScope; } /// An unstable reference to a scope-stack depth. Invalidated by /// pushes but not pops. @@ -387,9 +384,7 @@ class EHScopeStack { } /// Create a stable reference to the bottom of the EH stack. - static stable_iterator stable_end() { - return stable_iterator(0); - } + static stable_iterator stable_end() { return stable_iterator(0); } /// Translates an iterator into a stable_iterator. stable_iterator stabilize(iterator it) const; diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp index b4794921165b..e6362b34b24c 100644 --- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp @@ -221,9 +221,9 @@ Attribute ConstPtrAttr::parse(AsmParser &parser, Type odsType) { void ConstPtrAttr::print(AsmPrinter &printer) const { printer << '<'; if (isNullValue()) - printer << "null"; + printer << "null"; else - printer << getValue(); + printer << getValue(); printer << '>'; } diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index af6b0b85f3f5..0a6e10812b0c 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -189,8 +189,8 @@ bool omitRegionTerm(mlir::Region &r) { // CIR Custom Parsers/Printers //===----------------------------------------------------------------------===// -static mlir::ParseResult -parseOmittedTerminatorRegion(mlir::OpAsmParser &parser, mlir::Region ®ion) { +static mlir::ParseResult parseOmittedTerminatorRegion(mlir::OpAsmParser &parser, + mlir::Region ®ion) { auto regionLoc = parser.getCurrentLocation(); if (parser.parseRegion(region)) return failure(); @@ -200,8 +200,8 @@ parseOmittedTerminatorRegion(mlir::OpAsmParser &parser, mlir::Region ®ion) { } static void printOmittedTerminatorRegion(mlir::OpAsmPrinter &printer, - mlir::cir::ScopeOp &op, - mlir::Region ®ion) { + mlir::cir::ScopeOp &op, + mlir::Region ®ion) { printer.printRegion(region, /*printEntryBlockArgs=*/false, /*printBlockTerminators=*/!omitRegionTerm(region)); @@ -225,6 +225,30 @@ void AllocaOp::build(::mlir::OpBuilder &odsBuilder, odsState.addTypes(addr); } +//===----------------------------------------------------------------------===// +// ConditionOp +//===-----------------------------------------------------------------------===// + +//===---------------------------------- +// BranchOpTerminatorInterface Methods + +void ConditionOp::getSuccessorRegions( + ArrayRef operands, SmallVectorImpl ®ions) { + auto loopOp = cast(getOperation()->getParentOp()); + + // TODO(cir): The condition value may be folded to a constant, narrowing + // down its list of possible successors. + // Condition may branch to the body or to the parent op. + regions.emplace_back(&loopOp.getBody(), loopOp.getBody().getArguments()); + regions.emplace_back(loopOp->getResults()); +} + +MutableOperandRange +ConditionOp::getMutableSuccessorOperands(RegionBranchPoint point) { + // No values are yielded to the successor region. + return MutableOperandRange(getOperation(), 0, 0); +} + //===----------------------------------------------------------------------===// // ConstantOp //===----------------------------------------------------------------------===// @@ -1303,26 +1327,11 @@ void LoopOp::getSuccessorRegions(mlir::RegionBranchPoint point, llvm::SmallVector LoopOp::getLoopRegions() { return {&getBody()}; } LogicalResult LoopOp::verify() { - // Cond regions should only terminate with plain 'cir.yield' or - // 'cir.yield continue'. - auto terminateError = [&]() { - return emitOpError() << "cond region must be terminated with " - "'cir.yield' or 'cir.yield continue'"; - }; + if (getCond().empty()) + return emitOpError() << "cond region must not be empty"; - auto &blocks = getCond().getBlocks(); - for (Block &block : blocks) { - if (block.empty()) - continue; - auto &op = block.back(); - if (isa(op)) - continue; - if (!isa(op)) - terminateError(); - auto y = cast(op); - if (!(y.isPlain() || y.isContinue())) - terminateError(); - } + if (!llvm::isa(getCond().back().getTerminator())) + return emitOpError() << "cond region terminate with 'cir.condition'"; return success(); } diff --git a/clang/lib/CIR/Dialect/Transforms/IdiomRecognizer.cpp b/clang/lib/CIR/Dialect/Transforms/IdiomRecognizer.cpp index c0c31b0052f7..7b1218ad7c27 100644 --- a/clang/lib/CIR/Dialect/Transforms/IdiomRecognizer.cpp +++ b/clang/lib/CIR/Dialect/Transforms/IdiomRecognizer.cpp @@ -36,8 +36,8 @@ struct IdiomRecognizerPass : public IdiomRecognizerBase { IdiomRecognizerPass() = default; void runOnOperation() override; void recognizeCall(CallOp call); - void raiseStdFind(CallOp call); - void raiseIteratorBeginEnd(CallOp call); + bool raiseStdFind(CallOp call); + bool raiseIteratorBeginEnd(CallOp call); // Handle pass options struct Options { @@ -88,14 +88,14 @@ struct IdiomRecognizerPass : public IdiomRecognizerBase { }; } // namespace -void IdiomRecognizerPass::raiseStdFind(CallOp call) { +bool IdiomRecognizerPass::raiseStdFind(CallOp call) { // FIXME: tablegen all of this function. if (call.getNumOperands() != 3) - return; + return false; auto callExprAttr = call.getAstAttr(); if (!callExprAttr || !callExprAttr.isStdFunctionCall("find")) { - return; + return false; } if (opts.emitRemarkFoundCalls()) @@ -109,6 +109,7 @@ void IdiomRecognizerPass::raiseStdFind(CallOp call) { call.replaceAllUsesWith(findOp); call.erase(); + return true; } static bool isIteratorLikeType(mlir::Type t) { @@ -128,24 +129,24 @@ static bool isIteratorInStdContainter(mlir::Type t) { return isStdArrayType(t); } -void IdiomRecognizerPass::raiseIteratorBeginEnd(CallOp call) { +bool IdiomRecognizerPass::raiseIteratorBeginEnd(CallOp call) { // FIXME: tablegen all of this function. CIRBaseBuilderTy builder(getContext()); if (call.getNumOperands() != 1 || call.getNumResults() != 1) - return; + return false; auto callExprAttr = call.getAstAttr(); if (!callExprAttr) - return; + return false; if (!isIteratorLikeType(call.getResult(0).getType())) - return; + return false; // First argument is the container "this" pointer. auto thisPtr = call.getOperand(0).getType().dyn_cast(); if (!thisPtr || !isIteratorInStdContainter(thisPtr.getPointee())) - return; + return false; builder.setInsertionPointAfter(call.getOperation()); mlir::Operation *iterOp; @@ -162,16 +163,20 @@ void IdiomRecognizerPass::raiseIteratorBeginEnd(CallOp call) { call.getLoc(), call.getResult(0).getType(), call.getCalleeAttr(), call.getOperand(0)); } else { - return; + return false; } call.replaceAllUsesWith(iterOp); call.erase(); + return true; } void IdiomRecognizerPass::recognizeCall(CallOp call) { - raiseIteratorBeginEnd(call); - raiseStdFind(call); + if (raiseIteratorBeginEnd(call)) + return; + + if (raiseStdFind(call)) + return; } void IdiomRecognizerPass::runOnOperation() { diff --git a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp index 63148b74c4ca..611a35eacc2a 100644 --- a/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp +++ b/clang/lib/CIR/Dialect/Transforms/LoweringPrepare.cpp @@ -109,9 +109,8 @@ struct LoweringPreparePass : public LoweringPrepareBase { GlobalOp LoweringPreparePass::buildRuntimeVariable( mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc, mlir::Type type, mlir::cir::GlobalLinkageKind linkage) { - GlobalOp g = - dyn_cast_or_null(SymbolTable::lookupNearestSymbolFrom( - theModule, StringAttr::get(theModule->getContext(), name))); + GlobalOp g = dyn_cast_or_null(SymbolTable::lookupNearestSymbolFrom( + theModule, StringAttr::get(theModule->getContext(), name))); if (!g) { g = builder.create(loc, name, type); g.setLinkageAttr( @@ -125,9 +124,8 @@ GlobalOp LoweringPreparePass::buildRuntimeVariable( FuncOp LoweringPreparePass::buildRuntimeFunction( mlir::OpBuilder &builder, llvm::StringRef name, mlir::Location loc, mlir::cir::FuncType type, mlir::cir::GlobalLinkageKind linkage) { - FuncOp f = - dyn_cast_or_null(SymbolTable::lookupNearestSymbolFrom( - theModule, StringAttr::get(theModule->getContext(), name))); + FuncOp f = dyn_cast_or_null(SymbolTable::lookupNearestSymbolFrom( + theModule, StringAttr::get(theModule->getContext(), name))); if (!f) { f = builder.create(loc, name, type); f.setLinkageAttr( @@ -342,8 +340,8 @@ void LoweringPreparePass::lowerGetBitfieldOp(GetBitfieldOp op) { } val = builder.createIntCast(val, resultTy); - op.replaceAllUsesWith(val); - op.erase(); + op.replaceAllUsesWith(val); + op.erase(); } void LoweringPreparePass::lowerSetBitfieldOp(SetBitfieldOp op) { @@ -369,8 +367,7 @@ void LoweringPreparePass::lowerSetBitfieldOp(SetBitfieldOp op) { if (storageSize != size) { assert(storageSize > size && "Invalid bitfield size."); - mlir::Value val = - builder.create(loc, storageType, addr); + mlir::Value val = builder.create(loc, storageType, addr); srcVal = builder.createAnd(srcVal, llvm::APInt::getLowBitsSet(srcWidth, size)); @@ -380,8 +377,8 @@ void LoweringPreparePass::lowerSetBitfieldOp(SetBitfieldOp op) { srcVal = builder.createShiftLeft(srcVal, offset); // Mask out the original value. - val = builder.createAnd(val, - ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size)); + val = builder.createAnd( + val, ~llvm::APInt::getBitsSet(srcWidth, offset, offset + size)); // Or together the unchanged values and the source value. srcVal = builder.createOr(val, srcVal); diff --git a/clang/lib/CIR/Dialect/Transforms/MergeCleanups.cpp b/clang/lib/CIR/Dialect/Transforms/MergeCleanups.cpp index 822ce6f4bb2c..e4848a21d0bd 100644 --- a/clang/lib/CIR/Dialect/Transforms/MergeCleanups.cpp +++ b/clang/lib/CIR/Dialect/Transforms/MergeCleanups.cpp @@ -54,49 +54,6 @@ struct RemoveRedudantBranches : public OpRewritePattern { } }; -/// Merges basic blocks of trivial conditional branches. This is useful when a -/// the condition of conditional branch is a constant and the destinations of -/// the conditional branch both have only one predecessor. -/// -/// From: -/// ^bb0: -/// %0 = cir.const(#true) : !cir.bool -/// cir.brcond %0 ^bb1, ^bb2 -/// ^bb1: // pred: ^bb0 -/// cir.yield continue -/// ^bb2: // pred: ^bb0 -/// cir.yield -/// -/// To: -/// ^bb0: -/// cir.yield continue -/// -struct MergeTrivialConditionalBranches : public OpRewritePattern { - using OpRewritePattern::OpRewritePattern; - - LogicalResult match(BrCondOp op) const final { - return success(isa(op.getCond().getDefiningOp()) && - op.getDestFalse()->hasOneUse() && - op.getDestTrue()->hasOneUse()); - } - - /// Replace conditional branch with unconditional branch. - void rewrite(BrCondOp op, PatternRewriter &rewriter) const final { - auto constOp = llvm::cast(op.getCond().getDefiningOp()); - bool cond = constOp.getValue().cast().getValue(); - Block *block = op.getOperation()->getBlock(); - - rewriter.eraseOp(op); - if (cond) { - rewriter.mergeBlocks(op.getDestTrue(), block); - rewriter.eraseBlock(op.getDestFalse()); - } else { - rewriter.mergeBlocks(op.getDestFalse(), block); - rewriter.eraseBlock(op.getDestTrue()); - } - } -}; - struct RemoveEmptyScope : public OpRewritePattern { using OpRewritePattern::OpRewritePattern; @@ -145,7 +102,6 @@ void populateMergeCleanupPatterns(RewritePatternSet &patterns) { // clang-format off patterns.add< RemoveRedudantBranches, - MergeTrivialConditionalBranches, RemoveEmptyScope, RemoveEmptySwitch >(patterns.getContext()); diff --git a/clang/lib/CIR/Dialect/Transforms/StdHelpers.cpp b/clang/lib/CIR/Dialect/Transforms/StdHelpers.cpp index e6beada09786..93e19294feec 100644 --- a/clang/lib/CIR/Dialect/Transforms/StdHelpers.cpp +++ b/clang/lib/CIR/Dialect/Transforms/StdHelpers.cpp @@ -29,4 +29,4 @@ bool isStdArrayType(mlir::Type t) { } } // namespace cir -} // namespace mlir \ No newline at end of file +} // namespace mlir diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 895b9d319471..ca07a0568129 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -326,33 +326,30 @@ mlir::LLVM::Linkage convertLinkage(mlir::cir::GlobalLinkageKind linkage) { static void lowerNestedYield(mlir::cir::YieldOpKind targetKind, mlir::ConversionPatternRewriter &rewriter, - mlir::Region &body, - mlir::Block *dst) { + mlir::Region &body, mlir::Block *dst) { // top-level yields are lowered in matchAndRewrite of the parent operations auto isNested = [&](mlir::Operation *op) { return op->getParentRegion() != &body; }; - body.walk( - [&](mlir::Operation *op) { - if (!isNested(op)) - return mlir::WalkResult::advance(); + body.walk([&](mlir::Operation *op) { + if (!isNested(op)) + return mlir::WalkResult::advance(); - // don't process breaks/continues in nested loops and switches - if (isa(*op)) - return mlir::WalkResult::skip(); + // don't process breaks/continues in nested loops and switches + if (isa(*op)) + return mlir::WalkResult::skip(); - auto yield = dyn_cast(*op); - if (yield && yield.getKind() == targetKind) { - rewriter.setInsertionPoint(op); - rewriter.replaceOpWithNewOp(op, yield.getArgs(), dst); - } + auto yield = dyn_cast(*op); + if (yield && yield.getKind() == targetKind) { + rewriter.setInsertionPoint(op); + rewriter.replaceOpWithNewOp(op, yield.getArgs(), dst); + } - return mlir::WalkResult::advance(); - }); + return mlir::WalkResult::advance(); + }); } - class CIRCopyOpLowering : public mlir::OpConversionPattern { public: using mlir::OpConversionPattern::OpConversionPattern; @@ -406,25 +403,14 @@ class CIRLoopOpLowering : public mlir::OpConversionPattern { using mlir::OpConversionPattern::OpConversionPattern; using LoopKind = mlir::cir::LoopOpKind; - mlir::LogicalResult - fetchCondRegionYields(mlir::Region &condRegion, - mlir::cir::YieldOp &yieldToBody, - mlir::cir::YieldOp &yieldToCont) const { - for (auto &bb : condRegion) { - if (auto yieldOp = dyn_cast(bb.getTerminator())) { - if (!yieldOp.getKind().has_value()) - yieldToCont = yieldOp; - else if (yieldOp.getKind() == mlir::cir::YieldOpKind::Continue) - yieldToBody = yieldOp; - else - return mlir::failure(); - } - } - - // Succeed only if both yields are found. - if (!yieldToBody) - return mlir::failure(); - return mlir::success(); + inline void + lowerConditionOp(mlir::cir::ConditionOp op, mlir::Block *body, + mlir::Block *exit, + mlir::ConversionPatternRewriter &rewriter) const { + mlir::OpBuilder::InsertionGuard guard(rewriter); + rewriter.setInsertionPoint(op); + rewriter.replaceOpWithNewOp(op, op.getCondition(), + body, exit); } mlir::LogicalResult @@ -438,9 +424,6 @@ class CIRLoopOpLowering : public mlir::OpConversionPattern { // Fetch required info from the condition region. auto &condRegion = loopOp.getCond(); auto &condFrontBlock = condRegion.front(); - mlir::cir::YieldOp yieldToBody, yieldToCont; - if (fetchCondRegionYields(condRegion, yieldToBody, yieldToCont).failed()) - return loopOp.emitError("failed to fetch yields in cond region"); // Fetch required info from the body region. auto &bodyRegion = loopOp.getBody(); @@ -456,10 +439,10 @@ class CIRLoopOpLowering : public mlir::OpConversionPattern { dyn_cast(stepRegion.back().getTerminator()); auto &stepBlock = (kind == LoopKind::For ? stepFrontBlock : condFrontBlock); - lowerNestedYield(mlir::cir::YieldOpKind::Break, - rewriter, bodyRegion, continueBlock); - lowerNestedYield(mlir::cir::YieldOpKind::Continue, - rewriter, bodyRegion, &stepBlock); + lowerNestedYield(mlir::cir::YieldOpKind::Break, rewriter, bodyRegion, + continueBlock); + lowerNestedYield(mlir::cir::YieldOpKind::Continue, rewriter, bodyRegion, + &stepBlock); // Move loop op region contents to current CFG. rewriter.inlineRegionBefore(condRegion, continueBlock); @@ -472,15 +455,10 @@ class CIRLoopOpLowering : public mlir::OpConversionPattern { auto &entry = (kind != LoopKind::DoWhile ? condFrontBlock : bodyFrontBlock); rewriter.create(loopOp.getLoc(), &entry); - // Set loop exit point to continue block. - if (yieldToCont) { - rewriter.setInsertionPoint(yieldToCont); - rewriter.replaceOpWithNewOp(yieldToCont, continueBlock); - } - - // Branch from condition to body. - rewriter.setInsertionPoint(yieldToBody); - rewriter.replaceOpWithNewOp(yieldToBody, &bodyFrontBlock); + // Branch from condition region to body or exit. + auto conditionOp = + cast(condFrontBlock.getTerminator()); + lowerConditionOp(conditionOp, &bodyFrontBlock, continueBlock, rewriter); // Branch from body to condition or to step on for-loop cases. rewriter.setInsertionPoint(bodyYield); @@ -758,8 +736,8 @@ class CIRIfLowering : public mlir::OpConversionPattern { rewriter.setInsertionPointToEnd(elseAfterBody); if (auto elseYieldOp = dyn_cast(elseAfterBody->getTerminator())) { - if (!isBreakOrContinue(elseYieldOp)) // lowering of parent loop yields is - // deferred to loop lowering + if (!isBreakOrContinue(elseYieldOp)) // lowering of parent loop yields + // is deferred to loop lowering rewriter.replaceOpWithNewOp( elseYieldOp, elseYieldOp.getArgs(), continueBlock); } else if (!dyn_cast( @@ -873,23 +851,23 @@ class CIRCallLowering : public mlir::OpConversionPattern { mlir::ConversionPatternRewriter &rewriter) const override { llvm::SmallVector llvmResults; auto cirResults = op.getResultTypes(); - auto* converter = getTypeConverter(); + auto *converter = getTypeConverter(); if (converter->convertTypes(cirResults, llvmResults).failed()) return mlir::failure(); - if (auto callee = op.getCalleeAttr()) { // direct call + if (auto callee = op.getCalleeAttr()) { // direct call rewriter.replaceOpWithNewOp( - op, llvmResults, op.getCalleeAttr(), adaptor.getOperands()); + op, llvmResults, op.getCalleeAttr(), adaptor.getOperands()); } else { // indirect call - assert(op.getOperands().size() - && "operands list must no be empty for the indirect call"); - auto typ = op.getOperands().front().getType(); + assert(op.getOperands().size() && + "operands list must no be empty for the indirect call"); + auto typ = op.getOperands().front().getType(); assert(isa(typ) && "expected pointer type"); auto ptyp = dyn_cast(typ); auto ftyp = dyn_cast(ptyp.getPointee()); assert(ftyp && "expected a pointer to a function as the first operand"); - + rewriter.replaceOpWithNewOp( op, dyn_cast(converter->convertType(ftyp)), @@ -1391,7 +1369,7 @@ class CIRSwitchOpLowering fallthroughYieldOp = nullptr; } - for (auto& blk : region.getBlocks()) { + for (auto &blk : region.getBlocks()) { if (blk.getNumSuccessors()) continue; @@ -1412,7 +1390,7 @@ class CIRSwitchOpLowering rewriteYieldOp(rewriter, yieldOp, exitBlock); break; case mlir::cir::YieldOpKind::Continue: // Continue is handled only in - // loop lowering + // loop lowering break; default: return op->emitError("invalid yield kind in case statement"); @@ -1420,8 +1398,8 @@ class CIRSwitchOpLowering } } - lowerNestedYield(mlir::cir::YieldOpKind::Break, - rewriter, region, exitBlock); + lowerNestedYield(mlir::cir::YieldOpKind::Break, rewriter, region, + exitBlock); // Extract region contents before erasing the switch op. rewriter.inlineRegionBefore(region, exitBlock); @@ -2044,7 +2022,8 @@ class CIRVTableAddrPointOpLowering } }; -class CIRStackSaveLowering : public mlir::OpConversionPattern { +class CIRStackSaveLowering + : public mlir::OpConversionPattern { public: using OpConversionPattern::OpConversionPattern; @@ -2057,16 +2036,16 @@ class CIRStackSaveLowering : public mlir::OpConversionPattern { +class CIRStackRestoreLowering + : public mlir::OpConversionPattern { public: using OpConversionPattern::OpConversionPattern; mlir::LogicalResult matchAndRewrite(mlir::cir::StackRestoreOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const override { - rewriter.replaceOpWithNewOp( - op, - adaptor.getPtr()); + rewriter.replaceOpWithNewOp(op, + adaptor.getPtr()); return mlir::success(); } }; @@ -2074,19 +2053,18 @@ class CIRStackRestoreLowering : public mlir::OpConversionPattern(patterns.getContext()); - patterns.add( + patterns.add< + CIRCmpOpLowering, CIRLoopOpLowering, CIRBrCondOpLowering, + CIRPtrStrideOpLowering, CIRCallLowering, CIRUnaryOpLowering, + CIRBinOpLowering, CIRShiftOpLowering, CIRLoadLowering, + CIRConstantLowering, CIRStoreLowering, CIRAllocaLowering, CIRFuncLowering, + CIRScopeOpLowering, CIRCastOpLowering, CIRIfLowering, CIRGlobalOpLowering, + CIRGetGlobalOpLowering, CIRVAStartLowering, CIRVAEndLowering, + CIRVACopyLowering, CIRVAArgLowering, CIRBrOpLowering, + CIRTernaryOpLowering, CIRGetMemberOpLowering, CIRSwitchOpLowering, + CIRPtrDiffOpLowering, CIRCopyOpLowering, CIRMemCpyOpLowering, + CIRFAbsOpLowering, CIRVTableAddrPointOpLowering, CIRVectorCreateLowering, + CIRVectorExtractLowering, CIRStackSaveLowering, CIRStackRestoreLowering>( converter, patterns.getContext()); } diff --git a/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp b/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp index 0853eeb87782..e0a06c5bf401 100644 --- a/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp +++ b/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp @@ -74,7 +74,7 @@ struct ConvertCIRToMLIRPass virtual StringRef getArgument() const override { return "cir-to-mlir"; } }; -class CIRCallLowering : public mlir::OpConversionPattern { +class CIRCallOpLowering : public mlir::OpConversionPattern { public: using OpConversionPattern::OpConversionPattern; @@ -91,7 +91,7 @@ class CIRCallLowering : public mlir::OpConversionPattern { } }; -class CIRAllocaLowering +class CIRAllocaOpLowering : public mlir::OpConversionPattern { public: using OpConversionPattern::OpConversionPattern; @@ -109,7 +109,7 @@ class CIRAllocaLowering } }; -class CIRLoadLowering : public mlir::OpConversionPattern { +class CIRLoadOpLowering : public mlir::OpConversionPattern { public: using OpConversionPattern::OpConversionPattern; @@ -121,7 +121,8 @@ class CIRLoadLowering : public mlir::OpConversionPattern { } }; -class CIRStoreLowering : public mlir::OpConversionPattern { +class CIRStoreOpLowering + : public mlir::OpConversionPattern { public: using OpConversionPattern::OpConversionPattern; @@ -134,7 +135,7 @@ class CIRStoreLowering : public mlir::OpConversionPattern { } }; -class CIRConstantLowering +class CIRConstantOpLowering : public mlir::OpConversionPattern { public: using OpConversionPattern::OpConversionPattern; @@ -158,7 +159,7 @@ class CIRConstantLowering } }; -class CIRFuncLowering : public mlir::OpConversionPattern { +class CIRFuncOpLowering : public mlir::OpConversionPattern { public: using OpConversionPattern::OpConversionPattern; @@ -602,9 +603,9 @@ void populateCIRToMLIRConversionPatterns(mlir::RewritePatternSet &patterns, mlir::TypeConverter &converter) { patterns.add(patterns.getContext()); - patterns.add(converter, patterns.getContext()); } diff --git a/clang/test/CIR/CodeGen/loop.cpp b/clang/test/CIR/CodeGen/loop.cpp index 3472706fad78..6d6c93e08094 100644 --- a/clang/test/CIR/CodeGen/loop.cpp +++ b/clang/test/CIR/CodeGen/loop.cpp @@ -8,12 +8,8 @@ void l0() { // CHECK: cir.func @_Z2l0v // CHECK: cir.loop for(cond : { -// CHECK-NEXT: cir.yield continue -// CHECK-NEXT: }, step : { -// CHECK-NEXT: cir.yield -// CHECK-NEXT: }) { -// CHECK-NEXT: cir.yield -// CHECK-NEXT: } +// CHECK: %[[#TRUE:]] = cir.const(#true) : !cir.bool +// CHECK: cir.condition(%[[#TRUE]]) void l1() { int x = 0; @@ -27,11 +23,7 @@ void l1() { // CHECK-NEXT: %4 = cir.load %2 : cir.ptr , !s32i // CHECK-NEXT: %5 = cir.const(#cir.int<10> : !s32i) : !s32i // CHECK-NEXT: %6 = cir.cmp(lt, %4, %5) : !s32i, !cir.bool -// CHECK-NEXT: cir.brcond %6 ^bb1, ^bb2 -// CHECK-NEXT: ^bb1: -// CHECK-NEXT: cir.yield continue -// CHECK-NEXT: ^bb2: -// CHECK-NEXT: cir.yield +// CHECK-NEXT: cir.condition(%6) // CHECK-NEXT: }, step : { // CHECK-NEXT: %4 = cir.load %2 : cir.ptr , !s32i // CHECK-NEXT: %5 = cir.const(#cir.int<1> : !s32i) : !s32i @@ -63,11 +55,7 @@ void l2(bool cond) { // CHECK: cir.scope { // CHECK-NEXT: cir.loop while(cond : { // CHECK-NEXT: %3 = cir.load %0 : cir.ptr , !cir.bool -// CHECK-NEXT: cir.brcond %3 ^bb1, ^bb2 -// CHECK-NEXT: ^bb1: -// CHECK-NEXT: cir.yield continue -// CHECK-NEXT: ^bb2: -// CHECK-NEXT: cir.yield +// CHECK-NEXT: cir.condition(%3) // CHECK-NEXT: }, step : { // CHECK-NEXT: cir.yield // CHECK-NEXT: }) { @@ -80,7 +68,8 @@ void l2(bool cond) { // CHECK-NEXT: } // CHECK-NEXT: cir.scope { // CHECK-NEXT: cir.loop while(cond : { -// CHECK-NEXT: cir.yield continue +// CHECK-NEXT: %[[#TRUE:]] = cir.const(#true) : !cir.bool +// CHECK-NEXT: cir.condition(%[[#TRUE]]) // CHECK-NEXT: }, step : { // CHECK-NEXT: cir.yield // CHECK-NEXT: }) { @@ -95,11 +84,7 @@ void l2(bool cond) { // CHECK-NEXT: cir.loop while(cond : { // CHECK-NEXT: %3 = cir.const(#cir.int<1> : !s32i) : !s32i // CHECK-NEXT: %4 = cir.cast(int_to_bool, %3 : !s32i), !cir.bool -// CHECK-NEXT: cir.brcond %4 ^bb1, ^bb2 -// CHECK-NEXT: ^bb1: -// CHECK-NEXT: cir.yield continue -// CHECK-NEXT: ^bb2: -// CHECK-NEXT: cir.yield +// CHECK-NEXT: cir.condition(%4) // CHECK-NEXT: }, step : { // CHECK-NEXT: cir.yield // CHECK-NEXT: }) { @@ -127,12 +112,8 @@ void l3(bool cond) { // CHECK: cir.func @_Z2l3b // CHECK: cir.scope { // CHECK-NEXT: cir.loop dowhile(cond : { -// CHECK-NEXT: %3 = cir.load %0 : cir.ptr , !cir.bool -// CHECK-NEXT: cir.brcond %3 ^bb1, ^bb2 -// CHECK-NEXT: ^bb1: -// CHECK-NEXT: cir.yield continue -// CHECK-NEXT: ^bb2: -// CHECK-NEXT: cir.yield +// CHECK-NEXT: %[[#TRUE:]] = cir.load %0 : cir.ptr , !cir.bool +// CHECK-NEXT: cir.condition(%[[#TRUE]]) // CHECK-NEXT: }, step : { // CHECK-NEXT: cir.yield // CHECK-NEXT: }) { @@ -145,7 +126,8 @@ void l3(bool cond) { // CHECK-NEXT: } // CHECK-NEXT: cir.scope { // CHECK-NEXT: cir.loop dowhile(cond : { -// CHECK-NEXT: cir.yield continue +// CHECK-NEXT: %[[#TRUE:]] = cir.const(#true) : !cir.bool +// CHECK-NEXT: cir.condition(%[[#TRUE]]) // CHECK-NEXT: }, step : { // CHECK-NEXT: cir.yield // CHECK-NEXT: }) { @@ -160,11 +142,7 @@ void l3(bool cond) { // CHECK-NEXT: cir.loop dowhile(cond : { // CHECK-NEXT: %3 = cir.const(#cir.int<1> : !s32i) : !s32i // CHECK-NEXT: %4 = cir.cast(int_to_bool, %3 : !s32i), !cir.bool -// CHECK-NEXT: cir.brcond %4 ^bb1, ^bb2 -// CHECK-NEXT: ^bb1: -// CHECK-NEXT: cir.yield continue -// CHECK-NEXT: ^bb2: -// CHECK-NEXT: cir.yield +// CHECK-NEXT: cir.condition(%4) // CHECK-NEXT: }, step : { // CHECK-NEXT: cir.yield // CHECK-NEXT: }) { @@ -188,7 +166,8 @@ void l4() { // CHECK: cir.func @_Z2l4v // CHECK: cir.loop while(cond : { -// CHECK-NEXT: cir.yield continue +// CHECK-NEXT: %[[#TRUE:]] = cir.const(#true) : !cir.bool +// CHECK-NEXT: cir.condition(%[[#TRUE]]) // CHECK-NEXT: }, step : { // CHECK-NEXT: cir.yield // CHECK-NEXT: }) { @@ -215,11 +194,7 @@ void l5() { // CHECK-NEXT: cir.loop dowhile(cond : { // CHECK-NEXT: %0 = cir.const(#cir.int<0> : !s32i) : !s32i // CHECK-NEXT: %1 = cir.cast(int_to_bool, %0 : !s32i), !cir.bool -// CHECK-NEXT: cir.brcond %1 ^bb1, ^bb2 -// CHECK-NEXT: ^bb1: -// CHECK-NEXT: cir.yield continue -// CHECK-NEXT: ^bb2: -// CHECK-NEXT: cir.yield +// CHECK-NEXT: cir.condition(%1) // CHECK-NEXT: }, step : { // CHECK-NEXT: cir.yield // CHECK-NEXT: }) { @@ -238,7 +213,8 @@ void l6() { // CHECK: cir.func @_Z2l6v() // CHECK-NEXT: cir.scope { // CHECK-NEXT: cir.loop while(cond : { -// CHECK-NEXT: cir.yield continue +// CHECK-NEXT: %[[#TRUE:]] = cir.const(#true) : !cir.bool +// CHECK-NEXT: cir.condition(%[[#TRUE]]) // CHECK-NEXT: }, step : { // CHECK-NEXT: cir.yield // CHECK-NEXT: }) { diff --git a/clang/test/CIR/CodeGen/rangefor.cpp b/clang/test/CIR/CodeGen/rangefor.cpp index d1e16503ae1f..890136df7a88 100644 --- a/clang/test/CIR/CodeGen/rangefor.cpp +++ b/clang/test/CIR/CodeGen/rangefor.cpp @@ -46,11 +46,7 @@ void init(unsigned numImages) { // CHECK: cir.store %11, %6 : ![[VEC_IT]], cir.ptr // CHECK: cir.loop for(cond : { // CHECK: %12 = cir.call @_ZNK17__vector_iteratorI6triplePS0_RS0_EneERKS3_(%5, %6) : (!cir.ptr, !cir.ptr) -> !cir.bool -// CHECK: cir.brcond %12 ^bb1, ^bb2 -// CHECK: ^bb1: // pred: ^bb0 -// CHECK: cir.yield continue -// CHECK: ^bb2: // pred: ^bb0 -// CHECK: cir.yield +// CHECK: cir.condition(%12) // CHECK: }, step : { // CHECK: %12 = cir.call @_ZN17__vector_iteratorI6triplePS0_RS0_EppEv(%5) : (!cir.ptr) -> !cir.ptr // CHECK: cir.yield diff --git a/clang/test/CIR/IR/branch.cir b/clang/test/CIR/IR/branch.cir index 6f75d9e25bd3..7f418908a94c 100644 --- a/clang/test/CIR/IR/branch.cir +++ b/clang/test/CIR/IR/branch.cir @@ -1,60 +1,21 @@ // RUN: cir-opt %s | FileCheck %s -#false = #cir.bool : !cir.bool -#true = #cir.bool : !cir.bool - -cir.func @b0() { - cir.scope { - cir.loop while(cond : { - %0 = cir.const(#true) : !cir.bool - cir.brcond %0 ^bb1, ^bb2 - ^bb1: - cir.yield continue - ^bb2: - cir.yield - }, step : { - cir.yield - }) { - cir.br ^bb1 - ^bb1: - cir.return - } - } +cir.func @test_branch_parsing(%arg0: !cir.bool) { + // CHECK: cir.br ^bb1 + cir.br ^bb1 +^bb1: + // CHECK: cir.br ^bb2(%arg0 : !cir.bool) + cir.br ^bb2(%arg0 : !cir.bool) +// CHECK: ^bb2(%0: !cir.bool): +^bb2(%x: !cir.bool): cir.return } -// CHECK: cir.func @b0 -// CHECK-NEXT: cir.scope { -// CHECK-NEXT: cir.loop while(cond : { -// CHECK-NEXT: %0 = cir.const(#true) : !cir.bool -// CHECK-NEXT: cir.brcond %0 ^bb1, ^bb2 -// CHECK-NEXT: ^bb1: -// CHECK-NEXT: cir.yield continue -// CHECK-NEXT: ^bb2: -// CHECK-NEXT: cir.yield -// CHECK-NEXT: }, step : { -// CHECK-NEXT: cir.yield -// CHECK-NEXT: }) { -// CHECK-NEXT: cir.br ^bb1 -// CHECK-NEXT: ^bb1: -// CHECK-NEXT: cir.return -// CHECK-NEXT: } -// CHECK-NEXT: } -// CHECK-NEXT: cir.return -// CHECK-NEXT: } - - -!s32i = !cir.int -cir.func @test_br() -> !s32i { - %0 = cir.const(#cir.int<0>: !s32i) : !s32i - cir.br ^bb1(%0 : !s32i) - ^bb1(%x: !s32i): - cir.return %x : !s32i +cir.func @test_conditional_branch_parsing(%arg0 : !cir.bool) { + // CHEK: cir.brcond %arg0 ^bb1, ^bb2 + cir.brcond %arg0 ^bb1, ^bb2 +^bb1: + cir.return +^bb2: + cir.return } - -// CHECK: cir.func @test_br() -> !s32i { -// CHECK-NEXT: %0 = cir.const(#cir.int<0> : !s32i) : !s32i -// CHECK-NEXT: cir.br ^bb1(%0 : !s32i) -// CHECK-NEXT: ^bb1(%1: !s32i): // pred: ^bb0 -// CHECK-NEXT: cir.return %1 : !s32i -// CHECK-NEXT: } diff --git a/clang/test/CIR/IR/invalid.cir b/clang/test/CIR/IR/invalid.cir index 278909d59850..d353c7d7b878 100644 --- a/clang/test/CIR/IR/invalid.cir +++ b/clang/test/CIR/IR/invalid.cir @@ -318,13 +318,8 @@ cir.func @cast24(%p : !u32i) { #true = #cir.bool : !cir.bool cir.func @b0() { cir.scope { - cir.loop while(cond : { // expected-error {{cond region must be terminated with 'cir.yield' or 'cir.yield continue'}} - %0 = cir.const(#true) : !cir.bool - cir.brcond %0 ^bb1, ^bb2 - ^bb1: - cir.yield break - ^bb2: - cir.yield + cir.loop while(cond : { // expected-error {{cond region terminate with 'cir.condition'}} + cir.yield }, step : { cir.yield }) { diff --git a/clang/test/CIR/IR/loop.cir b/clang/test/CIR/IR/loop.cir index ac9658a304d3..798aaaeb5ae9 100644 --- a/clang/test/CIR/IR/loop.cir +++ b/clang/test/CIR/IR/loop.cir @@ -15,11 +15,7 @@ cir.func @l0() { %4 = cir.load %2 : cir.ptr , !u32i %5 = cir.const(#cir.int<10> : !u32i) : !u32i %6 = cir.cmp(lt, %4, %5) : !u32i, !cir.bool - cir.brcond %6 ^bb1, ^bb2 - ^bb1: - cir.yield continue - ^bb2: - cir.yield + cir.condition(%6) }, step : { %4 = cir.load %2 : cir.ptr , !u32i %5 = cir.const(#cir.int<1> : !u32i) : !u32i @@ -46,11 +42,7 @@ cir.func @l0() { %4 = cir.load %2 : cir.ptr , !u32i %5 = cir.const(#cir.int<10> : !u32i) : !u32i %6 = cir.cmp(lt, %4, %5) : !u32i, !cir.bool - cir.brcond %6 ^bb1, ^bb2 - ^bb1: - cir.yield continue - ^bb2: - cir.yield + cir.condition(%6) }, step : { cir.yield }) { @@ -74,11 +66,7 @@ cir.func @l0() { %4 = cir.load %2 : cir.ptr , !u32i %5 = cir.const(#cir.int<10> : !u32i) : !u32i %6 = cir.cmp(lt, %4, %5) : !u32i, !cir.bool - cir.brcond %6 ^bb1, ^bb2 - ^bb1: - cir.yield continue - ^bb2: - cir.yield + cir.condition(%6) }, step : { cir.yield }) { @@ -97,11 +85,7 @@ cir.func @l0() { // CHECK-NEXT: %4 = cir.load %2 : cir.ptr , !u32i // CHECK-NEXT: %5 = cir.const(#cir.int<10> : !u32i) : !u32i // CHECK-NEXT: %6 = cir.cmp(lt, %4, %5) : !u32i, !cir.bool -// CHECK-NEXT: cir.brcond %6 ^bb1, ^bb2 -// CHECK-NEXT: ^bb1: -// CHECK-NEXT: cir.yield continue -// CHECK-NEXT: ^bb2: -// CHECK-NEXT: cir.yield +// CHECK-NEXT: cir.condition(%6) // CHECK-NEXT: }, step : { // CHECK-NEXT: %4 = cir.load %2 : cir.ptr , !u32i // CHECK-NEXT: %5 = cir.const(#cir.int<1> : !u32i) : !u32i @@ -124,11 +108,7 @@ cir.func @l0() { // CHECK-NEXT: %4 = cir.load %2 : cir.ptr , !u32i // CHECK-NEXT: %5 = cir.const(#cir.int<10> : !u32i) : !u32i // CHECK-NEXT: %6 = cir.cmp(lt, %4, %5) : !u32i, !cir.bool -// CHECK-NEXT: cir.brcond %6 ^bb1, ^bb2 -// CHECK-NEXT: ^bb1: -// CHECK-NEXT: cir.yield continue -// CHECK-NEXT: ^bb2: -// CHECK-NEXT: cir.yield +// CHECK-NEXT: cir.condition(%6) // CHECK-NEXT: }, step : { // CHECK-NEXT: cir.yield // CHECK-NEXT: }) { @@ -147,11 +127,7 @@ cir.func @l0() { // CHECK-NEXT: %4 = cir.load %2 : cir.ptr , !u32i // CHECK-NEXT: %5 = cir.const(#cir.int<10> : !u32i) : !u32i // CHECK-NEXT: %6 = cir.cmp(lt, %4, %5) : !u32i, !cir.bool -// CHECK-NEXT: cir.brcond %6 ^bb1, ^bb2 -// CHECK-NEXT: ^bb1: -// CHECK-NEXT: cir.yield continue -// CHECK-NEXT: ^bb2: -// CHECK-NEXT: cir.yield +// CHECK-NEXT: cir.condition(%6) // CHECK-NEXT: }, step : { // CHECK-NEXT: cir.yield // CHECK-NEXT: }) { @@ -162,10 +138,10 @@ cir.func @l0() { // CHECK-NEXT: cir.yield // CHECK-NEXT: } -cir.func @l1() { +cir.func @l1(%arg0 : !cir.bool) { cir.scope { cir.loop while(cond : { - cir.yield continue + cir.condition(%arg0) }, step : { cir.yield }) { @@ -178,7 +154,7 @@ cir.func @l1() { // CHECK: cir.func @l1 // CHECK-NEXT: cir.scope { // CHECK-NEXT: cir.loop while(cond : { -// CHECK-NEXT: cir.yield continue +// CHECK-NEXT: cir.condition(%arg0) // CHECK-NEXT: }, step : { // CHECK-NEXT: cir.yield // CHECK-NEXT: }) { @@ -188,10 +164,10 @@ cir.func @l1() { // CHECK-NEXT: cir.return // CHECK-NEXT: } -cir.func @l2() { +cir.func @l2(%arg0 : !cir.bool) { cir.scope { cir.loop while(cond : { - cir.yield + cir.condition(%arg0) }, step : { cir.yield }) { @@ -204,7 +180,7 @@ cir.func @l2() { // CHECK: cir.func @l2 // CHECK-NEXT: cir.scope { // CHECK-NEXT: cir.loop while(cond : { -// CHECK-NEXT: cir.yield +// CHECK-NEXT: cir.condition(%arg0) // CHECK-NEXT: }, step : { // CHECK-NEXT: cir.yield // CHECK-NEXT: }) { diff --git a/clang/test/CIR/Lowering/dot.cir b/clang/test/CIR/Lowering/dot.cir index e889dcd05827..4f588e1f05f9 100644 --- a/clang/test/CIR/Lowering/dot.cir +++ b/clang/test/CIR/Lowering/dot.cir @@ -1,4 +1,4 @@ -// RUN: cir-opt %s -cir-to-llvm -o %t.mlir +// RUN: cir-opt %s -cir-to-llvm --reconcile-unrealized-casts -o %t.mlir // RUN: FileCheck --input-file=%t.mlir %s -check-prefix=MLIR !s32i = !cir.int @@ -23,11 +23,7 @@ module { %11 = cir.load %2 : cir.ptr , !s32i %12 = cir.cmp(lt, %10, %11) : !s32i, !s32i %13 = cir.cast(int_to_bool, %12 : !s32i), !cir.bool - cir.brcond %13 ^bb1, ^bb2 - ^bb1: // pred: ^bb0 - cir.yield continue - ^bb2: // pred: ^bb0 - cir.yield + cir.condition(%13) }, step : { %10 = cir.load %8 : cir.ptr , !s32i %11 = cir.unary(inc, %10) : !s32i, !s32i @@ -80,7 +76,7 @@ module { // MLIR-NEXT: %13 = llvm.mlir.constant(0 : i32) : i32 // MLIR-NEXT: llvm.store %13, %12 : i32, !llvm.ptr // MLIR-NEXT: llvm.br ^bb2 -// MLIR-NEXT: ^bb2: // 2 preds: ^bb1, ^bb6 +// MLIR-NEXT: ^bb2: // 2 preds: ^bb1, ^bb4 // MLIR-NEXT: %14 = llvm.load %12 : !llvm.ptr -> i32 // MLIR-NEXT: %15 = llvm.load %5 : !llvm.ptr -> i32 // MLIR-NEXT: %16 = llvm.icmp "slt" %14, %15 : i32 @@ -89,12 +85,8 @@ module { // MLIR-NEXT: %19 = llvm.icmp "ne" %17, %18 : i32 // MLIR-NEXT: %20 = llvm.zext %19 : i1 to i8 // MLIR-NEXT: %21 = llvm.trunc %20 : i8 to i1 -// MLIR-NEXT: llvm.cond_br %21, ^bb3, ^bb4 +// MLIR-NEXT: llvm.cond_br %21, ^bb3, ^bb5 // MLIR-NEXT: ^bb3: // pred: ^bb2 -// MLIR-NEXT: llvm.br ^bb5 -// MLIR-NEXT: ^bb4: // pred: ^bb2 -// MLIR-NEXT: llvm.br ^bb7 -// MLIR-NEXT: ^bb5: // pred: ^bb3 // MLIR-NEXT: %22 = llvm.load %1 : !llvm.ptr -> !llvm.ptr // MLIR-NEXT: %23 = llvm.load %12 : !llvm.ptr -> i32 // MLIR-NEXT: %24 = llvm.getelementptr %22[%23] : (!llvm.ptr, i32) -> !llvm.ptr, f64 @@ -107,16 +99,16 @@ module { // MLIR-NEXT: %31 = llvm.load %9 : !llvm.ptr -> f64 // MLIR-NEXT: %32 = llvm.fadd %31, %30 : f64 // MLIR-NEXT: llvm.store %32, %9 : f64, !llvm.ptr -// MLIR-NEXT: llvm.br ^bb6 -// MLIR-NEXT: ^bb6: // pred: ^bb5 +// MLIR-NEXT: llvm.br ^bb4 +// MLIR-NEXT: ^bb4: // pred: ^bb3 // MLIR-NEXT: %33 = llvm.load %12 : !llvm.ptr -> i32 // MLIR-NEXT: %34 = llvm.mlir.constant(1 : i32) : i32 // MLIR-NEXT: %35 = llvm.add %33, %34 : i32 // MLIR-NEXT: llvm.store %35, %12 : i32, !llvm.ptr // MLIR-NEXT: llvm.br ^bb2 -// MLIR-NEXT: ^bb7: // pred: ^bb4 -// MLIR-NEXT: llvm.br ^bb8 -// MLIR-NEXT: ^bb8: // pred: ^bb7 +// MLIR-NEXT: ^bb5: // pred: ^bb2 +// MLIR-NEXT: llvm.br ^bb6 +// MLIR-NEXT: ^bb6: // pred: ^bb5 // MLIR-NEXT: %36 = llvm.load %9 : !llvm.ptr -> f64 // MLIR-NEXT: llvm.store %36, %7 : f64, !llvm.ptr // MLIR-NEXT: %37 = llvm.load %7 : !llvm.ptr -> f64 diff --git a/clang/test/CIR/Lowering/loop.cir b/clang/test/CIR/Lowering/loop.cir index 685792a5b342..bbe42d179273 100644 --- a/clang/test/CIR/Lowering/loop.cir +++ b/clang/test/CIR/Lowering/loop.cir @@ -1,26 +1,15 @@ // RUN: cir-opt %s -cir-to-llvm -o %t.mlir -// RUN: FileCheck --input-file=%t.mlir %s -check-prefix=MLIR - +// RUN: FileCheck --input-file=%t.mlir %s +#true = #cir.bool : !cir.bool !s32i = !cir.int + + module { - cir.func @testFor() { - %0 = cir.alloca !s32i, cir.ptr , ["i", init] {alignment = 4 : i64} - %1 = cir.const(#cir.int<0> : !s32i) : !s32i - cir.store %1, %0 : !s32i, cir.ptr + + cir.func @testFor(%arg0 : !cir.bool) { cir.loop for(cond : { - %2 = cir.load %0 : cir.ptr , !s32i - %3 = cir.const(#cir.int<10> : !s32i) : !s32i - %4 = cir.cmp(lt, %2, %3) : !s32i, !s32i - %5 = cir.cast(int_to_bool, %4 : !s32i), !cir.bool - cir.brcond %5 ^bb1, ^bb2 - ^bb1: // pred: ^bb0 - cir.yield continue - ^bb2: // pred: ^bb0 - cir.yield + cir.condition(%arg0) }, step : { - %2 = cir.load %0 : cir.ptr , !s32i - %3 = cir.unary(inc, %2) : !s32i, !s32i - cir.store %3, %0 : !s32i, cir.ptr cir.yield }) { cir.yield @@ -28,271 +17,116 @@ module { cir.return } -// MLIR: module { -// MLIR-NEXT: llvm.func @testFor() -// MLIR-NEXT: %0 = llvm.mlir.constant(1 : index) : i64 -// MLIR-NEXT: %1 = llvm.alloca %0 x i32 {alignment = 4 : i64} : (i64) -> !llvm.ptr -// MLIR-NEXT: %2 = llvm.mlir.constant(0 : i32) : i32 -// MLIR-NEXT: llvm.store %2, %1 : i32, !llvm.ptr -// MLIR-NEXT: llvm.br ^bb1 -// ============= Condition block ============= -// MLIR-NEXT: ^bb1: // 2 preds: ^bb0, ^bb5 -// MLIR-NEXT: %3 = llvm.load %1 : !llvm.ptr -> i32 -// MLIR-NEXT: %4 = llvm.mlir.constant(10 : i32) : i32 -// MLIR-NEXT: %5 = llvm.icmp "slt" %3, %4 : i32 -// MLIR-NEXT: %6 = llvm.zext %5 : i1 to i32 -// MLIR-NEXT: %7 = llvm.mlir.constant(0 : i32) : i32 -// MLIR-NEXT: %8 = llvm.icmp "ne" %6, %7 : i32 -// MLIR-NEXT: %9 = llvm.zext %8 : i1 to i8 -// MLIR-NEXT: %10 = llvm.trunc %9 : i8 to i1 -// MLIR-NEXT: llvm.cond_br %10, ^bb2, ^bb3 -// MLIR-NEXT: ^bb2: // pred: ^bb1 -// MLIR-NEXT: llvm.br ^bb4 -// MLIR-NEXT: ^bb3: // pred: ^bb1 -// MLIR-NEXT: llvm.br ^bb6 -// ============= Body block ============= -// MLIR-NEXT: ^bb4: // pred: ^bb2 -// MLIR-NEXT: llvm.br ^bb5 -// ============= Step block ============= -// MLIR-NEXT: ^bb5: // pred: ^bb4 -// MLIR-NEXT: %11 = llvm.load %1 : !llvm.ptr -> i32 -// MLIR-NEXT: %12 = llvm.mlir.constant(1 : i32) : i32 -// MLIR-NEXT: %13 = llvm.add %11, %12 : i32 -// MLIR-NEXT: llvm.store %13, %1 : i32, !llvm.ptr -// MLIR-NEXT: llvm.br ^bb1 -// ============= Exit block ============= -// MLIR-NEXT: ^bb6: // pred: ^bb3 -// MLIR-NEXT: llvm.return -// MLIR-NEXT: } +// CHECK: @testFor +// CHECK: llvm.br ^bb[[#COND:]] +// CHECK: ^bb[[#COND]]: +// CHECK: llvm.cond_br %{{.+}}, ^bb[[#BODY:]], ^bb[[#EXIT:]] +// CHECK: ^bb[[#BODY]]: +// CHECK: llvm.br ^bb[[#STEP:]] +// CHECK: ^bb[[#STEP]]: +// CHECK: llvm.br ^bb[[#COND]] +// CHECK: ^bb[[#EXIT]]: + + // Test while cir.loop operation lowering. - cir.func @testWhile(%arg0: !s32i) { - %0 = cir.alloca !s32i, cir.ptr , ["i", init] {alignment = 4 : i64} - cir.store %arg0, %0 : !s32i, cir.ptr - cir.scope { - cir.loop while(cond : { - %1 = cir.load %0 : cir.ptr , !s32i - %2 = cir.const(#cir.int<10> : !s32i) : !s32i - %3 = cir.cmp(lt, %1, %2) : !s32i, !s32i - %4 = cir.cast(int_to_bool, %3 : !s32i), !cir.bool - cir.brcond %4 ^bb1, ^bb2 - ^bb1: // pred: ^bb0 - cir.yield continue - ^bb2: // pred: ^bb0 - cir.yield - }, step : { - cir.yield - }) { - %1 = cir.load %0 : cir.ptr , !s32i - %2 = cir.unary(inc, %1) : !s32i, !s32i - cir.store %2, %0 : !s32i, cir.ptr - cir.yield - } + cir.func @testWhile(%arg0 : !cir.bool) { + cir.loop while(cond : { + cir.condition(%arg0) + }, step : { // Droped when lowering while statements. + cir.yield + }) { + cir.yield } cir.return } - // MLIR: llvm.func @testWhile(%arg0: i32) - // MLIR-NEXT: %0 = llvm.mlir.constant(1 : index) : i64 - // MLIR-NEXT: %1 = llvm.alloca %0 x i32 {alignment = 4 : i64} : (i64) -> !llvm.ptr - // MLIR-NEXT: llvm.store %arg0, %1 : i32, !llvm.ptr - // MLIR-NEXT: llvm.br ^bb1 - // MLIR-NEXT: ^bb1: - // MLIR-NEXT: llvm.br ^bb2 - // ============= Condition block ============= - // MLIR-NEXT: ^bb2: // 2 preds: ^bb1, ^bb5 - // MLIR-NEXT: %2 = llvm.load %1 : !llvm.ptr -> i32 - // MLIR-NEXT: %3 = llvm.mlir.constant(10 : i32) : i32 - // MLIR-NEXT: %4 = llvm.icmp "slt" %2, %3 : i32 - // MLIR-NEXT: %5 = llvm.zext %4 : i1 to i32 - // MLIR-NEXT: %6 = llvm.mlir.constant(0 : i32) : i32 - // MLIR-NEXT: %7 = llvm.icmp "ne" %5, %6 : i32 - // MLIR-NEXT: %8 = llvm.zext %7 : i1 to i8 - // MLIR-NEXT: %9 = llvm.trunc %8 : i8 to i1 - // MLIR-NEXT: llvm.cond_br %9, ^bb3, ^bb4 - // MLIR-NEXT: ^bb3: // pred: ^bb2 - // MLIR-NEXT: llvm.br ^bb5 - // MLIR-NEXT: ^bb4: // pred: ^bb2 - // MLIR-NEXT: llvm.br ^bb6 - // ============= Body block ============= - // MLIR-NEXT: ^bb5: // pred: ^bb3 - // MLIR-NEXT: %10 = llvm.load %1 : !llvm.ptr -> i32 - // MLIR-NEXT: %11 = llvm.mlir.constant(1 : i32) : i32 - // MLIR-NEXT: %12 = llvm.add %10, %11 : i32 - // MLIR-NEXT: llvm.store %12, %1 : i32, !llvm.ptr - // MLIR-NEXT: llvm.br ^bb2 - // ============= Exit block ============= - // MLIR-NEXT: ^bb6: // pred: ^bb4 - // MLIR-NEXT: llvm.br ^bb7 +// CHECK: @testWhile +// CHECK: llvm.br ^bb[[#COND:]] +// CHECK: ^bb[[#COND]]: +// CHECK: llvm.cond_br %{{.+}}, ^bb[[#BODY:]], ^bb[[#EXIT:]] +// CHECK: ^bb[[#BODY]]: +// CHECK: llvm.br ^bb[[#COND]] +// CHECK: ^bb[[#EXIT]]: + + // Test do-while cir.loop operation lowering. - cir.func @testDoWhile(%arg0: !s32i) { - %0 = cir.alloca !s32i, cir.ptr , ["i", init] {alignment = 4 : i64} - cir.store %arg0, %0 : !s32i, cir.ptr - cir.scope { - cir.loop dowhile(cond : { - %1 = cir.load %0 : cir.ptr , !s32i - %2 = cir.const(#cir.int<10> : !s32i) : !s32i - %3 = cir.cmp(lt, %1, %2) : !s32i, !s32i - %4 = cir.cast(int_to_bool, %3 : !s32i), !cir.bool - cir.brcond %4 ^bb1, ^bb2 - ^bb1: // pred: ^bb0 - cir.yield continue - ^bb2: // pred: ^bb0 - cir.yield - }, step : { - cir.yield - }) { - %1 = cir.load %0 : cir.ptr , !s32i - %2 = cir.unary(inc, %1) : !s32i, !s32i - cir.store %2, %0 : !s32i, cir.ptr - cir.yield - } + cir.func @testDoWhile(%arg0 : !cir.bool) { + cir.loop dowhile(cond : { + cir.condition(%arg0) + }, step : { // Droped when lowering while statements. + cir.yield + }) { + cir.yield } cir.return } - // MLIR: llvm.func @testDoWhile(%arg0: i32) - // MLIR-NEXT: %0 = llvm.mlir.constant(1 : index) : i64 - // MLIR-NEXT: %1 = llvm.alloca %0 x i32 {alignment = 4 : i64} : (i64) -> !llvm.ptr - // MLIR-NEXT: llvm.store %arg0, %1 : i32, !llvm.ptr - // MLIR-NEXT: llvm.br ^bb1 - // MLIR-NEXT: ^bb1: - // MLIR-NEXT: llvm.br ^bb5 - // ============= Condition block ============= - // MLIR-NEXT: ^bb2: - // MLIR-NEXT: %2 = llvm.load %1 : !llvm.ptr -> i32 - // MLIR-NEXT: %3 = llvm.mlir.constant(10 : i32) : i32 - // MLIR-NEXT: %4 = llvm.icmp "slt" %2, %3 : i32 - // MLIR-NEXT: %5 = llvm.zext %4 : i1 to i32 - // MLIR-NEXT: %6 = llvm.mlir.constant(0 : i32) : i32 - // MLIR-NEXT: %7 = llvm.icmp "ne" %5, %6 : i32 - // MLIR-NEXT: %8 = llvm.zext %7 : i1 to i8 - // MLIR-NEXT: %9 = llvm.trunc %8 : i8 to i1 - // MLIR-NEXT: llvm.cond_br %9, ^bb3, ^bb4 - // MLIR-NEXT: ^bb3: - // MLIR-NEXT: llvm.br ^bb5 - // MLIR-NEXT: ^bb4: - // MLIR-NEXT: llvm.br ^bb6 - // ============= Body block ============= - // MLIR-NEXT: ^bb5: - // MLIR-NEXT: %10 = llvm.load %1 : !llvm.ptr -> i32 - // MLIR-NEXT: %11 = llvm.mlir.constant(1 : i32) : i32 - // MLIR-NEXT: %12 = llvm.add %10, %11 : i32 - // MLIR-NEXT: llvm.store %12, %1 : i32, !llvm.ptr - // MLIR-NEXT: llvm.br ^bb2 - // ============= Exit block ============= - // MLIR-NEXT: ^bb6: - // MLIR-NEXT: llvm.br ^bb7 +// CHECK: @testDoWhile +// CHECK: llvm.br ^bb[[#BODY:]] +// CHECK: ^bb[[#COND:]]: +// CHECK: llvm.cond_br %{{.+}}, ^bb[[#BODY:]], ^bb[[#EXIT:]] +// CHECK: ^bb[[#BODY]]: +// CHECK: llvm.br ^bb[[#COND]] +// CHECK: ^bb[[#EXIT]]: - // Test endless cir.loop lowering. - cir.func @testEndless() { - cir.scope { - cir.loop for(cond : { - cir.yield continue - }, step : { - cir.yield - }) { - cir.yield - } - } - cir.return - } - // MLIR: llvm.func @testEndless() - // MLIR-NEXT: llvm.br ^bb1 - // MLIR-NEXT: ^bb1: - // MLIR-NEXT: llvm.br ^bb2 - // ============= Condition block ============= - // MLIR-NEXT: ^bb2: - // MLIR-NEXT: llvm.br ^bb3 - // ============= Body block ============= - // MLIR-NEXT: ^bb3: - // MLIR-NEXT: llvm.br ^bb4 - // ============= Step block ============= - // MLIR-NEXT: ^bb4: - // MLIR-NEXT: llvm.br ^bb2 - // ============= Exit block ============= - // MLIR-NEXT: ^bb5: - // MLIR-NEXT: llvm.br ^bb6 - // MLIR-NEXT: ^bb6: - // MLIR-NEXT: llvm.return // test corner case // while (1) { // break; // } - cir.func @whileCornerCase() { - cir.scope { - cir.loop while(cond : { - %0 = cir.const(#cir.int<1> : !s32i) : !s32i - %1 = cir.cast(int_to_bool, %0 : !s32i), !cir.bool - cir.brcond %1 ^bb1, ^bb2 - ^bb1: // pred: ^bb0 - cir.yield continue - ^bb2: // pred: ^bb0 - cir.yield - }, step : { - cir.yield - }) { - cir.yield break - } + cir.func @testWhileWithBreakTerminatedBody(%arg0 : !cir.bool) { + cir.loop while(cond : { + cir.condition(%arg0) + }, step : { // Droped when lowering while statements. + cir.yield + }) { + cir.yield break } cir.return } - // MLIR: llvm.func @whileCornerCase() - // MLIR: %0 = llvm.mlir.constant(1 : i32) : i32 - // MLIR-NEXT: %1 = llvm.mlir.constant(0 : i32) : i32 - // MLIR-NEXT: %2 = llvm.icmp "ne" %0, %1 : i32 - // MLIR-NEXT: %3 = llvm.zext %2 : i1 to i8 - // MLIR-NEXT: %4 = llvm.trunc %3 : i8 to i - // MLIR-NEXT: llvm.cond_br %4, ^bb3, ^bb4 - // MLIR-NEXT: ^bb3: // pred: ^bb2 - // MLIR-NEXT: llvm.br ^bb5 - // MLIR-NEXT: ^bb4: // pred: ^bb2 - // MLIR-NEXT: llvm.br ^bb6 - // MLIR-NEXT: ^bb5: // pred: ^bb3 - // MLIR-NEXT: llvm.br ^bb6 - // MLIR-NEXT: ^bb6: // 2 preds: ^bb4, ^bb5 - // MLIR-NEXT: llvm.br ^bb7 - // MLIR-NEXT: ^bb7: // pred: ^bb6 - // MLIR-NEXT: llvm.return - // test corner case - no fails during the lowering +// CHECK: @testWhileWithBreakTerminatedBody +// CHECK: llvm.br ^bb[[#COND:]] +// CHECK: ^bb[[#COND]]: +// CHECK: llvm.cond_br %{{.+}}, ^bb[[#BODY:]], ^bb[[#EXIT:]] +// CHECK: ^bb[[#BODY]]: +// CHECK: llvm.br ^bb[[#EXIT]] +// CHECK: ^bb[[#EXIT]]: + + + + // test C only corner case - no fails during the lowering // for (;;) { // break; // } - cir.func @forCornerCase() { - cir.scope { + cir.func @forWithBreakTerminatedScopeInBody(%arg0 : !cir.bool) { cir.loop for(cond : { - cir.yield continue + cir.condition(%arg0) }, step : { cir.yield }) { - cir.scope { + cir.scope { // FIXME(cir): Redundant scope emitted during C codegen. cir.yield break } cir.yield } - } cir.return } -// MLIR: llvm.func @forCornerCase() -// MLIR: llvm.br ^bb1 -// MLIR-NEXT: ^bb1: // pred: ^bb0 -// MLIR-NEXT: llvm.br ^bb2 -// MLIR-NEXT: ^bb2: // 2 preds: ^bb1, ^bb6 -// MLIR-NEXT: llvm.br ^bb3 -// MLIR-NEXT: ^bb3: // pred: ^bb2 -// MLIR-NEXT: llvm.br ^bb4 -// MLIR-NEXT: ^bb4: // pred: ^bb3 -// MLIR-NEXT: llvm.br ^bb7 -// MLIR-NEXT: ^bb5: // no predecessors -// MLIR-NEXT: llvm.br ^bb6 -// MLIR-NEXT: ^bb6: // pred: ^bb5 -// MLIR-NEXT: llvm.br ^bb2 -// MLIR-NEXT: ^bb7: // pred: ^bb4 -// MLIR-NEXT: llvm.br ^bb8 -// MLIR-NEXT: ^bb8: // pred: ^bb7 -// MLIR-NEXT: llvm.return + +// CHECK: @forWithBreakTerminatedScopeInBody +// CHECK: llvm.br ^bb[[#COND:]] +// CHECK: ^bb[[#COND:]]: +// CHECK: llvm.cond_br %{{.+}}, ^bb[[#BODY:]], ^bb[[#EXIT:]] +// CHECK: ^bb[[#BODY]]: +// CHECK: llvm.br ^bb[[#SCOPE_IN:]] +// CHECK: ^bb[[#SCOPE_IN]]: +// CHECK: llvm.br ^bb[[#EXIT]] +// CHECK: ^bb[[#SCOPE_EXIT:]]: +// CHECK: llvm.br ^bb[[#STEP:]] +// CHECK: ^bb[[#STEP]]: +// CHECK: llvm.br ^bb[[#COND]] +// CHECK: ^bb[[#EXIT]]: } diff --git a/clang/test/CIR/Lowering/loops-with-break.cir b/clang/test/CIR/Lowering/loops-with-break.cir index f22865ebcc78..5bccde54df27 100644 --- a/clang/test/CIR/Lowering/loops-with-break.cir +++ b/clang/test/CIR/Lowering/loops-with-break.cir @@ -13,11 +13,7 @@ module { %3 = cir.const(#cir.int<10> : !s32i) : !s32i %4 = cir.cmp(lt, %2, %3) : !s32i, !s32i %5 = cir.cast(int_to_bool, %4 : !s32i), !cir.bool - cir.brcond %5 ^bb1, ^bb2 - ^bb1: // pred: ^bb0 - cir.yield continue - ^bb2: // pred: ^bb0 - cir.yield + cir.condition(%5) }, step : { %2 = cir.load %0 : cir.ptr , !s32i %3 = cir.unary(inc, %2) : !s32i, !s32i @@ -46,11 +42,7 @@ module { // CHECK: llvm.br ^bb[[#COND:]] // CHECK: ^bb[[#COND]]: // [...] - // CHECK: llvm.cond_br %{{.+}}, ^bb[[#preBREAK0:]], ^bb[[#preEXIT0:]] - // CHECK: ^bb[[#preBREAK0]]: - // CHECK: llvm.br ^bb[[#preBREAK1:]] - // CHECK: ^bb[[#preEXIT0]]: - // CHECK: llvm.br ^bb[[#EXIT:]] + // CHECK: llvm.cond_br %{{.+}}, ^bb[[#preBREAK1:]], ^bb[[#EXIT:]] // CHECK: ^bb[[#preBREAK1]]: // CHECK: llvm.br ^bb[[#preBREAK2:]] // CHECK: ^bb[[#preBREAK2]]: @@ -83,11 +75,7 @@ module { %3 = cir.const(#cir.int<10> : !s32i) : !s32i %4 = cir.cmp(lt, %2, %3) : !s32i, !s32i %5 = cir.cast(int_to_bool, %4 : !s32i), !cir.bool - cir.brcond %5 ^bb1, ^bb2 - ^bb1: // pred: ^bb0 - cir.yield continue - ^bb2: // pred: ^bb0 - cir.yield + cir.condition(%5) }, step : { %2 = cir.load %0 : cir.ptr , !s32i %3 = cir.unary(inc, %2) : !s32i, !s32i @@ -104,11 +92,7 @@ module { %5 = cir.const(#cir.int<10> : !s32i) : !s32i %6 = cir.cmp(lt, %4, %5) : !s32i, !s32i %7 = cir.cast(int_to_bool, %6 : !s32i), !cir.bool - cir.brcond %7 ^bb1, ^bb2 - ^bb1: // pred: ^bb0 - cir.yield continue - ^bb2: // pred: ^bb0 - cir.yield + cir.condition(%7) }, step : { %4 = cir.load %2 : cir.ptr , !s32i %5 = cir.unary(inc, %4) : !s32i, !s32i @@ -141,11 +125,7 @@ module { // CHECK: llvm.br ^bb[[#COND:]] // CHECK: ^bb[[#COND]]: // [...] - // CHECK: llvm.cond_br %{{.+}}, ^bb[[#preNESTED0:]], ^bb[[#preEXIT0:]] - // CHECK: ^bb[[#preNESTED0]]: - // CHECK: llvm.br ^bb[[#preNESTED1:]] - // CHECK: ^bb[[#preEXIT0]]: - // CHECK: llvm.br ^bb[[#EXIT:]] + // CHECK: llvm.cond_br %{{.+}}, ^bb[[#preNESTED1:]], ^bb[[#EXIT:]] // CHECK: ^bb[[#preNESTED1]]: // CHECK: llvm.br ^bb[[#preNESTED2:]] // CHECK: ^bb[[#preNESTED2]]: @@ -155,11 +135,7 @@ module { // CHECK: llvm.br ^bb[[#COND_NESTED:]] // CHECK: ^bb[[#COND_NESTED]]: // [...] - // CHECK: llvm.cond_br %{{.+}}, ^bb[[#preBREAK0:]], ^bb[[#preEXIT1:]] - // CHECK: ^bb[[#preBREAK0]]: - // CHECK: llvm.br ^bb[[#preBREAK1:]] - // CHECK: ^bb[[#preEXIT1]]: - // CHECK: llvm.br ^bb[[#EXIT_NESTED:]] + // CHECK: llvm.cond_br %{{.+}}, ^bb[[#preBREAK1:]], ^bb[[#EXIT_NESTED:]] // CHECK: ^bb[[#preBREAK1]]: // CHECK: llvm.br ^bb[[#preBREAK2:]] // CHECK: ^bb[[#preBREAK2]]: @@ -200,11 +176,7 @@ module { %3 = cir.const(#cir.int<10> : !s32i) : !s32i %4 = cir.cmp(lt, %2, %3) : !s32i, !s32i %5 = cir.cast(int_to_bool, %4 : !s32i), !cir.bool - cir.brcond %5 ^bb1, ^bb2 - ^bb1: // pred: ^bb0 - cir.yield continue - ^bb2: // pred: ^bb0 - cir.yield + cir.condition(%5) }, step : { cir.yield }) { @@ -232,11 +204,7 @@ module { // CHECK: llvm.br ^bb[[#COND:]] // CHECK: ^bb[[#COND]]: // [...] - // CHECK: llvm.cond_br %{{.+}}, ^bb[[#preBODY:]], ^bb[[#preEXIT0:]] - // CHECK: ^bb[[#preBODY]]: - // CHECK: llvm.br ^bb[[#BODY:]] - // CHECK: ^bb[[#preEXIT0]]: - // CHECK: llvm.br ^bb[[#EXIT:]] + // CHECK: llvm.cond_br %{{.+}}, ^bb[[#BODY:]], ^bb[[#EXIT:]] // CHECK: ^bb[[#BODY]]: // [...] // CHECK: llvm.br ^bb[[#BREAK:]] @@ -265,11 +233,7 @@ cir.func @testDoWhile() { %3 = cir.const(#cir.int<10> : !s32i) : !s32i %4 = cir.cmp(lt, %2, %3) : !s32i, !s32i %5 = cir.cast(int_to_bool, %4 : !s32i), !cir.bool - cir.brcond %5 ^bb1, ^bb2 - ^bb1: // pred: ^bb0 - cir.yield continue - ^bb2: // pred: ^bb0 - cir.yield + cir.condition(%5) }, step : { cir.yield }) { @@ -296,11 +260,7 @@ cir.func @testDoWhile() { // CHECK: llvm.br ^bb[[#COND:]] // CHECK: ^bb[[#COND]]: // [...] - // CHECK: llvm.cond_br %{{.+}}, ^bb[[#preBODY:]], ^bb[[#preEXIT0:]] - // CHECK: ^bb[[#preBODY]]: - // CHECK: llvm.br ^bb[[#BODY:]] - // CHECK: ^bb[[#preEXIT0]]: - // CHECK: llvm.br ^bb[[#EXIT:]] + // CHECK: llvm.cond_br %{{.+}}, ^bb[[#BODY:]], ^bb[[#EXIT:]] // CHECK: ^bb[[#BODY]]: // [...] // CHECK: llvm.br ^bb[[#BREAK:]] diff --git a/clang/test/CIR/Lowering/loops-with-continue.cir b/clang/test/CIR/Lowering/loops-with-continue.cir index c0f2c2658c2c..5dac140f7e24 100644 --- a/clang/test/CIR/Lowering/loops-with-continue.cir +++ b/clang/test/CIR/Lowering/loops-with-continue.cir @@ -13,11 +13,7 @@ module { %3 = cir.const(#cir.int<10> : !s32i) : !s32i %4 = cir.cmp(lt, %2, %3) : !s32i, !s32i %5 = cir.cast(int_to_bool, %4 : !s32i), !cir.bool - cir.brcond %5 ^bb1, ^bb2 - ^bb1: // pred: ^bb0 - cir.yield continue - ^bb2: // pred: ^bb0 - cir.yield + cir.condition(%5) }, step : { %2 = cir.load %0 : cir.ptr , !s32i %3 = cir.unary(inc, %2) : !s32i, !s32i @@ -46,11 +42,7 @@ module { // CHECK: llvm.br ^bb[[#COND:]] // CHECK: ^bb[[#COND]]: // [...] - // CHECK: llvm.cond_br %{{.+}}, ^bb[[#preCONTINUE0:]], ^bb[[#preEXIT0:]] - // CHECK: ^bb[[#preCONTINUE0]]: - // CHECK: llvm.br ^bb[[#preCONTINUE1:]] - // CHECK: ^bb[[#preEXIT0]]: - // CHECK: llvm.br ^bb[[#EXIT:]] + // CHECK: llvm.cond_br %{{.+}}, ^bb[[#preCONTINUE1:]], ^bb[[#EXIT:]] // CHECK: ^bb[[#preCONTINUE1]]: // CHECK: llvm.br ^bb[[#preCONTINUE2:]] // CHECK: ^bb[[#preCONTINUE2]]: @@ -84,11 +76,7 @@ module { %3 = cir.const(#cir.int<10> : !s32i) : !s32i %4 = cir.cmp(lt, %2, %3) : !s32i, !s32i %5 = cir.cast(int_to_bool, %4 : !s32i), !cir.bool - cir.brcond %5 ^bb1, ^bb2 - ^bb1: // pred: ^bb0 - cir.yield continue - ^bb2: // pred: ^bb0 - cir.yield + cir.condition(%5) }, step : { %2 = cir.load %0 : cir.ptr , !s32i %3 = cir.unary(inc, %2) : !s32i, !s32i @@ -105,11 +93,7 @@ module { %5 = cir.const(#cir.int<10> : !s32i) : !s32i %6 = cir.cmp(lt, %4, %5) : !s32i, !s32i %7 = cir.cast(int_to_bool, %6 : !s32i), !cir.bool - cir.brcond %7 ^bb1, ^bb2 - ^bb1: // pred: ^bb0 - cir.yield continue - ^bb2: // pred: ^bb0 - cir.yield + cir.condition(%7) }, step : { %4 = cir.load %2 : cir.ptr , !s32i %5 = cir.unary(inc, %4) : !s32i, !s32i @@ -142,11 +126,7 @@ module { // CHECK: llvm.br ^bb[[#COND:]] // CHECK: ^bb[[#COND]]: // [...] - // CHECK: llvm.cond_br %{{.+}}, ^bb[[#preNESTED0:]], ^bb[[#preEXIT0:]] - // CHECK: ^bb[[#preNESTED0]]: - // CHECK: llvm.br ^bb[[#preNESTED1:]] - // CHECK: ^bb[[#preEXIT0]]: - // CHECK: llvm.br ^bb[[#EXIT:]] + // CHECK: llvm.cond_br %{{.+}}, ^bb[[#preNESTED1:]], ^bb[[#EXIT:]] // CHECK: ^bb[[#preNESTED1]]: // CHECK: llvm.br ^bb[[#preNESTED2:]] // CHECK: ^bb[[#preNESTED2]]: @@ -156,11 +136,7 @@ module { // CHECK: llvm.br ^bb[[#COND_NESTED:]] // CHECK: ^bb[[#COND_NESTED]]: // [...] - // CHECK: llvm.cond_br %{{.+}}, ^bb[[#preCONTINUE0:]], ^bb[[#preEXIT1:]] - // CHECK: ^bb[[#preCONTINUE0]]: - // CHECK: llvm.br ^bb[[#preCONTINUE1:]] - // CHECK: ^bb[[#preEXIT1]]: - // CHECK: llvm.br ^bb[[#EXIT_NESTED:]] + // CHECK: llvm.cond_br %{{.+}}, ^bb[[#preCONTINUE1:]], ^bb[[#EXIT_NESTED:]] // CHECK: ^bb[[#preCONTINUE1]]: // CHECK: llvm.br ^bb[[#preCONTINUE2:]] // CHECK: ^bb[[#preCONTINUE2]]: @@ -200,11 +176,7 @@ cir.func @testWhile() { %3 = cir.const(#cir.int<10> : !s32i) : !s32i %4 = cir.cmp(lt, %2, %3) : !s32i, !s32i %5 = cir.cast(int_to_bool, %4 : !s32i), !cir.bool - cir.brcond %5 ^bb1, ^bb2 - ^bb1: // pred: ^bb0 - cir.yield continue - ^bb2: // pred: ^bb0 - cir.yield + cir.condition(%5) }, step : { cir.yield }) { @@ -231,11 +203,7 @@ cir.func @testWhile() { // CHECK: llvm.br ^bb[[#COND:]] // CHECK: ^bb[[#COND]]: // [...] - // CHECK: llvm.cond_br %{{.+}}, ^bb[[#preBODY:]], ^bb[[#preEXIT0:]] - // CHECK: ^bb[[#preBODY]]: - // CHECK: llvm.br ^bb[[#BODY:]] - // CHECK: ^bb[[#preEXIT0]]: - // CHECK: llvm.br ^bb[[#EXIT:]] + // CHECK: llvm.cond_br %{{.+}}, ^bb[[#BODY:]], ^bb[[#EXIT:]] // CHECK: ^bb[[#BODY]]: // [...] // CHECK: llvm.br ^bb[[#CONTINUE:]] @@ -262,11 +230,7 @@ cir.func @testWhile() { %3 = cir.const(#cir.int<10> : !s32i) : !s32i %4 = cir.cmp(lt, %2, %3) : !s32i, !s32i %5 = cir.cast(int_to_bool, %4 : !s32i), !cir.bool - cir.brcond %5 ^bb1, ^bb2 - ^bb1: // pred: ^bb0 - cir.yield continue - ^bb2: // pred: ^bb0 - cir.yield + cir.condition(%5) }, step : { cir.yield }) { @@ -294,11 +258,7 @@ cir.func @testWhile() { // CHECK: llvm.br ^bb[[#COND:]] // CHECK: ^bb[[#COND]]: // [...] - // CHECK: llvm.cond_br %{{.+}}, ^bb[[#preBODY:]], ^bb[[#preEXIT0:]] - // CHECK: ^bb[[#preBODY]]: - // CHECK: llvm.br ^bb[[#BODY:]] - // CHECK: ^bb[[#preEXIT0]]: - // CHECK: llvm.br ^bb[[#EXIT:]] + // CHECK: llvm.cond_br %{{.+}}, ^bb[[#BODY:]], ^bb[[#EXIT:]] // CHECK: ^bb[[#BODY]]: // [...] // CHECK: llvm.br ^bb[[#CONTINUE:]] diff --git a/clang/test/CIR/Transforms/merge-cleanups.cir b/clang/test/CIR/Transforms/merge-cleanups.cir index 3b0b21e935fe..8d84201aee35 100644 --- a/clang/test/CIR/Transforms/merge-cleanups.cir +++ b/clang/test/CIR/Transforms/merge-cleanups.cir @@ -65,31 +65,7 @@ module { cir.scope { cir.loop while(cond : { %0 = cir.const(#true) : !cir.bool - cir.brcond %0 ^bb1, ^bb2 - ^bb1: - cir.yield continue - ^bb2: - cir.yield - }, step : { - cir.yield - }) { - cir.br ^bb1 - ^bb1: - cir.return - } - } - cir.return - } - - cir.func @l1() { - cir.scope { - cir.loop while(cond : { - %0 = cir.const(#false) : !cir.bool - cir.brcond %0 ^bb1, ^bb2 - ^bb1: - cir.yield continue - ^bb2: - cir.yield + cir.condition(%0) }, step : { cir.yield }) { @@ -141,20 +117,8 @@ module { // CHECK: cir.func @l0 // CHECK-NEXT: cir.scope { // CHECK-NEXT: cir.loop while(cond : { -// CHECK-NEXT: cir.yield continue -// CHECK-NEXT: }, step : { -// CHECK-NEXT: cir.yield -// CHECK-NEXT: }) { -// CHECK-NEXT: cir.return -// CHECK-NEXT: } -// CHECK-NEXT: } -// CHECK-NEXT: cir.return -// CHECK-NEXT: } - -// CHECK: cir.func @l1 -// CHECK-NEXT: cir.scope { -// CHECK-NEXT: cir.loop while(cond : { -// CHECK-NEXT: cir.yield +// CHECK-NEXT: %0 = cir.const(#true) : !cir.bool +// CHECK-NEXT: cir.condition(%0) // CHECK-NEXT: }, step : { // CHECK-NEXT: cir.yield // CHECK-NEXT: }) {