Author: Andy Kaylor
Date: 2025-04-29T11:31:04-07:00
New Revision: 7d91cf4bab8c9c4daa3d3a9fca87778d6ccacb6b

URL: 
https://github.com/llvm/llvm-project/commit/7d91cf4bab8c9c4daa3d3a9fca87778d6ccacb6b
DIFF: 
https://github.com/llvm/llvm-project/commit/7d91cf4bab8c9c4daa3d3a9fca87778d6ccacb6b.diff

LOG: [CIR] Add support for compound assignment statements (#137740)

Compound assignment in C++ goes through a different path than the binary
assignment operators that were already handled for C. This change adds
the necessary handler to get this working with C++.

Added: 
    clang/test/CIR/CodeGen/compound_assign.cpp

Modified: 
    clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
    clang/lib/CIR/CodeGen/CIRGenFunction.cpp
    clang/lib/CIR/CodeGen/CIRGenFunction.h

Removed: 
    


################################################################################
diff  --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 4ca54940a60b8..aef5b125a2877 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -1010,6 +1010,55 @@ mlir::Value ScalarExprEmitter::emitCompoundAssign(
 
 } // namespace
 
+LValue
+CIRGenFunction::emitCompoundAssignmentLValue(const CompoundAssignOperator *e) {
+  ScalarExprEmitter emitter(*this, builder);
+  mlir::Value result;
+  switch (e->getOpcode()) {
+#define COMPOUND_OP(Op)                                                        
\
+  case BO_##Op##Assign:                                                        
\
+    return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op,   
\
+                                            result)
+    COMPOUND_OP(Mul);
+    COMPOUND_OP(Div);
+    COMPOUND_OP(Rem);
+    COMPOUND_OP(Add);
+    COMPOUND_OP(Sub);
+    COMPOUND_OP(Shl);
+    COMPOUND_OP(Shr);
+    COMPOUND_OP(And);
+    COMPOUND_OP(Xor);
+    COMPOUND_OP(Or);
+#undef COMPOUND_OP
+
+  case BO_PtrMemD:
+  case BO_PtrMemI:
+  case BO_Mul:
+  case BO_Div:
+  case BO_Rem:
+  case BO_Add:
+  case BO_Sub:
+  case BO_Shl:
+  case BO_Shr:
+  case BO_LT:
+  case BO_GT:
+  case BO_LE:
+  case BO_GE:
+  case BO_EQ:
+  case BO_NE:
+  case BO_Cmp:
+  case BO_And:
+  case BO_Xor:
+  case BO_Or:
+  case BO_LAnd:
+  case BO_LOr:
+  case BO_Assign:
+  case BO_Comma:
+    llvm_unreachable("Not valid compound assignment operators");
+  }
+  llvm_unreachable("Unhandled compound assignment operator");
+}
+
 /// Emit the computation of the specified expression of scalar type.
 mlir::Value CIRGenFunction::emitScalarExpr(const Expr *e) {
   assert(e && hasScalarEvaluationKind(e->getType()) &&

diff  --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp 
b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 5412f9f602711..fa86fce2f6e5c 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -517,6 +517,19 @@ LValue CIRGenFunction::emitLValue(const Expr *e) {
     return emitMemberExpr(cast<MemberExpr>(e));
   case Expr::BinaryOperatorClass:
     return emitBinaryOperatorLValue(cast<BinaryOperator>(e));
+  case Expr::CompoundAssignOperatorClass: {
+    QualType ty = e->getType();
+    if (const AtomicType *at = ty->getAs<AtomicType>()) {
+      cgm.errorNYI(e->getSourceRange(),
+                   "CompoundAssignOperator with AtomicType");
+      return LValue();
+    }
+    if (!ty->isAnyComplexType())
+      return emitCompoundAssignmentLValue(cast<CompoundAssignOperator>(e));
+    cgm.errorNYI(e->getSourceRange(),
+                 "CompoundAssignOperator with ComplexType");
+    return LValue();
+  }
   case Expr::ParenExprClass:
     return emitLValue(cast<ParenExpr>(e)->getSubExpr());
   case Expr::DeclRefExprClass:

diff  --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h 
b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index ec42aee08ee15..592d39930089d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -482,6 +482,8 @@ class CIRGenFunction : public CIRGenTypeCache {
                                    mlir::Type condType,
                                    bool buildingTopLevelCase);
 
+  LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e);
+
   mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s);
   mlir::LogicalResult emitDoStmt(const clang::DoStmt &s);
 

diff  --git a/clang/test/CIR/CodeGen/compound_assign.cpp 
b/clang/test/CIR/CodeGen/compound_assign.cpp
new file mode 100644
index 0000000000000..c54eb9e626016
--- /dev/null
+++ b/clang/test/CIR/CodeGen/compound_assign.cpp
@@ -0,0 +1,87 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
%t.cir
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value 
-fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value 
-emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+int compound_assign(int b) {
+  int x = 1;
+  x *= b;
+  x /= b;
+  x %= b;
+  x += b;
+  x -= b;
+  x >>= b;
+  x <<= b;
+  x &= b;
+  x ^= b;
+  x |= b;
+  return x;
+}
+
+// CIR: cir.func @_Z15compound_assigni
+// CIR:   %[[MUL:.*]] = cir.binop(mul, %{{.*}}, %{{.*}}) nsw : !s32i
+// CIR:   cir.store %[[MUL]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR:   %[[DIV:.*]] = cir.binop(div, %{{.*}}, %{{.*}}) : !s32i
+// CIR:   cir.store %[[DIV]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR:   %[[REM:.*]] = cir.binop(rem, %{{.*}}, %{{.*}}) : !s32i
+// CIR:   cir.store %[[REM]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR:   %[[ADD:.*]] = cir.binop(add, %{{.*}}, %{{.*}}) nsw : !s32i
+// CIR:   cir.store %[[ADD]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR:   %[[SUB:.*]] = cir.binop(sub, %{{.*}}, %{{.*}}) nsw : !s32i
+// CIR:   cir.store %[[SUB]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR:   %[[SHR:.*]] = cir.shift(right, %{{.*}} : !s32i, %{{.*}} : !s32i) -> 
!s32i
+// CIR:   cir.store %[[SHR]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR:   %[[SHL:.*]] = cir.shift(left, %{{.*}} : !s32i, %{{.*}} : !s32i) -> 
!s32i
+// CIR:   cir.store %[[SHL]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR:   %[[AND:.*]] = cir.binop(and, %{{.*}}, %{{.*}}) : !s32i
+// CIR:   cir.store %[[AND]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR:   %[[XOR:.*]] = cir.binop(xor, %{{.*}}, %{{.*}}) : !s32i
+// CIR:   cir.store %[[XOR]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR:   %[[OR:.*]] = cir.binop(or, %{{.*}}, %{{.*}}) : !s32i
+// CIR:   cir.store %[[OR]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+
+// LLVM: define {{.*}}i32 @_Z15compound_assigni
+// LLVM:   %[[MUL:.*]] = mul nsw i32 %{{.*}}, %{{.*}}
+// LLVM:   store i32 %[[MUL]], ptr %{{.*}}
+// LLVM:   %[[DIV:.*]] = sdiv i32 %{{.*}}, %{{.*}}
+// LLVM:   store i32 %[[DIV]], ptr %{{.*}}
+// LLVM:   %[[REM:.*]] = srem i32 %{{.*}}, %{{.*}}
+// LLVM:   store i32 %[[REM]], ptr %{{.*}}
+// LLVM:   %[[ADD:.*]] = add nsw i32 %{{.*}}, %{{.*}}
+// LLVM:   store i32 %[[ADD]], ptr %{{.*}}
+// LLVM:   %[[SUB:.*]] = sub nsw i32 %{{.*}}, %{{.*}}
+// LLVM:   store i32 %[[SUB]], ptr %{{.*}}
+// LLVM:   %[[SHR:.*]] = ashr i32 %{{.*}}, %{{.*}}
+// LLVM:   store i32 %[[SHR]], ptr %{{.*}}
+// LLVM:   %[[SHL:.*]] = shl i32 %{{.*}}, %{{.*}}
+// LLVM:   store i32 %[[SHL]], ptr %{{.*}}
+// LLVM:   %[[AND:.*]] = and i32 %{{.*}}, %{{.*}}
+// LLVM:   store i32 %[[AND]], ptr %{{.*}}
+// LLVM:   %[[XOR:.*]] = xor i32 %{{.*}}, %{{.*}}
+// LLVM:   store i32 %[[XOR]], ptr %{{.*}}
+// LLVM:   %[[OR:.*]] = or i32 %{{.*}}, %{{.*}}
+// LLVM:   store i32 %[[OR]], ptr %{{.*}}
+
+// OGCG: define {{.*}}i32 @_Z15compound_assigni
+// OGCG:   %[[MUL:.*]] = mul nsw i32 %{{.*}}, %{{.*}}
+// OGCG:   store i32 %[[MUL]], ptr %{{.*}}
+// OGCG:   %[[DIV:.*]] = sdiv i32 %{{.*}}, %{{.*}}
+// OGCG:   store i32 %[[DIV]], ptr %{{.*}}
+// OGCG:   %[[REM:.*]] = srem i32 %{{.*}}, %{{.*}}
+// OGCG:   store i32 %[[REM]], ptr %{{.*}}
+// OGCG:   %[[ADD:.*]] = add nsw i32 %{{.*}}, %{{.*}}
+// OGCG:   store i32 %[[ADD]], ptr %{{.*}}
+// OGCG:   %[[SUB:.*]] = sub nsw i32 %{{.*}}, %{{.*}}
+// OGCG:   store i32 %[[SUB]], ptr %{{.*}}
+// OGCG:   %[[SHR:.*]] = ashr i32 %{{.*}}, %{{.*}}
+// OGCG:   store i32 %[[SHR]], ptr %{{.*}}
+// OGCG:   %[[SHL:.*]] = shl i32 %{{.*}}, %{{.*}}
+// OGCG:   store i32 %[[SHL]], ptr %{{.*}}
+// OGCG:   %[[AND:.*]] = and i32 %{{.*}}, %{{.*}}
+// OGCG:   store i32 %[[AND]], ptr %{{.*}}
+// OGCG:   %[[XOR:.*]] = xor i32 %{{.*}}, %{{.*}}
+// OGCG:   store i32 %[[XOR]], ptr %{{.*}}
+// OGCG:   %[[OR:.*]] = or i32 %{{.*}}, %{{.*}}
+// OGCG:   store i32 %[[OR]], ptr %{{.*}}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to