Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/lib/CIR/CodeGen/CIRGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1630,7 +1630,7 @@ RValue CIRGenFunction::emitAnyExpr(const Expr *e, AggValueSlot aggSlot,
bool ignoreResult) {
switch (CIRGenFunction::getEvaluationKind(e->getType())) {
case cir::TEK_Scalar:
return RValue::get(emitScalarExpr(e));
return RValue::get(emitScalarExpr(e, ignoreResult));
case cir::TEK_Complex:
return RValue::getComplex(emitComplexExpr(e));
case cir::TEK_Aggregate: {
Expand Down
20 changes: 16 additions & 4 deletions clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,9 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
bool ignoreResultAssign;

public:
ScalarExprEmitter(CIRGenFunction &cgf, CIRGenBuilderTy &builder)
: cgf(cgf), builder(builder) {}
ScalarExprEmitter(CIRGenFunction &cgf, CIRGenBuilderTy &builder,
bool ignoreResultAssign = false)
: cgf(cgf), builder(builder), ignoreResultAssign(ignoreResultAssign) {}

//===--------------------------------------------------------------------===//
// Utilities
Expand Down Expand Up @@ -221,6 +222,8 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
}

mlir::Value VisitArraySubscriptExpr(ArraySubscriptExpr *e) {
ignoreResultAssign = false;

if (e->getBase()->getType()->isVectorType()) {
assert(!cir::MissingFeatures::scalableVectors());

Expand Down Expand Up @@ -839,6 +842,7 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {

BinOpInfo emitBinOps(const BinaryOperator *e,
QualType promotionType = QualType()) {
ignoreResultAssign = false;
BinOpInfo result;
result.lhs = cgf.emitPromotedScalarExpr(e->getLHS(), promotionType);
result.rhs = cgf.emitPromotedScalarExpr(e->getRHS(), promotionType);
Expand Down Expand Up @@ -924,6 +928,7 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
#undef HANDLEBINOP

mlir::Value emitCmp(const BinaryOperator *e) {
ignoreResultAssign = false;
const mlir::Location loc = cgf.getLoc(e->getExprLoc());
mlir::Value result;
QualType lhsTy = e->getLHS()->getType();
Expand Down Expand Up @@ -1406,11 +1411,13 @@ CIRGenFunction::emitCompoundAssignmentLValue(const CompoundAssignOperator *e) {
}

/// Emit the computation of the specified expression of scalar type.
mlir::Value CIRGenFunction::emitScalarExpr(const Expr *e) {
mlir::Value CIRGenFunction::emitScalarExpr(const Expr *e,
bool ignoreResultAssign) {
assert(e && hasScalarEvaluationKind(e->getType()) &&
"Invalid scalar expression to emit");

return ScalarExprEmitter(*this, builder).Visit(const_cast<Expr *>(e));
return ScalarExprEmitter(*this, builder, ignoreResultAssign)
.Visit(const_cast<Expr *>(e));
}

mlir::Value CIRGenFunction::emitPromotedScalarExpr(const Expr *e,
Expand Down Expand Up @@ -2054,6 +2061,11 @@ mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) {
mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
const unsigned numInitElements = e->getNumInits();

[[maybe_unused]] const bool ignore = std::exchange(ignoreResultAssign, false);
assert((ignore == false ||
(numInitElements == 0 && e->getType()->isVoidType())) &&
"init list ignored");

if (e->hadArrayRangeDesignator()) {
cgf.cgm.errorNYI(e->getSourceRange(), "ArrayRangeDesignator");
return {};
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1501,7 +1501,8 @@ class CIRGenFunction : public CIRGenTypeCache {
llvm::ArrayRef<mlir::Value> args = {});

/// Emit the computation of the specified expression of scalar type.
mlir::Value emitScalarExpr(const clang::Expr *e);
mlir::Value emitScalarExpr(const clang::Expr *e,
bool ignoreResultAssign = false);

mlir::Value emitScalarPrePostIncDec(const UnaryOperator *e, LValue lv,
cir::UnaryOpKind kind, bool isPre);
Expand Down
104 changes: 104 additions & 0 deletions clang/test/CIR/CodeGen/binassign.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,107 @@ void binary_assign_struct() {
// OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[LS_PTR]], ptr align 4 @gs, i64 8, i1 false)
// OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[LSV_PTR]], ptr align 4 @gsv, i64 8, i1 true)
// OGCG: ret void

int ignore_result_assign() {
int arr[10];
int i, j;
j = i = 123, 0;
j = arr[i = 5];
int *p, *q = 0;
if(p = q)
return 1;
return 0;
}

// CIR-LABEL: cir.func{{.*}} @ignore_result_assign() -> !s32i
// CIR: %[[RETVAL:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
// CIR: %[[ARR:.*]] = cir.alloca !cir.array<!s32i x 10>, !cir.ptr<!cir.array<!s32i x 10>>, ["arr"]
// CIR: %[[I:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i"]
// CIR: %[[J:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["j"]
// CIR: %[[P:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["p"]
// CIR: %[[Q:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["q", init]
// CIR: %[[VAL_123:.*]] = cir.const #cir.int<123> : !s32i
// CIR: cir.store{{.*}} %[[VAL_123]], %[[I]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.store{{.*}} %[[VAL_123]], %[[J]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[VAL_0:.*]] = cir.const #cir.int<0> : !s32i
// CIR: %[[VAL_5:.*]] = cir.const #cir.int<5> : !s32i
// CIR: cir.store{{.*}} %[[VAL_5]], %[[I]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[ARR_DECAY:.*]] = cir.cast array_to_ptrdecay %[[ARR]] : !cir.ptr<!cir.array<!s32i x 10>> -> !cir.ptr<!s32i>
// CIR: %[[ARR_ELEM:.*]] = cir.ptr_stride %[[ARR_DECAY]], %[[VAL_5]] : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
// CIR: %[[ARR_LOAD:.*]] = cir.load{{.*}} %[[ARR_ELEM]] : !cir.ptr<!s32i>, !s32i
// CIR: cir.store{{.*}} %[[ARR_LOAD]], %[[J]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[NULL:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!s32i>
// CIR: cir.store{{.*}} %[[NULL]], %[[Q]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
// CIR: cir.scope {
// CIR: %[[Q_VAL:.*]] = cir.load{{.*}} %[[Q]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
// CIR: cir.store{{.*}} %[[Q_VAL]], %[[P]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
// CIR: %[[COND:.*]] = cir.cast ptr_to_bool %[[Q_VAL]] : !cir.ptr<!s32i> -> !cir.bool
// CIR: cir.if %[[COND]] {
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CIR: cir.store %[[ONE]], %[[RETVAL]] : !s32i, !cir.ptr<!s32i>
// CIR: %{{.*}} = cir.load %[[RETVAL]] : !cir.ptr<!s32i>, !s32i
// CIR: cir.return
// CIR: }
// CIR: }
// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
// CIR: cir.store %[[ZERO]], %[[RETVAL]] : !s32i, !cir.ptr<!s32i>
// CIR: %{{.*}} = cir.load %[[RETVAL]] : !cir.ptr<!s32i>, !s32i
// CIR: cir.return

// LLVM-LABEL: define {{.*}}i32 @ignore_result_assign()
// LLVM: %[[RETVAL_PTR:.*]] = alloca i32
// LLVM: %[[ARR_PTR:.*]] = alloca [10 x i32]
// LLVM: %[[I_PTR:.*]] = alloca i32
// LLVM: %[[J_PTR:.*]] = alloca i32
// LLVM: %[[P_PTR:.*]] = alloca ptr
// LLVM: %[[Q_PTR:.*]] = alloca ptr
// LLVM: store i32 123, ptr %[[I_PTR]]
// LLVM: store i32 123, ptr %[[J_PTR]]
// LLVM: store i32 5, ptr %[[I_PTR]]
// LLVM: %[[GEP1:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i32 0
// LLVM: %[[GEP2:.*]] = getelementptr i32, ptr %[[GEP1]], i64 5
// LLVM: %[[ARR_VAL:.*]] = load i32, ptr %[[GEP2]]
// LLVM: store i32 %[[ARR_VAL]], ptr %[[J_PTR]]
// LLVM: store ptr null, ptr %[[Q_PTR]]
// LLVM: br label
// LLVM: %[[Q_VAL:.*]] = load ptr, ptr %[[Q_PTR]]
// LLVM: store ptr %[[Q_VAL]], ptr %[[P_PTR]]
// LLVM: %[[CMP:.*]] = icmp ne ptr %[[Q_VAL]], null
// LLVM: br i1 %[[CMP]], label %[[THEN:.*]], label %[[ELSE:.*]]
// LLVM: [[THEN]]:
// LLVM: store i32 1, ptr %[[RETVAL_PTR]]
// LLVM: %{{.*}} = load i32, ptr %[[RETVAL_PTR]]
// LLVM: ret i32
// LLVM: [[ELSE]]:
// LLVM: br label
// LLVM: store i32 0, ptr %[[RETVAL_PTR]]
// LLVM: %{{.*}} = load i32, ptr %[[RETVAL_PTR]]
// LLVM: ret i32

// OGCG-LABEL: define {{.*}}i32 @ignore_result_assign()
// OGCG: %[[RETVAL:.*]] = alloca i32
// OGCG: %[[ARR:.*]] = alloca [10 x i32]
// OGCG: %[[I:.*]] = alloca i32
// OGCG: %[[J:.*]] = alloca i32
// OGCG: %[[P:.*]] = alloca ptr
// OGCG: %[[Q:.*]] = alloca ptr
// OGCG: store i32 123, ptr %[[I]]
// OGCG: store i32 123, ptr %[[J]]
// OGCG: store i32 5, ptr %[[I]]
// OGCG: %[[ARRAYIDX:.*]] = getelementptr inbounds [10 x i32], ptr %[[ARR]], i64 0, i64 5
// OGCG: %[[ARR_VAL:.*]] = load i32, ptr %[[ARRAYIDX]]
// OGCG: store i32 %[[ARR_VAL]], ptr %[[J]]
// OGCG: store ptr null, ptr %[[Q]]
// OGCG: %[[Q_VAL:.*]] = load ptr, ptr %[[Q]]
// OGCG: store ptr %[[Q_VAL]], ptr %[[P]]
// OGCG: %[[TOBOOL:.*]] = icmp ne ptr %[[Q_VAL]], null
// OGCG: br i1 %[[TOBOOL]], label %[[IF_THEN:.*]], label %[[IF_END:.*]]
// OGCG: [[IF_THEN]]:
// OGCG: store i32 1, ptr %[[RETVAL]]
// OGCG: br label %[[RETURN:.*]]
// OGCG: [[IF_END]]:
// OGCG: store i32 0, ptr %[[RETVAL]]
// OGCG: br label %[[RETURN]]
// OGCG: [[RETURN]]:
// OGCG: %{{.*}} = load i32, ptr %[[RETVAL]]
// OGCG: ret i32