[CIR] Upstream scalar support for ParenExpr (#136332)

This change adds support for handling ParenExpr in scalar expressions. A
few more places will need to be updated after structure assignment and
complex type support is in place.
This commit is contained in:
Andy Kaylor
2025-04-18 11:25:41 -07:00
committed by GitHub
parent 7cc4472037
commit 7c51e42615
3 changed files with 67 additions and 0 deletions

View File

@@ -116,6 +116,8 @@ public:
return {};
}
mlir::Value VisitParenExpr(ParenExpr *pe) { return Visit(pe->getSubExpr()); }
/// Emits the address of the l-value, then loads and returns the result.
mlir::Value emitLoadOfLValue(const Expr *e) {
LValue lv = cgf.emitLValue(e);

View File

@@ -515,6 +515,8 @@ LValue CIRGenFunction::emitLValue(const Expr *e) {
return emitUnaryOpLValue(cast<UnaryOperator>(e));
case Expr::BinaryOperatorClass:
return emitBinaryOperatorLValue(cast<BinaryOperator>(e));
case Expr::ParenExprClass:
return emitLValue(cast<ParenExpr>(e)->getSubExpr());
case Expr::DeclRefExprClass:
return emitDeclRefLValue(cast<DeclRefExpr>(e));
}

View File

@@ -169,3 +169,66 @@ int f6(void) {
// OGCG-NEXT: entry:
// OGCG-NEXT: %[[GV:.*]] = load i32, ptr @gv, align 4
// OGCG-NEXT: ret i32 %[[GV]]
int f7(int a, int b, int c) {
return a + (b + c);
}
// CIR: cir.func @f7
// CIR: %[[A_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init]
// CIR: %[[B_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["b", init]
// CIR: %[[C_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["c", init]
// CIR: %[[A:.*]] = cir.load %[[A_PTR]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[B:.*]] = cir.load %[[B_PTR]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[C:.*]] = cir.load %[[C_PTR]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[B_PLUS_C:.*]] = cir.binop(add, %[[B]], %[[C]]) nsw : !s32i
// CIR: %[[RETVAL:.*]] = cir.binop(add, %[[A]], %[[B_PLUS_C]]) nsw : !s32i
// LLVM: define i32 @f7
// LLVM: %[[A_PTR:.*]] = alloca i32, i64 1, align 4
// LLVM: %[[B_PTR:.*]] = alloca i32, i64 1, align 4
// LLVM: %[[C_PTR:.*]] = alloca i32, i64 1, align 4
// LLVM: %[[A:.*]] = load i32, ptr %[[A_PTR]], align 4
// LLVM: %[[B:.*]] = load i32, ptr %[[B_PTR]], align 4
// LLVM: %[[C:.*]] = load i32, ptr %[[C_PTR]], align 4
// LLVM: %[[B_PLUS_C:.*]] = add nsw i32 %[[B]], %[[C]]
// LLVM: %[[RETVAL:.*]] = add nsw i32 %[[A]], %[[B_PLUS_C]]
// OGCG: define{{.*}} i32 @f7
// OGCG: entry:
// OGCG: %[[A_PTR:.*]] = alloca i32, align 4
// OGCG: %[[B_PTR:.*]] = alloca i32, align 4
// OGCG: %[[C_PTR:.*]] = alloca i32, align 4
// OGCG: %[[A:.*]] = load i32, ptr %[[A_PTR]], align 4
// OGCG: %[[B:.*]] = load i32, ptr %[[B_PTR]], align 4
// OGCG: %[[C:.*]] = load i32, ptr %[[C_PTR]], align 4
// OGCG: %[[B_PLUS_C:.*]] = add nsw i32 %[[B]], %[[C]]
// OGCG: %[[RETVAL:.*]] = add nsw i32 %[[A]], %[[B_PLUS_C]]
int f8(int *p) {
(*p) = 2;
return (*p);
}
// CIR: cir.func @f8
// CIR: %[[P_PTR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["p", init]
// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s32i
// CIR: %[[P:.*]] = cir.load deref %[[P_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
// CIR: cir.store %[[TWO]], %[[P]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[P2:.*]] = cir.load deref %[[P_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
// CIR: %[[STAR_P:.*]] = cir.load %[[P2]] : !cir.ptr<!s32i>, !s32i
// LLVM: define i32 @f8
// LLVM: %[[P_PTR:.*]] = alloca ptr, i64 1, align 8
// LLVM: %[[P:.*]] = load ptr, ptr %[[P_PTR]], align 8
// LLVM: store i32 2, ptr %[[P]], align 4
// LLVM: %[[P2:.*]] = load ptr, ptr %[[P_PTR]], align 8
// LLVM: %[[STAR_P:.*]] = load i32, ptr %[[P2]], align 4
// OGCG: define{{.*}} i32 @f8
// OGCG: entry:
// OGCG: %[[P_PTR:.*]] = alloca ptr, align 8
// OGCG: %[[P:.*]] = load ptr, ptr %[[P_PTR]], align 8
// OGCG: store i32 2, ptr %[[P]], align 4
// OGCG: %[[P2:.*]] = load ptr, ptr %[[P_PTR]], align 8
// OGCG: %[[STAR_P:.*]] = load i32, ptr %[[P2]], align 4