[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