Skip to content

Commit 33c1521

Browse files
committed
[CIR] Backport CountOf VLA with Array element type
1 parent 0255897 commit 33c1521

File tree

4 files changed

+95
-15
lines changed

4 files changed

+95
-15
lines changed

clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3028,28 +3028,44 @@ mlir::Value ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
30283028
mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
30293029
const UnaryExprOrTypeTraitExpr *E) {
30303030
QualType TypeToSize = E->getTypeOfArgument();
3031-
if (E->getKind() == UETT_SizeOf) {
3031+
if (auto kind = E->getKind();
3032+
kind == UETT_SizeOf || kind == UETT_DataSizeOf | kind == UETT_CountOf) {
30323033
if (const VariableArrayType *VAT =
30333034
CGF.getContext().getAsVariableArrayType(TypeToSize)) {
30343035

3035-
if (E->isArgumentType()) {
3036-
// sizeof(type) - make sure to emit the VLA size.
3037-
CGF.emitVariablyModifiedType(TypeToSize);
3038-
} else {
3039-
// C99 6.5.3.4p2: If the argument is an expression of type
3040-
// VLA, it is evaluated.
3041-
CGF.emitIgnoredExpr(E->getArgumentExpr());
3036+
// For _Countof, we only want to evaluate if the extent is actually
3037+
// variable as opposed to a multi-dimensional array whose extent is
3038+
// constant but whose element type is variable.
3039+
bool evaluateExtent = true;
3040+
if (kind == UETT_CountOf && VAT->getElementType()->isArrayType()) {
3041+
evaluateExtent =
3042+
!VAT->getSizeExpr()->isIntegerConstantExpr(CGF.getContext());
30423043
}
30433044

3044-
auto VlaSize = CGF.getVLASize(VAT);
3045-
mlir::Value size = VlaSize.NumElts;
3045+
if (evaluateExtent) {
3046+
if (E->isArgumentType()) {
3047+
// sizeof(type) - make sure to emit the VLA size.
3048+
CGF.emitVariablyModifiedType(TypeToSize);
3049+
} else {
3050+
// C99 6.5.3.4p2: If the argument is an expression of type
3051+
// VLA, it is evaluated.
3052+
CGF.emitIgnoredExpr(E->getArgumentExpr());
3053+
}
3054+
3055+
// For _Countof, we just want to return the size of a single dimension.
3056+
if (kind == UETT_CountOf)
3057+
return CGF.getVLAElements1D(VAT).NumElts;
3058+
3059+
auto VlaSize = CGF.getVLASize(VAT);
3060+
mlir::Value size = VlaSize.NumElts;
30463061

3047-
// Scale the number of non-VLA elements by the non-VLA element size.
3048-
CharUnits eltSize = CGF.getContext().getTypeSizeInChars(VlaSize.Type);
3049-
if (!eltSize.isOne())
3050-
size = Builder.createMul(size, CGF.CGM.getSize(eltSize).getValue());
3062+
// Scale the number of non-VLA elements by the non-VLA element size.
3063+
CharUnits eltSize = CGF.getContext().getTypeSizeInChars(VlaSize.Type);
3064+
if (!eltSize.isOne())
3065+
size = Builder.createMul(size, CGF.CGM.getSize(eltSize).getValue());
30513066

3052-
return size;
3067+
return size;
3068+
}
30533069
}
30543070
} else if (E->getKind() == UETT_OpenMPRequiredSimdAlign) {
30553071
llvm_unreachable("NYI");

clang/lib/CIR/CodeGen/CIRGenFunction.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1808,6 +1808,14 @@ CIRGenFunction::getVLASize(const VariableArrayType *type) {
18081808
return {numElements, elementType};
18091809
}
18101810

1811+
CIRGenFunction::VlaSizePair
1812+
CIRGenFunction::getVLAElements1D(const VariableArrayType *vla) {
1813+
mlir::Value vlaSize = VLASizeMap[vla->getSizeExpr()];
1814+
assert(vlaSize && "no size for VLA!");
1815+
assert(vlaSize->getType() == sizeTy);
1816+
return {vlaSize, vla->getElementType()};
1817+
}
1818+
18111819
// TODO(cir): most part of this function can be shared between CIRGen
18121820
// and traditional LLVM codegen
18131821
void CIRGenFunction::emitVariablyModifiedType(QualType type) {

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,10 @@ class CIRGenFunction : public CIRGenTypeCache {
683683
VlaSizePair(mlir::Value NE, QualType T) : NumElts(NE), Type(T) {}
684684
};
685685

686+
/// Return the number of elements for a single dimension
687+
/// for the given array type.
688+
VlaSizePair getVLAElements1D(const VariableArrayType *vla);
689+
686690
/// Returns an MLIR value that corresponds to the size,
687691
/// in non-variably-sized elements, of a variable length array type,
688692
/// plus that largest non-variably-sized element type. Assumes that

clang/test/CIR/CodeGen/count-of.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// RUN: %clang_cc1 -std=c2y -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir %s -o %t.cir
2+
// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
3+
// RUN: %clang_cc1 -std=c2y -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 -std=c2y -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+
unsigned long vla_with_array_element_type_with_const_size() {
9+
long size;
10+
return _Countof(int[5][size]);
11+
}
12+
13+
// CIR: %[[RET_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["__retval"]
14+
// CIR: %[[SIZE_ADDR:.*]] = cir.alloca !s64i, !cir.ptr<!s64i>, ["size"]
15+
// CIR: %[[CONST_5:.*]] = cir.const #cir.int<5> : !u64i
16+
// CIR: cir.store %[[CONST_5]], %[[RET_ADDR]] : !u64i, !cir.ptr<!u64i>
17+
// CIR: %[[RET_VAL:.*]] = cir.load %[[RET_ADDR]] : !cir.ptr<!u64i>, !u64i
18+
// CIR: cir.return %[[RET_VAL]] : !u64i
19+
20+
// LLVM: %[[RET_ADDR:.*]] = alloca i64, i64 1, align 8
21+
// LLVM: %[[SIZE_ADDR:.*]] = alloca i64, i64 1, align 8
22+
// LLVM: store i64 5, ptr %[[RET_ADDR]], align 8
23+
// LLVM: %[[RET_VAL:.*]] = load i64, ptr %[[RET_ADDR]], align 8
24+
// LLVM: ret i64 %[[RET_VAL]]
25+
26+
// OGCG: %[[SIZE_ADDR:.*]] = alloca i64, align 8
27+
// OGCG: ret i64 5
28+
29+
unsigned long vla_with_array_element_type_non_const_size() {
30+
long size;
31+
return _Countof(int[size][size]);
32+
}
33+
34+
// CIR: %[[REET_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["__retval"]
35+
// CIR: %[[SIZE_ADDR:.*]] = cir.alloca !s64i, !cir.ptr<!s64i>, ["size"]
36+
// CIR: %[[TMP_SIZE:.*]] = cir.load {{.*}} %[[SIZE_ADDR]] : !cir.ptr<!s64i>, !s64i
37+
// CIR: %[[TMP_SIZE_U64:.*]] = cir.cast integral %[[TMP_SIZE]] : !s64i -> !u64i
38+
// CIR: cir.store %[[TMP_SIZE_U64]], %[[RET_ADDR]] : !u64i, !cir.ptr<!u64i>
39+
// CIR: %[[TMP_RET:.*]] = cir.load %[[RET_ADDR]] : !cir.ptr<!u64i>, !u64i
40+
// CIR: cir.return %[[TMP_RET]] : !u64i
41+
42+
// LLVM: %[[RET_ADDR:.*]] = alloca i64, i64 1, align 8
43+
// LLVM: %[[SIZE_ADDR:.*]] = alloca i64, i64 1, align 8
44+
// LLVM: %[[TMP_SIZE:.*]] = load i64, ptr %[[SIZE_ADDR]], align 8
45+
// LLVM: store i64 %[[TMP_SIZE]], ptr %[[RET_ADDR]], align 8
46+
// LLVM: %[[TMP_RET:.*]] = load i64, ptr %[[RET_ADDR]], align 8
47+
// LLVM: ret i64 %[[TMP_RET]]
48+
49+
// OGCG: %[[SIZE_ADDR:.*]] = alloca i64, align 8
50+
// OGCG: %[[TMP_SIZE:.*]] = load i64, ptr %[[SIZE_ADDR]], align 8
51+
// OGCG: %[[TMP_SIZE_2:.*]] = load i64, ptr %[[SIZE_ADDR]], align 8
52+
// OGCG: ret i64 %[[TMP_SIZE]]

0 commit comments

Comments
 (0)