[clang] [CIR] Upstream initial support for unary op (PR #131369)
Erich Keane via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 14 11:19:20 PDT 2025
================
@@ -92,6 +92,222 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
mlir::Value VisitCastExpr(CastExpr *E);
+ // Unary Operators.
+ mlir::Value VisitUnaryPostDec(const UnaryOperator *e) {
+ LValue lv = cgf.emitLValue(e->getSubExpr());
+ return emitScalarPrePostIncDec(e, lv, false, false);
+ }
+ mlir::Value VisitUnaryPostInc(const UnaryOperator *e) {
+ LValue lv = cgf.emitLValue(e->getSubExpr());
+ return emitScalarPrePostIncDec(e, lv, true, false);
+ }
+ mlir::Value VisitUnaryPreDec(const UnaryOperator *e) {
+ LValue lv = cgf.emitLValue(e->getSubExpr());
+ return emitScalarPrePostIncDec(e, lv, false, true);
+ }
+ mlir::Value VisitUnaryPreInc(const UnaryOperator *e) {
+ LValue lv = cgf.emitLValue(e->getSubExpr());
+ return emitScalarPrePostIncDec(e, lv, true, true);
+ }
+ mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv,
+ bool isInc, bool isPre) {
+ if (cgf.getLangOpts().OpenMP)
+ cgf.cgm.errorNYI(e->getSourceRange(), "inc/dec OpenMP");
+
+ QualType type = e->getSubExpr()->getType();
+
+ mlir::Value value;
+ mlir::Value input;
+
+ if (type->getAs<AtomicType>()) {
+ cgf.cgm.errorNYI(e->getSourceRange(), "Atomic inc/dec");
+ // TODO(cir): This is not correct, but it will produce reasonable code
+ // until atomic operations are implemented.
+ value = cgf.emitLoadOfLValue(lv, e->getExprLoc()).getScalarVal();
+ input = value;
+ } else {
+ value = cgf.emitLoadOfLValue(lv, e->getExprLoc()).getScalarVal();
+ input = value;
+ }
+
+ // NOTE: When possible, more frequent cases are handled first.
+
+ // Special case of integer increment that we have to check first: bool++.
+ // Due to promotion rules, we get:
+ // bool++ -> bool = bool + 1
+ // -> bool = (int)bool + 1
+ // -> bool = ((int)bool + 1 != 0)
+ // An interesting aspect of this is that increment is always true.
+ // Decrement does not have this property.
+ if (isInc && type->isBooleanType()) {
+ value = builder.create<cir::ConstantOp>(cgf.getLoc(e->getExprLoc()),
+ cgf.convertType(type),
+ builder.getCIRBoolAttr(true));
+ } else if (type->isIntegerType()) {
+ QualType promotedType;
+ bool canPerformLossyDemotionCheck = false;
+ if (cgf.getContext().isPromotableIntegerType(type)) {
+ promotedType = cgf.getContext().getPromotedIntegerType(type);
+ assert(promotedType != type && "Shouldn't promote to the same type.");
+ canPerformLossyDemotionCheck = true;
+ canPerformLossyDemotionCheck &=
+ cgf.getContext().getCanonicalType(type) !=
+ cgf.getContext().getCanonicalType(promotedType);
+ canPerformLossyDemotionCheck &=
+ type->isIntegerType() && promotedType->isIntegerType();
+
+ // TODO(cir): Currently, we store bitwidths in CIR types only for
+ // integers. This might also be required for other types.
+ auto srcCirTy = mlir::dyn_cast<cir::IntType>(cgf.convertType(type));
+ auto promotedCirTy =
+ mlir::dyn_cast<cir::IntType>(cgf.convertType(type));
+ assert(srcCirTy && promotedCirTy && "Expected integer type");
----------------
erichkeane wrote:
If we're asserting here, those should just be `cast` above, and count on the `cast` assert.
https://github.com/llvm/llvm-project/pull/131369
More information about the cfe-commits
mailing list