Skip to content

[CIR][CIRGen] Add const attribute to alloca operations #892

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 11, 2024
Merged
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
5 changes: 5 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,9 @@ def AllocaOp : CIR_Op<"alloca", [
cases, the first use contains the initialization (a cir.store, a cir.call
to a ctor, etc).

The presence of the `const` attribute indicates that the local variable is
declared with C/C++ `const` keyword.

The `dynAllocSize` specifies the size to dynamically allocate on the stack
and ignores the allocation size based on the original type. This is useful
when handling VLAs and is omitted when declaring regular local variables.
Expand All @@ -492,6 +495,7 @@ def AllocaOp : CIR_Op<"alloca", [
TypeAttr:$allocaType,
StrAttr:$name,
UnitAttr:$init,
UnitAttr:$constant,
ConfinedAttr<OptionalAttr<I64Attr>, [IntMinValue<0>]>:$alignment,
OptionalAttr<ArrayAttr>:$annotations,
OptionalAttr<ASTVarDeclInterface>:$ast
Expand Down Expand Up @@ -530,6 +534,7 @@ def AllocaOp : CIR_Op<"alloca", [
($dynAllocSize^ `:` type($dynAllocSize) `,`)?
`[` $name
(`,` `init` $init^)?
(`,` `const` $constant^)?
`]`
($annotations^)?
(`ast` $ast^)? attr-dict
Expand Down
14 changes: 8 additions & 6 deletions clang/lib/CIR/CodeGen/CIRGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,10 +305,11 @@ mlir::LogicalResult CIRGenFunction::declare(const Decl *var, QualType ty,
assert(!symbolTable.count(var) && "not supposed to be available just yet");

addr = buildAlloca(namedVar->getName(), ty, loc, alignment);
if (isParam) {
auto allocaOp = cast<mlir::cir::AllocaOp>(addr.getDefiningOp());
auto allocaOp = cast<mlir::cir::AllocaOp>(addr.getDefiningOp());
if (isParam)
allocaOp.setInitAttr(mlir::UnitAttr::get(builder.getContext()));
}
if (ty->isReferenceType() || ty.isConstQualified())
allocaOp.setConstantAttr(mlir::UnitAttr::get(builder.getContext()));

symbolTable.insert(var, addr);
return mlir::success();
Expand All @@ -324,10 +325,11 @@ mlir::LogicalResult CIRGenFunction::declare(Address addr, const Decl *var,
assert(!symbolTable.count(var) && "not supposed to be available just yet");

addrVal = addr.getPointer();
if (isParam) {
auto allocaOp = cast<mlir::cir::AllocaOp>(addrVal.getDefiningOp());
auto allocaOp = cast<mlir::cir::AllocaOp>(addrVal.getDefiningOp());
if (isParam)
allocaOp.setInitAttr(mlir::UnitAttr::get(builder.getContext()));
}
if (ty->isReferenceType() || ty.isConstQualified())
allocaOp.setConstantAttr(mlir::UnitAttr::get(builder.getContext()));

symbolTable.insert(var, addrVal);
return mlir::success();
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CIR/CodeGen/assign-operator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ struct String {
//
// CHECK: cir.func linkonce_odr @_ZN10StringViewC2ERK6String
// CHECK: %0 = cir.alloca !cir.ptr<!ty_StringView>, !cir.ptr<!cir.ptr<!ty_StringView>>, ["this", init] {alignment = 8 : i64}
// CHECK: %1 = cir.alloca !cir.ptr<!ty_String>, !cir.ptr<!cir.ptr<!ty_String>>, ["s", init] {alignment = 8 : i64}
// CHECK: %1 = cir.alloca !cir.ptr<!ty_String>, !cir.ptr<!cir.ptr<!ty_String>>, ["s", init, const] {alignment = 8 : i64}
// CHECK: cir.store %arg0, %0 : !cir.ptr<!ty_StringView>
// CHECK: cir.store %arg1, %1 : !cir.ptr<!ty_String>
// CHECK: %2 = cir.load %0 : !cir.ptr<!cir.ptr<!ty_StringView>>
Expand Down Expand Up @@ -47,7 +47,7 @@ struct String {
//
// CHECK: cir.func linkonce_odr @_ZN10StringViewaSEOS_
// CHECK: %0 = cir.alloca !cir.ptr<!ty_StringView>, !cir.ptr<!cir.ptr<!ty_StringView>>, ["this", init] {alignment = 8 : i64}
// CHECK: %1 = cir.alloca !cir.ptr<!ty_StringView>, !cir.ptr<!cir.ptr<!ty_StringView>>, ["", init] {alignment = 8 : i64}
// CHECK: %1 = cir.alloca !cir.ptr<!ty_StringView>, !cir.ptr<!cir.ptr<!ty_StringView>>, ["", init, const] {alignment = 8 : i64}
// CHECK: %2 = cir.alloca !cir.ptr<!ty_StringView>, !cir.ptr<!cir.ptr<!ty_StringView>>, ["__retval"] {alignment = 8 : i64}
// CHECK: cir.store %arg0, %0 : !cir.ptr<!ty_StringView>
// CHECK: cir.store %arg1, %1 : !cir.ptr<!ty_StringView>
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CIR/CodeGen/basic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ void x() {
}

// CHECK: cir.func @_Z1xv()
// CHECK: %0 = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, ["b0", init] {alignment = 1 : i64}
// CHECK: %1 = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, ["b1", init] {alignment = 1 : i64}
// CHECK: %0 = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, ["b0", init, const] {alignment = 1 : i64}
// CHECK: %1 = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, ["b1", init, const] {alignment = 1 : i64}
// CHECK: %2 = cir.const #true
// CHECK: cir.store %2, %0 : !cir.bool, !cir.ptr<!cir.bool>
// CHECK: %3 = cir.const #false
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CIR/CodeGen/bitfields.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ void store_field() {
}

// CHECK: cir.func @_Z10load_field
// CHECK: [[TMP0:%.*]] = cir.alloca !cir.ptr<!ty_S>, !cir.ptr<!cir.ptr<!ty_S>>, ["s", init]
// CHECK: [[TMP0:%.*]] = cir.alloca !cir.ptr<!ty_S>, !cir.ptr<!cir.ptr<!ty_S>>, ["s", init, const]
// CHECK: [[TMP1:%.*]] = cir.load [[TMP0]] : !cir.ptr<!cir.ptr<!ty_S>>, !cir.ptr<!ty_S>
// CHECK: [[TMP2:%.*]] = cir.get_member [[TMP1]][1] {name = "d"} : !cir.ptr<!ty_S> -> !cir.ptr<!cir.array<!u8i x 3>>
// CHECK: [[TMP3:%.*]] = cir.get_bitfield(#bfi_d, [[TMP2]] : !cir.ptr<!cir.array<!u8i x 3>>) -> !s32i
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CIR/CodeGen/cond.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ min(const unsigned long& __a, const unsigned long& __b) {
}

// CHECK: cir.func @_Z3minRKmS0_(%arg0: !cir.ptr<!u64i>
// CHECK: %0 = cir.alloca !cir.ptr<!u64i>, !cir.ptr<!cir.ptr<!u64i>>, ["__a", init] {alignment = 8 : i64}
// CHECK: %1 = cir.alloca !cir.ptr<!u64i>, !cir.ptr<!cir.ptr<!u64i>>, ["__b", init] {alignment = 8 : i64}
// CHECK: %0 = cir.alloca !cir.ptr<!u64i>, !cir.ptr<!cir.ptr<!u64i>>, ["__a", init, const] {alignment = 8 : i64}
// CHECK: %1 = cir.alloca !cir.ptr<!u64i>, !cir.ptr<!cir.ptr<!u64i>>, ["__b", init, const] {alignment = 8 : i64}
// CHECK: %2 = cir.alloca !cir.ptr<!u64i>, !cir.ptr<!cir.ptr<!u64i>>, ["__retval"] {alignment = 8 : i64}
// CHECK: cir.store %arg0, %0 : !cir.ptr<!u64i>, !cir.ptr<!cir.ptr<!u64i>>
// CHECK: cir.store %arg1, %1 : !cir.ptr<!u64i>, !cir.ptr<!cir.ptr<!u64i>>
Expand Down
52 changes: 52 additions & 0 deletions clang/test/CIR/CodeGen/const-alloca.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s

int produce_int();
void blackbox(const int &);

void local_const_int() {
const int x = produce_int();
}

// CHECK-LABEL: @_Z15local_const_intv
// CHECK: %{{.+}} = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init, const]
// CHECK: }

void param_const_int(const int x) {}

// CHECK-LABEL: @_Z15param_const_inti
// CHECK: %{{.+}} = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init, const]
// CHECK: }

void local_constexpr_int() {
constexpr int x = 42;
blackbox(x);
}

// CHECK-LABEL: @_Z19local_constexpr_intv
// CHECK: %{{.+}} = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init, const]
// CHECK: }

void local_reference() {
int x = 0;
int &r = x;
}

// CHECK-LABEL: @_Z15local_referencev
// CHECK: %{{.+}} = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["r", init, const]
// CHECK: }

struct Foo {
int a;
int b;
};

Foo produce_foo();

void local_const_struct() {
const Foo x = produce_foo();
}

// CHECK-LABEL: @_Z18local_const_structv
// CHECK: %{{.+}} = cir.alloca !ty_Foo, !cir.ptr<!ty_Foo>, ["x", init, const]
// CHECK: }
4 changes: 2 additions & 2 deletions clang/test/CIR/CodeGen/coro-task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,8 @@ folly::coro::Task<int> byRef(const std::string& s) {

// FIXME: this could be less redundant than two allocas + reloads
// CHECK: cir.func coroutine @_Z5byRefRKSt6string(%arg0: !cir.ptr<![[StdString]]> {{.*}} ![[IntTask]] extra{{.*}}{
// CHECK: %[[#AllocaParam:]] = cir.alloca !cir.ptr<![[StdString]]>, {{.*}} ["s", init]
// CHECK: %[[#AllocaFnUse:]] = cir.alloca !cir.ptr<![[StdString]]>, {{.*}} ["s", init]
// CHECK: %[[#AllocaParam:]] = cir.alloca !cir.ptr<![[StdString]]>, {{.*}} ["s", init, const]
// CHECK: %[[#AllocaFnUse:]] = cir.alloca !cir.ptr<![[StdString]]>, {{.*}} ["s", init, const]

folly::coro::Task<void> silly_coro() {
std::optional<folly::coro::Task<int>> task;
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CIR/CodeGen/ctor-member-lvalue-to-rvalue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ struct String {
String(const String &s) : size{s.size} {}
// CHECK: cir.func linkonce_odr @_ZN6StringC2ERKS_
// CHECK: %0 = cir.alloca !cir.ptr<!ty_String>, !cir.ptr<!cir.ptr<!ty_String>>, ["this", init] {alignment = 8 : i64}
// CHECK: %1 = cir.alloca !cir.ptr<!ty_String>, !cir.ptr<!cir.ptr<!ty_String>>, ["s", init] {alignment = 8 : i64}
// CHECK: %1 = cir.alloca !cir.ptr<!ty_String>, !cir.ptr<!cir.ptr<!ty_String>>, ["s", init, const] {alignment = 8 : i64}
// CHECK: cir.store %arg0, %0
// CHECK: cir.store %arg1, %1
// CHECK: %2 = cir.load %0
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CIR/CodeGen/derived-to-base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ void vcall(C1 &c1) {
}

// CHECK: cir.func @_Z5vcallR2C1(%arg0: !cir.ptr<!ty_C1_>
// CHECK: %0 = cir.alloca !cir.ptr<!ty_C1_>, !cir.ptr<!cir.ptr<!ty_C1_>>, ["c1", init] {alignment = 8 : i64}
// CHECK: %0 = cir.alloca !cir.ptr<!ty_C1_>, !cir.ptr<!cir.ptr<!ty_C1_>>, ["c1", init, const] {alignment = 8 : i64}
// CHECK: %1 = cir.alloca !ty_buffy, !cir.ptr<!ty_buffy>, ["b"] {alignment = 8 : i64}
// CHECK: %2 = cir.alloca !s32i, !cir.ptr<!s32i>, ["e"] {alignment = 4 : i64}
// CHECK: %3 = cir.alloca !ty_buffy, !cir.ptr<!ty_buffy>, ["agg.tmp0"] {alignment = 8 : i64}
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CIR/CodeGen/lvalue-refs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ struct String {
void split(String &S) {}

// CHECK: cir.func @_Z5splitR6String(%arg0: !cir.ptr<!ty_String>
// CHECK: %0 = cir.alloca !cir.ptr<!ty_String>, !cir.ptr<!cir.ptr<!ty_String>>, ["S", init]
// CHECK: %0 = cir.alloca !cir.ptr<!ty_String>, !cir.ptr<!cir.ptr<!ty_String>>, ["S", init, const]

void foo() {
String s;
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CIR/CodeGen/new.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ void m(int a, int b) {
}

// CHECK: cir.func linkonce_odr @_ZSt11make_sharedI1SJRiS1_EESt10shared_ptrIT_EDpOT0_(
// CHECK: %0 = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["args", init] {alignment = 8 : i64}
// CHECK: %1 = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["args", init] {alignment = 8 : i64}
// CHECK: %0 = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["args", init, const] {alignment = 8 : i64}
// CHECK: %1 = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["args", init, const] {alignment = 8 : i64}
// CHECK: %2 = cir.alloca !ty_std3A3Ashared_ptr3CS3E, !cir.ptr<!ty_std3A3Ashared_ptr3CS3E>, ["__retval"] {alignment = 1 : i64}
// CHECK: cir.store %arg0, %0 : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
// CHECK: cir.store %arg1, %1 : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CIR/CodeGen/rangefor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ void init(unsigned numImages) {
// CHECK: %3 = cir.cast(integral, %2 : !u32i), !u64i
// CHECK: cir.call @_ZNSt6vectorI6tripleEC1Em(%1, %3) : (!cir.ptr<![[VEC]]>, !u64i) -> ()
// CHECK: cir.scope {
// CHECK: %4 = cir.alloca !cir.ptr<![[VEC]]>, !cir.ptr<!cir.ptr<![[VEC]]>>, ["__range1", init] {alignment = 8 : i64}
// CHECK: %4 = cir.alloca !cir.ptr<![[VEC]]>, !cir.ptr<!cir.ptr<![[VEC]]>>, ["__range1", init, const] {alignment = 8 : i64}
// CHECK: %5 = cir.alloca ![[VEC_IT]], !cir.ptr<![[VEC_IT]]>, ["__begin1", init] {alignment = 8 : i64}
// CHECK: %6 = cir.alloca ![[VEC_IT]], !cir.ptr<![[VEC_IT]]>, ["__end1", init] {alignment = 8 : i64}
// CHECK: %7 = cir.alloca !cir.ptr<!ty_triple>, !cir.ptr<!cir.ptr<!ty_triple>>, ["image", init] {alignment = 8 : i64}
// CHECK: %7 = cir.alloca !cir.ptr<!ty_triple>, !cir.ptr<!cir.ptr<!ty_triple>>, ["image", init, const] {alignment = 8 : i64}
// CHECK: cir.store %1, %4 : !cir.ptr<![[VEC]]>, !cir.ptr<!cir.ptr<![[VEC]]>>
// CHECK: %8 = cir.load %4 : !cir.ptr<!cir.ptr<![[VEC]]>>, !cir.ptr<![[VEC]]>
// CHECK: %9 = cir.call @_ZNSt6vectorI6tripleE5beginEv(%8) : (!cir.ptr<![[VEC]]>) -> ![[VEC_IT]]
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CIR/CodeGen/return.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ int &ret0(int &x) {
}

// CHECK: cir.func @_Z4ret0Ri
// CHECK: %0 = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["x", init] {alignment = 8 : i64}
// CHECK: %0 = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["x", init, const] {alignment = 8 : i64}
// CHECK: %1 = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["__retval"] {alignment = 8 : i64}
// CHECK: cir.store %arg0, %0 : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
// CHECK: %2 = cir.load %0 : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CIR/CodeGen/temporary-materialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ int test() {
// CHECK: cir.func @_Z4testv()
// CHECK-NEXT: %{{.+}} = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}
// CHECK-NEXT: %[[#TEMP_SLOT:]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["ref.tmp0", init] {alignment = 4 : i64}
// CHECK-NEXT: %[[#x:]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["x", init] {alignment = 8 : i64}
// CHECK-NEXT: %[[#x:]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["x", init, const] {alignment = 8 : i64}
// CHECK-NEXT: cir.scope {
// CHECK-NEXT: %[[#TEMP_VALUE:]] = cir.call @_Z8make_intv() : () -> !s32i
// CHECK-NEXT: cir.store %[[#TEMP_VALUE]], %[[#TEMP_SLOT]] : !s32i, !cir.ptr<!s32i>
Expand All @@ -33,7 +33,7 @@ int test_scoped() {
// CHECK-NEXT: %{{.+}} = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init] {alignment = 4 : i64}
// CHECK: cir.scope {
// CHECK-NEXT: %[[#TEMP_SLOT:]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["ref.tmp0", init] {alignment = 4 : i64}
// CHECK-NEXT: %[[#y:]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["y", init] {alignment = 8 : i64}
// CHECK-NEXT: %[[#y:]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["y", init, const] {alignment = 8 : i64}
// CHECK-NEXT: cir.scope {
// CHECK-NEXT: %[[#TEMP_VALUE:]] = cir.call @_Z8make_intv() : () -> !s32i
// CHECK-NEXT: cir.store %[[#TEMP_VALUE]], %[[#TEMP_SLOT]] : !s32i, !cir.ptr<!s32i>
Expand Down