diff options
Diffstat (limited to 'clang/test/CIR/CodeGen')
-rw-r--r-- | clang/test/CIR/CodeGen/dynamic-cast.cpp | 56 | ||||
-rw-r--r-- | clang/test/CIR/CodeGen/ptrdiff.c | 51 | ||||
-rw-r--r-- | clang/test/CIR/CodeGen/ptrdiff.cpp | 33 | ||||
-rw-r--r-- | clang/test/CIR/CodeGen/throws.cpp | 73 | ||||
-rw-r--r-- | clang/test/CIR/CodeGen/vla.c | 285 |
5 files changed, 498 insertions, 0 deletions
diff --git a/clang/test/CIR/CodeGen/dynamic-cast.cpp b/clang/test/CIR/CodeGen/dynamic-cast.cpp index b493840..5d010d2 100644 --- a/clang/test/CIR/CodeGen/dynamic-cast.cpp +++ b/clang/test/CIR/CodeGen/dynamic-cast.cpp @@ -101,3 +101,59 @@ Derived &ref_cast(Base &b) { // OGCG: br i1 %[[IS_NULL]], label %[[BAD_CAST:.*]], label %[[DONE:.*]] // OGCG: [[BAD_CAST]]: // OGCG: call void @__cxa_bad_cast() + +void *ptr_cast_to_complete(Base *ptr) { + return dynamic_cast<void *>(ptr); +} + +// CIR-BEFORE: cir.func dso_local @_Z20ptr_cast_to_completeP4Base +// CIR-BEFORE: %{{.+}} = cir.dyn_cast ptr %{{.+}} : !cir.ptr<!rec_Base> -> !cir.ptr<!void> +// CIR-BEFORE: } + +// CIR-AFTER: cir.func dso_local @_Z20ptr_cast_to_completeP4Base +// CIR-AFTER: %[[SRC:.*]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!cir.ptr<!rec_Base>>, !cir.ptr<!rec_Base> +// CIR-AFTER-NEXT: %[[SRC_IS_NOT_NULL:.*]] = cir.cast ptr_to_bool %[[SRC]] : !cir.ptr<!rec_Base> -> !cir.bool +// CIR-AFTER-NEXT: %{{.+}} = cir.ternary(%[[SRC_IS_NOT_NULL]], true { +// CIR-AFTER-NEXT: %[[VPTR_PTR:.*]] = cir.vtable.get_vptr %[[SRC]] : !cir.ptr<!rec_Base> -> !cir.ptr<!cir.vptr> +// CIR-AFTER-NEXT: %[[VPTR:.*]] = cir.load %[[VPTR_PTR]] : !cir.ptr<!cir.vptr>, !cir.vptr +// CIR-AFTER-NEXT: %[[ELEM_PTR:.*]] = cir.cast bitcast %[[VPTR]] : !cir.vptr -> !cir.ptr<!s64i> +// CIR-AFTER-NEXT: %[[MINUS_TWO:.*]] = cir.const #cir.int<-2> : !s64i +// CIR-AFTER-NEXT: %[[BASE_OFFSET_PTR:.*]] = cir.ptr_stride %[[ELEM_PTR]], %[[MINUS_TWO]] : (!cir.ptr<!s64i>, !s64i) -> !cir.ptr<!s64i> +// CIR-AFTER-NEXT: %[[BASE_OFFSET:.*]] = cir.load{{.*}} %[[BASE_OFFSET_PTR]] : !cir.ptr<!s64i>, !s64i +// CIR-AFTER-NEXT: %[[SRC_BYTES_PTR:.*]] = cir.cast bitcast %[[SRC]] : !cir.ptr<!rec_Base> -> !cir.ptr<!u8i> +// CIR-AFTER-NEXT: %[[DST_BYTES_PTR:.*]] = cir.ptr_stride %[[SRC_BYTES_PTR]], %[[BASE_OFFSET]] : (!cir.ptr<!u8i>, !s64i) -> !cir.ptr<!u8i> +// CIR-AFTER-NEXT: %[[CASTED_PTR:.*]] = cir.cast bitcast %[[DST_BYTES_PTR]] : !cir.ptr<!u8i> -> !cir.ptr<!void> +// CIR-AFTER-NEXT: cir.yield %[[CASTED_PTR]] : !cir.ptr<!void> +// CIR-AFTER-NEXT: }, false { +// CIR-AFTER-NEXT: %[[NULL_PTR:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!void> +// CIR-AFTER-NEXT: cir.yield %[[NULL_PTR]] : !cir.ptr<!void> +// CIR-AFTER-NEXT: }) : (!cir.bool) -> !cir.ptr<!void> +// CIR-AFTER: } + +// LLVM: define {{.*}} @_Z20ptr_cast_to_completeP4Base +// LLVM: %[[IS_NOT_NULL:.*]] = icmp ne ptr %[[PTR:.*]], null +// LLVM: br i1 %[[IS_NOT_NULL]], label %[[NOT_NULL:.*]], label %[[NULL:.*]] +// LLVM: [[NOT_NULL]]: +// LLVM: %[[VPTR:.*]] = load ptr, ptr %[[PTR]] +// LLVM: %[[BASE_OFFSET_PTR:.*]] = getelementptr i64, ptr %7, i64 -2 +// LLVM: %[[BASE_OFFSET:.*]] = load i64, ptr %[[BASE_OFFSET_PTR]] +// LLVM: %[[RESULT:.*]] = getelementptr i8, ptr %[[PTR]], i64 %[[BASE_OFFSET]] +// LLVM: br label %[[DONE:.*]] +// LLVM: [[NULL]]: +// LLVM: br label %[[DONE]] +// LLVM: [[DONE]]: +// LLVM: %[[RET:.*]] = phi ptr [ null, %[[NULL]] ], [ %[[RESULT]], %[[NOT_NULL]] ] + +// OGCG: define {{.*}} @_Z20ptr_cast_to_completeP4Base +// OGCG: %[[IS_NULL:.*]] = icmp eq ptr %[[PTR:.*]], null +// OGCG: br i1 %[[IS_NULL]], label %[[NULL:.*]], label %[[NOT_NULL:.*]] +// OGCG: [[NOT_NULL]]: +// OGCG: %[[VPTR:.*]] = load ptr, ptr %[[PTR]] +// OGCG: %[[BASE_OFFSET_PTR:.*]] = getelementptr inbounds i64, ptr %[[VPTR]], i64 -2 +// OGCG: %[[BASE_OFFSET:.*]] = load i64, ptr %[[BASE_OFFSET_PTR]] +// OGCG: %[[RESULT:.*]] = getelementptr inbounds i8, ptr %[[PTR]], i64 %[[BASE_OFFSET]] +// OGCG: br label %[[DONE:.*]] +// OGCG: [[NULL]]: +// OGCG: br label %[[DONE]] +// OGCG: [[DONE]]: +// OGCG: %[[RET:.*]] = phi ptr [ %[[RESULT]], %[[NOT_NULL]] ], [ null, %[[NULL]] ] diff --git a/clang/test/CIR/CodeGen/ptrdiff.c b/clang/test/CIR/CodeGen/ptrdiff.c new file mode 100644 index 0000000..e6a754e --- /dev/null +++ b/clang/test/CIR/CodeGen/ptrdiff.c @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll +// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s + +int addrcmp(const void* a, const void* b) { + // CIR-LABEL: addrcmp + // CIR: %[[R:.*]] = cir.ptr_diff + // CIR: cir.cast integral %[[R]] : !s64i -> !s32i + + // LLVM-LABEL: define dso_local i32 @addrcmp( + // LLVM: %[[PTR_A:.*]] = ptrtoint ptr {{.*}} to i64 + // LLVM: %[[PTR_B:.*]] = ptrtoint ptr {{.*}} to i64 + // LLVM: %[[SUB:.*]] = sub i64 %[[PTR_A]], %[[PTR_B]] + // LLVM-NOT: sdiv + // LLVM: trunc i64 %[[SUB]] to i32 + + // OGCG-LABEL: define dso_local i32 @addrcmp( + // OGCG: %[[PTR_A:.*]] = ptrtoint ptr {{.*}} to i64 + // OGCG: %[[PTR_B:.*]] = ptrtoint ptr {{.*}} to i64 + // OGCG: %[[SUB:.*]] = sub i64 %[[PTR_A]], %[[PTR_B]] + // OGCG-NOT: sdiv + // OGCG: trunc i64 %[[SUB]] to i32 + return *(const void**)a - *(const void**)b; +} + +unsigned long long test_ptr_diff(int *a, int* b) { + // CIR-LABEL: test_ptr_diff + // CIR: %[[D:.*]] = cir.ptr_diff {{.*}} : !cir.ptr<!s32i> -> !s64i + // CIR: %[[U:.*]] = cir.cast integral %[[D]] : !s64i -> !u64i + // CIR: cir.return {{.*}} : !u64i + + // LLVM-LABEL: define dso_local i64 @test_ptr_diff( + // LLVM: %[[IA:.*]] = ptrtoint ptr %{{.*}} to i64 + // LLVM: %[[IB:.*]] = ptrtoint ptr %{{.*}} to i64 + // LLVM: %[[SUB:.*]] = sub i64 %[[IA]], %[[IB]] + // LLVM: %[[Q:.*]] = sdiv exact i64 %[[SUB]], 4 + // LLVM: store i64 %[[Q]], ptr %[[RETADDR:.*]], align + // LLVM: %[[RETLOAD:.*]] = load i64, ptr %[[RETADDR]], align + // LLVM: ret i64 %[[RETLOAD]] + + // OGCG-LABEL: define dso_local i64 @test_ptr_diff( + // OGCG: %[[IA:.*]] = ptrtoint ptr %{{.*}} to i64 + // OGCG: %[[IB:.*]] = ptrtoint ptr %{{.*}} to i64 + // OGCG: %[[SUB:.*]] = sub i64 %[[IA]], %[[IB]] + // OGCG: %[[Q:.*]] = sdiv exact i64 %[[SUB]], 4 + // OGCG: ret i64 %[[Q]] + return a - b; +}
\ No newline at end of file diff --git a/clang/test/CIR/CodeGen/ptrdiff.cpp b/clang/test/CIR/CodeGen/ptrdiff.cpp new file mode 100644 index 0000000..34ba0ff --- /dev/null +++ b/clang/test/CIR/CodeGen/ptrdiff.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM +// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG + +typedef unsigned long size_type; + +size_type size(unsigned long *_start, unsigned long *_finish) { + // CIR-LABEL: cir.func dso_local @_Z4sizePmS_ + // CIR: %[[D:.*]] = cir.ptr_diff {{.*}} : !cir.ptr<!u64i> -> !s64i + // CIR: %[[U:.*]] = cir.cast integral %[[D]] : !s64i -> !u64i + // CIR: cir.return {{.*}} : !u64i + + // LLVM-LABEL: define dso_local {{.*}}i64 @_Z4sizePmS_( + // LLVM: %[[IA:.*]] = ptrtoint ptr %{{.*}} to i64 + // LLVM: %[[IB:.*]] = ptrtoint ptr %{{.*}} to i64 + // LLVM: %[[SUB:.*]] = sub i64 %[[IA]], %[[IB]] + // LLVM: %[[Q:.*]] = sdiv exact i64 %[[SUB]], 8 + // LLVM: store i64 %[[Q]], ptr %[[RETADDR:.*]], align + // LLVM: %[[RET:.*]] = load i64, ptr %[[RETADDR]], align + // LLVM: ret i64 %[[RET]] + + // OGCG-LABEL: define dso_local {{.*}}i64 @_Z4sizePmS_( + // OGCG: %[[IA:.*]] = ptrtoint ptr %{{.*}} to i64 + // OGCG: %[[IB:.*]] = ptrtoint ptr %{{.*}} to i64 + // OGCG: %[[SUB:.*]] = sub i64 %[[IA]], %[[IB]] + // OGCG: %[[Q:.*]] = sdiv exact i64 %[[SUB]], 8 + // OGCG: ret i64 %[[Q]] + + return static_cast<size_type>(_finish - _start); +}
\ No newline at end of file diff --git a/clang/test/CIR/CodeGen/throws.cpp b/clang/test/CIR/CodeGen/throws.cpp index ff6aa62..89cb072 100644 --- a/clang/test/CIR/CodeGen/throws.cpp +++ b/clang/test/CIR/CodeGen/throws.cpp @@ -123,3 +123,76 @@ void paren_expr() { (throw 0, 1 + 2); } // OGCG: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 4) // OGCG: store i32 0, ptr %[[EXCEPTION_ADDR]], align 16 // OGCG: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIi, ptr null) + +void throw_complex_expr() { + throw __builtin_complex(1.1f, 2.2f); +} + +// CIR: %[[EXCEPTION_ADDR:.*]] = cir.alloc.exception 8 -> !cir.ptr<!cir.complex<!cir.float>> +// CIR: %[[EXCEPTION_VALUE:.*]] = cir.const #cir.const_complex<#cir.fp<1.100000e+00> : !cir.float, #cir.fp<2.200000e+00> : !cir.float> : !cir.complex<!cir.float> +// CIR: cir.store{{.*}} %[[EXCEPTION_VALUE]], %[[EXCEPTION_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>> +// CIR: cir.throw %[[EXCEPTION_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, @_ZTICf +// CIR: cir.unreachable + +// LLVM: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 8) +// LLVM: store { float, float } { float 0x3FF19999A0000000, float 0x40019999A0000000 }, ptr %[[EXCEPTION_ADDR]], align 16 +// LLVM: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTICf, ptr null) + +// OGCG: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 8) +// OGCG: %[[EXCEPTION_REAL:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[EXCEPTION_ADDR]], i32 0, i32 0 +// OGCG: %[[EXCEPTION_IMAG:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[EXCEPTION_ADDR]], i32 0, i32 1 +// OGCG: store float 0x3FF19999A0000000, ptr %[[EXCEPTION_REAL]], align 16 +// OGCG: store float 0x40019999A0000000, ptr %[[EXCEPTION_IMAG]], align 4 +// OGCG: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTICf, ptr null) + +void throw_vector_type() { + typedef int vi4 __attribute__((vector_size(16))); + vi4 a; + throw a; +} + +// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a"] +// CIR: %[[EXCEPTION_ADDR:.*]] = cir.alloc.exception 16 -> !cir.ptr<!cir.vector<4 x !s32i>> +// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i> +// CIR: cir.store{{.*}} %[[TMP_A]], %[[EXCEPTION_ADDR]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>> +// CIR: cir.throw %[[EXCEPTION_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, @_ZTIDv4_i +// CIR: cir.unreachable + +// LLVM: %[[A_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16 +// LLVM: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 16) +// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16 +// LLVM: store <4 x i32> %[[TMP_A]], ptr %[[EXCEPTION_ADDR]], align 16 +// LLVM: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIDv4_i, ptr null) + +// OGCG: %[[A_ADDR:.*]] = alloca <4 x i32>, align 16 +// OGCG: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 16) +// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16 +// OGCG: store <4 x i32> %[[TMP_A]], ptr %[[EXCEPTION_ADDR]], align 16 +// OGCG: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIDv4_i, ptr null) +// OGCG: unreachable + +void throw_ext_vector_type() { + typedef int vi4 __attribute__((ext_vector_type(4))); + vi4 a; + throw a; +} + +// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a"] +// CIR: %[[EXCEPTION_ADDR:.*]] = cir.alloc.exception 16 -> !cir.ptr<!cir.vector<4 x !s32i>> +// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i> +// CIR: cir.store{{.*}} %[[TMP_A]], %[[EXCEPTION_ADDR]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>> +// CIR: cir.throw %[[EXCEPTION_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, @_ZTIDv4_i +// CIR: cir.unreachable + +// LLVM: %[[A_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16 +// LLVM: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 16) +// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16 +// LLVM: store <4 x i32> %[[TMP_A]], ptr %[[EXCEPTION_ADDR]], align 16 +// LLVM: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIDv4_i, ptr null) + +// OGCG: %[[A_ADDR:.*]] = alloca <4 x i32>, align 16 +// OGCG: %[[EXCEPTION_ADDR:.*]] = call ptr @__cxa_allocate_exception(i64 16) +// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16 +// OGCG: store <4 x i32> %[[TMP_A]], ptr %[[EXCEPTION_ADDR]], align 16 +// OGCG: call void @__cxa_throw(ptr %[[EXCEPTION_ADDR]], ptr @_ZTIDv4_i, ptr null) +// OGCG: unreachable diff --git a/clang/test/CIR/CodeGen/vla.c b/clang/test/CIR/CodeGen/vla.c new file mode 100644 index 0000000..e2adf45 --- /dev/null +++ b/clang/test/CIR/CodeGen/vla.c @@ -0,0 +1,285 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll +// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG + +void f0(int len) { + int arr[len]; +} + +// CIR: cir.func{{.*}} @f0(%[[LEN_ARG:.*]]: !s32i {{.*}}) +// CIR: %[[LEN_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["len", init] +// CIR: %[[SAVED_STACK:.*]] = cir.alloca !cir.ptr<!u8i>, !cir.ptr<!cir.ptr<!u8i>>, ["saved_stack"] +// CIR: cir.store{{.*}} %[[LEN_ARG]], %[[LEN_ADDR]] +// CIR: %[[LEN:.*]] = cir.load{{.*}} %[[LEN_ADDR]] +// CIR: %[[LEN_SIZE_T:.*]] = cir.cast integral %[[LEN]] : !s32i -> !u64i +// CIR: %[[STACK_PTR:.*]] = cir.stacksave +// CIR: cir.store{{.*}} %[[STACK_PTR]], %[[SAVED_STACK]] +// CIR: %[[ARR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, %[[LEN_SIZE_T]] : !u64i, ["arr"] +// CIR: %[[STACK_RESTORE_PTR:.*]] = cir.load{{.*}} %[[SAVED_STACK]] +// CIR: cir.stackrestore %[[STACK_RESTORE_PTR]] + +// LLVM: define{{.*}} void @f0(i32 %[[LEN_ARG:.*]]) { +// LLVM: %[[LEN_ADDR:.*]] = alloca i32 +// LLVM: %[[SAVED_STACK:.*]] = alloca ptr +// LLVM: store i32 %[[LEN_ARG]], ptr %[[LEN_ADDR]] +// LLVM: %[[LEN:.*]] = load i32, ptr %[[LEN_ADDR]] +// LLVM: %[[LEN_SIZE_T:.*]] = sext i32 %[[LEN]] to i64 +// LLVM: %[[STACK_PTR:.*]] = call ptr @llvm.stacksave.p0() +// LLVM: store ptr %[[STACK_PTR]], ptr %[[SAVED_STACK]] +// LLVM: %[[ARR:.*]] = alloca i32, i64 %[[LEN_SIZE_T]] +// LLVM: %[[STACK_RESTORE_PTR:.*]] = load ptr, ptr %[[SAVED_STACK]] +// LLVM: call void @llvm.stackrestore.p0(ptr %[[STACK_RESTORE_PTR]]) + +// Note: VLA_EXPR0 below is emitted to capture debug info. + +// OGCG: define{{.*}} void @f0(i32 {{.*}} %[[LEN_ARG:.*]]) +// OGCG: %[[LEN_ADDR:.*]] = alloca i32 +// OGCG: %[[SAVED_STACK:.*]] = alloca ptr +// OGCG: %[[VLA_EXPR0:.*]] = alloca i64 +// OGCG: store i32 %[[LEN_ARG]], ptr %[[LEN_ADDR]] +// OGCG: %[[LEN:.*]] = load i32, ptr %[[LEN_ADDR]] +// OGCG: %[[LEN_SIZE_T:.*]] = zext i32 %[[LEN]] to i64 +// OGCG: %[[STACK_PTR:.*]] = call ptr @llvm.stacksave.p0() +// OGCG: store ptr %[[STACK_PTR]], ptr %[[SAVED_STACK]] +// OGCG: %[[ARR:.*]] = alloca i32, i64 %[[LEN_SIZE_T]] +// OGCG: store i64 %[[LEN_SIZE_T]], ptr %[[VLA_EXPR0]] +// OGCG: %[[STACK_RESTORE_PTR:.*]] = load ptr, ptr %[[SAVED_STACK]] +// OGCG: call void @llvm.stackrestore.p0(ptr %[[STACK_RESTORE_PTR]]) + +void f1(int len) { + int arr[16][len]; +} + +// CIR: cir.func{{.*}} @f1(%[[LEN_ARG:.*]]: !s32i {{.*}}) +// CIR: %[[LEN_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["len", init] +// CIR: %[[SAVED_STACK:.*]] = cir.alloca !cir.ptr<!u8i>, !cir.ptr<!cir.ptr<!u8i>>, ["saved_stack"] +// CIR: cir.store{{.*}} %[[LEN_ARG]], %[[LEN_ADDR]] +// CIR: %[[SIXTEEN:.*]] = cir.const #cir.int<16> : !s32i +// CIR: %[[SIXTEEN_SIZE_T:.*]] = cir.cast integral %[[SIXTEEN]] : !s32i -> !u64i +// CIR: %[[LEN:.*]] = cir.load{{.*}} %[[LEN_ADDR]] +// CIR: %[[LEN_SIZE_T:.*]] = cir.cast integral %[[LEN]] : !s32i -> !u64i +// CIR: %[[STACK_PTR:.*]] = cir.stacksave +// CIR: cir.store{{.*}} %[[STACK_PTR]], %[[SAVED_STACK]] +// CIR: %[[TOTAL_LEN:.*]] = cir.binop(mul, %[[SIXTEEN_SIZE_T]], %[[LEN_SIZE_T]]) nuw +// CIR: %[[ARR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, %[[TOTAL_LEN]] : !u64i, ["arr"] +// CIR: %[[STACK_RESTORE_PTR:.*]] = cir.load{{.*}} %[[SAVED_STACK]] +// CIR: cir.stackrestore %[[STACK_RESTORE_PTR]] + +// LLVM: define{{.*}} void @f1(i32 %[[LEN_ARG:.*]]) { +// LLVM: %[[LEN_ADDR:.*]] = alloca i32 +// LLVM: %[[SAVED_STACK:.*]] = alloca ptr +// LLVM: store i32 %[[LEN_ARG]], ptr %[[LEN_ADDR]] +// LLVM: %[[LEN:.*]] = load i32, ptr %[[LEN_ADDR]] +// LLVM: %[[LEN_SIZE_T:.*]] = sext i32 %[[LEN]] to i64 +// LLVM: %[[STACK_PTR:.*]] = call ptr @llvm.stacksave.p0() +// LLVM: store ptr %[[STACK_PTR]], ptr %[[SAVED_STACK]] +// LLVM: %[[TOTAL_LEN:.*]] = mul nuw i64 16, %[[LEN_SIZE_T]] +// LLVM: %[[ARR:.*]] = alloca i32, i64 %[[TOTAL_LEN]] +// LLVM: %[[STACK_RESTORE_PTR:.*]] = load ptr, ptr %[[SAVED_STACK]] +// LLVM: call void @llvm.stackrestore.p0(ptr %[[STACK_RESTORE_PTR]]) + +// Note: VLA_EXPR0 below is emitted to capture debug info. + +// OGCG: define{{.*}} void @f1(i32 {{.*}} %[[LEN_ARG:.*]]) +// OGCG: %[[LEN_ADDR:.*]] = alloca i32 +// OGCG: %[[SAVED_STACK:.*]] = alloca ptr +// OGCG: %[[VLA_EXPR0:.*]] = alloca i64 +// OGCG: store i32 %[[LEN_ARG]], ptr %[[LEN_ADDR]] +// OGCG: %[[LEN:.*]] = load i32, ptr %[[LEN_ADDR]] +// OGCG: %[[LEN_SIZE_T:.*]] = zext i32 %[[LEN]] to i64 +// OGCG: %[[STACK_PTR:.*]] = call ptr @llvm.stacksave.p0() +// OGCG: store ptr %[[STACK_PTR]], ptr %[[SAVED_STACK]] +// OGCG: %[[TOTAL_LEN:.*]] = mul nuw i64 16, %[[LEN_SIZE_T]] +// OGCG: %[[ARR:.*]] = alloca i32, i64 %[[TOTAL_LEN]] +// OGCG: store i64 %[[LEN_SIZE_T]], ptr %[[VLA_EXPR0]] +// OGCG: %[[STACK_RESTORE_PTR:.*]] = load ptr, ptr %[[SAVED_STACK]] +// OGCG: call void @llvm.stackrestore.p0(ptr %[[STACK_RESTORE_PTR]]) + +void f2(int len) { + int arr[len + 4]; +} + +// CIR: cir.func{{.*}} @f2(%[[LEN_ARG:.*]]: !s32i {{.*}}) +// CIR: %[[LEN_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["len", init] +// CIR: %[[SAVED_STACK:.*]] = cir.alloca !cir.ptr<!u8i>, !cir.ptr<!cir.ptr<!u8i>>, ["saved_stack"] +// CIR: cir.store{{.*}} %[[LEN_ARG]], %[[LEN_ADDR]] +// CIR: %[[LEN:.*]] = cir.load{{.*}} %[[LEN_ADDR]] +// CIR: %[[FOUR:.*]] = cir.const #cir.int<4> : !s32i +// CIR: %[[TOTAL_LEN:.*]] = cir.binop(add, %[[LEN]], %[[FOUR]]) nsw : !s32i +// CIR: %[[TOTAL_LEN_SIZE_T:.*]] = cir.cast integral %[[TOTAL_LEN]] : !s32i -> !u64i +// CIR: %[[STACK_PTR:.*]] = cir.stacksave +// CIR: cir.store{{.*}} %[[STACK_PTR]], %[[SAVED_STACK]] +// CIR: %[[ARR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, %[[TOTAL_LEN_SIZE_T]] : !u64i, ["arr"] +// CIR: %[[STACK_RESTORE_PTR:.*]] = cir.load{{.*}} %[[SAVED_STACK]] +// CIR: cir.stackrestore %[[STACK_RESTORE_PTR]] + +// LLVM: define{{.*}} void @f2(i32 %[[LEN_ARG:.*]]) { +// LLVM: %[[LEN_ADDR:.*]] = alloca i32 +// LLVM: %[[SAVED_STACK:.*]] = alloca ptr +// LLVM: store i32 %[[LEN_ARG]], ptr %[[LEN_ADDR]] +// LLVM: %[[LEN:.*]] = load i32, ptr %[[LEN_ADDR]] +// LLVM: %[[TOTAL_LEN:.*]] = add nsw i32 %[[LEN]], 4 +// LLVM: %[[TOTAL_LEN_SIZE_T:.*]] = sext i32 %[[TOTAL_LEN]] to i64 +// LLVM: %[[STACK_PTR:.*]] = call ptr @llvm.stacksave.p0() +// LLVM: store ptr %[[STACK_PTR]], ptr %[[SAVED_STACK]] +// LLVM: %[[ARR:.*]] = alloca i32, i64 %[[TOTAL_LEN_SIZE_T]] +// LLVM: %[[STACK_RESTORE_PTR:.*]] = load ptr, ptr %[[SAVED_STACK]] +// LLVM: call void @llvm.stackrestore.p0(ptr %[[STACK_RESTORE_PTR]]) + +// Note: VLA_EXPR0 below is emitted to capture debug info. + +// OGCG: define{{.*}} void @f2(i32 {{.*}} %[[LEN_ARG:.*]]) +// OGCG: %[[LEN_ADDR:.*]] = alloca i32 +// OGCG: %[[SAVED_STACK:.*]] = alloca ptr +// OGCG: %[[VLA_EXPR0:.*]] = alloca i64 +// OGCG: store i32 %[[LEN_ARG]], ptr %[[LEN_ADDR]] +// OGCG: %[[LEN:.*]] = load i32, ptr %[[LEN_ADDR]] +// OGCG: %[[TOTAL_LEN:.*]] = add nsw i32 %[[LEN]], 4 +// OGCG: %[[TOTAL_LEN_SIZE_T:.*]] = zext i32 %[[TOTAL_LEN]] to i64 +// OGCG: %[[STACK_PTR:.*]] = call ptr @llvm.stacksave.p0() +// OGCG: store ptr %[[STACK_PTR]], ptr %[[SAVED_STACK]] +// OGCG: %[[ARR:.*]] = alloca i32, i64 %[[TOTAL_LEN_SIZE_T]] +// OGCG: store i64 %[[TOTAL_LEN_SIZE_T]], ptr %[[VLA_EXPR0]] +// OGCG: %[[STACK_RESTORE_PTR:.*]] = load ptr, ptr %[[SAVED_STACK]] +// OGCG: call void @llvm.stackrestore.p0(ptr %[[STACK_RESTORE_PTR]]) + +void f3(unsigned len) { + char s1[len]; + unsigned i = 0u; + while (++i < len) { + char s2[i]; + } +} + +// CIR: cir.func{{.*}} @f3(%[[LEN_ARG:.*]]: !u32i {{.*}}) +// CIR: %[[LEN_ADDR:.*]] = cir.alloca !u32i, !cir.ptr<!u32i>, ["len", init] +// CIR: %[[SAVED_STACK:.*]] = cir.alloca !cir.ptr<!u8i>, !cir.ptr<!cir.ptr<!u8i>>, ["saved_stack"] +// CIR: cir.store{{.*}} %[[LEN_ARG]], %[[LEN_ADDR]] +// CIR: %[[LEN:.*]] = cir.load{{.*}} %[[LEN_ADDR]] +// CIR: %[[LEN_SIZE_T:.*]] = cir.cast integral %[[LEN]] : !u32i -> !u64i +// CIR: %[[STACK_PTR:.*]] = cir.stacksave +// CIR: cir.store{{.*}} %[[STACK_PTR]], %[[SAVED_STACK]] +// CIR: %[[S1:.*]] = cir.alloca !s8i, !cir.ptr<!s8i>, %[[LEN_SIZE_T]] : !u64i, ["s1"] +// CIR: %[[I:.*]] = cir.alloca !u32i, !cir.ptr<!u32i>, ["i", init] +// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !u32i +// CIR: cir.store{{.*}} %[[ZERO]], %[[I]] +// CIR: cir.scope { +// CIR: cir.while { +// CIR: %[[CUR_I:.*]] = cir.load{{.*}} %[[I]] +// CIR: %[[NEXT:.*]] = cir.unary(inc, %[[CUR_I]]) +// CIR: cir.store{{.*}} %[[NEXT]], %[[I]] +// CIR: %[[LEN2:.*]] = cir.load{{.*}} %[[LEN_ADDR]] +// CIR: %[[CMP:.*]] = cir.cmp(lt, %[[NEXT]], %[[LEN2]]) +// CIR: cir.condition(%[[CMP]]) +// CIR: } do { +// CIR: cir.scope { +// CIR: %[[SAVED_STACK2:.*]] = cir.alloca !cir.ptr<!u8i>, !cir.ptr<!cir.ptr<!u8i>>, ["saved_stack"] +// CIR: %[[I_LEN:.*]] = cir.load{{.*}} %[[I]] +// CIR: %[[I_LEN_SIZE_T2:.*]] = cir.cast integral %[[I_LEN]] : !u32i -> !u64i +// CIR: %[[STACK_PTR2:.*]] = cir.stacksave +// CIR: cir.store{{.*}} %[[STACK_PTR2]], %[[SAVED_STACK2]] +// CIR: %[[S2:.*]] = cir.alloca !s8i, !cir.ptr<!s8i>, %[[I_LEN_SIZE_T2]] : !u64i, ["s2"] +// CIR: %[[SAVED_RESTORE_PTR2:.*]] = cir.load{{.*}} %[[SAVED_STACK2]] +// CIR: cir.stackrestore %[[SAVED_RESTORE_PTR2]] +// CIR: } +// CIR: cir.yield +// CIR: } +// CIR: } +// CIR: %[[STACK_RESTORE_PTR:.*]] = cir.load{{.*}} %[[SAVED_STACK]] +// CIR: cir.stackrestore %[[STACK_RESTORE_PTR]] + +// LLVM: define{{.*}} void @f3(i32 %[[LEN_ARG:.*]]) { +// LLVM: %[[SAVED_STACK2:.*]] = alloca ptr +// LLVM: %[[LEN_ADDR:.*]] = alloca i32 +// LLVM: %[[SAVED_STACK:.*]] = alloca ptr +// LLVM: store i32 %[[LEN_ARG]], ptr %[[LEN_ADDR]] +// LLVM: %[[LEN:.*]] = load i32, ptr %[[LEN_ADDR]] +// LLVM: %[[LEN_SIZE_T:.*]] = zext i32 %[[LEN]] to i64 +// LLVM: %[[STACK_PTR:.*]] = call ptr @llvm.stacksave.p0() +// LLVM: store ptr %[[STACK_PTR]], ptr %[[SAVED_STACK]] +// LLVM: %[[S1:.*]] = alloca i8, i64 %[[LEN_SIZE_T]] +// LLVM: %[[I:.*]] = alloca i32 +// LLVM: store i32 0, ptr %[[I]] +// LLVM: br label %[[WHILE_START:.*]] +// LLVM: [[WHILE_START]]: +// LLVM: br label %[[WHILE_COND:.*]] +// LLVM: [[WHILE_COND]]: +// LLVM: %[[CUR_I:.*]] = load i32, ptr %[[I]] +// LLVM: %[[NEXT:.*]] = add i32 %[[CUR_I]], 1 +// LLVM: store i32 %[[NEXT]], ptr %[[I]] +// LLVM: %[[LEN2:.*]] = load i32, ptr %[[LEN_ADDR]] +// LLVM: %[[CMP:.*]] = icmp ult i32 %[[NEXT]], %[[LEN2]] +// LLVM: br i1 %[[CMP]], label %[[WHILE_BODY:.*]], label %[[WHILE_END:.*]] +// LLVM: [[WHILE_BODY]]: +// LLVM: br label %[[WHILE_BODY2:.*]] +// LLVM: [[WHILE_BODY2]]: +// LLVM: %[[I_LEN:.*]] = load i32, ptr %[[I]] +// LLVM: %[[I_LEN_SIZE_T2:.*]] = zext i32 %[[I_LEN]] to i64 +// LLVM: %[[STACK_PTR2:.*]] = call ptr @llvm.stacksave.p0() +// LLVM: store ptr %[[STACK_PTR2]], ptr %[[SAVED_STACK2]] +// LLVM: %[[S2:.*]] = alloca i8, i64 %[[I_LEN_SIZE_T2]] +// LLVM: %[[STACK_RESTORE_PTR2:.*]] = load ptr, ptr %[[SAVED_STACK2]] +// LLVM: call void @llvm.stackrestore.p0(ptr %[[STACK_RESTORE_PTR2]]) +// LLVM: br label %[[WHILE_BODY_END:.*]] +// LLVM: [[WHILE_BODY_END]]: +// LLVM: br label %[[WHILE_COND]] +// LLVM: [[WHILE_END]]: +// LLVM: br label %[[F3_END:.*]] +// LLVM: [[F3_END]]: +// LLVM: %[[STACK_RESTORE_PTR:.*]] = load ptr, ptr %[[SAVED_STACK]] +// LLVM: call void @llvm.stackrestore.p0(ptr %[[STACK_RESTORE_PTR]]) + +// Note: VLA_EXPR0 and VLA_EXPR1 below are emitted to capture debug info. + +// OGCG: define{{.*}} void @f3(i32 {{.*}} %[[LEN_ARG:.*]]) +// OGCG: %[[LEN_ADDR:.*]] = alloca i32 +// OGCG: %[[SAVED_STACK:.*]] = alloca ptr +// OGCG: %[[VLA_EXPR0:.*]] = alloca i64 +// OGCG: %[[I:.*]] = alloca i32 +// OGCG: %[[SAVED_STACK1:.*]] = alloca ptr +// OGCG: %[[VLA_EXPR1:.*]] = alloca i64 +// OGCG: store i32 %[[LEN_ARG]], ptr %[[LEN_ADDR]] +// OGCG: %[[LEN:.*]] = load i32, ptr %[[LEN_ADDR]] +// OGCG: %[[LEN_SIZE_T:.*]] = zext i32 %[[LEN]] to i64 +// OGCG: %[[STACK_PTR:.*]] = call ptr @llvm.stacksave.p0() +// OGCG: store ptr %[[STACK_PTR]], ptr %[[SAVED_STACK]] +// OGCG: %[[S1:.*]] = alloca i8, i64 %[[LEN_SIZE_T]] +// OGCG: store i64 %[[LEN_SIZE_T]], ptr %[[VLA_EXPR0]] +// OGCG: br label %[[WHILE_COND:.*]] +// OGCG: [[WHILE_COND]]: +// OGCG: %[[CUR_I:.*]] = load i32, ptr %[[I]] +// OGCG: %[[NEXT:.*]] = add i32 %[[CUR_I]], 1 +// OGCG: store i32 %[[NEXT]], ptr %[[I]] +// OGCG: %[[LEN2:.*]] = load i32, ptr %[[LEN_ADDR]] +// OGCG: %[[CMP:.*]] = icmp ult i32 %[[NEXT]], %[[LEN2]] +// OGCG: br i1 %[[CMP]], label %[[WHILE_BODY:.*]], label %[[WHILE_END:.*]] +// OGCG: [[WHILE_BODY]]: +// OGCG: %[[I_LEN:.*]] = load i32, ptr %[[I]] +// OGCG: %[[I_LEN_SIZE_T:.*]] = zext i32 %[[I_LEN]] to i64 +// OGCG: %[[STACK_PTR1:.*]] = call ptr @llvm.stacksave.p0() +// OGCG: store ptr %[[STACK_PTR1]], ptr %[[SAVED_STACK1]] +// OGCG: %[[S2:.*]] = alloca i8, i64 %[[I_LEN_SIZE_T]] +// OGCG: store i64 %[[I_LEN_SIZE_T]], ptr %[[VLA_EXPR1]] +// OGCG: %[[STACK_RESTORE_PTR1:.*]] = load ptr, ptr %[[SAVED_STACK1]] +// OGCG: call void @llvm.stackrestore.p0(ptr %[[STACK_RESTORE_PTR1]]) +// OGCG: br label %[[WHILE_COND]] +// OGCG: [[WHILE_END]]: +// OGCG: %[[STACK_RESTORE_PTR:.*]] = load ptr, ptr %[[SAVED_STACK]] +// OGCG: call void @llvm.stackrestore.p0(ptr %[[STACK_RESTORE_PTR]]) + + +// The following test case is disabled because it runs into a bug (unrelated +// to VLA) in the handling of cleanups in loops with break statements. +// +// void f4(unsigned len) { +// char s1[len]; +// while (1) { +// char s2[len]; +// if (1) +// break; +// } +// } +
\ No newline at end of file |