================ @@ -875,6 +877,174 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { // NOTE: We don't need to EnsureInsertPoint() like LLVM codegen. return Visit(e->getRHS()); } + + mlir::Value VisitBinLAnd(const clang::BinaryOperator *e) { + if (e->getType()->isVectorType()) { + assert(!cir::MissingFeatures::vectorType()); + return {}; + } + + bool instrumentRegions = cgf.cgm.getCodeGenOpts().hasProfileClangInstr(); + mlir::Type resTy = cgf.convertType(e->getType()); + mlir::Location loc = cgf.getLoc(e->getExprLoc()); + + // If we have 0 && RHS, see if we can elide RHS, if so, just return 0. + // If we have 1 && X, just emit X without inserting the control flow. + bool lhsCondVal; + if (cgf.constantFoldsToSimpleInteger(e->getLHS(), lhsCondVal)) { + if (lhsCondVal) { // If we have 1 && X, just emit X. + + mlir::Value rhsCond = cgf.evaluateExprAsBool(e->getRHS()); + + if (instrumentRegions) { + assert(!cir::MissingFeatures::instrumenation()); + cgf.cgm.errorNYI(e->getExprLoc(), "instrumenation"); + } + // ZExt result to int or bool. + return builder.createZExtOrBitCast(rhsCond.getLoc(), rhsCond, resTy); + } + // 0 && RHS: If it is safe, just elide the RHS, and return 0/false. + if (!cgf.containsLabel(e->getRHS())) + return builder.getNullValue(resTy, loc); + } + + CIRGenFunction::ConditionalEvaluation eval(cgf); + + mlir::Value lhsCondV = cgf.evaluateExprAsBool(e->getLHS()); + auto resOp = builder.create<cir::TernaryOp>( + loc, lhsCondV, /*trueBuilder=*/ + [&](mlir::OpBuilder &b, mlir::Location loc) { + CIRGenFunction::LexicalScope lexScope{cgf, loc, + b.getInsertionBlock()}; + cgf.curLexScope->setAsTernary(); + mlir::Value rhsCondV = cgf.evaluateExprAsBool(e->getRHS()); + auto res = b.create<cir::TernaryOp>( + loc, rhsCondV, /*trueBuilder*/ + [&](mlir::OpBuilder &b, mlir::Location loc) { + CIRGenFunction::LexicalScope lexScope{cgf, loc, + b.getInsertionBlock()}; + cgf.curLexScope->setAsTernary(); + auto res = + b.create<cir::ConstantOp>(loc, builder.getTrueAttr()); + b.create<cir::YieldOp>(loc, res.getRes()); + }, + /*falseBuilder*/ + [&](mlir::OpBuilder &b, mlir::Location loc) { + CIRGenFunction::LexicalScope lexScope{cgf, loc, + b.getInsertionBlock()}; + cgf.curLexScope->setAsTernary(); + auto res = + b.create<cir::ConstantOp>(loc, builder.getFalseAttr()); + b.create<cir::YieldOp>(loc, res.getRes()); + }); + b.create<cir::YieldOp>(loc, res.getResult()); + }, + /*falseBuilder*/ + [&](mlir::OpBuilder &b, mlir::Location loc) { + CIRGenFunction::LexicalScope lexScope{cgf, loc, + b.getInsertionBlock()}; + cgf.curLexScope->setAsTernary(); + auto res = b.create<cir::ConstantOp>(loc, builder.getFalseAttr()); + b.create<cir::YieldOp>(loc, res.getRes()); + }); + return builder.createZExtOrBitCast(resOp.getLoc(), resOp.getResult(), ---------------- andykaylor wrote:
VisitUnaryLNot does this: ``` // ZExt result to the expr type. mlir::Type dstTy = cgf.convertType(e->getType()); if (mlir::isa<cir::IntType>(dstTy)) return builder.createBoolToInt(boolVal, dstTy); if (mlir::isa<cir::BoolType>(dstTy)) return boolVal; cgf.cgm.errorNYI("destination type for logical-not unary operator is NYI"); ``` A helper function seems reasonable, but I'd prefer to see it be named something like `maybePromoteBoolResult`. https://github.com/llvm/llvm-project/pull/138156 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits