[clang] [CIR] Add support for compound assignment statements (PR #137740)
Andy Kaylor via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 29 08:48:23 PDT 2025
https://github.com/andykaylor updated https://github.com/llvm/llvm-project/pull/137740
>From 17ac341126dd9110a9e1f7cdd3c4197f2a04268b Mon Sep 17 00:00:00 2001
From: Andy Kaylor <akaylor at nvidia.com>
Date: Mon, 28 Apr 2025 16:26:34 -0700
Subject: [PATCH] [CIR] Add support for compound assignment statements
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++.
---
clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 49 ++++++++++++
clang/lib/CIR/CodeGen/CIRGenFunction.cpp | 13 ++++
clang/lib/CIR/CodeGen/CIRGenFunction.h | 2 +
clang/test/CIR/CodeGen/compound_assign.cpp | 87 ++++++++++++++++++++++
4 files changed, 151 insertions(+)
create mode 100644 clang/test/CIR/CodeGen/compound_assign.cpp
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 %{{.*}}
More information about the cfe-commits
mailing list