Skip to content

Commit 4a1ca09

Browse files
andykaylorIanWood1
authored andcommitted
[CIR] Add support for compound assignment statements (llvm#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++.
1 parent 328cb90 commit 4a1ca09

File tree

4 files changed

+151
-0
lines changed

4 files changed

+151
-0
lines changed

clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1010,6 +1010,55 @@ mlir::Value ScalarExprEmitter::emitCompoundAssign(
10101010

10111011
} // namespace
10121012

1013+
LValue
1014+
CIRGenFunction::emitCompoundAssignmentLValue(const CompoundAssignOperator *e) {
1015+
ScalarExprEmitter emitter(*this, builder);
1016+
mlir::Value result;
1017+
switch (e->getOpcode()) {
1018+
#define COMPOUND_OP(Op) \
1019+
case BO_##Op##Assign: \
1020+
return emitter.emitCompoundAssignLValue(e, &ScalarExprEmitter::emit##Op, \
1021+
result)
1022+
COMPOUND_OP(Mul);
1023+
COMPOUND_OP(Div);
1024+
COMPOUND_OP(Rem);
1025+
COMPOUND_OP(Add);
1026+
COMPOUND_OP(Sub);
1027+
COMPOUND_OP(Shl);
1028+
COMPOUND_OP(Shr);
1029+
COMPOUND_OP(And);
1030+
COMPOUND_OP(Xor);
1031+
COMPOUND_OP(Or);
1032+
#undef COMPOUND_OP
1033+
1034+
case BO_PtrMemD:
1035+
case BO_PtrMemI:
1036+
case BO_Mul:
1037+
case BO_Div:
1038+
case BO_Rem:
1039+
case BO_Add:
1040+
case BO_Sub:
1041+
case BO_Shl:
1042+
case BO_Shr:
1043+
case BO_LT:
1044+
case BO_GT:
1045+
case BO_LE:
1046+
case BO_GE:
1047+
case BO_EQ:
1048+
case BO_NE:
1049+
case BO_Cmp:
1050+
case BO_And:
1051+
case BO_Xor:
1052+
case BO_Or:
1053+
case BO_LAnd:
1054+
case BO_LOr:
1055+
case BO_Assign:
1056+
case BO_Comma:
1057+
llvm_unreachable("Not valid compound assignment operators");
1058+
}
1059+
llvm_unreachable("Unhandled compound assignment operator");
1060+
}
1061+
10131062
/// Emit the computation of the specified expression of scalar type.
10141063
mlir::Value CIRGenFunction::emitScalarExpr(const Expr *e) {
10151064
assert(e && hasScalarEvaluationKind(e->getType()) &&

clang/lib/CIR/CodeGen/CIRGenFunction.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,19 @@ LValue CIRGenFunction::emitLValue(const Expr *e) {
517517
return emitMemberExpr(cast<MemberExpr>(e));
518518
case Expr::BinaryOperatorClass:
519519
return emitBinaryOperatorLValue(cast<BinaryOperator>(e));
520+
case Expr::CompoundAssignOperatorClass: {
521+
QualType ty = e->getType();
522+
if (const AtomicType *at = ty->getAs<AtomicType>()) {
523+
cgm.errorNYI(e->getSourceRange(),
524+
"CompoundAssignOperator with AtomicType");
525+
return LValue();
526+
}
527+
if (!ty->isAnyComplexType())
528+
return emitCompoundAssignmentLValue(cast<CompoundAssignOperator>(e));
529+
cgm.errorNYI(e->getSourceRange(),
530+
"CompoundAssignOperator with ComplexType");
531+
return LValue();
532+
}
520533
case Expr::ParenExprClass:
521534
return emitLValue(cast<ParenExpr>(e)->getSubExpr());
522535
case Expr::DeclRefExprClass:

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,8 @@ class CIRGenFunction : public CIRGenTypeCache {
482482
mlir::Type condType,
483483
bool buildingTopLevelCase);
484484

485+
LValue emitCompoundAssignmentLValue(const clang::CompoundAssignOperator *e);
486+
485487
mlir::LogicalResult emitContinueStmt(const clang::ContinueStmt &s);
486488
mlir::LogicalResult emitDoStmt(const clang::DoStmt &s);
487489

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
2+
// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
3+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll
4+
// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
5+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll
6+
// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
7+
8+
int compound_assign(int b) {
9+
int x = 1;
10+
x *= b;
11+
x /= b;
12+
x %= b;
13+
x += b;
14+
x -= b;
15+
x >>= b;
16+
x <<= b;
17+
x &= b;
18+
x ^= b;
19+
x |= b;
20+
return x;
21+
}
22+
23+
// CIR: cir.func @_Z15compound_assigni
24+
// CIR: %[[MUL:.*]] = cir.binop(mul, %{{.*}}, %{{.*}}) nsw : !s32i
25+
// CIR: cir.store %[[MUL]], %{{.*}} : !s32i, !cir.ptr<!s32i>
26+
// CIR: %[[DIV:.*]] = cir.binop(div, %{{.*}}, %{{.*}}) : !s32i
27+
// CIR: cir.store %[[DIV]], %{{.*}} : !s32i, !cir.ptr<!s32i>
28+
// CIR: %[[REM:.*]] = cir.binop(rem, %{{.*}}, %{{.*}}) : !s32i
29+
// CIR: cir.store %[[REM]], %{{.*}} : !s32i, !cir.ptr<!s32i>
30+
// CIR: %[[ADD:.*]] = cir.binop(add, %{{.*}}, %{{.*}}) nsw : !s32i
31+
// CIR: cir.store %[[ADD]], %{{.*}} : !s32i, !cir.ptr<!s32i>
32+
// CIR: %[[SUB:.*]] = cir.binop(sub, %{{.*}}, %{{.*}}) nsw : !s32i
33+
// CIR: cir.store %[[SUB]], %{{.*}} : !s32i, !cir.ptr<!s32i>
34+
// CIR: %[[SHR:.*]] = cir.shift(right, %{{.*}} : !s32i, %{{.*}} : !s32i) -> !s32i
35+
// CIR: cir.store %[[SHR]], %{{.*}} : !s32i, !cir.ptr<!s32i>
36+
// CIR: %[[SHL:.*]] = cir.shift(left, %{{.*}} : !s32i, %{{.*}} : !s32i) -> !s32i
37+
// CIR: cir.store %[[SHL]], %{{.*}} : !s32i, !cir.ptr<!s32i>
38+
// CIR: %[[AND:.*]] = cir.binop(and, %{{.*}}, %{{.*}}) : !s32i
39+
// CIR: cir.store %[[AND]], %{{.*}} : !s32i, !cir.ptr<!s32i>
40+
// CIR: %[[XOR:.*]] = cir.binop(xor, %{{.*}}, %{{.*}}) : !s32i
41+
// CIR: cir.store %[[XOR]], %{{.*}} : !s32i, !cir.ptr<!s32i>
42+
// CIR: %[[OR:.*]] = cir.binop(or, %{{.*}}, %{{.*}}) : !s32i
43+
// CIR: cir.store %[[OR]], %{{.*}} : !s32i, !cir.ptr<!s32i>
44+
45+
// LLVM: define {{.*}}i32 @_Z15compound_assigni
46+
// LLVM: %[[MUL:.*]] = mul nsw i32 %{{.*}}, %{{.*}}
47+
// LLVM: store i32 %[[MUL]], ptr %{{.*}}
48+
// LLVM: %[[DIV:.*]] = sdiv i32 %{{.*}}, %{{.*}}
49+
// LLVM: store i32 %[[DIV]], ptr %{{.*}}
50+
// LLVM: %[[REM:.*]] = srem i32 %{{.*}}, %{{.*}}
51+
// LLVM: store i32 %[[REM]], ptr %{{.*}}
52+
// LLVM: %[[ADD:.*]] = add nsw i32 %{{.*}}, %{{.*}}
53+
// LLVM: store i32 %[[ADD]], ptr %{{.*}}
54+
// LLVM: %[[SUB:.*]] = sub nsw i32 %{{.*}}, %{{.*}}
55+
// LLVM: store i32 %[[SUB]], ptr %{{.*}}
56+
// LLVM: %[[SHR:.*]] = ashr i32 %{{.*}}, %{{.*}}
57+
// LLVM: store i32 %[[SHR]], ptr %{{.*}}
58+
// LLVM: %[[SHL:.*]] = shl i32 %{{.*}}, %{{.*}}
59+
// LLVM: store i32 %[[SHL]], ptr %{{.*}}
60+
// LLVM: %[[AND:.*]] = and i32 %{{.*}}, %{{.*}}
61+
// LLVM: store i32 %[[AND]], ptr %{{.*}}
62+
// LLVM: %[[XOR:.*]] = xor i32 %{{.*}}, %{{.*}}
63+
// LLVM: store i32 %[[XOR]], ptr %{{.*}}
64+
// LLVM: %[[OR:.*]] = or i32 %{{.*}}, %{{.*}}
65+
// LLVM: store i32 %[[OR]], ptr %{{.*}}
66+
67+
// OGCG: define {{.*}}i32 @_Z15compound_assigni
68+
// OGCG: %[[MUL:.*]] = mul nsw i32 %{{.*}}, %{{.*}}
69+
// OGCG: store i32 %[[MUL]], ptr %{{.*}}
70+
// OGCG: %[[DIV:.*]] = sdiv i32 %{{.*}}, %{{.*}}
71+
// OGCG: store i32 %[[DIV]], ptr %{{.*}}
72+
// OGCG: %[[REM:.*]] = srem i32 %{{.*}}, %{{.*}}
73+
// OGCG: store i32 %[[REM]], ptr %{{.*}}
74+
// OGCG: %[[ADD:.*]] = add nsw i32 %{{.*}}, %{{.*}}
75+
// OGCG: store i32 %[[ADD]], ptr %{{.*}}
76+
// OGCG: %[[SUB:.*]] = sub nsw i32 %{{.*}}, %{{.*}}
77+
// OGCG: store i32 %[[SUB]], ptr %{{.*}}
78+
// OGCG: %[[SHR:.*]] = ashr i32 %{{.*}}, %{{.*}}
79+
// OGCG: store i32 %[[SHR]], ptr %{{.*}}
80+
// OGCG: %[[SHL:.*]] = shl i32 %{{.*}}, %{{.*}}
81+
// OGCG: store i32 %[[SHL]], ptr %{{.*}}
82+
// OGCG: %[[AND:.*]] = and i32 %{{.*}}, %{{.*}}
83+
// OGCG: store i32 %[[AND]], ptr %{{.*}}
84+
// OGCG: %[[XOR:.*]] = xor i32 %{{.*}}, %{{.*}}
85+
// OGCG: store i32 %[[XOR]], ptr %{{.*}}
86+
// OGCG: %[[OR:.*]] = or i32 %{{.*}}, %{{.*}}
87+
// OGCG: store i32 %[[OR]], ptr %{{.*}}

0 commit comments

Comments
 (0)