@@ -474,6 +474,106 @@ void CIRGenFunction::emitIgnoredExpr(const Expr *e) {
474474 emitLValue (e);
475475}
476476
477+ // / Emit an `if` on a boolean condition, filling `then` and `else` into
478+ // / appropriated regions.
479+ mlir::LogicalResult CIRGenFunction::emitIfOnBoolExpr (const Expr *cond,
480+ const Stmt *thenS,
481+ const Stmt *elseS) {
482+ // Attempt to be more accurate as possible with IfOp location, generate
483+ // one fused location that has either 2 or 4 total locations, depending
484+ // on else's availability.
485+ auto getStmtLoc = [this ](const Stmt &s) {
486+ return mlir::FusedLoc::get (&getMLIRContext (),
487+ {getLoc (s.getSourceRange ().getBegin ()),
488+ getLoc (s.getSourceRange ().getEnd ())});
489+ };
490+ mlir::Location thenLoc = getStmtLoc (*thenS);
491+ std::optional<mlir::Location> elseLoc;
492+ if (elseS)
493+ elseLoc = getStmtLoc (*elseS);
494+
495+ mlir::LogicalResult resThen = mlir::success (), resElse = mlir::success ();
496+ emitIfOnBoolExpr (
497+ cond, /* thenBuilder=*/
498+ [&](mlir::OpBuilder &, mlir::Location) {
499+ LexicalScope lexScope{*this , thenLoc, builder.getInsertionBlock ()};
500+ resThen = emitStmt (thenS, /* useCurrentScope=*/ true );
501+ },
502+ thenLoc,
503+ /* elseBuilder=*/
504+ [&](mlir::OpBuilder &, mlir::Location) {
505+ assert (elseLoc && " Invalid location for elseS." );
506+ LexicalScope lexScope{*this , *elseLoc, builder.getInsertionBlock ()};
507+ resElse = emitStmt (elseS, /* useCurrentScope=*/ true );
508+ },
509+ elseLoc);
510+
511+ return mlir::LogicalResult::success (resThen.succeeded () &&
512+ resElse.succeeded ());
513+ }
514+
515+ // / Emit an `if` on a boolean condition, filling `then` and `else` into
516+ // / appropriated regions.
517+ cir::IfOp CIRGenFunction::emitIfOnBoolExpr (
518+ const clang::Expr *cond, BuilderCallbackRef thenBuilder,
519+ mlir::Location thenLoc, BuilderCallbackRef elseBuilder,
520+ std::optional<mlir::Location> elseLoc) {
521+
522+ SmallVector<mlir::Location, 2 > ifLocs{thenLoc};
523+ if (elseLoc)
524+ ifLocs.push_back (*elseLoc);
525+ mlir::Location loc = mlir::FusedLoc::get (&getMLIRContext (), ifLocs);
526+
527+ // Emit the code with the fully general case.
528+ mlir::Value condV = emitOpOnBoolExpr (loc, cond);
529+ return builder.create <cir::IfOp>(loc, condV, elseLoc.has_value (),
530+ /* thenBuilder=*/ thenBuilder,
531+ /* elseBuilder=*/ elseBuilder);
532+ }
533+
534+ // / TODO(cir): PGO data
535+ // / TODO(cir): see EmitBranchOnBoolExpr for extra ideas).
536+ mlir::Value CIRGenFunction::emitOpOnBoolExpr (mlir::Location loc,
537+ const Expr *cond) {
538+ // TODO(CIR): scoped ApplyDebugLocation DL(*this, Cond);
539+ // TODO(CIR): __builtin_unpredictable and profile counts?
540+ cond = cond->IgnoreParens ();
541+
542+ // if (const BinaryOperator *CondBOp = dyn_cast<BinaryOperator>(cond)) {
543+ // llvm_unreachable("binaryoperator ifstmt NYI");
544+ // }
545+
546+ if (const UnaryOperator *CondUOp = dyn_cast<UnaryOperator>(cond)) {
547+ // In LLVM the condition is reversed here for efficient codegen.
548+ // This should be done in CIR prior to LLVM lowering, if we do now
549+ // we can make CIR based diagnostics misleading.
550+ // cir.ternary(!x, t, f) -> cir.ternary(x, f, t)
551+ assert (!cir::MissingFeatures::shouldReverseUnaryCondOnBoolExpr ());
552+ }
553+
554+ if (const ConditionalOperator *CondOp = dyn_cast<ConditionalOperator>(cond)) {
555+
556+ cgm.errorNYI (cond->getExprLoc (), " Ternary NYI" );
557+ assert (!cir::MissingFeatures::ternaryOp ());
558+ return createDummyValue (loc, cond->getType ());
559+ }
560+
561+ // if (const CXXThrowExpr *Throw = dyn_cast<CXXThrowExpr>(cond)) {
562+ // llvm_unreachable("NYI");
563+ // }
564+
565+ // If the branch has a condition wrapped by __builtin_unpredictable,
566+ // create metadata that specifies that the branch is unpredictable.
567+ // Don't bother if not optimizing because that metadata would not be used.
568+ auto *Call = dyn_cast<CallExpr>(cond->IgnoreImpCasts ());
569+ if (Call && cgm.getCodeGenOpts ().OptimizationLevel != 0 ) {
570+ assert (!cir::MissingFeatures::insertBuiltinUnpredictable ());
571+ }
572+
573+ // Emit the code with the fully general case.
574+ return evaluateExprAsBool (cond);
575+ }
576+
477577mlir::Value CIRGenFunction::emitAlloca (StringRef name, mlir::Type ty,
478578 mlir::Location loc, CharUnits alignment,
479579 bool insertIntoFnEntryBlock,
0 commit comments