aboutsummaryrefslogtreecommitdiff
path: root/clang/test/CIR/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/CIR/CodeGen')
-rw-r--r--clang/test/CIR/CodeGen/X86/cir-sqrt-builtins.c45
-rw-r--r--clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c14
-rw-r--r--clang/test/CIR/CodeGen/address-space-conversion.cpp92
-rw-r--r--clang/test/CIR/CodeGen/address-space.c6
-rw-r--r--clang/test/CIR/CodeGen/agg-expr-lvalue.c13
-rw-r--r--clang/test/CIR/CodeGen/array-ctor.cpp8
-rw-r--r--clang/test/CIR/CodeGen/array.cpp174
-rw-r--r--clang/test/CIR/CodeGen/asm-label-inline-builtins.c58
-rw-r--r--clang/test/CIR/CodeGen/assign-operator.cpp4
-rw-r--r--clang/test/CIR/CodeGen/atomic-thread-fence.c181
-rw-r--r--clang/test/CIR/CodeGen/atomic.c292
-rw-r--r--clang/test/CIR/CodeGen/base-to-derived.cpp97
-rw-r--r--clang/test/CIR/CodeGen/binassign.c104
-rw-r--r--clang/test/CIR/CodeGen/bitfield-union.c2
-rw-r--r--clang/test/CIR/CodeGen/bitfields.c6
-rw-r--r--clang/test/CIR/CodeGen/bitfields.cpp6
-rw-r--r--clang/test/CIR/CodeGen/bitfields_be.c4
-rw-r--r--clang/test/CIR/CodeGen/builtin_bit.cpp628
-rw-r--r--clang/test/CIR/CodeGen/builtin_call.cpp308
-rw-r--r--clang/test/CIR/CodeGen/builtin_inline.c91
-rw-r--r--clang/test/CIR/CodeGen/builtin_prefetch.c43
-rw-r--r--clang/test/CIR/CodeGen/builtin_printf.cpp65
-rw-r--r--clang/test/CIR/CodeGen/builtins-elementwise.c118
-rw-r--r--clang/test/CIR/CodeGen/builtins-floating-point.c20
-rw-r--r--clang/test/CIR/CodeGen/builtins.cpp42
-rw-r--r--clang/test/CIR/CodeGen/call.c2
-rw-r--r--clang/test/CIR/CodeGen/complex-compound-assignment.cpp16
-rw-r--r--clang/test/CIR/CodeGen/complex.cpp182
-rw-r--r--clang/test/CIR/CodeGen/compound_literal.cpp29
-rw-r--r--clang/test/CIR/CodeGen/constant-inits.cpp62
-rw-r--r--clang/test/CIR/CodeGen/copy-constructor.cpp52
-rw-r--r--clang/test/CIR/CodeGen/coro-task.cpp124
-rw-r--r--clang/test/CIR/CodeGen/count-of.c52
-rw-r--r--clang/test/CIR/CodeGen/ctor-null-init.cpp91
-rw-r--r--clang/test/CIR/CodeGen/cxx-conversion-operators.cpp10
-rw-r--r--clang/test/CIR/CodeGen/cxx-rewritten-binary-operator.cpp39
-rw-r--r--clang/test/CIR/CodeGen/cxx-special-member-attr.cpp66
-rw-r--r--clang/test/CIR/CodeGen/defaultarg.cpp54
-rw-r--r--clang/test/CIR/CodeGen/delete.cpp8
-rw-r--r--clang/test/CIR/CodeGen/derived-to-base.cpp129
-rw-r--r--clang/test/CIR/CodeGen/destructors.cpp6
-rw-r--r--clang/test/CIR/CodeGen/dtors.cpp2
-rw-r--r--clang/test/CIR/CodeGen/dynamic-cast.cpp12
-rw-r--r--clang/test/CIR/CodeGen/global-array-dtor.cpp113
-rw-r--r--clang/test/CIR/CodeGen/global-constant.c20
-rw-r--r--clang/test/CIR/CodeGen/global-ctor-dtor.cpp8
-rw-r--r--clang/test/CIR/CodeGen/global-init.cpp106
-rw-r--r--clang/test/CIR/CodeGen/globals.cpp6
-rw-r--r--clang/test/CIR/CodeGen/gnu-null.cpp28
-rw-r--r--clang/test/CIR/CodeGen/goto.cpp16
-rw-r--r--clang/test/CIR/CodeGen/inline-attributes.cpp12
-rw-r--r--clang/test/CIR/CodeGen/kr-func-promote.c42
-rw-r--r--clang/test/CIR/CodeGen/label-values.c204
-rw-r--r--clang/test/CIR/CodeGen/label.c14
-rw-r--r--clang/test/CIR/CodeGen/lambda-static-invoker.cpp6
-rw-r--r--clang/test/CIR/CodeGen/lambda.cpp63
-rw-r--r--clang/test/CIR/CodeGen/linkage-spec.cpp28
-rw-r--r--clang/test/CIR/CodeGen/loop.cpp28
-rw-r--r--clang/test/CIR/CodeGen/no-common.c103
-rw-r--r--clang/test/CIR/CodeGen/no-prototype.c16
-rw-r--r--clang/test/CIR/CodeGen/nrvo.cpp62
-rw-r--r--clang/test/CIR/CodeGen/object-size-flex-array.c317
-rw-r--r--clang/test/CIR/CodeGen/object-size.c877
-rw-r--r--clang/test/CIR/CodeGen/object-size.cpp108
-rw-r--r--clang/test/CIR/CodeGen/offset-of.cpp93
-rw-r--r--clang/test/CIR/CodeGen/paren-init-list.cpp13
-rw-r--r--clang/test/CIR/CodeGen/placement-new.cpp40
-rw-r--r--clang/test/CIR/CodeGen/pointer-to-data-member.cpp32
-rw-r--r--clang/test/CIR/CodeGen/ptrdiff.cpp2
-rw-r--r--clang/test/CIR/CodeGen/record-zero-init-padding.c16
-rw-r--r--clang/test/CIR/CodeGen/size-of-vla.cpp156
-rw-r--r--clang/test/CIR/CodeGen/statement-exprs.c34
-rw-r--r--clang/test/CIR/CodeGen/static-members.cpp94
-rw-r--r--clang/test/CIR/CodeGen/stmt-expr.cpp47
-rw-r--r--clang/test/CIR/CodeGen/struct-init.cpp60
-rw-r--r--clang/test/CIR/CodeGen/struct.cpp97
-rw-r--r--clang/test/CIR/CodeGen/switch.cpp87
-rw-r--r--clang/test/CIR/CodeGen/temporary-materialization.cpp86
-rw-r--r--clang/test/CIR/CodeGen/ternary-throw.cpp43
-rw-r--r--clang/test/CIR/CodeGen/tls.c29
-rw-r--r--clang/test/CIR/CodeGen/try-catch-tmp.cpp44
-rw-r--r--clang/test/CIR/CodeGen/var_arg.c26
-rw-r--r--clang/test/CIR/CodeGen/variable-decomposition.cpp15
-rw-r--r--clang/test/CIR/CodeGen/vbase.cpp2
-rw-r--r--clang/test/CIR/CodeGen/vector-ext-element.cpp341
-rw-r--r--clang/test/CIR/CodeGen/volatile.cpp20
-rw-r--r--clang/test/CIR/CodeGen/vtable-emission.cpp4
-rw-r--r--clang/test/CIR/CodeGen/vtt.cpp14
88 files changed, 5117 insertions, 1812 deletions
diff --git a/clang/test/CIR/CodeGen/X86/cir-sqrt-builtins.c b/clang/test/CIR/CodeGen/X86/cir-sqrt-builtins.c
new file mode 100644
index 0000000..d540e9c
--- /dev/null
+++ b/clang/test/CIR/CodeGen/X86/cir-sqrt-builtins.c
@@ -0,0 +1,45 @@
+// Test X86-specific sqrt builtins
+
+// 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 -target-feature +avx512f -target-feature +avx512fp16 -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
+
+typedef float __m512 __attribute__((__vector_size__(64), __aligned__(64)));
+typedef double __m512d __attribute__((__vector_size__(64), __aligned__(64)));
+typedef _Float16 __m512h __attribute__((__vector_size__(64), __aligned__(64)));
+
+// Test __builtin_ia32_sqrtph512
+__m512h test_sqrtph512(__m512h a) {
+ return __builtin_ia32_sqrtph512(a, 4);
+}
+// CIR-LABEL: cir.func {{.*}}@test_sqrtph512
+// CIR: cir.sqrt {{%.*}} : !cir.vector<32 x !cir.f16>
+// LLVM-LABEL: define {{.*}} @test_sqrtph512
+// LLVM: call <32 x half> @llvm.sqrt.v32f16
+// OGCG-LABEL: define {{.*}} @test_sqrtph512
+// OGCG: call <32 x half> @llvm.sqrt.v32f16
+
+// Test __builtin_ia32_sqrtps512
+__m512 test_sqrtps512(__m512 a) {
+ return __builtin_ia32_sqrtps512(a, 4);
+}
+// CIR-LABEL: cir.func {{.*}}@test_sqrtps512
+// CIR: cir.sqrt {{%.*}} : !cir.vector<16 x !cir.float>
+// LLVM-LABEL: define {{.*}} @test_sqrtps512
+// LLVM: call <16 x float> @llvm.sqrt.v16f32
+// OGCG-LABEL: define {{.*}} @test_sqrtps512
+// OGCG: call <16 x float> @llvm.sqrt.v16f32
+
+// Test __builtin_ia32_sqrtpd512
+__m512d test_sqrtpd512(__m512d a) {
+ return __builtin_ia32_sqrtpd512(a, 4);
+}
+// CIR-LABEL: cir.func {{.*}}@test_sqrtpd512
+// CIR: cir.sqrt {{%.*}} : !cir.vector<8 x !cir.double>
+// LLVM-LABEL: define {{.*}} @test_sqrtpd512
+// LLVM: call <8 x double> @llvm.sqrt.v8f64
+// OGCG-LABEL: define {{.*}} @test_sqrtpd512
+// OGCG: call <8 x double> @llvm.sqrt.v8f64 \ No newline at end of file
diff --git a/clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c b/clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c
index 19362cf..66891f9 100644
--- a/clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c
+++ b/clang/test/CIR/CodeGen/aapcs-volatile-bitfields.c
@@ -82,7 +82,7 @@ int check_load(st1 *s1) {
return s1->b;
}
-// CIR: cir.func dso_local @check_load
+// CIR: cir.func {{.*}} @check_load
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_st1>>, !cir.ptr<!rec_st1>
// CIR: [[MEMBER:%.*]] = cir.get_member [[LOAD]][0] {name = "b"} : !cir.ptr<!rec_st1> -> !cir.ptr<!u16i>
// CIR: [[BITFI:%.*]] = cir.get_bitfield align(4) (#bfi_b, [[MEMBER]] {is_volatile} : !cir.ptr<!u16i>) -> !u32i
@@ -114,7 +114,7 @@ int check_load_exception(st3 *s3) {
return s3->b;
}
-// CIR: cir.func dso_local @check_load_exception
+// CIR: cir.func {{.*}} @check_load_exception
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_st3>>, !cir.ptr<!rec_st3>
// CIR: [[MEMBER:%.*]] = cir.get_member [[LOAD]][2] {name = "b"} : !cir.ptr<!rec_st3> -> !cir.ptr<!u8i>
// CIR: [[BITFI:%.*]] = cir.get_bitfield align(4) (#bfi_b1, [[MEMBER]] {is_volatile} : !cir.ptr<!u8i>) -> !u32i
@@ -151,7 +151,7 @@ int clip_load_exception2(clip *c) {
return c->a;
}
-// CIR: cir.func dso_local @clip_load_exception2
+// CIR: cir.func {{.*}} @clip_load_exception2
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_clip>>, !cir.ptr<!rec_clip>
// CIR: [[MEMBER:%.*]] = cir.get_member [[LOAD]][0] {name = "a"} : !cir.ptr<!rec_clip> -> !cir.ptr<!cir.array<!u8i x 3>>
// CIR: [[BITFI:%.*]] = cir.get_bitfield align(4) (#bfi_a1, [[MEMBER]] {is_volatile} : !cir.ptr<!cir.array<!u8i x 3>>) -> !s32i
@@ -178,7 +178,7 @@ void check_store(st2 *s2) {
s2->a = 1;
}
-// CIR: cir.func dso_local @check_store
+// CIR: cir.func {{.*}} @check_store
// CIR: [[CONST:%.*]] = cir.const #cir.int<1> : !s32i
// CIR: [[CAST:%.*]] = cir.cast integral [[CONST]] : !s32i -> !s16i
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_st2>>, !cir.ptr<!rec_st2>
@@ -209,7 +209,7 @@ void check_store_exception(st3 *s3) {
s3->b = 2;
}
-// CIR: cir.func dso_local @check_store_exception
+// CIR: cir.func {{.*}} @check_store_exception
// CIR: [[CONST:%.*]] = cir.const #cir.int<2> : !s32i
// CIR: [[CAST:%.*]] = cir.cast integral [[CONST]] : !s32i -> !u32i
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_st3>>, !cir.ptr<!rec_st3>
@@ -239,7 +239,7 @@ void clip_store_exception2(clip *c) {
c->a = 3;
}
-// CIR: cir.func dso_local @clip_store_exception2
+// CIR: cir.func {{.*}} @clip_store_exception2
// CIR: [[CONST:%.*]] = cir.const #cir.int<3> : !s32i
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_clip>>, !cir.ptr<!rec_clip>
// CIR: [[MEMBER:%.*]] = cir.get_member [[LOAD]][0] {name = "a"} : !cir.ptr<!rec_clip> -> !cir.ptr<!cir.array<!u8i x 3>>
@@ -261,7 +261,7 @@ void check_store_second_member (st4 *s4) {
s4->b = 1;
}
-// CIR: cir.func dso_local @check_store_second_member
+// CIR: cir.func {{.*}} @check_store_second_member
// CIR: [[ONE:%.*]] = cir.const #cir.int<1> : !s32i
// CIR: [[CAST:%.*]] = cir.cast integral [[ONE]] : !s32i -> !u64i
// CIR: [[LOAD:%.*]] = cir.load align(8) {{.*}} : !cir.ptr<!cir.ptr<!rec_st4>>, !cir.ptr<!rec_st4>
diff --git a/clang/test/CIR/CodeGen/address-space-conversion.cpp b/clang/test/CIR/CodeGen/address-space-conversion.cpp
new file mode 100644
index 0000000..9ce1f5e
--- /dev/null
+++ b/clang/test/CIR/CodeGen/address-space-conversion.cpp
@@ -0,0 +1,92 @@
+// RUN: %clang_cc1 -std=c++17 -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++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+using pi1_t = int __attribute__((address_space(1))) *;
+using pi2_t = int __attribute__((address_space(2))) *;
+
+using ri1_t = int __attribute__((address_space(1))) &;
+using ri2_t = int __attribute__((address_space(2))) &;
+
+// CIR: cir.func {{.*}} @{{.*test_ptr.*}}
+// LLVM: define dso_local void @{{.*test_ptr.*}}
+// OGCG: define dso_local void @{{.*test_ptr.*}}
+void test_ptr() {
+ pi1_t ptr1;
+ pi2_t ptr2 = (pi2_t)ptr1;
+ // CIR: %[[#PTR1:]] = cir.load{{.*}} %{{[0-9]+}} : !cir.ptr<!cir.ptr<!s32i, target_address_space(1)>>, !cir.ptr<!s32i, target_address_space(1)>
+ // CIR-NEXT: %[[#CAST:]] = cir.cast address_space %[[#PTR1]] : !cir.ptr<!s32i, target_address_space(1)> -> !cir.ptr<!s32i, target_address_space(2)>
+ // CIR-NEXT: cir.store{{.*}} %[[#CAST]], %{{[0-9]+}} : !cir.ptr<!s32i, target_address_space(2)>, !cir.ptr<!cir.ptr<!s32i, target_address_space(2)>>
+
+ // LLVM: %[[#PTR1:]] = load ptr addrspace(1), ptr %{{.*}}
+ // LLVM-NEXT: %[[#CAST:]] = addrspacecast ptr addrspace(1) %[[#PTR1]] to ptr addrspace(2)
+ // LLVM-NEXT: store ptr addrspace(2) %[[#CAST]], ptr %{{.*}}
+
+ // OGCG: %{{.*}} = load ptr addrspace(1), ptr %{{.*}}
+ // OGCG-NEXT: %{{.*}} = addrspacecast ptr addrspace(1) %{{.*}} to ptr addrspace(2)
+ // OGCG-NEXT: store ptr addrspace(2) %{{.*}}, ptr %{{.*}}
+}
+
+// CIR: cir.func {{.*}} @{{.*test_ref.*}}
+// LLVM: define dso_local void @{{.*test_ref.*}}
+// OGCG: define dso_local void @{{.*test_ref.*}}
+void test_ref() {
+ pi1_t ptr;
+ ri1_t ref1 = *ptr;
+ ri2_t ref2 = (ri2_t)ref1;
+ // CIR: %[[#DEREF:]] = cir.load deref{{.*}} %{{[0-9]+}} : !cir.ptr<!cir.ptr<!s32i, target_address_space(1)>>, !cir.ptr<!s32i, target_address_space(1)>
+ // CIR-NEXT: cir.store{{.*}} %[[#DEREF]], %{{[0-9]+}} : !cir.ptr<!s32i, target_address_space(1)>, !cir.ptr<!cir.ptr<!s32i, target_address_space(1)>>
+ // CIR-NEXT: %[[#REF1:]] = cir.load %{{[0-9]+}} : !cir.ptr<!cir.ptr<!s32i, target_address_space(1)>>, !cir.ptr<!s32i, target_address_space(1)>
+ // CIR-NEXT: %[[#CAST:]] = cir.cast address_space %[[#REF1]] : !cir.ptr<!s32i, target_address_space(1)> -> !cir.ptr<!s32i, target_address_space(2)>
+ // CIR-NEXT: cir.store{{.*}} %[[#CAST]], %{{[0-9]+}} : !cir.ptr<!s32i, target_address_space(2)>, !cir.ptr<!cir.ptr<!s32i, target_address_space(2)>>
+
+ // LLVM: %[[#DEREF:]] = load ptr addrspace(1), ptr %{{.*}}
+ // LLVM-NEXT: store ptr addrspace(1) %[[#DEREF]], ptr %{{.*}}
+ // LLVM-NEXT: %[[#REF1:]] = load ptr addrspace(1), ptr %{{.*}}
+ // LLVM-NEXT: %[[#CAST:]] = addrspacecast ptr addrspace(1) %[[#REF1]] to ptr addrspace(2)
+ // LLVM-NEXT: store ptr addrspace(2) %[[#CAST]], ptr %{{.*}}
+
+ // OGCG: %{{.*}} = load ptr addrspace(1), ptr %{{.*}}
+ // OGCG-NEXT: store ptr addrspace(1) %{{.*}}, ptr %{{.*}}
+ // OGCG-NEXT: %{{.*}} = load ptr addrspace(1), ptr %{{.*}}
+ // OGCG-NEXT: %{{.*}} = addrspacecast ptr addrspace(1) %{{.*}} to ptr addrspace(2)
+ // OGCG-NEXT: store ptr addrspace(2) %{{.*}}, ptr %{{.*}}
+}
+
+// CIR: cir.func {{.*}} @{{.*test_nullptr.*}}
+// LLVM: define dso_local void @{{.*test_nullptr.*}}
+// OGCG: define dso_local void @{{.*test_nullptr.*}}
+void test_nullptr() {
+ constexpr pi1_t null1 = nullptr;
+ pi2_t ptr = (pi2_t)null1;
+ // CIR: %[[#NULL1:]] = cir.const #cir.ptr<null> : !cir.ptr<!s32i, target_address_space(1)>
+ // CIR-NEXT: cir.store{{.*}} %[[#NULL1]], %{{[0-9]+}} : !cir.ptr<!s32i, target_address_space(1)>, !cir.ptr<!cir.ptr<!s32i, target_address_space(1)>>
+ // CIR-NEXT: %[[#NULL2:]] = cir.const #cir.ptr<null> : !cir.ptr<!s32i, target_address_space(2)>
+ // CIR-NEXT: cir.store{{.*}} %[[#NULL2]], %{{[0-9]+}} : !cir.ptr<!s32i, target_address_space(2)>, !cir.ptr<!cir.ptr<!s32i, target_address_space(2)>>
+
+ // LLVM: store ptr addrspace(1) null, ptr %{{.*}}
+ // LLVM-NEXT: store ptr addrspace(2) null, ptr %{{.*}}
+
+ // OGCG: store ptr addrspace(1) null, ptr %{{.*}}
+ // OGCG-NEXT: store ptr addrspace(2) null, ptr %{{.*}}
+}
+
+// CIR: cir.func {{.*}} @{{.*test_side_effect.*}}
+// LLVM: define dso_local void @{{.*test_side_effect.*}}
+// OGCG: define dso_local void @{{.*test_side_effect.*}}
+void test_side_effect(pi1_t b) {
+ pi2_t p = (pi2_t)(*b++, (int*)0);
+ // CIR: %[[#DEREF:]] = cir.load deref{{.*}} %{{[0-9]+}} : !cir.ptr<!cir.ptr<!s32i, target_address_space(1)>>, !cir.ptr<!s32i, target_address_space(1)>
+ // CIR: %[[#STRIDE:]] = cir.ptr_stride %[[#DEREF]], %{{[0-9]+}} : (!cir.ptr<!s32i, target_address_space(1)>, !s32i) -> !cir.ptr<!s32i, target_address_space(1)>
+ // CIR: %[[#NULL:]] = cir.const #cir.ptr<null> : !cir.ptr<!s32i, target_address_space(2)>
+ // CIR-NEXT: cir.store{{.*}} %[[#NULL]], %{{[0-9]+}} : !cir.ptr<!s32i, target_address_space(2)>, !cir.ptr<!cir.ptr<!s32i, target_address_space(2)>>
+
+ // LLVM: %{{[0-9]+}} = getelementptr {{.*}}i32, ptr addrspace(1) %{{[0-9]+}}, i{{32|64}} 1
+ // LLVM: store ptr addrspace(2) null, ptr %{{.*}}
+
+ // OGCG: %{{.*}} = getelementptr{{.*}} i32, ptr addrspace(1) %{{.*}}, i32 1
+ // OGCG: store ptr addrspace(2) null, ptr %{{.*}}
+}
diff --git a/clang/test/CIR/CodeGen/address-space.c b/clang/test/CIR/CodeGen/address-space.c
index a334b8a..2a5c0e1 100644
--- a/clang/test/CIR/CodeGen/address-space.c
+++ b/clang/test/CIR/CodeGen/address-space.c
@@ -6,7 +6,7 @@
// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
// Test address space 1
-// CIR: cir.func dso_local @foo(%arg0: !cir.ptr<!s32i, target_address_space(1)>
+// CIR: cir.func {{.*}} @foo(%arg0: !cir.ptr<!s32i, target_address_space(1)>
// LLVM: define dso_local void @foo(ptr addrspace(1) %0)
// OGCG: define dso_local void @foo(ptr addrspace(1) noundef %arg)
void foo(int __attribute__((address_space(1))) *arg) {
@@ -14,7 +14,7 @@ void foo(int __attribute__((address_space(1))) *arg) {
}
// Test explicit address space 0 (should be same as default)
-// CIR: cir.func dso_local @bar(%arg0: !cir.ptr<!s32i, target_address_space(0)>
+// CIR: cir.func {{.*}} @bar(%arg0: !cir.ptr<!s32i, target_address_space(0)>
// LLVM: define dso_local void @bar(ptr %0)
// OGCG: define dso_local void @bar(ptr noundef %arg)
void bar(int __attribute__((address_space(0))) *arg) {
@@ -22,7 +22,7 @@ void bar(int __attribute__((address_space(0))) *arg) {
}
// Test default address space (no attribute)
-// CIR: cir.func dso_local @baz(%arg0: !cir.ptr<!s32i>
+// CIR: cir.func {{.*}} @baz(%arg0: !cir.ptr<!s32i>
// LLVM: define dso_local void @baz(ptr %0)
// OGCG: define dso_local void @baz(ptr noundef %arg)
void baz(int *arg) {
diff --git a/clang/test/CIR/CodeGen/agg-expr-lvalue.c b/clang/test/CIR/CodeGen/agg-expr-lvalue.c
index c826f8f..509f021 100644
--- a/clang/test/CIR/CodeGen/agg-expr-lvalue.c
+++ b/clang/test/CIR/CodeGen/agg-expr-lvalue.c
@@ -95,16 +95,13 @@ void test_string_array_in_array(void) {
}
// CIR-LABEL: cir.func{{.*}} @test_string_array_in_array
-// CIR: cir.alloca !cir.array<!cir.array<!s8i x 6> x 2>, {{.*}}, ["matrix", init]
-// CIR: cir.get_global
-// CIR: cir.copy
-// CIR: cir.get_global
-// CIR: cir.copy
+// CIR: %[[MATRIX:.*]] = cir.alloca !cir.array<!cir.array<!s8i x 6> x 2>, {{.*}}, ["matrix", init]
+// CIR: %[[CONST:.*]] = cir.const #cir.const_array<[#cir.const_array<[#cir.int<104> : !s8i, #cir.int<101> : !s8i, #cir.int<108> : !s8i, #cir.int<108> : !s8i, #cir.int<111> : !s8i, #cir.int<0> : !s8i]> : !cir.array<!s8i x 6>, #cir.const_array<[#cir.int<119> : !s8i, #cir.int<111> : !s8i, #cir.int<114> : !s8i, #cir.int<108> : !s8i, #cir.int<100> : !s8i, #cir.int<0> : !s8i]> : !cir.array<!s8i x 6>]>
+// CIR: cir.store{{.*}} %[[CONST]], %[[MATRIX]]
// LLVM-LABEL: define{{.*}} @test_string_array_in_array
-// LLVM: alloca [2 x [6 x i8]]
-// LLVM: call void @llvm.memcpy
-// LLVM: call void @llvm.memcpy
+// LLVM: %[[MATRIX:.*]] = alloca [2 x [6 x i8]]
+// LLVM: store [2 x [6 x i8]] {{\[}}[6 x i8] c"hello\00", [6 x i8] c"world\00"], ptr %[[MATRIX]]
// OGCG-LABEL: define{{.*}} @test_string_array_in_array
// OGCG: alloca [2 x [6 x i8]]
diff --git a/clang/test/CIR/CodeGen/array-ctor.cpp b/clang/test/CIR/CodeGen/array-ctor.cpp
index 1fb14ec..8643c8c 100644
--- a/clang/test/CIR/CodeGen/array-ctor.cpp
+++ b/clang/test/CIR/CodeGen/array-ctor.cpp
@@ -14,7 +14,7 @@ void foo() {
S s[42];
}
-// CIR-BEFORE-LPP: cir.func dso_local @_Z3foov()
+// CIR-BEFORE-LPP: cir.func {{.*}} @_Z3foov()
// CIR-BEFORE-LPP: %[[ARRAY:.*]] = cir.alloca !cir.array<!rec_S x 42>, !cir.ptr<!cir.array<!rec_S x 42>>, ["s", init]
// CIR-BEFORE-LPP: cir.array.ctor %[[ARRAY]] : !cir.ptr<!cir.array<!rec_S x 42>> {
// CIR-BEFORE-LPP: ^bb0(%[[ARG:.*]]: !cir.ptr<!rec_S>):
@@ -24,7 +24,7 @@ void foo() {
// CIR-BEFORE-LPP: cir.return
// CIR-BEFORE-LPP: }
-// CIR: cir.func dso_local @_Z3foov()
+// CIR: cir.func {{.*}} @_Z3foov()
// CIR: %[[ARRAY:.*]] = cir.alloca !cir.array<!rec_S x 42>, !cir.ptr<!cir.array<!rec_S x 42>>, ["s", init]
// CIR: %[[CONST42:.*]] = cir.const #cir.int<42> : !u64i
// CIR: %[[DECAY:.*]] = cir.cast array_to_ptrdecay %[[ARRAY]] : !cir.ptr<!cir.array<!rec_S x 42>> -> !cir.ptr<!rec_S>
@@ -84,12 +84,12 @@ void zero_sized() {
S s[0];
}
-// CIR-BEFORE-LPP: cir.func dso_local @_Z10zero_sizedv()
+// CIR-BEFORE-LPP: cir.func {{.*}} @_Z10zero_sizedv()
// CIR-BEFORE-LPP: cir.alloca !cir.array<!rec_S x 0>, !cir.ptr<!cir.array<!rec_S x 0>>, ["s"]
// CIR-BEFORE-LPP-NOT: cir.array.ctor
// CIR-BEFORE-LPP: cir.return
-// CIR: cir.func dso_local @_Z10zero_sizedv()
+// CIR: cir.func {{.*}} @_Z10zero_sizedv()
// CIR: cir.alloca !cir.array<!rec_S x 0>, !cir.ptr<!cir.array<!rec_S x 0>>, ["s"]
// CIR-NOT: cir.do
// CIR-NOT: cir.call @_ZN1SC1Ev
diff --git a/clang/test/CIR/CodeGen/array.cpp b/clang/test/CIR/CodeGen/array.cpp
index 82add4b..5e87381 100644
--- a/clang/test/CIR/CodeGen/array.cpp
+++ b/clang/test/CIR/CodeGen/array.cpp
@@ -151,50 +151,12 @@ void func2() {
}
// CIR: %[[ARR2:.*]] = cir.alloca !cir.array<!s32i x 2>, !cir.ptr<!cir.array<!s32i x 2>>, ["arr", init]
-// CIR: %[[ARR_PTR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["arrayinit.temp", init]
-// CIR: %[[ARR_0:.*]] = cir.cast array_to_ptrdecay %[[ARR2]] : !cir.ptr<!cir.array<!s32i x 2>> -> !cir.ptr<!s32i>
-// CIR: %[[FIVE:.*]] = cir.const #cir.int<5> : !s32i
-// CIR: cir.store{{.*}} %[[FIVE]], %[[ARR_0]] : !s32i, !cir.ptr<!s32i>
-// CIR: %[[OFFSET_0:.*]] = cir.const #cir.int<1> : !s64i
-// CIR: %[[ELE_PTR:.*]] = cir.ptr_stride %[[ARR_0]], %[[OFFSET_0]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i>
-// CIR: cir.store{{.*}} %[[ELE_PTR]], %[[ARR_PTR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
-// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s64i
-// CIR: %[[ARR_END:.*]] = cir.ptr_stride %[[ARR_0]], %[[TWO]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i>
-// CIR: cir.do {
-// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
-// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
-// CIR: cir.store{{.*}} %[[ZERO]], %[[ARR_CUR]] : !s32i, !cir.ptr<!s32i>
-// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i
-// CIR: %[[ARR_NEXT:.*]] = cir.ptr_stride %[[ARR_CUR]], %[[ONE]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i>
-// CIR: cir.store{{.*}} %[[ARR_NEXT]], %[[ARR_PTR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
-// CIR: cir.yield
-// CIR: } while {
-// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
-// CIR: %[[CMP:.*]] = cir.cmp(ne, %[[ARR_CUR]], %[[ARR_END]]) : !cir.ptr<!s32i>, !cir.bool
-// CIR: cir.condition(%[[CMP]])
-// CIR: }
+// CIR: %[[CONST:.*]] = cir.const #cir.const_array<[#cir.int<5> : !s32i, #cir.int<0> : !s32i]> : !cir.array<!s32i x 2>
+// CIR: cir.store{{.*}} %[[CONST]], %[[ARR2]] : !cir.array<!s32i x 2>, !cir.ptr<!cir.array<!s32i x 2>>
// LLVM: define{{.*}} void @_Z5func2v(){{.*}}
// LLVM: %[[ARR:.*]] = alloca [2 x i32], i64 1, align 4
-// LLVM: %[[TMP:.*]] = alloca ptr, i64 1, align 8
-// LLVM: %[[ARR_PTR:.*]] = getelementptr i32, ptr %[[ARR]], i32 0
-// LLVM: store i32 5, ptr %[[ARR_PTR]], align 4
-// LLVM: %[[ELE_1_PTR:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i64 1
-// LLVM: store ptr %[[ELE_1_PTR]], ptr %[[TMP]], align 8
-// LLVM: %[[END_PTR:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i64 2
-// LLVM: br label %[[LOOP_BODY:.*]]
-// LLVM: [[LOOP_NEXT:.*]]:
-// LLVM: %[[CUR:.*]] = load ptr, ptr %[[TMP]], align 8
-// LLVM: %[[CMP:.*]] = icmp ne ptr %[[CUR]], %[[END_PTR]]
-// LLVM: br i1 %[[CMP]], label %[[LOOP_BODY]], label %[[LOOP_END:.*]]
-// LLVM: [[LOOP_BODY]]:
-// LLVM: %[[CUR:.*]] = load ptr, ptr %[[TMP]], align 8
-// LLVM: store i32 0, ptr %[[CUR]], align 4
-// LLVM: %[[NEXT:.*]] = getelementptr i32, ptr %[[CUR]], i64 1
-// LLVM: store ptr %[[NEXT]], ptr %[[TMP]], align 8
-// LLVM: br label %[[LOOP_NEXT:.*]]
-// LLVM: [[LOOP_END]]:
-// LLVM: ret void
+// LLVM: store [2 x i32] [i32 5, i32 0], ptr %[[ARR]], align 4
// OGCG: %[[ARR:.*]] = alloca [2 x i32], align 4
// OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[ARR]], ptr align 4 @[[FUN2_ARR]], i64 8, i1 false)
@@ -209,13 +171,8 @@ void func3() {
// CIR: %[[ARR:.*]] = cir.alloca !cir.array<!s32i x 2>, !cir.ptr<!cir.array<!s32i x 2>>, ["arr", init]
// CIR: %[[IDX:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["idx", init]
// CIR: %[[INIT:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e", init]
-// CIR: %[[ARR_PTR:.*]] = cir.cast array_to_ptrdecay %[[ARR]] : !cir.ptr<!cir.array<!s32i x 2>> -> !cir.ptr<!s32i>
-// CIR: %[[V0:.*]] = cir.const #cir.int<5> : !s32i
-// CIR: cir.store{{.*}} %[[V0]], %[[ARR_PTR]] : !s32i, !cir.ptr<!s32i>
-// CIR: %[[OFFSET_0:.*]] = cir.const #cir.int<1> : !s64i
-// CIR: %[[ELE_1_PTR:.*]] = cir.ptr_stride %[[ARR_PTR]], %[[OFFSET_0]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i>
-// CIR: %[[V1:.*]] = cir.const #cir.int<6> : !s32i
-// CIR: cir.store{{.*}} %[[V1]], %[[ELE_1_PTR]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[CONST:.*]] = cir.const #cir.const_array<[#cir.int<5> : !s32i, #cir.int<6> : !s32i]> : !cir.array<!s32i x 2>
+// CIR: cir.store{{.*}} %[[CONST]], %[[ARR]] : !cir.array<!s32i x 2>, !cir.ptr<!cir.array<!s32i x 2>>
// CIR: %[[IDX_V:.*]] = cir.const #cir.int<1> : !s32i
// CIR: cir.store{{.*}} %[[IDX_V]], %[[IDX]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[TMP_IDX:.*]] = cir.load{{.*}} %[[IDX]] : !cir.ptr<!s32i>, !s32i
@@ -228,10 +185,7 @@ void func3() {
// LLVM: %[[ARR:.*]] = alloca [2 x i32], i64 1, align 4
// LLVM: %[[IDX:.*]] = alloca i32, i64 1, align 4
// LLVM: %[[INIT:.*]] = alloca i32, i64 1, align 4
-// LLVM: %[[ARR_PTR:.*]] = getelementptr i32, ptr %[[ARR]], i32 0
-// LLVM: store i32 5, ptr %[[ARR_PTR]], align 4
-// LLVM: %[[ELE_1_PTR:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i64 1
-// LLVM: store i32 6, ptr %[[ELE_1_PTR]], align 4
+// LLVM: store [2 x i32] [i32 5, i32 6], ptr %[[ARR]], align 4
// LLVM: store i32 1, ptr %[[IDX]], align 4
// LLVM: %[[TMP1:.*]] = load i32, ptr %[[IDX]], align 4
// LLVM: %[[ARR_PTR:.*]] = getelementptr i32, ptr %[[ARR]], i32 0
@@ -258,15 +212,8 @@ void func4() {
// CIR: %[[ARR:.*]] = cir.alloca !cir.array<!cir.array<!s32i x 1> x 2>, !cir.ptr<!cir.array<!cir.array<!s32i x 1> x 2>>, ["arr", init]
// CIR: %[[INIT:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e", init]
-// CIR: %[[ARR_PTR:.*]] = cir.cast array_to_ptrdecay %[[ARR]] : !cir.ptr<!cir.array<!cir.array<!s32i x 1> x 2>> -> !cir.ptr<!cir.array<!s32i x 1>>
-// CIR: %[[ARR_0_PTR:.*]] = cir.cast array_to_ptrdecay %[[ARR_PTR]] : !cir.ptr<!cir.array<!s32i x 1>> -> !cir.ptr<!s32i>
-// CIR: %[[V_0_0:.*]] = cir.const #cir.int<5> : !s32i
-// CIR: cir.store{{.*}} %[[V_0_0]], %[[ARR_0_PTR]] : !s32i, !cir.ptr<!s32i>
-// CIR: %[[OFFSET:.*]] = cir.const #cir.int<1> : !s64i
-// CIR: %[[ARR_1:.*]] = cir.ptr_stride %[[ARR_PTR]], %[[OFFSET]] : (!cir.ptr<!cir.array<!s32i x 1>>, !s64i) -> !cir.ptr<!cir.array<!s32i x 1>>
-// CIR: %[[ARR_1_PTR:.*]] = cir.cast array_to_ptrdecay %[[ARR_1]] : !cir.ptr<!cir.array<!s32i x 1>> -> !cir.ptr<!s32i>
-// CIR: %[[V_1_0:.*]] = cir.const #cir.int<6> : !s32i
-// CIR: cir.store{{.*}} %[[V_1_0]], %[[ARR_1_PTR]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[CONST:.*]] = cir.const #cir.const_array<[#cir.const_array<[#cir.int<5> : !s32i]> : !cir.array<!s32i x 1>, #cir.const_array<[#cir.int<6> : !s32i]> : !cir.array<!s32i x 1>]> : !cir.array<!cir.array<!s32i x 1> x 2>
+// CIR: cir.store{{.*}} %[[CONST]], %[[ARR]] : !cir.array<!cir.array<!s32i x 1> x 2>, !cir.ptr<!cir.array<!cir.array<!s32i x 1> x 2>>
// CIR: %[[IDX:.*]] = cir.const #cir.int<0> : !s32i
// CIR: %[[IDX_1:.*]] = cir.const #cir.int<1> : !s32i
// CIR: %[[ARR_PTR:.*]] = cir.cast array_to_ptrdecay %[[ARR]] : !cir.ptr<!cir.array<!cir.array<!s32i x 1> x 2>> -> !cir.ptr<!cir.array<!s32i x 1>>
@@ -279,12 +226,7 @@ void func4() {
// LLVM: define{{.*}} void @_Z5func4v(){{.*}}
// LLVM: %[[ARR:.*]] = alloca [2 x [1 x i32]], i64 1, align 4
// LLVM: %[[INIT:.*]] = alloca i32, i64 1, align 4
-// LLVM: %[[ARR_PTR:.*]] = getelementptr [1 x i32], ptr %[[ARR]], i32 0
-// LLVM: %[[ARR_0_0:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i32 0
-// LLVM: store i32 5, ptr %[[ARR_0_0]], align 4
-// LLVM: %[[ARR_1:.*]] = getelementptr [1 x i32], ptr %[[ARR_PTR]], i64 1
-// LLVM: %[[ARR_1_0:.*]] = getelementptr i32, ptr %[[ARR_1]], i32 0
-// LLVM: store i32 6, ptr %[[ARR_1_0]], align 4
+// LLVM: store [2 x [1 x i32]] {{\[}}[1 x i32] [i32 5], [1 x i32] [i32 6]], ptr %[[ARR]], align 4
// LLVM: %[[ARR_PTR:.*]] = getelementptr [1 x i32], ptr %[[ARR]], i32 0
// LLVM: %[[ARR_1:.*]] = getelementptr [1 x i32], ptr %[[ARR_PTR]], i64 1
// LLVM: %[[ARR_1_0:.*]] = getelementptr i32, ptr %[[ARR_1]], i32 0
@@ -305,52 +247,12 @@ void func5() {
}
// CIR: %[[ARR:.*]] = cir.alloca !cir.array<!cir.array<!s32i x 1> x 2>, !cir.ptr<!cir.array<!cir.array<!s32i x 1> x 2>>, ["arr", init]
-// CIR: %[[ARR_PTR:.*]] = cir.alloca !cir.ptr<!cir.array<!s32i x 1>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>>, ["arrayinit.temp", init]
-// CIR: %[[ARR_0:.*]] = cir.cast array_to_ptrdecay %0 : !cir.ptr<!cir.array<!cir.array<!s32i x 1> x 2>> -> !cir.ptr<!cir.array<!s32i x 1>>
-// CIR: %[[ARR_0_PTR:.*]] = cir.cast array_to_ptrdecay %[[ARR_0]] : !cir.ptr<!cir.array<!s32i x 1>> -> !cir.ptr<!s32i>
-// CIR: %[[V_0_0:.*]] = cir.const #cir.int<5> : !s32i
-// CIR: cir.store{{.*}} %[[V_0_0]], %[[ARR_0_PTR]] : !s32i, !cir.ptr<!s32i>
-// CIR: %[[OFFSET:.*]] = cir.const #cir.int<1> : !s64i
-// CIR: %[[ARR_1:.*]] = cir.ptr_stride %[[ARR_0]], %[[OFFSET]] : (!cir.ptr<!cir.array<!s32i x 1>>, !s64i) -> !cir.ptr<!cir.array<!s32i x 1>>
-// CIR: cir.store{{.*}} %[[ARR_1]], %[[ARR_PTR]] : !cir.ptr<!cir.array<!s32i x 1>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>>
-// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s64i
-// CIR: %[[ARR_END:.*]] = cir.ptr_stride %[[ARR_0]], %[[TWO]] : (!cir.ptr<!cir.array<!s32i x 1>>, !s64i) -> !cir.ptr<!cir.array<!s32i x 1>>
-// CIR: cir.do {
-// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>>, !cir.ptr<!cir.array<!s32i x 1>>
-// CIR: %[[ZERO:.*]] = cir.const #cir.zero : !cir.array<!s32i x 1>
-// CIR: cir.store{{.*}} %[[ZERO]], %[[ARR_CUR]] : !cir.array<!s32i x 1>, !cir.ptr<!cir.array<!s32i x 1>>
-// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i
-// CIR: %[[ARR_NEXT:.*]] = cir.ptr_stride %[[ARR_CUR]], %[[ONE]] : (!cir.ptr<!cir.array<!s32i x 1>>, !s64i) -> !cir.ptr<!cir.array<!s32i x 1>>
-// CIR: cir.store{{.*}} %[[ARR_NEXT]], %[[ARR_PTR]] : !cir.ptr<!cir.array<!s32i x 1>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>>
-// CIR: cir.yield
-// CIR: } while {
-// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!cir.array<!s32i x 1>>>, !cir.ptr<!cir.array<!s32i x 1>>
-// CIR: %[[CMP:.*]] = cir.cmp(ne, %[[ARR_CUR]], %[[ARR_END]]) : !cir.ptr<!cir.array<!s32i x 1>>, !cir.bool
-// CIR: cir.condition(%[[CMP]])
-// CIR: }
+// CIR: %[[CONST:.*]] = cir.const #cir.const_array<[#cir.const_array<[#cir.int<5> : !s32i]> : !cir.array<!s32i x 1>, #cir.zero : !cir.array<!s32i x 1>]> : !cir.array<!cir.array<!s32i x 1> x 2>
+// CIR: cir.store{{.*}} %[[CONST]], %[[ARR]] : !cir.array<!cir.array<!s32i x 1> x 2>, !cir.ptr<!cir.array<!cir.array<!s32i x 1> x 2>>
// LLVM: define{{.*}} void @_Z5func5v(){{.*}}
// LLVM: %[[ARR:.*]] = alloca [2 x [1 x i32]], i64 1, align 4
-// LLVM: %[[TMP:.*]] = alloca ptr, i64 1, align 8
-// LLVM: %[[ARR_PTR:.*]] = getelementptr [1 x i32], ptr %[[ARR]], i32 0
-// LLVM: %[[ARR_0:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i32 0
-// LLVM: store i32 5, ptr %[[ARR_0]], align 4
-// LLVM: %[[ARR_1:.*]] = getelementptr [1 x i32], ptr %[[ARR_PTR]], i64 1
-// LLVM: store ptr %[[ARR_1]], ptr %[[TMP]], align 8
-// LLVM: %[[END_PTR:.*]] = getelementptr [1 x i32], ptr %[[ARR_PTR]], i64 2
-// LLVM: br label %[[LOOP_BODY:.*]]
-// LLVM: [[LOOP_NEXT:.*]]:
-// LLVM: %[[CUR:.*]] = load ptr, ptr %[[TMP]], align 8
-// LLVM: %[[CMP:.*]] = icmp ne ptr %[[CUR]], %[[END_PTR]]
-// LLVM: br i1 %[[CMP]], label %[[LOOP_BODY]], label %[[LOOP_END:.*]]
-// LLVM: [[LOOP_BODY]]:
-// LLVM: %[[CUR:.*]] = load ptr, ptr %[[TMP]], align 8
-// LLVM: store [1 x i32] zeroinitializer, ptr %[[CUR]], align 4
-// LLVM: %[[NEXT:.*]] = getelementptr [1 x i32], ptr %[[CUR]], i64 1
-// LLVM: store ptr %[[NEXT]], ptr %[[TMP]], align 8
-// LLVM: br label %[[LOOP_NEXT:.*]]
-// LLVM: [[LOOP_END]]:
-// LLVM: ret void
+// LLVM: store [2 x [1 x i32]] {{\[}}[1 x i32] [i32 5], [1 x i32] zeroinitializer], ptr %[[ARR]], align 4
// ORGC: %[[ARR:.*]] = alloca [2 x [1 x i32]], align 4
// ORGC: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[ARR]], ptr align 4 @[[FUN5_ARR]], i64 8, i1 false)
@@ -395,44 +297,12 @@ void func7() {
}
// CIR: %[[ARR:.*]] = cir.alloca !cir.array<!cir.ptr<!s32i> x 1>, !cir.ptr<!cir.array<!cir.ptr<!s32i> x 1>>, ["arr", init]
-// CIR: %[[ARR_PTR:.*]] = cir.alloca !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, ["arrayinit.temp", init]
-// CIR: %[[ARR_0:.*]] = cir.cast array_to_ptrdecay %[[ARR]] : !cir.ptr<!cir.array<!cir.ptr<!s32i> x 1>> -> !cir.ptr<!cir.ptr<!s32i>>
-// CIR: cir.store{{.*}} %[[ARR_0]], %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>
-// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i
-// CIR: %[[ARR_END:.*]] = cir.ptr_stride %[[ARR_0]], %[[ONE]] : (!cir.ptr<!cir.ptr<!s32i>>, !s64i) -> !cir.ptr<!cir.ptr<!s32i>>
-// CIR: cir.do {
-// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, !cir.ptr<!cir.ptr<!s32i>>
-// CIR: %[[NULL_PTR:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!s32i>
-// CIR: cir.store{{.*}} %[[NULL_PTR]], %[[ARR_CUR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
-// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i
-// CIR: %[[ARR_NEXT:.*]] = cir.ptr_stride %[[ARR_CUR]], %[[ONE]] : (!cir.ptr<!cir.ptr<!s32i>>, !s64i) -> !cir.ptr<!cir.ptr<!s32i>>
-// CIR: cir.store{{.*}} %[[ARR_NEXT]], %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>
-// CIR: cir.yield
-// CIR: } while {
-// CIR: %[[ARR_CUR:.*]] = cir.load{{.*}} %[[ARR_PTR]] : !cir.ptr<!cir.ptr<!cir.ptr<!s32i>>>, !cir.ptr<!cir.ptr<!s32i>>
-// CIR: %[[CMP:.*]] = cir.cmp(ne, %[[ARR_CUR]], %[[ARR_END]]) : !cir.ptr<!cir.ptr<!s32i>>, !cir.bool
-// CIR: cir.condition(%[[CMP]])
-// CIR: }
+// CIR: %[[CONST:.*]] = cir.const #cir.zero : !cir.array<!cir.ptr<!s32i> x 1>
+// CIR: cir.store{{.*}} %[[CONST]], %[[ARR]] : !cir.array<!cir.ptr<!s32i> x 1>, !cir.ptr<!cir.array<!cir.ptr<!s32i> x 1>>
// LLVM: define{{.*}} void @_Z5func7v(){{.*}}
// LLVM: %[[ARR:.*]] = alloca [1 x ptr], i64 1, align 8
-// LLVM: %[[TMP:.*]] = alloca ptr, i64 1, align 8
-// LLVM: %[[ARR_PTR:.*]] = getelementptr ptr, ptr %[[ARR]], i32 0
-// LLVM: store ptr %[[ARR_PTR]], ptr %[[TMP]], align 8
-// LLVM: %[[END_PTR:.*]] = getelementptr ptr, ptr %[[ARR_PTR]], i64 1
-// LLVM: br label %[[LOOP_BODY:.*]]
-// LLVM: [[LOOP_NEXT:.*]]:
-// LLVM: %[[CUR:.*]] = load ptr, ptr %[[TMP]], align 8
-// LLVM: %[[CMP:.*]] = icmp ne ptr %[[CUR]], %[[END_PTR]]
-// LLVM: br i1 %[[CMP]], label %[[LOOP_BODY]], label %[[LOOP_END:.*]]
-// LLVM: [[LOOP_BODY]]:
-// LLVM: %[[CUR:.*]] = load ptr, ptr %[[TMP]], align 8
-// LLVM: store ptr null, ptr %[[CUR]], align 8
-// LLVM: %[[NEXT:.*]] = getelementptr ptr, ptr %[[CUR]], i64 1
-// LLVM: store ptr %[[NEXT]], ptr %[[TMP]], align 8
-// LLVM: br label %[[LOOP_NEXT:.*]]
-// LLVM: [[LOOP_END]]:
-// LLVM: ret void
+// LLVM: store [1 x ptr] zeroinitializer, ptr %[[ARR]], align 8
// OGCG: %[[ARR:.*]] = alloca [1 x ptr], align 8
// OGCG: call void @llvm.memset.p0.i64(ptr align 8 %[[ARR]], i8 0, i64 8, i1 false)
@@ -581,19 +451,11 @@ void array_with_complex_elements() {
}
// CIR: %[[ARR_ADDR:.*]] = cir.alloca !cir.array<!cir.complex<!cir.float> x 2>, !cir.ptr<!cir.array<!cir.complex<!cir.float> x 2>>, ["arr", init]
-// CIR: %[[ARR_0:.*]] = cir.cast array_to_ptrdecay %[[ARR_ADDR]] : !cir.ptr<!cir.array<!cir.complex<!cir.float> x 2>> -> !cir.ptr<!cir.complex<!cir.float>>
-// CIR: %[[CONST_COMPLEX_0:.*]] = 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{{.*}} %[[CONST_COMPLEX_0]], %[[ARR_0]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
-// CIR: %[[IDX_1:.*]] = cir.const #cir.int<1> : !s64i
-// CIR: %[[ARR_1:.*]] = cir.ptr_stride %1, %[[IDX_1]] : (!cir.ptr<!cir.complex<!cir.float>>, !s64i) -> !cir.ptr<!cir.complex<!cir.float>>
-// CIR: %[[CONST_COMPLEX_1:.*]] = cir.const #cir.const_complex<#cir.fp<3.300000e+00> : !cir.float, #cir.fp<4.400000e+00> : !cir.float> : !cir.complex<!cir.float>
-// CIR: cir.store{{.*}} %[[CONST_COMPLEX_1]], %[[ARR_1]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
+// CIR: %[[CONST:.*]] = cir.const #cir.const_array<[#cir.const_complex<#cir.fp<1.100000e+00> : !cir.float, #cir.fp<2.200000e+00> : !cir.float> : !cir.complex<!cir.float>, #cir.const_complex<#cir.fp<3.300000e+00> : !cir.float, #cir.fp<4.400000e+00> : !cir.float> : !cir.complex<!cir.float>]> : !cir.array<!cir.complex<!cir.float> x 2>
+// CIR: cir.store{{.*}} %[[CONST]], %[[ARR_ADDR]] : !cir.array<!cir.complex<!cir.float> x 2>, !cir.ptr<!cir.array<!cir.complex<!cir.float> x 2>>
// LLVM: %[[ARR_ADDR:.*]] = alloca [2 x { float, float }], i64 1, align 16
-// LLVM: %[[ARR_0:.*]] = getelementptr { float, float }, ptr %[[ARR_ADDR]], i32 0
-// LLVM: store { float, float } { float 0x3FF19999A0000000, float 0x40019999A0000000 }, ptr %[[ARR_0]], align 8
-// LLVM: %[[ARR_1:.*]] = getelementptr { float, float }, ptr %[[ARR_0]], i64 1
-// LLVM: store { float, float } { float 0x400A666660000000, float 0x40119999A0000000 }, ptr %[[ARR_1]], align 8
+// LLVM: store [2 x { float, float }] [{ float, float } { float 0x3FF19999A0000000, float 0x40019999A0000000 }, { float, float } { float 0x400A666660000000, float 0x40119999A0000000 }], ptr %[[ARR_ADDR]], align 16
// OGCG: %[[ARR_ADDR:.*]] = alloca [2 x { float, float }], align 16
// OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 16 %[[ARR_ADDR]], ptr align 16 @__const._Z27array_with_complex_elementsv.arr, i64 16, i1 false)
diff --git a/clang/test/CIR/CodeGen/asm-label-inline-builtins.c b/clang/test/CIR/CodeGen/asm-label-inline-builtins.c
new file mode 100644
index 0000000..bad521a
--- /dev/null
+++ b/clang/test/CIR/CodeGen/asm-label-inline-builtins.c
@@ -0,0 +1,58 @@
+// RUN: %clang_cc1 -triple x86_64 -fclangir -emit-cir -disable-llvm-passes -o %t-cir.cir %s
+// RUN: FileCheck --input-file=%t-cir.cir %s --check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64 -fclangir -emit-llvm -disable-llvm-passes -o %t-cir.ll %s
+// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64 -emit-llvm -disable-llvm-passes -o %t.ll %s
+// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG
+
+
+// Verifies that clang-generated *.inline carry the same name at call and callee
+// site, in spite of asm labels.
+
+typedef struct _IO_FILE FILE;
+extern FILE *stdout;
+extern int vprintf (const char *__restrict __format, __builtin_va_list __arg);
+extern int __vfprintf_chk (FILE *__restrict __stream, int __flag,
+ const char *__restrict __format, __builtin_va_list __ap);
+extern int __vprintf_chk (int __flag, const char *__restrict __format,
+ __builtin_va_list __ap);
+
+extern __typeof (vprintf) vprintf __asm ("__vprintfieee128");
+extern __typeof (__vfprintf_chk) __vfprintf_chk __asm ("__vfprintf_chkieee128");
+extern __typeof (__vprintf_chk) __vprintf_chk __asm ("__vprintf_chkieee128");
+
+extern __inline __attribute__ ((__always_inline__)) __attribute__ ((__gnu_inline__)) __attribute__ ((__artificial__)) int
+vprintf (const char *__restrict __fmt, __builtin_va_list __ap)
+{
+ return __vfprintf_chk (stdout, 2 - 1, __fmt, __ap);
+}
+
+void test(const char *fmt, __builtin_va_list ap) {
+ vprintf(fmt, ap);
+}
+
+// CIR: cir.func always_inline internal private @__vprintfieee128.inline({{.*}}) -> !s32i
+// CIR: cir.call @__vfprintf_chkieee128(%{{.*}}, %{{.*}}, %{{.*}}, %{{.*}})
+//
+// CIR: cir.func {{.*}} @test({{.*}})
+// CIR: cir.call @__vprintfieee128.inline(%{{.*}}, %{{.*}})
+
+
+// LLVM: define internal i32 @__vprintfieee128.inline({{.*}}) #[[ALWAYS_INLINE_ATTR:.*]] {
+// LLVM: call i32 @__vfprintf_chkieee128(ptr %{{.*}}, i32 1, ptr %{{.*}}, ptr %{{.*}})
+//
+// LLVM: define {{.*}} void @test{{.*}}
+// LLVM: call i32 @__vprintfieee128.inline(ptr %{{.*}}, ptr %{{.*}})
+//
+// LLVM: attributes #[[ALWAYS_INLINE_ATTR]] = { alwaysinline }
+
+// Note: OGCG emits these in the opposite order, but the content is the same.
+
+
+// OGCG: define {{.*}} void @test{{.*}}
+// OGCG: call i32 @__vprintfieee128.inline(ptr noundef %{{.*}}, ptr noundef %{{.*}})
+//
+// OGCG: define internal i32 @__vprintfieee128.inline({{.*}}) #[[ALWAYS_INLINE_ATTR:.*]] {
+// OGCG: call i32 @__vfprintf_chkieee128(ptr noundef %{{.*}}, i32 noundef 1, ptr noundef %{{.*}}, ptr noundef %{{.*}})
+//
+// OGCG: attributes #[[ALWAYS_INLINE_ATTR]] = { alwaysinline {{.*}} }
diff --git a/clang/test/CIR/CodeGen/assign-operator.cpp b/clang/test/CIR/CodeGen/assign-operator.cpp
index 66d4b48..ad3e5c0 100644
--- a/clang/test/CIR/CodeGen/assign-operator.cpp
+++ b/clang/test/CIR/CodeGen/assign-operator.cpp
@@ -13,7 +13,7 @@ void a() {
a = 1u;
}
-// CIR: cir.func private @_ZN1xaSEi(!cir.ptr<!rec_x>, !s32i)
+// CIR: cir.func {{.*}} @_ZN1xaSEi(!cir.ptr<!rec_x>, !s32i)
// CIR: cir.func{{.*}} @_Z1av()
// CIR: %[[A_ADDR:.*]] = cir.alloca !rec_x, !cir.ptr<!rec_x>, ["a"]
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !u32i
@@ -63,7 +63,7 @@ void copy_c(C &c1, C &c2) {
// Implicit assignment operator for C.
-// CIR: cir.func comdat linkonce_odr @_ZN1CaSERKS_(%arg0: !cir.ptr<!rec_C> {{.*}}, %arg1: !cir.ptr<!rec_C> {{.*}}) -> !cir.ptr<!rec_C>
+// CIR: cir.func {{.*}} @_ZN1CaSERKS_(%arg0: !cir.ptr<!rec_C> {{.*}}, %arg1: !cir.ptr<!rec_C> {{.*}}) -> !cir.ptr<!rec_C>
// CIR: %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<!rec_C>, !cir.ptr<!cir.ptr<!rec_C>>, ["this", init]
// CIR: %[[ARG1_ADDR:.*]] = cir.alloca !cir.ptr<!rec_C>, !cir.ptr<!cir.ptr<!rec_C>>, ["", init, const]
// CIR: %[[RET_ADDR:.*]] = cir.alloca !cir.ptr<!rec_C>, !cir.ptr<!cir.ptr<!rec_C>>, ["__retval"]
diff --git a/clang/test/CIR/CodeGen/atomic-thread-fence.c b/clang/test/CIR/CodeGen/atomic-thread-fence.c
new file mode 100644
index 0000000..f28bc68
--- /dev/null
+++ b/clang/test/CIR/CodeGen/atomic-thread-fence.c
@@ -0,0 +1,181 @@
+// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -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.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
+
+struct Data {
+ int value;
+ void *ptr;
+};
+
+typedef struct Data *DataPtr;
+
+void applyThreadFence() {
+ __atomic_thread_fence(__ATOMIC_SEQ_CST);
+ // CIR-LABEL: @applyThreadFence
+ // CIR: cir.atomic.fence syncscope(system) seq_cst
+ // CIR: cir.return
+
+ // LLVM-LABEL: @applyThreadFence
+ // LLVM: fence seq_cst
+ // LLVM: ret void
+
+ // OGCG-LABEL: @applyThreadFence
+ // OGCG: fence seq_cst
+ // OGCG: ret void
+}
+
+void applySignalFence() {
+ __atomic_signal_fence(__ATOMIC_SEQ_CST);
+ // CIR-LABEL: @applySignalFence
+ // CIR: cir.atomic.fence syncscope(single_thread) seq_cst
+ // CIR: cir.return
+
+ // LLVM-LABEL: @applySignalFence
+ // LLVM: fence syncscope("singlethread") seq_cst
+ // LLVM: ret void
+
+ // OGCG-LABEL: @applySignalFence
+ // OGCG: fence syncscope("singlethread") seq_cst
+ // OGCG: ret void
+}
+
+void modifyWithThreadFence(DataPtr d) {
+ __atomic_thread_fence(__ATOMIC_SEQ_CST);
+ d->value = 42;
+ // CIR-LABEL: @modifyWithThreadFence
+ // CIR: %[[DATA:.*]] = cir.alloca !cir.ptr<!rec_Data>, !cir.ptr<!cir.ptr<!rec_Data>>, ["d", init] {alignment = 8 : i64}
+ // CIR: cir.atomic.fence syncscope(system) seq_cst
+ // CIR: %[[VAL_42:.*]] = cir.const #cir.int<42> : !s32i
+ // CIR: %[[LOAD_DATA:.*]] = cir.load{{.*}} %[[DATA]] : !cir.ptr<!cir.ptr<!rec_Data>>, !cir.ptr<!rec_Data>
+ // CIR: %[[DATA_VALUE:.*]] = cir.get_member %[[LOAD_DATA]][0] {name = "value"} : !cir.ptr<!rec_Data> -> !cir.ptr<!s32i>
+ // CIR: cir.store{{.*}} %[[VAL_42]], %[[DATA_VALUE]] : !s32i, !cir.ptr<!s32i>
+ // CIR: cir.return
+
+ // LLVM-LABEL: @modifyWithThreadFence
+ // LLVM: %[[DATA:.*]] = alloca ptr, i64 1, align 8
+ // LLVM: fence seq_cst
+ // LLVM: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8
+ // LLVM: %[[DATA_VALUE:.*]] = getelementptr %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 0
+ // LLVM: store i32 42, ptr %[[DATA_VALUE]], align 8
+ // LLVM: ret void
+
+ // OGCG-LABEL: @modifyWithThreadFence
+ // OGCG: %[[DATA:.*]] = alloca ptr, align 8
+ // OGCG: fence seq_cst
+ // OGCG: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8
+ // OGCG: %[[DATA_VALUE:.*]] = getelementptr inbounds nuw %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 0
+ // OGCG: store i32 42, ptr %[[DATA_VALUE]], align 8
+ // OGCG: ret void
+}
+
+void modifyWithSignalFence(DataPtr d) {
+ __atomic_signal_fence(__ATOMIC_SEQ_CST);
+ d->value = 24;
+ // CIR-LABEL: @modifyWithSignalFence
+ // CIR: %[[DATA:.*]] = cir.alloca !cir.ptr<!rec_Data>, !cir.ptr<!cir.ptr<!rec_Data>>, ["d", init] {alignment = 8 : i64}
+ // CIR: cir.atomic.fence syncscope(single_thread) seq_cst
+ // CIR: %[[VAL_42:.*]] = cir.const #cir.int<24> : !s32i
+ // CIR: %[[LOAD_DATA:.*]] = cir.load{{.*}} %[[DATA]] : !cir.ptr<!cir.ptr<!rec_Data>>, !cir.ptr<!rec_Data>
+ // CIR: %[[DATA_VALUE:.*]] = cir.get_member %[[LOAD_DATA]][0] {name = "value"} : !cir.ptr<!rec_Data> -> !cir.ptr<!s32i>
+ // CIR: cir.store{{.*}} %[[VAL_42]], %[[DATA_VALUE]] : !s32i, !cir.ptr<!s32i>
+ // CIR: cir.return
+
+ // LLVM-LABEL: @modifyWithSignalFence
+ // LLVM: %[[DATA:.*]] = alloca ptr, i64 1, align 8
+ // LLVM: fence syncscope("singlethread") seq_cst
+ // LLVM: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8
+ // LLVM: %[[DATA_VALUE:.*]] = getelementptr %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 0
+ // LLVM: store i32 24, ptr %[[DATA_VALUE]], align 8
+ // LLVM: ret void
+
+ // OGCG-LABEL: @modifyWithSignalFence
+ // OGCG: %[[DATA:.*]] = alloca ptr, align 8
+ // OGCG: fence syncscope("singlethread") seq_cst
+ // OGCG: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8
+ // OGCG: %[[DATA_VALUE:.*]] = getelementptr inbounds nuw %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 0
+ // OGCG: store i32 24, ptr %[[DATA_VALUE]], align 8
+ // OGCG: ret void
+}
+
+void loadWithThreadFence(DataPtr d) {
+ __atomic_thread_fence(__ATOMIC_SEQ_CST);
+ __atomic_load_n(&d->ptr, __ATOMIC_SEQ_CST);
+ // CIR-LABEL: @loadWithThreadFence
+ // CIR: %[[DATA:.*]] = cir.alloca !cir.ptr<!rec_Data>, !cir.ptr<!cir.ptr<!rec_Data>>, ["d", init] {alignment = 8 : i64}
+ // CIR: %[[ATOMIC_TEMP:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["atomic-temp"] {alignment = 8 : i64}
+ // CIR: cir.atomic.fence syncscope(system) seq_cst
+ // CIR: %[[LOAD_DATA:.*]] = cir.load{{.*}} %[[DATA]] : !cir.ptr<!cir.ptr<!rec_Data>>, !cir.ptr<!rec_Data>
+ // CIR: %[[DATA_VALUE:.*]] = cir.get_member %[[LOAD_DATA]][1] {name = "ptr"} : !cir.ptr<!rec_Data> -> !cir.ptr<!cir.ptr<!void>>
+ // CIR: %[[CASTED_DATA_VALUE:.*]] = cir.cast bitcast %[[DATA_VALUE]] : !cir.ptr<!cir.ptr<!void>> -> !cir.ptr<!u64i>
+ // CIR: %[[CASTED_ATOMIC_TEMP:.*]] = cir.cast bitcast %[[ATOMIC_TEMP]] : !cir.ptr<!cir.ptr<!void>> -> !cir.ptr<!u64i>
+ // CIR: %[[ATOMIC_LOAD:.*]] = cir.load{{.*}} atomic(seq_cst) %[[CASTED_DATA_VALUE]] : !cir.ptr<!u64i>, !u64i
+ // CIR: cir.store{{.*}} %[[ATOMIC_LOAD]], %[[CASTED_ATOMIC_TEMP]] : !u64i, !cir.ptr<!u64i>
+ // CIR: %[[DOUBLE_CASTED_ATOMIC_TEMP:.*]] = cir.cast bitcast %[[CASTED_ATOMIC_TEMP]] : !cir.ptr<!u64i> -> !cir.ptr<!cir.ptr<!void>>
+ // CIR: %[[ATOMIC_LOAD_PTR:.*]] = cir.load{{.*}} %[[DOUBLE_CASTED_ATOMIC_TEMP]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+ // CIR: cir.return
+
+ // LLVM-LABEL: @loadWithThreadFence
+ // LLVM: %[[DATA:.*]] = alloca ptr, i64 1, align 8
+ // LLVM: %[[DATA_TEMP:.*]] = alloca ptr, i64 1, align 8
+ // LLVM: fence seq_cst
+ // LLVM: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8
+ // LLVM: %[[DATA_VALUE:.*]] = getelementptr %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 1
+ // LLVM: %[[ATOMIC_LOAD:.*]] = load atomic i64, ptr %[[DATA_VALUE]] seq_cst, align 8
+ // LLVM: store i64 %[[ATOMIC_LOAD]], ptr %[[DATA_TEMP]], align 8
+ // LLVM: %[[DATA_TEMP_LOAD:.*]] = load ptr, ptr %[[DATA_TEMP]], align 8
+ // LLVM: ret void
+
+ // OGCG-LABEL: @loadWithThreadFence
+ // OGCG: %[[DATA:.*]] = alloca ptr, align 8
+ // OGCG: %[[DATA_TEMP:.*]] = alloca ptr, align 8
+ // OGCG: fence seq_cst
+ // OGCG: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8
+ // OGCG: %[[DATA_VALUE:.*]] = getelementptr inbounds nuw %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 1
+ // OGCG: %[[ATOMIC_LOAD:.*]] = load atomic i64, ptr %[[DATA_VALUE]] seq_cst, align 8
+ // OGCG: store i64 %[[ATOMIC_LOAD]], ptr %[[DATA_TEMP]], align 8
+ // OGCG: %[[DATA_TEMP_LOAD:.*]] = load ptr, ptr %[[DATA_TEMP]], align 8
+ // OGCG: ret void
+}
+
+void loadWithSignalFence(DataPtr d) {
+ __atomic_signal_fence(__ATOMIC_SEQ_CST);
+ __atomic_load_n(&d->ptr, __ATOMIC_SEQ_CST);
+ // CIR-LABEL: @loadWithSignalFence
+ // CIR: %[[DATA:.*]] = cir.alloca !cir.ptr<!rec_Data>, !cir.ptr<!cir.ptr<!rec_Data>>, ["d", init] {alignment = 8 : i64}
+ // CIR: %[[ATOMIC_TEMP:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["atomic-temp"] {alignment = 8 : i64}
+ // CIR: cir.atomic.fence syncscope(single_thread) seq_cst
+ // CIR: %[[LOAD_DATA:.*]] = cir.load{{.*}} %[[DATA]] : !cir.ptr<!cir.ptr<!rec_Data>>, !cir.ptr<!rec_Data>
+ // CIR: %[[DATA_PTR:.*]] = cir.get_member %[[LOAD_DATA]][1] {name = "ptr"} : !cir.ptr<!rec_Data> -> !cir.ptr<!cir.ptr<!void>>
+ // CIR: %[[CASTED_DATA_PTR:.*]] = cir.cast bitcast %[[DATA_PTR]] : !cir.ptr<!cir.ptr<!void>> -> !cir.ptr<!u64i>
+ // CIR: %[[CASTED_ATOMIC_TEMP:.*]] = cir.cast bitcast %[[ATOMIC_TEMP]] : !cir.ptr<!cir.ptr<!void>> -> !cir.ptr<!u64i>
+ // CIR: %[[ATOMIC_LOAD:.*]] = cir.load{{.*}} atomic(seq_cst) %[[CASTED_DATA_PTR]] : !cir.ptr<!u64i>, !u64i
+ // CIR: cir.store{{.*}} %[[ATOMIC_LOAD]], %[[CASTED_ATOMIC_TEMP]] : !u64i, !cir.ptr<!u64i>
+ // CIR: %[[DOUBLE_CASTED_ATOMIC_TEMP:.*]] = cir.cast bitcast %[[CASTED_ATOMIC_TEMP]] : !cir.ptr<!u64i> -> !cir.ptr<!cir.ptr<!void>>
+ // CIR: %[[LOAD_ATOMIC_TEMP:.*]] = cir.load{{.*}} %[[DOUBLE_CASTED_ATOMIC_TEMP]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+ // CIR: cir.return
+
+ // LLVM-LABEL: @loadWithSignalFence
+ // LLVM: %[[DATA:.*]] = alloca ptr, i64 1, align 8
+ // LLVM: %[[DATA_TEMP:.*]] = alloca ptr, i64 1, align 8
+ // LLVM: fence syncscope("singlethread") seq_cst
+ // LLVM: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8
+ // LLVM: %[[DATA_VALUE:.*]] = getelementptr %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 1
+ // LLVM: %[[ATOMIC_LOAD:.*]] = load atomic i64, ptr %[[DATA_VALUE]] seq_cst, align 8
+ // LLVM: store i64 %[[ATOMIC_LOAD]], ptr %[[DATA_TEMP]], align 8
+ // LLVM: %[[DATA_TEMP_LOAD]] = load ptr, ptr %[[DATA_TEMP]], align 8
+ // LLVM: ret void
+
+ // OGCG-LABEL: @loadWithSignalFence
+ // OGCG: %[[DATA:.*]] = alloca ptr, align 8
+ // OGCG: %[[DATA_TEMP:.*]] = alloca ptr, align 8
+ // OGCG: fence syncscope("singlethread") seq_cst
+ // OGCG: %[[DATA_PTR:.*]] = load ptr, ptr %[[DATA]], align 8
+ // OGCG: %[[DATA_VALUE:.*]] = getelementptr inbounds nuw %struct.Data, ptr %[[DATA_PTR]], i32 0, i32 1
+ // OGCG: %[[ATOMIC_LOAD:.*]] = load atomic i64, ptr %[[DATA_VALUE]] seq_cst, align 8
+ // OGCG: store i64 %[[ATOMIC_LOAD]], ptr %[[DATA_TEMP]], align 8
+ // OGCG: %[[DATA_TEMP_LOAD]] = load ptr, ptr %[[DATA_TEMP]], align 8
+ // OGCG: ret void
+}
diff --git a/clang/test/CIR/CodeGen/atomic.c b/clang/test/CIR/CodeGen/atomic.c
index 6579988..71cb1f1 100644
--- a/clang/test/CIR/CodeGen/atomic.c
+++ b/clang/test/CIR/CodeGen/atomic.c
@@ -46,6 +46,32 @@ void f2(void) {
// OGCG-NEXT: store i32 42, ptr %[[SLOT]], align 4
// OGCG: }
+void f3(_Atomic(int) *p) {
+ *p = 42;
+}
+
+// CIR-LABEL: @f3
+// CIR: cir.store align(4) atomic(seq_cst) %{{.+}}, %{{.+}} : !s32i, !cir.ptr<!s32i>
+
+// LLVM-LABEL: @f3
+// LLVM: store atomic i32 42, ptr %{{.+}} seq_cst, align 4
+
+// OGCG-LABEL: @f3
+// OGCG: store atomic i32 42, ptr %{{.+}} seq_cst, align 4
+
+void f4(_Atomic(float) *p) {
+ *p = 3.14;
+}
+
+// CIR-LABEL: @f4
+// CIR: cir.store align(4) atomic(seq_cst) %{{.+}}, %{{.+}} : !cir.float, !cir.ptr<!cir.float>
+
+// LLVM-LABEL: @f4
+// LLVM: store atomic float 0x40091EB860000000, ptr %{{.+}} seq_cst, align 4
+
+// OGCG-LABEL: @f4
+// OGCG: store atomic float 0x40091EB860000000, ptr %{{.+}} seq_cst, align 4
+
void load(int *ptr) {
int x;
__atomic_load(ptr, &x, __ATOMIC_RELAXED);
@@ -1107,3 +1133,269 @@ int c11_atomic_fetch_nand(_Atomic(int) *ptr, int value) {
// OGCG: %[[RES:.+]] = atomicrmw nand ptr %{{.+}}, i32 %{{.+}} seq_cst, align 4
// OGCG-NEXT: store i32 %[[RES]], ptr %{{.+}}, align 4
}
+
+int atomic_load_dynamic_order(int *ptr, int order) {
+ // CIR-LABEL: atomic_load_dynamic_order
+ // LLVM-LABEL: atomic_load_dynamic_order
+ // OGCG-LABEL: atomic_load_dynamic_order
+
+ return __atomic_load_n(ptr, order);
+
+ // CIR: %[[PTR:.+]] = cir.load align(8) %{{.+}} : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
+ // CIR-NEXT: %[[ORDER:.+]] = cir.load align(4) %{{.+}} : !cir.ptr<!s32i>, !s32i
+ // CIR-NEXT: cir.switch (%[[ORDER]] : !s32i) {
+ // CIR-NEXT: cir.case(default, []) {
+ // CIR-NEXT: %[[RES:.+]] = cir.load align(4) atomic(relaxed) %[[PTR]] : !cir.ptr<!s32i>, !s32i
+ // CIR-NEXT: cir.store align(4) %[[RES]], %[[RES_SLOT:.+]] : !s32i, !cir.ptr<!s32i>
+ // CIR-NEXT: cir.break
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.case(anyof, [#cir.int<1> : !s32i, #cir.int<2> : !s32i]) {
+ // CIR-NEXT: %[[RES:.+]] = cir.load align(4) atomic(acquire) %[[PTR]] : !cir.ptr<!s32i>, !s32i
+ // CIR-NEXT: cir.store align(4) %[[RES]], %[[RES_SLOT]] : !s32i, !cir.ptr<!s32i>
+ // CIR-NEXT: cir.break
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.case(anyof, [#cir.int<5> : !s32i]) {
+ // CIR-NEXT: %[[RES:.+]] = cir.load align(4) atomic(seq_cst) %[[PTR]] : !cir.ptr<!s32i>, !s32i
+ // CIR-NEXT: cir.store align(4) %[[RES]], %[[RES_SLOT]] : !s32i, !cir.ptr<!s32i>
+ // CIR-NEXT: cir.break
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.yield
+ // CIR-NEXT: }
+ // CIR-NEXT: %{{.+}} = cir.load align(4) %[[RES_SLOT]] : !cir.ptr<!s32i>, !s32i
+
+ // LLVM: %[[PTR:.+]] = load ptr, ptr %{{.+}}, align 8
+ // LLVM-NEXT: %[[ORDER:.+]] = load i32, ptr %{{.+}}, align 4
+ // LLVM-NEXT: br label %[[SWITCH_BLK:.+]]
+ // LLVM: [[SWITCH_BLK]]:
+ // LLVM-NEXT: switch i32 %[[ORDER]], label %[[DEFAULT_BLK:.+]] [
+ // LLVM-NEXT: i32 1, label %[[ACQUIRE_BLK:.+]]
+ // LLVM-NEXT: i32 2, label %[[ACQUIRE_BLK]]
+ // LLVM-NEXT: i32 5, label %[[SEQ_CST_BLK:.+]]
+ // LLVM-NEXT: ]
+ // LLVM: [[DEFAULT_BLK]]:
+ // LLVM-NEXT: %[[RES:.+]] = load atomic i32, ptr %[[PTR]] monotonic, align 4
+ // LLVM-NEXT: store i32 %[[RES]], ptr %[[RES_SLOT:.+]], align 4
+ // LLVM-NEXT: br label %[[CONTINUE_BLK:.+]]
+ // LLVM: [[ACQUIRE_BLK]]:
+ // LLVM-NEXT: %[[RES:.+]] = load atomic i32, ptr %[[PTR]] acquire, align 4
+ // LLVM-NEXT: store i32 %[[RES]], ptr %[[RES_SLOT]], align 4
+ // LLVM-NEXT: br label %[[CONTINUE_BLK]]
+ // LLVM: [[SEQ_CST_BLK]]:
+ // LLVM-NEXT: %[[RES:.+]] = load atomic i32, ptr %[[PTR]] seq_cst, align 4
+ // LLVM-NEXT: store i32 %[[RES]], ptr %[[RES_SLOT]], align 4
+ // LLVM-NEXT: br label %[[CONTINUE_BLK]]
+ // LLVM: [[CONTINUE_BLK]]:
+ // LLVM-NEXT: %{{.+}} = load i32, ptr %[[RES_SLOT]], align 4
+
+ // OGCG: %[[PTR:.+]] = load ptr, ptr %{{.+}}, align 8
+ // OGCG-NEXT: %[[ORDER:.+]] = load i32, ptr %{{.+}}, align 4
+ // OGCG-NEXT: switch i32 %[[ORDER]], label %[[DEFAULT_BLK:.+]] [
+ // OGCG-NEXT: i32 1, label %[[ACQUIRE_BLK:.+]]
+ // OGCG-NEXT: i32 2, label %[[ACQUIRE_BLK]]
+ // OGCG-NEXT: i32 5, label %[[SEQ_CST_BLK:.+]]
+ // OGCG-NEXT: ]
+ // OGCG: [[DEFAULT_BLK]]:
+ // OGCG-NEXT: %[[RES:.+]] = load atomic i32, ptr %[[PTR]] monotonic, align 4
+ // OGCG-NEXT: store i32 %[[RES]], ptr %[[RES_SLOT:.+]], align 4
+ // OGCG-NEXT: br label %[[CONTINUE_BLK:.+]]
+ // OGCG: [[ACQUIRE_BLK]]:
+ // OGCG-NEXT: %[[RES:.+]] = load atomic i32, ptr %[[PTR]] acquire, align 4
+ // OGCG-NEXT: store i32 %[[RES]], ptr %[[RES_SLOT]], align 4
+ // OGCG-NEXT: br label %[[CONTINUE_BLK]]
+ // OGCG: [[SEQ_CST_BLK]]:
+ // OGCG-NEXT: %[[RES:.+]] = load atomic i32, ptr %[[PTR]] seq_cst, align 4
+ // OGCG-NEXT: store i32 %[[RES]], ptr %[[RES_SLOT]], align 4
+ // OGCG-NEXT: br label %[[CONTINUE_BLK]]
+ // OGCG: [[CONTINUE_BLK]]:
+ // OGCG-NEXT: %{{.+}} = load i32, ptr %[[RES_SLOT]], align 4
+}
+
+void atomic_store_dynamic_order(int *ptr, int order) {
+ // CIR-LABEL: atomic_store_dynamic_order
+ // LLVM-LABEL: atomic_store_dynamic_order
+ // OGCG-LABEL: atomic_store_dynamic_order
+
+ __atomic_store_n(ptr, 10, order);
+
+ // CIR: %[[PTR:.+]] = cir.load align(8) %{{.+}} : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
+ // CIR-NEXT: %[[ORDER:.+]] = cir.load align(4) %{{.+}} : !cir.ptr<!s32i>, !s32i
+ // CIR: cir.switch (%[[ORDER]] : !s32i) {
+ // CIR-NEXT: cir.case(default, []) {
+ // CIR-NEXT: %[[VALUE:.+]] = cir.load align(4) %{{.+}} : !cir.ptr<!s32i>, !s32i
+ // CIR-NEXT: cir.store align(4) atomic(relaxed) %[[VALUE]], %[[PTR]] : !s32i, !cir.ptr<!s32i>
+ // CIR-NEXT: cir.break
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.case(anyof, [#cir.int<3> : !s32i]) {
+ // CIR-NEXT: %[[VALUE:.+]] = cir.load align(4) %{{.+}} : !cir.ptr<!s32i>, !s32i
+ // CIR-NEXT: cir.store align(4) atomic(release) %[[VALUE]], %[[PTR]] : !s32i, !cir.ptr<!s32i>
+ // CIR-NEXT: cir.break
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.case(anyof, [#cir.int<5> : !s32i]) {
+ // CIR-NEXT: %[[VALUE:.+]] = cir.load align(4) %{{.+}} : !cir.ptr<!s32i>, !s32i
+ // CIR-NEXT: cir.store align(4) atomic(seq_cst) %[[VALUE]], %[[PTR]] : !s32i, !cir.ptr<!s32i>
+ // CIR-NEXT: cir.break
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.yield
+ // CIR-NEXT: }
+
+ // LLVM: %[[PTR:.+]] = load ptr, ptr %{{.+}}, align 8
+ // LLVM-NEXT: %[[ORDER:.+]] = load i32, ptr %{{.+}}, align 4
+ // LLVM: br label %[[SWITCH_BLK:.+]]
+ // LLVM: [[SWITCH_BLK]]:
+ // LLVM-NEXT: switch i32 %[[ORDER]], label %[[DEFAULT_BLK:.+]] [
+ // LLVM-NEXT: i32 3, label %[[RELEASE_BLK:.+]]
+ // LLVM-NEXT: i32 5, label %[[SEQ_CST_BLK:.+]]
+ // LLVM-NEXT: ]
+ // LLVM: [[DEFAULT_BLK]]:
+ // LLVM-NEXT: %[[VALUE:.+]] = load i32, ptr %{{.+}}, align 4
+ // LLVM-NEXT: store atomic i32 %[[VALUE]], ptr %[[PTR]] monotonic, align 4
+ // LLVM-NEXT: br label %{{.+}}
+ // LLVM: [[RELEASE_BLK]]:
+ // LLVM-NEXT: %[[VALUE:.+]] = load i32, ptr %{{.+}}, align 4
+ // LLVM-NEXT: store atomic i32 %[[VALUE]], ptr %[[PTR]] release, align 4
+ // LLVM-NEXT: br label %{{.+}}
+ // LLVM: [[SEQ_CST_BLK]]:
+ // LLVM-NEXT: %[[VALUE:.+]] = load i32, ptr %{{.+}}, align 4
+ // LLVM-NEXT: store atomic i32 %[[VALUE]], ptr %[[PTR]] seq_cst, align 4
+ // LLVM-NEXT: br label %{{.+}}
+
+ // OGCG: %[[PTR:.+]] = load ptr, ptr %{{.+}}, align 8
+ // OGCG-NEXT: %[[ORDER:.+]] = load i32, ptr %{{.+}}, align 4
+ // OGCG: switch i32 %[[ORDER]], label %[[DEFAULT_BLK:.+]] [
+ // OGCG-NEXT: i32 3, label %[[RELEASE_BLK:.+]]
+ // OGCG-NEXT: i32 5, label %[[SEQ_CST_BLK:.+]]
+ // OGCG-NEXT: ]
+ // OGCG: [[DEFAULT_BLK]]:
+ // OGCG-NEXT: %[[VALUE:.+]] = load i32, ptr %{{.+}}, align 4
+ // OGCG-NEXT: store atomic i32 %[[VALUE]], ptr %[[PTR]] monotonic, align 4
+ // OGCG-NEXT: br label %{{.+}}
+ // OGCG: [[RELEASE_BLK]]:
+ // OGCG-NEXT: %[[VALUE:.+]] = load i32, ptr %{{.+}}, align 4
+ // OGCG-NEXT: store atomic i32 %[[VALUE]], ptr %[[PTR]] release, align 4
+ // OGCG-NEXT: br label %{{.+}}
+ // OGCG: [[SEQ_CST_BLK]]:
+ // OGCG-NEXT: %[[VALUE:.+]] = load i32, ptr %{{.+}}, align 4
+ // OGCG-NEXT: store atomic i32 %[[VALUE]], ptr %[[PTR]] seq_cst, align 4
+ // OGCG-NEXT: br label %{{.+}}
+}
+
+int atomic_load_and_store_dynamic_order(int *ptr, int order) {
+ // CIR-LABEL: atomic_load_and_store_dynamic_order
+ // LLVM-LABEL: atomic_load_and_store_dynamic_order
+ // OGCG-LABEL: atomic_load_and_store_dynamic_order
+
+ return __atomic_exchange_n(ptr, 20, order);
+
+ // CIR: %[[PTR:.+]] = cir.load align(8) %{{.+}} : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
+ // CIR-NEXT: %[[ORDER:.+]] = cir.load align(4) %{{.+}} : !cir.ptr<!s32i>, !s32i
+ // CIR: cir.switch (%[[ORDER]] : !s32i) {
+ // CIR-NEXT: cir.case(default, []) {
+ // CIR-NEXT: %[[LIT:.+]] = cir.load align(4) %{{.+}} : !cir.ptr<!s32i>, !s32i
+ // CIR-NEXT: %[[RES:.+]] = cir.atomic.xchg relaxed %[[PTR]], %[[LIT]] : (!cir.ptr<!s32i>, !s32i) -> !s32i
+ // CIR-NEXT: cir.store align(4) %[[RES]], %[[RES_SLOT:.+]] : !s32i, !cir.ptr<!s32i>
+ // CIR-NEXT: cir.break
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.case(anyof, [#cir.int<1> : !s32i, #cir.int<2> : !s32i]) {
+ // CIR-NEXT: %[[LIT:.+]] = cir.load align(4) %{{.+}} : !cir.ptr<!s32i>, !s32i
+ // CIR-NEXT: %[[RES:.+]] = cir.atomic.xchg acquire %[[PTR]], %[[LIT]] : (!cir.ptr<!s32i>, !s32i) -> !s32i
+ // CIR-NEXT: cir.store align(4) %[[RES]], %[[RES_SLOT]] : !s32i, !cir.ptr<!s32i>
+ // CIR-NEXT: cir.break
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.case(anyof, [#cir.int<3> : !s32i]) {
+ // CIR-NEXT: %[[LIT:.+]] = cir.load align(4) %{{.+}} : !cir.ptr<!s32i>, !s32i
+ // CIR-NEXT: %[[RES:.+]] = cir.atomic.xchg release %[[PTR]], %[[LIT]] : (!cir.ptr<!s32i>, !s32i) -> !s32i
+ // CIR-NEXT: cir.store align(4) %[[RES]], %[[RES_SLOT]] : !s32i, !cir.ptr<!s32i>
+ // CIR-NEXT: cir.break
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.case(anyof, [#cir.int<4> : !s32i]) {
+ // CIR-NEXT: %[[LIT:.+]] = cir.load align(4) %{{.+}} : !cir.ptr<!s32i>, !s32i
+ // CIR-NEXT: %[[RES:.+]] = cir.atomic.xchg acq_rel %[[PTR]], %[[LIT]] : (!cir.ptr<!s32i>, !s32i) -> !s32i
+ // CIR-NEXT: cir.store align(4) %[[RES]], %[[RES_SLOT]] : !s32i, !cir.ptr<!s32i>
+ // CIR-NEXT: cir.break
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.case(anyof, [#cir.int<5> : !s32i]) {
+ // CIR-NEXT: %[[LIT:.+]] = cir.load align(4) %{{.+}} : !cir.ptr<!s32i>, !s32i
+ // CIR-NEXT: %[[RES:.+]] = cir.atomic.xchg seq_cst %[[PTR]], %[[LIT]] : (!cir.ptr<!s32i>, !s32i) -> !s32i
+ // CIR-NEXT: cir.store align(4) %[[RES]], %[[RES_SLOT]] : !s32i, !cir.ptr<!s32i>
+ // CIR-NEXT: cir.break
+ // CIR-NEXT: }
+ // CIR-NEXT: cir.yield
+ // CIR-NEXT: }
+ // CIR-NEXT: %{{.+}} = cir.load align(4) %[[RES_SLOT]] : !cir.ptr<!s32i>, !s32i
+
+ // LLVM: %[[PTR:.+]] = load ptr, ptr %{{.+}}, align 8
+ // LLVM-NEXT: %[[ORDER:.+]] = load i32, ptr %{{.+}}, align 4
+ // LLVM: br label %[[SWITCH_BLK:.+]]
+ // LLVM: [[SWITCH_BLK]]:
+ // LLVM-NEXT: switch i32 %[[ORDER]], label %[[DEFAULT_BLK:.+]] [
+ // LLVM-NEXT: i32 1, label %[[ACQUIRE_BLK:.+]]
+ // LLVM-NEXT: i32 2, label %[[ACQUIRE_BLK]]
+ // LLVM-NEXT: i32 3, label %[[RELEASE_BLK:.+]]
+ // LLVM-NEXT: i32 4, label %[[ACQ_REL_BLK:.+]]
+ // LLVM-NEXT: i32 5, label %[[SEQ_CST_BLK:.+]]
+ // LLVM-NEXT: ]
+ // LLVM: [[DEFAULT_BLK]]:
+ // LLVM-NEXT: %[[VALUE:.+]] = load i32, ptr %{{.+}}, align 4
+ // LLVM-NEXT: %[[RES:.+]] = atomicrmw xchg ptr %[[PTR]], i32 %[[VALUE]] monotonic, align 4
+ // LLVM-NEXT: store i32 %[[RES]], ptr %[[RES_SLOT:.+]], align 4
+ // LLVM-NEXT: br label %[[CONTINUE_BLK:.+]]
+ // LLVM: [[ACQUIRE_BLK]]:
+ // LLVM-NEXT: %[[VALUE:.+]] = load i32, ptr %{{.+}}, align 4
+ // LLVM-NEXT: %[[RES:.+]] = atomicrmw xchg ptr %[[PTR]], i32 %[[VALUE]] acquire, align 4
+ // LLVM-NEXT: store i32 %[[RES]], ptr %[[RES_SLOT]], align 4
+ // LLVM-NEXT: br label %[[CONTINUE_BLK]]
+ // LLVM: [[RELEASE_BLK]]:
+ // LLVM-NEXT: %[[VALUE:.+]] = load i32, ptr %{{.+}}, align 4
+ // LLVM-NEXT: %[[RES:.+]] = atomicrmw xchg ptr %[[PTR]], i32 %[[VALUE]] release, align 4
+ // LLVM-NEXT: store i32 %[[RES]], ptr %[[RES_SLOT]], align 4
+ // LLVM-NEXT: br label %[[CONTINUE_BLK]]
+ // LLVM: [[ACQ_REL_BLK]]:
+ // LLVM-NEXT: %[[VALUE:.+]] = load i32, ptr %{{.+}}, align 4
+ // LLVM-NEXT: %[[RES:.+]] = atomicrmw xchg ptr %[[PTR]], i32 %[[VALUE]] acq_rel, align 4
+ // LLVM-NEXT: store i32 %[[RES]], ptr %[[RES_SLOT]], align 4
+ // LLVM-NEXT: br label %[[CONTINUE_BLK]]
+ // LLVM: [[SEQ_CST_BLK]]:
+ // LLVM-NEXT: %[[VALUE:.+]] = load i32, ptr %{{.+}}, align 4
+ // LLVM-NEXT: %[[RES:.+]] = atomicrmw xchg ptr %[[PTR]], i32 %[[VALUE]] seq_cst, align 4
+ // LLVM-NEXT: store i32 %[[RES]], ptr %[[RES_SLOT]], align 4
+ // LLVM-NEXT: br label %[[CONTINUE_BLK]]
+ // LLVM: [[CONTINUE_BLK]]:
+ // LLVM-NEXT: %{{.+}} = load i32, ptr %[[RES_SLOT]], align 4
+
+ // OGCG: %[[PTR:.+]] = load ptr, ptr %{{.+}}, align 8
+ // OGCG-NEXT: %[[ORDER:.+]] = load i32, ptr %{{.+}}, align 4
+ // OGCG: switch i32 %[[ORDER]], label %[[DEFAULT_BLK:.+]] [
+ // OGCG-NEXT: i32 1, label %[[ACQUIRE_BLK:.+]]
+ // OGCG-NEXT: i32 2, label %[[ACQUIRE_BLK]]
+ // OGCG-NEXT: i32 3, label %[[RELEASE_BLK:.+]]
+ // OGCG-NEXT: i32 4, label %[[ACQ_REL_BLK:.+]]
+ // OGCG-NEXT: i32 5, label %[[SEQ_CST_BLK:.+]]
+ // OGCG-NEXT: ]
+ // OGCG: [[DEFAULT_BLK]]:
+ // OGCG-NEXT: %[[VALUE:.+]] = load i32, ptr %{{.+}}, align 4
+ // OGCG-NEXT: %[[RES:.+]] = atomicrmw xchg ptr %[[PTR]], i32 %[[VALUE]] monotonic, align 4
+ // OGCG-NEXT: store i32 %[[RES]], ptr %[[RES_SLOT:.+]], align 4
+ // OGCG-NEXT: br label %[[CONTINUE_BLK:.+]]
+ // OGCG: [[ACQUIRE_BLK]]:
+ // OGCG-NEXT: %[[VALUE:.+]] = load i32, ptr %{{.+}}, align 4
+ // OGCG-NEXT: %[[RES:.+]] = atomicrmw xchg ptr %[[PTR]], i32 %[[VALUE]] acquire, align 4
+ // OGCG-NEXT: store i32 %[[RES]], ptr %[[RES_SLOT]], align 4
+ // OGCG-NEXT: br label %[[CONTINUE_BLK]]
+ // OGCG: [[RELEASE_BLK]]:
+ // OGCG-NEXT: %[[VALUE:.+]] = load i32, ptr %{{.+}}, align 4
+ // OGCG-NEXT: %[[RES:.+]] = atomicrmw xchg ptr %[[PTR]], i32 %[[VALUE]] release, align 4
+ // OGCG-NEXT: store i32 %[[RES]], ptr %[[RES_SLOT]], align 4
+ // OGCG-NEXT: br label %[[CONTINUE_BLK]]
+ // OGCG: [[ACQ_REL_BLK]]:
+ // OGCG-NEXT: %[[VALUE:.+]] = load i32, ptr %{{.+}}, align 4
+ // OGCG-NEXT: %[[RES:.+]] = atomicrmw xchg ptr %[[PTR]], i32 %[[VALUE]] acq_rel, align 4
+ // OGCG-NEXT: store i32 %[[RES]], ptr %[[RES_SLOT]], align 4
+ // OGCG-NEXT: br label %[[CONTINUE_BLK]]
+ // OGCG: [[SEQ_CST_BLK]]:
+ // OGCG-NEXT: %[[VALUE:.+]] = load i32, ptr %{{.+}}, align 4
+ // OGCG-NEXT: %[[RES:.+]] = atomicrmw xchg ptr %[[PTR]], i32 %[[VALUE]] seq_cst, align 4
+ // OGCG-NEXT: store i32 %[[RES]], ptr %[[RES_SLOT]], align 4
+ // OGCG-NEXT: br label %[[CONTINUE_BLK]]
+ // OGCG: [[CONTINUE_BLK]]:
+ // OGCG-NEXT: %{{.+}} = load i32, ptr %[[RES_SLOT]], align 4
+}
diff --git a/clang/test/CIR/CodeGen/base-to-derived.cpp b/clang/test/CIR/CodeGen/base-to-derived.cpp
new file mode 100644
index 0000000..af9aa0f
--- /dev/null
+++ b/clang/test/CIR/CodeGen/base-to-derived.cpp
@@ -0,0 +1,97 @@
+// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-android21 -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
+
+class A {
+ int a;
+};
+
+class B {
+ int b;
+public:
+ A *getAsA();
+};
+
+class X : public A, public B {
+ int x;
+};
+
+X *castAtoX(A *a) {
+ return static_cast<X*>(a);
+}
+
+// CIR: cir.func {{.*}} @_Z8castAtoXP1A(%[[ARG0:.*]]: !cir.ptr<!rec_A> {{.*}})
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.ptr<!rec_A>, !cir.ptr<!cir.ptr<!rec_A>>, ["a", init]
+// CIR: cir.store %[[ARG0]], %[[A_ADDR]] : !cir.ptr<!rec_A>, !cir.ptr<!cir.ptr<!rec_A>>
+// CIR: %[[A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.ptr<!rec_A>>, !cir.ptr<!rec_A>
+// CIR: %[[X:.*]] = cir.derived_class_addr %[[A]] : !cir.ptr<!rec_A> [0] -> !cir.ptr<!rec_X>
+
+// Note: Because the offset is 0, a null check is not needed.
+
+// LLVM: define {{.*}} ptr @_Z8castAtoXP1A(ptr %[[ARG0:.*]])
+// LLVM: %[[A_ADDR:.*]] = alloca ptr
+// LLVM: store ptr %[[ARG0]], ptr %[[A_ADDR]]
+// LLVM: %[[X:.*]] = load ptr, ptr %[[A_ADDR]]
+
+// OGCG: define {{.*}} ptr @_Z8castAtoXP1A(ptr {{.*}} %[[ARG0:.*]])
+// OGCG: %[[A_ADDR:.*]] = alloca ptr
+// OGCG: store ptr %[[ARG0]], ptr %[[A_ADDR]]
+// OGCG: %[[X:.*]] = load ptr, ptr %[[A_ADDR]]
+
+X *castBtoX(B *b) {
+ return static_cast<X*>(b);
+}
+
+// CIR: cir.func {{.*}} @_Z8castBtoXP1B(%[[ARG0:.*]]: !cir.ptr<!rec_B> {{.*}})
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.ptr<!rec_B>, !cir.ptr<!cir.ptr<!rec_B>>, ["b", init]
+// CIR: cir.store %[[ARG0]], %[[B_ADDR]] : !cir.ptr<!rec_B>, !cir.ptr<!cir.ptr<!rec_B>>
+// CIR: %[[B:.*]] = cir.load{{.*}} %[[B_ADDR]] : !cir.ptr<!cir.ptr<!rec_B>>, !cir.ptr<!rec_B>
+// CIR: %[[X:.*]] = cir.derived_class_addr %[[B]] : !cir.ptr<!rec_B> [4] -> !cir.ptr<!rec_X>
+
+// LLVM: define {{.*}} ptr @_Z8castBtoXP1B(ptr %[[ARG0:.*]])
+// LLVM: %[[B_ADDR:.*]] = alloca ptr, i64 1, align 8
+// LLVM: store ptr %[[ARG0]], ptr %[[B_ADDR]], align 8
+// LLVM: %[[B:.*]] = load ptr, ptr %[[B_ADDR]], align 8
+// LLVM: %[[IS_NULL:.*]] = icmp eq ptr %[[B]], null
+// LLVM: %[[B_NON_NULL:.*]] = getelementptr inbounds i8, ptr %[[B]], i32 -4
+// LLVM: %[[X:.*]] = select i1 %[[IS_NULL]], ptr %[[B]], ptr %[[B_NON_NULL]]
+
+// OGCG: define {{.*}} ptr @_Z8castBtoXP1B(ptr {{.*}} %[[ARG0:.*]])
+// OGCG: entry:
+// OGCG: %[[B_ADDR:.*]] = alloca ptr
+// OGCG: store ptr %[[ARG0]], ptr %[[B_ADDR]]
+// OGCG: %[[B:.*]] = load ptr, ptr %[[B_ADDR]]
+// OGCG: %[[IS_NULL:.*]] = icmp eq ptr %[[B]], null
+// OGCG: br i1 %[[IS_NULL]], label %[[LABEL_NULL:.*]], label %[[LABEL_NOTNULL:.*]]
+// OGCG: [[LABEL_NOTNULL]]:
+// OGCG: %[[B_NON_NULL:.*]] = getelementptr inbounds i8, ptr %[[B]], i64 -4
+// OGCG: br label %[[LABEL_END:.*]]
+// OGCG: [[LABEL_NULL]]:
+// OGCG: br label %[[LABEL_END:.*]]
+// OGCG: [[LABEL_END]]:
+// OGCG: %[[X:.*]] = phi ptr [ %[[B_NON_NULL]], %[[LABEL_NOTNULL]] ], [ null, %[[LABEL_NULL]] ]
+
+X &castBReftoXRef(B &b) {
+ return static_cast<X&>(b);
+}
+
+// CIR: cir.func {{.*}} @_Z14castBReftoXRefR1B(%[[ARG0:.*]]: !cir.ptr<!rec_B> {{.*}})
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.ptr<!rec_B>, !cir.ptr<!cir.ptr<!rec_B>>, ["b", init, const]
+// CIR: cir.store %[[ARG0]], %[[B_ADDR]] : !cir.ptr<!rec_B>, !cir.ptr<!cir.ptr<!rec_B>>
+// CIR: %[[B:.*]] = cir.load{{.*}} %[[B_ADDR]] : !cir.ptr<!cir.ptr<!rec_B>>, !cir.ptr<!rec_B>
+// CIR: %[[X:.*]] = cir.derived_class_addr %[[B]] : !cir.ptr<!rec_B> nonnull [4] -> !cir.ptr<!rec_X>
+
+// LLVM: define {{.*}} ptr @_Z14castBReftoXRefR1B(ptr %[[ARG0:.*]])
+// LLVM: %[[B_ADDR:.*]] = alloca ptr
+// LLVM: store ptr %[[ARG0]], ptr %[[B_ADDR]]
+// LLVM: %[[B:.*]] = load ptr, ptr %[[B_ADDR]]
+// LLVM: %[[X:.*]] = getelementptr inbounds i8, ptr %[[B]], i32 -4
+
+// OGCG: define {{.*}} ptr @_Z14castBReftoXRefR1B(ptr {{.*}} %[[ARG0:.*]])
+// OGCG: %[[B_ADDR:.*]] = alloca ptr
+// OGCG: store ptr %[[ARG0]], ptr %[[B_ADDR]]
+// OGCG: %[[B:.*]] = load ptr, ptr %[[B_ADDR]]
+// OGCG: %[[X:.*]] = getelementptr inbounds i8, ptr %[[B]], i64 -4
diff --git a/clang/test/CIR/CodeGen/binassign.c b/clang/test/CIR/CodeGen/binassign.c
index 44c54b4..4520063 100644
--- a/clang/test/CIR/CodeGen/binassign.c
+++ b/clang/test/CIR/CodeGen/binassign.c
@@ -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
diff --git a/clang/test/CIR/CodeGen/bitfield-union.c b/clang/test/CIR/CodeGen/bitfield-union.c
index 14a2aaf..9c235c5 100644
--- a/clang/test/CIR/CodeGen/bitfield-union.c
+++ b/clang/test/CIR/CodeGen/bitfield-union.c
@@ -39,7 +39,7 @@ void f() {
// CIR: #bfi_y = #cir.bitfield_info<name = "y", storage_type = !u8i, size = 4, offset = 0, is_signed = true>
// CIR: #bfi_z = #cir.bitfield_info<name = "z", storage_type = !u8i, size = 8, offset = 0, is_signed = true>
-// CIR: cir.func no_proto dso_local @f
+// CIR: cir.func {{.*}} @f
// CIR: [[ALLOC:%.*]] = cir.alloca !rec_demo, !cir.ptr<!rec_demo>, ["d"] {alignment = 4 : i64}
// CIR: [[ONE:%.*]] = cir.const #cir.int<1> : !s32i
// CIR: [[X:%.*]] = cir.get_member [[ALLOC]][0] {name = "x"} : !cir.ptr<!rec_demo> -> !cir.ptr<!s32i>
diff --git a/clang/test/CIR/CodeGen/bitfields.c b/clang/test/CIR/CodeGen/bitfields.c
index b2c7d1c..d116039 100644
--- a/clang/test/CIR/CodeGen/bitfields.c
+++ b/clang/test/CIR/CodeGen/bitfields.c
@@ -122,7 +122,7 @@ unsigned int load_field_unsigned(A* s) {
return s->more_bits;
}
-//CIR: cir.func dso_local @load_field_unsigned
+//CIR: cir.func {{.*}} @load_field_unsigned
//CIR: [[TMP0:%.*]] = cir.alloca !cir.ptr<!rec_A>, !cir.ptr<!cir.ptr<!rec_A>>, ["s", init] {alignment = 8 : i64}
//CIR: [[TMP1:%.*]] = cir.load align(8) [[TMP0]] : !cir.ptr<!cir.ptr<!rec_A>>, !cir.ptr<!rec_A>
//CIR: [[TMP2:%.*]] = cir.get_member [[TMP1]][3] {name = "more_bits"} : !cir.ptr<!rec_A> -> !cir.ptr<!u16i>
@@ -228,7 +228,7 @@ void get_volatile(V* v) {
v->b = 3;
}
-// CIR: cir.func dso_local @get_volatile
+// CIR: cir.func {{.*}} @get_volatile
// CIR: [[TMP0:%.*]] = cir.alloca !cir.ptr<!rec_V>, !cir.ptr<!cir.ptr<!rec_V>>, ["v", init] {alignment = 8 : i64}
// CIR: [[TMP1:%.*]] = cir.const #cir.int<3> : !s32i
// CIR: [[TMP2:%.*]] = cir.load align(8) [[TMP0]] : !cir.ptr<!cir.ptr<!rec_V>>, !cir.ptr<!rec_V>
@@ -255,7 +255,7 @@ void get_volatile(V* v) {
void set_volatile(V* v) {
v->b = 3;
}
-//CIR: cir.func dso_local @set_volatile
+//CIR: cir.func {{.*}} @set_volatile
//CIR: [[TMP0:%.*]] = cir.alloca !cir.ptr<!rec_V>, !cir.ptr<!cir.ptr<!rec_V>>, ["v", init] {alignment = 8 : i64}
//CIR: [[TMP1:%.*]] = cir.const #cir.int<3> : !s32i
//CIR: [[TMP2:%.*]] = cir.load align(8) [[TMP0]] : !cir.ptr<!cir.ptr<!rec_V>>, !cir.ptr<!rec_V>
diff --git a/clang/test/CIR/CodeGen/bitfields.cpp b/clang/test/CIR/CodeGen/bitfields.cpp
index 7650e0b..8eeb71c 100644
--- a/clang/test/CIR/CodeGen/bitfields.cpp
+++ b/clang/test/CIR/CodeGen/bitfields.cpp
@@ -35,7 +35,7 @@ void def() {
int load_field(S* s) {
return s->c;
}
-// CIR: cir.func dso_local @_Z10load_field
+// CIR: cir.func {{.*}} @_Z10load_field
// CIR: [[TMP0:%.*]] = cir.alloca !cir.ptr<!rec_S>, !cir.ptr<!cir.ptr<!rec_S>>, ["s", init]
// CIR: [[TMP1:%.*]] = cir.load{{.*}} [[TMP0]] : !cir.ptr<!cir.ptr<!rec_S>>, !cir.ptr<!rec_S>
// CIR: [[TMP2:%.*]] = cir.get_member [[TMP1]][0] {name = "c"} : !cir.ptr<!rec_S> -> !cir.ptr<!u64i>
@@ -63,7 +63,7 @@ void store_field() {
S s;
s.a = 3;
}
-// CIR: cir.func dso_local @_Z11store_field
+// CIR: cir.func {{.*}} @_Z11store_field
// CIR: [[TMP0:%.*]] = cir.alloca !rec_S, !cir.ptr<!rec_S>
// CIR: [[TMP1:%.*]] = cir.const #cir.int<3> : !s32i
// CIR: [[TMP2:%.*]] = cir.get_member [[TMP0]][0] {name = "a"} : !cir.ptr<!rec_S> -> !cir.ptr<!u64i>
@@ -88,7 +88,7 @@ void store_bitfield_to_bitfield(S* s) {
s->a = s->b = 3;
}
-// CIR: cir.func dso_local @_Z26store_bitfield_to_bitfieldP1S
+// CIR: cir.func {{.*}} @_Z26store_bitfield_to_bitfieldP1S
// CIR: [[TMP0:%.*]] = cir.alloca !cir.ptr<!rec_S>, !cir.ptr<!cir.ptr<!rec_S>>, ["s", init] {alignment = 8 : i64}
// CIR: [[TMP1:%.*]] = cir.const #cir.int<3> : !s32i
// CIR: [[TMP2:%.*]] = cir.load align(8) [[TMP0]] : !cir.ptr<!cir.ptr<!rec_S>>, !cir.ptr<!rec_S>
diff --git a/clang/test/CIR/CodeGen/bitfields_be.c b/clang/test/CIR/CodeGen/bitfields_be.c
index 3e1f054..f4f3476 100644
--- a/clang/test/CIR/CodeGen/bitfields_be.c
+++ b/clang/test/CIR/CodeGen/bitfields_be.c
@@ -21,7 +21,7 @@ int init(S* s) {
return s->c;
}
-//CIR: cir.func dso_local @init
+//CIR: cir.func {{.*}} @init
//CIR: [[TMP0:%.*]] = cir.alloca !cir.ptr<!rec_S>, !cir.ptr<!cir.ptr<!rec_S>>, ["s", init] {alignment = 8 : i64}
//CIR: [[TMP1:%.*]] = cir.load align(8) [[TMP0]] : !cir.ptr<!cir.ptr<!rec_S>>, !cir.ptr<!rec_S>
//CIR: [[TMP2:%.*]] = cir.get_member [[TMP1]][0] {name = "c"} : !cir.ptr<!rec_S> -> !cir.ptr<!u32i>
@@ -51,7 +51,7 @@ void load(S* s) {
}
// field 'a'
-// CIR: cir.func dso_local @load
+// CIR: cir.func {{.*}} @load
// CIR: %[[PTR0:.*]] = cir.alloca !cir.ptr<!rec_S>, !cir.ptr<!cir.ptr<!rec_S>>, ["s", init] {alignment = 8 : i64} loc(#loc35)
// CIR: %[[CONST1:.*]] = cir.const #cir.int<4> : !s32i
// CIR: %[[MIN1:.*]] = cir.unary(minus, %[[CONST1]]) nsw : !s32i, !s32i
diff --git a/clang/test/CIR/CodeGen/builtin_bit.cpp b/clang/test/CIR/CodeGen/builtin_bit.cpp
deleted file mode 100644
index 32a53d8..0000000
--- a/clang/test/CIR/CodeGen/builtin_bit.cpp
+++ /dev/null
@@ -1,628 +0,0 @@
-// RUN: %clang_cc1 -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 -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 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
-// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
-
-int test_builtin_clrsb(int x) {
- return __builtin_clrsb(x);
-}
-
-// CIR-LABEL: _Z18test_builtin_clrsbi
-// CIR: [[TMP:%.+]] = cir.clrsb %{{.+}} : !s32i
-
-// LLVM-LABEL: _Z18test_builtin_clrsbi
-// LLVM: %[[X:.+]] = load i32, ptr %{{.+}}, align 4
-// LLVM-NEXT: %[[X_NEG:.+]] = icmp slt i32 %[[X]], 0
-// LLVM-NEXT: %[[X_NOT:.+]] = xor i32 %[[X]], -1
-// LLVM-NEXT: %[[P:.+]] = select i1 %[[X_NEG]], i32 %[[X_NOT]], i32 %[[X]]
-// LLVM-NEXT: %[[LZ:.+]] = call i32 @llvm.ctlz.i32(i32 %[[P]], i1 false)
-// LLVM-NEXT: %{{.+}} = sub i32 %[[LZ]], 1
-
-// OGCG-LABEL: _Z18test_builtin_clrsbi
-// OGCG: %[[X:.+]] = load i32, ptr %{{.+}}, align 4
-// OGCG-NEXT: %[[X_NEG:.+]] = icmp slt i32 %[[X]], 0
-// OGCG-NEXT: %[[X_NOT:.+]] = xor i32 %[[X]], -1
-// OGCG-NEXT: %[[P:.+]] = select i1 %[[X_NEG]], i32 %[[X_NOT]], i32 %[[X]]
-// OGCG-NEXT: %[[LZ:.+]] = call i32 @llvm.ctlz.i32(i32 %[[P]], i1 false)
-// OGCG-NEXT: %{{.+}} = sub i32 %[[LZ]], 1
-
-int test_builtin_clrsbl(long x) {
- return __builtin_clrsbl(x);
-}
-
-// CIR-LABEL: _Z19test_builtin_clrsbll
-// CIR: [[TMP:%.+]] = cir.clrsb %{{.+}} : !s64i
-// CIR: {{%.+}} = cir.cast integral [[TMP]] : !s64i -> !s32i
-
-// LLVM-LABEL: _Z19test_builtin_clrsbll
-// LLVM: %[[X:.+]] = load i64, ptr %{{.+}}, align 8
-// LLVM-NEXT: %[[X_NEG:.+]] = icmp slt i64 %[[X]], 0
-// LLVM-NEXT: %[[X_NOT:.+]] = xor i64 %[[X]], -1
-// LLVM-NEXT: %[[P:.+]] = select i1 %[[X_NEG]], i64 %[[X_NOT]], i64 %[[X]]
-// LLVM-NEXT: %[[LZ:.+]] = call i64 @llvm.ctlz.i64(i64 %[[P]], i1 false)
-// LLVM-NEXT: %{{.+}} = sub i64 %[[LZ]], 1
-
-// OGCG-LABEL: _Z19test_builtin_clrsbll
-// OGCG: %[[X:.+]] = load i64, ptr %{{.+}}, align 8
-// OGCG-NEXT: %[[X_NEG:.+]] = icmp slt i64 %[[X]], 0
-// OGCG-NEXT: %[[X_NOT:.+]] = xor i64 %[[X]], -1
-// OGCG-NEXT: %[[P:.+]] = select i1 %[[X_NEG]], i64 %[[X_NOT]], i64 %[[X]]
-// OGCG-NEXT: %[[LZ:.+]] = call i64 @llvm.ctlz.i64(i64 %[[P]], i1 false)
-// OGCG-NEXT: %{{.+}} = sub i64 %[[LZ]], 1
-
-int test_builtin_clrsbll(long long x) {
- return __builtin_clrsbll(x);
-}
-
-// CIR-LABEL: _Z20test_builtin_clrsbllx
-// CIR: [[TMP:%.+]] = cir.clrsb %{{.+}} : !s64i
-// CIR: {{%.+}} = cir.cast integral [[TMP]] : !s64i -> !s32i
-
-// LLVM-LABEL: _Z20test_builtin_clrsbllx
-// LLVM: %[[X:.+]] = load i64, ptr %{{.+}}, align 8
-// LLVM-NEXT: %[[X_NEG:.+]] = icmp slt i64 %[[X]], 0
-// LLVM-NEXT: %[[X_NOT:.+]] = xor i64 %[[X]], -1
-// LLVM-NEXT: %[[P:.+]] = select i1 %[[X_NEG]], i64 %[[X_NOT]], i64 %[[X]]
-// LLVM-NEXT: %[[LZ:.+]] = call i64 @llvm.ctlz.i64(i64 %[[P]], i1 false)
-// LLVM-NEXT: %{{.+}} = sub i64 %[[LZ]], 1
-
-// OGCG-LABEL: _Z20test_builtin_clrsbllx
-// OGCG: %[[X:.+]] = load i64, ptr %{{.+}}, align 8
-// OGCG-NEXT: %[[X_NEG:.+]] = icmp slt i64 %[[X]], 0
-// OGCG-NEXT: %[[X_NOT:.+]] = xor i64 %[[X]], -1
-// OGCG-NEXT: %[[P:.+]] = select i1 %[[X_NEG]], i64 %[[X_NOT]], i64 %[[X]]
-// OGCG-NEXT: %[[LZ:.+]] = call i64 @llvm.ctlz.i64(i64 %[[P]], i1 false)
-// OGCG-NEXT: %{{.+}} = sub i64 %[[LZ]], 1
-
-int test_builtin_ctzs(unsigned short x) {
- return __builtin_ctzs(x);
-}
-
-// CIR-LABEL: _Z17test_builtin_ctzst
-// CIR: [[TMP:%.+]] = cir.ctz %{{.+}} poison_zero : !u16i
-// CIR: {{%.+}} = cir.cast integral [[TMP]] : !u16i -> !s32i
-
-// LLVM-LABEL: _Z17test_builtin_ctzst
-// LLVM: %{{.+}} = call i16 @llvm.cttz.i16(i16 %{{.+}}, i1 true)
-
-// OGCG-LABEL: _Z17test_builtin_ctzst
-// OGCG: %{{.+}} = call i16 @llvm.cttz.i16(i16 %{{.+}}, i1 true)
-
-int test_builtin_ctz(unsigned x) {
- return __builtin_ctz(x);
-}
-
-// CIR-LABEL: _Z16test_builtin_ctzj
-// CIR: [[TMP:%.+]] = cir.ctz %{{.+}} poison_zero : !u32i
-// CIR: {{%.+}} = cir.cast integral [[TMP]] : !u32i -> !s32i
-
-// LLVM-LABEL: _Z16test_builtin_ctzj
-// LLVM: %{{.+}} = call i32 @llvm.cttz.i32(i32 %{{.+}}, i1 true)
-
-// OGCG-LABEL: _Z16test_builtin_ctzj
-// OGCG: %{{.+}} = call i32 @llvm.cttz.i32(i32 %{{.+}}, i1 true)
-
-int test_builtin_ctzl(unsigned long x) {
- return __builtin_ctzl(x);
-}
-
-// CIR-LABEL: _Z17test_builtin_ctzlm
-// CIR: [[TMP:%.+]] = cir.ctz %{{.+}} poison_zero : !u64i
-// CIR: {{%.+}} = cir.cast integral [[TMP]] : !u64i -> !s32i
-
-// LLVM-LABEL: _Z17test_builtin_ctzlm
-// LLVM: %{{.+}} = call i64 @llvm.cttz.i64(i64 %{{.+}}, i1 true)
-
-// OGCG-LABEL: _Z17test_builtin_ctzlm
-// OGCG: %{{.+}} = call i64 @llvm.cttz.i64(i64 %{{.+}}, i1 true)
-
-int test_builtin_ctzll(unsigned long long x) {
- return __builtin_ctzll(x);
-}
-
-// CIR-LABEL: _Z18test_builtin_ctzlly
-// CIR: [[TMP:%.+]] = cir.ctz %{{.+}} poison_zero : !u64i
-// CIR: {{%.+}} = cir.cast integral [[TMP]] : !u64i -> !s32i
-
-// LLVM-LABEL: _Z18test_builtin_ctzlly
-// LLVM: %{{.+}} = call i64 @llvm.cttz.i64(i64 %{{.+}}, i1 true)
-
-// OGCG-LABEL: _Z18test_builtin_ctzlly
-// OGCG: %{{.+}} = call i64 @llvm.cttz.i64(i64 %{{.+}}, i1 true)
-
-int test_builtin_ctzg(unsigned x) {
- return __builtin_ctzg(x);
-}
-
-// CIR-LABEL: _Z17test_builtin_ctzgj
-// CIR: [[TMP:%.+]] = cir.ctz %{{.+}} poison_zero : !u32i
-// CIR: {{%.+}} = cir.cast integral [[TMP]] : !u32i -> !s32i
-
-// LLVM-LABEL: _Z17test_builtin_ctzgj
-// LLVM: %{{.+}} = call i32 @llvm.cttz.i32(i32 %{{.+}}, i1 true)
-
-// OGCG-LABEL: _Z17test_builtin_ctzgj
-// OGCG: %{{.+}} = call i32 @llvm.cttz.i32(i32 %{{.+}}, i1 true)
-
-int test_builtin_clzs(unsigned short x) {
- return __builtin_clzs(x);
-}
-
-// CIR-LABEL: _Z17test_builtin_clzst
-// CIR: [[TMP:%.+]] = cir.clz %{{.+}} poison_zero : !u16i
-// CIR: {{%.+}} = cir.cast integral [[TMP]] : !u16i -> !s32i
-
-// LLVM-LABEL: _Z17test_builtin_clzst
-// LLVM: %{{.+}} = call i16 @llvm.ctlz.i16(i16 %{{.+}}, i1 true)
-
-// OGCG-LABEL: _Z17test_builtin_clzst
-// OGCG: %{{.+}} = call i16 @llvm.ctlz.i16(i16 %{{.+}}, i1 true)
-
-int test_builtin_clz(unsigned x) {
- return __builtin_clz(x);
-}
-
-// CIR-LABEL: _Z16test_builtin_clzj
-// CIR: [[TMP:%.+]] = cir.clz %{{.+}} poison_zero : !u32i
-// CIR: {{%.+}} = cir.cast integral [[TMP]] : !u32i -> !s32i
-
-// LLVM-LABEL: _Z16test_builtin_clzj
-// LLVM: %{{.+}} = call i32 @llvm.ctlz.i32(i32 %{{.+}}, i1 true)
-
-// OGCG-LABEL: _Z16test_builtin_clzj
-// OGCG: %{{.+}} = call i32 @llvm.ctlz.i32(i32 %{{.+}}, i1 true)
-
-int test_builtin_clzl(unsigned long x) {
- return __builtin_clzl(x);
-}
-
-// CIR-LABEL: _Z17test_builtin_clzlm
-// CIR: [[TMP:%.+]] = cir.clz %{{.+}} poison_zero : !u64i
-// CIR: {{%.+}} = cir.cast integral [[TMP]] : !u64i -> !s32i
-
-// LLVM-LABEL: _Z17test_builtin_clzlm
-// LLVM: %{{.+}} = call i64 @llvm.ctlz.i64(i64 %{{.+}}, i1 true)
-
-// OGCG-LABEL: _Z17test_builtin_clzlm
-// OGCG: %{{.+}} = call i64 @llvm.ctlz.i64(i64 %{{.+}}, i1 true)
-
-int test_builtin_clzll(unsigned long long x) {
- return __builtin_clzll(x);
-}
-
-// CIR-LABEL: _Z18test_builtin_clzlly
-// CIR: [[TMP:%.+]] = cir.clz %{{.+}} poison_zero : !u64i
-// CIR: {{%.+}} = cir.cast integral [[TMP]] : !u64i -> !s32i
-
-// LLVM-LABEL: _Z18test_builtin_clzlly
-// LLVM: %{{.+}} = call i64 @llvm.ctlz.i64(i64 %{{.+}}, i1 true)
-
-// OGCG-LABEL: _Z18test_builtin_clzlly
-// OGCG: %{{.+}} = call i64 @llvm.ctlz.i64(i64 %{{.+}}, i1 true)
-
-int test_builtin_clzg(unsigned x) {
- return __builtin_clzg(x);
-}
-
-// CIR-LABEL: _Z17test_builtin_clzgj
-// CIR: [[TMP:%.+]] = cir.clz %{{.+}} poison_zero : !u32i
-// CIR: {{%.+}} = cir.cast integral [[TMP]] : !u32i -> !s32i
-
-// LLVM-LABEL: _Z17test_builtin_clzgj
-// LLVM: %{{.+}} = call i32 @llvm.ctlz.i32(i32 %{{.+}}, i1 true)
-
-// OGCG-LABEL: _Z17test_builtin_clzgj
-// OGCG: %{{.+}} = call i32 @llvm.ctlz.i32(i32 %{{.+}}, i1 true)
-
-int test_builtin_ffs(int x) {
- return __builtin_ffs(x);
-}
-
-// CIR-LABEL: _Z16test_builtin_ffsi
-// CIR: %{{.+}} = cir.ffs %{{.+}} : !s32i
-// CIR: }
-
-// LLVM-LABEL: _Z16test_builtin_ffsi
-// LLVM: %[[INPUT:.+]] = load i32, ptr %{{.+}}, align 4
-// LLVM-NEXT: %[[CTZ:.+]] = call i32 @llvm.cttz.i32(i32 %[[INPUT]], i1 true)
-// LLVM-NEXT: %[[R1:.+]] = add i32 %[[CTZ]], 1
-// LLVM-NEXT: %[[IS_ZERO:.+]] = icmp eq i32 %[[INPUT]], 0
-// LLVM-NEXT: %{{.+}} = select i1 %[[IS_ZERO]], i32 0, i32 %[[R1]]
-// LLVM: }
-
-// OGCG-LABEL: _Z16test_builtin_ffsi
-// OGCG: %[[INPUT:.+]] = load i32, ptr %{{.+}}, align 4
-// OGCG-NEXT: %[[CTZ:.+]] = call i32 @llvm.cttz.i32(i32 %[[INPUT]], i1 true)
-// OGCG-NEXT: %[[R1:.+]] = add i32 %[[CTZ]], 1
-// OGCG-NEXT: %[[IS_ZERO:.+]] = icmp eq i32 %[[INPUT]], 0
-// OGCG-NEXT: %{{.+}} = select i1 %[[IS_ZERO]], i32 0, i32 %[[R1]]
-// OGCG: }
-
-int test_builtin_ffsl(long x) {
- return __builtin_ffsl(x);
-}
-
-// CIR-LABEL: _Z17test_builtin_ffsll
-// CIR: %{{.+}} = cir.ffs %{{.+}} : !s64i
-// CIR: }
-
-// LLVM-LABEL: _Z17test_builtin_ffsll
-// LLVM: %[[INPUT:.+]] = load i64, ptr %{{.+}}, align 8
-// LLVM-NEXT: %[[CTZ:.+]] = call i64 @llvm.cttz.i64(i64 %[[INPUT]], i1 true)
-// LLVM-NEXT: %[[R1:.+]] = add i64 %[[CTZ]], 1
-// LLVM-NEXT: %[[IS_ZERO:.+]] = icmp eq i64 %[[INPUT]], 0
-// LLVM-NEXT: %{{.+}} = select i1 %[[IS_ZERO]], i64 0, i64 %[[R1]]
-// LLVM: }
-
-// OGCG-LABEL: _Z17test_builtin_ffsll
-// OGCG: %[[INPUT:.+]] = load i64, ptr %{{.+}}, align 8
-// OGCG-NEXT: %[[CTZ:.+]] = call i64 @llvm.cttz.i64(i64 %[[INPUT]], i1 true)
-// OGCG-NEXT: %[[R1:.+]] = add i64 %[[CTZ]], 1
-// OGCG-NEXT: %[[IS_ZERO:.+]] = icmp eq i64 %[[INPUT]], 0
-// OGCG-NEXT: %{{.+}} = select i1 %[[IS_ZERO]], i64 0, i64 %[[R1]]
-// OGCG: }
-
-int test_builtin_ffsll(long long x) {
- return __builtin_ffsll(x);
-}
-
-// CIR-LABEL: _Z18test_builtin_ffsllx
-// CIR: %{{.+}} = cir.ffs %{{.+}} : !s64i
-// CIR: }
-
-// LLVM-LABEL: _Z18test_builtin_ffsllx
-// LLVM: %[[INPUT:.+]] = load i64, ptr %{{.+}}, align 8
-// LLVM-NEXT: %[[CTZ:.+]] = call i64 @llvm.cttz.i64(i64 %[[INPUT]], i1 true)
-// LLVM-NEXT: %[[R1:.+]] = add i64 %[[CTZ]], 1
-// LLVM-NEXT: %[[IS_ZERO:.+]] = icmp eq i64 %[[INPUT]], 0
-// LLVM-NEXT: %{{.+}} = select i1 %[[IS_ZERO]], i64 0, i64 %[[R1]]
-// LLVM: }
-
-// OGCG-LABEL: _Z18test_builtin_ffsllx
-// OGCG: %[[INPUT:.+]] = load i64, ptr %{{.+}}, align 8
-// OGCG-NEXT: %[[CTZ:.+]] = call i64 @llvm.cttz.i64(i64 %[[INPUT]], i1 true)
-// OGCG-NEXT: %[[R1:.+]] = add i64 %[[CTZ]], 1
-// OGCG-NEXT: %[[IS_ZERO:.+]] = icmp eq i64 %[[INPUT]], 0
-// OGCG-NEXT: %{{.+}} = select i1 %[[IS_ZERO]], i64 0, i64 %[[R1]]
-// OGCG: }
-
-int test_builtin_parity(unsigned x) {
- return __builtin_parity(x);
-}
-
-// CIR-LABEL: _Z19test_builtin_parityj
-// CIR: [[TMP:%.+]] = cir.parity %{{.+}} : !u32i
-// CIR: {{%.+}} = cir.cast integral [[TMP]] : !u32i -> !s32i
-
-// LLVM-LABEL: _Z19test_builtin_parityj
-// LLVM: %[[X:.+]] = load i32, ptr %{{.+}}, align 4
-// LLVM-NEXT: %[[POPCNT:.+]] = call i32 @llvm.ctpop.i32(i32 %[[X]])
-// LLVM-NEXT: %{{.+}} = and i32 %[[POPCNT]], 1
-
-// OGCG-LABEL: _Z19test_builtin_parityj
-// OGCG: %[[X:.+]] = load i32, ptr %{{.+}}, align 4
-// OGCG-NEXT: %[[POPCNT:.+]] = call i32 @llvm.ctpop.i32(i32 %[[X]])
-// OGCG-NEXT: %{{.+}} = and i32 %[[POPCNT]], 1
-
-int test_builtin_parityl(unsigned long x) {
- return __builtin_parityl(x);
-}
-
-// CIR-LABEL: _Z20test_builtin_paritylm
-// CIR: [[TMP:%.+]] = cir.parity %{{.+}} : !u64i
-// CIR: {{%.+}} = cir.cast integral [[TMP]] : !u64i -> !s32i
-
-// LLVM-LABEL: _Z20test_builtin_paritylm
-// LLVM: %[[X:.+]] = load i64, ptr %{{.+}}, align 8
-// LLVM-NEXT: %[[POPCNT:.+]] = call i64 @llvm.ctpop.i64(i64 %[[X]])
-// LLVM-NEXT: %{{.+}} = and i64 %[[POPCNT]], 1
-
-// OGCG-LABEL: _Z20test_builtin_paritylm
-// OGCG: %[[X:.+]] = load i64, ptr %{{.+}}, align 8
-// OGCG-NEXT: %[[POPCNT:.+]] = call i64 @llvm.ctpop.i64(i64 %[[X]])
-// OGCG-NEXT: %{{.+}} = and i64 %[[POPCNT]], 1
-
-int test_builtin_parityll(unsigned long long x) {
- return __builtin_parityll(x);
-}
-
-// CIR-LABEL: _Z21test_builtin_paritylly
-// CIR: [[TMP:%.+]] = cir.parity %{{.+}} : !u64i
-// CIR: {{%.+}} = cir.cast integral [[TMP]] : !u64i -> !s32i
-
-// LLVM-LABEL: _Z21test_builtin_paritylly
-// LLVM: %[[X:.+]] = load i64, ptr %{{.+}}, align 8
-// LLVM-NEXT: %[[POPCNT:.+]] = call i64 @llvm.ctpop.i64(i64 %[[X]])
-// LLVM-NEXT: %{{.+}} = and i64 %[[POPCNT]], 1
-
-// OGCG-LABEL: _Z21test_builtin_paritylly
-// OGCG: %[[X:.+]] = load i64, ptr %{{.+}}, align 8
-// OGCG-NEXT: %[[POPCNT:.+]] = call i64 @llvm.ctpop.i64(i64 %[[X]])
-// OGCG-NEXT: %{{.+}} = and i64 %[[POPCNT]], 1
-
-int test_builtin_popcount(unsigned x) {
- return __builtin_popcount(x);
-}
-
-// CIR-LABEL: _Z21test_builtin_popcountj
-// CIR: [[TMP:%.+]] = cir.popcount %{{.+}} : !u32i
-// CIR: {{%.+}} = cir.cast integral [[TMP]] : !u32i -> !s32i
-
-// LLVM-LABEL: _Z21test_builtin_popcountj
-// LLVM: %{{.+}} = call i32 @llvm.ctpop.i32(i32 %{{.+}})
-
-// OGCG-LABEL: _Z21test_builtin_popcountj
-// OGCG: %{{.+}} = call i32 @llvm.ctpop.i32(i32 %{{.+}})
-
-int test_builtin_popcountl(unsigned long x) {
- return __builtin_popcountl(x);
-}
-
-// CIR-LABEL: _Z22test_builtin_popcountlm
-// CIR: [[TMP:%.+]] = cir.popcount %{{.+}} : !u64i
-// CIR: {{%.+}} = cir.cast integral [[TMP]] : !u64i -> !s32i
-
-// LLVM-LABEL: _Z22test_builtin_popcountlm
-// LLVM: %{{.+}} = call i64 @llvm.ctpop.i64(i64 %{{.+}})
-
-// OGCG-LABEL: _Z22test_builtin_popcountlm
-// OGCG: %{{.+}} = call i64 @llvm.ctpop.i64(i64 %{{.+}})
-
-int test_builtin_popcountll(unsigned long long x) {
- return __builtin_popcountll(x);
-}
-
-// CIR-LABEL: _Z23test_builtin_popcountlly
-// CIR: [[TMP:%.+]] = cir.popcount %{{.+}} : !u64i
-// CIR: {{%.+}} = cir.cast integral [[TMP]] : !u64i -> !s32i
-
-// LLVM-LABEL: _Z23test_builtin_popcountlly
-// LLVM: %{{.+}} = call i64 @llvm.ctpop.i64(i64 %{{.+}})
-
-// OGCG-LABEL: _Z23test_builtin_popcountlly
-// OGCG: %{{.+}} = call i64 @llvm.ctpop.i64(i64 %{{.+}})
-
-int test_builtin_popcountg(unsigned x) {
- return __builtin_popcountg(x);
-}
-
-// CIR-LABEL: _Z22test_builtin_popcountgj
-// CIR: [[TMP:%.+]] = cir.popcount %{{.+}} : !u32i
-// CIR: {{%.+}} = cir.cast integral [[TMP]] : !u32i -> !s32i
-
-// LLVM-LABEL: _Z22test_builtin_popcountgj
-// LLVM: %{{.+}} = call i32 @llvm.ctpop.i32(i32 %{{.+}})
-
-// OGCG-LABEL: _Z22test_builtin_popcountgj
-// OGCG: %{{.+}} = call i32 @llvm.ctpop.i32(i32 %{{.+}})
-
-unsigned char test_builtin_bitreverse8(unsigned char x) {
- return __builtin_bitreverse8(x);
-}
-
-// CIR-LABEL: @_Z24test_builtin_bitreverse8h
-// CIR: %{{.+}} = cir.bitreverse %{{.+}} : !u8i
-
-// LLVM-LABEL: @_Z24test_builtin_bitreverse8h
-// LLVM: %{{.+}} = call i8 @llvm.bitreverse.i8(i8 %{{.+}})
-
-// OGCG-LABEL: @_Z24test_builtin_bitreverse8h
-// OGCG: %{{.+}} = call i8 @llvm.bitreverse.i8(i8 %{{.+}})
-
-unsigned short test_builtin_bitreverse16(unsigned short x) {
- return __builtin_bitreverse16(x);
-}
-
-// CIR-LABEL: @_Z25test_builtin_bitreverse16t
-// CIR: %{{.+}} = cir.bitreverse %{{.+}} : !u16i
-
-// LLVM-LABEL: @_Z25test_builtin_bitreverse16t
-// LLVM: %{{.+}} = call i16 @llvm.bitreverse.i16(i16 %{{.+}})
-
-// OGCG-LABEL: @_Z25test_builtin_bitreverse16t
-// OGCG: %{{.+}} = call i16 @llvm.bitreverse.i16(i16 %{{.+}})
-
-unsigned test_builtin_bitreverse32(unsigned x) {
- return __builtin_bitreverse32(x);
-}
-
-// CIR-LABEL: @_Z25test_builtin_bitreverse32j
-// CIR: %{{.+}} = cir.bitreverse %{{.+}} : !u32i
-
-// LLVM-LABEL: @_Z25test_builtin_bitreverse32j
-// LLVM: %{{.+}} = call i32 @llvm.bitreverse.i32(i32 %{{.+}})
-
-// OGCG-LABEL: @_Z25test_builtin_bitreverse32j
-// OGCG: %{{.+}} = call i32 @llvm.bitreverse.i32(i32 %{{.+}})
-
-unsigned long long test_builtin_bitreverse64(unsigned long long x) {
- return __builtin_bitreverse64(x);
-}
-
-// CIR-LABEL: @_Z25test_builtin_bitreverse64y
-// CIR: %{{.+}} = cir.bitreverse %{{.+}} : !u64i
-
-// LLVM-LABEL: @_Z25test_builtin_bitreverse64y
-// LLVM: %{{.+}} = call i64 @llvm.bitreverse.i64(i64 %{{.+}})
-
-// OGCG-LABEL: @_Z25test_builtin_bitreverse64y
-// OGCG: %{{.+}} = call i64 @llvm.bitreverse.i64(i64 %{{.+}})
-
-unsigned short test_builtin_bswap16(unsigned short x) {
- return __builtin_bswap16(x);
-}
-
-// CIR-LABEL: @_Z20test_builtin_bswap16t
-// CIR: %{{.+}} = cir.byte_swap %{{.+}} : !u16i
-
-// LLVM-LABEL: @_Z20test_builtin_bswap16t
-// LLVM: %{{.+}} = call i16 @llvm.bswap.i16(i16 %{{.+}})
-
-// OGCG-LABEL: @_Z20test_builtin_bswap16t
-// OGCG: %{{.+}} = call i16 @llvm.bswap.i16(i16 %{{.+}})
-
-unsigned test_builtin_bswap32(unsigned x) {
- return __builtin_bswap32(x);
-}
-
-// CIR-LABEL: @_Z20test_builtin_bswap32j
-// CIR: %{{.+}} = cir.byte_swap %{{.+}} : !u32i
-
-// LLVM-LABEL: @_Z20test_builtin_bswap32j
-// LLVM: %{{.+}} = call i32 @llvm.bswap.i32(i32 %{{.+}})
-
-// OGCG-LABEL: @_Z20test_builtin_bswap32j
-// OGCG: %{{.+}} = call i32 @llvm.bswap.i32(i32 %{{.+}})
-
-unsigned long long test_builtin_bswap64(unsigned long long x) {
- return __builtin_bswap64(x);
-}
-
-// CIR-LABEL: @_Z20test_builtin_bswap64y
-// CIR: %{{.+}} = cir.byte_swap %{{.+}} : !u64i
-
-// LLVM-LABEL: @_Z20test_builtin_bswap64y
-// LLVM: %{{.+}} = call i64 @llvm.bswap.i64(i64 %{{.+}})
-
-// OGCG-LABEL: @_Z20test_builtin_bswap64y
-// OGCG: %{{.+}} = call i64 @llvm.bswap.i64(i64 %{{.+}})
-
-unsigned char test_builtin_rotateleft8(unsigned char x, unsigned char y) {
- return __builtin_rotateleft8(x, y);
-}
-
-// CIR-LABEL: @_Z24test_builtin_rotateleft8hh
-// CIR: %{{.+}} = cir.rotate left %{{.+}}, %{{.+}} : !u8i
-
-// LLVM-LABEL: @_Z24test_builtin_rotateleft8hh
-// LLVM: %[[INPUT:.+]] = load i8, ptr %{{.+}}, align 1
-// LLVM-NEXT: %[[AMOUNT:.+]] = load i8, ptr %{{.+}}, align 1
-// LLVM-NEXT: %{{.+}} = call i8 @llvm.fshl.i8(i8 %[[INPUT]], i8 %[[INPUT]], i8 %[[AMOUNT]])
-
-// OGCG-LABEL: @_Z24test_builtin_rotateleft8hh
-// OGCG: %[[INPUT:.+]] = load i8, ptr %{{.+}}, align 1
-// OGCG-NEXT: %[[AMOUNT:.+]] = load i8, ptr %{{.+}}, align 1
-// OGCG-NEXT: %{{.+}} = call i8 @llvm.fshl.i8(i8 %[[INPUT]], i8 %[[INPUT]], i8 %[[AMOUNT]])
-
-unsigned short test_builtin_rotateleft16(unsigned short x, unsigned short y) {
- return __builtin_rotateleft16(x, y);
-}
-
-// CIR-LABEL: @_Z25test_builtin_rotateleft16tt
-// CIR: %{{.+}} = cir.rotate left %{{.+}}, %{{.+}} : !u16i
-
-// LLVM-LABEL: @_Z25test_builtin_rotateleft16tt
-// LLVM: %[[INPUT:.+]] = load i16, ptr %{{.+}}, align 2
-// LLVM-NEXT: %[[AMOUNT:.+]] = load i16, ptr %{{.+}}, align 2
-// LLVM-NEXT: %{{.+}} = call i16 @llvm.fshl.i16(i16 %[[INPUT]], i16 %[[INPUT]], i16 %[[AMOUNT]])
-
-// OGCG-LABEL: @_Z25test_builtin_rotateleft16tt
-// OGCG: %[[INPUT:.+]] = load i16, ptr %{{.+}}, align 2
-// OGCG-NEXT: %[[AMOUNT:.+]] = load i16, ptr %{{.+}}, align 2
-// OGCG-NEXT: %{{.+}} = call i16 @llvm.fshl.i16(i16 %[[INPUT]], i16 %[[INPUT]], i16 %[[AMOUNT]])
-
-unsigned test_builtin_rotateleft32(unsigned x, unsigned y) {
- return __builtin_rotateleft32(x, y);
-}
-
-// CIR-LABEL: @_Z25test_builtin_rotateleft32jj
-// CIR: %{{.+}} = cir.rotate left %{{.+}}, %{{.+}} : !u32i
-
-// LLVM-LABEL: @_Z25test_builtin_rotateleft32jj
-// LLVM: %[[INPUT:.+]] = load i32, ptr %{{.+}}, align 4
-// LLVM-NEXT: %[[AMOUNT:.+]] = load i32, ptr %{{.+}}, align 4
-// LLVM-NEXT: %{{.+}} = call i32 @llvm.fshl.i32(i32 %[[INPUT]], i32 %[[INPUT]], i32 %[[AMOUNT]])
-
-// OGCG-LABEL: @_Z25test_builtin_rotateleft32jj
-// OGCG: %[[INPUT:.+]] = load i32, ptr %{{.+}}, align 4
-// OGCG-NEXT: %[[AMOUNT:.+]] = load i32, ptr %{{.+}}, align 4
-// OGCG-NEXT: %{{.+}} = call i32 @llvm.fshl.i32(i32 %[[INPUT]], i32 %[[INPUT]], i32 %[[AMOUNT]])
-
-unsigned long long test_builtin_rotateleft64(unsigned long long x,
- unsigned long long y) {
- return __builtin_rotateleft64(x, y);
-}
-
-// CIR-LABEL: @_Z25test_builtin_rotateleft64yy
-// CIR: %{{.+}} = cir.rotate left %{{.+}}, %{{.+}} : !u64i
-
-// LLVM-LABEL: @_Z25test_builtin_rotateleft64yy
-// LLVM: %[[INPUT:.+]] = load i64, ptr %{{.+}}, align 8
-// LLVM-NEXT: %[[AMOUNT:.+]] = load i64, ptr %{{.+}}, align 8
-// LLVM-NEXT: %{{.+}} = call i64 @llvm.fshl.i64(i64 %[[INPUT]], i64 %[[INPUT]], i64 %[[AMOUNT]])
-
-// OGCG-LABEL: @_Z25test_builtin_rotateleft64yy
-// OGCG: %[[INPUT:.+]] = load i64, ptr %{{.+}}, align 8
-// OGCG-NEXT: %[[AMOUNT:.+]] = load i64, ptr %{{.+}}, align 8
-// OGCG-NEXT: %{{.+}} = call i64 @llvm.fshl.i64(i64 %[[INPUT]], i64 %[[INPUT]], i64 %[[AMOUNT]])
-
-unsigned char test_builtin_rotateright8(unsigned char x, unsigned char y) {
- return __builtin_rotateright8(x, y);
-}
-
-// CIR-LABEL: @_Z25test_builtin_rotateright8hh
-// CIR: %{{.+}} = cir.rotate right %{{.+}}, %{{.+}} : !u8i
-
-// LLVM-LABEL: @_Z25test_builtin_rotateright8hh
-// LLVM: %[[INPUT:.+]] = load i8, ptr %{{.+}}, align 1
-// LLVM-NEXT: %[[AMOUNT:.+]] = load i8, ptr %{{.+}}, align 1
-// LLVM-NEXT: %{{.+}} = call i8 @llvm.fshr.i8(i8 %[[INPUT]], i8 %[[INPUT]], i8 %[[AMOUNT]])
-
-// OGCG-LABEL: @_Z25test_builtin_rotateright8hh
-// OGCG: %[[INPUT:.+]] = load i8, ptr %{{.+}}, align 1
-// OGCG-NEXT: %[[AMOUNT:.+]] = load i8, ptr %{{.+}}, align 1
-// OGCG-NEXT: %{{.+}} = call i8 @llvm.fshr.i8(i8 %[[INPUT]], i8 %[[INPUT]], i8 %[[AMOUNT]])
-
-unsigned short test_builtin_rotateright16(unsigned short x, unsigned short y) {
- return __builtin_rotateright16(x, y);
-}
-
-// CIR-LABEL: @_Z26test_builtin_rotateright16tt
-// CIR: %{{.+}} = cir.rotate right %{{.+}}, %{{.+}} : !u16i
-
-// LLVM-LABEL: @_Z26test_builtin_rotateright16tt
-// LLVM: %[[INPUT:.+]] = load i16, ptr %{{.+}}, align 2
-// LLVM-NEXT: %[[AMOUNT:.+]] = load i16, ptr %{{.+}}, align 2
-// LLVM-NEXT: %{{.+}} = call i16 @llvm.fshr.i16(i16 %[[INPUT]], i16 %[[INPUT]], i16 %[[AMOUNT]])
-
-// OGCG-LABEL: @_Z26test_builtin_rotateright16tt
-// OGCG: %[[INPUT:.+]] = load i16, ptr %{{.+}}, align 2
-// OGCG-NEXT: %[[AMOUNT:.+]] = load i16, ptr %{{.+}}, align 2
-// OGCG-NEXT: %{{.+}} = call i16 @llvm.fshr.i16(i16 %[[INPUT]], i16 %[[INPUT]], i16 %[[AMOUNT]])
-
-unsigned test_builtin_rotateright32(unsigned x, unsigned y) {
- return __builtin_rotateright32(x, y);
-}
-
-// CIR-LABEL: @_Z26test_builtin_rotateright32jj
-// CIR: %{{.+}} = cir.rotate right %{{.+}}, %{{.+}} : !u32i
-
-// LLVM-LABEL: @_Z26test_builtin_rotateright32jj
-// LLVM: %[[INPUT:.+]] = load i32, ptr %{{.+}}, align 4
-// LLVM-NEXT: %[[AMOUNT:.+]] = load i32, ptr %{{.+}}, align 4
-// LLVM-NEXT: %{{.+}} = call i32 @llvm.fshr.i32(i32 %[[INPUT]], i32 %[[INPUT]], i32 %[[AMOUNT]])
-
-// OGCG-LABEL: @_Z26test_builtin_rotateright32jj
-// OGCG: %[[INPUT:.+]] = load i32, ptr %{{.+}}, align 4
-// OGCG-NEXT: %[[AMOUNT:.+]] = load i32, ptr %{{.+}}, align 4
-// OGCG-NEXT: %{{.+}} = call i32 @llvm.fshr.i32(i32 %[[INPUT]], i32 %[[INPUT]], i32 %[[AMOUNT]])
-
-unsigned long long test_builtin_rotateright64(unsigned long long x,
- unsigned long long y) {
- return __builtin_rotateright64(x, y);
-}
-
-// CIR-LABEL: @_Z26test_builtin_rotateright64yy
-// CIR: %{{.+}} = cir.rotate right %{{.+}}, %{{.+}} : !u64i
-
-// LLVM-LABEL: @_Z26test_builtin_rotateright64yy
-// LLVM: %[[INPUT:.+]] = load i64, ptr %{{.+}}, align 8
-// LLVM-NEXT: %[[AMOUNT:.+]] = load i64, ptr %{{.+}}, align 8
-// LLVM-NEXT: %{{.+}} = call i64 @llvm.fshr.i64(i64 %[[INPUT]], i64 %[[INPUT]], i64 %[[AMOUNT]])
-
-// OGCG-LABEL: @_Z26test_builtin_rotateright64yy
-// OGCG: %[[INPUT:.+]] = load i64, ptr %{{.+}}, align 8
-// OGCG-NEXT: %[[AMOUNT:.+]] = load i64, ptr %{{.+}}, align 8
-// OGCG-NEXT: %{{.+}} = call i64 @llvm.fshr.i64(i64 %[[INPUT]], i64 %[[INPUT]], i64 %[[AMOUNT]])
diff --git a/clang/test/CIR/CodeGen/builtin_call.cpp b/clang/test/CIR/CodeGen/builtin_call.cpp
deleted file mode 100644
index a08a784..0000000
--- a/clang/test/CIR/CodeGen/builtin_call.cpp
+++ /dev/null
@@ -1,308 +0,0 @@
-// RUN: %clang_cc1 -std=c++11 -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 -std=c++11 -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 -std=c++11 -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
-
-constexpr extern int cx_var = __builtin_is_constant_evaluated();
-
-// CIR: cir.global {{.*}} @cx_var = #cir.int<1> : !s32i
-// LLVM: @cx_var = {{.*}} i32 1
-// OGCG: @cx_var = {{.*}} i32 1
-
-constexpr extern float cx_var_single = __builtin_huge_valf();
-
-// CIR: cir.global {{.*}} @cx_var_single = #cir.fp<0x7F800000> : !cir.float
-// LLVM: @cx_var_single = {{.*}} float 0x7FF0000000000000
-// OGCG: @cx_var_single = {{.*}} float 0x7FF0000000000000
-
-constexpr extern long double cx_var_ld = __builtin_huge_vall();
-
-// CIR: cir.global {{.*}} @cx_var_ld = #cir.fp<0x7FFF8000000000000000> : !cir.long_double<!cir.f80>
-// LLVM: @cx_var_ld = {{.*}} x86_fp80 0xK7FFF8000000000000000
-// OGCG: @cx_var_ld = {{.*}} x86_fp80 0xK7FFF8000000000000000
-
-int is_constant_evaluated() {
- return __builtin_is_constant_evaluated();
-}
-
-// CIR: cir.func{{.*}} @_Z21is_constant_evaluatedv() -> !s32i
-// CIR: %[[ZERO:.+]] = cir.const #cir.int<0>
-
-// LLVM: define {{.*}}i32 @_Z21is_constant_evaluatedv()
-// LLVM: %[[MEM:.+]] = alloca i32
-// LLVM: store i32 0, ptr %[[MEM]]
-// LLVM: %[[RETVAL:.+]] = load i32, ptr %[[MEM]]
-// LLVM: ret i32 %[[RETVAL]]
-// LLVM: }
-
-// OGCG: define {{.*}}i32 @_Z21is_constant_evaluatedv()
-// OGCG: ret i32 0
-// OGCG: }
-
-long double constant_fp_builtin_ld() {
- return __builtin_fabsl(-0.1L);
-}
-
-// CIR: cir.func{{.*}} @_Z22constant_fp_builtin_ldv() -> !cir.long_double<!cir.f80>
-// CIR: %[[PONE:.+]] = cir.const #cir.fp<1.000000e-01> : !cir.long_double<!cir.f80>
-
-// LLVM: define {{.*}}x86_fp80 @_Z22constant_fp_builtin_ldv()
-// LLVM: %[[MEM:.+]] = alloca x86_fp80
-// LLVM: store x86_fp80 0xK3FFBCCCCCCCCCCCCCCCD, ptr %[[MEM]]
-// LLVM: %[[RETVAL:.+]] = load x86_fp80, ptr %[[MEM]]
-// LLVM: ret x86_fp80 %[[RETVAL]]
-// LLVM: }
-
-// OGCG: define {{.*}}x86_fp80 @_Z22constant_fp_builtin_ldv()
-// OGCG: ret x86_fp80 0xK3FFBCCCCCCCCCCCCCCCD
-// OGCG: }
-
-float constant_fp_builtin_single() {
- return __builtin_fabsf(-0.1f);
-}
-
-// CIR: cir.func{{.*}} @_Z26constant_fp_builtin_singlev() -> !cir.float
-// CIR: %[[PONE:.+]] = cir.const #cir.fp<1.000000e-01> : !cir.float
-
-// LLVM: define {{.*}}float @_Z26constant_fp_builtin_singlev()
-// LLVM: %[[MEM:.+]] = alloca float
-// LLVM: store float 0x3FB99999A0000000, ptr %[[MEM]]
-// LLVM: %[[RETVAL:.+]] = load float, ptr %[[MEM]]
-// LLVM: ret float %[[RETVAL]]
-// LLVM: }
-
-// OGCG: define {{.*}}float @_Z26constant_fp_builtin_singlev()
-// OGCG: ret float 0x3FB99999A0000000
-// OGCG: }
-
-void library_builtins() {
- __builtin_printf(nullptr);
- __builtin_abort();
-}
-
-// CIR: cir.func{{.*}} @_Z16library_builtinsv()
-// CIR: %[[NULL:.+]] = cir.const #cir.ptr<null> : !cir.ptr<!s8i>
-// CIR: cir.call @printf(%[[NULL]]) nothrow : (!cir.ptr<!s8i>) -> !s32i
-// CIR: cir.call @abort() nothrow : () -> ()
-
-// LLVM: define{{.*}} void @_Z16library_builtinsv()
-// LLVM: call i32 (ptr, ...) @printf(ptr null)
-// LLVM: call void @abort()
-
-// OGCG: define{{.*}} void @_Z16library_builtinsv()
-// OGCG: call i32 (ptr, ...) @printf(ptr noundef null)
-// OGCG: call void @abort()
-
-void assume(bool arg) {
- __builtin_assume(arg);
-}
-
-// CIR: cir.func{{.*}} @_Z6assumeb
-// CIR: cir.assume %{{.+}} : !cir.bool
-// CIR: }
-
-// LLVM: define {{.*}}void @_Z6assumeb
-// LLVM: call void @llvm.assume(i1 %{{.+}})
-// LLVM: }
-
-// OGCG: define {{.*}}void @_Z6assumeb
-// OGCG: call void @llvm.assume(i1 %{{.+}})
-// OGCG: }
-
-void *assume_aligned(void *ptr) {
- return __builtin_assume_aligned(ptr, 16);
-}
-
-// CIR: @_Z14assume_alignedPv
-// CIR: %{{.+}} = cir.assume_aligned %{{.+}} alignment 16 : !cir.ptr<!void>
-// CIR: }
-
-// LLVM: @_Z14assume_alignedPv
-// LLVM: call void @llvm.assume(i1 true) [ "align"(ptr %{{.+}}, i64 16) ]
-// LLVM: }
-
-// OGCG: @_Z14assume_alignedPv
-// OGCG: call void @llvm.assume(i1 true) [ "align"(ptr %{{.+}}, i64 16) ]
-// OGCG: }
-
-void *assume_aligned_misalignment(void *ptr, unsigned misalignment) {
- return __builtin_assume_aligned(ptr, 16, misalignment);
-}
-
-// CIR: @_Z27assume_aligned_misalignmentPvj
-// CIR: %{{.+}} = cir.assume_aligned %{{.+}} alignment 16[offset %{{.+}} : !u64i] : !cir.ptr<!void>
-// CIR: }
-
-// LLVM: @_Z27assume_aligned_misalignmentPvj
-// LLVM: call void @llvm.assume(i1 true) [ "align"(ptr %{{.+}}, i64 16, i64 %{{.+}}) ]
-// LLVM: }
-
-// OGCG: @_Z27assume_aligned_misalignmentPvj
-// OGCG: call void @llvm.assume(i1 true) [ "align"(ptr %{{.+}}, i64 16, i64 %{{.+}}) ]
-// OGCG: }
-
-void assume_separate_storage(void *p1, void *p2) {
- __builtin_assume_separate_storage(p1, p2);
-}
-
-// CIR: cir.func{{.*}} @_Z23assume_separate_storagePvS_
-// CIR: cir.assume_separate_storage %{{.+}}, %{{.+}} : !cir.ptr<!void>
-// CIR: }
-
-// LLVM: define {{.*}}void @_Z23assume_separate_storagePvS_
-// LLVM: call void @llvm.assume(i1 true) [ "separate_storage"(ptr %{{.+}}, ptr %{{.+}}) ]
-// LLVM: }
-
-// OGCG: define {{.*}}void @_Z23assume_separate_storagePvS_
-// OGCG: call void @llvm.assume(i1 true) [ "separate_storage"(ptr %{{.+}}, ptr %{{.+}}) ]
-// OGCG: }
-
-void expect(int x, int y) {
- __builtin_expect(x, y);
-}
-
-// CIR-LABEL: cir.func{{.*}} @_Z6expectii
-// CIR: %[[X:.+]] = cir.load align(4) %{{.+}} : !cir.ptr<!s32i>, !s32i
-// CIR-NEXT: %[[X_LONG:.+]] = cir.cast integral %[[X]] : !s32i -> !s64i
-// CIR-NEXT: %[[Y:.+]] = cir.load align(4) %{{.+}} : !cir.ptr<!s32i>, !s32i
-// CIR-NEXT: %[[Y_LONG:.+]] = cir.cast integral %[[Y]] : !s32i -> !s64i
-// CIR-NEXT: %{{.+}} = cir.expect(%[[X_LONG]], %[[Y_LONG]]) : !s64i
-// CIR: }
-
-// LLVM-LABEL: define{{.*}} void @_Z6expectii
-// LLVM: %[[X:.+]] = load i32, ptr %{{.+}}, align 4
-// LLVM-NEXT: %[[X_LONG:.+]] = sext i32 %[[X]] to i64
-// LLVM-NEXT: %[[Y:.+]] = load i32, ptr %{{.+}}, align 4
-// LLVM-NEXT: %[[Y_LONG:.+]] = sext i32 %[[Y]] to i64
-// LLVM-NEXT: %{{.+}} = call i64 @llvm.expect.i64(i64 %[[X_LONG]], i64 %[[Y_LONG]])
-// LLVM: }
-
-void expect_prob(int x, int y) {
- __builtin_expect_with_probability(x, y, 0.25);
-}
-
-// CIR-LABEL: cir.func{{.*}} @_Z11expect_probii
-// CIR: %[[X:.+]] = cir.load align(4) %{{.+}} : !cir.ptr<!s32i>, !s32i
-// CIR-NEXT: %[[X_LONG:.+]] = cir.cast integral %[[X]] : !s32i -> !s64i
-// CIR-NEXT: %[[Y:.+]] = cir.load align(4) %{{.+}} : !cir.ptr<!s32i>, !s32i
-// CIR-NEXT: %[[Y_LONG:.+]] = cir.cast integral %[[Y]] : !s32i -> !s64i
-// CIR-NEXT: %{{.+}} = cir.expect(%[[X_LONG]], %[[Y_LONG]], 2.500000e-01) : !s64i
-// CIR: }
-
-// LLVM: define{{.*}} void @_Z11expect_probii
-// LLVM: %[[X:.+]] = load i32, ptr %{{.+}}, align 4
-// LLVM-NEXT: %[[X_LONG:.+]] = sext i32 %[[X]] to i64
-// LLVM-NEXT: %[[Y:.+]] = load i32, ptr %{{.+}}, align 4
-// LLVM-NEXT: %[[Y_LONG:.+]] = sext i32 %[[Y]] to i64
-// LLVM-NEXT: %{{.+}} = call i64 @llvm.expect.with.probability.i64(i64 %[[X_LONG]], i64 %[[Y_LONG]], double 2.500000e-01)
-// LLVM: }
-
-void unreachable() {
- __builtin_unreachable();
-}
-
-// CIR-LABEL: @_Z11unreachablev
-// CIR: cir.unreachable
-// CIR: }
-
-// LLVM-LABEL: @_Z11unreachablev
-// LLVM: unreachable
-// LLVM: }
-
-// OGCG-LABEL: @_Z11unreachablev
-// OGCG: unreachable
-// OGCG: }
-
-void f1();
-void unreachable2() {
- __builtin_unreachable();
- f1();
-}
-
-// CIR-LABEL: @_Z12unreachable2v
-// CIR: cir.unreachable
-// CIR-NEXT: ^{{.+}}:
-// CIR-NEXT: cir.call @_Z2f1v() : () -> ()
-// CIR: }
-
-// LLVM-LABEL: @_Z12unreachable2v
-// LLVM: unreachable
-// LLVM: {{.+}}:
-// LLVM-NEXT: call void @_Z2f1v()
-// LLVM: }
-
-// OGCG-LABEL: @_Z12unreachable2v
-// OGCG: unreachable
-
-void trap() {
- __builtin_trap();
-}
-
-// CIR-LABEL: @_Z4trapv
-// CIR: cir.trap
-// CIR: }
-
-// LLVM-LABEL: @_Z4trapv
-// LLVM: call void @llvm.trap()
-// LLVM: }
-
-// OGCG-LABEL: @_Z4trapv
-// OGCG: call void @llvm.trap()
-// OGCG: }
-
-void trap2() {
- __builtin_trap();
- f1();
-}
-
-// CIR-LABEL: @_Z5trap2v
-// CIR: cir.trap
-// CIR-NEXT: ^{{.+}}:
-// CIR-NEXT: cir.call @_Z2f1v() : () -> ()
-// CIR: }
-
-// LLVM-LABEL: @_Z5trap2v
-// LLVM: call void @llvm.trap()
-// LLVM-NEXT: unreachable
-// LLVM: {{.+}}:
-// LLVM-NEXT: call void @_Z2f1v()
-// LLVM: }
-
-// OGCG-LABEL: define{{.*}} void @_Z5trap2v
-// OGCG: call void @llvm.trap()
-// OGCG-NEXT: call void @_Z2f1v()
-// OGCG: ret void
-// OGCG: }
-
-void *test_alloca(unsigned long n) {
- return __builtin_alloca(n);
-}
-
-// CIR-LABEL: @_Z11test_allocam(
-// CIR: %{{.+}} = cir.alloca !u8i, !cir.ptr<!u8i>, %{{.+}} : !u64i, ["bi_alloca"]
-
-// LLVM-LABEL: @_Z11test_allocam(
-// LLVM: alloca i8, i64 %{{.+}}
-
-// OGCG-LABEL: @_Z11test_allocam(
-// OGCG: alloca i8, i64 %{{.+}}
-
-bool test_multiple_allocas(unsigned long n) {
- void *a = __builtin_alloca(n);
- void *b = __builtin_alloca(n);
- return a != b;
-}
-
-// CIR-LABEL: @_Z21test_multiple_allocasm(
-// CIR: %{{.+}} = cir.alloca !u8i, !cir.ptr<!u8i>, %{{.+}} : !u64i, ["bi_alloca"]
-// CIR: %{{.+}} = cir.alloca !u8i, !cir.ptr<!u8i>, %{{.+}} : !u64i, ["bi_alloca"]
-
-// LLVM-LABEL: @_Z21test_multiple_allocasm(
-// LLVM: alloca i8, i64 %{{.+}}
-// LLVM: alloca i8, i64 %{{.+}}
-
-// OGCG-LABEL: @_Z21test_multiple_allocasm(
-// OGCG: alloca i8, i64 %{{.+}}
-// OGCG: alloca i8, i64 %{{.+}}
diff --git a/clang/test/CIR/CodeGen/builtin_inline.c b/clang/test/CIR/CodeGen/builtin_inline.c
deleted file mode 100644
index 83a3ba6..0000000
--- a/clang/test/CIR/CodeGen/builtin_inline.c
+++ /dev/null
@@ -1,91 +0,0 @@
-// RUN: %clang_cc1 -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 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm -disable-llvm-passes %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 -emit-llvm -disable-llvm-passes %s -o %t.ll
-// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
-
-typedef unsigned long size_t;
-
-// Normal inline builtin declaration
-// When a builtin is redefined with extern inline + always_inline attributes,
-// the compiler creates a .inline version to avoid conflicts with the builtin
-
-extern inline __attribute__((always_inline)) __attribute__((gnu_inline))
-void *memcpy(void *a, const void *b, size_t c) {
- return __builtin_memcpy(a, b, c);
-}
-
-void *test_inline_builtin_memcpy(void *a, const void *b, size_t c) {
- return memcpy(a, b, c);
-}
-
-// CIR: cir.func internal private{{.*}}@memcpy.inline({{.*}}) -> !cir.ptr<!void> inline(always)
-
-// CIR-LABEL: @test_inline_builtin_memcpy(
-// CIR: cir.call @memcpy.inline(
-// CIR: }
-
-// LLVM: define internal ptr @memcpy.inline(ptr{{.*}}, ptr{{.*}}, i64{{.*}}) #{{[0-9]+}}
-
-// LLVM-LABEL: @test_inline_builtin_memcpy(
-// LLVM: call ptr @memcpy.inline(
-
-// OGCG-LABEL: @test_inline_builtin_memcpy(
-// OGCG: call ptr @memcpy.inline(
-
-// OGCG: define internal ptr @memcpy.inline(ptr{{.*}} %a, ptr{{.*}} %b, i64{{.*}} %c) #{{[0-9]+}}
-
-// Shadowing case
-// When a non-inline function definition shadows an inline builtin declaration,
-// the .inline version should be replaced with the regular function and removed.
-
-extern inline __attribute__((always_inline)) __attribute__((gnu_inline))
-void *memmove(void *a, const void *b, size_t c) {
- return __builtin_memmove(a, b, c);
-}
-
-void *memmove(void *a, const void *b, size_t c) {
- char *dst = (char *)a;
- const char *src = (const char *)b;
- if (dst < src) {
- for (size_t i = 0; i < c; i++) {
- dst[i] = src[i];
- }
- } else {
- for (size_t i = c; i > 0; i--) {
- dst[i-1] = src[i-1];
- }
- }
- return a;
-}
-
-void *test_shadowed_memmove(void *a, const void *b, size_t c) {
- return memmove(a, b, c);
-}
-
-// CIR: cir.func{{.*}}@memmove({{.*}}) -> !cir.ptr<!void>{{.*}}{
-// CIR-NOT: @memmove.inline
-
-// CIR-LABEL: @test_shadowed_memmove(
-// CIR: cir.call @memmove(
-// CIR-NOT: @memmove.inline
-// CIR: }
-
-// LLVM: define dso_local ptr @memmove(ptr{{.*}}, ptr{{.*}}, i64{{.*}}) #{{[0-9]+}}
-// LLVM-NOT: @memmove.inline
-
-// LLVM-LABEL: @test_shadowed_memmove(
-// TODO - this deviation from OGCG is expected until we implement the nobuiltin
-// attribute. See CIRGenFunction::emitDirectCallee
-// LLVM: call ptr @memmove(
-// LLVM-NOT: @memmove.inline
-// LLVM: }
-
-// OGCG: define dso_local ptr @memmove(ptr{{.*}} %a, ptr{{.*}} %b, i64{{.*}} %c) #{{[0-9]+}}
-// OGCG-NOT: @memmove.inline
-
-// OGCG-LABEL: @test_shadowed_memmove(
-// OGCG: call void @llvm.memmove.p0.p0.i64(
-// OGCG-NOT: @memmove.inline
-// OGCG: }
diff --git a/clang/test/CIR/CodeGen/builtin_prefetch.c b/clang/test/CIR/CodeGen/builtin_prefetch.c
deleted file mode 100644
index cfe85b9..0000000
--- a/clang/test/CIR/CodeGen/builtin_prefetch.c
+++ /dev/null
@@ -1,43 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-cir %s -o - | FileCheck %s -check-prefix=CIR
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s -check-prefix=LLVM
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s -check-prefix=OGCG
-
-void foo(void *a) {
- __builtin_prefetch(a); // rw=0, locality=3
- __builtin_prefetch(a, 0); // rw=0, locality=3
- __builtin_prefetch(a, 1); // rw=1, locality=3
- __builtin_prefetch(a, 1, 1); // rw=1, locality=1
-}
-
-// CIR-LABEL: cir.func dso_local @foo(
-// CIR: %[[ALLOCA:.*]] = cir.alloca !cir.ptr<!void>
-// CIR: cir.store %arg0, %[[ALLOCA]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
-// CIR: %[[P1:.*]] = cir.load{{.*}} %[[ALLOCA]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
-// CIR: cir.prefetch read locality(3) %[[P1]] : !cir.ptr<!void>
-// CIR: %[[P2:.*]] = cir.load{{.*}} %[[ALLOCA]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
-// CIR: cir.prefetch read locality(3) %[[P2]] : !cir.ptr<!void>
-// CIR: %[[P3:.*]] = cir.load{{.*}} %[[ALLOCA]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
-// CIR: cir.prefetch write locality(3) %[[P3]] : !cir.ptr<!void>
-// CIR: %[[P4:.*]] = cir.load{{.*}} %[[ALLOCA]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
-// CIR: cir.prefetch write locality(1) %[[P4]] : !cir.ptr<!void>
-// CIR: cir.return
-
-// LLVM-LABEL: define dso_local void @foo(
-// LLVM: [[ALLOCA:%.*]] = alloca ptr, i64 1
-// LLVM: store ptr {{.*}}, ptr [[ALLOCA]]
-// LLVM: [[LP1:%.*]] = load ptr, ptr [[ALLOCA]]
-// LLVM: call void @llvm.prefetch.p0(ptr [[LP1]], i32 0, i32 3, i32 1)
-// LLVM: [[LP2:%.*]] = load ptr, ptr [[ALLOCA]]
-// LLVM: call void @llvm.prefetch.p0(ptr [[LP2]], i32 0, i32 3, i32 1)
-// LLVM: [[LP3:%.*]] = load ptr, ptr [[ALLOCA]]
-// LLVM: call void @llvm.prefetch.p0(ptr [[LP3]], i32 1, i32 3, i32 1)
-// LLVM: [[LP4:%.*]] = load ptr, ptr [[ALLOCA]]
-// LLVM: call void @llvm.prefetch.p0(ptr [[LP4]], i32 1, i32 1, i32 1)
-// LLVM: ret void
-
-// OGCG-LABEL: define dso_local void @foo(ptr
-// OGCG: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 3, i32 1)
-// OGCG: call void @llvm.prefetch.p0(ptr {{.*}}, i32 0, i32 3, i32 1)
-// OGCG: call void @llvm.prefetch.p0(ptr {{.*}}, i32 1, i32 3, i32 1)
-// OGCG: call void @llvm.prefetch.p0(ptr {{.*}}, i32 1, i32 1, i32 1)
-// OGCG: ret void
diff --git a/clang/test/CIR/CodeGen/builtin_printf.cpp b/clang/test/CIR/CodeGen/builtin_printf.cpp
deleted file mode 100644
index 7200df1..0000000
--- a/clang/test/CIR/CodeGen/builtin_printf.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-// RUN: %clang_cc1 -std=c++11 -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 -std=c++11 -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 -std=c++11 -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
-
-// CIR: cir.global "private" constant cir_private dso_local @".str" = #cir.const_array<"%s\00" : !cir.array<!s8i x 3>> : !cir.array<!s8i x 3>
-// CIR: cir.global "private" constant cir_private dso_local @".str.1" = #cir.const_array<"%s %d\0A\00" : !cir.array<!s8i x 7>> : !cir.array<!s8i x 7>
-// LLVM: @.str = private constant [3 x i8] c"%s\00"
-// LLVM: @.str.1 = private constant [7 x i8] c"%s %d\0A\00"
-// OGCG: @.str = private unnamed_addr constant [3 x i8] c"%s\00"
-// OGCG: @.str.1 = private unnamed_addr constant [7 x i8] c"%s %d\0A\00"
-
-void func(char const * const str, int i) {
- __builtin_printf(nullptr);
- __builtin_printf("%s", str);
- __builtin_printf("%s %d\n", str, i);
-}
-
-// CIR: cir.func{{.*}} @printf(!cir.ptr<!s8i>, ...) -> !s32i
-
-// CIR: cir.func{{.*}} @_Z4funcPKci(%[[arg0:.+]]: !cir.ptr<!s8i>{{.*}}, %[[arg1:.+]]: !s32i
-// CIR: %[[str_ptr:.+]] = cir.alloca !cir.ptr<!s8i>, !cir.ptr<!cir.ptr<!s8i>>, ["str", init, const]
-// CIR: %[[i_ptr:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init]
-// CIR: cir.store %[[arg0]], %[[str_ptr]] : !cir.ptr<!s8i>, !cir.ptr<!cir.ptr<!s8i>>
-// CIR: cir.store %[[arg1]], %[[i_ptr]] : !s32i, !cir.ptr<!s32i>
-// CIR: %[[null_ptr:.+]] = cir.const #cir.ptr<null> : !cir.ptr<!s8i>
-// CIR: %[[printf_result1:.+]] = cir.call @printf(%[[null_ptr]]) nothrow : (!cir.ptr<!s8i>) -> !s32i
-// CIR: %[[str_fmt_global:.+]] = cir.get_global @".str" : !cir.ptr<!cir.array<!s8i x 3>>
-// CIR: %[[str_fmt_ptr:.+]] = cir.cast array_to_ptrdecay %[[str_fmt_global]] : !cir.ptr<!cir.array<!s8i x 3>> -> !cir.ptr<!s8i>
-// CIR: %[[str_val:.+]] = cir.load{{.*}} %[[str_ptr]] : !cir.ptr<!cir.ptr<!s8i>>, !cir.ptr<!s8i>
-// CIR: %[[printf_result2:.+]] = cir.call @printf(%[[str_fmt_ptr]], %[[str_val]]) nothrow : (!cir.ptr<!s8i>, !cir.ptr<!s8i>) -> !s32i
-// CIR: %[[full_fmt_global:.+]] = cir.get_global @".str.1" : !cir.ptr<!cir.array<!s8i x 7>>
-// CIR: %[[full_fmt_ptr:.+]] = cir.cast array_to_ptrdecay %[[full_fmt_global]] : !cir.ptr<!cir.array<!s8i x 7>> -> !cir.ptr<!s8i>
-// CIR: %[[str_val2:.+]] = cir.load{{.*}} %[[str_ptr]] : !cir.ptr<!cir.ptr<!s8i>>, !cir.ptr<!s8i>
-// CIR: %[[i_val:.+]] = cir.load{{.*}} %[[i_ptr]] : !cir.ptr<!s32i>, !s32i
-// CIR: %[[printf_result3:.+]] = cir.call @printf(%[[full_fmt_ptr]], %[[str_val2]], %[[i_val]]) nothrow : (!cir.ptr<!s8i>, !cir.ptr<!s8i>, !s32i) -> !s32i
-// CIR: cir.return
-
-// LLVM: define{{.*}} void @_Z4funcPKci(ptr %[[arg0:.+]], i32 %[[arg1:.+]])
-// LLVM: %[[str_ptr:.+]] = alloca ptr
-// LLVM: %[[i_ptr:.+]] = alloca i32
-// LLVM: store ptr %[[arg0]], ptr %[[str_ptr]]{{.*}}
-// LLVM: store i32 %[[arg1]], ptr %[[i_ptr]]{{.*}}
-// LLVM: %[[printf_result1:.+]] = call i32 (ptr, ...) @printf(ptr null)
-// LLVM: %[[str_val:.+]] = load ptr, ptr %[[str_ptr]]{{.*}}
-// LLVM: %[[printf_result2:.+]] = call i32 (ptr, ...) @printf(ptr @.str, ptr %[[str_val]])
-// LLVM: %[[str_val2:.+]] = load ptr, ptr %[[str_ptr]]{{.*}}
-// LLVM: %[[i_val:.+]] = load i32, ptr %[[i_ptr]]{{.*}}
-// LLVM: %[[printf_result3:.+]] = call i32 (ptr, ...) @printf(ptr @.str.1, ptr %[[str_val2]], i32 %[[i_val]])
-// LLVM: ret void
-
-// OGCG: define{{.*}} void @_Z4funcPKci(ptr noundef %[[arg0:.+]], i32 noundef %[[arg1:.+]])
-// OGCG: %[[str_ptr:.+]] = alloca ptr
-// OGCG: %[[i_ptr:.+]] = alloca i32
-// OGCG: store ptr %[[arg0]], ptr %[[str_ptr]]{{.*}}
-// OGCG: store i32 %[[arg1]], ptr %[[i_ptr]]{{.*}}
-// OGCG: %[[printf_result1:.+]] = call i32 (ptr, ...) @printf(ptr noundef null)
-// OGCG: %[[str_val:.+]] = load ptr, ptr %[[str_ptr]]{{.*}}
-// OGCG: %[[printf_result2:.+]] = call i32 (ptr, ...) @printf(ptr noundef @.str, ptr noundef %[[str_val]])
-// OGCG: %[[str_val2:.+]] = load ptr, ptr %[[str_ptr]]{{.*}}
-// OGCG: %[[i_val:.+]] = load i32, ptr %[[i_ptr]]{{.*}}
-// OGCG: %[[printf_result3:.+]] = call i32 (ptr, ...) @printf(ptr noundef @.str.1, ptr noundef %[[str_val2]], i32 noundef %[[i_val]])
-// OGCG: ret void
diff --git a/clang/test/CIR/CodeGen/builtins-elementwise.c b/clang/test/CIR/CodeGen/builtins-elementwise.c
deleted file mode 100644
index f64080b..0000000
--- a/clang/test/CIR/CodeGen/builtins-elementwise.c
+++ /dev/null
@@ -1,118 +0,0 @@
-// RUN: %clang_cc1 -triple aarch64-none-linux-android24 -Wno-unused-value -fclangir -emit-cir %s -o %t.cir
-// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
-// RUN: %clang_cc1 -triple aarch64-none-linux-android24 -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 aarch64-none-linux-android24 -Wno-unused-value -emit-llvm %s -o %t.ll
-// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
-
-typedef int vint4 __attribute__((ext_vector_type(4)));
-typedef float vfloat4 __attribute__((ext_vector_type(4)));
-typedef double vdouble4 __attribute__((ext_vector_type(4)));
-
-void test_builtin_elementwise_acos(float f, double d, vfloat4 vf4,
- vdouble4 vd4) {
- // CIR-LABEL: test_builtin_elementwise_acos
- // LLVM-LABEL: test_builtin_elementwise_acos
- // OGCG-LABEL: test_builtin_elementwise_acos
-
- // CIR: %{{.*}} = cir.acos %{{.*}} : !cir.float
- // LLVM: %{{.*}} = call float @llvm.acos.f32(float %{{.*}})
- // OGCG: %{{.*}} = call float @llvm.acos.f32(float %{{.*}})
- f = __builtin_elementwise_acos(f);
-
- // CIR: %{{.*}} = cir.acos %{{.*}} : !cir.double
- // LLVM: %{{.*}} = call double @llvm.acos.f64(double %{{.*}})
- // OGCG: %{{.*}} = call double @llvm.acos.f64(double %{{.*}})
- d = __builtin_elementwise_acos(d);
-
- // CIR: %{{.*}} = cir.acos %{{.*}} : !cir.vector<4 x !cir.float>
- // LLVM: %{{.*}} = call <4 x float> @llvm.acos.v4f32(<4 x float> %{{.*}})
- // OGCG: %{{.*}} = call <4 x float> @llvm.acos.v4f32(<4 x float> %{{.*}})
- vf4 = __builtin_elementwise_acos(vf4);
-
- // CIR: %{{.*}} = cir.acos %{{.*}} : !cir.vector<4 x !cir.double>
- // LLVM: %{{.*}} = call <4 x double> @llvm.acos.v4f64(<4 x double> %{{.*}})
- // OGCG: %{{.*}} = call <4 x double> @llvm.acos.v4f64(<4 x double> %{{.*}})
- vd4 = __builtin_elementwise_acos(vd4);
-}
-
-void test_builtin_elementwise_asin(float f, double d, vfloat4 vf4,
- vdouble4 vd4) {
- // CIR-LABEL: test_builtin_elementwise_asin
- // LLVM-LABEL: test_builtin_elementwise_asin
- // OGCG-LABEL: test_builtin_elementwise_asin
-
- // CIR: %{{.*}} = cir.asin %{{.*}} : !cir.float
- // LLVM: %{{.*}} = call float @llvm.asin.f32(float %{{.*}})
- // OGCG: %{{.*}} = call float @llvm.asin.f32(float %{{.*}})
- f = __builtin_elementwise_asin(f);
-
- // CIR: %{{.*}} = cir.asin %{{.*}} : !cir.double
- // LLVM: %{{.*}} = call double @llvm.asin.f64(double %{{.*}})
- // OGCG: %{{.*}} = call double @llvm.asin.f64(double %{{.*}})
- d = __builtin_elementwise_asin(d);
-
- // CIR: %{{.*}} = cir.asin %{{.*}} : !cir.vector<4 x !cir.float>
- // LLVM: %{{.*}} = call <4 x float> @llvm.asin.v4f32(<4 x float> %{{.*}})
- // OGCG: %{{.*}} = call <4 x float> @llvm.asin.v4f32(<4 x float> %{{.*}})
- vf4 = __builtin_elementwise_asin(vf4);
-
- // CIR: %{{.*}} = cir.asin %{{.*}} : !cir.vector<4 x !cir.double>
- // LLVM: %{{.*}} = call <4 x double> @llvm.asin.v4f64(<4 x double> %{{.*}})
- // OGCG: %{{.*}} = call <4 x double> @llvm.asin.v4f64(<4 x double> %{{.*}})
- vd4 = __builtin_elementwise_asin(vd4);
-}
-
-void test_builtin_elementwise_atan(float f, double d, vfloat4 vf4,
- vdouble4 vd4) {
- // CIR-LABEL: test_builtin_elementwise_atan
- // LLVM-LABEL: test_builtin_elementwise_atan
- // OGCG-LABEL: test_builtin_elementwise_atan
-
- // CIR: %{{.*}} = cir.atan %{{.*}} : !cir.float
- // LLVM: %{{.*}} = call float @llvm.atan.f32(float %{{.*}})
- // OGCG: %{{.*}} = call float @llvm.atan.f32(float %{{.*}})
- f = __builtin_elementwise_atan(f);
-
- // CIR: %{{.*}} = cir.atan %{{.*}} : !cir.double
- // LLVM: %{{.*}} = call double @llvm.atan.f64(double %{{.*}})
- // OGCG: %{{.*}} = call double @llvm.atan.f64(double %{{.*}})
- d = __builtin_elementwise_atan(d);
-
- // CIR: %{{.*}} = cir.atan %{{.*}} : !cir.vector<4 x !cir.float>
- // LLVM: %{{.*}} = call <4 x float> @llvm.atan.v4f32(<4 x float> %{{.*}})
- // OGCG: %{{.*}} = call <4 x float> @llvm.atan.v4f32(<4 x float> %{{.*}})
- vf4 = __builtin_elementwise_atan(vf4);
-
- // CIR: %{{.*}} = cir.atan %{{.*}} : !cir.vector<4 x !cir.double>
- // LLVM: %{{.*}} = call <4 x double> @llvm.atan.v4f64(<4 x double> %{{.*}})
- // OGCG: %{{.*}} = call <4 x double> @llvm.atan.v4f64(<4 x double> %{{.*}})
- vd4 = __builtin_elementwise_atan(vd4);
-}
-
-void test_builtin_elementwise_cos(float f, double d, vfloat4 vf4,
- vdouble4 vd4) {
- // CIR-LABEL: test_builtin_elementwise_cos
- // LLVM-LABEL: test_builtin_elementwise_cos
- // OGCG-LABEL: test_builtin_elementwise_cos
-
- // CIR: {{%.*}} = cir.cos {{%.*}} : !cir.float
- // LLVM: {{%.*}} = call float @llvm.cos.f32(float {{%.*}})
- // OGCG: {{%.*}} = call float @llvm.cos.f32(float {{%.*}})
- f = __builtin_elementwise_cos(f);
-
- // CIR: {{%.*}} = cir.cos {{%.*}} : !cir.double
- // LLVM: {{%.*}} = call double @llvm.cos.f64(double {{%.*}})
- // OGCG: {{%.*}} = call double @llvm.cos.f64(double {{%.*}})
- d = __builtin_elementwise_cos(d);
-
- // CIR: {{%.*}} = cir.cos {{%.*}} : !cir.vector<4 x !cir.float>
- // LLVM: {{%.*}} = call <4 x float> @llvm.cos.v4f32(<4 x float> {{%.*}})
- // OGCG: {{%.*}} = call <4 x float> @llvm.cos.v4f32(<4 x float> {{%.*}})
- vf4 = __builtin_elementwise_cos(vf4);
-
- // CIR: {{%.*}} = cir.cos {{%.*}} : !cir.vector<4 x !cir.double>
- // LLVM: {{%.*}} = call <4 x double> @llvm.cos.v4f64(<4 x double> {{%.*}})
- // OGCG: {{%.*}} = call <4 x double> @llvm.cos.v4f64(<4 x double> {{%.*}})
- vd4 = __builtin_elementwise_cos(vd4);
-}
diff --git a/clang/test/CIR/CodeGen/builtins-floating-point.c b/clang/test/CIR/CodeGen/builtins-floating-point.c
deleted file mode 100644
index 193cc172d..0000000
--- a/clang/test/CIR/CodeGen/builtins-floating-point.c
+++ /dev/null
@@ -1,20 +0,0 @@
-// RUN: %clang_cc1 -triple aarch64-none-linux-android24 -Wno-unused-value -fclangir -emit-cir %s -o %t.cir
-// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
-// RUN: %clang_cc1 -triple aarch64-none-linux-android24 -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 aarch64-none-linux-android24 -Wno-unused-value -emit-llvm %s -o %t.ll
-// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
-
-float cosf(float f) {
- return __builtin_cosf(f);
- // CHECK: %{{.*}} = cir.cos {{.*}} : !cir.float
- // LLVM: %{{.*}} = call float @llvm.cos.f32(float %{{.*}})
- // OGCG: %{{.*}} = call float @llvm.cos.f32(float %{{.*}})
-}
-
-double cos(double f) {
- return __builtin_cos(f);
- // CIR: {{.+}} = cir.cos {{.+}} : !cir.double
- // LLVM: %{{.*}} = call double @llvm.cos.f64(double %{{.*}})
- // OGCG: %{{.*}} = call double @llvm.cos.f64(double %{{.*}})
-}
diff --git a/clang/test/CIR/CodeGen/builtins.cpp b/clang/test/CIR/CodeGen/builtins.cpp
deleted file mode 100644
index 0e43480..0000000
--- a/clang/test/CIR/CodeGen/builtins.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-// 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
-
-double fabs(double x) {
- return __builtin_fabs(x);
-}
-
-// CIR: {{.*}} = cir.fabs {{.*}} : !cir.double
-// LLVM: {{.*}} = call double @llvm.fabs.f64(double {{.*}})
-// OGCG: {{.*}} = call double @llvm.fabs.f64(double {{.*}})
-
-extern "C" void *test_return_address(void) {
- return __builtin_return_address(1);
-
- // CIR-LABEL: test_return_address
- // CIR: [[ARG:%.*]] = cir.const #cir.int<1> : !u32i
- // CIR: {{%.*}} = cir.return_address([[ARG]])
-
- // LLVM-LABEL: @test_return_address
- // LLVM: {{%.*}} = call ptr @llvm.returnaddress(i32 1)
-
- // OGCG-LABEL: @test_return_address
- // OGCG: {{%.*}} = call ptr @llvm.returnaddress(i32 1)
-}
-
-extern "C" void *test_frame_address(void) {
- return __builtin_frame_address(1);
-
- // CIR-LABEL: test_frame_address
- // CIR: [[ARG:%.*]] = cir.const #cir.int<1> : !u32i
- // CIR: {{%.*}} = cir.frame_address([[ARG]])
-
- // LLVM-LABEL: @test_frame_address
- // LLVM: {{%.*}} = call ptr @llvm.frameaddress.p0(i32 1)
-
- // OGCG-LABEL: @test_frame_address
- // OGCG: {{%.*}} = call ptr @llvm.frameaddress.p0(i32 1)
-}
diff --git a/clang/test/CIR/CodeGen/call.c b/clang/test/CIR/CodeGen/call.c
index d780e37..35d977f 100644
--- a/clang/test/CIR/CodeGen/call.c
+++ b/clang/test/CIR/CodeGen/call.c
@@ -130,7 +130,7 @@ int f12(void) {
// OGCG: %{{.+}} = call i32 @f10(i32 noundef 1) #[[ATTR0:.+]]
// OGCG-NEXT: %{{.+}} = call i32 @f11(i32 noundef 2) #[[ATTR1:.+]]
-// LLVM: attributes #[[ATTR0]] = { nounwind willreturn memory(read, errnomem: none) }
+// LLVM: attributes #[[ATTR0]] = { nounwind willreturn memory(read) }
// LLVM: attributes #[[ATTR1]] = { nounwind willreturn memory(none) }
// OGCG: attributes #[[ATTR0]] = { nounwind willreturn memory(read) }
diff --git a/clang/test/CIR/CodeGen/complex-compound-assignment.cpp b/clang/test/CIR/CodeGen/complex-compound-assignment.cpp
index a5070f5..f2dbb3cc 100644
--- a/clang/test/CIR/CodeGen/complex-compound-assignment.cpp
+++ b/clang/test/CIR/CodeGen/complex-compound-assignment.cpp
@@ -237,18 +237,18 @@ void foo4() {
// CXX_CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["a"]
// CXX_CIR: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["b"]
// CXX_CIR: %[[C_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["c", init]
-// CXX_CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
-// CXX_CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[B_ADDR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
+// CXX_CIR: %[[TMP_A:.*]] = cir.load volatile {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
+// CXX_CIR: %[[TMP_B:.*]] = cir.load volatile {{.*}} %[[B_ADDR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
// CXX_CIR: %[[RESULT:.*]] = cir.complex.add %[[TMP_B]], %[[TMP_A]] : !cir.complex<!s32i>
-// CXX_CIR: cir.store{{.*}} %[[RESULT]], %[[B_ADDR]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>
-// CXX_CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[B_ADDR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
+// CXX_CIR: cir.store volatile {{.*}} %[[RESULT]], %[[B_ADDR]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>
+// CXX_CIR: %[[TMP_B:.*]] = cir.load volatile {{.*}} %[[B_ADDR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
// CXX_CIR: cir.store{{.*}} %[[TMP_B]], %[[C_ADDR]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>
// CXX_LLVM: %[[A_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4
// CXX_LLVM: %[[B_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4
// CXX_LLVM: %[[C_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4
-// CXX_LLVM: %[[TMP_A:.*]] = load { i32, i32 }, ptr %[[A_ADDR]], align 4
-// CXX_LLVM: %[[TMP_B:.*]] = load { i32, i32 }, ptr %[[B_ADDR]], align 4
+// CXX_LLVM: %[[TMP_A:.*]] = load volatile { i32, i32 }, ptr %[[A_ADDR]], align 4
+// CXX_LLVM: %[[TMP_B:.*]] = load volatile { i32, i32 }, ptr %[[B_ADDR]], align 4
// CXX_LLVM: %[[B_REAL:.*]] = extractvalue { i32, i32 } %[[TMP_B]], 0
// CXX_LLVM: %[[B_IMAG:.*]] = extractvalue { i32, i32 } %[[TMP_B]], 1
// CXX_LLVM: %[[A_REAL:.*]] = extractvalue { i32, i32 } %[[TMP_A]], 0
@@ -257,8 +257,8 @@ void foo4() {
// CXX_LLVM: %[[ADD_IMAG:.*]] = add i32 %[[B_IMAG]], %[[A_IMAG]]
// CXX_LLVM: %[[TMP_RESULT:.*]] = insertvalue { i32, i32 } poison, i32 %[[ADD_REAL]], 0
// CXX_LLVM: %[[RESULT:.*]] = insertvalue { i32, i32 } %[[TMP_RESULT]], i32 %[[ADD_IMAG]], 1
-// CXX_LLVM: store { i32, i32 } %[[RESULT]], ptr %[[B_ADDR]], align 4
-// CXX_LLVM: %[[TMP_B:.*]] = load { i32, i32 }, ptr %[[B_ADDR]], align 4
+// CXX_LLVM: store volatile { i32, i32 } %[[RESULT]], ptr %[[B_ADDR]], align 4
+// CXX_LLVM: %[[TMP_B:.*]] = load volatile { i32, i32 }, ptr %[[B_ADDR]], align 4
// CXX_LLVM: store { i32, i32 } %[[TMP_B]], ptr %[[C_ADDR]], align 4
// CXX_OGCG: %[[A_ADDR:.*]] = alloca { i32, i32 }, align 4
diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp
index 3fb78dc..82c9f2d 100644
--- a/clang/test/CIR/CodeGen/complex.cpp
+++ b/clang/test/CIR/CodeGen/complex.cpp
@@ -1495,3 +1495,185 @@ void calling_function_that_return_complex() {
// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1
// OGCG: store float %[[RESULT_REAL]], ptr %[[A_REAL_PTR]], align 4
// OGCG: store float %[[RESULT_IMAG]], ptr %[[A_IMAG_PTR]], align 4
+
+void imag_literal_gnu_extension() {
+ float _Complex a = 3.0fi;
+ double _Complex b = 3.0i;
+ int _Complex c = 3i;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a", init]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["b", init]
+// CIR: %[[C_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["c", init]
+// CIR: %[[COMPLEX_A:.*]] = cir.const #cir.const_complex<#cir.fp<0.000000e+00> : !cir.float, #cir.fp<3.000000e+00> : !cir.float> : !cir.complex<!cir.float>
+// CIR: cir.store{{.*}} %[[COMPLEX_A]], %[[A_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
+// CIR: %[[COMPLEX_B:.*]] = cir.const #cir.const_complex<#cir.fp<0.000000e+00> : !cir.double, #cir.fp<3.000000e+00> : !cir.double> : !cir.complex<!cir.double>
+// CIR: cir.store{{.*}} %[[COMPLEX_B]], %[[B_ADDR]] : !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>
+// CIR: %[[COMPLEX_C:.*]] = cir.const #cir.const_complex<#cir.int<0> : !s32i, #cir.int<3> : !s32i> : !cir.complex<!s32i>
+// CIR: cir.store{{.*}} %[[COMPLEX_C]], %[[C_ADDR]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>
+
+// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4
+// LLVM: %[[B_ADDR:.*]] = alloca { double, double }, i64 1, align 8
+// LLVM: %[[C_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4
+// LLVM: store { float, float } { float 0.000000e+00, float 3.000000e+00 }, ptr %[[A_ADDR]], align 4
+// LLVM: store { double, double } { double 0.000000e+00, double 3.000000e+00 }, ptr %[[B_ADDR]], align 8
+// LLVM: store { i32, i32 } { i32 0, i32 3 }, ptr %[[C_ADDR]], align 4
+
+// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4
+// OGCG: %[[B_ADDR:.*]] = alloca { double, double }, align 8
+// OGCG: %[[C_ADDR:.*]] = alloca { i32, i32 }, align 4
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0
+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1
+// OGCG: store float 0.000000e+00, ptr %[[A_REAL_PTR]], align 4
+// OGCG: store float 3.000000e+00, ptr %[[A_IMAG_PTR]], align 4
+// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 0
+// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 1
+// OGCG: store double 0.000000e+00, ptr %[[B_REAL_PTR]], align 8
+// OGCG: store double 3.000000e+00, ptr %[[B_IMAG_PTR]], align 8
+// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[C_ADDR]], i32 0, i32 0
+// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[C_ADDR]], i32 0, i32 1
+// OGCG: store i32 0, ptr %[[C_REAL_PTR]], align 4
+// OGCG: store i32 3, ptr %[[C_IMAG_PTR]], align 4
+
+void load_store_volatile() {
+ volatile double _Complex a;
+ volatile double _Complex b;
+ a = b;
+
+ volatile int _Complex c;
+ volatile int _Complex d;
+ c = d;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["a"]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["b"]
+// CIR: %[[C_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["c"]
+// CIR: %[[D_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["d"]
+// CIR: %[[TMP_B:.*]] = cir.load volatile {{.*}} %[[B_ADDR]] : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>
+// CIR: cir.store volatile {{.*}} %[[TMP_B]], %[[A_ADDR]] : !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>
+// CIR: %[[TMP_D:.*]] = cir.load volatile {{.*}} %[[D_ADDR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
+// CIR: cir.store volatile {{.*}} %[[TMP_D]], %[[C_ADDR]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>
+
+// LLVM: %[[A_ADDR:.*]] = alloca { double, double }, i64 1, align 8
+// LLVM: %[[B_ADDR:.*]] = alloca { double, double }, i64 1, align 8
+// LLVM: %[[C_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4
+// LLVM: %[[D_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4
+// LLVM: %[[TMP_B:.*]] = load volatile { double, double }, ptr %[[B_ADDR]], align 8
+// LLVM: store volatile { double, double } %[[TMP_B]], ptr %[[A_ADDR]], align 8
+// LLVM: %[[TMP_D:.*]] = load volatile { i32, i32 }, ptr %[[D_ADDR]], align 4
+// LLVM: store volatile { i32, i32 } %[[TMP_D]], ptr %[[C_ADDR]], align 4
+
+// OGCG: %[[A_ADDR:.*]] = alloca { double, double }, align 8
+// OGCG: %[[B_ADDR:.*]] = alloca { double, double }, align 8
+// OGCG: %[[C_ADDR:.*]] = alloca { i32, i32 }, align 4
+// OGCG: %[[D_ADDR:.*]] = alloca { i32, i32 }, align 4
+// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 0
+// OGCG: %[[B_REAL:.*]] = load volatile double, ptr %[[B_REAL_PTR]], align 8
+// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 1
+// OGCG: %[[B_IMAG:.*]] = load volatile double, ptr %[[B_IMAG_PTR]], align 8
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 0
+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 1
+// OGCG: store volatile double %[[B_REAL]], ptr %[[A_REAL_PTR]], align 8
+// OGCG: store volatile double %[[B_IMAG]], ptr %[[A_IMAG_PTR]], align 8
+// OGCG: %[[D_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[D_ADDR]], i32 0, i32 0
+// OGCG: %[[D_REAL:.*]] = load volatile i32, ptr %[[D_REAL_PTR]], align 4
+// OGCG: %[[D_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[D_ADDR]], i32 0, i32 1
+// OGCG: %[[D_IMAG:.*]] = load volatile i32, ptr %[[D_IMAG_PTR]], align 4
+// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[C_ADDR]], i32 0, i32 0
+// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[C_ADDR]], i32 0, i32 1
+// OGCG: store volatile i32 %[[D_REAL]], ptr %[[C_REAL_PTR]], align 4
+// OGCG: store volatile i32 %[[D_IMAG]], ptr %[[C_IMAG_PTR]], align 4
+
+
+void load_store_volatile_2() {
+ volatile double _Complex av;
+ double _Complex a;
+ av = a;
+
+ double _Complex b;
+ volatile double _Complex bv;
+ b = bv;
+
+ int _Complex c;
+ volatile int _Complex cv;
+ c = cv;
+
+ volatile int _Complex dv;
+ int _Complex d;
+ dv = d;
+}
+
+// CIR: %[[AV_ADDR:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["av"]
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["a"]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["b"]
+// CIR: %[[BV_ADDR:.*]] = cir.alloca !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>, ["bv"]
+// CIR: %[[C_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["c"]
+// CIR: %[[CV_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["cv"]
+// CIR: %[[DV_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["dv"]
+// CIR: %[[D_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["d"]
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>
+// CIR: cir.store volatile {{.*}} %[[TMP_A]], %[[AV_ADDR]] : !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>
+// CIR: %[[TMP_BV:.*]] = cir.load volatile {{.*}} %[[BV_ADDR]] : !cir.ptr<!cir.complex<!cir.double>>, !cir.complex<!cir.double>
+// CIR: cir.store {{.*}} %[[TMP_BV]], %[[B_ADDR]] : !cir.complex<!cir.double>, !cir.ptr<!cir.complex<!cir.double>>
+// CIR: %[[TMP_CV:.*]] = cir.load volatile {{.*}} %[[CV_ADDR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
+// CIR: cir.store {{.*}} %[[TMP_CV]], %[[C_ADDR]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>
+// CIR: %[[TMP_D:.*]] = cir.load {{.*}} %[[D_ADDR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
+// CIR: cir.store volatile {{.*}} %[[TMP_D]], %[[DV_ADDR]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>
+
+// LLVM: %[[AV_ADDR:.*]] = alloca { double, double }, i64 1, align 8
+// LLVM: %[[A_ADDR:.*]] = alloca { double, double }, i64 1, align 8
+// LLVM: %[[B_ADDR:.*]] = alloca { double, double }, i64 1, align 8
+// LLVM: %[[BV_ADDR:.*]] = alloca { double, double }, i64 1, align 8
+// LLVM: %[[C_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4
+// LLVM: %[[CV_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4
+// LLVM: %[[DV_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4
+// LLVM: %[[D_ADDR:.*]] = alloca { i32, i32 }, i64 1, align 4
+// LLVM: %[[TMP_A:.*]] = load { double, double }, ptr %[[A_ADDR]], align 8
+// LLVM: store volatile { double, double } %[[TMP_A]], ptr %[[AV_ADDR]], align 8
+// LLVM: %[[TMP_BV:.*]] = load volatile { double, double }, ptr %[[BV_ADDR]], align 8
+// LLVM: store { double, double } %[[TMP_BV]], ptr %[[B_ADDR]], align 8
+// LLVM: %[[TMP_CV:.*]] = load volatile { i32, i32 }, ptr %[[CV_ADDR]], align 4
+// LLVM: store { i32, i32 } %[[TMP_CV]], ptr %[[C_ADDR]], align 4
+// LLVM: %[[TMP_D:.*]] = load { i32, i32 }, ptr %[[D_ADDR]], align 4
+// LLVM: store volatile { i32, i32 } %[[TMP_D]], ptr %[[DV_ADDR]], align 4
+
+// OGCG: %[[AV_ADDR:.*]] = alloca { double, double }, align 8
+// OGCG: %[[A_ADDR:.*]] = alloca { double, double }, align 8
+// OGCG: %[[B_ADDR:.*]] = alloca { double, double }, align 8
+// OGCG: %[[BV_ADDR:.*]] = alloca { double, double }, align 8
+// OGCG: %[[C_ADDR:.*]] = alloca { i32, i32 }, align 4
+// OGCG: %[[CV_ADDR:.*]] = alloca { i32, i32 }, align 4
+// OGCG: %[[DV_ADDR:.*]] = alloca { i32, i32 }, align 4
+// OGCG: %[[D_ADDR:.*]] = alloca { i32, i32 }, align 4
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 0
+// OGCG: %[[A_REAL:.*]] = load double, ptr %[[A_REAL_PTR]], align 8
+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[A_ADDR]], i32 0, i32 1
+// OGCG: %[[A_IMAG:.*]] = load double, ptr %[[A_IMAG_PTR]], align 8
+// OGCG: %[[AV_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[AV_ADDR]], i32 0, i32 0
+// OGCG: %[[AV_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[AV_ADDR]], i32 0, i32 1
+// OGCG: store volatile double %[[A_REAL]], ptr %[[AV_REAL_PTR]], align 8
+// OGCG: store volatile double %[[A_IMAG]], ptr %[[AV_IMAG_PTR]], align 8
+// OGCG: %[[BV_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[BV_ADDR]], i32 0, i32 0
+// OGCG: %[[BV_REAL:.*]] = load volatile double, ptr %[[BV_REAL_PTR]], align 8
+// OGCG: %[[BV_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[BV_ADDR]], i32 0, i32 1
+// OGCG: %[[BV_IMAG:.*]] = load volatile double, ptr %[[BV_IMAG_PTR]], align 8
+// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 0
+// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { double, double }, ptr %[[B_ADDR]], i32 0, i32 1
+// OGCG: store double %[[BV_REAL]], ptr %[[B_REAL_PTR]], align 8
+// OGCG: store double %[[BV_IMAG]], ptr %[[B_IMAG_PTR]], align 8
+// OGCG: %[[CV_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[CV_ADDR]], i32 0, i32 0
+// OGCG: %[[CV_REAL:.*]] = load volatile i32, ptr %[[CV_REAL_PTR]], align 4
+// OGCG: %[[CV_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[CV_ADDR]], i32 0, i32 1
+// OGCG: %[[CV_IMAG:.*]] = load volatile i32, ptr %[[CV_IMAG_PTR]], align 4
+// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[C_ADDR]], i32 0, i32 0
+// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[C_ADDR]], i32 0, i32 1
+// OGCG: store i32 %[[CV_REAL]], ptr %[[C_REAL_PTR]], align 4
+// OGCG: store i32 %[[CV_IMAG]], ptr %[[C_IMAG_PTR]], align 4
+// OGCG: %[[D_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[D_ADDR]], i32 0, i32 0
+// OGCG: %[[D_REAL:.*]] = load i32, ptr %[[D_REAL_PTR]], align 4
+// OGCG: %[[D_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[D_ADDR]], i32 0, i32 1
+// OGCG: %[[D_IMAG:.*]] = load i32, ptr %[[D_IMAG_PTR]], align 4
+// OGCG: %[[DV_REAL_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[DV_ADDR]], i32 0, i32 0
+// OGCG: %[[DV_IMAG_PTR:.*]] = getelementptr inbounds nuw { i32, i32 }, ptr %[[DV_ADDR]], i32 0, i32 1
+// OGCG: store volatile i32 %[[D_REAL]], ptr %[[DV_REAL_PTR]], align 4
+// OGCG: store volatile i32 %[[D_IMAG]], ptr %[[DV_IMAG_PTR]], align 4
diff --git a/clang/test/CIR/CodeGen/compound_literal.cpp b/clang/test/CIR/CodeGen/compound_literal.cpp
index 30a1dc0..5219710 100644
--- a/clang/test/CIR/CodeGen/compound_literal.cpp
+++ b/clang/test/CIR/CodeGen/compound_literal.cpp
@@ -79,17 +79,17 @@ void foo3() {
}
// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a", init]
-// CIR: %[[CL_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, [".compoundliteral", init]
// CIR: %[[VEC:.*]] = cir.const #cir.const_vector<[#cir.int<10> : !s32i, #cir.int<20> : !s32i, #cir.int<30> : !s32i, #cir.int<40> : !s32i]> : !cir.vector<4 x !s32i>
-// CIR: cir.store{{.*}} %[[VEC]], %[[CL_ADDR]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
-// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[CL_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
-// CIR: cir.store{{.*}} %[[TMP]], %[[A_ADDR]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
+// CIR: cir.store{{.*}} %[[VEC]], %[[A_ADDR]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
// LLVM: %[[A_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
-// LLVM: %[[CL_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
-// LLVM: store <4 x i32> <i32 10, i32 20, i32 30, i32 40>, ptr %[[CL_ADDR]], align 16
-// LLVM: %[[TMP:.*]] = load <4 x i32>, ptr %[[CL_ADDR]], align 16
-// LLVM: store <4 x i32> %[[TMP]], ptr %[[A_ADDR]], align 16
+// LLVM: store <4 x i32> <i32 10, i32 20, i32 30, i32 40>, ptr %[[A_ADDR]], align 16
+
+// FIXME: OGCG emits a temporary compound literal in this case because it omits
+// vector types from the check for aggregate constants in
+// EmitAutoVarAlloca. This looks like an oversight in OGCG because the
+// code to emit a constant in EmitStoresForConstant specifically looks
+// for vector types in OGCG.
// OGCG: %[[A_ADDR:.*]] = alloca <4 x i32>, align 16
// OGCG: %[[CL_ADDR:.*]] = alloca <4 x i32>, align 16
@@ -107,19 +107,12 @@ void foo4() {
// CIR-LABEL: @_Z4foo4v
// CIR: %[[P:.*]] = cir.alloca !rec_Point, !cir.ptr<!rec_Point>, ["p", init]
-// CIR: %[[P_X:.*]] = cir.get_member %[[P]][0] {name = "x"}
-// CIR: %[[FIVE:.*]] = cir.const #cir.int<5> : !s32i
-// CIR: cir.store{{.*}} %[[FIVE]], %[[P_X]]
-// CIR: %[[P_Y:.*]] = cir.get_member %[[P]][1] {name = "y"}
-// CIR: %[[TEN:.*]] = cir.const #cir.int<10> : !s32i
-// CIR: cir.store{{.*}} %[[TEN]], %[[P_Y]]
+// CIR: %[[CONST:.*]] = cir.const #cir.const_record<{#cir.int<5> : !s32i, #cir.int<10> : !s32i}> : !rec_Point
+// CIR: cir.store{{.*}} %[[CONST]], %[[P]] : !rec_Point, !cir.ptr<!rec_Point>
// LLVM-LABEL: @_Z4foo4v
// LLVM: %[[P:.*]] = alloca %struct.Point
-// LLVM: %[[P_X:.*]] = getelementptr %struct.Point, ptr %[[P]], i32 0, i32 0
-// LLVM: store i32 5, ptr %[[P_X]]
-// LLVM: %[[P_Y:.*]] = getelementptr %struct.Point, ptr %[[P]], i32 0, i32 1
-// LLVM: store i32 10, ptr %[[P_Y]]
+// LLVM: store %struct.Point { i32 5, i32 10 }, ptr %[[P]], align 4
// OGCG-LABEL: @_Z4foo4v
// OGCG: %[[P:.*]] = alloca %struct.Point
diff --git a/clang/test/CIR/CodeGen/constant-inits.cpp b/clang/test/CIR/CodeGen/constant-inits.cpp
index d5a7bb9..ff0c0da 100644
--- a/clang/test/CIR/CodeGen/constant-inits.cpp
+++ b/clang/test/CIR/CodeGen/constant-inits.cpp
@@ -105,79 +105,79 @@ void function() {
// CIR-DAG: !rec_anon_struct = !cir.record<struct {!u8i, !u8i, !u8i, !u8i}>
// CIR-DAG: !rec_anon_struct1 = !cir.record<struct {!u8i, !u8i, !cir.array<!u8i x 2>}>
-// CIR-DAG: cir.global "private" internal dso_local @_ZZ8functionvE1e = #cir.zero : !rec_empty
-// CIR-DAG: cir.global "private" internal dso_local @_ZZ8functionvE1s = #cir.const_record<{#cir.int<0> : !s32i, #cir.int<-1> : !s32i}> : !rec_simple
-// CIR-DAG: cir.global "private" internal dso_local @_ZZ8functionvE2p1 = #cir.const_record<{#cir.int<10> : !s32i, #cir.int<20> : !s32i, #cir.const_array<[#cir.int<99> : !s8i, #cir.int<88> : !s8i, #cir.int<77> : !s8i]> : !cir.array<!s8i x 3>, #cir.int<40> : !s32i}> : !rec_Point
-// CIR-DAG: cir.global "private" internal dso_local @_ZZ8functionvE2p2 = #cir.const_record<{#cir.int<123> : !s8i, #cir.int<456> : !s32i}> : !rec_packed
-// CIR-DAG: cir.global "private" internal dso_local @_ZZ8functionvE3paa = #cir.const_record<{#cir.int<1> : !s16i, #cir.int<2> : !s8i, #cir.fp<3.000000e+00> : !cir.float, #cir.zero : !u8i}> : !rec_packed_and_aligned
+// CIR-DAG: cir.global "private" constant internal dso_local @_ZZ8functionvE1e = #cir.zero : !rec_empty
+// CIR-DAG: cir.global "private" constant internal dso_local @_ZZ8functionvE1s = #cir.const_record<{#cir.int<0> : !s32i, #cir.int<-1> : !s32i}> : !rec_simple
+// CIR-DAG: cir.global "private" constant internal dso_local @_ZZ8functionvE2p1 = #cir.const_record<{#cir.int<10> : !s32i, #cir.int<20> : !s32i, #cir.const_array<[#cir.int<99> : !s8i, #cir.int<88> : !s8i, #cir.int<77> : !s8i]> : !cir.array<!s8i x 3>, #cir.int<40> : !s32i}> : !rec_Point
+// CIR-DAG: cir.global "private" constant internal dso_local @_ZZ8functionvE2p2 = #cir.const_record<{#cir.int<123> : !s8i, #cir.int<456> : !s32i}> : !rec_packed
+// CIR-DAG: cir.global "private" constant internal dso_local @_ZZ8functionvE3paa = #cir.const_record<{#cir.int<1> : !s16i, #cir.int<2> : !s8i, #cir.fp<3.000000e+00> : !cir.float, #cir.zero : !u8i}> : !rec_packed_and_aligned
-// CIR-DAG: cir.global "private" internal dso_local @_ZZ8functionvE5array = #cir.const_array<[
+// CIR-DAG: cir.global "private" constant internal dso_local @_ZZ8functionvE5array = #cir.const_array<[
// CIR-DAG-SAME: #cir.const_record<{#cir.int<123> : !s32i, #cir.int<456> : !s32i, #cir.const_array<[#cir.int<11> : !s8i, #cir.int<22> : !s8i, #cir.int<33> : !s8i]> : !cir.array<!s8i x 3>, #cir.int<789> : !s32i}> : !rec_Point
// CIR-DAG-SAME: #cir.const_record<{#cir.int<10> : !s32i, #cir.int<20> : !s32i, #cir.zero : !cir.array<!s8i x 3>, #cir.int<40> : !s32i}> : !rec_Point
// CIR-DAG-SAME: ]> : !cir.array<!rec_Point x 2>
-// CIR-DAG: cir.global "private" internal dso_local @_ZZ8functionvE12simple_array = #cir.const_array<[
+// CIR-DAG: cir.global "private" constant internal dso_local @_ZZ8functionvE12simple_array = #cir.const_array<[
// CIR-DAG-SAME: #cir.const_record<{#cir.int<0> : !s32i, #cir.int<-1> : !s32i}> : !rec_simple,
// CIR-DAG-SAME: #cir.const_record<{#cir.int<1111> : !s32i, #cir.int<2222> : !s32i}> : !rec_simple,
// CIR-DAG-SAME: #cir.const_record<{#cir.int<0> : !s32i, #cir.int<-1> : !s32i}> : !rec_simple
// CIR-DAG-SAME: ]> : !cir.array<!rec_simple x 3>
-// CIR-DAG: cir.global "private" internal dso_local @_ZZ8functionvE12packed_array = #cir.const_array<[
+// CIR-DAG: cir.global "private" constant internal dso_local @_ZZ8functionvE12packed_array = #cir.const_array<[
// CIR-DAG-SAME: #cir.const_record<{#cir.int<123> : !s8i, #cir.int<456> : !s32i}> : !rec_packed,
// CIR-DAG-SAME: #cir.const_record<{#cir.int<123> : !s8i, #cir.int<456> : !s32i}> : !rec_packed
// CIR-DAG-SAME: ]> : !cir.array<!rec_packed x 2>
-// CIR-DAG: cir.global "private" internal dso_local @_ZZ8functionvE9paa_array = #cir.const_array<[
+// CIR-DAG: cir.global "private" constant internal dso_local @_ZZ8functionvE9paa_array = #cir.const_array<[
// CIR-DAG-SAME: #cir.const_record<{#cir.int<1> : !s16i, #cir.int<2> : !s8i, #cir.fp<3.000000e+00> : !cir.float, #cir.zero : !u8i}> : !rec_packed_and_aligned,
// CIR-DAG-SAME: #cir.zero : !rec_packed_and_aligned
// CIR-DAG-SAME: ]> : !cir.array<!rec_packed_and_aligned x 2>
-// CIR-DAG: cir.global "private" internal dso_local @_ZZ8functionvE6ba_bf1 = #cir.const_record<{
+// CIR-DAG: cir.global "private" constant internal dso_local @_ZZ8functionvE6ba_bf1 = #cir.const_record<{
// CIR-DAG-SAME: #cir.int<255> : !u8i,
// CIR-DAG-SAME: #cir.int<170> : !u8i,
// CIR-DAG-SAME: #cir.int<52> : !u8i,
// CIR-DAG-SAME: #cir.int<18> : !u8i
// CIR-DAG-SAME: }> : !rec_anon_struct
-// CIR-DAG: cir.global "private" internal dso_local @_ZZ8functionvE6ba_bf2 = #cir.const_record<{
+// CIR-DAG: cir.global "private" constant internal dso_local @_ZZ8functionvE6ba_bf2 = #cir.const_record<{
// CIR-DAG-SAME: #cir.int<255> : !u8i,
// CIR-DAG-SAME: #cir.int<127> : !u8i,
// CIR-DAG-SAME: #cir.const_array<[#cir.zero : !u8i, #cir.zero : !u8i]> : !cir.array<!u8i x 2>
// CIR-DAG-SAME: }> : !rec_anon_struct1
-// CIR-DAG: cir.global "private" internal dso_local @_ZZ8functionvE6ba_bf3 = #cir.const_record<{
+// CIR-DAG: cir.global "private" constant internal dso_local @_ZZ8functionvE6ba_bf3 = #cir.const_record<{
// CIR-DAG-SAME: #cir.int<42> : !u8i
// CIR-DAG-SAME: }> : !rec_single_byte_bitfield
-// CIR-DAG: cir.global "private" internal dso_local @_ZZ8functionvE5p_bf1 = #cir.const_record<{
+// CIR-DAG: cir.global "private" constant internal dso_local @_ZZ8functionvE5p_bf1 = #cir.const_record<{
// CIR-DAG-SAME: #cir.int<17> : !u8i,
// CIR-DAG-SAME: #cir.int<3> : !u8i,
// CIR-DAG-SAME: #cir.const_array<[#cir.zero : !u8i, #cir.zero : !u8i]> : !cir.array<!u8i x 2>
// CIR-DAG-SAME: }> : !rec_anon_struct1
-// CIR-DAG: cir.global "private" internal dso_local @_ZZ8functionvE5p_bf2 = #cir.const_record<{
+// CIR-DAG: cir.global "private" constant internal dso_local @_ZZ8functionvE5p_bf2 = #cir.const_record<{
// CIR-DAG-SAME: #cir.int<127> : !u8i,
// CIR-DAG-SAME: #cir.const_array<[#cir.zero : !u8i, #cir.zero : !u8i, #cir.zero : !u8i]> : !cir.array<!u8i x 3>
// CIR-DAG-SAME: }> : !rec_signed_partial_bitfields
-// CIR-DAG: cir.global "private" internal dso_local @_ZZ8functionvE5p_bf3 = #cir.const_record<{
+// CIR-DAG: cir.global "private" constant internal dso_local @_ZZ8functionvE5p_bf3 = #cir.const_record<{
// CIR-DAG-SAME: #cir.int<125> : !u8i
// CIR-DAG-SAME: }> : !rec_mixed_partial_bitfields
-// CIR-LABEL: cir.func dso_local @_Z8functionv()
+// CIR-LABEL: cir.func {{.*}} @_Z8functionv()
// CIR: cir.return
-// LLVM-DAG: @_ZZ8functionvE12packed_array = internal global [2 x %struct.packed] [%struct.packed <{ i8 123, i32 456 }>, %struct.packed <{ i8 123, i32 456 }>]
-// LLVM-DAG: @_ZZ8functionvE12simple_array = internal global [3 x %struct.simple] [%struct.simple { i32 0, i32 -1 }, %struct.simple { i32 1111, i32 2222 }, %struct.simple { i32 0, i32 -1 }]
-// LLVM-DAG: @_ZZ8functionvE1e = internal global %struct.empty zeroinitializer
-// LLVM-DAG: @_ZZ8functionvE1s = internal global %struct.simple { i32 0, i32 -1 }
-// LLVM-DAG: @_ZZ8functionvE2p1 = internal global %struct.Point { i32 10, i32 20, [3 x i8] c"cXM", i32 40 }
-// LLVM-DAG: @_ZZ8functionvE2p2 = internal global %struct.packed <{ i8 123, i32 456 }>
-// LLVM-DAG: @_ZZ8functionvE3paa = internal global %struct.packed_and_aligned <{ i16 1, i8 2, float 3.000000e+00, i8 0 }>
-// LLVM-DAG: @_ZZ8functionvE5array = internal global [2 x %struct.Point] [%struct.Point { i32 123, i32 456, [3 x i8] c"\0B\16!", i32 789 }, %struct.Point { i32 10, i32 20, [3 x i8] zeroinitializer, i32 40 }]
-// LLVM-DAG: @_ZZ8functionvE9paa_array = internal global [2 x %struct.packed_and_aligned] [%struct.packed_and_aligned <{ i16 1, i8 2, float 3.000000e+00, i8 0 }>, %struct.packed_and_aligned zeroinitializer]
-// LLVM-DAG: @_ZZ8functionvE6ba_bf1 = internal global { i8, i8, i8, i8 } { i8 -1, i8 -86, i8 52, i8 18 }
-// LLVM-DAG: @_ZZ8functionvE6ba_bf2 = internal global { i8, i8, [2 x i8] } { i8 -1, i8 127, [2 x i8] zeroinitializer }
-// LLVM-DAG: @_ZZ8functionvE6ba_bf3 = internal global %struct.single_byte_bitfield { i8 42 }
-// LLVM-DAG: @_ZZ8functionvE5p_bf1 = internal global { i8, i8, [2 x i8] } { i8 17, i8 3, [2 x i8] zeroinitializer }
-// LLVM-DAG: @_ZZ8functionvE5p_bf2 = internal global %struct.signed_partial_bitfields { i8 127, [3 x i8] zeroinitializer }
-// LLVM-DAG: @_ZZ8functionvE5p_bf3 = internal global %struct.mixed_partial_bitfields { i8 125 }
+// LLVM-DAG: @_ZZ8functionvE12packed_array = internal constant [2 x %struct.packed] [%struct.packed <{ i8 123, i32 456 }>, %struct.packed <{ i8 123, i32 456 }>]
+// LLVM-DAG: @_ZZ8functionvE12simple_array = internal constant [3 x %struct.simple] [%struct.simple { i32 0, i32 -1 }, %struct.simple { i32 1111, i32 2222 }, %struct.simple { i32 0, i32 -1 }]
+// LLVM-DAG: @_ZZ8functionvE1e = internal constant %struct.empty zeroinitializer
+// LLVM-DAG: @_ZZ8functionvE1s = internal constant %struct.simple { i32 0, i32 -1 }
+// LLVM-DAG: @_ZZ8functionvE2p1 = internal constant %struct.Point { i32 10, i32 20, [3 x i8] c"cXM", i32 40 }
+// LLVM-DAG: @_ZZ8functionvE2p2 = internal constant %struct.packed <{ i8 123, i32 456 }>
+// LLVM-DAG: @_ZZ8functionvE3paa = internal constant %struct.packed_and_aligned <{ i16 1, i8 2, float 3.000000e+00, i8 0 }>
+// LLVM-DAG: @_ZZ8functionvE5array = internal constant [2 x %struct.Point] [%struct.Point { i32 123, i32 456, [3 x i8] c"\0B\16!", i32 789 }, %struct.Point { i32 10, i32 20, [3 x i8] zeroinitializer, i32 40 }]
+// LLVM-DAG: @_ZZ8functionvE9paa_array = internal constant [2 x %struct.packed_and_aligned] [%struct.packed_and_aligned <{ i16 1, i8 2, float 3.000000e+00, i8 0 }>, %struct.packed_and_aligned zeroinitializer]
+// LLVM-DAG: @_ZZ8functionvE6ba_bf1 = internal constant { i8, i8, i8, i8 } { i8 -1, i8 -86, i8 52, i8 18 }
+// LLVM-DAG: @_ZZ8functionvE6ba_bf2 = internal constant { i8, i8, [2 x i8] } { i8 -1, i8 127, [2 x i8] zeroinitializer }
+// LLVM-DAG: @_ZZ8functionvE6ba_bf3 = internal constant %struct.single_byte_bitfield { i8 42 }
+// LLVM-DAG: @_ZZ8functionvE5p_bf1 = internal constant { i8, i8, [2 x i8] } { i8 17, i8 3, [2 x i8] zeroinitializer }
+// LLVM-DAG: @_ZZ8functionvE5p_bf2 = internal constant %struct.signed_partial_bitfields { i8 127, [3 x i8] zeroinitializer }
+// LLVM-DAG: @_ZZ8functionvE5p_bf3 = internal constant %struct.mixed_partial_bitfields { i8 125 }
// LLVM-LABEL: define{{.*}} void @_Z8functionv
// LLVM: ret void
diff --git a/clang/test/CIR/CodeGen/copy-constructor.cpp b/clang/test/CIR/CodeGen/copy-constructor.cpp
new file mode 100644
index 0000000..97c514a
--- /dev/null
+++ b/clang/test/CIR/CodeGen/copy-constructor.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -mconstructor-aliases -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 -mconstructor-aliases -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 -mconstructor-aliases -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
+
+struct HasScalarArrayMember {
+ int arr[2][2];
+ HasScalarArrayMember(const HasScalarArrayMember &);
+};
+
+HasScalarArrayMember::HasScalarArrayMember(const HasScalarArrayMember &) = default;
+
+// CIR-LABEL: cir.func {{.*}} @_ZN20HasScalarArrayMemberC2ERKS_(
+// CIR-NEXT: %[[THIS:.*]] = cir.alloca !cir.ptr<!rec_HasScalarArrayMember>
+// CIR-NEXT: %[[OTHER:.*]] = cir.alloca !cir.ptr<!rec_HasScalarArrayMember>
+// CIR-NEXT: cir.store %arg0, %[[THIS]]
+// CIR-NEXT: cir.store %arg1, %[[OTHER]]
+// CIR-NEXT: %[[THIS_LOAD:.*]] = cir.load{{.*}} %[[THIS]]
+// CIR-NEXT: %[[THIS_ARR:.*]] = cir.get_member %[[THIS_LOAD]][0] {name = "arr"}
+// CIR-NEXT: %[[OTHER_LOAD:.*]] = cir.load{{.*}} %[[OTHER]]
+// CIR-NEXT: %[[OTHER_ARR:.*]] = cir.get_member %[[OTHER_LOAD]][0] {name = "arr"}
+// CIR-NEXT: cir.copy %[[OTHER_ARR]] to %[[THIS_ARR]] : !cir.ptr<!cir.array<!cir.array<!s32i x 2> x 2>>
+// CIR-NEXT: cir.return
+
+// LLVM-LABEL: define {{.*}} @_ZN20HasScalarArrayMemberC2ERKS_(
+// LLVM-SAME: ptr %[[ARG0:.*]], ptr %[[ARG1:.*]])
+// LLVM-NEXT: %[[THIS:.*]] = alloca ptr
+// LLVM-NEXT: %[[OTHER:.*]] = alloca ptr
+// LLVM-NEXT: store ptr %[[ARG0]], ptr %[[THIS]]
+// LLVM-NEXT: store ptr %[[ARG1]], ptr %[[OTHER]]
+// LLVM-NEXT: %[[THIS_LOAD:.*]] = load ptr, ptr %[[THIS]]
+// LLVM-NEXT: %[[THIS_ARR:.*]] = getelementptr %struct.HasScalarArrayMember, ptr %[[THIS_LOAD]], i32 0, i32 0
+// LLVM-NEXT: %[[OTHER_LOAD:.*]] = load ptr, ptr %[[OTHER]]
+// LLVM-NEXT: %[[OTHER_ARR:.*]] = getelementptr %struct.HasScalarArrayMember, ptr %[[OTHER_LOAD]], i32 0, i32 0
+// LLVM-NEXT: call void @llvm.memcpy.p0.p0.i32(ptr %[[THIS_ARR]], ptr %[[OTHER_ARR]], i32 16, i1 false)
+// LLVM-NEXT: ret void
+
+// OGCG-LABEL: define {{.*}} @_ZN20HasScalarArrayMemberC2ERKS_(
+// OGCG-SAME: ptr {{.*}} %[[ARG0:.*]], ptr {{.*}} %[[ARG1:.*]])
+// OGCG-NEXT: entry:
+// OGCG-NEXT: %[[THIS:.*]] = alloca ptr
+// OGCG-NEXT: %[[OTHER:.*]] = alloca ptr
+// OGCG-NEXT: store ptr %[[ARG0]], ptr %[[THIS]]
+// OGCG-NEXT: store ptr %[[ARG1]], ptr %[[OTHER]]
+// OGCG-NEXT: %[[THIS_LOAD:.*]] = load ptr, ptr %[[THIS]]
+// OGCG-NEXT: %[[THIS_ARR:.*]] = getelementptr inbounds nuw %struct.HasScalarArrayMember, ptr %[[THIS_LOAD]], i32 0, i32 0
+// OGCG-NEXT: %[[OTHER_LOAD:.*]] = load ptr, ptr %[[OTHER]]
+// OGCG-NEXT: %[[OTHER_ARR:.*]] = getelementptr inbounds nuw %struct.HasScalarArrayMember, ptr %[[OTHER_LOAD]], i32 0, i32 0
+// OGCG-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr {{.*}} %[[THIS_ARR]], ptr {{.*}} %[[OTHER_ARR]], i64 16, i1 false)
+// OGCG-NEXT: ret void
diff --git a/clang/test/CIR/CodeGen/coro-task.cpp b/clang/test/CIR/CodeGen/coro-task.cpp
index 265325f..c6e21c9 100644
--- a/clang/test/CIR/CodeGen/coro-task.cpp
+++ b/clang/test/CIR/CodeGen/coro-task.cpp
@@ -36,6 +36,12 @@ struct suspend_never {
void await_resume() noexcept {}
};
+struct string {
+ int size() const;
+ string();
+ string(char const *s);
+};
+
} // namespace std
namespace folly {
@@ -101,6 +107,14 @@ co_invoke_fn co_invoke;
}} // namespace folly::coro
// CIR-DAG: ![[VoidTask:.*]] = !cir.record<struct "folly::coro::Task<void>" padded {!u8i}>
+// CIR-DAG: ![[IntTask:.*]] = !cir.record<struct "folly::coro::Task<int>" padded {!u8i}>
+// CIR-DAG: ![[VoidPromisse:.*]] = !cir.record<struct "folly::coro::Task<void>::promise_type" padded {!u8i}>
+// CIR-DAG: ![[IntPromisse:.*]] = !cir.record<struct "folly::coro::Task<int>::promise_type" padded {!u8i}>
+// CIR-DAG: ![[StdString:.*]] = !cir.record<struct "std::string" padded {!u8i}>
+// CIR-DAG: ![[CoroHandleVoid:.*]] = !cir.record<struct "std::coroutine_handle<void>" padded {!u8i}>
+// CIR-DAG: ![[CoroHandlePromiseVoid:rec_.*]] = !cir.record<struct "std::coroutine_handle<folly::coro::Task<void>::promise_type>" padded {!u8i}>
+// CIR-DAG: ![[CoroHandlePromiseInt:rec_.*]] = !cir.record<struct "std::coroutine_handle<folly::coro::Task<int>::promise_type>" padded {!u8i}>
+// CIR-DAG: ![[SuspendAlways:.*]] = !cir.record<struct "std::suspend_always" padded {!u8i}>
// CIR: module {{.*}} {
// CIR-NEXT: cir.global external @_ZN5folly4coro9co_invokeE = #cir.zero : !rec_folly3A3Acoro3A3Aco_invoke_fn
@@ -116,9 +130,10 @@ VoidTask silly_task() {
co_await std::suspend_always();
}
-// CIR: cir.func coroutine dso_local @_Z10silly_taskv() -> ![[VoidTask]]
+// CIR: cir.func coroutine {{.*}} @_Z10silly_taskv() -> ![[VoidTask]]
// CIR: %[[VoidTaskAddr:.*]] = cir.alloca ![[VoidTask]], {{.*}}, ["__retval"]
// CIR: %[[SavedFrameAddr:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["__coro_frame_addr"]
+// CIR: %[[VoidPromisseAddr:.*]] = cir.alloca ![[VoidPromisse]], {{.*}}, ["__promise"]
// Get coroutine id with __builtin_coro_id.
@@ -138,3 +153,110 @@ VoidTask silly_task() {
// CIR: }
// CIR: %[[Load0:.*]] = cir.load{{.*}} %[[SavedFrameAddr]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
// CIR: %[[CoroFrameAddr:.*]] = cir.call @__builtin_coro_begin(%[[CoroId]], %[[Load0]])
+
+// Call promise.get_return_object() to retrieve the task object.
+
+// CIR: %[[RetObj:.*]] = cir.call @_ZN5folly4coro4TaskIvE12promise_type17get_return_objectEv(%[[VoidPromisseAddr]]) nothrow : {{.*}} -> ![[VoidTask]]
+// CIR: cir.store{{.*}} %[[RetObj]], %[[VoidTaskAddr]] : ![[VoidTask]]
+// Start a new scope for the actual codegen for co_await, create temporary allocas for
+// holding coroutine handle and the suspend_always struct.
+
+// CIR: cir.scope {
+// CIR: %[[SuspendAlwaysAddr:.*]] = cir.alloca ![[SuspendAlways]], {{.*}} ["ref.tmp0"] {alignment = 1 : i64}
+// CIR: %[[CoroHandleVoidAddr:.*]] = cir.alloca ![[CoroHandleVoid]], {{.*}} ["agg.tmp0"] {alignment = 1 : i64}
+// CIR: %[[CoroHandlePromiseAddr:.*]] = cir.alloca ![[CoroHandlePromiseVoid]], {{.*}} ["agg.tmp1"] {alignment = 1 : i64}
+
+// Effectively execute `coawait promise_type::initial_suspend()` by calling initial_suspend() and getting
+// the suspend_always struct to use for cir.await. Note that we return by-value since we defer ABI lowering
+// to later passes, same is done elsewhere.
+
+// CIR: %[[Tmp0:.*]] = cir.call @_ZN5folly4coro4TaskIvE12promise_type15initial_suspendEv(%[[VoidPromisseAddr]])
+// CIR: cir.store{{.*}} %[[Tmp0:.*]], %[[SuspendAlwaysAddr]]
+
+//
+// Here we start mapping co_await to cir.await.
+//
+
+// First regions `ready` has a special cir.yield code to veto suspension.
+
+// CIR: cir.await(init, ready : {
+// CIR: %[[ReadyVeto:.*]] = cir.scope {
+// CIR: %[[TmpCallRes:.*]] = cir.call @_ZNSt14suspend_always11await_readyEv(%[[SuspendAlwaysAddr]])
+// CIR: cir.yield %[[TmpCallRes:.*]] : !cir.bool
+// CIR: }
+// CIR: cir.condition(%[[ReadyVeto]])
+
+// Second region `suspend` contains the actual suspend logic.
+//
+// - Start by getting the coroutine handle using from_address().
+// - Implicit convert coroutine handle from task specific promisse
+// specialization to a void one.
+// - Call suspend_always::await_suspend() passing the handle.
+//
+// FIXME: add veto support for non-void await_suspends.
+
+// CIR: }, suspend : {
+// CIR: %[[FromAddrRes:.*]] = cir.call @_ZNSt16coroutine_handleIN5folly4coro4TaskIvE12promise_typeEE12from_addressEPv(%[[CoroFrameAddr]])
+// CIR: cir.store{{.*}} %[[FromAddrRes]], %[[CoroHandlePromiseAddr]] : ![[CoroHandlePromiseVoid]]
+// CIR: %[[CoroHandlePromiseReload:.*]] = cir.load{{.*}} %[[CoroHandlePromiseAddr]]
+// CIR: cir.call @_ZNSt16coroutine_handleIvEC1IN5folly4coro4TaskIvE12promise_typeEEES_IT_E(%[[CoroHandleVoidAddr]], %[[CoroHandlePromiseReload]])
+// CIR: %[[CoroHandleVoidReload:.*]] = cir.load{{.*}} %[[CoroHandleVoidAddr]] : !cir.ptr<![[CoroHandleVoid]]>, ![[CoroHandleVoid]]
+// CIR: cir.call @_ZNSt14suspend_always13await_suspendESt16coroutine_handleIvE(%[[SuspendAlwaysAddr]], %[[CoroHandleVoidReload]])
+// CIR: cir.yield
+
+// Third region `resume` handles coroutine resuming logic.
+
+// CIR: }, resume : {
+// CIR: cir.call @_ZNSt14suspend_always12await_resumeEv(%[[SuspendAlwaysAddr]])
+// CIR: cir.yield
+// CIR: },)
+// CIR: }
+
+// Since we already tested cir.await guts above, the remaining checks for:
+// - The actual user written co_await
+// - The promise call
+// - The final suspend co_await
+// - Return
+
+folly::coro::Task<int> byRef(const std::string& s) {
+ co_return s.size();
+}
+
+// CIR: cir.func coroutine {{.*}} @_Z5byRefRKSt6string(%[[ARG:.*]]: !cir.ptr<![[StdString]]> {{.*}}) -> ![[IntTask]]
+// CIR: %[[AllocaParam:.*]] = cir.alloca !cir.ptr<![[StdString]]>, {{.*}}, ["s", init, const]
+// CIR: %[[IntTaskAddr:.*]] = cir.alloca ![[IntTask]], {{.*}}, ["__retval"]
+// CIR: %[[SavedFrameAddr:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["__coro_frame_addr"]
+// CIR: %[[AllocaFnUse:.*]] = cir.alloca !cir.ptr<![[StdString]]>, {{.*}}, ["s", init, const]
+// CIR: %[[IntPromisseAddr:.*]] = cir.alloca ![[IntPromisse]], {{.*}}, ["__promise"]
+// CIR: cir.store %[[ARG]], %[[AllocaParam]] : !cir.ptr<![[StdString]]>, {{.*}}
+
+// Call promise.get_return_object() to retrieve the task object.
+
+// CIR: %[[LOAD:.*]] = cir.load %[[AllocaParam]] : !cir.ptr<!cir.ptr<![[StdString]]>>, !cir.ptr<![[StdString]]>
+// CIR: cir.store {{.*}} %[[LOAD]], %[[AllocaFnUse]] : !cir.ptr<![[StdString]]>, !cir.ptr<!cir.ptr<![[StdString]]>>
+// CIR: %[[RetObj:.*]] = cir.call @_ZN5folly4coro4TaskIiE12promise_type17get_return_objectEv(%4) nothrow : {{.*}} -> ![[IntTask]]
+// CIR: cir.store {{.*}} %[[RetObj]], %[[IntTaskAddr]] : ![[IntTask]]
+// CIR: cir.scope {
+// CIR: %[[SuspendAlwaysAddr:.*]] = cir.alloca ![[SuspendAlways]], {{.*}} ["ref.tmp0"] {alignment = 1 : i64}
+// CIR: %[[CoroHandleVoidAddr:.*]] = cir.alloca ![[CoroHandleVoid]], {{.*}} ["agg.tmp0"] {alignment = 1 : i64}
+// CIR: %[[CoroHandlePromiseAddr:.*]] = cir.alloca ![[CoroHandlePromiseInt]], {{.*}} ["agg.tmp1"] {alignment = 1 : i64}
+// CIR: %[[Tmp0:.*]] = cir.call @_ZN5folly4coro4TaskIiE12promise_type15initial_suspendEv(%[[IntPromisseAddr]])
+// CIR: cir.await(init, ready : {
+// CIR: %[[ReadyVeto:.*]] = cir.scope {
+// CIR: %[[TmpCallRes:.*]] = cir.call @_ZNSt14suspend_always11await_readyEv(%[[SuspendAlwaysAddr]])
+// CIR: cir.yield %[[TmpCallRes:.*]] : !cir.bool
+// CIR: }
+// CIR: cir.condition(%[[ReadyVeto]])
+// CIR: }, suspend : {
+// CIR: %[[FromAddrRes:.*]] = cir.call @_ZNSt16coroutine_handleIN5folly4coro4TaskIiE12promise_typeEE12from_addressEPv(%[[CoroFrameAddr:.*]])
+// CIR: cir.store{{.*}} %[[FromAddrRes]], %[[CoroHandlePromiseAddr]] : ![[CoroHandlePromiseInt]]
+// CIR: %[[CoroHandlePromiseReload:.*]] = cir.load{{.*}} %[[CoroHandlePromiseAddr]]
+// CIR: cir.call @_ZNSt16coroutine_handleIvEC1IN5folly4coro4TaskIiE12promise_typeEEES_IT_E(%[[CoroHandleVoidAddr]], %[[CoroHandlePromiseReload]])
+// CIR: %[[CoroHandleVoidReload:.*]] = cir.load{{.*}} %[[CoroHandleVoidAddr]] : !cir.ptr<![[CoroHandleVoid]]>, ![[CoroHandleVoid]]
+// CIR: cir.call @_ZNSt14suspend_always13await_suspendESt16coroutine_handleIvE(%[[SuspendAlwaysAddr]], %[[CoroHandleVoidReload]])
+// CIR: cir.yield
+// CIR: }, resume : {
+// CIR: cir.call @_ZNSt14suspend_always12await_resumeEv(%[[SuspendAlwaysAddr]])
+// CIR: cir.yield
+// CIR: },)
+// CIR: }
diff --git a/clang/test/CIR/CodeGen/count-of.c b/clang/test/CIR/CodeGen/count-of.c
new file mode 100644
index 0000000..1fd1290
--- /dev/null
+++ b/clang/test/CIR/CodeGen/count-of.c
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -std=c2y -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 -std=c2y -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 -std=c2y -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
+
+unsigned long vla_with_array_element_type_with_const_size() {
+ long size;
+ return _Countof(int[5][size]);
+}
+
+// CIR: %[[RET_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["__retval"]
+// CIR: %[[SIZE_ADDR:.*]] = cir.alloca !s64i, !cir.ptr<!s64i>, ["size"]
+// CIR: %[[CONST_5:.*]] = cir.const #cir.int<5> : !u64i
+// CIR: cir.store %[[CONST_5]], %[[RET_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[RET_VAL:.*]] = cir.load %[[RET_ADDR]] : !cir.ptr<!u64i>, !u64i
+// CIR: cir.return %[[RET_VAL]] : !u64i
+
+// LLVM: %[[RET_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[SIZE_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: store i64 5, ptr %[[RET_ADDR]], align 8
+// LLVM: %[[RET_VAL:.*]] = load i64, ptr %[[RET_ADDR]], align 8
+// LLVM: ret i64 %[[RET_VAL]]
+
+// OGCG: %[[SIZE_ADDR:.*]] = alloca i64, align 8
+// OGCG: ret i64 5
+
+unsigned long vla_with_array_element_type_non_const_size() {
+ long size;
+ return _Countof(int[size][size]);
+}
+
+// CIR: %[[REET_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["__retval"]
+// CIR: %[[SIZE_ADDR:.*]] = cir.alloca !s64i, !cir.ptr<!s64i>, ["size"]
+// CIR: %[[TMP_SIZE:.*]] = cir.load {{.*}} %[[SIZE_ADDR]] : !cir.ptr<!s64i>, !s64i
+// CIR: %[[TMP_SIZE_U64:.*]] = cir.cast integral %[[TMP_SIZE]] : !s64i -> !u64i
+// CIR: cir.store %[[TMP_SIZE_U64]], %[[RET_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[TMP_RET:.*]] = cir.load %[[RET_ADDR]] : !cir.ptr<!u64i>, !u64i
+// CIR: cir.return %[[TMP_RET]] : !u64i
+
+// LLVM: %[[RET_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[SIZE_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[TMP_SIZE:.*]] = load i64, ptr %[[SIZE_ADDR]], align 8
+// LLVM: store i64 %[[TMP_SIZE]], ptr %[[RET_ADDR]], align 8
+// LLVM: %[[TMP_RET:.*]] = load i64, ptr %[[RET_ADDR]], align 8
+// LLVM: ret i64 %[[TMP_RET]]
+
+// OGCG: %[[SIZE_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[TMP_SIZE:.*]] = load i64, ptr %[[SIZE_ADDR]], align 8
+// OGCG: %[[TMP_SIZE_2:.*]] = load i64, ptr %[[SIZE_ADDR]], align 8
+// OGCG: ret i64 %[[TMP_SIZE]]
diff --git a/clang/test/CIR/CodeGen/ctor-null-init.cpp b/clang/test/CIR/CodeGen/ctor-null-init.cpp
new file mode 100644
index 0000000..6f31a46
--- /dev/null
+++ b/clang/test/CIR/CodeGen/ctor-null-init.cpp
@@ -0,0 +1,91 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir --check-prefix=CIR %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll --check-prefix=LLVM %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll --check-prefix=OGCG %s
+
+struct A {
+ A() = default;
+ A(int); // This constructor triggers the null base class initialization.
+};
+
+struct B : A {
+};
+
+void test_empty_base_null_init() {
+ B{};
+}
+
+// CIR: cir.func {{.*}} @_Z25test_empty_base_null_initv()
+// CIR-NEXT: %[[B_ADDR:.*]] = cir.alloca !rec_B, !cir.ptr<!rec_B>, ["agg.tmp.ensured"]
+// CIR-NEXT: %[[A_ADDR:.*]] = cir.base_class_addr %[[B_ADDR]] : !cir.ptr<!rec_B> nonnull [0] -> !cir.ptr<!rec_A>
+
+// LLVM: define{{.*}} @_Z25test_empty_base_null_initv()
+// LLVM-NEXT: %[[B:.*]] = alloca %struct.B
+// LLVM-NEXT: ret void
+
+// OGCG: define{{.*}} @_Z25test_empty_base_null_initv()
+// OGCG-NEXT: entry:
+// OGCG-NEXT: %[[B:.*]] = alloca %struct.B
+// OGCG-NEXT: ret void
+
+
+struct C {
+ int c;
+ C() = default;
+ C(int); // This constructor triggers the null base class initialization.
+};
+
+struct D : C {
+};
+
+void test_non_empty_base_null_init() {
+ D{};
+}
+
+// CIR: cir.func {{.*}} @_Z29test_non_empty_base_null_initv()
+// CIR: %[[TMP:.*]] = cir.alloca !rec_D, !cir.ptr<!rec_D>, ["agg.tmp.ensured"]
+// CIR: %[[BASE:.*]] = cir.base_class_addr %[[TMP]] : !cir.ptr<!rec_D> nonnull [0] -> !cir.ptr<!rec_C>
+// CIR: %[[ZERO:.*]] = cir.const #cir.const_record<{#cir.int<0> : !s32i}> : !rec_C
+// CIR: cir.store{{.*}} %[[ZERO]], %[[BASE]]
+
+// LLVM: define{{.*}} void @_Z29test_non_empty_base_null_initv()
+// LLVM: %[[TMP:.*]] = alloca %struct.D
+// LLVM: store %struct.C zeroinitializer, ptr %[[TMP]]
+
+// OGCG: define {{.*}} void @_Z29test_non_empty_base_null_initv()
+// OGCG: %[[TMP:.*]] = alloca %struct.D
+// OGCG: %[[BASE:.*]] = getelementptr inbounds i8, ptr %[[TMP]], i64 0
+// OGCG: call void @llvm.memset.p0.i64(ptr{{.*}} %[[BASE]], i8 0, i64 4, i1 false)
+
+struct E {
+ int e;
+};
+
+struct F : E {
+ F() = default;
+ F(int);
+};
+
+struct G : F {
+};
+
+void test_base_chain_null_init() {
+ G{};
+}
+
+// CIR: cir.func {{.*}} @_Z25test_base_chain_null_initv()
+// CIR: %[[TMP:.*]] = cir.alloca !rec_G, !cir.ptr<!rec_G>, ["agg.tmp.ensured"]
+// CIR: %[[BASE:.*]] = cir.base_class_addr %[[TMP]] : !cir.ptr<!rec_G> nonnull [0] -> !cir.ptr<!rec_F>
+// CIR: %[[ZERO:.*]] = cir.const #cir.const_record<{#cir.zero : !rec_E}> : !rec_F
+// CIR: cir.store{{.*}} %[[ZERO]], %[[BASE]]
+
+// LLVM: define{{.*}} void @_Z25test_base_chain_null_initv()
+// LLVM: %[[TMP:.*]] = alloca %struct.G
+// LLVM: store %struct.F zeroinitializer, ptr %[[TMP]]
+
+// OGCG: define {{.*}} void @_Z25test_base_chain_null_initv()
+// OGCG: %[[TMP:.*]] = alloca %struct.G
+// OGCG: %[[BASE:.*]] = getelementptr inbounds i8, ptr %[[TMP]], i64 0
+// OGCG: call void @llvm.memset.p0.i64(ptr{{.*}} %[[BASE]], i8 0, i64 4, i1 false)
diff --git a/clang/test/CIR/CodeGen/cxx-conversion-operators.cpp b/clang/test/CIR/CodeGen/cxx-conversion-operators.cpp
index a386a41..30e6298 100644
--- a/clang/test/CIR/CodeGen/cxx-conversion-operators.cpp
+++ b/clang/test/CIR/CodeGen/cxx-conversion-operators.cpp
@@ -27,7 +27,7 @@ void test() {
x = o;
}
-// CIR: cir.func dso_local @_ZN20out_of_line_operatorcviEv(%[[THIS_ARG:.+]]: !cir.ptr<!rec_out_of_line_operator>{{.*}}) -> !s32i
+// CIR: cir.func {{.*}} @_ZN20out_of_line_operatorcviEv(%[[THIS_ARG:.+]]: !cir.ptr<!rec_out_of_line_operator>{{.*}}) -> !s32i
// CIR: %[[THIS_ALLOCA:.+]] = cir.alloca !cir.ptr<!rec_out_of_line_operator>, !cir.ptr<!cir.ptr<!rec_out_of_line_operator>>, ["this", init]
// CIR: %[[RETVAL:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
// CIR: cir.store %[[THIS_ARG]], %[[THIS_ALLOCA]] : !cir.ptr<!rec_out_of_line_operator>, !cir.ptr<!cir.ptr<!rec_out_of_line_operator>>
@@ -38,7 +38,7 @@ void test() {
// CIR: cir.return %[[RET_LOAD]] : !s32i
// CIR: }
-// CIR: cir.func comdat linkonce_odr @_ZNK15inline_operatorcviEv(%[[INLINE_THIS_ARG:.+]]: !cir.ptr<!rec_inline_operator>{{.*}}) -> !s32i
+// CIR: cir.func no_inline comdat linkonce_odr @_ZNK15inline_operatorcviEv(%[[INLINE_THIS_ARG:.+]]: !cir.ptr<!rec_inline_operator>{{.*}}) -> !s32i
// CIR: %[[INLINE_THIS_ALLOCA:.+]] = cir.alloca !cir.ptr<!rec_inline_operator>, !cir.ptr<!cir.ptr<!rec_inline_operator>>, ["this", init]
// CIR: %[[INLINE_RETVAL:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
// CIR: cir.store %[[INLINE_THIS_ARG]], %[[INLINE_THIS_ALLOCA]] : !cir.ptr<!rec_inline_operator>, !cir.ptr<!cir.ptr<!rec_inline_operator>>
@@ -49,7 +49,7 @@ void test() {
// CIR: cir.return %[[INLINE_RET_LOAD]] : !s32i
// CIR: }
-// CIR: cir.func dso_local @_Z4testv()
+// CIR: cir.func {{.*}} @_Z4testv()
// CIR: %[[X_ALLOCA:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init]
// CIR: %[[I_ALLOCA:.+]] = cir.alloca {{.*}}, {{.*}}, ["i"]
// CIR: %[[O_ALLOCA:.+]] = cir.alloca {{.*}}, {{.*}}, ["o"]
@@ -82,7 +82,7 @@ void test() {
// LLVM: ret i32 %[[INLINE_RET_LOAD]]
// LLVM: }
-// LLVM: define dso_local void @_Z4testv()
+// LLVM: define {{.*}} void @_Z4testv()
// LLVM: %[[X_ALLOCA:.+]] = alloca i32, i64 1
// LLVM: %[[I_ALLOCA:.+]] = alloca {{.*}}, i64 1
// LLVM: %[[O_ALLOCA:.+]] = alloca {{.*}}, i64 1
@@ -102,7 +102,7 @@ void test() {
// OGCG: ret i32 123
// OGCG: }
-// OGCG: define dso_local void @_Z4testv()
+// OGCG: define {{.*}} void @_Z4testv()
// OGCG: entry:
// OGCG: %[[X_VAR:.+]] = alloca i32
// OGCG: %[[I_VAR:.+]] = alloca {{.*}}
diff --git a/clang/test/CIR/CodeGen/cxx-rewritten-binary-operator.cpp b/clang/test/CIR/CodeGen/cxx-rewritten-binary-operator.cpp
new file mode 100644
index 0000000..ac4cac4
--- /dev/null
+++ b/clang/test/CIR/CodeGen/cxx-rewritten-binary-operator.cpp
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -std=c++20 -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 -std=c++20 -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 -std=c++20 -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
+
+struct HasOpEq {
+ bool operator==(const HasOpEq &) const;
+};
+
+void cxx_rewritten_binary_operator_scalar_expr() {
+ HasOpEq a;
+ HasOpEq b;
+ bool neq = a != b;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !rec_HasOpEq, !cir.ptr<!rec_HasOpEq>, ["a"]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !rec_HasOpEq, !cir.ptr<!rec_HasOpEq>, ["b"]
+// CIR: %[[NEQ_ADDR:.*]] = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, ["neq", init]
+// CIR: %[[EQ:.*]] = cir.call @_ZNK7HasOpEqeqERKS_(%[[A_ADDR]], %[[B_ADDR]]) : (!cir.ptr<!rec_HasOpEq>, !cir.ptr<!rec_HasOpEq>) -> !cir.bool
+// CIR: %[[NEQ:.*]] = cir.unary(not, %[[EQ]]) : !cir.bool, !cir.bool
+// CIR: cir.store{{.*}} %[[NEQ]], %[[NEQ_ADDR]] : !cir.bool, !cir.ptr<!cir.bool>
+
+// LLVM: %[[A_ADDR:.*]] = alloca %struct.HasOpEq, i64 1, align 1
+// LLVM: %[[B_ADDR:.*]] = alloca %struct.HasOpEq, i64 1, align 1
+// LLVM: %[[NEQ_ADDR:.*]] = alloca i8, i64 1, align 1
+// LLVM: %[[EQ:.*]] = call i1 @_ZNK7HasOpEqeqERKS_(ptr %[[A_ADDR]], ptr %[[B_ADDR]])
+// LLVM: %[[NEQ_I1:.*]] = xor i1 %[[EQ]], true
+// LLVM: %[[NEQ:.*]] = zext i1 %[[NEQ_I1]] to i8
+// LLVM: store i8 %[[NEQ]], ptr %[[NEQ_ADDR]], align 1
+
+// OGCG: %[[A_ADDR:.*]] = alloca %struct.HasOpEq, align 1
+// OGCG: %[[B_ADDR:.*]] = alloca %struct.HasOpEq, align 1
+// OGCG: %[[NEQ_ADDR:.*]] = alloca i8, align 1
+// OGCG: %[[EQ:.*]] = call {{.*}} zeroext i1 @_ZNK7HasOpEqeqERKS_(ptr {{.*}} %[[A_ADDR]], ptr {{.*}} %[[B_ADDR]])
+// OGCG: %[[NEQ_I1:.*]] = xor i1 %[[EQ]], true
+// OGCG: %[[NEQ:.*]] = zext i1 %[[NEQ_I1]] to i8
+// OGCG: store i8 %[[NEQ]], ptr %[[NEQ_ADDR]], align 1
diff --git a/clang/test/CIR/CodeGen/cxx-special-member-attr.cpp b/clang/test/CIR/CodeGen/cxx-special-member-attr.cpp
new file mode 100644
index 0000000..f2c2c1f
--- /dev/null
+++ b/clang/test/CIR/CodeGen/cxx-special-member-attr.cpp
@@ -0,0 +1,66 @@
+// RUN: %clang_cc1 -std=c++11 -triple aarch64-none-linux-android21 -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+
+struct Flub {
+ int a = 123;
+};
+
+struct Foo {
+ int a;
+
+ Foo() : a(123) {}
+ Foo(const Foo &other) : a(other.a) {}
+ Foo(Foo &&other) noexcept : a(other.a) { other.a = 0; }
+
+ Foo &operator=(const Foo &other) {
+ if (this != &other) {
+ a = other.a;
+ }
+ return *this;
+ }
+
+ Foo &operator=(Foo &&other) noexcept {
+ if (this != &other) {
+ a = other.a;
+ other.a = 0;
+ }
+ return *this;
+ }
+
+ ~Foo();
+};
+
+void trivial_func() {
+ Flub f1{};
+
+ Flub f2 = f1;
+ // Trivial copy constructors/assignments are replaced with cir.copy
+ // CIR: cir.copy {{.*}} : !cir.ptr<!rec_Flub>
+
+ Flub f3 = static_cast<Flub&&>(f1);
+ // CIR: @_ZN4FlubC1EOS_(%arg0: !cir.ptr<!rec_Flub> loc({{.*}}), %arg1: !cir.ptr<!rec_Flub> loc({{.*}})) special_member<#cir.cxx_ctor<!rec_Flub, move, trivial true>
+
+ f2 = f1;
+ // CIR: @_ZN4FlubaSERKS_(%arg0: !cir.ptr<!rec_Flub> loc({{.*}}), %arg1: !cir.ptr<!rec_Flub> loc({{.*}})) -> !cir.ptr<!rec_Flub> special_member<#cir.cxx_assign<!rec_Flub, copy, trivial true>>
+
+ f1 = static_cast<Flub&&>(f3);
+ // CIR: @_ZN4FlubaSEOS_(%arg0: !cir.ptr<!rec_Flub> loc({{.*}}), %arg1: !cir.ptr<!rec_Flub> loc({{.*}})) -> !cir.ptr<!rec_Flub> special_member<#cir.cxx_assign<!rec_Flub, move, trivial true>>
+}
+
+void non_trivial_func() {
+ Foo f1{};
+ // CIR: @_ZN3FooC2Ev(%arg0: !cir.ptr<!rec_Foo> loc({{.*}})) special_member<#cir.cxx_ctor<!rec_Foo, default>>
+
+ Foo f2 = f1;
+ // CIR: @_ZN3FooC2ERKS_(%arg0: !cir.ptr<!rec_Foo> loc({{.*}}), %arg1: !cir.ptr<!rec_Foo> loc({{.*}})) special_member<#cir.cxx_ctor<!rec_Foo, copy>>
+
+ Foo f3 = static_cast<Foo&&>(f1);
+ // CIR: @_ZN3FooC2EOS_(%arg0: !cir.ptr<!rec_Foo> loc({{.*}}), %arg1: !cir.ptr<!rec_Foo> loc({{.*}})) special_member<#cir.cxx_ctor<!rec_Foo, move>>
+
+ f2 = f1;
+ // CIR: @_ZN3FooaSERKS_(%arg0: !cir.ptr<!rec_Foo> loc({{.*}}), %arg1: !cir.ptr<!rec_Foo> loc({{.*}})) -> !cir.ptr<!rec_Foo> special_member<#cir.cxx_assign<!rec_Foo, copy>>
+
+ f1 = static_cast<Foo&&>(f3);
+ // CIR: @_ZN3FooaSEOS_(%arg0: !cir.ptr<!rec_Foo> loc({{.*}}), %arg1: !cir.ptr<!rec_Foo> loc({{.*}})) -> !cir.ptr<!rec_Foo> special_member<#cir.cxx_assign<!rec_Foo, move>>
+ // CIR: @_ZN3FooD1Ev(!cir.ptr<!rec_Foo>) special_member<#cir.cxx_dtor<!rec_Foo>>
+}
diff --git a/clang/test/CIR/CodeGen/defaultarg.cpp b/clang/test/CIR/CodeGen/defaultarg.cpp
new file mode 100644
index 0000000..29c929c
--- /dev/null
+++ b/clang/test/CIR/CodeGen/defaultarg.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -std=c++17 %s -o %t.cir
+// RUN: FileCheck %s --input-file=%t.cir --check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm -std=c++17 %s -o %t-cir.ll
+// RUN: FileCheck %s --input-file=%t-cir.ll --check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm -std=c++17 %s -o %t.ll
+// RUN: FileCheck %s --input-file=%t.ll --check-prefix=OGCG
+
+void bar(const int &i = 42);
+
+void foo() {
+ bar();
+}
+
+// CIR: cir.func {{.*}} @_Z3foov()
+// CIR: cir.scope {
+// CIR: %[[TMP0:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["ref.tmp0"]
+// CIR: %[[TMP1:.*]] = cir.const #cir.int<42>
+// CIR: cir.store{{.*}} %[[TMP1]], %[[TMP0]]
+// CIR: cir.call @_Z3barRKi(%[[TMP0]])
+// CIR: }
+
+// LLVM: define{{.*}} @_Z3foov()
+// LLVM: %[[TMP0:.*]] = alloca i32
+// LLVM: br label %[[SCOPE_LABEL:.*]]
+// LLVM: [[SCOPE_LABEL]]:
+// LLVM: store i32 42, ptr %[[TMP0]]
+// LLVM: call void @_Z3barRKi(ptr %[[TMP0]])
+
+// OGCG: define{{.*}} @_Z3foov()
+// OGCG: %[[TMP0:.*]] = alloca i32
+// OGCG: store i32 42, ptr %[[TMP0]]
+// OGCG: call void @_Z3barRKi(ptr {{.*}} %[[TMP0]])
+
+struct S
+{
+ S(int n = 2);
+};
+
+void test_ctor_defaultarg() {
+ S s;
+}
+
+// CIR: cir.func {{.*}} @_Z20test_ctor_defaultargv()
+// CIR: %[[S:.*]] = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["s", init]
+// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s32i
+// CIR: cir.call @_ZN1SC1Ei(%[[S]], %[[TWO]]) : (!cir.ptr<!rec_S>, !s32i) -> ()
+
+// LLVM: define{{.*}} @_Z20test_ctor_defaultargv()
+// LLVM: %[[S:.*]] = alloca %struct.S
+// LLVM: call void @_ZN1SC1Ei(ptr %[[S]], i32 2)
+
+// OGCG: define{{.*}} @_Z20test_ctor_defaultargv()
+// OGCG: %[[S:.*]] = alloca %struct.S
+// OGCG: call void @_ZN1SC1Ei(ptr{{.*}} %[[S]], i32 {{.*}} 2)
diff --git a/clang/test/CIR/CodeGen/delete.cpp b/clang/test/CIR/CodeGen/delete.cpp
index d8ac436..c8d6f05 100644
--- a/clang/test/CIR/CodeGen/delete.cpp
+++ b/clang/test/CIR/CodeGen/delete.cpp
@@ -19,7 +19,7 @@ void test_sized_delete(SizedDelete *x) {
// CIR: cir.func private @_ZN11SizedDeletedlEPvm(!cir.ptr<!void>, !u64i)
// LLVM: declare void @_ZN11SizedDeletedlEPvm(ptr, i64)
-// CIR: cir.func dso_local @_Z17test_sized_deleteP11SizedDelete
+// CIR: cir.func {{.*}} @_Z17test_sized_deleteP11SizedDelete
// CIR: %[[X:.*]] = cir.load{{.*}} %{{.*}}
// CIR: %[[X_CAST:.*]] = cir.cast bitcast %[[X]] : !cir.ptr<!rec_SizedDelete> -> !cir.ptr<!void>
// CIR: %[[OBJ_SIZE:.*]] = cir.const #cir.int<4> : !u64i
@@ -49,15 +49,15 @@ struct Container {
Container::~Container() { delete contents; }
// Contents::~Contents()
-// CIR: cir.func comdat linkonce_odr @_ZN8ContentsD2Ev
+// CIR: cir.func {{.*}} @_ZN8ContentsD2Ev
// LLVM: define linkonce_odr void @_ZN8ContentsD2Ev
// operator delete(void*, unsigned long)
-// CIR: cir.func private @_ZdlPvm(!cir.ptr<!void>, !u64i)
+// CIR: cir.func {{.*}} @_ZdlPvm(!cir.ptr<!void>, !u64i)
// LLVM: declare void @_ZdlPvm(ptr, i64)
// Container::~Container()
-// CIR: cir.func dso_local @_ZN9ContainerD2Ev
+// CIR: cir.func {{.*}} @_ZN9ContainerD2Ev
// CIR: %[[THIS:.*]] = cir.load %{{.*}}
// CIR: %[[CONTENTS_PTR_ADDR:.*]] = cir.get_member %[[THIS]][0] {name = "contents"} : !cir.ptr<!rec_Container> -> !cir.ptr<!cir.ptr<!rec_Contents>>
// CIR: %[[CONTENTS_PTR:.*]] = cir.load{{.*}} %[[CONTENTS_PTR_ADDR]]
diff --git a/clang/test/CIR/CodeGen/derived-to-base.cpp b/clang/test/CIR/CodeGen/derived-to-base.cpp
new file mode 100644
index 0000000..13acb47
--- /dev/null
+++ b/clang/test/CIR/CodeGen/derived-to-base.cpp
@@ -0,0 +1,129 @@
+// RUN: %clang_cc1 -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 -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 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG
+
+// TODO(cir): The constructors in this test case are only here because we don't
+// have support for zero-initialization of base classes yet. We should
+// fix that soon.
+
+struct Base {
+ Base();
+ void f();
+ int a;
+};
+
+struct Derived : Base {
+ Derived();
+ double b;
+};
+
+void f() {
+ Derived d;
+ d.f();
+}
+
+// CIR: cir.func {{.*}} @_Z1fv()
+// CIR: %[[D:.*]] = cir.alloca !rec_Derived, !cir.ptr<!rec_Derived>, ["d", init]
+// CIR: cir.call @_ZN7DerivedC1Ev(%[[D]]) : (!cir.ptr<!rec_Derived>) -> ()
+// CIR: %[[D_BASE:.*]] = cir.base_class_addr %[[D]] : !cir.ptr<!rec_Derived> nonnull [0] -> !cir.ptr<!rec_Base>
+// CIR: cir.call @_ZN4Base1fEv(%[[D_BASE]]) : (!cir.ptr<!rec_Base>) -> ()
+
+// LLVM: define {{.*}}void @_Z1fv()
+// LLVM: %[[D:.*]] = alloca %struct.Derived
+// LLVM: call void @_ZN7DerivedC1Ev(ptr %[[D]])
+// LLVM: call void @_ZN4Base1fEv(ptr %[[D]])
+
+// OGCG: define {{.*}}void @_Z1fv()
+// OGCG: %[[D:.*]] = alloca %struct.Derived
+// OGCG: call void @_ZN7DerivedC1Ev(ptr {{.*}} %[[D]])
+// OGCG: call void @_ZN4Base1fEv(ptr {{.*}} %[[D]])
+
+void useBase(Base *base);
+void callBaseUsingDerived(Derived *derived) {
+ useBase(derived);
+}
+
+
+// CIR: cir.func {{.*}} @_Z20callBaseUsingDerivedP7Derived(%[[DERIVED_ARG:.*]]: !cir.ptr<!rec_Derived> {{.*}})
+// CIR: %[[DERIVED_ADDR:.*]] = cir.alloca !cir.ptr<!rec_Derived>, !cir.ptr<!cir.ptr<!rec_Derived>>, ["derived", init]
+// CIR: cir.store %[[DERIVED_ARG]], %[[DERIVED_ADDR]]
+// CIR: %[[DERIVED:.*]] = cir.load{{.*}} %[[DERIVED_ADDR]]
+// CIR: %[[DERIVED_BASE:.*]] = cir.base_class_addr %[[DERIVED]] : !cir.ptr<!rec_Derived> nonnull [0] -> !cir.ptr<!rec_Base>
+// CIR: cir.call @_Z7useBaseP4Base(%[[DERIVED_BASE]]) : (!cir.ptr<!rec_Base>) -> ()
+
+// LLVM: define {{.*}} void @_Z20callBaseUsingDerivedP7Derived(ptr %[[DERIVED_ARG:.*]])
+// LLVM: %[[DERIVED_ADDR:.*]] = alloca ptr
+// LLVM: store ptr %[[DERIVED_ARG]], ptr %[[DERIVED_ADDR]]
+// LLVM: %[[DERIVED:.*]] = load ptr, ptr %[[DERIVED_ADDR]]
+// LLVM: call void @_Z7useBaseP4Base(ptr %[[DERIVED]])
+
+// OGCG: define {{.*}} void @_Z20callBaseUsingDerivedP7Derived(ptr {{.*}} %[[DERIVED_ARG:.*]])
+// OGCG: %[[DERIVED_ADDR:.*]] = alloca ptr
+// OGCG: store ptr %[[DERIVED_ARG]], ptr %[[DERIVED_ADDR]]
+// OGCG: %[[DERIVED:.*]] = load ptr, ptr %[[DERIVED_ADDR]]
+// OGCG: call void @_Z7useBaseP4Base(ptr {{.*}} %[[DERIVED]])
+
+Base *returnBaseFromDerived(Derived* derived) {
+ return derived;
+}
+
+// CIR: cir.func {{.*}} @_Z21returnBaseFromDerivedP7Derived(%[[DERIVED_ARG:.*]]: !cir.ptr<!rec_Derived> {{.*}}) -> !cir.ptr<!rec_Base>
+// CIR: %[[DERIVED_ADDR:.*]] = cir.alloca !cir.ptr<!rec_Derived>, !cir.ptr<!cir.ptr<!rec_Derived>>, ["derived", init]
+// CIR: %[[BASE_ADDR:.*]] = cir.alloca !cir.ptr<!rec_Base>, !cir.ptr<!cir.ptr<!rec_Base>>, ["__retval"]
+// CIR: cir.store %[[DERIVED_ARG]], %[[DERIVED_ADDR]]
+// CIR: %[[DERIVED:.*]] = cir.load{{.*}} %[[DERIVED_ADDR]]
+// CIR: %[[DERIVED_BASE:.*]] = cir.base_class_addr %[[DERIVED]] : !cir.ptr<!rec_Derived> nonnull [0] -> !cir.ptr<!rec_Base>
+// CIR: cir.store %[[DERIVED_BASE]], %[[BASE_ADDR]]
+// CIR: %[[BASE:.*]] = cir.load{{.*}} %[[BASE_ADDR]]
+// CIR: cir.return %[[BASE]] : !cir.ptr<!rec_Base>
+
+// LLVM: define {{.*}} ptr @_Z21returnBaseFromDerivedP7Derived(ptr %[[DERIVED_ARG:.*]])
+// LLVM: %[[DERIVED_ADDR:.*]] = alloca ptr
+// LLVM: store ptr %[[DERIVED_ARG]], ptr %[[DERIVED_ADDR]]
+// LLVM: %[[DERIVED:.*]] = load ptr, ptr %[[DERIVED_ADDR]]
+
+// OGCG: define {{.*}} ptr @_Z21returnBaseFromDerivedP7Derived(ptr {{.*}} %[[DERIVED_ARG:.*]])
+// OGCG: %[[DERIVED_ADDR:.*]] = alloca ptr
+// OGCG: store ptr %[[DERIVED_ARG]], ptr %[[DERIVED_ADDR]]
+// OGCG: %[[DERIVED:.*]] = load ptr, ptr %[[DERIVED_ADDR]]
+
+volatile Derived derivedObj;
+
+void test_volatile_store() {
+ derivedObj.a = 0;
+}
+
+// CIR: cir.func {{.*}} @_Z19test_volatile_storev()
+// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
+// CIR: %[[DERIVED_OBJ:.*]] = cir.get_global @derivedObj : !cir.ptr<!rec_Derived>
+// CIR: %[[DERIVED_OBJ_BASE:.*]] = cir.base_class_addr %[[DERIVED_OBJ]] : !cir.ptr<!rec_Derived> nonnull [0] -> !cir.ptr<!rec_Base>
+// CIR: %[[DERIVED_OBJ_A:.*]] = cir.get_member %[[DERIVED_OBJ_BASE]][0] {name = "a"} : !cir.ptr<!rec_Base> -> !cir.ptr<!s32i>
+// CIR: cir.store volatile {{.*}} %[[ZERO]], %[[DERIVED_OBJ_A]] : !s32i, !cir.ptr<!s32i>
+
+// LLVM: define {{.*}} void @_Z19test_volatile_storev()
+// LLVM: store volatile i32 0, ptr @derivedObj
+
+// OGCG: define {{.*}} void @_Z19test_volatile_storev()
+// OGCG: store volatile i32 0, ptr @derivedObj
+
+void test_volatile_load() {
+ [[maybe_unused]] int val = derivedObj.a;
+}
+
+// CIR: cir.func {{.*}} @_Z18test_volatile_loadv()
+// CIR: %[[DERIVED_OBJ:.*]] = cir.get_global @derivedObj : !cir.ptr<!rec_Derived>
+// CIR: %[[DERIVED_OBJ_BASE:.*]] = cir.base_class_addr %[[DERIVED_OBJ]] : !cir.ptr<!rec_Derived> nonnull [0] -> !cir.ptr<!rec_Base>
+// CIR: %[[DERIVED_OBJ_A:.*]] = cir.get_member %[[DERIVED_OBJ_BASE]][0] {name = "a"} : !cir.ptr<!rec_Base> -> !cir.ptr<!s32i>
+// CIR: %[[VAL:.*]] = cir.load volatile {{.*}} %[[DERIVED_OBJ_A]] : !cir.ptr<!s32i>, !s32i
+
+// LLVM: define {{.*}} void @_Z18test_volatile_loadv()
+// LLVM: %[[VAL_ADDR:.*]] = alloca i32
+// LLVM: %[[DERIVED_OBJ:.*]] = load volatile i32, ptr @derivedObj
+
+// OGCG: define {{.*}} void @_Z18test_volatile_loadv()
+// OGCG: %[[VAL_ADDR:.*]] = alloca i32
+// OGCG: %[[DERIVED_OBJ:.*]] = load volatile i32, ptr @derivedObj
+// OGCG: store i32 %[[DERIVED_OBJ]], ptr %[[VAL_ADDR]]
diff --git a/clang/test/CIR/CodeGen/destructors.cpp b/clang/test/CIR/CodeGen/destructors.cpp
index 4363db5a..ec190f5 100644
--- a/clang/test/CIR/CodeGen/destructors.cpp
+++ b/clang/test/CIR/CodeGen/destructors.cpp
@@ -18,7 +18,7 @@ out_of_line_destructor::~out_of_line_destructor() {
// CIR: !rec_out_of_line_destructor = !cir.record<struct "out_of_line_destructor" {!s32i}>
-// CIR: cir.func dso_local @_ZN22out_of_line_destructorD2Ev(%{{.+}}: !cir.ptr<!rec_out_of_line_destructor>
+// CIR: cir.func {{.*}} @_ZN22out_of_line_destructorD2Ev(%{{.+}}: !cir.ptr<!rec_out_of_line_destructor>
// CIR: cir.call @_Z13some_functionv() nothrow : () -> ()
// CIR: cir.return
@@ -30,7 +30,7 @@ out_of_line_destructor::~out_of_line_destructor() {
// OGCG: call void @_Z13some_functionv()
// OGCG: ret void
-// CIR: cir.func dso_local @_ZN22out_of_line_destructorD1Ev(%{{.+}}: !cir.ptr<!rec_out_of_line_destructor>
+// CIR: cir.func {{.*}} @_ZN22out_of_line_destructorD1Ev(%{{.+}}: !cir.ptr<!rec_out_of_line_destructor>
// CIR: cir.call @_ZN22out_of_line_destructorD2Ev(%{{.*}}) nothrow : (!cir.ptr<!rec_out_of_line_destructor>)
// CIR: cir.return
@@ -61,7 +61,7 @@ void test_array_destructor() {
array_element arr[5]{};
}
-// CIR: cir.func dso_local @_Z21test_array_destructorv()
+// CIR: cir.func {{.*}} @_Z21test_array_destructorv()
// CIR: %[[ARR:.*]] = cir.alloca !cir.array<!rec_array_element x 5>, !cir.ptr<!cir.array<!rec_array_element x 5>>, ["arr", init]
// CIR: %[[ARR_PTR:.*]] = cir.alloca !cir.ptr<!rec_array_element>, !cir.ptr<!cir.ptr<!rec_array_element>>, ["arrayinit.temp", init]
// CIR: %[[BEGIN:.*]] = cir.cast array_to_ptrdecay %[[ARR]] : !cir.ptr<!cir.array<!rec_array_element x 5>>
diff --git a/clang/test/CIR/CodeGen/dtors.cpp b/clang/test/CIR/CodeGen/dtors.cpp
index 1fe048b7..aeee085 100644
--- a/clang/test/CIR/CodeGen/dtors.cpp
+++ b/clang/test/CIR/CodeGen/dtors.cpp
@@ -13,7 +13,7 @@ void test_temporary_dtor() {
A();
}
-// CIR: cir.func dso_local @_Z19test_temporary_dtorv()
+// CIR: cir.func {{.*}} @_Z19test_temporary_dtorv()
// CIR: %[[ALLOCA:.*]] = cir.alloca !rec_A, !cir.ptr<!rec_A>, ["agg.tmp.ensured"]
// CIR: cir.call @_ZN1AD1Ev(%[[ALLOCA]]) nothrow : (!cir.ptr<!rec_A>) -> ()
diff --git a/clang/test/CIR/CodeGen/dynamic-cast.cpp b/clang/test/CIR/CodeGen/dynamic-cast.cpp
index 5d010d2..e963be0 100644
--- a/clang/test/CIR/CodeGen/dynamic-cast.cpp
+++ b/clang/test/CIR/CodeGen/dynamic-cast.cpp
@@ -21,11 +21,11 @@ Derived *ptr_cast(Base *b) {
return dynamic_cast<Derived *>(b);
}
-// CIR-BEFORE: cir.func dso_local @_Z8ptr_castP4Base
+// CIR-BEFORE: cir.func {{.*}} @_Z8ptr_castP4Base
// CIR-BEFORE: %{{.+}} = cir.dyn_cast ptr %{{.+}} : !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived> #dyn_cast_info__ZTI4Base__ZTI7Derived
// CIR-BEFORE: }
-// CIR-AFTER: cir.func dso_local @_Z8ptr_castP4Base
+// CIR-AFTER: cir.func {{.*}} @_Z8ptr_castP4Base
// 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 {
@@ -69,11 +69,11 @@ Derived &ref_cast(Base &b) {
return dynamic_cast<Derived &>(b);
}
-// CIR-BEFORE: cir.func dso_local @_Z8ref_castR4Base
+// CIR-BEFORE: cir.func {{.*}} @_Z8ref_castR4Base
// CIR-BEFORE: %{{.+}} = cir.dyn_cast ref %{{.+}} : !cir.ptr<!rec_Base> -> !cir.ptr<!rec_Derived> #dyn_cast_info__ZTI4Base__ZTI7Derived
// CIR-BEFORE: }
-// CIR-AFTER: cir.func dso_local @_Z8ref_castR4Base
+// CIR-AFTER: cir.func {{.*}} @_Z8ref_castR4Base
// CIR-AFTER: %[[SRC_VOID_PTR:.*]] = cir.cast bitcast %{{.+}} : !cir.ptr<!rec_Base> -> !cir.ptr<!void>
// CIR-AFTER-NEXT: %[[SRC_RTTI:.*]] = cir.const #cir.global_view<@_ZTI4Base> : !cir.ptr<!u8i>
// CIR-AFTER-NEXT: %[[DEST_RTTI:.*]] = cir.const #cir.global_view<@_ZTI7Derived> : !cir.ptr<!u8i>
@@ -106,11 +106,11 @@ 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.func {{.*}} @_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: cir.func {{.*}} @_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 {
diff --git a/clang/test/CIR/CodeGen/global-array-dtor.cpp b/clang/test/CIR/CodeGen/global-array-dtor.cpp
new file mode 100644
index 0000000..01277a3
--- /dev/null
+++ b/clang/test/CIR/CodeGen/global-array-dtor.cpp
@@ -0,0 +1,113 @@
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-lowering-prepare %s -o %t.cir 2> %t-before.cir
+// RUN: FileCheck --input-file=%t-before.cir %s --check-prefix=CIR-BEFORE-LPP
+// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR
+// RUN: %clang_cc1 -std=c++17 -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++17 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG
+
+// This duplicates a test case in global-init.cpp, but having it by itself
+// forces the __cxa_atexit function to be emitted for this case, which was
+// broken in the original implementation.
+
+struct ArrayDtor {
+ ~ArrayDtor();
+};
+
+ArrayDtor arrDtor[16];
+
+// CIR-BEFORE-LPP: cir.global external @arrDtor = #cir.zero : !cir.array<!rec_ArrayDtor x 16>
+// CIR-BEFORE-LPP-SAME: dtor {
+// CIR-BEFORE-LPP: %[[THIS:.*]] = cir.get_global @arrDtor : !cir.ptr<!cir.array<!rec_ArrayDtor x 16>>
+// CIR-BEFORE-LPP: cir.array.dtor %[[THIS]] : !cir.ptr<!cir.array<!rec_ArrayDtor x 16>> {
+// CIR-BEFORE-LPP: ^bb0(%[[ELEM:.*]]: !cir.ptr<!rec_ArrayDtor>):
+// CIR-BEFORE-LPP: cir.call @_ZN9ArrayDtorD1Ev(%[[ELEM]]) nothrow : (!cir.ptr<!rec_ArrayDtor>) -> ()
+// CIR-BEFORE-LPP: cir.yield
+// CIR-BEFORE-LPP: }
+// CIR-BEFORE-LPP: }
+
+// CIR: cir.global external @arrDtor = #cir.zero : !cir.array<!rec_ArrayDtor x 16> {alignment = 16 : i64}
+// CIR: cir.func internal private @__cxx_global_array_dtor(%[[ARR_ARG:.*]]: !cir.ptr<!void> {{.*}}) {
+// CIR: %[[CONST15:.*]] = cir.const #cir.int<15> : !u64i
+// CIR: %[[BEGIN:.*]] = cir.cast array_to_ptrdecay %[[ARR_ARG]] : !cir.ptr<!void> -> !cir.ptr<!rec_ArrayDtor>
+// CIR: %[[END:.*]] = cir.ptr_stride %[[BEGIN]], %[[CONST15]] : (!cir.ptr<!rec_ArrayDtor>, !u64i) -> !cir.ptr<!rec_ArrayDtor>
+// CIR: %[[CUR_ADDR:.*]] = cir.alloca !cir.ptr<!rec_ArrayDtor>, !cir.ptr<!cir.ptr<!rec_ArrayDtor>>, ["__array_idx"]
+// CIR: cir.store %[[END]], %[[CUR_ADDR]] : !cir.ptr<!rec_ArrayDtor>, !cir.ptr<!cir.ptr<!rec_ArrayDtor>>
+// CIR: cir.do {
+// CIR: %[[CUR:.*]] = cir.load %[[CUR_ADDR]] : !cir.ptr<!cir.ptr<!rec_ArrayDtor>>, !cir.ptr<!rec_ArrayDtor>
+// CIR: cir.call @_ZN9ArrayDtorD1Ev(%[[CUR]]) nothrow : (!cir.ptr<!rec_ArrayDtor>) -> ()
+// CIR: %[[NEG_ONE:.*]] = cir.const #cir.int<-1> : !s64i
+// CIR: %[[NEXT:.*]] = cir.ptr_stride %[[CUR]], %[[NEG_ONE]] : (!cir.ptr<!rec_ArrayDtor>, !s64i) -> !cir.ptr<!rec_ArrayDtor>
+// CIR: cir.store %[[NEXT]], %[[CUR_ADDR]] : !cir.ptr<!rec_ArrayDtor>, !cir.ptr<!cir.ptr<!rec_ArrayDtor>>
+// CIR: cir.yield
+// CIR: } while {
+// CIR: %[[CUR:.*]] = cir.load %[[CUR_ADDR]] : !cir.ptr<!cir.ptr<!rec_ArrayDtor>>, !cir.ptr<!rec_ArrayDtor>
+// CIR: %[[CMP:.*]] = cir.cmp(ne, %[[CUR]], %[[BEGIN]]) : !cir.ptr<!rec_ArrayDtor>, !cir.bool
+// CIR: cir.condition(%[[CMP]])
+// CIR: }
+// CIR: cir.return
+// CIR: }
+//
+// CIR: cir.func internal private @__cxx_global_var_init() {
+// CIR: %[[ARR:.*]] = cir.get_global @arrDtor : !cir.ptr<!cir.array<!rec_ArrayDtor x 16>>
+// CIR: %[[DTOR:.*]] = cir.get_global @__cxx_global_array_dtor : !cir.ptr<!cir.func<(!cir.ptr<!void>)>>
+// CIR: %[[DTOR_CAST:.*]] = cir.cast bitcast %[[DTOR]] : !cir.ptr<!cir.func<(!cir.ptr<!void>)>> -> !cir.ptr<!cir.func<(!cir.ptr<!void>)>>
+// CIR: %[[ARR_CAST:.*]] = cir.cast bitcast %[[ARR]] : !cir.ptr<!cir.array<!rec_ArrayDtor x 16>> -> !cir.ptr<!void>
+// CIR: %[[HANDLE:.*]] = cir.get_global @__dso_handle : !cir.ptr<i8>
+// CIR: cir.call @__cxa_atexit(%[[DTOR_CAST]], %[[ARR_CAST]], %[[HANDLE]]) : (!cir.ptr<!cir.func<(!cir.ptr<!void>)>>, !cir.ptr<!void>, !cir.ptr<i8>) -> ()
+
+// LLVM: define internal void @__cxx_global_array_dtor(ptr %[[ARR_ARG:.*]]) {
+// LLVM: %[[BEGIN:.*]] = getelementptr %struct.ArrayDtor, ptr %[[ARR_ARG]], i32 0
+// LLVM: %[[END:.*]] = getelementptr %struct.ArrayDtor, ptr %[[BEGIN]], i64 15
+// LLVM: %[[CUR_ADDR:.*]] = alloca ptr
+// LLVM: store ptr %[[END]], ptr %[[CUR_ADDR]]
+// LLVM: br label %[[LOOP_BODY:.*]]
+// LLVM: [[LOOP_COND:.*]]:
+// LLVM: %[[CUR:.*]] = load ptr, ptr %[[CUR_ADDR]]
+// LLVM: %[[CMP:.*]] = icmp ne ptr %[[CUR]], %[[BEGIN]]
+// LLVM: br i1 %[[CMP]], label %[[LOOP_BODY]], label %[[LOOP_END:.*]]
+// LLVM: [[LOOP_BODY]]:
+// LLVM: %[[CUR:.*]] = load ptr, ptr %[[CUR_ADDR]]
+// LLVM: call void @_ZN9ArrayDtorD1Ev(ptr %[[CUR]]) #0
+// LLVM: %[[PREV:.*]] = getelementptr %struct.ArrayDtor, ptr %[[CUR]], i64 -1
+// LLVM: store ptr %[[PREV]], ptr %[[CUR_ADDR]]
+// LLVM: br label %[[LOOP_COND]]
+// LLVM: [[LOOP_END]]:
+// LLVM: ret void
+// LLVM: }
+//
+// LLVM: define internal void @__cxx_global_var_init() {
+// LLVM: call void @__cxa_atexit(ptr @__cxx_global_array_dtor, ptr @arrDtor, ptr @__dso_handle)
+
+// Note: OGCG defines these functions in reverse order of CIR->LLVM.
+// Note also: OGCG doesn't pass the address of the array to the destructor function.
+// Instead, it uses the global directly in the helper function.
+
+// OGCG: define internal void @__cxx_global_var_init() {{.*}} section ".text.startup" {
+// OGCG: call i32 @__cxa_atexit(ptr @__cxx_global_array_dtor, ptr null, ptr @__dso_handle)
+
+// OGCG: define internal void @__cxx_global_array_dtor(ptr noundef %[[ARG:.*]]) {{.*}} section ".text.startup" {
+// OGCG: entry:
+// OGCG: %[[UNUSED_ADDR:.*]] = alloca ptr
+// OGCG: store ptr %[[ARG]], ptr %[[UNUSED_ADDR]]
+// OGCG: br label %[[LOOP_BODY:.*]]
+// OGCG: [[LOOP_BODY]]:
+// OGCG: %[[PREV:.*]] = phi ptr [ getelementptr inbounds (%struct.ArrayDtor, ptr @arrDtor, i64 16), %entry ], [ %[[CUR:.*]], %[[LOOP_BODY]] ]
+// OGCG: %[[CUR]] = getelementptr inbounds %struct.ArrayDtor, ptr %[[PREV]], i64 -1
+// OGCG: call void @_ZN9ArrayDtorD1Ev(ptr noundef nonnull align 1 dereferenceable(1) %[[CUR]])
+// OGCG: %[[DONE:.*]] = icmp eq ptr %[[CUR]], @arrDtor
+// OGCG: br i1 %[[DONE]], label %[[LOOP_END:.*]], label %[[LOOP_BODY]]
+// OGCG: [[LOOP_END]]:
+// OGCG: ret void
+// OGCG: }
+
+// Common init function for all globals with default priority
+
+// CIR: cir.func private @_GLOBAL__sub_I_[[FILENAME:.*]]() {
+// CIR: cir.call @__cxx_global_var_init() : () -> ()
+
+// LLVM: define void @_GLOBAL__sub_I_[[FILENAME:.*]]()
+// LLVM: call void @__cxx_global_var_init()
+
+// OGCG: define internal void @_GLOBAL__sub_I_[[FILENAME:.*]]() {{.*}} section ".text.startup" {
+// OGCG: call void @__cxx_global_var_init()
diff --git a/clang/test/CIR/CodeGen/global-constant.c b/clang/test/CIR/CodeGen/global-constant.c
new file mode 100644
index 0000000..588642c
--- /dev/null
+++ b/clang/test/CIR/CodeGen/global-constant.c
@@ -0,0 +1,20 @@
+// 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
+
+const int global_no_use = 12;
+// CIR: cir.global constant {{.*}}@global_no_use
+// LLVM: @global_no_use = constant
+// OGCG: @global_no_use = constant
+
+const float global_used = 1.2f;
+// CIR: cir.global constant {{.*}}@global_used
+// LLVM: @global_used = constant
+// OGCG: @global_used = constant
+
+float const * get_float_ptr() {
+ return &global_used;
+}
diff --git a/clang/test/CIR/CodeGen/global-ctor-dtor.cpp b/clang/test/CIR/CodeGen/global-ctor-dtor.cpp
index 2e03ff3..63f1752 100644
--- a/clang/test/CIR/CodeGen/global-ctor-dtor.cpp
+++ b/clang/test/CIR/CodeGen/global-ctor-dtor.cpp
@@ -13,28 +13,28 @@ void foo(void) {
bar();
}
-// CIR-BEFORE-LPP: cir.func dso_local @_Z3foov() global_ctor
+// CIR-BEFORE-LPP: cir.func {{.*}} @_Z3foov() global_ctor
void foo2(void) __attribute__((constructor(777)));
void foo2(void) {
bar();
}
-// CIR-BEFORE-LPP: cir.func dso_local @_Z4foo2v() global_ctor(777)
+// CIR-BEFORE-LPP: cir.func {{.*}} @_Z4foo2v() global_ctor(777)
void foo3(void) __attribute__((destructor));
void foo3(void) {
bar();
}
-// CIR-BEFORE-LPP: cir.func dso_local @_Z4foo3v() global_dtor
+// CIR-BEFORE-LPP: cir.func {{.*}} @_Z4foo3v() global_dtor
void foo4(void) __attribute__((destructor(789)));
void foo4(void) {
bar();
}
-// CIR-BEFORE-LPP: cir.func dso_local @_Z4foo4v() global_dtor(789)
+// CIR-BEFORE-LPP: cir.func {{.*}} @_Z4foo4v() global_dtor(789)
// CIR-AFTER: module @{{.*}} attributes {cir.global_ctors = [#cir.global_ctor<"_Z3foov", 65535>, #cir.global_ctor<"_Z4foo2v", 777>], cir.global_dtors = [#cir.global_dtor<"_Z4foo3v", 65535>, #cir.global_dtor<"_Z4foo4v", 789>]
diff --git a/clang/test/CIR/CodeGen/global-init.cpp b/clang/test/CIR/CodeGen/global-init.cpp
index 01e2868..3510e3e 100644
--- a/clang/test/CIR/CodeGen/global-init.cpp
+++ b/clang/test/CIR/CodeGen/global-init.cpp
@@ -15,12 +15,14 @@
// LLVM: @needsCtor = global %struct.NeedsCtor zeroinitializer, align 1
// LLVM: @needsDtor = global %struct.NeedsDtor zeroinitializer, align 1
// LLVM: @needsCtorDtor = global %struct.NeedsCtorDtor zeroinitializer, align 1
+// LLVM: @arrDtor = global [16 x %struct.ArrayDtor] zeroinitializer, align 16
// LLVM: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I_[[FILENAME:.*]], ptr null }]
// OGCG: @needsCtor = global %struct.NeedsCtor zeroinitializer, align 1
// OGCG: @needsDtor = global %struct.NeedsDtor zeroinitializer, align 1
// OGCG: @__dso_handle = external hidden global i8
// OGCG: @needsCtorDtor = global %struct.NeedsCtorDtor zeroinitializer, align 1
+// OGCG: @arrDtor = global [16 x %struct.ArrayDtor] zeroinitializer, align 16
// OGCG: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I_[[FILENAME:.*]], ptr null }]
struct NeedsCtor {
@@ -145,11 +147,11 @@ float fp;
int i = (int)fp;
// CIR-BEFORE-LPP: cir.global external @i = ctor : !s32i {
-// CIR-BEFORE-LPP: %0 = cir.get_global @i : !cir.ptr<!s32i>
-// CIR-BEFORE-LPP: %1 = cir.get_global @fp : !cir.ptr<!cir.float>
-// CIR-BEFORE-LPP: %2 = cir.load{{.*}} %1 : !cir.ptr<!cir.float>, !cir.float
-// CIR-BEFORE-LPP: %3 = cir.cast float_to_int %2 : !cir.float -> !s32i
-// CIR-BEFORE-LPP: cir.store{{.*}} %3, %0 : !s32i, !cir.ptr<!s32i>
+// CIR-BEFORE-LPP: %[[I:.*]] = cir.get_global @i : !cir.ptr<!s32i>
+// CIR-BEFORE-LPP: %[[FP:.*]] = cir.get_global @fp : !cir.ptr<!cir.float>
+// CIR-BEFORE-LPP: %[[FP_VAL:.*]] = cir.load{{.*}} %[[FP]] : !cir.ptr<!cir.float>, !cir.float
+// CIR-BEFORE-LPP: %[[FP_I32:.*]] = cir.cast float_to_int %[[FP_VAL]] : !cir.float -> !s32i
+// CIR-BEFORE-LPP: cir.store{{.*}} %[[FP_I32]], %[[I]] : !s32i, !cir.ptr<!s32i>
// CIR-BEFORE-LPP: }
// CIR: cir.func internal private @__cxx_global_var_init.4()
@@ -169,6 +171,97 @@ int i = (int)fp;
// OGCG: %[[FP_I32:.*]] = fptosi float %[[TMP_FP]] to i32
// OGCG: store i32 %[[FP_I32]], ptr @i, align 4
+struct ArrayDtor {
+ ~ArrayDtor();
+};
+
+ArrayDtor arrDtor[16];
+
+// CIR-BEFORE-LPP: cir.global external @arrDtor = #cir.zero : !cir.array<!rec_ArrayDtor x 16>
+// CIR-BEFORE-LPP-SAME: dtor {
+// CIR-BEFORE-LPP: %[[THIS:.*]] = cir.get_global @arrDtor : !cir.ptr<!cir.array<!rec_ArrayDtor x 16>>
+// CIR-BEFORE-LPP: cir.array.dtor %[[THIS]] : !cir.ptr<!cir.array<!rec_ArrayDtor x 16>> {
+// CIR-BEFORE-LPP: ^bb0(%[[ELEM:.*]]: !cir.ptr<!rec_ArrayDtor>):
+// CIR-BEFORE-LPP: cir.call @_ZN9ArrayDtorD1Ev(%[[ELEM]]) nothrow : (!cir.ptr<!rec_ArrayDtor>) -> ()
+// CIR-BEFORE-LPP: cir.yield
+// CIR-BEFORE-LPP: }
+// CIR-BEFORE-LPP: }
+
+// CIR: cir.global external @arrDtor = #cir.zero : !cir.array<!rec_ArrayDtor x 16> {alignment = 16 : i64}
+// CIR: cir.func internal private @__cxx_global_array_dtor(%[[ARR_ARG:.*]]: !cir.ptr<!void> {{.*}}) {
+// CIR: %[[CONST15:.*]] = cir.const #cir.int<15> : !u64i
+// CIR: %[[BEGIN:.*]] = cir.cast array_to_ptrdecay %[[ARR_ARG]] : !cir.ptr<!void> -> !cir.ptr<!rec_ArrayDtor>
+// CIR: %[[END:.*]] = cir.ptr_stride %[[BEGIN]], %[[CONST15]] : (!cir.ptr<!rec_ArrayDtor>, !u64i) -> !cir.ptr<!rec_ArrayDtor>
+// CIR: %[[CUR_ADDR:.*]] = cir.alloca !cir.ptr<!rec_ArrayDtor>, !cir.ptr<!cir.ptr<!rec_ArrayDtor>>, ["__array_idx"]
+// CIR: cir.store %[[END]], %[[CUR_ADDR]] : !cir.ptr<!rec_ArrayDtor>, !cir.ptr<!cir.ptr<!rec_ArrayDtor>>
+// CIR: cir.do {
+// CIR: %[[CUR:.*]] = cir.load %[[CUR_ADDR]] : !cir.ptr<!cir.ptr<!rec_ArrayDtor>>, !cir.ptr<!rec_ArrayDtor>
+// CIR: cir.call @_ZN9ArrayDtorD1Ev(%[[CUR]]) nothrow : (!cir.ptr<!rec_ArrayDtor>) -> ()
+// CIR: %[[NEG_ONE:.*]] = cir.const #cir.int<-1> : !s64i
+// CIR: %[[NEXT:.*]] = cir.ptr_stride %[[CUR]], %[[NEG_ONE]] : (!cir.ptr<!rec_ArrayDtor>, !s64i) -> !cir.ptr<!rec_ArrayDtor>
+// CIR: cir.store %[[NEXT]], %[[CUR_ADDR]] : !cir.ptr<!rec_ArrayDtor>, !cir.ptr<!cir.ptr<!rec_ArrayDtor>>
+// CIR: cir.yield
+// CIR: } while {
+// CIR: %[[CUR:.*]] = cir.load %[[CUR_ADDR]] : !cir.ptr<!cir.ptr<!rec_ArrayDtor>>, !cir.ptr<!rec_ArrayDtor>
+// CIR: %[[CMP:.*]] = cir.cmp(ne, %[[CUR]], %[[BEGIN]]) : !cir.ptr<!rec_ArrayDtor>, !cir.bool
+// CIR: cir.condition(%[[CMP]])
+// CIR: }
+// CIR: cir.return
+// CIR: }
+//
+// CIR: cir.func internal private @__cxx_global_var_init.5() {
+// CIR: %[[ARR:.*]] = cir.get_global @arrDtor : !cir.ptr<!cir.array<!rec_ArrayDtor x 16>>
+// CIR: %[[DTOR:.*]] = cir.get_global @__cxx_global_array_dtor : !cir.ptr<!cir.func<(!cir.ptr<!void>)>>
+// CIR: %[[DTOR_CAST:.*]] = cir.cast bitcast %[[DTOR]] : !cir.ptr<!cir.func<(!cir.ptr<!void>)>> -> !cir.ptr<!cir.func<(!cir.ptr<!void>)>>
+// CIR: %[[ARR_CAST:.*]] = cir.cast bitcast %[[ARR]] : !cir.ptr<!cir.array<!rec_ArrayDtor x 16>> -> !cir.ptr<!void>
+// CIR: %[[HANDLE:.*]] = cir.get_global @__dso_handle : !cir.ptr<i8>
+// CIR: cir.call @__cxa_atexit(%[[DTOR_CAST]], %[[ARR_CAST]], %[[HANDLE]]) : (!cir.ptr<!cir.func<(!cir.ptr<!void>)>>, !cir.ptr<!void>, !cir.ptr<i8>) -> ()
+
+// LLVM: define internal void @__cxx_global_array_dtor(ptr %[[ARR_ARG:.*]]) {
+// LLVM: %[[BEGIN:.*]] = getelementptr %struct.ArrayDtor, ptr %[[ARR_ARG]], i32 0
+// LLVM: %[[END:.*]] = getelementptr %struct.ArrayDtor, ptr %[[BEGIN]], i64 15
+// LLVM: %[[CUR_ADDR:.*]] = alloca ptr
+// LLVM: store ptr %[[END]], ptr %[[CUR_ADDR]]
+// LLVM: br label %[[LOOP_BODY:.*]]
+// LLVM: [[LOOP_COND:.*]]:
+// LLVM: %[[CUR:.*]] = load ptr, ptr %[[CUR_ADDR]]
+// LLVM: %[[CMP:.*]] = icmp ne ptr %[[CUR]], %[[BEGIN]]
+// LLVM: br i1 %[[CMP]], label %[[LOOP_BODY]], label %[[LOOP_END:.*]]
+// LLVM: [[LOOP_BODY]]:
+// LLVM: %[[CUR:.*]] = load ptr, ptr %[[CUR_ADDR]]
+// LLVM: call void @_ZN9ArrayDtorD1Ev(ptr %[[CUR]]) #0
+// LLVM: %[[PREV:.*]] = getelementptr %struct.ArrayDtor, ptr %[[CUR]], i64 -1
+// LLVM: store ptr %[[PREV]], ptr %[[CUR_ADDR]]
+// LLVM: br label %[[LOOP_COND]]
+// LLVM: [[LOOP_END]]:
+// LLVM: ret void
+// LLVM: }
+//
+// LLVM: define internal void @__cxx_global_var_init.5() {
+// LLVM: call void @__cxa_atexit(ptr @__cxx_global_array_dtor, ptr @arrDtor, ptr @__dso_handle)
+
+// Note: OGCG defines these functions in reverse order of CIR->LLVM.
+// Note also: OGCG doesn't pass the address of the array to the destructor function.
+// Instead, it uses the global directly in the helper function.
+
+// OGCG: define internal void @__cxx_global_var_init.5() {{.*}} section ".text.startup" {
+// OGCG: call i32 @__cxa_atexit(ptr @__cxx_global_array_dtor, ptr null, ptr @__dso_handle)
+
+// OGCG: define internal void @__cxx_global_array_dtor(ptr noundef %[[ARG:.*]]) {{.*}} section ".text.startup" {
+// OGCG: entry:
+// OGCG: %[[UNUSED_ADDR:.*]] = alloca ptr
+// OGCG: store ptr %[[ARG]], ptr %[[UNUSED_ADDR]]
+// OGCG: br label %[[LOOP_BODY:.*]]
+// OGCG: [[LOOP_BODY]]:
+// OGCG: %[[PREV:.*]] = phi ptr [ getelementptr inbounds (%struct.ArrayDtor, ptr @arrDtor, i64 16), %entry ], [ %[[CUR:.*]], %[[LOOP_BODY]] ]
+// OGCG: %[[CUR]] = getelementptr inbounds %struct.ArrayDtor, ptr %[[PREV]], i64 -1
+// OGCG: call void @_ZN9ArrayDtorD1Ev(ptr noundef nonnull align 1 dereferenceable(1) %[[CUR]])
+// OGCG: %[[DONE:.*]] = icmp eq ptr %[[CUR]], @arrDtor
+// OGCG: br i1 %[[DONE]], label %[[LOOP_END:.*]], label %[[LOOP_BODY]]
+// OGCG: [[LOOP_END]]:
+// OGCG: ret void
+// OGCG: }
+
// Common init function for all globals with default priority
// CIR: cir.func private @_GLOBAL__sub_I_[[FILENAME:.*]]() {
@@ -177,6 +270,7 @@ int i = (int)fp;
// CIR: cir.call @__cxx_global_var_init.2() : () -> ()
// CIR: cir.call @__cxx_global_var_init.3() : () -> ()
// CIR: cir.call @__cxx_global_var_init.4() : () -> ()
+// CIR: cir.call @__cxx_global_var_init.5() : () -> ()
// LLVM: define void @_GLOBAL__sub_I_[[FILENAME]]()
// LLVM: call void @__cxx_global_var_init()
@@ -184,6 +278,7 @@ int i = (int)fp;
// LLVM: call void @__cxx_global_var_init.2()
// LLVM: call void @__cxx_global_var_init.3()
// LLVM: call void @__cxx_global_var_init.4()
+// LLVM: call void @__cxx_global_var_init.5()
// OGCG: define internal void @_GLOBAL__sub_I_[[FILENAME]]() {{.*}} section ".text.startup" {
// OGCG: call void @__cxx_global_var_init()
@@ -191,3 +286,4 @@ int i = (int)fp;
// OGCG: call void @__cxx_global_var_init.2()
// OGCG: call void @__cxx_global_var_init.3()
// OGCG: call void @__cxx_global_var_init.4()
+// OGCG: call void @__cxx_global_var_init.5()
diff --git a/clang/test/CIR/CodeGen/globals.cpp b/clang/test/CIR/CodeGen/globals.cpp
index a3e1613..848cac8 100644
--- a/clang/test/CIR/CodeGen/globals.cpp
+++ b/clang/test/CIR/CodeGen/globals.cpp
@@ -35,3 +35,9 @@ int *constArrAddr = &arr[2][1];
// LLVM: @constArrAddr = global ptr getelementptr inbounds nuw (i8, ptr @arr, i64 132), align 8
// OGCG: @constArrAddr = global ptr getelementptr (i8, ptr @arr, i64 132), align 8
+
+bool bool_global = true;
+
+// CIR: cir.global external @bool_global = #true {alignment = 1 : i64}
+// LLVM: @bool_global = global i8 1, align 1
+// OGCG: @bool_global = global i8 1, align 1
diff --git a/clang/test/CIR/CodeGen/gnu-null.cpp b/clang/test/CIR/CodeGen/gnu-null.cpp
new file mode 100644
index 0000000..d1d15f2
--- /dev/null
+++ b/clang/test/CIR/CodeGen/gnu-null.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -std=c++20 -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 -std=c++20 -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 -std=c++20 -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 gnu_null_expr() {
+ long a = __null;
+ int *b = __null;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !s64i, !cir.ptr<!s64i>, ["a", init]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["b", init]
+// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s64i
+// CIR: cir.store {{.*}} %[[CONST_0]], %[[A_ADDR]] : !s64i, !cir.ptr<!s64i>
+// CIR: %[[CONST_NULL:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!s32i>
+// CIR: cir.store {{.*}} %[[CONST_NULL]], %[[B_ADDR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
+
+// LLVM: %[[A_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[B_ADDR:.*]] = alloca ptr, i64 1, align 8
+// LLVM: store i64 0, ptr %[[A_ADDR]], align 8
+// LLVM: store ptr null, ptr %[[B_ADDR]], align 8
+
+// OGCG: %[[A_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[B_ADDR:.*]] = alloca ptr, align 8
+// OGCG: store i64 0, ptr %[[A_ADDR]], align 8
+// OGCG: store ptr null, ptr %[[B_ADDR]], align 8
diff --git a/clang/test/CIR/CodeGen/goto.cpp b/clang/test/CIR/CodeGen/goto.cpp
index 257c255..4b825d6 100644
--- a/clang/test/CIR/CodeGen/goto.cpp
+++ b/clang/test/CIR/CodeGen/goto.cpp
@@ -12,7 +12,7 @@ int shouldNotGenBranchRet(int x) {
err:
return -1;
}
-// CIR: cir.func dso_local @_Z21shouldNotGenBranchReti
+// CIR: cir.func {{.*}} @_Z21shouldNotGenBranchReti
// CIR: cir.if {{.*}} {
// CIR: cir.goto "err"
// CIR: }
@@ -63,7 +63,7 @@ int shouldGenBranch(int x) {
err:
return -1;
}
-// CIR: cir.func dso_local @_Z15shouldGenBranchi
+// CIR: cir.func {{.*}} @_Z15shouldGenBranchi
// CIR: cir.if {{.*}} {
// CIR: cir.goto "err"
// CIR: }
@@ -99,7 +99,7 @@ end1:
end2:
b = b + 2;
}
-// CIR: cir.func dso_local @_Z19severalLabelsInARowi
+// CIR: cir.func {{.*}} @_Z19severalLabelsInARowi
// CIR: cir.goto "end1"
// CIR: ^bb[[#BLK1:]]
// CIR: cir.goto "end2"
@@ -132,7 +132,7 @@ void severalGotosInARow(int a) {
end:
b = b + 2;
}
-// CIR: cir.func dso_local @_Z18severalGotosInARowi
+// CIR: cir.func {{.*}} @_Z18severalGotosInARowi
// CIR: cir.goto "end"
// CIR: ^bb[[#BLK1:]]:
// CIR: cir.goto "end"
@@ -163,7 +163,7 @@ extern "C" void multiple_non_case(int v) {
}
}
-// CIR: cir.func dso_local @multiple_non_case
+// CIR: cir.func {{.*}} @multiple_non_case
// CIR: cir.switch
// CIR: cir.case(default, []) {
// CIR: cir.call @action1()
@@ -202,7 +202,7 @@ extern "C" void case_follow_label(int v) {
}
}
-// CIR: cir.func dso_local @case_follow_label
+// CIR: cir.func {{.*}} @case_follow_label
// CIR: cir.switch
// CIR: cir.case(equal, [#cir.int<1> : !s32i]) {
// CIR: cir.br ^bb1
@@ -264,7 +264,7 @@ extern "C" void default_follow_label(int v) {
}
}
-// CIR: cir.func dso_local @default_follow_label
+// CIR: cir.func {{.*}} @default_follow_label
// CIR: cir.switch
// CIR: cir.case(equal, [#cir.int<1> : !s32i]) {
// CIR: cir.yield
@@ -313,7 +313,7 @@ label:
goto label;
}
-// CIR: cir.func dso_local @_Z2g3v
+// CIR: cir.func {{.*}} @_Z2g3v
// CIR: cir.br ^bb1
// CIR: ^bb1:
// CIR: cir.label "label"
diff --git a/clang/test/CIR/CodeGen/inline-attributes.cpp b/clang/test/CIR/CodeGen/inline-attributes.cpp
index fab4010..5477797 100644
--- a/clang/test/CIR/CodeGen/inline-attributes.cpp
+++ b/clang/test/CIR/CodeGen/inline-attributes.cpp
@@ -29,17 +29,17 @@ int (*inline_hint_ptr)(int) = &inline_hint_function;
int (*noinline_ptr)(int) = &noinline_function;
int (*regular_ptr)(int) = &regular_function;
-// CIR-LABEL: cir.func dso_local @_Z17noinline_functioni(%arg0: !s32i {{.*}}) -> !s32i inline(never)
+// CIR-LABEL: cir.func no_inline dso_local @_Z17noinline_functioni(%arg0: !s32i {{.*}}) -> !s32i
// CIR-LABEL: cir.func dso_local @_Z16regular_functioni(%arg0: !s32i {{.*}}) -> !s32i
-// CIR-NOT: inline(never)
-// CIR-NOT: inline(always)
-// CIR-NOT: inline(hint)
+// CIR-NOT: no_inline
+// CIR-NOT: always_inline
+// CIR-NOT: inline_hint
// CIR-SAME: {
-// CIR-LABEL: cir.func {{.*}}@_Z22always_inline_functioni(%arg0: !s32i {{.*}}) -> !s32i inline(always)
+// CIR-LABEL: cir.func{{.*}} always_inline {{.*}}@_Z22always_inline_functioni(%arg0: !s32i {{.*}}) -> !s32i
-// CIR-LABEL: cir.func {{.*}}@_Z20inline_hint_functioni(%arg0: !s32i {{.*}}) -> !s32i inline(hint)
+// CIR-LABEL: cir.func{{.*}} inline_hint {{.*}}@_Z20inline_hint_functioni(%arg0: !s32i {{.*}}) -> !s32i
// LLVM: ; Function Attrs:{{.*}} noinline
// LLVM: define{{.*}} i32 @_Z17noinline_functioni
diff --git a/clang/test/CIR/CodeGen/kr-func-promote.c b/clang/test/CIR/CodeGen/kr-func-promote.c
new file mode 100644
index 0000000..5fed068
--- /dev/null
+++ b/clang/test/CIR/CodeGen/kr-func-promote.c
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c89 -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 -std=c89 -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 -std=c89 -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+// CIR: cir.func {{.*}}@foo(%arg0: !s32i
+// CIR: %0 = cir.alloca !s16i, !cir.ptr<!s16i>, ["x", init]
+// CIR: %1 = cir.cast integral %arg0 : !s32i -> !s16i
+// CIR: cir.store %1, %0 : !s16i, !cir.ptr<!s16i>
+// expected-warning@+1 {{a function definition without a prototype is deprecated}}
+void foo(x) short x; {}
+
+// LLVM: define{{.*}} void @foo(i32 %0)
+// LLVM: %[[X_PTR:.*]] = alloca i16, i64 1, align 2
+// LLVM: %[[X:.*]] = trunc i32 %0 to i16
+// LLVM: store i16 %[[X]], ptr %[[X_PTR]], align 2
+
+// OGCG: define{{.*}} void @foo(i32 noundef %0)
+// OGCG: entry:
+// OGCG: %[[X_PTR:.*]] = alloca i16, align 2
+// OGCG: %[[X:.*]] = trunc i32 %0 to i16
+// OGCG: store i16 %[[X]], ptr %[[X_PTR]], align 2
+
+// CIR: cir.func{{.*}}no_proto dso_local @bar(%arg0: !cir.double
+// CIR: %0 = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["f", init]
+// CIR: %1 = cir.cast floating %arg0 : !cir.double -> !cir.float
+// CIR: cir.store %1, %0 : !cir.float, !cir.ptr<!cir.float>
+// expected-warning@+1 {{a function definition without a prototype is deprecated}}
+void bar(f) float f; {}
+
+// LLVM: define{{.*}} void @bar(double %0)
+// LLVM: %[[F_PTR:.*]] = alloca float, i64 1, align 4
+// LLVM: %[[F:.*]] = fptrunc double %0 to float
+// LLVM: store float %[[F]], ptr %[[F_PTR]], align 4
+
+// OGCG: define{{.*}} void @bar(double noundef %0)
+// OGCG: entry:
+// OGCG: %[[F_PTR:.*]] = alloca float, align 4
+// OGCG: %[[F:.*]] = fptrunc double %0 to float
+// OGCG: store float %[[F]], ptr %[[F_PTR]], align 4
diff --git a/clang/test/CIR/CodeGen/label-values.c b/clang/test/CIR/CodeGen/label-values.c
new file mode 100644
index 0000000..750ef1f6
--- /dev/null
+++ b/clang/test/CIR/CodeGen/label-values.c
@@ -0,0 +1,204 @@
+// RUN: %clang_cc1 -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 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG
+
+void A(void) {
+ void *ptr = &&LABEL_A;
+ goto *ptr;
+LABEL_A:
+ return;
+}
+// CIR: cir.func {{.*}} @A
+// CIR: [[PTR:%.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] {alignment = 8 : i64}
+// CIR: [[BLOCK:%.*]] = cir.block_address <@A, "LABEL_A"> : !cir.ptr<!void>
+// CIR: cir.store align(8) [[BLOCK]], [[PTR]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
+// CIR: [[BLOCKADD:%.*]] = cir.load align(8) [[PTR]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+// CIR: cir.br ^bb1([[BLOCKADD]] : !cir.ptr<!void>)
+// CIR: ^bb1([[PHI:%.*]]: !cir.ptr<!void> {{.*}}): // pred: ^bb0
+// CIR: cir.indirect_br [[PHI]] : !cir.ptr<!void>, [
+// CIR: ^bb2
+// CIR: ]
+// CIR: ^bb2: // pred: ^bb1
+// CIR: cir.label "LABEL_A"
+// CIR: cir.return
+
+// OGCG: define dso_local void @A()
+// OGCG: [[PTR:%.*]] = alloca ptr, align 8
+// OGCG: store ptr blockaddress(@A, %LABEL_A), ptr [[PTR]], align 8
+// OGCG: [[BLOCKADD:%.*]] = load ptr, ptr [[PTR]], align 8
+// OGCG: br label %indirectgoto
+// OGCG: LABEL_A: ; preds = %indirectgoto
+// OGCG: ret void
+// OGCG: indirectgoto: ; preds = %entry
+// OGCG: %indirect.goto.dest = phi ptr [ [[BLOCKADD]], %entry ]
+// OGCG: indirectbr ptr %indirect.goto.dest, [label %LABEL_A]
+
+void B(void) {
+LABEL_B:
+ void *ptr = &&LABEL_B;
+ goto *ptr;
+}
+
+// CIR: cir.func {{.*}} @B()
+// CIR: [[PTR:%.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init] {alignment = 8 : i64}
+// CIR: cir.br ^bb1
+// CIR: ^bb1: // 2 preds: ^bb0, ^bb2
+// CIR: cir.label "LABEL_B"
+// CIR: [[BLOCK:%.*]] = cir.block_address <@B, "LABEL_B"> : !cir.ptr<!void>
+// CIR: cir.store align(8) [[BLOCK]], [[PTR]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
+// CIR: [[BLOCKADD:%.*]] = cir.load align(8) [[PTR]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+// CIR: cir.br ^bb2([[BLOCKADD]] : !cir.ptr<!void>)
+// CIR: ^bb2([[PHI:%.*]]: !cir.ptr<!void> {{.*}}): // pred: ^bb1
+// CIR: cir.indirect_br [[PHI]] : !cir.ptr<!void>, [
+// CIR-NEXT: ^bb1
+// CIR: ]
+
+// OGCG: define dso_local void @B
+// OGCG: [[PTR:%.*]] = alloca ptr, align 8
+// OGCG: br label %LABEL_B
+// OGCG: LABEL_B: ; preds = %indirectgoto, %entry
+// OGCG: store ptr blockaddress(@B, %LABEL_B), ptr [[PTR]], align 8
+// OGCG: [[BLOCKADD:%.*]] = load ptr, ptr [[PTR]], align 8
+// OGCG: br label %indirectgoto
+// OGCG: indirectgoto: ; preds = %LABEL_B
+// OGCG: %indirect.goto.dest = phi ptr [ [[BLOCKADD]], %LABEL_B ]
+// OGCG: indirectbr ptr %indirect.goto.dest, [label %LABEL_B]
+
+void C(int x) {
+ void *ptr = (x == 0) ? &&LABEL_A : &&LABEL_B;
+ goto *ptr;
+LABEL_A:
+ return;
+LABEL_B:
+ return;
+}
+
+// CIR: cir.func {{.*}} @C
+// CIR: [[BLOCK1:%.*]] = cir.block_address <@C, "LABEL_A"> : !cir.ptr<!void>
+// CIR: [[BLOCK2:%.*]] = cir.block_address <@C, "LABEL_B"> : !cir.ptr<!void>
+// CIR: [[COND:%.*]] = cir.select if [[CMP:%.*]] then [[BLOCK1]] else [[BLOCK2]] : (!cir.bool, !cir.ptr<!void>, !cir.ptr<!void>) -> !cir.ptr<!void>
+// CIR: cir.store align(8) [[COND]], [[PTR:%.*]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
+// CIR: [[BLOCKADD:%.*]] = cir.load align(8) [[PTR]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+// CIR: cir.br ^bb1([[BLOCKADD]] : !cir.ptr<!void>)
+// CIR: ^bb1([[PHI:%.*]]: !cir.ptr<!void> {{.*}}): // pred: ^bb0
+// CIR: cir.indirect_br [[PHI]] : !cir.ptr<!void>, [
+// CIR-NEXT: ^bb2,
+// CIR-NEXT: ^bb4
+// CIR: ]
+// CIR: ^bb2: // pred: ^bb1
+// CIR: cir.label "LABEL_A"
+// CIR: cir.br ^bb3
+// CIR: ^bb3: // 2 preds: ^bb2, ^bb4
+// CIR: cir.return
+// CIR: ^bb4: // pred: ^bb1
+// CIR: cir.label "LABEL_B"
+// CIR: cir.br ^bb3
+
+// OGCG: define dso_local void @C
+// OGCG: [[COND:%.*]] = select i1 [[CMP:%.*]], ptr blockaddress(@C, %LABEL_A), ptr blockaddress(@C, %LABEL_B)
+// OGCG: store ptr [[COND]], ptr [[PTR:%.*]], align 8
+// OGCG: [[BLOCKADD:%.*]] = load ptr, ptr [[PTR]], align 8
+// OGCG: br label %indirectgoto
+// OGCG: LABEL_A: ; preds = %indirectgoto
+// OGCG: br label %return
+// OGCG: LABEL_B: ; preds = %indirectgoto
+// OGCG: br label %return
+// OGCG: return: ; preds = %LABEL_B, %LABEL_A
+// OGCG: ret void
+// OGCG: indirectgoto: ; preds = %entry
+// OGCG: %indirect.goto.dest = phi ptr [ [[BLOCKADD]], %entry ]
+// OGCG: indirectbr ptr %indirect.goto.dest, [label %LABEL_A, label %LABEL_B]
+
+void D(void) {
+ void *ptr = &&LABEL_A;
+ void *ptr2 = &&LABEL_A;
+ goto *ptr2;
+LABEL_A:
+ void *ptr3 = &&LABEL_A;
+ return;
+}
+
+// CIR: cir.func {{.*}} @D
+// CIR: %[[PTR:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr", init]
+// CIR: %[[PTR2:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr2", init]
+// CIR: %[[PTR3:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["ptr3", init]
+// CIR: %[[BLK1:.*]] = cir.block_address <@D, "LABEL_A"> : !cir.ptr<!void>
+// CIR: cir.store align(8) %[[BLK1]], %[[PTR]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
+// CIR: %[[BLK2:.*]] = cir.block_address <@D, "LABEL_A"> : !cir.ptr<!void>
+// CIR: cir.store align(8) %[[BLK2]], %[[PTR2]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
+// CIR: cir.br ^bb1
+// CIR: ^bb1([[PHI:%*.]]: !cir.ptr<!void> {{.*}}): // pred: ^bb0
+// CIR: cir.indirect_br [[PHI]] : !cir.ptr<!void>, [
+// CIR-DAG: ^bb2,
+// CIR-DAG: ^bb2,
+// CIR-DAG: ^bb2
+// CIR: ]
+// CIR: ^bb2: // 3 preds: ^bb1, ^bb1, ^bb1
+// CIR: cir.label "LABEL_A"
+// CIR: %[[BLK3:.*]] = cir.block_address <@D, "LABEL_A"> : !cir.ptr<!void>
+// CIR: cir.store align(8) %[[BLK3]], %[[PTR3]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
+// CIR: cir.return
+
+// OGCG: define dso_local void @D
+// OGCG: %[[PTR:.*]] = alloca ptr, align 8
+// OGCG: %[[PTR2:.*]] = alloca ptr, align 8
+// OGCG: %[[PTR3:.*]] = alloca ptr, align 8
+// OGCG: store ptr blockaddress(@D, %LABEL_A), ptr %[[PTR]], align 8
+// OGCG: store ptr blockaddress(@D, %LABEL_A), ptr %[[PTR2]], align 8
+// OGCG: %[[BLOCKADD:.*]] = load ptr, ptr %[[PTR2]], align 8
+// OGCG: br label %indirectgoto
+// OGCG: LABEL_A: ; preds = %indirectgoto, %indirectgoto, %indirectgoto
+// OGCG: store ptr blockaddress(@D, %LABEL_A), ptr %[[PTR3]], align 8
+// OGCG: ret void
+// OGCG: indirectgoto: ; preds = %entry
+// OGCG: %indirect.goto.dest = phi ptr [ %[[BLOCKADD]], %entry ]
+// OGCG: indirectbr ptr %indirect.goto.dest, [label %LABEL_A, label %LABEL_A, label %LABEL_A]
+
+// This test checks that CIR preserves insertion order of blockaddresses
+// for indirectbr, even if some were resolved immediately and others later.
+void E(void) {
+ void *ptr = &&LABEL_D;
+ void *ptr2 = &&LABEL_C;
+LABEL_A:
+LABEL_B:
+ void *ptr3 = &&LABEL_B;
+ void *ptr4 = &&LABEL_A;
+LABEL_C:
+LABEL_D:
+ return;
+}
+
+//CIR: cir.func {{.*}} @E()
+//CIR: ^bb1({{.*}}: !cir.ptr<!void> {{.*}}): // no predecessors
+//CIR: cir.indirect_br {{.*}} poison : !cir.ptr<!void>, [
+//CIR-NEXT: ^bb5,
+//CIR-NEXT: ^bb4,
+//CIR-NEXT: ^bb3,
+//CIR-NEXT: ^bb2
+//CIR: ]
+//CIR: ^bb2: // 2 preds: ^bb0, ^bb1
+//CIR: cir.label "LABEL_A"
+//CIR: ^bb3: // 2 preds: ^bb1, ^bb2
+//CIR: cir.label "LABEL_B"
+//CIR: ^bb4: // 2 preds: ^bb1, ^bb3
+//CIR: cir.label "LABEL_C"
+//CIR: ^bb5: // 2 preds: ^bb1, ^bb4
+//CIR: cir.label "LABEL_D"
+
+// OGCG: define dso_local void @E() #0 {
+// OGCG: store ptr blockaddress(@E, %LABEL_D), ptr %ptr, align 8
+// OGCG: store ptr blockaddress(@E, %LABEL_C), ptr %ptr2, align 8
+// OGCG: br label %LABEL_A
+// OGCG: A: ; preds = %indirectgoto, %entry
+// OGCG: br label %LABEL_B
+// OGCG: B: ; preds = %indirectgoto, %LABEL_A
+// OGCG: store ptr blockaddress(@E, %LABEL_B), ptr %ptr3, align 8
+// OGCG: store ptr blockaddress(@E, %LABEL_A), ptr %ptr4, align 8
+// OGCG: br label %LABEL_C
+// OGCG: C: ; preds = %LABEL_B, %indirectgoto
+// OGCG: br label %LABEL_D
+// OGCG: D: ; preds = %LABEL_C, %indirectgoto
+// OGCG: ret void
+// OGCG: indirectgoto: ; No predecessors!
+// OGCG: indirectbr ptr poison, [label %LABEL_D, label %LABEL_C, label %LABEL_B, label %LABEL_A]
diff --git a/clang/test/CIR/CodeGen/label.c b/clang/test/CIR/CodeGen/label.c
index fd3c7f2..d3fdf5f 100644
--- a/clang/test/CIR/CodeGen/label.c
+++ b/clang/test/CIR/CodeGen/label.c
@@ -10,7 +10,7 @@ labelA:
return;
}
-// CIR: cir.func no_proto dso_local @label
+// CIR: cir.func {{.*}} @label
// CIR: cir.br ^bb1
// CIR: ^bb1:
// CIR: cir.label "labelA"
@@ -32,7 +32,7 @@ labelC:
return;
}
-// CIR: cir.func no_proto dso_local @multiple_labels
+// CIR: cir.func {{.*}} @multiple_labels
// CIR: cir.br ^bb1
// CIR: ^bb1:
// CIR: cir.label "labelB"
@@ -62,7 +62,7 @@ labelD:
}
}
-// CIR: cir.func dso_local @label_in_if
+// CIR: cir.func {{.*}} @label_in_if
// CIR: cir.if {{.*}} {
// CIR: cir.br ^bb1
// CIR: ^bb1:
@@ -107,7 +107,7 @@ void after_return() {
label:
}
-// CIR: cir.func no_proto dso_local @after_return
+// CIR: cir.func {{.*}} @after_return
// CIR: cir.br ^bb1
// CIR: ^bb1: // 2 preds: ^bb0, ^bb2
// CIR: cir.return
@@ -133,7 +133,7 @@ void after_unreachable() {
label:
}
-// CIR: cir.func no_proto dso_local @after_unreachable
+// CIR: cir.func {{.*}} @after_unreachable
// CIR: cir.unreachable
// CIR: ^bb1:
// CIR: cir.label "label"
@@ -153,7 +153,7 @@ void labelWithoutMatch() {
end:
return;
}
-// CIR: cir.func no_proto dso_local @labelWithoutMatch
+// CIR: cir.func {{.*}} @labelWithoutMatch
// CIR: cir.br ^bb1
// CIR: ^bb1:
// CIR: cir.label "end"
@@ -181,7 +181,7 @@ void foo() {
}
}
-// CIR: cir.func no_proto dso_local @foo
+// CIR: cir.func {{.*}} @foo
// CIR: cir.scope {
// CIR: %0 = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["agg.tmp0"]
// CIR: cir.br ^bb1
diff --git a/clang/test/CIR/CodeGen/lambda-static-invoker.cpp b/clang/test/CIR/CodeGen/lambda-static-invoker.cpp
index e7d199b..fc68447f 100644
--- a/clang/test/CIR/CodeGen/lambda-static-invoker.cpp
+++ b/clang/test/CIR/CodeGen/lambda-static-invoker.cpp
@@ -37,7 +37,7 @@ int g3() {
// OGCG: ret ptr @"_ZZ2g3vEN3$_08__invokeERKi"
// lambda operator()
-// CIR: cir.func lambda internal private dso_local @_ZZ2g3vENK3$_0clERKi(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_G3:.*]]> {{.*}}, %[[REF_I_ARG:.*]]: !cir.ptr<!s32i> {{.*}})
+// CIR: cir.func no_inline lambda internal private dso_local @_ZZ2g3vENK3$_0clERKi(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_G3:.*]]> {{.*}}, %[[REF_I_ARG:.*]]: !cir.ptr<!s32i> {{.*}})
// CIR: %[[THIS_ALLOCA:.*]] = cir.alloca !cir.ptr<![[REC_LAM_G3]]>, !cir.ptr<!cir.ptr<![[REC_LAM_G3]]>>, ["this", init]
// CIR: %[[REF_I_ALLOCA:.*]] = cir.alloca {{.*}} ["i", init, const]
// CIR: %[[RETVAL:.*]] = cir.alloca {{.*}} ["__retval"]
@@ -66,7 +66,7 @@ int g3() {
// In OGCG, the _ZZ2g3vENK3$_0clERKi function is emitted after _ZZ2g3vEN3$_08__invokeERKi, see below.
// lambda invoker
-// CIR: cir.func internal private dso_local @_ZZ2g3vEN3$_08__invokeERKi(%[[REF_I_ARG:.*]]: !cir.ptr<!s32i> {{.*}}) -> !s32i{{.*}} {
+// CIR: cir.func no_inline internal private dso_local @_ZZ2g3vEN3$_08__invokeERKi(%[[REF_I_ARG:.*]]: !cir.ptr<!s32i> {{.*}}) -> !s32i{{.*}} {
// CIR: %[[REF_I_ALLOCA:.*]] = cir.alloca {{.*}} ["i", init, const]
// CIR: %[[RETVAL:.*]] = cir.alloca {{.*}} ["__retval"]
// CIR: %[[LAM_ALLOCA:.*]] = cir.alloca ![[REC_LAM_G3]], !cir.ptr<![[REC_LAM_G3]]>, ["unused.capture"]
@@ -91,7 +91,7 @@ int g3() {
// In OGCG, the _ZZ2g3vEN3$_08__invokeERKi function is emitted after _ZN1A3barEv, see below.
// lambda operator int (*)(int const&)()
-// CIR: cir.func internal private dso_local @_ZZ2g3vENK3$_0cvPFiRKiEEv(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_G3]]> {{.*}}) -> !cir.ptr<!cir.func<(!cir.ptr<!s32i>) -> !s32i>>{{.*}} {
+// CIR: cir.func no_inline internal private dso_local @_ZZ2g3vENK3$_0cvPFiRKiEEv(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_G3]]> {{.*}}) -> !cir.ptr<!cir.func<(!cir.ptr<!s32i>) -> !s32i>>{{.*}} {
// CIR: %[[THIS_ALLOCA:.*]] = cir.alloca !cir.ptr<![[REC_LAM_G3]]>, !cir.ptr<!cir.ptr<![[REC_LAM_G3]]>>, ["this", init]
// CIR: %[[RETVAL:.*]] = cir.alloca !cir.ptr<!cir.func<(!cir.ptr<!s32i>) -> !s32i>>, !cir.ptr<!cir.ptr<!cir.func<(!cir.ptr<!s32i>) -> !s32i>>>, ["__retval"]
// CIR: cir.store %[[THIS_ARG]], %[[THIS_ALLOCA]]
diff --git a/clang/test/CIR/CodeGen/lambda.cpp b/clang/test/CIR/CodeGen/lambda.cpp
index 91380b9..3c2b096 100644
--- a/clang/test/CIR/CodeGen/lambda.cpp
+++ b/clang/test/CIR/CodeGen/lambda.cpp
@@ -8,18 +8,51 @@
// We declare anonymous record types to represent lambdas. Rather than trying to
// to match the declarations, we establish variables for these when they are used.
+auto global_lambda = [](){};
+void use_global_lambda() {
+ global_lambda();
+}
+
+// CIR: cir.global "private" internal dso_local @global_lambda = #cir.undef : ![[REC_LAM_GLOBAL_LAMBDA:.*]] {alignment = 1 : i64}
+// CIR: cir.func {{.*}} lambda internal private dso_local @_ZNK3$_0clEv(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_GLOBAL_LAMBDA]]> {{.*}})
+// CIR: %[[THIS:.*]] = cir.alloca !cir.ptr<![[REC_LAM_GLOBAL_LAMBDA]]>, !cir.ptr<!cir.ptr<![[REC_LAM_GLOBAL_LAMBDA]]>>, ["this", init]
+// CIR: cir.store %[[THIS_ARG]], %[[THIS]]
+// CIR: cir.load %[[THIS]]
+//
+// CIR: cir.func {{.*}} @_Z17use_global_lambdav()
+// CIR: %[[LAMBDA:.*]] = cir.get_global @global_lambda : !cir.ptr<![[REC_LAM_GLOBAL_LAMBDA]]>
+// CIR: cir.call @_ZNK3$_0clEv(%[[LAMBDA]]) : (!cir.ptr<![[REC_LAM_GLOBAL_LAMBDA]]>) -> ()
+
+// LLVM: @global_lambda = internal global %[[REC_LAM_GLOBAL_LAMBDA:.*]] undef, align 1
+// LLVM: define internal void @"_ZNK3$_0clEv"(ptr %[[THIS_ARG:.*]])
+// LLVM: %[[THIS_ADDR:.*]] = alloca ptr
+// LLVM: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
+// LLVM: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
+//
+// LLVM: define dso_local void @_Z17use_global_lambdav()
+// LLVM: call void @"_ZNK3$_0clEv"(ptr @global_lambda)
+
+// OGCG: @global_lambda = internal global %[[REC_LAM_GLOBAL_LAMBDA:.*]] undef, align 1
+// OGCG: define dso_local void @_Z17use_global_lambdav()
+// OGCG: call void @"_ZNK3$_0clEv"(ptr noundef nonnull align 1 dereferenceable(1) @global_lambda)
+//
+// OGCG: define internal void @"_ZNK3$_0clEv"(ptr {{.*}} %[[THIS_ARG:.*]])
+// OGCG: %[[THIS_ADDR:.*]] = alloca ptr
+// OGCG: store ptr %[[THIS_ARG]], ptr %[[THIS_ADDR]]
+// OGCG: %[[THIS:.*]] = load ptr, ptr %[[THIS_ADDR]]
+
void fn() {
auto a = [](){};
a();
}
-// CIR: cir.func lambda internal private dso_local @_ZZ2fnvENK3$_0clEv(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_FN_A:.*]]> {{.*}}) {{.*}} {
+// CIR: cir.func {{.*}} lambda internal private dso_local @_ZZ2fnvENK3$_0clEv(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_FN_A:.*]]> {{.*}})
// CIR: %[[THIS:.*]] = cir.alloca !cir.ptr<![[REC_LAM_FN_A]]>, !cir.ptr<!cir.ptr<![[REC_LAM_FN_A]]>>, ["this", init]
// CIR: cir.store %[[THIS_ARG]], %[[THIS]]
// CIR: cir.load %[[THIS]]
// CIR: cir.return
-// CIR: cir.func dso_local @_Z2fnv() {{.*}} {
+// CIR: cir.func {{.*}} @_Z2fnv()
// CIR: %[[A:.*]] = cir.alloca ![[REC_LAM_FN_A]], !cir.ptr<![[REC_LAM_FN_A]]>, ["a"]
// CIR: cir.call @_ZZ2fnvENK3$_0clEv(%[[A]])
@@ -52,7 +85,7 @@ void l0() {
a();
}
-// CIR: cir.func lambda internal private dso_local @_ZZ2l0vENK3$_0clEv(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_L0_A:.*]]> {{.*}}) {{.*}} {
+// CIR: cir.func {{.*}} lambda internal private dso_local @_ZZ2l0vENK3$_0clEv(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_L0_A:.*]]> {{.*}})
// CIR: %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<![[REC_LAM_L0_A]]>, !cir.ptr<!cir.ptr<![[REC_LAM_L0_A]]>>, ["this", init] {alignment = 8 : i64}
// CIR: cir.store %[[THIS_ARG]], %[[THIS_ADDR]]
// CIR: %[[THIS:.*]] = cir.load %[[THIS_ADDR]]
@@ -66,7 +99,7 @@ void l0() {
// CIR: cir.store{{.*}} %[[I_PLUS_ONE]], %[[I_ADDR]]
// CIR: cir.return
-// CIR: cir.func {{.*}} @_Z2l0v() {{.*}} {
+// CIR: cir.func {{.*}} @_Z2l0v()
// CIR: %[[I:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i"]
// CIR: %[[A:.*]] = cir.alloca ![[REC_LAM_L0_A]], !cir.ptr<![[REC_LAM_L0_A]]>, ["a", init]
// CIR: %[[I_ADDR:.*]] = cir.get_member %[[A]][0] {name = "i"}
@@ -124,7 +157,7 @@ auto g() {
};
}
-// CIR: cir.func dso_local @_Z1gv() -> ![[REC_LAM_G:.*]] {{.*}} {
+// CIR: cir.func {{.*}} @_Z1gv() -> ![[REC_LAM_G:.*]] {
// CIR: %[[RETVAL:.*]] = cir.alloca ![[REC_LAM_G]], !cir.ptr<![[REC_LAM_G]]>, ["__retval"]
// CIR: %[[I_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init]
// CIR: %[[TWELVE:.*]] = cir.const #cir.int<12> : !s32i
@@ -166,7 +199,7 @@ auto g2() {
}
// Should be same as above because of NRVO
-// CIR: cir.func dso_local @_Z2g2v() -> ![[REC_LAM_G2:.*]] {{.*}} {
+// CIR: cir.func {{.*}} @_Z2g2v() -> ![[REC_LAM_G2:.*]] {
// CIR: %[[RETVAL:.*]] = cir.alloca ![[REC_LAM_G2]], !cir.ptr<![[REC_LAM_G2]]>, ["__retval", init]
// CIR: %[[I_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init]
// CIR: %[[TWELVE:.*]] = cir.const #cir.int<12> : !s32i
@@ -199,7 +232,7 @@ int f() {
return g2()();
}
-// CIR:cir.func lambda internal private dso_local @_ZZ2g2vENK3$_0clEv(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_G2]]> {{.*}}) -> !s32i {{.*}} {
+// CIR:cir.func {{.*}} lambda internal private dso_local @_ZZ2g2vENK3$_0clEv(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_G2]]> {{.*}}) -> !s32i
// CIR: %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<![[REC_LAM_G2]]>, !cir.ptr<!cir.ptr<![[REC_LAM_G2]]>>, ["this", init]
// CIR: %[[RETVAL:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
// CIR: cir.store %[[THIS_ARG]], %[[THIS_ADDR]]
@@ -217,7 +250,7 @@ int f() {
// CIR: %[[RET:.*]] = cir.load %[[RETVAL]]
// CIR: cir.return %[[RET]]
-// CIR: cir.func dso_local @_Z1fv() -> !s32i {{.*}} {
+// CIR: cir.func {{.*}} @_Z1fv() -> !s32i
// CIR: %[[RETVAL:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
// CIR: cir.scope {
// CIR: %[[TMP:.*]] = cir.alloca ![[REC_LAM_G2]], !cir.ptr<![[REC_LAM_G2]]>, ["ref.tmp0"]
@@ -299,7 +332,7 @@ struct A {
// OGCG: call noundef i32 @_ZN1A3barEv(ptr {{.*}} %[[A_THIS]])
// lambda operator() in foo()
-// CIR: cir.func lambda comdat linkonce_odr @_ZZN1A3fooEvENKUlvE_clEv(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_A:.*]]> {{.*}}) {{.*}} {
+// CIR: cir.func {{.*}} lambda comdat linkonce_odr @_ZZN1A3fooEvENKUlvE_clEv(%[[THIS_ARG:.*]]: !cir.ptr<![[REC_LAM_A:.*]]> {{.*}})
// CIR: %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<![[REC_LAM_A]]>, !cir.ptr<!cir.ptr<![[REC_LAM_A]]>>, ["this", init]
// CIR: %[[RETVAL:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
// CIR: cir.store{{.*}} %[[THIS_ARG]], %[[THIS_ADDR]]
@@ -326,7 +359,7 @@ struct A {
// The function above is defined after _ZN1A3barEv in OGCG, see below.
// A::foo()
-// CIR: cir.func {{.*}} @_ZN1A3fooEv(%[[THIS_ARG:.*]]: !cir.ptr<!rec_A> {{.*}}) -> !s32i {{.*}} {
+// CIR: cir.func {{.*}} @_ZN1A3fooEv(%[[THIS_ARG:.*]]: !cir.ptr<!rec_A> {{.*}}) -> !s32i
// CIR: %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<!rec_A>, !cir.ptr<!cir.ptr<!rec_A>>, ["this", init]
// CIR: %[[RETVAL:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
// CIR: cir.store %[[THIS_ARG]], %[[THIS_ADDR]]
@@ -334,7 +367,7 @@ struct A {
// CIR: cir.scope {
// CIR: %[[LAM_ADDR:.*]] = cir.alloca ![[REC_LAM_A]], !cir.ptr<![[REC_LAM_A]]>, ["ref.tmp0"]
// CIR: %[[STRUCT_A:.*]] = cir.get_member %[[LAM_ADDR]][0] {name = "this"} : !cir.ptr<![[REC_LAM_A]]> -> !cir.ptr<!rec_A>
-// CIR: cir.call @_ZN1AC1ERKS_(%[[STRUCT_A]], %[[THIS]]){{.*}} : (!cir.ptr<!rec_A>, !cir.ptr<!rec_A>){{.*}} -> ()
+// CIR: cir.copy %[[THIS]] to %[[STRUCT_A]] : !cir.ptr<!rec_A>
// CIR: %[[LAM_RET:.*]] = cir.call @_ZZN1A3fooEvENKUlvE_clEv(%[[LAM_ADDR]])
// CIR: cir.store{{.*}} %[[LAM_RET]], %[[RETVAL]]
// CIR: }
@@ -350,7 +383,7 @@ struct A {
// LLVM: br label %[[SCOPE_BB:.*]]
// LLVM: [[SCOPE_BB]]:
// LLVM: %[[STRUCT_A:.*]] = getelementptr %[[REC_LAM_A]], ptr %[[LAM_ALLOCA]], i32 0, i32 0
-// LLVM: call void @_ZN1AC1ERKS_(ptr %[[STRUCT_A]], ptr %[[THIS]])
+// LLVM: call void @llvm.memcpy.p0.p0.i32(ptr %[[STRUCT_A]], ptr %[[THIS]], i32 4, i1 false)
// LLVM: %[[LAM_RET:.*]] = call i32 @_ZZN1A3fooEvENKUlvE_clEv(ptr %[[LAM_ALLOCA]])
// LLVM: store i32 %[[LAM_RET]], ptr %[[RETVAL]]
// LLVM: br label %[[RET_BB:.*]]
@@ -369,7 +402,7 @@ struct A {
// OGCG: ret i32 %[[LAM_RET]]
// lambda operator() in bar()
-// CIR: cir.func {{.*}} @_ZZN1A3barEvENKUlvE_clEv(%[[THIS_ARG2:.*]]: !cir.ptr<![[REC_LAM_PTR_A:.*]]> {{.*}}) -> !s32i {{.*}} {
+// CIR: cir.func {{.*}} @_ZZN1A3barEvENKUlvE_clEv(%[[THIS_ARG2:.*]]: !cir.ptr<![[REC_LAM_PTR_A:.*]]> {{.*}}) -> !s32i
// CIR: %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<![[REC_LAM_PTR_A]]>, !cir.ptr<!cir.ptr<![[REC_LAM_PTR_A]]>>, ["this", init]
// CIR: %[[RETVAL:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
// CIR: cir.store{{.*}} %[[THIS_ARG]], %[[THIS_ADDR]]
@@ -398,7 +431,7 @@ struct A {
// The function above is defined after _ZZN1A3fooEvENKUlvE_clEv in OGCG, see below.
// A::bar()
-// CIR: cir.func {{.*}} @_ZN1A3barEv(%[[THIS_ARG:.*]]: !cir.ptr<!rec_A> {{.*}}) -> !s32i {{.*}} {
+// CIR: cir.func {{.*}} @_ZN1A3barEv(%[[THIS_ARG:.*]]: !cir.ptr<!rec_A> {{.*}}) -> !s32i
// CIR: %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<!rec_A>, !cir.ptr<!cir.ptr<!rec_A>>, ["this", init]
// CIR: %[[RETVAL:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
// CIR: cir.store %[[THIS_ARG]], %[[THIS_ADDR]]
@@ -466,7 +499,7 @@ int test_lambda_this1(){
return x+y;
}
-// CIR: cir.func {{.*}} @_Z17test_lambda_this1v{{.*}} {
+// CIR: cir.func {{.*}} @_Z17test_lambda_this1v
// CIR: cir.call @_ZN1AC1Ev(%[[A_THIS:.*]]){{.*}} : (!cir.ptr<!rec_A>) -> ()
// CIR: cir.call @_ZN1A3fooEv(%[[A_THIS]]){{.*}} : (!cir.ptr<!rec_A>) -> !s32i
// CIR: cir.call @_ZN1A3barEv(%[[A_THIS]]){{.*}} : (!cir.ptr<!rec_A>) -> !s32i
diff --git a/clang/test/CIR/CodeGen/linkage-spec.cpp b/clang/test/CIR/CodeGen/linkage-spec.cpp
index 1affecd..bfb21f8 100644
--- a/clang/test/CIR/CodeGen/linkage-spec.cpp
+++ b/clang/test/CIR/CodeGen/linkage-spec.cpp
@@ -1,42 +1,42 @@
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o - 2>&1 | FileCheck %s
extern "C" void TopLevelC(){}
-// CHECK: cir.func dso_local @TopLevelC() inline(never) {
+// CHECK: cir.func no_inline dso_local @TopLevelC()
extern "C++" void TopLevelCpp(){}
-// CHECK: cir.func dso_local @_Z11TopLevelCppv() inline(never) {
+// CHECK: cir.func no_inline dso_local @_Z11TopLevelCppv()
extern "C++" {
void ExternCppEmpty(){}
- // CHECK: cir.func dso_local @_Z14ExternCppEmptyv() inline(never) {
+ // CHECK: cir.func no_inline dso_local @_Z14ExternCppEmptyv()
extern "C" void ExternCpp_C(){}
- // CHECK: cir.func dso_local @ExternCpp_C() inline(never) {
+ // CHECK: cir.func no_inline dso_local @ExternCpp_C()
extern "C++" void ExternCpp_Cpp(){}
- // CHECK: cir.func dso_local @_Z13ExternCpp_Cppv() inline(never) {
+ // CHECK: cir.func no_inline dso_local @_Z13ExternCpp_Cppv()
extern "C" {
void ExternCpp_CEmpty(){}
- // CHECK: cir.func dso_local @ExternCpp_CEmpty() inline(never) {
+ // CHECK: cir.func no_inline dso_local @ExternCpp_CEmpty()
extern "C" void ExternCpp_C_C(){}
- // CHECK: cir.func dso_local @ExternCpp_C_C() inline(never) {
+ // CHECK: cir.func no_inline dso_local @ExternCpp_C_C()
extern "C++" void ExternCpp_C_Cpp(){}
- // CHECK: cir.func dso_local @_Z15ExternCpp_C_Cppv() inline(never) {
+ // CHECK: cir.func no_inline dso_local @_Z15ExternCpp_C_Cppv()
}
}
extern "C" {
void ExternCEmpty(){}
- // CHECK: cir.func dso_local @ExternCEmpty() inline(never) {
+ // CHECK: cir.func no_inline dso_local @ExternCEmpty()
extern "C" void ExternC_C(){}
- // CHECK: cir.func dso_local @ExternC_C() inline(never) {
+ // CHECK: cir.func no_inline dso_local @ExternC_C()
extern "C++" void ExternC_Cpp(){}
- // CHECK: cir.func dso_local @_Z11ExternC_Cppv() inline(never) {
+ // CHECK: cir.func no_inline dso_local @_Z11ExternC_Cppv()
extern "C++" {
void ExternC_CppEmpty(){}
- // CHECK: cir.func dso_local @_Z16ExternC_CppEmptyv() inline(never) {
+ // CHECK: cir.func no_inline dso_local @_Z16ExternC_CppEmptyv()
extern "C" void ExternC_Cpp_C(){}
- // CHECK: cir.func dso_local @ExternC_Cpp_C() inline(never) {
+ // CHECK: cir.func no_inline dso_local @ExternC_Cpp_C()
extern "C++" void ExternC_Cpp_Cpp(){}
- // CHECK: cir.func dso_local @_Z15ExternC_Cpp_Cppv() inline(never) {
+ // CHECK: cir.func no_inline dso_local @_Z15ExternC_Cpp_Cppv()
}
}
diff --git a/clang/test/CIR/CodeGen/loop.cpp b/clang/test/CIR/CodeGen/loop.cpp
index 3d28666..463434c 100644
--- a/clang/test/CIR/CodeGen/loop.cpp
+++ b/clang/test/CIR/CodeGen/loop.cpp
@@ -312,23 +312,10 @@ void l5() {
// CIR: %[[BEGIN_ADDR:.*]] = cir.alloca {{.*}} ["__begin1", init]
// CIR: %[[END_ADDR:.*]] = cir.alloca {{.*}} ["__end1", init]
// CIR: %[[X_ADDR:.*]] = cir.alloca {{.*}} ["x", init]
-// CIR: %[[ARR_CAST:.*]] = cir.cast array_to_ptrdecay %[[ARR_ADDR]] : {{.*}}
-// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
-// CIR: cir.store{{.*}} %[[ONE]], %[[ARR_CAST]]
-// CIR: %[[OFFSET1:.*]] = cir.const #cir.int<1> : !s64i
-// CIR: %[[STRIDE:.*]] = cir.ptr_stride %[[ARR_CAST]], %[[OFFSET1]] : ({{.*}}, {{.*}})
-// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s32i
-// CIR: cir.store{{.*}} %[[TWO]], %[[STRIDE]]
-// CIR: %[[OFFSET2:.*]] = cir.const #cir.int<2> : !s64i
-// CIR: %[[STRIDE2:.*]] = cir.ptr_stride %[[ARR_CAST]], %[[OFFSET2]] : ({{.*}}, {{.*}})
-// CIR: %[[THREE:.*]] = cir.const #cir.int<3> : !s32i
-// CIR: cir.store{{.*}} %[[THREE]], %[[STRIDE2]]
-// CIR: %[[OFFSET3:.*]] = cir.const #cir.int<3> : !s64i
-// CIR: %[[STRIDE3:.*]] = cir.ptr_stride %[[ARR_CAST]], %[[OFFSET3]] : ({{.*}}, {{.*}})
-// CIR: %[[FOUR:.*]] = cir.const #cir.int<4> : !s32i
-// CIR: cir.store{{.*}} %[[FOUR]], %[[STRIDE3]]
+// CIR: %[[ARR_INIT:.*]] = cir.const #cir.const_array<[#cir.int<1> : !s32i, #cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<4> : !s32i]>
+// CIR: cir.store{{.*}} %[[ARR_INIT]], %[[ARR_ADDR]]
// CIR: cir.store{{.*}} %[[ARR_ADDR]], %[[RANGE_ADDR]]
-// CIR: %[[RANGE_LOAD:.*]] = cir.load{{.*}} %[[RANGE_ADDR]]
+// CIR: %[[RANGE_LOAD:.*]] = cir.load %[[RANGE_ADDR]]
// CIR: %[[RANGE_CAST:.*]] = cir.cast array_to_ptrdecay %[[RANGE_LOAD]] : {{.*}}
// CIR: cir.store{{.*}} %[[RANGE_CAST]], %[[BEGIN_ADDR]]
// CIR: %[[BEGIN:.*]] = cir.load{{.*}} %[[RANGE_ADDR]]
@@ -363,14 +350,7 @@ void l5() {
// LLVM: %[[X_ADDR:.*]] = alloca i32
// LLVM: br label %[[SETUP:.*]]
// LLVM: [[SETUP]]:
-// LLVM: %[[ARR_0:.*]] = getelementptr i32, ptr %[[ARR_ADDR]], i32 0
-// LLVM: store i32 1, ptr %[[ARR_0]]
-// LLVM: %[[ARR_1:.*]] = getelementptr i32, ptr %[[ARR_0]], i64 1
-// LLVM: store i32 2, ptr %[[ARR_1]]
-// LLVM: %[[ARR_2:.*]] = getelementptr i32, ptr %[[ARR_0]], i64 2
-// LLVM: store i32 3, ptr %[[ARR_2]]
-// LLVM: %[[ARR_3:.*]] = getelementptr i32, ptr %[[ARR_0]], i64 3
-// LLVM: store i32 4, ptr %[[ARR_3]]
+// LLVM: store [4 x i32] [i32 1, i32 2, i32 3, i32 4], ptr %[[ARR_ADDR]]
// LLVM: store ptr %[[ARR_ADDR]], ptr %[[RANGE_ADDR]]
// LLVM: %[[BEGIN:.*]] = load ptr, ptr %[[RANGE_ADDR]]
// LLVM: %[[BEGIN_CAST:.*]] = getelementptr i32, ptr %[[BEGIN]], i32 0
diff --git a/clang/test/CIR/CodeGen/no-common.c b/clang/test/CIR/CodeGen/no-common.c
new file mode 100644
index 0000000..ce4c5fc
--- /dev/null
+++ b/clang/test/CIR/CodeGen/no-common.c
@@ -0,0 +1,103 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir %s -emit-cir -o %t-default.cir
+// RUN: FileCheck --input-file=%t-default.cir %s -check-prefix=CIR-DEFAULT
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir %s -fno-common -emit-cir -o %t-no-common.cir
+// RUN: FileCheck --input-file=%t-no-common.cir %s -check-prefix=CIR-DEFAULT
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir %s -fcommon -emit-cir -o %t-common.cir
+// RUN: FileCheck --input-file=%t-common.cir %s -check-prefix=CIR-COMMON
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir %s -emit-llvm -o %t-default-cir.ll
+// RUN: FileCheck --input-file=%t-default-cir.ll %s -check-prefix=LLVM-DEFAULT
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir %s -fno-common -emit-llvm -o %t-no-common-cir.ll
+// RUN: FileCheck --input-file=%t-no-common-cir.ll %s -check-prefix=LLVM-DEFAULT
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir %s -fcommon -emit-llvm -o %t-common-cir.ll
+// RUN: FileCheck --input-file=%t-common-cir.ll %s -check-prefix=LLVM-COMMON
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu %s -emit-llvm -o %t-default.ll
+// RUN: FileCheck --input-file=%t-default.ll %s -check-prefix=OGCG-DEFAULT
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu %s -fno-common -emit-llvm -o %t-no-common.ll
+// RUN: FileCheck --input-file=%t-no-common.ll %s -check-prefix=OGCG-DEFAULT
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu %s -fcommon -emit-llvm -o %t-common.ll
+// RUN: FileCheck --input-file=%t-common.ll %s -check-prefix=OGCG-COMMON
+
+const int a = 42;
+// CIR-DEFAULT: cir.global constant external @a = #cir.int<42>
+// LLVM-DEFAULT: @a = constant i32 42
+// OGCG-DEFAULT: @a = constant i32 42
+
+// CIR-COMMON: cir.global constant external @a
+// LLVM-COMMON: @a = constant i32 42
+// OGCG-COMMON: @a = constant i32 42
+
+const int b __attribute__((common)) = 42;
+// CIR-DEFAULT: cir.global constant external @b = #cir.int<42>
+// LLVM-DEFAULT: @b = constant i32 42
+// OGCG-DEFAULT: @b = constant i32 42
+
+// CIR-COMMON: cir.global constant external @b = #cir.int<42>
+// LLVM-COMMON: @b = constant i32 42
+// OGCG-COMMON: @b = constant i32 42
+
+const int c __attribute__((nocommon)) = 42;
+// CIR-DEFAULT: cir.global constant external @c = #cir.int<42>
+// LLVM-DEFAULT: @c = constant i32 42
+// OGCG-DEFAULT: @c = constant i32 42
+
+// CIR-COMMON: cir.global constant external @c = #cir.int<42>
+// LLVM-COMMON: @c = constant i32 42
+// OGCG-COMMON: @c = constant i32 42
+
+int d = 11;
+// CIR-DEFAULT: cir.global external @d = #cir.int<11>
+// LLVM-DEFAULT: @d = global i32 11
+// OGCG-DEFAULT: @d = global i32 11
+
+// CIR-COMMON: cir.global external @d = #cir.int<11>
+// LLVM-COMMON: @d = global i32 11
+// OGCG-COMMON: @d = global i32 11
+
+int e;
+// CIR-DEFAULT: cir.global external @e = #cir.int<0>
+// LLVM-DEFAULT: @e = global i32 0
+// OGCG-DEFAULT: @e = global i32 0
+
+// CIR-COMMON: cir.global common @e = #cir.int<0>
+// LLVM-COMMON: @e = common global i32 0
+// OGCG-COMMON: @e = common global i32 0
+
+
+int f __attribute__((common));
+// CIR-DEFAULT: cir.global common @f = #cir.int<0>
+// LLVM-DEFAULT: @f = common global i32 0
+// OGCG-DEFAULT: @f = common global i32 0
+
+// CIR-COMMON: cir.global common @f
+// LLVM-COMMON: @f = common global i32 0
+// OGCG-COMMON: @f = common global i32 0
+
+int g __attribute__((nocommon));
+// CIR-DEFAULT: cir.global external @g = #cir.int<0>
+// LLVM-DEFAULT: @g = global i32
+// OGCG-DEFAULT: @g = global i32 0
+
+// CIR-COMMON: cir.global external @g = #cir.int<0>
+// LLVM-COMMON: @g = global i32 0
+// OGCG-COMMON: @g = global i32 0
+
+const int h;
+// CIR-DEFAULT: cir.global constant external @h = #cir.int<0>
+// LLVM-DEFAULT: @h = constant i32
+// OGCG-DEFAULT: @h = constant i32 0
+
+// CIR-COMMON: cir.global common @h = #cir.int<0>
+// LLVM-COMMON: @h = common global i32 0
+// OGCG-COMMON: @h = common global i32 0
+
+typedef void* (*fn_t)(long a, long b, char *f, int c);
+fn_t ABC __attribute__ ((nocommon));
+// CIR-DEFAULT: cir.global external @ABC = #cir.ptr<null>
+// LLVM-DEFAULT: @ABC = global ptr null
+// OGCG-DEFAULT: @ABC = global ptr null
+
+// CIR-COMMON: cir.global external @ABC = #cir.ptr<null>
+// LLVM-COMMON: @ABC = global ptr null
+// OGCG-COMMON: @ABC = global ptr null
diff --git a/clang/test/CIR/CodeGen/no-prototype.c b/clang/test/CIR/CodeGen/no-prototype.c
index 728c4b8..d266ccb 100644
--- a/clang/test/CIR/CodeGen/no-prototype.c
+++ b/clang/test/CIR/CodeGen/no-prototype.c
@@ -7,9 +7,9 @@
// No-proto definition followed by a correct call.
int noProto0(x) int x; { return x; }
-// CHECK: cir.func no_proto dso_local @noProto0(%arg0: !s32i {{.+}}) -> !s32i
+// CHECK: cir.func {{.*}} no_proto {{.*}} @noProto0(%arg0: !s32i {{.+}}) -> !s32i
int test0(int x) {
- // CHECK: cir.func dso_local @test0
+ // CHECK: cir.func {{.*}} @test0
return noProto0(x); // We know the definition. Should be a direct call.
// CHECK: %{{.+}} = cir.call @noProto0(%{{.+}})
}
@@ -21,9 +21,9 @@ int test0(int x) {
// definition is not marked as no-proto.
int noProto1();
int noProto1(int x) { return x; }
-// CHECK: cir.func dso_local @noProto1(%arg0: !s32i {{.+}}) -> !s32i
+// CHECK: cir.func {{.*}} @noProto1(%arg0: !s32i {{.+}}) -> !s32i
int test1(int x) {
- // CHECK: cir.func dso_local @test1
+ // CHECK: cir.func {{.*}} @test1
return noProto1(x);
// CHECK: %{{.+}} = cir.call @noProto1(%{{[0-9]+}}) : (!s32i) -> !s32i
}
@@ -39,7 +39,7 @@ int test2(int x) {
// CHECK: {{.*}} = cir.call [[GGO]](%{{[0-9]+}}) : (!cir.ptr<!cir.func<(!s32i) -> !s32i>>, !s32i) -> !s32i
}
int noProto2(int x) { return x; }
-// CHECK: cir.func no_proto dso_local @noProto2(%arg0: !s32i {{.+}}) -> !s32i
+// CHECK: cir.func {{.*}} no_proto {{.*}} @noProto2(%arg0: !s32i {{.+}}) -> !s32i
// No-proto declaration without definition (any call here is "correct").
//
@@ -48,7 +48,7 @@ int noProto2(int x) { return x; }
int noProto3();
// cir.func private no_proto @noProto3(...) -> !s32i
int test3(int x) {
-// CHECK: cir.func dso_local @test3
+// CHECK: cir.func {{.*}} @test3
return noProto3(x);
// CHECK: [[GGO:%.*]] = cir.get_global @noProto3 : !cir.ptr<!cir.func<(...) -> !s32i>>
// CHECK: [[CAST:%.*]] = cir.cast bitcast [[GGO]] : !cir.ptr<!cir.func<(...) -> !s32i>> -> !cir.ptr<!cir.func<(!s32i) -> !s32i>>
@@ -64,7 +64,7 @@ int test3(int x) {
// No-proto definition followed by an incorrect call due to extra args.
int noProto4() { return 0; }
-// cir.func private no_proto @noProto4() -> !s32i
+// cir.func {{.*}} no_proto {{.*}} @noProto4() -> !s32i
int test4(int x) {
return noProto4(x); // Even if we know the definition, this should compile.
// CHECK: [[GGO:%.*]] = cir.get_global @noProto4 : !cir.ptr<!cir.func<() -> !s32i>>
@@ -81,4 +81,4 @@ int test5(int x) {
// CHECK: {{%.*}} = cir.call [[CAST]]() : (!cir.ptr<!cir.func<() -> !s32i>>) -> !s32i
}
int noProto5(int x) { return x; }
-// CHECK: cir.func no_proto dso_local @noProto5(%arg0: !s32i {{.+}}) -> !s32i
+// CHECK: cir.func {{.*}} no_proto {{.*}} @noProto5(%arg0: !s32i {{.+}}) -> !s32i
diff --git a/clang/test/CIR/CodeGen/nrvo.cpp b/clang/test/CIR/CodeGen/nrvo.cpp
index ce08c79..0fc9b9b 100644
--- a/clang/test/CIR/CodeGen/nrvo.cpp
+++ b/clang/test/CIR/CodeGen/nrvo.cpp
@@ -49,3 +49,65 @@ struct S f1() {
// OGCG-NEXT: call void @_ZN1SC1Ev(ptr {{.*}} %[[RETVAL]])
// OGCG-NEXT: %[[RET:.*]] = load i64, ptr %[[RETVAL]]
// OGCG-NEXT: ret i64 %[[RET]]
+
+struct NonTrivial {
+ ~NonTrivial();
+};
+
+void maybeThrow();
+
+NonTrivial test_nrvo() {
+ NonTrivial result;
+ maybeThrow();
+ return result;
+}
+
+// TODO(cir): Handle normal cleanup properly.
+
+// CIR: cir.func {{.*}} @_Z9test_nrvov()
+// CIR: %[[RESULT:.*]] = cir.alloca !rec_NonTrivial, !cir.ptr<!rec_NonTrivial>, ["__retval"]
+// CIR: %[[NRVO_FLAG:.*]] = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, ["nrvo"]
+// CIR: %[[FALSE:.*]] = cir.const #false
+// CIR: cir.store{{.*}} %[[FALSE]], %[[NRVO_FLAG]]
+// CIR: cir.call @_Z10maybeThrowv() : () -> ()
+// CIR: %[[TRUE:.*]] = cir.const #true
+// CIR: cir.store{{.*}} %[[TRUE]], %[[NRVO_FLAG]]
+// CIR: %[[NRVO_FLAG_VAL:.*]] = cir.load{{.*}} %[[NRVO_FLAG]]
+// CIR: %[[NOT_NRVO_VAL:.*]] = cir.unary(not, %[[NRVO_FLAG_VAL]])
+// CIR: cir.if %[[NOT_NRVO_VAL]] {
+// CIR: cir.call @_ZN10NonTrivialD1Ev(%[[RESULT]])
+// CIR: }
+// CIR: %[[RET:.*]] = cir.load %[[RESULT]]
+// CIR: cir.return %[[RET]]
+
+// LLVM: define {{.*}} %struct.NonTrivial @_Z9test_nrvov()
+// LLVM: %[[RESULT:.*]] = alloca %struct.NonTrivial
+// LLVM: %[[NRVO_FLAG:.*]] = alloca i8
+// LLVM: store i8 0, ptr %[[NRVO_FLAG]]
+// LLVM: call void @_Z10maybeThrowv()
+// LLVM: store i8 1, ptr %[[NRVO_FLAG]]
+// LLVM: %[[NRVO_VAL:.*]] = load i8, ptr %[[NRVO_FLAG]]
+// LLVM: %[[NRVO_VAL_TRUNC:.*]] = trunc i8 %[[NRVO_VAL]] to i1
+// LLVM: %[[NOT_NRVO_VAL:.*]] = xor i1 %[[NRVO_VAL_TRUNC]], true
+// LLVM: br i1 %[[NOT_NRVO_VAL]], label %[[NRVO_UNUSED:.*]], label %[[NRVO_USED:.*]]
+// LLVM: [[NRVO_UNUSED]]:
+// LLVM: call void @_ZN10NonTrivialD1Ev(ptr %[[RESULT]])
+// LLVM: br label %[[NRVO_USED]]
+// LLVM: [[NRVO_USED]]:
+// LLVM: %[[RET:.*]] = load %struct.NonTrivial, ptr %[[RESULT]]
+// LLVM: ret %struct.NonTrivial %[[RET]]
+
+// OGCG: define {{.*}} void @_Z9test_nrvov(ptr {{.*}} sret(%struct.NonTrivial) {{.*}} %[[RESULT:.*]])
+// OGCG: %[[RESULT_ADDR:.*]] = alloca ptr
+// OGCG: %[[NRVO_FLAG:.*]] = alloca i1, align 1
+// OGCG: store ptr %[[RESULT]], ptr %[[RESULT_ADDR]]
+// OGCG: store i1 false, ptr %[[NRVO_FLAG]]
+// OGCG: call void @_Z10maybeThrowv()
+// OGCG: store i1 true, ptr %[[NRVO_FLAG]]
+// OGCG: %[[NRVO_VAL:.*]] = load i1, ptr %[[NRVO_FLAG]]
+// OGCG: br i1 %[[NRVO_VAL]], label %[[SKIPDTOR:.*]], label %[[NRVO_UNUSED:.*]]
+// OGCG: [[NRVO_UNUSED]]:
+// OGCG: call void @_ZN10NonTrivialD1Ev(ptr {{.*}} %[[RESULT]])
+// OGCG: br label %[[SKIPDTOR]]
+// OGCG: [[SKIPDTOR]]:
+// OGCG: ret void
diff --git a/clang/test/CIR/CodeGen/object-size-flex-array.c b/clang/test/CIR/CodeGen/object-size-flex-array.c
new file mode 100644
index 0000000..74229fd
--- /dev/null
+++ b/clang/test/CIR/CodeGen/object-size-flex-array.c
@@ -0,0 +1,317 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR --check-prefix=CIR-NO-STRICT
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -emit-llvm -disable-llvm-passes %s -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM --check-prefix=LLVM-NO-STRICT
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -emit-llvm -disable-llvm-passes %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG --check-prefix=OGCG-NO-STRICT
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -fstrict-flex-arrays=0 -emit-cir %s -o %t-strict-0.cir
+// RUN: FileCheck --input-file=%t-strict-0.cir %s --check-prefix=CIR --check-prefix=CIR-STRICT-0
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -fstrict-flex-arrays=0 -emit-llvm -disable-llvm-passes %s -o %t-cir-strict-0.ll
+// RUN: FileCheck --input-file=%t-cir-strict-0.ll %s --check-prefix=LLVM --check-prefix=LLVM-STRICT-0
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fstrict-flex-arrays=0 -emit-llvm -disable-llvm-passes %s -o %t-strict-0.ll
+// RUN: FileCheck --input-file=%t-strict-0.ll %s --check-prefix=OGCG --check-prefix=OGCG-STRICT-0
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -fstrict-flex-arrays=1 -emit-cir %s -o %t-strict-1.cir
+// RUN: FileCheck --input-file=%t-strict-1.cir %s --check-prefix=CIR --check-prefix=CIR-STRICT-1
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -fstrict-flex-arrays=1 -emit-llvm -disable-llvm-passes %s -o %t-cir-strict-1.ll
+// RUN: FileCheck --input-file=%t-cir-strict-1.ll %s --check-prefix=LLVM --check-prefix=LLVM-STRICT-1
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fstrict-flex-arrays=1 -emit-llvm -disable-llvm-passes %s -o %t-strict-1.ll
+// RUN: FileCheck --input-file=%t-strict-1.ll %s --check-prefix=OGCG --check-prefix=OGCG-STRICT-1
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -fstrict-flex-arrays=2 -emit-cir %s -o %t-strict-2.cir
+// RUN: FileCheck --input-file=%t-strict-2.cir %s --check-prefix=CIR --check-prefix=CIR-STRICT-2
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -fstrict-flex-arrays=2 -emit-llvm -disable-llvm-passes %s -o %t-cir-strict-2.ll
+// RUN: FileCheck --input-file=%t-cir-strict-2.ll %s --check-prefix=LLVM --check-prefix=LLVM-STRICT-2
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fstrict-flex-arrays=2 -emit-llvm -disable-llvm-passes %s -o %t-strict-2.ll
+// RUN: FileCheck --input-file=%t-strict-2.ll %s --check-prefix=OGCG --check-prefix=OGCG-STRICT-2
+
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -fstrict-flex-arrays=3 -emit-cir %s -o %t-strict-3.cir
+// RUN: FileCheck --input-file=%t-strict-3.cir %s --check-prefix=CIR --check-prefix=CIR-STRICT-3
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fclangir -fstrict-flex-arrays=3 -emit-llvm -disable-llvm-passes %s -o %t-cir-strict-3.ll
+// RUN: FileCheck --input-file=%t-cir-strict-3.ll %s --check-prefix=LLVM --check-prefix=LLVM-STRICT-3
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -O2 -fstrict-flex-arrays=3 -emit-llvm -disable-llvm-passes %s -o %t-strict-3.ll
+// RUN: FileCheck --input-file=%t-strict-3.ll %s --check-prefix=OGCG --check-prefix=OGCG-STRICT-3
+
+#define OBJECT_SIZE_BUILTIN __builtin_object_size
+
+typedef struct {
+ float f;
+ double c[];
+} foo_t;
+
+typedef struct {
+ float f;
+ double c[0];
+} foo0_t;
+
+typedef struct {
+ float f;
+ double c[1];
+} foo1_t;
+
+typedef struct {
+ float f;
+ double c[2];
+} foo2_t;
+
+// CIR-LABEL: @bar
+// LLVM-LABEL: @bar(
+// OGCG-LABEL: @bar(
+unsigned bar(foo_t *f) {
+ // CIR-NO-STRICT: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-0: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-1: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-2: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-3: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // LLVM-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // LLVM-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // LLVM-STRICT-2: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // LLVM-STRICT-3: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // OGCG-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // OGCG-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // OGCG-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // OGCG-STRICT-2: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // OGCG-STRICT-3: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ return OBJECT_SIZE_BUILTIN(f->c, 1);
+}
+
+// CIR-LABEL: @bar0
+// LLVM-LABEL: @bar0(
+// OGCG-LABEL: @bar0(
+unsigned bar0(foo0_t *f) {
+ // CIR-NO-STRICT: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-0: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-1: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-2: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-3: cir.const #cir.int<0>
+ // LLVM-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // LLVM-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // LLVM-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // LLVM-STRICT-2: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // LLVM-STRICT-3: store i32 0
+ // OGCG-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // OGCG-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // OGCG-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // OGCG-STRICT-2: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // OGCG-STRICT-3: ret i32 0
+ return OBJECT_SIZE_BUILTIN(f->c, 1);
+}
+
+// CIR-LABEL: @bar1
+// LLVM-LABEL: @bar1(
+// OGCG-LABEL: @bar1(
+unsigned bar1(foo1_t *f) {
+ // CIR-NO-STRICT: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-0: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-1: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-2: cir.const #cir.int<8>
+ // CIR-STRICT-3: cir.const #cir.int<8>
+ // LLVM-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // LLVM-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // LLVM-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // LLVM-STRICT-2: store i32 8
+ // LLVM-STRICT-3: store i32 8
+ // OGCG-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // OGCG-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // OGCG-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // OGCG-STRICT-2: ret i32 8
+ // OGCG-STRICT-3: ret i32 8
+ return OBJECT_SIZE_BUILTIN(f->c, 1);
+}
+
+// CIR-LABEL: @bar2
+// LLVM-LABEL: @bar2(
+// OGCG-LABEL: @bar2(
+unsigned bar2(foo2_t *f) {
+ // CIR-NO-STRICT: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-0: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-1: cir.const #cir.int<16>
+ // CIR-STRICT-2: cir.const #cir.int<16>
+ // CIR-STRICT-3: cir.const #cir.int<16>
+ // LLVM-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // LLVM-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // LLVM-STRICT-1: store i32 16
+ // LLVM-STRICT-2: store i32 16
+ // LLVM-STRICT-3: store i32 16
+ // OGCG-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // OGCG-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 false)
+ // OGCG-STRICT-1: ret i32 16
+ // OGCG-STRICT-2: ret i32 16
+ // OGCG-STRICT-3: ret i32 16
+ return OBJECT_SIZE_BUILTIN(f->c, 1);
+}
+
+#define DYNAMIC_OBJECT_SIZE_BUILTIN __builtin_dynamic_object_size
+
+// CIR-LABEL: @dyn_bar
+// LLVM-LABEL: @dyn_bar(
+// OGCG-LABEL: @dyn_bar(
+unsigned dyn_bar(foo_t *f) {
+ // CIR-NO-STRICT: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-0: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-1: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-2: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-3: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // LLVM-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // LLVM-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // LLVM-STRICT-2: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // LLVM-STRICT-3: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // OGCG-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // OGCG-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // OGCG-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // OGCG-STRICT-2: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // OGCG-STRICT-3: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ return DYNAMIC_OBJECT_SIZE_BUILTIN(f->c, 1);
+}
+
+// CIR-LABEL: @dyn_bar0
+// LLVM-LABEL: @dyn_bar0(
+// OGCG-LABEL: @dyn_bar0(
+unsigned dyn_bar0(foo0_t *f) {
+ // CIR-NO-STRICT: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-0: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-1: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-2: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-3: cir.const #cir.int<0>
+ // LLVM-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // LLVM-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // LLVM-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // LLVM-STRICT-2: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // LLVM-STRICT-3: store i32 0
+ // OGCG-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // OGCG-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // OGCG-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // OGCG-STRICT-2: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // OGCG-STRICT-3: ret i32 0
+ return DYNAMIC_OBJECT_SIZE_BUILTIN(f->c, 1);
+}
+
+// CIR-LABEL: @dyn_bar1
+// LLVM-LABEL: @dyn_bar1(
+// OGCG-LABEL: @dyn_bar1(
+unsigned dyn_bar1(foo1_t *f) {
+ // CIR-NO-STRICT: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-0: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-1: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-2: cir.const #cir.int<8>
+ // CIR-STRICT-3: cir.const #cir.int<8>
+ // LLVM-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // LLVM-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // LLVM-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // LLVM-STRICT-2: store i32 8
+ // LLVM-STRICT-3: store i32 8
+ // OGCG-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // OGCG-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // OGCG-STRICT-1: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // OGCG-STRICT-2: ret i32 8
+ // OGCG-STRICT-3: ret i32 8
+ return DYNAMIC_OBJECT_SIZE_BUILTIN(f->c, 1);
+}
+
+// CIR-LABEL: @dyn_bar2
+// LLVM-LABEL: @dyn_bar2(
+// OGCG-LABEL: @dyn_bar2(
+unsigned dyn_bar2(foo2_t *f) {
+ // CIR-NO-STRICT: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-0: cir.objsize max nullunknown dynamic {{.*}} : !cir.ptr<!void> -> !u64i
+ // CIR-STRICT-1: cir.const #cir.int<16>
+ // CIR-STRICT-2: cir.const #cir.int<16>
+ // CIR-STRICT-3: cir.const #cir.int<16>
+ // LLVM-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // LLVM-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // LLVM-STRICT-1: store i32 16
+ // LLVM-STRICT-2: store i32 16
+ // LLVM-STRICT-3: store i32 16
+ // OGCG-NO-STRICT: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // OGCG-STRICT-0: llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1 true)
+ // OGCG-STRICT-1: ret i32 16
+ // OGCG-STRICT-2: ret i32 16
+ // OGCG-STRICT-3: ret i32 16
+ return DYNAMIC_OBJECT_SIZE_BUILTIN(f->c, 1);
+}
+
+// Also checks for non-trailing flex-array like members
+
+typedef struct {
+ double c[0];
+ float f;
+} foofoo0_t;
+
+typedef struct {
+ double c[1];
+ float f;
+} foofoo1_t;
+
+typedef struct {
+ double c[2];
+ float f;
+} foofoo2_t;
+
+// CIR-LABEL: @babar0
+// LLVM-LABEL: @babar0(
+// OGCG-LABEL: @babar0(
+unsigned babar0(foofoo0_t *f) {
+ // CIR-NO-STRICT: cir.const #cir.int<0>
+ // CIR-STRICT-0: cir.const #cir.int<0>
+ // CIR-STRICT-1: cir.const #cir.int<0>
+ // CIR-STRICT-2: cir.const #cir.int<0>
+ // CIR-STRICT-3: cir.const #cir.int<0>
+ // LLVM-NO-STRICT: store i32 0
+ // LLVM-STRICT-0: store i32 0
+ // LLVM-STRICT-1: store i32 0
+ // LLVM-STRICT-2: store i32 0
+ // LLVM-STRICT-3: store i32 0
+ // OGCG-NO-STRICT: ret i32 0
+ // OGCG-STRICT-0: ret i32 0
+ // OGCG-STRICT-1: ret i32 0
+ // OGCG-STRICT-2: ret i32 0
+ // OGCG-STRICT-3: ret i32 0
+ return OBJECT_SIZE_BUILTIN(f->c, 1);
+}
+
+// CIR-LABEL: @babar1
+// LLVM-LABEL: @babar1(
+// OGCG-LABEL: @babar1(
+unsigned babar1(foofoo1_t *f) {
+ // CIR-NO-STRICT: cir.const #cir.int<8>
+ // CIR-STRICT-0: cir.const #cir.int<8>
+ // CIR-STRICT-1: cir.const #cir.int<8>
+ // CIR-STRICT-2: cir.const #cir.int<8>
+ // CIR-STRICT-3: cir.const #cir.int<8>
+ // LLVM-NO-STRICT: store i32 8
+ // LLVM-STRICT-0: store i32 8
+ // LLVM-STRICT-1: store i32 8
+ // LLVM-STRICT-2: store i32 8
+ // LLVM-STRICT-3: store i32 8
+ // OGCG-NO-STRICT: ret i32 8
+ // OGCG-STRICT-0: ret i32 8
+ // OGCG-STRICT-1: ret i32 8
+ // OGCG-STRICT-2: ret i32 8
+ // OGCG-STRICT-3: ret i32 8
+ return OBJECT_SIZE_BUILTIN(f->c, 1);
+}
+
+// CIR-LABEL: @babar2
+// LLVM-LABEL: @babar2(
+// OGCG-LABEL: @babar2(
+unsigned babar2(foofoo2_t *f) {
+ // CIR-NO-STRICT: cir.const #cir.int<16>
+ // CIR-STRICT-0: cir.const #cir.int<16>
+ // CIR-STRICT-1: cir.const #cir.int<16>
+ // CIR-STRICT-2: cir.const #cir.int<16>
+ // CIR-STRICT-3: cir.const #cir.int<16>
+ // LLVM-NO-STRICT: store i32 16
+ // LLVM-STRICT-0: store i32 16
+ // LLVM-STRICT-1: store i32 16
+ // LLVM-STRICT-2: store i32 16
+ // LLVM-STRICT-3: store i32 16
+ // OGCG-NO-STRICT: ret i32 16
+ // OGCG-STRICT-0: ret i32 16
+ // OGCG-STRICT-1: ret i32 16
+ // OGCG-STRICT-2: ret i32 16
+ // OGCG-STRICT-3: ret i32 16
+ return OBJECT_SIZE_BUILTIN(f->c, 1);
+}
diff --git a/clang/test/CIR/CodeGen/object-size.c b/clang/test/CIR/CodeGen/object-size.c
new file mode 100644
index 0000000..1b10fb8b
--- /dev/null
+++ b/clang/test/CIR/CodeGen/object-size.c
@@ -0,0 +1,877 @@
+// RUN: %clang_cc1 -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 -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 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG
+
+char gbuf[63];
+char *gp;
+int gi, gj;
+
+// CIR-LABEL: @test1
+// LLVM-LABEL: define {{.*}} void @test1
+// OGCG-LABEL: define {{.*}} void @test1
+void test1(void) {
+ // CIR: cir.const #cir.int<59>
+ // LLVM: store i32 59
+ // OGCG: store i32 59
+ gi = __builtin_object_size(&gbuf[4], 1);
+}
+
+// CIR-LABEL: @test2
+// LLVM-LABEL: define {{.*}} void @test2
+// OGCG-LABEL: define {{.*}} void @test2
+void test2(void) {
+ // CIR: cir.const #cir.int<63>
+ // LLVM: store i32 63
+ // OGCG: store i32 63
+ gi = __builtin_object_size(gbuf, 1);
+}
+
+// CIR-LABEL: @test3
+// LLVM-LABEL: define {{.*}} void @test3
+// OGCG-LABEL: define {{.*}} void @test3
+void test3(void) {
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(&gbuf[100], 1);
+}
+
+// CIR-LABEL: @test4
+// LLVM-LABEL: define {{.*}} void @test4
+// OGCG-LABEL: define {{.*}} void @test4
+void test4(void) {
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size((char*)(void*)&gbuf[-1], 1);
+}
+
+// CIR-LABEL: @test5
+// LLVM-LABEL: define {{.*}} void @test5
+// OGCG-LABEL: define {{.*}} void @test5
+void test5(void) {
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(gp, 0);
+}
+
+// CIR-LABEL: @test6
+// LLVM-LABEL: define {{.*}} void @test6
+// OGCG-LABEL: define {{.*}} void @test6
+void test6(void) {
+ char buf[57];
+
+ // CIR: cir.const #cir.int<53>
+ // LLVM: store i32 53
+ // OGCG: store i32 53
+ gi = __builtin_object_size(&buf[4], 1);
+}
+
+// CIR-LABEL: @test18
+// LLVM-LABEL: define {{.*}} i32 @test18
+// OGCG-LABEL: define {{.*}} i32 @test18
+unsigned test18(int cond) {
+ int a[4], b[4];
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64
+ // OGCG: call i64 @llvm.objectsize.i64
+ return __builtin_object_size(cond ? a : b, 0);
+}
+
+// CIR-LABEL: @test19
+// LLVM-LABEL: define {{.*}} void @test19
+// OGCG-LABEL: define {{.*}} void @test19
+void test19(void) {
+ struct {
+ int a, b;
+ } foo;
+
+ // CIR: cir.const #cir.int<8>
+ // LLVM: store i32 8
+ // OGCG: store i32 8
+ gi = __builtin_object_size(&foo.a, 0);
+
+ // CIR: cir.const #cir.int<4>
+ // LLVM: store i32 4
+ // OGCG: store i32 4
+ gi = __builtin_object_size(&foo.a, 1);
+
+ // CIR: cir.const #cir.int<8>
+ // LLVM: store i32 8
+ // OGCG: store i32 8
+ gi = __builtin_object_size(&foo.a, 2);
+
+ // CIR: cir.const #cir.int<4>
+ // LLVM: store i32 4
+ // OGCG: store i32 4
+ gi = __builtin_object_size(&foo.a, 3);
+
+ // CIR: cir.const #cir.int<4>
+ // LLVM: store i32 4
+ // OGCG: store i32 4
+ gi = __builtin_object_size(&foo.b, 0);
+
+ // CIR: cir.const #cir.int<4>
+ // LLVM: store i32 4
+ // OGCG: store i32 4
+ gi = __builtin_object_size(&foo.b, 1);
+
+ // CIR: cir.const #cir.int<4>
+ // LLVM: store i32 4
+ // OGCG: store i32 4
+ gi = __builtin_object_size(&foo.b, 2);
+
+ // CIR: cir.const #cir.int<4>
+ // LLVM: store i32 4
+ // OGCG: store i32 4
+ gi = __builtin_object_size(&foo.b, 3);
+}
+
+// CIR-LABEL: @test20
+// LLVM-LABEL: define {{.*}} void @test20
+// OGCG-LABEL: define {{.*}} void @test20
+void test20(void) {
+ struct { int t[10]; } t[10];
+
+ // CIR: cir.const #cir.int<380>
+ // LLVM: store i32 380
+ // OGCG: store i32 380
+ gi = __builtin_object_size(&t[0].t[5], 0);
+
+ // CIR: cir.const #cir.int<20>
+ // LLVM: store i32 20
+ // OGCG: store i32 20
+ gi = __builtin_object_size(&t[0].t[5], 1);
+
+ // CIR: cir.const #cir.int<380>
+ // LLVM: store i32 380
+ // OGCG: store i32 380
+ gi = __builtin_object_size(&t[0].t[5], 2);
+
+ // CIR: cir.const #cir.int<20>
+ // LLVM: store i32 20
+ // OGCG: store i32 20
+ gi = __builtin_object_size(&t[0].t[5], 3);
+}
+
+// CIR-LABEL: @test21
+// LLVM-LABEL: define {{.*}} void @test21
+// OGCG-LABEL: define {{.*}} void @test21
+void test21(void) {
+ struct { int t; } t;
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(&t + 1, 0);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(&t + 1, 1);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(&t + 1, 2);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(&t + 1, 3);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(&t.t + 1, 0);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(&t.t + 1, 1);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(&t.t + 1, 2);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(&t.t + 1, 3);
+}
+
+// CIR-LABEL: @test22
+// LLVM-LABEL: define {{.*}} void @test22
+// OGCG-LABEL: define {{.*}} void @test22
+void test22(void) {
+ struct { int t[10]; } t[10];
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(&t[10], 0);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(&t[10], 1);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(&t[10], 2);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(&t[10], 3);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(&t[9].t[10], 0);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(&t[9].t[10], 1);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(&t[9].t[10], 2);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(&t[9].t[10], 3);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size((char*)&t[0] + sizeof(t), 0);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size((char*)&t[0] + sizeof(t), 1);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size((char*)&t[0] + sizeof(t), 2);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size((char*)&t[0] + sizeof(t), 3);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size((char*)&t[9].t[0] + 10*sizeof(t[0].t), 0);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size((char*)&t[9].t[0] + 10*sizeof(t[0].t), 1);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size((char*)&t[9].t[0] + 10*sizeof(t[0].t), 2);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size((char*)&t[9].t[0] + 10*sizeof(t[0].t), 3);
+}
+
+struct Test23Ty { int a; int t[10]; };
+
+// CIR-LABEL: @test23
+// LLVM-LABEL: define {{.*}} void @test23
+// OGCG-LABEL: define {{.*}} void @test23
+void test23(struct Test23Ty *p) {
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(p, 0);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(p, 1);
+
+ // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ gi = __builtin_object_size(p, 2);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(p, 3);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(&p->a, 0);
+
+ // CIR: cir.const #cir.int<4>
+ // LLVM: store i32 4
+ // OGCG: store i32 4
+ gi = __builtin_object_size(&p->a, 1);
+
+ // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ gi = __builtin_object_size(&p->a, 2);
+
+ // CIR: cir.const #cir.int<4>
+ // LLVM: store i32 4
+ // OGCG: store i32 4
+ gi = __builtin_object_size(&p->a, 3);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(&p->t[5], 0);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(&p->t[5], 1);
+
+ // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ gi = __builtin_object_size(&p->t[5], 2);
+
+ // CIR: cir.const #cir.int<20>
+ // LLVM: store i32 20
+ // OGCG: store i32 20
+ gi = __builtin_object_size(&p->t[5], 3);
+}
+
+// CIR-LABEL: @test24
+// LLVM-LABEL: define {{.*}} void @test24
+// OGCG-LABEL: define {{.*}} void @test24
+void test24(void) {
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size((void*)0, 0);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size((void*)0, 1);
+
+ // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 true, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 true, i1 true, i1
+ gi = __builtin_object_size((void*)0, 2);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size((void*)0, 3);
+}
+
+// CIR-LABEL: @test25
+// LLVM-LABEL: define {{.*}} void @test25
+// OGCG-LABEL: define {{.*}} void @test25
+void test25(void) {
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size((void*)0x1000, 0);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size((void*)0x1000, 1);
+
+ // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 true, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 true, i1 true, i1
+ gi = __builtin_object_size((void*)0x1000, 2);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size((void*)0x1000, 3);
+
+ // Skipping (void*)0 + 0x1000 tests - void pointer arithmetic NYI in CIR
+}
+
+// CIR-LABEL: @test26
+// LLVM-LABEL: define {{.*}} void @test26
+// OGCG-LABEL: define {{.*}} void @test26
+void test26(void) {
+ struct { int v[10]; } t[10];
+
+ // CIR: cir.const #cir.int<316>
+ // LLVM: store i32 316
+ // OGCG: store i32 316
+ gi = __builtin_object_size(&t[1].v[11], 0);
+
+ // CIR: cir.const #cir.int<312>
+ // LLVM: store i32 312
+ // OGCG: store i32 312
+ gi = __builtin_object_size(&t[1].v[12], 1);
+
+ // CIR: cir.const #cir.int<308>
+ // LLVM: store i32 308
+ // OGCG: store i32 308
+ gi = __builtin_object_size(&t[1].v[13], 2);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(&t[1].v[14], 3);
+}
+
+struct Test27IncompleteTy;
+
+// CIR-LABEL: @test27
+// LLVM-LABEL: define {{.*}} void @test27
+// OGCG-LABEL: define {{.*}} void @test27
+void test27(struct Test27IncompleteTy *t) {
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(t, 0);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(t, 1);
+
+ // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ gi = __builtin_object_size(t, 2);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(t, 3);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(&test27, 0);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(&test27, 1);
+
+ // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 true, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr {{.*}}, i1 true, i1 true, i1
+ gi = __builtin_object_size(&test27, 2);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(&test27, 3);
+}
+
+// CIR-LABEL: @test28
+// LLVM-LABEL: define {{.*}} void @test28
+// OGCG-LABEL: define {{.*}} void @test28
+void test28(void) {
+ struct { int v[10]; } t[10];
+
+ // CIR: cir.const #cir.int<360>
+ // LLVM: store i32 360
+ // OGCG: store i32 360
+ gi = __builtin_object_size((char*)((short*)(&t[1])), 0);
+
+ // CIR: cir.const #cir.int<360>
+ // LLVM: store i32 360
+ // OGCG: store i32 360
+ gi = __builtin_object_size((char*)((short*)(&t[1])), 1);
+
+ // CIR: cir.const #cir.int<360>
+ // LLVM: store i32 360
+ // OGCG: store i32 360
+ gi = __builtin_object_size((char*)((short*)(&t[1])), 2);
+
+ // CIR: cir.const #cir.int<360>
+ // LLVM: store i32 360
+ // OGCG: store i32 360
+ gi = __builtin_object_size((char*)((short*)(&t[1])), 3);
+
+ // CIR: cir.const #cir.int<356>
+ // LLVM: store i32 356
+ // OGCG: store i32 356
+ gi = __builtin_object_size((char*)((short*)(&t[1].v[1])), 0);
+
+ // CIR: cir.const #cir.int<36>
+ // LLVM: store i32 36
+ // OGCG: store i32 36
+ gi = __builtin_object_size((char*)((short*)(&t[1].v[1])), 1);
+
+ // CIR: cir.const #cir.int<356>
+ // LLVM: store i32 356
+ // OGCG: store i32 356
+ gi = __builtin_object_size((char*)((short*)(&t[1].v[1])), 2);
+
+ // CIR: cir.const #cir.int<36>
+ // LLVM: store i32 36
+ // OGCG: store i32 36
+ gi = __builtin_object_size((char*)((short*)(&t[1].v[1])), 3);
+}
+
+struct DynStructVar {
+ char fst[16];
+ char snd[];
+};
+
+struct DynStruct0 {
+ char fst[16];
+ char snd[0];
+};
+
+struct DynStruct1 {
+ char fst[16];
+ char snd[1];
+};
+
+struct StaticStruct {
+ char fst[16];
+ char snd[2];
+};
+
+// CIR-LABEL: @test29
+// LLVM-LABEL: define {{.*}} void @test29
+// OGCG-LABEL: define {{.*}} void @test29
+void test29(struct DynStructVar *dv, struct DynStruct0 *d0,
+ struct DynStruct1 *d1, struct StaticStruct *ss) {
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(dv->snd, 0);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(dv->snd, 1);
+
+ // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ gi = __builtin_object_size(dv->snd, 2);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(dv->snd, 3);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(d0->snd, 0);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(d0->snd, 1);
+
+ // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ gi = __builtin_object_size(d0->snd, 2);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(d0->snd, 3);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(d1->snd, 0);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(d1->snd, 1);
+
+ // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ gi = __builtin_object_size(d1->snd, 2);
+
+ // CIR: cir.const #cir.int<1>
+ // LLVM: store i32 1
+ // OGCG: store i32 1
+ gi = __builtin_object_size(d1->snd, 3);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(ss->snd, 0);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(ss->snd, 1);
+
+ // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ gi = __builtin_object_size(ss->snd, 2);
+
+ // CIR: cir.const #cir.int<2>
+ // LLVM: store i32 2
+ // OGCG: store i32 2
+ gi = __builtin_object_size(ss->snd, 3);
+}
+
+// CIR-LABEL: @test30
+// LLVM-LABEL: define {{.*}} void @test30
+// OGCG-LABEL: define {{.*}} void @test30
+void test30(void) {
+ struct { struct DynStruct1 fst, snd; } *nested;
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(nested->fst.snd, 0);
+
+ // CIR: cir.const #cir.int<1>
+ // LLVM: store i32 1
+ // OGCG: store i32 1
+ gi = __builtin_object_size(nested->fst.snd, 1);
+
+ // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ gi = __builtin_object_size(nested->fst.snd, 2);
+
+ // CIR: cir.const #cir.int<1>
+ // LLVM: store i32 1
+ // OGCG: store i32 1
+ gi = __builtin_object_size(nested->fst.snd, 3);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(nested->snd.snd, 0);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(nested->snd.snd, 1);
+
+ // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ gi = __builtin_object_size(nested->snd.snd, 2);
+
+ // CIR: cir.const #cir.int<1>
+ // LLVM: store i32 1
+ // OGCG: store i32 1
+ gi = __builtin_object_size(nested->snd.snd, 3);
+
+ union { struct DynStruct1 d1; char c[1]; } *u;
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(u->c, 0);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(u->c, 1);
+
+ // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ gi = __builtin_object_size(u->c, 2);
+
+ // CIR: cir.const #cir.int<1>
+ // LLVM: store i32 1
+ // OGCG: store i32 1
+ gi = __builtin_object_size(u->c, 3);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(u->d1.snd, 0);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(u->d1.snd, 1);
+
+ // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ gi = __builtin_object_size(u->d1.snd, 2);
+
+ // CIR: cir.const #cir.int<1>
+ // LLVM: store i32 1
+ // OGCG: store i32 1
+ gi = __builtin_object_size(u->d1.snd, 3);
+}
+
+// CIR-LABEL: @test32
+// LLVM-LABEL: define {{.*}} i64 @test32
+// OGCG-LABEL: define {{.*}} i64 @test32
+static struct DynStructVar D32 = {
+ .fst = {},
+ .snd = { 0, 1, 2, },
+};
+unsigned long test32(void) {
+ // CIR: cir.const #cir.int<19>
+ // LLVM: store i64 19
+ // OGCG: ret i64 19
+ return __builtin_object_size(&D32, 1);
+}
+
+// CIR-LABEL: @test33
+// LLVM-LABEL: define {{.*}} i64 @test33
+// OGCG-LABEL: define {{.*}} i64 @test33
+static struct DynStructVar D33 = {
+ .fst = {},
+ .snd = {},
+};
+unsigned long test33(void) {
+ // CIR: cir.const #cir.int<16>
+ // LLVM: store i64 16
+ // OGCG: ret i64 16
+ return __builtin_object_size(&D33, 1);
+}
+
+// CIR-LABEL: @test34
+// LLVM-LABEL: define {{.*}} i64 @test34
+// OGCG-LABEL: define {{.*}} i64 @test34
+static struct DynStructVar D34 = {
+ .fst = {},
+};
+unsigned long test34(void) {
+ // CIR: cir.const #cir.int<16>
+ // LLVM: store i64 16
+ // OGCG: ret i64 16
+ return __builtin_object_size(&D34, 1);
+}
+
+// CIR-LABEL: @test35
+// LLVM-LABEL: define {{.*}} i64 @test35
+// OGCG-LABEL: define {{.*}} i64 @test35
+unsigned long test35(void) {
+ // CIR: cir.const #cir.int<16>
+ // LLVM: store i64 16
+ // OGCG: ret i64 16
+ return __builtin_object_size(&(struct DynStructVar){}, 1);
+}
+
+// CIR-LABEL: @test37
+// LLVM-LABEL: define {{.*}} i64 @test37
+// OGCG-LABEL: define {{.*}} i64 @test37
+struct Z { struct A { int x, y[]; } z; int a; int b[]; };
+static struct Z my_z = { .b = {1,2,3} };
+unsigned long test37(void) {
+ // CIR: cir.const #cir.int<4>
+ // LLVM: store i64 4
+ // OGCG: ret i64 4
+ return __builtin_object_size(&my_z.z, 1);
+}
+
+// CIR-LABEL: @PR30346
+// LLVM-LABEL: define {{.*}} void @PR30346
+// OGCG-LABEL: define {{.*}} void @PR30346
+void PR30346(void) {
+ struct sa_family_t {};
+ struct sockaddr {
+ struct sa_family_t sa_family;
+ char sa_data[14];
+ };
+
+ struct sockaddr *sa;
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(sa->sa_data, 0);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1
+ gi = __builtin_object_size(sa->sa_data, 1);
+
+ // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1
+ gi = __builtin_object_size(sa->sa_data, 2);
+
+ // CIR: cir.const #cir.int<14>
+ // LLVM: store i32 14
+ // OGCG: store i32 14
+ gi = __builtin_object_size(sa->sa_data, 3);
+}
+
+extern char incomplete_char_array[];
+
+// CIR-LABEL: @incomplete_and_function_types
+// LLVM-LABEL: define {{.*}} void @incomplete_and_function_types
+// OGCG-LABEL: define {{.*}} void @incomplete_and_function_types
+void incomplete_and_function_types(void) {
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0
+ // OGCG: call i64 @llvm.objectsize.i64.p0
+ gi = __builtin_object_size(incomplete_char_array, 0);
+
+ // CIR: cir.objsize max nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0
+ // OGCG: call i64 @llvm.objectsize.i64.p0
+ gi = __builtin_object_size(incomplete_char_array, 1);
+
+ // CIR: cir.objsize min nullunknown {{.*}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0
+ // OGCG: call i64 @llvm.objectsize.i64.p0
+ gi = __builtin_object_size(incomplete_char_array, 2);
+
+ // CIR: cir.const #cir.int<0>
+ // LLVM: store i32 0
+ // OGCG: store i32 0
+ gi = __builtin_object_size(incomplete_char_array, 3);
+}
+
+// CIR-LABEL: @deeply_nested
+// LLVM-LABEL: define {{.*}} void @deeply_nested
+// OGCG-LABEL: define {{.*}} void @deeply_nested
+void deeply_nested(void) {
+ struct {
+ struct {
+ struct {
+ struct {
+ int e[2];
+ char f;
+ } d[2];
+ } c[2];
+ } b[2];
+ } *a;
+
+ // CIR: cir.const #cir.int<4>
+ // LLVM: store i32 4
+ // OGCG: store i32 4
+ gi = __builtin_object_size(&a->b[1].c[1].d[1].e[1], 1);
+
+ // CIR: cir.const #cir.int<4>
+ // LLVM: store i32 4
+ // OGCG: store i32 4
+ gi = __builtin_object_size(&a->b[1].c[1].d[1].e[1], 3);
+}
diff --git a/clang/test/CIR/CodeGen/object-size.cpp b/clang/test/CIR/CodeGen/object-size.cpp
new file mode 100644
index 0000000..b60e245
--- /dev/null
+++ b/clang/test/CIR/CodeGen/object-size.cpp
@@ -0,0 +1,108 @@
+// RUN: %clang_cc1 -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 -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 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG
+
+// C++-specific tests for __builtin_object_size
+
+int gi;
+
+// CIR-LABEL: @_Z5test1v
+// LLVM-LABEL: define{{.*}} void @_Z5test1v()
+// OGCG-LABEL: define{{.*}} void @_Z5test1v()
+void test1() {
+ // Guaranteeing that our cast removal logic doesn't break more interesting
+ // cases.
+ struct A { int a; };
+ struct B { int b; };
+ struct C: public A, public B {};
+
+ C c;
+
+ // CIR: cir.const #cir.int<8>
+ // LLVM: store i32 8
+ // OGCG: store i32 8
+ gi = __builtin_object_size(&c, 0);
+ // CIR: cir.const #cir.int<8>
+ // LLVM: store i32 8
+ // OGCG: store i32 8
+ gi = __builtin_object_size((A*)&c, 0);
+ // CIR: cir.const #cir.int<4>
+ // LLVM: store i32 4
+ // OGCG: store i32 4
+ gi = __builtin_object_size((B*)&c, 0);
+
+ // CIR: cir.const #cir.int<8>
+ // LLVM: store i32 8
+ // OGCG: store i32 8
+ gi = __builtin_object_size((char*)&c, 0);
+ // CIR: cir.const #cir.int<8>
+ // LLVM: store i32 8
+ // OGCG: store i32 8
+ gi = __builtin_object_size((char*)(A*)&c, 0);
+ // CIR: cir.const #cir.int<4>
+ // LLVM: store i32 4
+ // OGCG: store i32 4
+ gi = __builtin_object_size((char*)(B*)&c, 0);
+}
+
+// CIR-LABEL: @_Z5test2v()
+// LLVM-LABEL: define{{.*}} void @_Z5test2v()
+// OGCG-LABEL: define{{.*}} void @_Z5test2v()
+void test2() {
+ struct A { char buf[16]; };
+ struct B : A {};
+ struct C { int i; B bs[1]; } *c;
+
+ // CIR: cir.objsize max nullunknown %{{.+}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false)
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false)
+ gi = __builtin_object_size(&c->bs[0], 0);
+ // CIR: cir.objsize max nullunknown %{{.+}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false)
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false)
+ gi = __builtin_object_size(&c->bs[0], 1);
+ // CIR: cir.objsize min nullunknown %{{.+}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 false)
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 false)
+ gi = __builtin_object_size(&c->bs[0], 2);
+ // CIR: cir.const #cir.int<16>
+ // LLVM: store i32 16
+ // OGCG: store i32 16
+ gi = __builtin_object_size(&c->bs[0], 3);
+
+ // NYI: DerivedToBase cast
+ // gi = __builtin_object_size((A*)&c->bs[0], 0);
+
+ // CIR: cir.const #cir.int<16>
+ // LLVM: store i32 16
+ // OGCG: store i32 16
+ gi = __builtin_object_size((A*)&c->bs[0], 1);
+
+ // NYI: DerivedToBase cast
+ // gi = __builtin_object_size((A*)&c->bs[0], 2);
+
+ // CIR: cir.const #cir.int<16>
+ // LLVM: store i32 16
+ // OGCG: store i32 16
+ gi = __builtin_object_size((A*)&c->bs[0], 3);
+
+ // CIR: cir.objsize max nullunknown %{{.+}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false)
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 false, i1 true, i1 false)
+ gi = __builtin_object_size(&c->bs[0].buf[0], 0);
+ // CIR: cir.const #cir.int<16>
+ // LLVM: store i32 16
+ // OGCG: store i32 16
+ gi = __builtin_object_size(&c->bs[0].buf[0], 1);
+ // CIR: cir.objsize min nullunknown %{{.+}} : !cir.ptr<!void> -> !u64i
+ // LLVM: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 false)
+ // OGCG: call i64 @llvm.objectsize.i64.p0(ptr %{{.*}}, i1 true, i1 true, i1 false)
+ gi = __builtin_object_size(&c->bs[0].buf[0], 2);
+ // CIR: cir.const #cir.int<16>
+ // LLVM: store i32 16
+ // OGCG: store i32 16
+ gi = __builtin_object_size(&c->bs[0].buf[0], 3);
+}
diff --git a/clang/test/CIR/CodeGen/offset-of.cpp b/clang/test/CIR/CodeGen/offset-of.cpp
new file mode 100644
index 0000000..f62da9e
--- /dev/null
+++ b/clang/test/CIR/CodeGen/offset-of.cpp
@@ -0,0 +1,93 @@
+// RUN: %clang_cc1 -std=c++20 -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 -std=c++20 -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 -std=c++20 -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
+
+struct Struct {
+ int a;
+ float b;
+ double c;
+ bool d;
+};
+
+void offset_of_builtin() {
+ unsigned long a = __builtin_offsetof(Struct, a);
+ unsigned long b = __builtin_offsetof(Struct, b);
+ unsigned long c = __builtin_offsetof(Struct, c);
+ unsigned long d = __builtin_offsetof(Struct, d);
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["a", init]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["b", init]
+// CIR: %[[C_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["c", init]
+// CIR: %[[D_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["d", init]
+// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_0]], %[[A_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[CONST_4:.*]] = cir.const #cir.int<4> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_4]], %[[B_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[CONST_8:.*]] = cir.const #cir.int<8> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_8]], %[[C_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[CONST_16:.*]] = cir.const #cir.int<16> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_16]], %[[D_ADDR]] : !u64i, !cir.ptr<!u64i>
+
+// LLVM: %[[A_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[B_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[C_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[D_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: store i64 0, ptr %[[A_ADDR]], align 8
+// LLVM: store i64 4, ptr %[[B_ADDR]], align 8
+// LLVM: store i64 8, ptr %[[C_ADDR]], align 8
+// LLVM: store i64 16, ptr %[[D_ADDR]], align 8
+
+// OGCG: %[[A_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[B_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[C_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[D_ADDR:.*]] = alloca i64, align 8
+// OGCG: store i64 0, ptr %[[A_ADDR]], align 8
+// OGCG: store i64 4, ptr %[[B_ADDR]], align 8
+// OGCG: store i64 8, ptr %[[C_ADDR]], align 8
+// OGCG: store i64 16, ptr %[[D_ADDR]], align 8
+
+struct StructWithArray {
+ Struct array[4][4];
+};
+
+void offset_of_builtin_from_array_element() {
+ unsigned long a = __builtin_offsetof(StructWithArray, array[0][0].a);
+ unsigned long b = __builtin_offsetof(StructWithArray, array[1][1].b);
+ unsigned long c = __builtin_offsetof(StructWithArray, array[2][2].c);
+ unsigned long d = __builtin_offsetof(StructWithArray, array[3][3].d);
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["a", init]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["b", init]
+// CIR: %[[C_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["c", init]
+// CIR: %[[D_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["d", init]
+// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_0]], %[[A_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[CONST_124:.*]] = cir.const #cir.int<124> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_124]], %[[B_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[CONST_248:.*]] = cir.const #cir.int<248> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_248]], %[[C_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[CONST_376:.*]] = cir.const #cir.int<376> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_376]], %[[D_ADDR]] : !u64i, !cir.ptr<!u64i>
+
+// LLVM: %[[A_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[B_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[C_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[D_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: store i64 0, ptr %[[A_ADDR]], align 8
+// LLVM: store i64 124, ptr %[[B_ADDR]], align 8
+// LLVM: store i64 248, ptr %[[C_ADDR]], align 8
+// LLVM: store i64 376, ptr %[[D_ADDR]], align 8
+
+// OGCG: %[[A_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[B_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[C_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[D_ADDR:.*]] = alloca i64, align 8
+// OGCG: store i64 0, ptr %[[A_ADDR]], align 8
+// OGCG: store i64 124, ptr %[[B_ADDR]], align 8
+// OGCG: store i64 248, ptr %[[C_ADDR]], align 8
+// OGCG: store i64 376, ptr %[[D_ADDR]], align 8
diff --git a/clang/test/CIR/CodeGen/paren-init-list.cpp b/clang/test/CIR/CodeGen/paren-init-list.cpp
index 0efa363..a5676e2 100644
--- a/clang/test/CIR/CodeGen/paren-init-list.cpp
+++ b/clang/test/CIR/CodeGen/paren-init-list.cpp
@@ -13,18 +13,11 @@ struct CompleteS {
void cxx_paren_list_init_expr() { CompleteS a(1, 'a'); }
// CIR: %[[A_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["a", init]
-// CIR: %[[ELEM_0_PTR:.*]] = cir.get_member %[[A_ADDR]][0] {name = "a"} : !cir.ptr<!rec_CompleteS> -> !cir.ptr<!s32i>
-// CIR: %[[ELEM_0_VAL:.*]] = cir.const #cir.int<1> : !s32i
-// CIR: cir.store{{.*}} %[[ELEM_0_VAL]], %[[ELEM_0_PTR]] : !s32i, !cir.ptr<!s32i>
-// CIR: %[[ELEM_1_PTR:.*]] = cir.get_member %[[A_ADDR]][1] {name = "b"} : !cir.ptr<!rec_CompleteS> -> !cir.ptr<!s8i>
-// CIR: %[[ELEM_1_VAL:.*]] = cir.const #cir.int<97> : !s8i
-// CIR: cir.store{{.*}} %[[ELEM_1_VAL]], %[[ELEM_1_PTR]] : !s8i, !cir.ptr<!s8i>
+// CIR: %[[CONST:.*]] = cir.const #cir.const_record<{#cir.int<1> : !s32i, #cir.int<97> : !s8i}> : !rec_CompleteS
+// CIR: cir.store{{.*}} %[[CONST]], %[[A_ADDR]]
// LLVM: %[[A_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 4
-// LLVM: %[[ELEM_0_PTR:.*]] = getelementptr %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 0
-// LLVM: store i32 1, ptr %[[ELEM_0_PTR]], align 4
-// LLVM: %[[ELEM_1_PTR:.*]] = getelementptr %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 1
-// LLVM: store i8 97, ptr %[[ELEM_1_PTR]], align 4
+// LLVM: store %struct.CompleteS { i32 1, i8 97 }, ptr %[[A_ADDR]], align 4
// OGCG: %[[A_ADDR:.*]] = alloca %struct.CompleteS, align 4
// OGCG: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %[[A_ADDR]], ptr align 4 @__const._Z24cxx_paren_list_init_exprv.a, i64 8, i1 false)
diff --git a/clang/test/CIR/CodeGen/placement-new.cpp b/clang/test/CIR/CodeGen/placement-new.cpp
new file mode 100644
index 0000000..ccc3548
--- /dev/null
+++ b/clang/test/CIR/CodeGen/placement-new.cpp
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu %s -fclangir -emit-cir -o %t.cir
+// RUN: FileCheck --input-file=%t.cir -check-prefix=CIR %s
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu %s -fclangir -emit-llvm -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll -check-prefix=LLVM %s
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu %s -emit-llvm -o %t.ll
+// RUN: FileCheck --input-file=%t.ll -check-prefix=OGCG %s
+
+typedef __typeof__(sizeof(0)) size_t;
+
+// Declare the reserved placement operators.
+void *operator new(size_t, void*) throw();
+
+struct A { A(); ~A(); };
+
+void test_reserved_placement_new(void *p) {
+ new (p) A();
+}
+
+// CIR-LABEL: cir.func {{.*}} @_Z27test_reserved_placement_newPv(
+// CIR-SAME: %[[ARG0:.*]]: !cir.ptr<!void>
+// CIR: %[[P:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["p", init]
+// CIR: cir.store %[[ARG0]], %[[P]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
+// CIR: %[[SIZE:.*]] = cir.const #cir.int<1> : !u64i
+// CIR: %[[PTR:.*]] = cir.load{{.*}} %[[P]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+// CIR: %[[PTR_A:.*]] = cir.cast bitcast %[[PTR]] : !cir.ptr<!void> -> !cir.ptr<!rec_A>
+// CIR: cir.call @_ZN1AC1Ev(%[[PTR_A]]) : (!cir.ptr<!rec_A>) -> ()
+
+// LLVM-LABEL: define dso_local void @_Z27test_reserved_placement_newPv(
+// LLVM-SAME: ptr %[[ARG0:.*]]
+// LLVM: %[[P:.*]] = alloca ptr
+// LLVM: store ptr %[[ARG0:.*]], ptr %[[P]]
+// LLVM: %[[PTR:.*]] = load ptr, ptr %[[P]]
+// LLVM: call void @_ZN1AC1Ev(ptr %[[PTR]])
+
+// OGCG-LABEL: define dso_local void @_Z27test_reserved_placement_newPv(
+// OGCG-SAME: ptr {{.*}} %[[ARG0:.*]]
+// OGCG: %[[P:.*]] = alloca ptr
+// OGCG: store ptr %[[ARG0:.*]], ptr %[[P]]
+// OGCG: %[[PTR:.*]] = load ptr, ptr %[[P]]
+// OGCG: call void @_ZN1AC1Ev(ptr {{.*}} %[[PTR]])
diff --git a/clang/test/CIR/CodeGen/pointer-to-data-member.cpp b/clang/test/CIR/CodeGen/pointer-to-data-member.cpp
new file mode 100644
index 0000000..b116d21
--- /dev/null
+++ b/clang/test/CIR/CodeGen/pointer-to-data-member.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++17 -fclangir -Wno-unused-value -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 -std=c++17 -fclangir -Wno-unused-value -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 -std=c++17 -Wno-unused-value -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
+
+struct Point {
+ int x;
+ int y;
+ int z;
+};
+
+auto test1() -> int Point::* {
+ return &Point::y;
+}
+
+// CIR: cir.func {{.*}} @_Z5test1v() -> !cir.data_member<!s32i in !rec_Point> {
+// CIR: %[[RETVAL:.*]] = cir.alloca !cir.data_member<!s32i in !rec_Point>, !cir.ptr<!cir.data_member<!s32i in !rec_Point>>, ["__retval"]
+// CIR: %[[MEMBER:.*]] = cir.const #cir.data_member<1> : !cir.data_member<!s32i in !rec_Point>
+// CIR: cir.store %[[MEMBER]], %[[RETVAL]] : !cir.data_member<!s32i in !rec_Point>, !cir.ptr<!cir.data_member<!s32i in !rec_Point>>
+// CIR: %[[RET:.*]] = cir.load %[[RETVAL]] : !cir.ptr<!cir.data_member<!s32i in !rec_Point>>, !cir.data_member<!s32i in !rec_Point>
+// CIR: cir.return %[[RET]] : !cir.data_member<!s32i in !rec_Point>
+
+// LLVM: define {{.*}} i64 @_Z5test1v()
+// LLVM: %[[RETVAL:.*]] = alloca i64
+// LLVM: store i64 4, ptr %[[RETVAL]]
+// LLVM: %[[RET:.*]] = load i64, ptr %[[RETVAL]]
+// LLVM: ret i64 %[[RET]]
+
+// OGCG: define {{.*}} i64 @_Z5test1v()
+// OGCG: ret i64 4
diff --git a/clang/test/CIR/CodeGen/ptrdiff.cpp b/clang/test/CIR/CodeGen/ptrdiff.cpp
index 34ba0ff..5805349 100644
--- a/clang/test/CIR/CodeGen/ptrdiff.cpp
+++ b/clang/test/CIR/CodeGen/ptrdiff.cpp
@@ -8,7 +8,7 @@
typedef unsigned long size_type;
size_type size(unsigned long *_start, unsigned long *_finish) {
- // CIR-LABEL: cir.func dso_local @_Z4sizePmS_
+ // CIR-LABEL: cir.func {{.*}} @_Z4sizePmS_
// CIR: %[[D:.*]] = cir.ptr_diff {{.*}} : !cir.ptr<!u64i> -> !s64i
// CIR: %[[U:.*]] = cir.cast integral %[[D]] : !s64i -> !u64i
// CIR: cir.return {{.*}} : !u64i
diff --git a/clang/test/CIR/CodeGen/record-zero-init-padding.c b/clang/test/CIR/CodeGen/record-zero-init-padding.c
index f131c9b..9c8dacc 100644
--- a/clang/test/CIR/CodeGen/record-zero-init-padding.c
+++ b/clang/test/CIR/CodeGen/record-zero-init-padding.c
@@ -41,28 +41,28 @@ void test_zero_init_padding(void) {
// CIR-DAG: !rec_anon_struct3 = !cir.record<struct {!s8i, !cir.array<!u8i x 3>, !s32i}>
// paf: char + 3 bytes padding + int -> uses !rec_anon_struct3
-// CIR-DAG: cir.global "private" internal dso_local @test_zero_init_padding.paf = #cir.const_record<{
+// CIR-DAG: cir.global "private" constant internal dso_local @test_zero_init_padding.paf = #cir.const_record<{
// CIR-DAG-SAME: #cir.int<1> : !s8i,
// CIR-DAG-SAME: #cir.const_array<[#cir.zero : !u8i, #cir.zero : !u8i, #cir.zero : !u8i]> : !cir.array<!u8i x 3>,
// CIR-DAG-SAME: #cir.int<42> : !s32i
// CIR-DAG-SAME: }> : !rec_anon_struct3
// bfp: unsigned bitfield byte + 3 bytes padding + int -> uses !rec_anon_struct2
-// CIR-DAG: cir.global "private" internal dso_local @test_zero_init_padding.bfp = #cir.const_record<{
+// CIR-DAG: cir.global "private" constant internal dso_local @test_zero_init_padding.bfp = #cir.const_record<{
// CIR-DAG-SAME: #cir.int<17> : !u8i,
// CIR-DAG-SAME: #cir.const_array<[#cir.zero : !u8i, #cir.zero : !u8i, #cir.zero : !u8i]> : !cir.array<!u8i x 3>,
// CIR-DAG-SAME: #cir.int<99> : !s32i
// CIR-DAG-SAME: }> : !rec_anon_struct2
// tp: int + char + 3 bytes tail padding -> uses !rec_anon_struct1
-// CIR-DAG: cir.global "private" internal dso_local @test_zero_init_padding.tp = #cir.const_record<{
+// CIR-DAG: cir.global "private" constant internal dso_local @test_zero_init_padding.tp = #cir.const_record<{
// CIR-DAG-SAME: #cir.int<10> : !s32i,
// CIR-DAG-SAME: #cir.int<20> : !s8i,
// CIR-DAG-SAME: #cir.const_array<[#cir.zero : !u8i, #cir.zero : !u8i, #cir.zero : !u8i]> : !cir.array<!u8i x 3>
// CIR-DAG-SAME: }> : !rec_anon_struct1
// mp: char + 1 byte padding + short + 4 bytes padding + long long -> uses !rec_anon_struct
-// CIR-DAG: cir.global "private" internal dso_local @test_zero_init_padding.mp = #cir.const_record<{
+// CIR-DAG: cir.global "private" constant internal dso_local @test_zero_init_padding.mp = #cir.const_record<{
// CIR-DAG-SAME: #cir.int<5> : !s8i,
// CIR-DAG-SAME: #cir.zero : !u8i,
// CIR-DAG-SAME: #cir.int<10> : !s16i,
@@ -73,10 +73,10 @@ void test_zero_init_padding(void) {
// CIR-LABEL: cir.func {{.*}}@test_zero_init_padding
// CIR: cir.return
-// LLVM-DAG: @test_zero_init_padding.paf = internal global { i8, [3 x i8], i32 } { i8 1, [3 x i8] zeroinitializer, i32 42 }
-// LLVM-DAG: @test_zero_init_padding.bfp = internal global { i8, [3 x i8], i32 } { i8 17, [3 x i8] zeroinitializer, i32 99 }
-// LLVM-DAG: @test_zero_init_padding.tp = internal global { i32, i8, [3 x i8] } { i32 10, i8 20, [3 x i8] zeroinitializer }
-// LLVM-DAG: @test_zero_init_padding.mp = internal global { i8, i8, i16, [4 x i8], i64 } { i8 5, i8 0, i16 10, [4 x i8] zeroinitializer, i64 100 }
+// LLVM-DAG: @test_zero_init_padding.paf = internal constant { i8, [3 x i8], i32 } { i8 1, [3 x i8] zeroinitializer, i32 42 }
+// LLVM-DAG: @test_zero_init_padding.bfp = internal constant { i8, [3 x i8], i32 } { i8 17, [3 x i8] zeroinitializer, i32 99 }
+// LLVM-DAG: @test_zero_init_padding.tp = internal constant { i32, i8, [3 x i8] } { i32 10, i8 20, [3 x i8] zeroinitializer }
+// LLVM-DAG: @test_zero_init_padding.mp = internal constant { i8, i8, i16, [4 x i8], i64 } { i8 5, i8 0, i16 10, [4 x i8] zeroinitializer, i64 100 }
// LLVM-LABEL: define{{.*}} void @test_zero_init_padding
// LLVM: ret void
diff --git a/clang/test/CIR/CodeGen/size-of-vla.cpp b/clang/test/CIR/CodeGen/size-of-vla.cpp
new file mode 100644
index 0000000..bcaab27
--- /dev/null
+++ b/clang/test/CIR/CodeGen/size-of-vla.cpp
@@ -0,0 +1,156 @@
+// 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 vla_type_with_element_type_of_size_1() {
+ unsigned long n = 10ul;
+ unsigned long size = sizeof(bool[n]);
+}
+
+// CIR: %[[N_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["n", init]
+// CIR: %[[SIZE_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["size", init]
+// CIR: %[[CONST_10:.*]] = cir.const #cir.int<10> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_10]], %[[N_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[TMP_N:.*]] = cir.load {{.*}} %[[N_ADDR]] : !cir.ptr<!u64i>, !u64i
+// CIR: cir.store {{.*}} %[[TMP_N]], %[[SIZE_ADDR]] : !u64i, !cir.ptr<!u64i>
+
+// LLVM: %[[N_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[SIZE_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: store i64 10, ptr %[[N_ADDR]], align 8
+// LLVM: %[[TMP_N:.*]] = load i64, ptr %[[N_ADDR]], align 8
+// LLVM: store i64 %[[TMP_N]], ptr %[[SIZE_ADDR]], align 8
+
+// OGCG: %[[N_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[SIZE_ADDR:.*]] = alloca i64, align 8
+// OGCG: store i64 10, ptr %[[N_ADDR]], align 8
+// OGCG: %[[TMP_N:.*]] = load i64, ptr %[[N_ADDR]], align 8
+// OGCG: store i64 %[[TMP_N]], ptr %[[SIZE_ADDR]], align 8
+
+void vla_type_with_element_type_int() {
+ unsigned long n = 10ul;
+ unsigned long size = sizeof(int[n]);
+}
+
+// CIR: %[[N_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["n", init]
+// CIR: %[[SIZE_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["size", init]
+// CIR: %[[CONST_10:.*]] = cir.const #cir.int<10> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_10]], %[[N_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %3 = cir.load {{.*}} %[[N_ADDR]] : !cir.ptr<!u64i>, !u64i
+// CIR: %[[CONST_4:.*]] = cir.const #cir.int<4> : !u64i
+// CIR: %[[SIZE:.*]] = cir.binop(mul, %[[CONST_4]], %3) nuw : !u64i
+// CIR: cir.store {{.*}} %[[SIZE]], %[[SIZE_ADDR]] : !u64i, !cir.ptr<!u64i>
+
+// LLVM: %[[N_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[SIZE_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: store i64 10, ptr %[[N_ADDR]], align 8
+// LLVM: %[[TMP_N:.*]] = load i64, ptr %[[N_ADDR]], align 8
+// LLVM: %[[SIZE:.*]] = mul nuw i64 4, %[[TMP_N]]
+// LLVM: store i64 %[[SIZE]], ptr %[[SIZE_ADDR]], align 8
+
+// OGCG: %[[N_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[SIZE_ADDR:.*]] = alloca i64, align 8
+// OGCG: store i64 10, ptr %[[N_ADDR]], align 8
+// OGCG: %[[TMP_N:.*]] = load i64, ptr %[[N_ADDR]], align 8
+// OGCG: %[[SIZE:.*]] = mul nuw i64 4, %[[TMP_N]]
+// OGCG: store i64 %[[SIZE]], ptr %[[SIZE_ADDR]], align 8
+
+void vla_expr_element_type_of_size_1() {
+ unsigned long n = 10ul;
+ bool arr[n];
+ unsigned long size = sizeof(arr);
+}
+
+// CIR: %[[N_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["n", init]
+// CIR: %[[SAVED_STACK_ADDR:.*]] = cir.alloca !cir.ptr<!u8i>, !cir.ptr<!cir.ptr<!u8i>>, ["saved_stack"]
+// CIR: %[[CONST_10:.*]] = cir.const #cir.int<10> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_10]], %[[N_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[TMP_N:.*]] = cir.load {{.*}} %[[N_ADDR]] : !cir.ptr<!u64i>, !u64i
+// CIR: %[[STACK_SAVE:.*]] = cir.stacksave : !cir.ptr<!u8i>
+// CIR: cir.store {{.*}} %[[STACK_SAVE]], %[[SAVED_STACK_ADDR]] : !cir.ptr<!u8i>, !cir.ptr<!cir.ptr<!u8i>>
+// CIR: %[[ARR_ADDR:.*]] = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, %[[TMP_N]] : !u64i, ["arr"]
+// CIR: %[[SIZE_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["size", init]
+// CIR: cir.store {{.*}} %[[TMP_N]], %[[SIZE_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[TMP_SAVED_STACK:.*]] = cir.load {{.*}} %[[SAVED_STACK_ADDR]] : !cir.ptr<!cir.ptr<!u8i>>, !cir.ptr<!u8i>
+// CIR: cir.stackrestore %[[TMP_SAVED_STACK]] : !cir.ptr<!u8i>
+
+// LLVM: %[[N_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[SAVED_STACK_ADDR:.*]] = alloca ptr, i64 1, align 8
+// LLVM: store i64 10, ptr %[[N_ADDR]], align 8
+// LLVM: %[[TMP_N:.*]] = load i64, ptr %[[N_ADDR]], align 8
+// LLVM: %[[STACK_SAVE:.*]] = call ptr @llvm.stacksave.p0()
+// LLVM: store ptr %[[STACK_SAVE]], ptr %[[SAVED_STACK_ADDR]], align 8
+// LLVM: %[[ARR_ADDR:.*]] = alloca i8, i64 %[[TMP_N]], align 16
+// LLVM: %[[SIZE_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: store i64 %[[TMP_N]], ptr %[[SIZE_ADDR]], align 8
+// LLVM: %[[TMP_SAVED_STACK:.*]] = load ptr, ptr %[[SAVED_STACK_ADDR]], align 8
+// LLVM: call void @llvm.stackrestore.p0(ptr %[[TMP_SAVED_STACK]])
+
+// Note: VLA_EXPR0 below is emitted to capture debug info.
+
+// OGCG: %[[N_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[SAVED_STACK_ADDR:.*]] = alloca ptr, align 8
+// OGCG: %[[VLA_EXPR0:.*]] = alloca i64, align 8
+// OGCG: %[[SIZE_ADDR:.*]] = alloca i64, align 8
+// OGCG: store i64 10, ptr %[[N_ADDR]], align 8
+// OGCG: %[[TMP_N:.*]] = load i64, ptr %[[N_ADDR]], align 8
+// OGCG: %[[STACK_SAVE:.*]] = call ptr @llvm.stacksave.p0()
+// OGCG: store ptr %[[STACK_SAVE]], ptr %[[SAVED_STACK_ADDR]], align 8
+// OGCG: %[[ARR_ADDR:.*]] = alloca i8, i64 %[[TMP_N]], align 16
+// OGCG: store i64 %[[TMP_N]], ptr %[[VLA_EXPR0]], align 8
+// OGCG: store i64 %[[TMP_N]], ptr %[[SIZE_ADDR]], align 8
+// OGCG: %[[TMP_SAVED_STACK:.*]] = load ptr, ptr %[[SAVED_STACK_ADDR]], align 8
+// OGCG: call void @llvm.stackrestore.p0(ptr %[[TMP_SAVED_STACK]])
+
+void vla_expr_element_type_int() {
+ unsigned long n = 10ul;
+ int arr[n];
+ unsigned long size = sizeof(arr);
+}
+
+// CIR: %[[N_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["n", init]
+// CIR: %[[SAVED_STACK_ADDR:.*]] = cir.alloca !cir.ptr<!u8i>, !cir.ptr<!cir.ptr<!u8i>>, ["saved_stack"]
+// CIR: %[[CONST_10:.*]] = cir.const #cir.int<10> : !u64i
+// CIR: cir.store {{.*}} %[[CONST_10]], %[[N_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[TMP_N:.*]] = cir.load {{.*}} %[[N_ADDR]] : !cir.ptr<!u64i>, !u64i
+// CIR: %[[STACK_SAVE:.*]] = cir.stacksave : !cir.ptr<!u8i>
+// CIR: cir.store {{.*}} %[[STACK_SAVE]], %[[SAVED_STACK_ADDR]] : !cir.ptr<!u8i>, !cir.ptr<!cir.ptr<!u8i>>
+// CIR: %[[ARR_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, %[[TMP_N]] : !u64i, ["arr"]
+// CIR: %[[SIZE_ADDR:.*]] = cir.alloca !u64i, !cir.ptr<!u64i>, ["size", init]
+// CIR: %[[CONST_4:.*]] = cir.const #cir.int<4> : !u64i
+// CIR: %[[SIZE:.*]] = cir.binop(mul, %[[CONST_4]], %[[TMP_N]]) nuw : !u64i
+// CIR: cir.store {{.*}} %[[SIZE]], %[[SIZE_ADDR]] : !u64i, !cir.ptr<!u64i>
+// CIR: %[[TMP_SAVED_STACK:.*]] = cir.load {{.*}} %[[SAVED_STACK_ADDR]] : !cir.ptr<!cir.ptr<!u8i>>, !cir.ptr<!u8i>
+// CIR: cir.stackrestore %[[TMP_SAVED_STACK]] : !cir.ptr<!u8i>
+
+// LLVM: %[[N_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[SAVED_STACK_ADDR:.*]] = alloca ptr, i64 1, align 8
+// LLVM: store i64 10, ptr %[[N_ADDR]], align 8
+// LLVM: %[[TMP_N:.*]] = load i64, ptr %[[N_ADDR]], align 8
+// LLVM: %[[STACK_SAVE:.*]] = call ptr @llvm.stacksave.p0()
+// LLVM: store ptr %[[STACK_SAVE]], ptr %[[SAVED_STACK_ADDR]], align 8
+// LLVM: %[[ARR_ADDR:.*]] = alloca i32, i64 %[[TMP_N]], align 16
+// LLVM: %[[SIZE_ADDR:.*]] = alloca i64, i64 1, align 8
+// LLVM: %[[SIZE:.*]] = mul nuw i64 4, %[[TMP_N]]
+// LLVM: store i64 %[[SIZE]], ptr %[[SIZE_ADDR]], align 8
+// LLVM: %[[TMP_SAVED_STACK:.*]] = load ptr, ptr %[[SAVED_STACK_ADDR]], align 8
+// LLVM: call void @llvm.stackrestore.p0(ptr %[[TMP_SAVED_STACK]])
+
+// Note: VLA_EXPR0 below is emitted to capture debug info.
+
+// OGCG: %[[N_ADDR:.*]] = alloca i64, align 8
+// OGCG: %[[SAVED_STACK_ADDR:.*]] = alloca ptr, align 8
+// OGCG: %[[VLA_EXPR0:.*]] = alloca i64, align 8
+// OGCG: %[[SIZE_ADDR:.*]] = alloca i64, align 8
+// OGCG: store i64 10, ptr %[[N_ADDR]], align 8
+// OGCG: %[[TMP_N:.*]] = load i64, ptr %[[N_ADDR]], align 8
+// OGCG: %[[STACK_SAVE:.*]] = call ptr @llvm.stacksave.p0()
+// OGCG: store ptr %[[STACK_SAVE]], ptr %[[SAVED_STACK_ADDR]], align 8
+// OGCG: %[[ARR_ADDR:.*]] = alloca i32, i64 %[[TMP_N]], align 16
+// OGCG: store i64 %[[TMP_N]], ptr %[[VLA_EXPR0]], align 8
+// OGCG: %[[SIZE:.*]] = mul nuw i64 4, %[[TMP_N]]
+// OGCG: store i64 %[[SIZE]], ptr %[[SIZE_ADDR]], align 8
+// OGCG: %[[TMP_SAVED_STACK:.*]] = load ptr, ptr %[[SAVED_STACK_ADDR]], align 8
+// OGCG: call void @llvm.stackrestore.p0(ptr %[[TMP_SAVED_STACK]])
diff --git a/clang/test/CIR/CodeGen/statement-exprs.c b/clang/test/CIR/CodeGen/statement-exprs.c
index c784ec9..2ea4672 100644
--- a/clang/test/CIR/CodeGen/statement-exprs.c
+++ b/clang/test/CIR/CodeGen/statement-exprs.c
@@ -6,10 +6,10 @@
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG
int f19(void) {
- return ({ 3;;4;; });
+ return ({ 3;;4; });
}
-// CIR: cir.func dso_local @f19() -> !s32i
+// CIR: cir.func {{.*}} @f19() -> !s32i
// CIR: %[[RETVAL:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
// CIR: %[[TMP:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["tmp"]
// CIR: cir.scope {
@@ -42,6 +42,16 @@ int f19(void) {
// OGCG: %[[TMP_VAL:.+]] = load i32, ptr %[[TMP]]
// OGCG: ret i32 %[[TMP_VAL]]
+// PR166036: The trailing NullStmt should result in a void.
+void f20(void) {
+ return ({ 3;;4;; });
+}
+
+// CIR-LABEL: cir.func {{.*}} @f20() {{[^-]*}}
+// CIR: cir.return {{[^%]*}}
+
+// LLVM-LABEL: define{{.*}} void @f20
+// LLVM: ret void
int nested(void) {
({123;});
@@ -51,7 +61,7 @@ int nested(void) {
}
}
-// CIR: cir.func dso_local @nested() -> !s32i
+// CIR: cir.func {{.*}} @nested() -> !s32i
// CIR: %[[RETVAL:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
// CIR: %[[TMP_OUTER:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["tmp"]
// CIR: cir.scope {
@@ -154,7 +164,7 @@ void empty() {
return ({;;;;});
}
-// CIR: cir.func no_proto dso_local @empty()
+// CIR: cir.func {{.*}} @empty()
// CIR-NEXT: cir.return
// LLVM: define dso_local void @empty()
@@ -167,7 +177,7 @@ void empty() {
void empty2() { ({ }); }
-// CIR: @empty2
+// CIR: cir.func {{.*}} @empty2
// CIR-NEXT: cir.return
// LLVM: @empty2()
@@ -181,7 +191,7 @@ void empty2() { ({ }); }
// Yields an out-of-scope scalar.
void test2() { ({int x = 3; x; }); }
-// CIR: @test2
+// CIR: cir.func {{.*}} @test2
// CIR: %[[RETVAL:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>
// CIR: cir.scope {
// CIR: %[[VAR:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init]
@@ -216,16 +226,15 @@ void test2() { ({int x = 3; x; }); }
// Yields an aggregate.
struct S { int x; };
int test3() { return ({ struct S s = {1}; s; }).x; }
-// CIR: cir.func no_proto dso_local @test3() -> !s32i
+// CIR: cir.func {{.*}} @test3() -> !s32i
// CIR: %[[RETVAL:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
// CIR: cir.scope {
// CIR: %[[REF_TMP0:.+]] = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["ref.tmp0"]
// CIR: %[[TMP:.+]] = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["tmp"]
// CIR: cir.scope {
// CIR: %[[S:.+]] = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["s", init]
-// CIR: %[[GEP_X_S:.+]] = cir.get_member %[[S]][0] {name = "x"} : !cir.ptr<!rec_S> -> !cir.ptr<!s32i>
-// CIR: %[[C1:.+]] = cir.const #cir.int<1> : !s32i
-// CIR: cir.store {{.*}} %[[C1]], %[[GEP_X_S]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[CONST:.*]] = cir.const #cir.const_record<{#cir.int<1> : !s32i}> : !rec_S
+// CIR: cir.store{{.*}} %[[CONST]], %[[S]] : !rec_S, !cir.ptr<!rec_S>
// CIR: cir.copy %[[S]] to %[[REF_TMP0]] : !cir.ptr<!rec_S>
// CIR: }
// CIR: %[[GEP_X_TMP:.+]] = cir.get_member %[[REF_TMP0]][0] {name = "x"} : !cir.ptr<!rec_S> -> !cir.ptr<!s32i>
@@ -244,8 +253,7 @@ int test3() { return ({ struct S s = {1}; s; }).x; }
// LLVM: [[LBL5]]:
// LLVM: br label %[[LBL6:.+]]
// LLVM: [[LBL6]]:
-// LLVM: %[[GEP_S:.+]] = getelementptr %struct.S, ptr %[[VAR3]], i32 0, i32 0
-// LLVM: store i32 1, ptr %[[GEP_S]]
+// LLVM: store %struct.S { i32 1 }, ptr %[[VAR3]]
// LLVM: call void @llvm.memcpy.p0.p0.i32(ptr %[[VAR1]], ptr %[[VAR3]], i32 4, i1 false)
// LLVM: br label %[[LBL8:.+]]
// LLVM: [[LBL8]]:
@@ -269,6 +277,6 @@ int test3() { return ({ struct S s = {1}; s; }).x; }
// Expression is wrapped in an expression attribute (just ensure it does not crash).
void test4(int x) { ({[[gsl::suppress("foo")]] x;}); }
-// CIR: @test4
+// CIR: cir.func {{.*}} @test4
// LLVM: @test4
// OGCG: @test4
diff --git a/clang/test/CIR/CodeGen/static-members.cpp b/clang/test/CIR/CodeGen/static-members.cpp
new file mode 100644
index 0000000..8722dc2
--- /dev/null
+++ b/clang/test/CIR/CodeGen/static-members.cpp
@@ -0,0 +1,94 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
+// RUN: FileCheck %s -check-prefix=CIR --input-file=%t.cir
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
+// RUN: FileCheck %s -check-prefix=LLVM --input-file=%t-cir.ll
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck %s -check-prefix=OGCG --input-file=%t.ll
+
+struct HasDtor {
+ ~HasDtor();
+};
+struct S {
+ static inline HasDtor hd;
+};
+
+// CIR: cir.global linkonce_odr comdat @_ZN1S2hdE = #cir.zero : !rec_HasDtor
+
+// CIR: cir.func internal private @__cxx_global_var_init() {
+// CIR: %[[HD:.*]] = cir.get_global @_ZN1S2hdE : !cir.ptr<!rec_HasDtor>
+// CIR: %[[DTOR:.*]] = cir.get_global @_ZN7HasDtorD1Ev : !cir.ptr<!cir.func<(!cir.ptr<!rec_HasDtor>)>>
+// CIR: %[[DTOR_CAST:.*]] = cir.cast bitcast %[[DTOR]] : !cir.ptr<!cir.func<(!cir.ptr<!rec_HasDtor>)>> -> !cir.ptr<!cir.func<(!cir.ptr<!void>)>>
+// CIR: %[[HD_CAST:.*]] = cir.cast bitcast %[[HD]] : !cir.ptr<!rec_HasDtor> -> !cir.ptr<!void>
+// CIR: %[[HANDLE:.*]] = cir.get_global @__dso_handle : !cir.ptr<i8>
+// CIR: cir.call @__cxa_atexit(%[[DTOR_CAST]], %[[HD_CAST]], %[[HANDLE]])
+
+// LLVM: @_ZN1S2hdE = linkonce_odr global %struct.HasDtor zeroinitializer, comdat
+// LLVM: @_ZN5Outer5Inner2hdE = linkonce_odr global %struct.HasDtor zeroinitializer, comdat
+
+// LLVM: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I_static_members.cpp, ptr null }]
+// LLVM: define internal void @__cxx_global_var_init()
+// LLVM: call void @__cxa_atexit(ptr @_ZN7HasDtorD1Ev, ptr @_ZN1S2hdE, ptr @__dso_handle)
+
+// FIXME(cir): OGCG has a guard variable for this case that we don't generate in CIR.
+// This is needed because the variable linkonce_odr linkage.
+
+// OGCG: @_ZN1S2hdE = linkonce_odr global %struct.HasDtor zeroinitializer, comdat
+// OGCG: @_ZGVN1S2hdE = linkonce_odr global i64 0, comdat($_ZN1S2hdE)
+// OGCG: @_ZN5Outer5Inner2hdE = linkonce_odr global %struct.HasDtor zeroinitializer, comdat
+// OGCG: @_ZGVN5Outer5Inner2hdE = linkonce_odr global i64 0, comdat($_ZN5Outer5Inner2hdE)
+// OGCG: @llvm.global_ctors = appending global [2 x { i32, ptr, ptr }] [
+// OGCG-SAME: { i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init, ptr @_ZN1S2hdE },
+// OGCG-SAME: { i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init.1, ptr @_ZN5Outer5Inner2hdE }]
+
+// OGCG: define internal void @__cxx_global_var_init() {{.*}} section ".text.startup" comdat($_ZN1S2hdE) {
+// OGCG: %[[GUARD:.*]] = load atomic i8, ptr @_ZGVN1S2hdE acquire
+// OGCG: %[[UNINIT:.*]] = icmp eq i8 %[[GUARD]], 0
+// OGCG: br i1 %[[UNINIT]], label %[[INIT_CHECK:.*]], label %[[INIT_END:.*]]
+// OGCG: [[INIT_CHECK:.*]]:
+// OGCG: %[[GUARD_ACQUIRE:.*]] = call i32 @__cxa_guard_acquire(ptr @_ZGVN1S2hdE)
+// OGCG: %[[TOBOOL:.*]] = icmp ne i32 %[[GUARD_ACQUIRE]], 0
+// OGCG: br i1 %[[TOBOOL]], label %[[INIT:.*]], label %[[INIT_END]]
+// OGCG: [[INIT:.*]]:
+// OGCG: %[[ATEXIT:.*]] = call i32 @__cxa_atexit(ptr @_ZN7HasDtorD1Ev, ptr @_ZN1S2hdE, ptr @__dso_handle)
+// OGCG: call void @__cxa_guard_release(ptr @_ZGVN1S2hdE)
+// OGCG: br label %[[INIT_END]]
+// OGCG: [[INIT_END]]:
+
+struct Outer {
+ struct Inner {
+ static inline HasDtor hd;
+ };
+};
+
+// CIR: cir.global linkonce_odr comdat @_ZN5Outer5Inner2hdE = #cir.zero : !rec_HasDtor
+// CIR: cir.func internal private @__cxx_global_var_init.1()
+// CIR: %[[HD:.*]] = cir.get_global @_ZN5Outer5Inner2hdE : !cir.ptr<!rec_HasDtor>
+// CIR: %[[DTOR:.*]] = cir.get_global @_ZN7HasDtorD1Ev : !cir.ptr<!cir.func<(!cir.ptr<!rec_HasDtor>)>>
+// CIR: %[[DTOR_CAST:.*]] = cir.cast bitcast %[[DTOR]] : !cir.ptr<!cir.func<(!cir.ptr<!rec_HasDtor>)>> -> !cir.ptr<!cir.func<(!cir.ptr<!void>)>>
+// CIR: %[[HD_CAST:.*]] = cir.cast bitcast %[[HD]] : !cir.ptr<!rec_HasDtor> -> !cir.ptr<!void>
+// CIR: %[[HANDLE:.*]] = cir.get_global @__dso_handle : !cir.ptr<i8>
+// CIR: cir.call @__cxa_atexit(%[[DTOR_CAST]], %[[HD_CAST]], %[[HANDLE]]) : (!cir.ptr<!cir.func<(!cir.ptr<!void>)>>, !cir.ptr<!void>, !cir.ptr<i8>) -> ()
+
+// LLVM: define internal void @__cxx_global_var_init.1()
+// LLVM: call void @__cxa_atexit(ptr @_ZN7HasDtorD1Ev, ptr @_ZN5Outer5Inner2hdE, ptr @__dso_handle)
+
+// OGCG: define internal void @__cxx_global_var_init.1() {{.*}} section ".text.startup" comdat($_ZN5Outer5Inner2hdE) {
+// OGCG: %[[GUARD:.*]] = load atomic i8, ptr @_ZGVN5Outer5Inner2hdE acquire
+// OGCG: %[[UNINIT:.*]] = icmp eq i8 %[[GUARD]], 0
+// OGCG: br i1 %[[UNINIT]], label %[[INIT_CHECK:.*]], label %[[INIT_END:.*]]
+// OGCG: [[INIT_CHECK:.*]]:
+// OGCG: %[[GUARD_ACQUIRE:.*]] = call i32 @__cxa_guard_acquire(ptr @_ZGVN5Outer5Inner2hdE)
+// OGCG: %[[TOBOOL:.*]] = icmp ne i32 %[[GUARD_ACQUIRE]], 0
+// OGCG: br i1 %[[TOBOOL]], label %[[INIT:.*]], label %[[INIT_END]]
+// OGCG: [[INIT:.*]]:
+// OGCG: %[[ATEXIT:.*]] = call i32 @__cxa_atexit(ptr @_ZN7HasDtorD1Ev, ptr @_ZN5Outer5Inner2hdE, ptr @__dso_handle)
+// OGCG: call void @__cxa_guard_release(ptr @_ZGVN5Outer5Inner2hdE)
+// OGCG: br label %[[INIT_END]]
+// OGCG: [[INIT_END]]:
+
+
+// CIR: cir.func private @_GLOBAL__sub_I_static_members.cpp()
+// CIR: cir.call @__cxx_global_var_init()
+
+// LLVM: define void @_GLOBAL__sub_I_static_members.cpp()
+// LLVM: call void @__cxx_global_var_init()
diff --git a/clang/test/CIR/CodeGen/stmt-expr.cpp b/clang/test/CIR/CodeGen/stmt-expr.cpp
index 9e3911f..b645b15 100644
--- a/clang/test/CIR/CodeGen/stmt-expr.cpp
+++ b/clang/test/CIR/CodeGen/stmt-expr.cpp
@@ -20,7 +20,7 @@ void test1() {
}).Foo();
}
-// CIR: cir.func dso_local @_Z5test1v()
+// CIR: cir.func {{.*}} @_Z5test1v()
// CIR: cir.scope {
// CIR: %[[REF_TMP0:.+]] = cir.alloca !rec_A, !cir.ptr<!rec_A>, ["ref.tmp0"]
// CIR: %[[TMP:.+]] = cir.alloca !rec_A, !cir.ptr<!rec_A>, ["tmp"]
@@ -67,7 +67,7 @@ void cleanup() {
({ with_dtor wd; });
}
-// CIR: cir.func dso_local @_Z7cleanupv()
+// CIR: cir.func {{.*}} @_Z7cleanupv()
// CIR: cir.scope {
// CIR: %[[WD:.+]] = cir.alloca !rec_with_dtor, !cir.ptr<!rec_with_dtor>, ["wd"]
// CIR: cir.call @_ZN9with_dtorD1Ev(%[[WD]]) nothrow : (!cir.ptr<!rec_with_dtor>) -> ()
@@ -88,3 +88,46 @@ void cleanup() {
// OGCG: %[[WD:.+]] = alloca %struct.with_dtor
// OGCG: call void @_ZN9with_dtorD1Ev(ptr {{.*}} %[[WD]])
// OGCG: ret void
+
+void gnu_statement_extension() {
+ float b = __real__ ({float _Complex a; a;});
+}
+
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["b", init]
+// CIR: %[[TMP_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["tmp"]
+// CIR: cir.scope {
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
+// CIR: cir.store {{.*}} %[[TMP_A]], %[[TMP_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>
+// CIR: }
+// CIR: %[[TMP:.*]] = cir.load {{.*}} %[[TMP_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>
+// CIR: %[[REAL:.*]] = cir.complex.real %[[TMP]] : !cir.complex<!cir.float> -> !cir.float
+// CIR: cir.store {{.*}} %[[REAL]], %[[B_ADDR]] : !cir.float, !cir.ptr<!cir.float>
+
+// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 4
+// LLVM: %[[B_ADDR:.*]] = alloca float, i64 1, align 4
+// LLVM: %[[TMP_ADDR:.*]] = alloca { float, float }, i64 1, align 4
+// LLVM: br label %[[LABEL_1:.*]]
+// LLVM: [[LABEL_1]]:
+// LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 4
+// LLVM: store { float, float } %[[TMP_A]], ptr %[[TMP_ADDR]], align 4
+// LLVM: br label %[[LABEL_2:.*]]
+// LLVM: [[LABEL_2]]:
+// LLVM: %[[TMP:.*]] = load { float, float }, ptr %[[TMP_ADDR]], align 4
+// LLVM: %[[REAL:.*]] = extractvalue { float, float } %[[TMP]], 0
+// LLVM: store float %[[REAL]], ptr %[[B_ADDR]], align 4
+
+// OGCG: %[[B_ADDR:.*]] = alloca float, align 4
+// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 4
+// OGCG: %[[TMP_ADDR:.*]] = alloca { float, float }, align 4
+// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 0
+// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 4
+// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 1
+// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 4
+// OGCG: %[[TMP_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[TMP_ADDR]], i32 0, i32 0
+// OGCG: %[[TMP_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[TMP_ADDR]], i32 0, i32 1
+// OGCG: store float %[[A_REAL]], ptr %[[TMP_REAL_PTR]], align 4
+// OGCG: store float %[[A_IMAG]], ptr %[[TMP_IMAG_PTR]], align 4
+// OGCG: %[[TMP_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[TMP_ADDR]], i32 0, i32 0
+// OGCG: %[[TMP_REAL:.*]] = load float, ptr %[[TMP_REAL_PTR]], align 4
+// OGCG: store float %[[TMP_REAL]], ptr %[[B_ADDR]], align 4
diff --git a/clang/test/CIR/CodeGen/struct-init.cpp b/clang/test/CIR/CodeGen/struct-init.cpp
index 7988619..f5c013a 100644
--- a/clang/test/CIR/CodeGen/struct-init.cpp
+++ b/clang/test/CIR/CodeGen/struct-init.cpp
@@ -65,41 +65,16 @@ void init() {
// CIR: cir.func{{.*}} @_Z4initv()
// CIR: %[[S1:.*]] = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["s1", init]
// CIR: %[[S2:.*]] = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["s2", init]
-// CIR: %[[S1_A:.*]] = cir.get_member %[[S1]][0] {name = "a"}
-// CIR: %[[ONE:.*]] = cir.const #cir.int<1>
-// CIR: cir.store{{.*}} %[[ONE]], %[[S1_A]]
-// CIR: %[[S1_B:.*]] = cir.get_member %[[S1]][1] {name = "b"}
-// CIR: %[[TWO:.*]] = cir.const #cir.int<2>
-// CIR: cir.store{{.*}} %[[TWO]], %[[S1_B]]
-// CIR: %[[S1_C:.*]] = cir.get_member %[[S1]][2] {name = "c"}
-// CIR: %[[THREE:.*]] = cir.const #cir.int<3>
-// CIR: cir.store{{.*}} %[[THREE]], %[[S1_C]]
-// CIR: %[[S2_A:.*]] = cir.get_member %[[S2]][0] {name = "a"}
-// CIR: %[[FOUR:.*]] = cir.const #cir.int<4>
-// CIR: cir.store{{.*}} %[[FOUR]], %[[S2_A]]
-// CIR: %[[S2_B:.*]] = cir.get_member %[[S2]][1] {name = "b"}
-// CIR: %[[FIVE:.*]] = cir.const #cir.int<5>
-// CIR: cir.store{{.*}} %[[FIVE]], %[[S2_B]]
-// CIR: %[[S2_C:.*]] = cir.get_member %[[S2]][2] {name = "c"}
-// CIR: %[[ZERO:.*]] = cir.const #cir.int<0>
-// CIR: cir.store{{.*}} %[[ZERO]], %[[S2_C]]
-// CIR: cir.return
+// CIR: %[[CONST_1:.*]] = cir.const #cir.const_record<{#cir.int<1> : !s32i, #cir.int<2> : !s32i, #cir.int<3> : !s32i}> : !rec_S
+// CIR: cir.store{{.*}} %[[CONST_1]], %[[S1]]
+// CIR: %[[CONST_2:.*]] = cir.const #cir.const_record<{#cir.int<4> : !s32i, #cir.int<5> : !s32i, #cir.int<0> : !s32i}> : !rec_S
+// CIR: cir.store{{.*}} %[[CONST_2]], %[[S2]]
// LLVM: define{{.*}} void @_Z4initv()
// LLVM: %[[S1:.*]] = alloca %struct.S
// LLVM: %[[S2:.*]] = alloca %struct.S
-// LLVM: %[[S1_A:.*]] = getelementptr %struct.S, ptr %[[S1]], i32 0, i32 0
-// LLVM: store i32 1, ptr %[[S1_A]]
-// LLVM: %[[S1_B:.*]] = getelementptr %struct.S, ptr %[[S1]], i32 0, i32 1
-// LLVM: store i32 2, ptr %[[S1_B]]
-// LLVM: %[[S1_C:.*]] = getelementptr %struct.S, ptr %[[S1]], i32 0, i32 2
-// LLVM: store i32 3, ptr %[[S1_C]]
-// LLVM: %[[S2_A:.*]] = getelementptr %struct.S, ptr %[[S2]], i32 0, i32 0
-// LLVM: store i32 4, ptr %[[S2_A]]
-// LLVM: %[[S2_B:.*]] = getelementptr %struct.S, ptr %[[S2]], i32 0, i32 1
-// LLVM: store i32 5, ptr %[[S2_B]]
-// LLVM: %[[S2_C:.*]] = getelementptr %struct.S, ptr %[[S2]], i32 0, i32 2
-// LLVM: store i32 0, ptr %[[S2_C]]
+// LLVM: store %struct.S { i32 1, i32 2, i32 3 }, ptr %[[S1]], align 4
+// LLVM: store %struct.S { i32 4, i32 5, i32 0 }, ptr %[[S2]], align 4
// OGCG: @__const._Z4initv.s1 = private unnamed_addr constant %struct.S { i32 1, i32 2, i32 3 }
// OGCG: @__const._Z4initv.s2 = private unnamed_addr constant %struct.S { i32 4, i32 5, i32 0 }
@@ -230,3 +205,26 @@ void init_expr(int a, int b, int c) {
// OGCG: %[[C_PLUS_THREE:.*]] = add nsw i32 %[[C]], 3
// OGCG: store i32 %[[C_PLUS_THREE]], ptr %[[S_C]]
// OGCG: ret void
+
+void cxx_default_init_with_struct_field() {
+ struct Parent {
+ int getA();
+ int a = getA();
+ };
+ Parent p = Parent{};
+}
+
+// CIR: %[[P_ADDR:.*]] = cir.alloca !rec_Parent, !cir.ptr<!rec_Parent>, ["p", init]
+// CIR: %[[P_ELEM_0_PTR:.*]] = cir.get_member %[[P_ADDR]][0] {name = "a"} : !cir.ptr<!rec_Parent> -> !cir.ptr<!s32i>
+// CIR: %[[METHOD_CALL:.*]] = cir.call @_ZZ34cxx_default_init_with_struct_fieldvEN6Parent4getAEv(%[[P_ADDR]]) : (!cir.ptr<!rec_Parent>) -> !s32i
+// CIR: cir.store{{.*}} %[[METHOD_CALL]], %[[P_ELEM_0_PTR]] : !s32i, !cir.ptr<!s32i>
+
+// LLVM: %[[P_ADDR:.*]] = alloca %struct.Parent, i64 1, align 4
+// LLVM: %[[P_ELEM_0_PTR:.*]] = getelementptr %struct.Parent, ptr %[[P_ADDR]], i32 0, i32 0
+// LLVM: %[[METHOD_CALL:.*]] = call i32 @_ZZ34cxx_default_init_with_struct_fieldvEN6Parent4getAEv(ptr %[[P_ADDR]])
+// LLVM: store i32 %[[METHOD_CALL]], ptr %[[P_ELEM_0_PTR]], align 4
+
+// OGCG: %[[P_ADDR:.*]] = alloca %struct.Parent, align 4
+// OGCG: %[[P_ELEM_0_PTR:.*]] = getelementptr inbounds nuw %struct.Parent, ptr %[[P_ADDR]], i32 0, i32 0
+// OGCG: %[[METHOD_CALL:.*]] = call noundef i32 @_ZZ34cxx_default_init_with_struct_fieldvEN6Parent4getAEv(ptr {{.*}} %[[P_ADDR]])
+// OGCG: store i32 %[[METHOD_CALL]], ptr %[[P_ELEM_0_PTR]], align 4
diff --git a/clang/test/CIR/CodeGen/struct.cpp b/clang/test/CIR/CodeGen/struct.cpp
index c8db714..dc3e241 100644
--- a/clang/test/CIR/CodeGen/struct.cpp
+++ b/clang/test/CIR/CodeGen/struct.cpp
@@ -107,22 +107,15 @@ void paren_expr() {
// CIR: cir.func{{.*}} @_Z10paren_exprv()
// CIR: %[[A_ADDR:.*]] = cir.alloca !rec_Point, !cir.ptr<!rec_Point>, ["a", init]
// CIR: %[[B_ADDR:.*]] = cir.alloca !rec_Point, !cir.ptr<!rec_Point>, ["b", init]
-// CIR: %[[X_ELEM_PTR:.*]] = cir.get_member %[[A_ADDR]][0] {name = "x"} : !cir.ptr<!rec_Point> -> !cir.ptr<!s32i>
-// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s32i
-// CIR: cir.store{{.*}} %[[CONST_0]], %[[X_ELEM_PTR]] : !s32i, !cir.ptr<!s32i>
-// CIR: %[[Y_ELEM_PTR:.*]] = cir.get_member %[[A_ADDR]][1] {name = "y"} : !cir.ptr<!rec_Point> -> !cir.ptr<!s32i>
-// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s32i
-// CIR: cir.store{{.*}} %[[CONST_0]], %[[Y_ELEM_PTR]] : !s32i, !cir.ptr<!s32i>
-// CIR: cir.call @_ZZ10paren_exprvEN5PointC1ERKS_(%[[B_ADDR]], %[[A_ADDR]]) nothrow : (!cir.ptr<!rec_Point>, !cir.ptr<!rec_Point>) -> ()
+// CIR: %[[CONST:.*]] = cir.const #cir.zero : !rec_Point
+// CIR: cir.store{{.*}} %[[CONST]], %[[A_ADDR]] : !rec_Point, !cir.ptr<!rec_Point>
+// CIR: cir.copy %[[A_ADDR]] to %[[B_ADDR]] : !cir.ptr<!rec_Point>
// LLVM: define{{.*}} void @_Z10paren_exprv()
// LLVM: %[[A_ADDR:.*]] = alloca %struct.Point, i64 1, align 4
// LLVM: %[[B_ADDR:.*]] = alloca %struct.Point, i64 1, align 4
-// LLVM: %[[X_ELEM_PTR:.*]] = getelementptr %struct.Point, ptr %[[A_ADDR]], i32 0, i32 0
-// LLVM: store i32 0, ptr %[[X_ELEM_PTR]], align 4
-// LLVM: %[[Y_ELEM_PTR:.*]] = getelementptr %struct.Point, ptr %[[A_ADDR]], i32 0, i32 1
-// LLVM: store i32 0, ptr %[[Y_ELEM_PTR]], align 4
-// LLVM: call void @_ZZ10paren_exprvEN5PointC1ERKS_(ptr %[[B_ADDR]], ptr %[[A_ADDR]])
+// LLVM: store %struct.Point zeroinitializer, ptr %[[A_ADDR]], align 4
+// LLVM: call void @llvm.memcpy.p0.p0.i32(ptr %[[B_ADDR]], ptr %[[A_ADDR]], i32 8, i1 false)
// OGCG: define{{.*}} void @_Z10paren_exprv()
// OGCG: %[[A_ADDR:.*]] = alloca %struct.Point, align 4
@@ -140,14 +133,13 @@ void choose_expr() {
// CIR: %[[A_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["a"]
// CIR: %[[B_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["b"]
// CIR: %[[C_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["c", init]
-// TODO(cir): Call to default copy constructor should be replaced by `cir.copy` op
-// CIR: cir.call @_ZN9CompleteSC1ERKS_(%[[C_ADDR]], %[[A_ADDR]]) nothrow : (!cir.ptr<!rec_CompleteS>, !cir.ptr<!rec_CompleteS>) -> ()
+// CIR: cir.copy %[[A_ADDR]] to %[[C_ADDR]] : !cir.ptr<!rec_CompleteS>
// LLVM: define{{.*}} void @_Z11choose_exprv()
// LLVM: %[[A_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 4
// LLVM: %[[B_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 4
// LLVM: %[[C_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 4
-// LLVM: call void @_ZN9CompleteSC1ERKS_(ptr %[[C_ADDR]], ptr %[[A_ADDR]])
+// LLVM: call void @llvm.memcpy.p0.p0.i32(ptr %[[C_ADDR]], ptr %[[A_ADDR]], i32 8, i1 false)
// OGCG: define{{.*}} void @_Z11choose_exprv()
// OGCG: %[[A_ADDR:.*]] = alloca %struct.CompleteS, align 4
@@ -167,15 +159,14 @@ void generic_selection() {
// CIR: %[[B_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["b"]
// CIR: %[[C_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["c"]
// CIR: %[[D_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["d", init]
-// TODO(cir): Call to default copy constructor should be replaced by `cir.copy` op
-// CIR: cir.call @_ZN9CompleteSC1ERKS_(%[[D_ADDR]], %[[A_ADDR]]) nothrow : (!cir.ptr<!rec_CompleteS>, !cir.ptr<!rec_CompleteS>) -> ()
+// CIR: cir.copy %[[A_ADDR]] to %[[D_ADDR]] : !cir.ptr<!rec_CompleteS>
// LLVM: define{{.*}} void @_Z17generic_selectionv()
// LLVM: %1 = alloca %struct.CompleteS, i64 1, align 4
// LLVM: %2 = alloca %struct.CompleteS, i64 1, align 4
// LLVM: %3 = alloca i32, i64 1, align 4
// LLVM: %4 = alloca %struct.CompleteS, i64 1, align 4
-// LLVM: call void @_ZN9CompleteSC1ERKS_(ptr %4, ptr %1)
+// LLVM: call void @llvm.memcpy.p0.p0.i32(ptr %4, ptr %1, i32 8, i1 false)
// OGCG: define{{.*}} void @_Z17generic_selectionv()
// OGCG: %[[A_ADDR:.*]] = alloca %struct.CompleteS, align 4
@@ -195,7 +186,7 @@ void designated_init_update_expr() {
// CIR: %[[A_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["a"]
// CIR: %[[B_ADDR:.*]] = cir.alloca !rec_Container, !cir.ptr<!rec_Container>, ["b", init]
// CIR: %[[C_ADDR:.*]] = cir.get_member %[[B_ADDR]][0] {name = "c"} : !cir.ptr<!rec_Container> -> !cir.ptr<!rec_CompleteS>
-// CIR: cir.call @_ZN9CompleteSC1ERKS_(%2, %[[A_ADDR]]) nothrow : (!cir.ptr<!rec_CompleteS>, !cir.ptr<!rec_CompleteS>) -> ()
+// CIR: cir.copy %[[A_ADDR]] to %[[C_ADDR]] : !cir.ptr<!rec_CompleteS>
// CIR: %[[ELEM_0_PTR:.*]] = cir.get_member %[[C_ADDR]][0] {name = "a"} : !cir.ptr<!rec_CompleteS> -> !cir.ptr<!s32i>
// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s32i
// CIR: cir.store{{.*}} %[[CONST_1]], %[[ELEM_0_PTR]] : !s32i, !cir.ptr<!s32i>
@@ -204,7 +195,7 @@ void designated_init_update_expr() {
// LLVM: %[[A_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 4
// LLVM: %[[B_ADDR:.*]] = alloca %struct.Container, i64 1, align 4
// LLVM: %[[C_ADDR:.*]] = getelementptr %struct.Container, ptr %[[B_ADDR]], i32 0, i32 0
-// LLVM: call void @_ZN9CompleteSC1ERKS_(ptr %[[C_ADDR]], ptr %[[A_ADDR]])
+// LLVM: call void @llvm.memcpy.p0.p0.i32(ptr %[[C_ADDR]], ptr %[[A_ADDR]], i32 8, i1 false)
// LLVM: %[[ELEM_0_PTR:.*]] = getelementptr %struct.CompleteS, ptr %[[C_ADDR]], i32 0, i32 0
// LLVM: store i32 1, ptr %[[ELEM_0_PTR]], align 4
// LLVM: %[[ELEM_1_PTR:.*]] = getelementptr %struct.CompleteS, ptr %[[C_ADDR]], i32 0, i32 1
@@ -265,16 +256,11 @@ void bin_comma() {
// CIR: cir.func{{.*}} @_Z9bin_commav()
// CIR: %[[A_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["a", init]
-// CIR: %[[TMP_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["agg.tmp.ensured"]
-// CIR: %[[ZERO:.*]] = cir.const #cir.zero : !rec_CompleteS
-// CIR: cir.store{{.*}} %[[ZERO]], %[[TMP_ADDR]] : !rec_CompleteS, !cir.ptr<!rec_CompleteS>
-// CIR: %[[ZERO:.*]] = cir.const #cir.zero : !rec_CompleteS
-// CIR: cir.store{{.*}} %[[ZERO]], %[[A_ADDR]] : !rec_CompleteS, !cir.ptr<!rec_CompleteS>
+// CIR: %[[CONST:.*]] = cir.const #cir.zero : !rec_CompleteS
+// CIR: cir.store{{.*}} %[[CONST]], %[[A_ADDR]] : !rec_CompleteS, !cir.ptr<!rec_CompleteS>
// LLVM: define{{.*}} void @_Z9bin_commav()
// LLVM: %[[A_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 4
-// LLVM: %[[TMP_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 4
-// LLVM: store %struct.CompleteS zeroinitializer, ptr %[[TMP_ADDR]], align 4
// LLVM: store %struct.CompleteS zeroinitializer, ptr %[[A_ADDR]], align 4
// OGCG: define{{.*}} void @_Z9bin_commav()
@@ -284,20 +270,13 @@ void bin_comma() {
void compound_literal_expr() { CompleteS a = (CompleteS){}; }
// CIR: %[[A_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["a", init]
-// CIR: %[[A_ELEM_0_PTR:.*]] = cir.get_member %[[A_ADDR]][0] {name = "a"} : !cir.ptr<!rec_CompleteS> -> !cir.ptr<!s32i>
-// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s32i
-// CIR: cir.store{{.*}} %[[CONST_0]], %[[A_ELEM_0_PTR]] : !s32i, !cir.ptr<!s32i>
-// CIR: %[[A_ELEM_1_PTR:.*]] = cir.get_member %[[A_ADDR]][1] {name = "b"} : !cir.ptr<!rec_CompleteS> -> !cir.ptr<!s8i>
-// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s8i
-// CIR: cir.store{{.*}} %[[CONST_0]], %[[A_ELEM_1_PTR]] : !s8i, !cir.ptr<!s8i>
+// CIR: %[[CONST:.*]] = cir.const #cir.zero : !rec_CompleteS
+// CIR: cir.store{{.*}} %[[CONST]], %[[A_ADDR]] : !rec_CompleteS, !cir.ptr<!rec_CompleteS>
// TODO(cir): zero-initialize the padding
// LLVM: %[[A_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 4
-// LLVM: %[[A_ELEM_0_PTR:.*]] = getelementptr %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 0
-// LLVM: store i32 0, ptr %[[A_ELEM_0_PTR]], align 4
-// LLVM: %[[A_ELEM_1_PTR:.*]] = getelementptr %struct.CompleteS, ptr %[[A_ADDR]], i32 0, i32 1
-// LLVM: store i8 0, ptr %[[A_ELEM_1_PTR]], align 4
+// LLVM: store %struct.CompleteS zeroinitializer, ptr %[[A_ADDR]], align 4
// OGCG: %[[A_ADDR:.*]] = alloca %struct.CompleteS, align 4
// OGCG: call void @llvm.memset.p0.i64(ptr align 4 %[[A_ADDR]], i8 0, i64 8, i1 false)
@@ -344,3 +323,47 @@ void struct_with_const_member_expr() {
// OGCG: %[[BF_SET:.*]] = or i8 %[[BF_CLEAR]], 0
// OGCG: store i8 %[[BF_SET]], ptr %[[REF_ADDR]], align 4
// OGCG: store i32 0, ptr %[[A_ADDR]], align 4
+
+void function_arg_with_default_value(CompleteS a = {1, 2}) {}
+
+// CIR: %[[ARG_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["a", init]
+// CIR: cir.store %{{.*}}, %[[ARG_ADDR]] : !rec_CompleteS, !cir.ptr<!rec_CompleteS>
+
+// LLVM: %[[ARG_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 4
+// LLVM: store %struct.CompleteS %{{.*}}, ptr %[[ARG_ADDR]], align 4
+
+// OGCG: %[[ARG_ADDR:.*]] = alloca %struct.CompleteS, align 4
+// OGCG: store i64 %{{.*}}, ptr %[[ARG_ADDR]], align 4
+
+void calling_function_with_default_values() {
+ function_arg_with_default_value();
+}
+
+// CIR: %[[AGG_ADDR:.*]] = cir.alloca !rec_CompleteS, !cir.ptr<!rec_CompleteS>, ["agg.tmp0"]
+// CIR: %[[ELEM_0_PTR:.*]] = cir.get_member %[[AGG_ADDR]][0] {name = "a"} : !cir.ptr<!rec_CompleteS> -> !cir.ptr<!s32i>
+// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s32i
+// CIR: cir.store{{.*}} %[[CONST_1]], %[[ELEM_0_PTR]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[ELEM_1_PTR:.*]] = cir.get_member %[[AGG_ADDR]][1] {name = "b"} : !cir.ptr<!rec_CompleteS> -> !cir.ptr<!s8i>
+// CIR: %[[CONST_2:.*]] = cir.const #cir.int<2> : !s32i
+// CIR: %[[CONST_2_I8:.*]] = cir.cast integral %[[CONST_2]] : !s32i -> !s8i
+// CIR: cir.store{{.*}} %[[CONST_2_I8]], %[[ELEM_1_PTR]] : !s8i, !cir.ptr<!s8i>
+// CIR: %[[TMP_AGG:.*]] = cir.load{{.*}} %[[AGG_ADDR]] : !cir.ptr<!rec_CompleteS>, !rec_CompleteS
+// CIR: cir.call @_Z31function_arg_with_default_value9CompleteS(%[[TMP_AGG]]) : (!rec_CompleteS) -> ()
+
+// TODO(CIR): the difference between the CIR LLVM and OGCG is because the lack of calling convention lowering,
+
+// LLVM: %[[AGG_ADDR:.*]] = alloca %struct.CompleteS, i64 1, align 4
+// LLVM: %[[ELEM_0_PTR:.*]] = getelementptr %struct.CompleteS, ptr %[[AGG_ADDR]], i32 0, i32 0
+// LLVM: store i32 1, ptr %[[ELEM_0_PTR]], align 4
+// LLVM: %[[ELEM_1_PTR:.*]] = getelementptr %struct.CompleteS, ptr %[[AGG_ADDR]], i32 0, i32 1
+// LLVM: store i8 2, ptr %[[ELEM_1_PTR]], align 4
+// LLVM: %[[TMP_AGG:.*]] = load %struct.CompleteS, ptr %[[AGG_ADDR]], align 4
+// LLVM: call void @_Z31function_arg_with_default_value9CompleteS(%struct.CompleteS %[[TMP_AGG]])
+
+// OGCG: %[[AGG_ADDR:.*]] = alloca %struct.CompleteS, align 4
+// OGCG: %[[ELEM_0_PTR:.*]] = getelementptr inbounds nuw %struct.CompleteS, ptr %[[AGG_ADDR]], i32 0, i32 0
+// OGCG: store i32 1, ptr %[[ELEM_0_PTR]], align 4
+// OGCG: %[[ELEM_1_PTR:.*]] = getelementptr inbounds nuw %struct.CompleteS, ptr %[[AGG_ADDR]], i32 0, i32 1
+// OGCG: store i8 2, ptr %[[ELEM_1_PTR]], align 4
+// OGCG: %[[TMP_AGG:.*]] = load i64, ptr %[[AGG_ADDR]], align 4
+// OGCG: call void @_Z31function_arg_with_default_value9CompleteS(i64 %[[TMP_AGG]])
diff --git a/clang/test/CIR/CodeGen/switch.cpp b/clang/test/CIR/CodeGen/switch.cpp
index e13aa8f..3824be0 100644
--- a/clang/test/CIR/CodeGen/switch.cpp
+++ b/clang/test/CIR/CodeGen/switch.cpp
@@ -1183,3 +1183,90 @@ int nested_switch(int a) {
// OGCG: [[IFEND10]]:
// OGCG: br label %[[EPILOG]]
// OGCG: [[EPILOG]]:
+
+int sw_return_multi_cases(int x) {
+ switch (x) {
+ case 0:
+ return 0;
+ case 1:
+ return 1;
+ case 2:
+ return 2;
+ default:
+ return -1;
+ }
+}
+
+// CIR-LABEL: cir.func{{.*}} @_Z21sw_return_multi_casesi
+// CIR: cir.switch (%{{.*}} : !s32i) {
+// CIR-NEXT: cir.case(equal, [#cir.int<0> : !s32i]) {
+// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
+// CIR: cir.store{{.*}} %[[ZERO]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[RET0:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s32i>, !s32i
+// CIR-NEXT: cir.return %[[RET0]] : !s32i
+// CIR-NEXT: }
+// CIR-NEXT: cir.case(equal, [#cir.int<1> : !s32i]) {
+// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
+// CIR: cir.store{{.*}} %[[ONE]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[RET1:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s32i>, !s32i
+// CIR-NEXT: cir.return %[[RET1]] : !s32i
+// CIR-NEXT: }
+// CIR-NEXT: cir.case(equal, [#cir.int<2> : !s32i]) {
+// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s32i
+// CIR: cir.store{{.*}} %[[TWO]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[RET2:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s32i>, !s32i
+// CIR-NEXT: cir.return %[[RET2]] : !s32i
+// CIR-NEXT: }
+// CIR-NEXT: cir.case(default, []) {
+// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
+// CIR: %[[NEG:.*]] = cir.unary(minus, %[[ONE]]) {{.*}} : !s32i, !s32i
+// CIR: cir.store{{.*}} %[[NEG]], %{{.*}} : !s32i, !cir.ptr<!s32i>
+// CIR: %[[RETDEF:.*]] = cir.load{{.*}} %{{.*}} : !cir.ptr<!s32i>, !s32i
+// CIR-NEXT: cir.return %[[RETDEF]] : !s32i
+// CIR-NEXT: }
+// CIR-NEXT: cir.yield
+
+// LLVM-LABEL: define{{.*}} i32 @_Z21sw_return_multi_casesi
+// LLVM: switch i32 %{{.*}}, label %[[DEFAULT:.*]] [
+// LLVM-DAG: i32 0, label %[[CASE0:.*]]
+// LLVM-DAG: i32 1, label %[[CASE1:.*]]
+// LLVM-DAG: i32 2, label %[[CASE2:.*]]
+// LLVM: ]
+// LLVM: [[CASE0]]:
+// LLVM: store i32 0, ptr %{{.*}}, align 4
+// LLVM: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// LLVM: ret i32 %{{.*}}
+// LLVM: [[CASE1]]:
+// LLVM: store i32 1, ptr %{{.*}}, align 4
+// LLVM: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// LLVM: ret i32 %{{.*}}
+// LLVM: [[CASE2]]:
+// LLVM: store i32 2, ptr %{{.*}}, align 4
+// LLVM: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// LLVM: ret i32 %{{.*}}
+// LLVM: [[DEFAULT]]:
+// LLVM: store i32 -1, ptr %{{.*}}, align 4
+// LLVM: %{{.*}} = load i32, ptr %{{.*}}, align 4
+// LLVM: ret i32 %{{.*}}
+
+// OGCG-LABEL: define{{.*}} i32 @_Z21sw_return_multi_casesi
+// OGCG: entry:
+// OGCG: %[[RETVAL:.*]] = alloca i32, align 4
+// OGCG: %[[X_ADDR:.*]] = alloca i32, align 4
+// OGCG: %[[X_VAL:.*]] = load i32, ptr %[[X_ADDR]], align 4
+// OGCG: switch i32 %[[X_VAL]], label %[[DEFAULT:.*]] [
+// OGCG-DAG: i32 0, label %[[SW0:.*]]
+// OGCG-DAG: i32 1, label %[[SW1:.*]]
+// OGCG-DAG: i32 2, label %[[SW2:.*]]
+// OGCG: ]
+// OGCG: [[SW0]]:
+// OGCG: br label %[[RETURN:.*]]
+// OGCG: [[SW1]]:
+// OGCG: br label %[[RETURN]]
+// OGCG: [[SW2]]:
+// OGCG: br label %[[RETURN]]
+// OGCG: [[DEFAULT]]:
+// OGCG: br label %[[RETURN]]
+// OGCG: [[RETURN]]:
+// OGCG: %[[RETVAL_LOAD:.*]] = load i32, ptr %[[RETVAL]], align 4
+// OGCG: ret i32 %[[RETVAL_LOAD]]
diff --git a/clang/test/CIR/CodeGen/temporary-materialization.cpp b/clang/test/CIR/CodeGen/temporary-materialization.cpp
new file mode 100644
index 0000000..b936ddf
--- /dev/null
+++ b/clang/test/CIR/CodeGen/temporary-materialization.cpp
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -std=c++17 -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++17 -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++17 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG
+
+int make_int();
+
+int test() {
+ const int &x = make_int();
+ return x;
+}
+
+// CIR: cir.func {{.*}} @_Z4testv()
+// CIR: %[[TEMP_SLOT:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["ref.tmp0", init]
+// CIR-NEXT: %[[X:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["x", init, const]
+// CIR-NEXT: %[[TEMP_VALUE:.*]] = cir.call @_Z8make_intv() : () -> !s32i
+// CIR-NEXT: cir.store{{.*}} %[[TEMP_VALUE]], %[[TEMP_SLOT]]
+// CIR-NEXT: cir.store{{.*}} %[[TEMP_SLOT]], %[[X]]
+
+// LLVM: define {{.*}} i32 @_Z4testv()
+// LLVM: %[[RETVAL:.*]] = alloca i32
+// LLVM: %[[TEMP_SLOT:.*]] = alloca i32
+// LLVM: %[[X:.*]] = alloca ptr
+// LLVM: %[[TEMP_VALUE:.*]] = call i32 @_Z8make_intv()
+// LLVM: store i32 %[[TEMP_VALUE]], ptr %[[TEMP_SLOT]]
+// LLVM: store ptr %[[TEMP_SLOT]], ptr %[[X]]
+
+// OGCG: define {{.*}} i32 @_Z4testv()
+// OGCG: %[[X:.*]] = alloca ptr
+// OGCG: %[[TEMP_SLOT:.*]] = alloca i32
+// OGCG: %[[TEMP_VALUE:.*]] = call noundef i32 @_Z8make_intv()
+// OGCG: store i32 %[[TEMP_VALUE]], ptr %[[TEMP_SLOT]]
+// OGCG: store ptr %[[TEMP_SLOT]], ptr %[[X]]
+
+int test_scoped() {
+ int x = make_int();
+ {
+ const int &y = make_int();
+ x = y;
+ }
+ return x;
+}
+
+// CIR: cir.func {{.*}} @_Z11test_scopedv()
+// CIR: %[[X:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init]
+// CIR: cir.scope {
+// CIR-NEXT: %[[TEMP_SLOT:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["ref.tmp0", init]
+// CIR-NEXT: %[[Y_ADDR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["y", init, const]
+// CIR-NEXT: %[[TEMP_VALUE:.*]] = cir.call @_Z8make_intv() : () -> !s32i
+// CIR-NEXT: cir.store{{.*}} %[[TEMP_VALUE]], %[[TEMP_SLOT]] : !s32i, !cir.ptr<!s32i>
+// CIR-NEXT: cir.store{{.*}} %[[TEMP_SLOT]], %[[Y_ADDR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
+// CIR-NEXT: %[[Y_REF:.*]] = cir.load %[[Y_ADDR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
+// CIR-NEXT: %[[Y_VALUE:.*]] = cir.load{{.*}} %[[Y_REF]] : !cir.ptr<!s32i>, !s32i
+// CIR-NEXT: cir.store{{.*}} %[[Y_VALUE]], %[[X]] : !s32i, !cir.ptr<!s32i>
+// CIR-NEXT: }
+
+// LLVM: define {{.*}} i32 @_Z11test_scopedv()
+// LLVM: %[[TEMP_SLOT:.*]] = alloca i32
+// LLVM: %[[Y_ADDR:.*]] = alloca ptr
+// LLVM: %[[RETVAL:.*]] = alloca i32
+// LLVM: %[[X:.*]] = alloca i32
+// LLVM: %[[TEMP_VALUE1:.*]] = call i32 @_Z8make_intv()
+// LLVM: store i32 %[[TEMP_VALUE1]], ptr %[[X]]
+// LLVM: br label %[[SCOPE_LABEL:.*]]
+// LLVM: [[SCOPE_LABEL]]:
+// LLVM: %[[TEMP_VALUE2:.*]] = call i32 @_Z8make_intv()
+// LLVM: store i32 %[[TEMP_VALUE2]], ptr %[[TEMP_SLOT]]
+// LLVM: store ptr %[[TEMP_SLOT]], ptr %[[Y_ADDR]]
+// LLVM: %[[Y_REF:.*]] = load ptr, ptr %[[Y_ADDR]]
+// LLVM: %[[Y_VALUE:.*]] = load i32, ptr %[[Y_REF]]
+// LLVM: store i32 %[[Y_VALUE]], ptr %[[X]]
+
+// OGCG: define {{.*}} i32 @_Z11test_scopedv()
+// OGCG: %[[X:.*]] = alloca i32
+// OGCG: %[[Y_ADDR:.*]] = alloca ptr
+// OGCG: %[[TEMP_SLOT:.*]] = alloca i32
+// OGCG: %[[TEMP_VALUE1:.*]] = call noundef i32 @_Z8make_intv()
+// OGCG: store i32 %[[TEMP_VALUE1]], ptr %[[X]]
+// OGCG: %[[TEMP_VALUE2:.*]] = call noundef i32 @_Z8make_intv()
+// OGCG: store i32 %[[TEMP_VALUE2]], ptr %[[TEMP_SLOT]]
+// OGCG: store ptr %[[TEMP_SLOT]], ptr %[[Y_ADDR]]
+// OGCG: %[[Y_REF:.*]] = load ptr, ptr %[[Y_ADDR]]
+// OGCG: %[[Y_VALUE:.*]] = load i32, ptr %[[Y_REF]]
+// OGCG: store i32 %[[Y_VALUE]], ptr %[[X]]
diff --git a/clang/test/CIR/CodeGen/ternary-throw.cpp b/clang/test/CIR/CodeGen/ternary-throw.cpp
index fb8897f..74168c1 100644
--- a/clang/test/CIR/CodeGen/ternary-throw.cpp
+++ b/clang/test/CIR/CodeGen/ternary-throw.cpp
@@ -195,3 +195,46 @@ const int& test_cond_const_false_throw_true() {
// OGCG-NOT: __cxa_throw
// OGCG: ret ptr %[[A]]
+const int &test_cond_const_true_throw_true() {
+ const int a = 30;
+ return true ? throw 0 : a;
+}
+
+// CIR-LABEL: cir.func{{.*}} @_Z31test_cond_const_true_throw_truev(
+// CIR: %[[RET_ADDR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["__retval"]
+// CIR: %[[A_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init, const]
+// CIR: %[[CONST_30:.*]] = cir.const #cir.int<30> : !s32i
+// CIR: cir.store{{.*}} %[[CONST_30]], %[[A_ADDR]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[EXCEPTION:.*]] = cir.alloc.exception 4 -> !cir.ptr<!s32i>
+// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s32i
+// CIR: cir.store{{.*}} %[[CONST_0]], %[[EXCEPTION]] : !s32i, !cir.ptr<!s32i>
+// CIR: cir.throw %[[EXCEPTION]] : !cir.ptr<!s32i>, @_ZTIi
+// CIR: cir.unreachable
+// CIR: ^[[NO_PRED_LABEL:.*]]:
+// CIR: %[[CONST_NULL:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!s32i>
+// CIR: cir.store %[[CONST_NULL]], %[[RET_ADDR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
+// CIR: %[[TMP_RET:.*]] = cir.load %[[RET_ADDR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
+// CIR: cir.return %[[TMP_RET]] : !cir.ptr<!s32i>
+
+// LLVM-LABEL: define{{.*}} ptr @_Z31test_cond_const_true_throw_truev(
+// LLVM: %[[RET_ADDR:.*]] = alloca ptr, i64 1, align 8
+// LLVM: %[[A_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: store i32 30, ptr %[[A_ADDR]], align 4
+// LLVM: %[[EXCEPTION:.*]] = call ptr @__cxa_allocate_exception(i64 4)
+// LLVM: store i32 0, ptr %[[EXCEPTION]], align 16
+// LLVM: call void @__cxa_throw(ptr %[[EXCEPTION]], ptr @_ZTIi, ptr null)
+// LLVM: unreachable
+// LLVM: [[NO_PRED_LABEL:.*]]:
+// LLVM: store ptr null, ptr %[[RET_ADDR]], align 8
+// LLVM: %[[TMP_RET:.*]] = load ptr, ptr %[[RET_ADDR]], align 8
+// LLVM: ret ptr %[[TMP_RET]]
+
+// OGCG-LABEL: define{{.*}} ptr @_Z31test_cond_const_true_throw_truev(
+// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4
+// OGCG: store i32 30, ptr %[[A_ADDR]], align 4
+// OGCG: %[[EXCEPTION:.*]] = call ptr @__cxa_allocate_exception(i64 4)
+// OGCG: store i32 0, ptr %[[EXCEPTION]], align 16
+// OGCG: call void @__cxa_throw(ptr %[[EXCEPTION]], ptr @_ZTIi, ptr null)
+// OGCG: unreachable
+// OGCG: [[NO_PRED_LABEL:.*]]:
+// OGCG: ret ptr [[UNDEF:.*]]
diff --git a/clang/test/CIR/CodeGen/tls.c b/clang/test/CIR/CodeGen/tls.c
new file mode 100644
index 0000000..582a716
--- /dev/null
+++ b/clang/test/CIR/CodeGen/tls.c
@@ -0,0 +1,29 @@
+// 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.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ogcg.ll
+// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ogcg.ll %s
+
+extern __thread int b;
+// CIR: cir.global "private" external tls_dyn @b : !s32i
+
+__thread int a;
+// CIR: cir.global external tls_dyn @a = #cir.int<0> : !s32i
+
+int c(void) { return *&b; }
+// CIR: cir.func no_inline dso_local @c() -> !s32i
+// CIR: %[[TLS_ADDR:.*]] = cir.get_global thread_local @b : !cir.ptr<!s32i>
+
+// LLVM: @b = external thread_local global i32
+// LLVM: @a = thread_local global i32 0
+
+// LLVM-LABEL: @c
+// LLVM: = call ptr @llvm.threadlocal.address.p0(ptr @b)
+
+// OGCG: @b = external thread_local{{.*}} global i32
+// OGCG: @a = thread_local{{.*}} global i32 0
+
+// OGCG-LABEL: define{{.*}} @c
+// OGCG: call{{.*}} ptr @llvm.threadlocal.address.p0(ptr{{.*}} @b)
+
diff --git a/clang/test/CIR/CodeGen/try-catch-tmp.cpp b/clang/test/CIR/CodeGen/try-catch-tmp.cpp
new file mode 100644
index 0000000..078447f
--- /dev/null
+++ b/clang/test/CIR/CodeGen/try-catch-tmp.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fcxx-exceptions -fexceptions -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 -fcxx-exceptions -fexceptions -emit-llvm %s -o %t.ll
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
+
+int division();
+
+void calling_division_inside_try_block() {
+ try {
+ division();
+ } catch (...) {
+ }
+}
+
+// CIR: cir.scope {
+// CIR: cir.try {
+// CIR: %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> !s32i
+// CIR: cir.yield
+// CIR: } catch all {
+// CIR: cir.yield
+// CIR: }
+// CIR: }
+
+// OGCG: %[[EXN_OBJ_ADDR:.*]] = alloca ptr, align 8
+// OGCG: %[[EH_SELECTOR_ADDR:.*]] = alloca i32, align 4
+// OGCG: %[[CALL:.*]] = invoke noundef i32 @_Z8divisionv()
+// OGCG: to label %[[INVOKE_CONT:.*]] unwind label %[[LANDING_PAD:.*]]
+// OGCG: [[INVOKE_CONT]]:
+// OGCG: br label %[[TRY_CONT:.*]]
+// OGCG: [[LANDING_PAD]]:
+// OGCG: %[[LP:.*]] = landingpad { ptr, i32 }
+// OGCG: catch ptr null
+// OGCG: %[[EXN_OBJ:.*]] = extractvalue { ptr, i32 } %[[LP]], 0
+// OGCG: store ptr %[[EXN_OBJ]], ptr %[[EXN_OBJ_ADDR]], align 8
+// OGCG: %[[EH_SELECTOR_VAL:.*]] = extractvalue { ptr, i32 } %[[LP]], 1
+// OGCG: store i32 %[[EH_SELECTOR_VAL]], ptr %[[EH_SELECTOR_ADDR]], align 4
+// OGCG: br label %[[CATCH:.*]]
+// OGCG: [[CATCH]]:
+// OGCG: %[[EXN_OBJ:.*]] = load ptr, ptr %[[EXN_OBJ_ADDR]], align 8
+// OGCG: %[[CATCH_BEGIN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ]])
+// OGCG: call void @__cxa_end_catch()
+// OGCG: br label %[[TRY_CONT]]
+// OGCG: [[TRY_CONT]]:
+// OGCG: ret void
diff --git a/clang/test/CIR/CodeGen/var_arg.c b/clang/test/CIR/CodeGen/var_arg.c
index f5b92c6..aab909e 100644
--- a/clang/test/CIR/CodeGen/var_arg.c
+++ b/clang/test/CIR/CodeGen/var_arg.c
@@ -17,7 +17,7 @@ int varargs(int count, ...) {
return res;
}
-// CIR-LABEL: cir.func dso_local @varargs(
+// CIR-LABEL: cir.func {{.*}} @varargs(
// CIR: %[[COUNT_ADDR:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["count", init]
// CIR: %[[RET_ADDR:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
// CIR: %[[VAAREA:.+]] = cir.alloca !cir.array<!rec___va_list_tag x 1>, !cir.ptr<!cir.array<!rec___va_list_tag x 1>>, ["args"]
@@ -93,7 +93,7 @@ int stdarg_start(int count, ...) {
return res;
}
-// CIR-LABEL: cir.func dso_local @stdarg_start(
+// CIR-LABEL: cir.func {{.*}} @stdarg_start(
// CIR: %[[COUNT_ADDR:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["count", init]
// CIR: %[[RET_ADDR:.+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
// CIR: %[[VAAREA:.+]] = cir.alloca !cir.array<!rec___va_list_tag x 1>, !cir.ptr<!cir.array<!rec___va_list_tag x 1>>, ["args"]
@@ -141,7 +141,7 @@ int stdarg_start(int count, ...) {
// OGCG: %[[COND:.+]] = icmp ule i32 %[[GPOFFSET]], 40
// OGCG: br i1 %[[COND]], label %vaarg.in_reg, label %vaarg.in_mem
//
-// OGCG: vaarg.in_reg:
+// OGCG: vaarg.in_reg:
// OGCG: %[[REGSAVE_PTR:.+]] = getelementptr inbounds nuw %struct.__va_list_tag, ptr %[[DECAY1]], i32 0, i32 3
// OGCG: %[[REGSAVE:.+]] = load ptr, ptr %[[REGSAVE_PTR]]
// OGCG: %[[VAADDR1:.+]] = getelementptr i8, ptr %[[REGSAVE]], i32 %[[GPOFFSET]]
@@ -164,3 +164,23 @@ int stdarg_start(int count, ...) {
// OGCG: call void @llvm.va_end.p0(ptr %[[DECAY2]])
// OGCG: %[[VAL:.+]] = load i32, ptr %[[RES_ADDR]]
// OGCG: ret i32 %[[VAL]]
+
+void stdarg_copy() {
+ __builtin_va_list src, dest;
+ __builtin_va_copy(src, dest);
+}
+
+// CIR-LABEL: @stdarg_copy
+// CIR: %{{.*}} = cir.cast array_to_ptrdecay %{{.*}} : !cir.ptr<!cir.array<!rec___va_list_tag x 1>> -> !cir.ptr<!rec___va_list_tag>
+// CIR: %{{.*}} = cir.cast array_to_ptrdecay %{{.*}} : !cir.ptr<!cir.array<!rec___va_list_tag x 1>> -> !cir.ptr<!rec___va_list_tag>
+// CIR: cir.va_copy %{{.*}} to %{{.*}} : !cir.ptr<!rec___va_list_tag>, !cir.ptr<!rec___va_list_tag>
+
+// LLVM-LABEL: @stdarg_copy
+// LLVM: %{{.*}} = getelementptr %struct.__va_list_tag, ptr %{{.*}}
+// LLVM: %{{.*}} = getelementptr %struct.__va_list_tag, ptr %{{.*}}
+// LLVM: call void @llvm.va_copy.p0(ptr %{{.*}}, ptr %{{.*}}
+
+// OGCG-LABEL: @stdarg_copy
+// OGCG: %{{.*}} = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %{{.*}}
+// OGCG: %{{.*}} = getelementptr inbounds [1 x %struct.__va_list_tag], ptr %{{.*}}
+// OGCG: call void @llvm.va_copy.p0(ptr %{{.*}}, ptr %{{.*}}
diff --git a/clang/test/CIR/CodeGen/variable-decomposition.cpp b/clang/test/CIR/CodeGen/variable-decomposition.cpp
index ba59109..3ba2fac 100644
--- a/clang/test/CIR/CodeGen/variable-decomposition.cpp
+++ b/clang/test/CIR/CodeGen/variable-decomposition.cpp
@@ -16,15 +16,11 @@ float function() {
return a + b;
}
-// CIR-LABEL: cir.func dso_local @_Z8functionv() -> !cir.float
+// CIR-LABEL: cir.func {{.*}} @_Z8functionv() -> !cir.float
// CIR: %[[RETVAL:.+]] = cir.alloca !cir.float, !cir.ptr<!cir.float>, ["__retval"]
// CIR: %[[STRUCT:.+]] = cir.alloca !rec_some_struct, !cir.ptr<!rec_some_struct>, ["", init]
-// CIR: %[[MEMBER_A:.+]] = cir.get_member %[[STRUCT]][0] {name = "a"} : !cir.ptr<!rec_some_struct> -> !cir.ptr<!s32i>
-// CIR: %[[CONST_1:.+]] = cir.const #cir.int<1> : !s32i
-// CIR: cir.store{{.*}} %[[CONST_1]], %[[MEMBER_A]]
-// CIR: %[[MEMBER_B:.+]] = cir.get_member %[[STRUCT]][1] {name = "b"} : !cir.ptr<!rec_some_struct> -> !cir.ptr<!cir.float>
-// CIR: %[[TWO_FP:.+]] = cir.const #cir.fp<2.000000e+00> : !cir.float
-// CIR: cir.store{{.*}} %[[TWO_FP]], %[[MEMBER_B]]
+// CIR: %[[CONST:.+]] = cir.const #cir.const_record<{#cir.int<1> : !s32i, #cir.fp<2.000000e+00> : !cir.float}> : !rec_some_struct
+// CIR: cir.store{{.*}} %[[CONST]], %[[STRUCT]]
// CIR: %[[MEMBER_A:.+]] = cir.get_member %[[STRUCT]][0] {name = "a"} : !cir.ptr<!rec_some_struct> -> !cir.ptr<!s32i>
// CIR: %[[LOAD_A:.+]] = cir.load align(4) %[[MEMBER_A]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[CAST_A:.+]] = cir.cast int_to_float %[[LOAD_A]] : !s32i -> !cir.float
@@ -38,10 +34,7 @@ float function() {
// LLVM-LABEL: define dso_local float @_Z8functionv()
// LLVM: %[[RETVAL:.+]] = alloca float, i64 1
// LLVM: %[[STRUCT:.+]] = alloca %struct.some_struct, i64 1
-// LLVM: %[[GEP_A:.+]] = getelementptr %struct.some_struct, ptr %[[STRUCT]], i32 0, i32 0
-// LLVM: store i32 1, ptr %[[GEP_A]]
-// LLVM: %[[GEP_B:.+]] = getelementptr %struct.some_struct, ptr %[[STRUCT]], i32 0, i32 1
-// LLVM: store float 2.000000e+00, ptr %[[GEP_B]]
+// LLVM: store %struct.some_struct { i32 1, float 2.000000e+00 }, ptr %[[STRUCT]]
// LLVM: %[[GEP_A:.+]] = getelementptr %struct.some_struct, ptr %[[STRUCT]], i32 0, i32 0
// LLVM: %[[LOAD_A:.+]] = load i32, ptr %[[GEP_A]]
// LLVM: %[[CAST_A:.+]] = sitofp i32 %[[LOAD_A]] to float
diff --git a/clang/test/CIR/CodeGen/vbase.cpp b/clang/test/CIR/CodeGen/vbase.cpp
index 8fcb2a4..c1f3972 100644
--- a/clang/test/CIR/CodeGen/vbase.cpp
+++ b/clang/test/CIR/CodeGen/vbase.cpp
@@ -128,7 +128,7 @@ void ppp() { B b; }
// OGCG: ret void
// Constructor for B
-// CIR: cir.func comdat linkonce_odr @_ZN1BC1Ev(%arg0: !cir.ptr<!rec_B>
+// CIR: cir.func {{.*}} @_ZN1BC1Ev(%arg0: !cir.ptr<!rec_B>
// CIR: %[[THIS_ADDR:.*]] = cir.alloca !cir.ptr<!rec_B>, !cir.ptr<!cir.ptr<!rec_B>>, ["this", init]
// CIR: cir.store %arg0, %[[THIS_ADDR]] : !cir.ptr<!rec_B>, !cir.ptr<!cir.ptr<!rec_B>>
// CIR: %[[THIS:.*]] = cir.load %[[THIS_ADDR]] : !cir.ptr<!cir.ptr<!rec_B>>, !cir.ptr<!rec_B>
diff --git a/clang/test/CIR/CodeGen/vector-ext-element.cpp b/clang/test/CIR/CodeGen/vector-ext-element.cpp
new file mode 100644
index 0000000..77ca3b4
--- /dev/null
+++ b/clang/test/CIR/CodeGen/vector-ext-element.cpp
@@ -0,0 +1,341 @@
+// 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
+
+typedef int vi2 __attribute__((ext_vector_type(2)));
+typedef int vi4 __attribute__((ext_vector_type(4)));
+
+void element_expr_from_gl() {
+ vi4 a;
+ int x = a.x;
+ int y = a.y;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a"]
+// CIR: %[[X_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init]
+// CIR: %[[Y_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["y", init]
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
+// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s64i
+// CIR: %[[ELEM_0:.*]] = cir.vec.extract %[[TMP_A]][%[[CONST_0]] : !s64i] : !cir.vector<4 x !s32i>
+// CIR: cir.store {{.*}} %[[ELEM_0]], %[[X_ADDR]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
+// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s64i
+// CIR: %[[ELEM_1:.*]] = cir.vec.extract %[[TMP_A]][%[[CONST_1]] : !s64i] : !cir.vector<4 x !s32i>
+// CIR: cir.store {{.*}} %[[ELEM_1]], %[[Y_ADDR]] : !s32i, !cir.ptr<!s32i>
+
+// LLVM: %[[A_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[X_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: %[[Y_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
+// LLVM: %[[ELEM_0:.*]] = extractelement <4 x i32> %4, i64 0
+// LLVM: store i32 %[[ELEM_0]], ptr %[[X_ADDR]], align 4
+// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
+// LLVM: %[[ELEM_1:.*]] = extractelement <4 x i32> %6, i64 1
+// LLVM: store i32 %[[ELEM_1]], ptr %[[Y_ADDR]], align 4
+
+// OGCG: %[[A_ADDR:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[X_ADDR:.*]] = alloca i32, align 4
+// OGCG: %[[Y_ADDR:.*]] = alloca i32, align 4
+// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
+// OGCG: %[[ELEM_0:.*]] = extractelement <4 x i32> %[[TMP_A]], i64 0
+// OGCG: store i32 %[[ELEM_0]], ptr %[[X_ADDR]], align 4
+// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
+// OGCG: %[[ELEM_1:.*]] = extractelement <4 x i32> %[[TMP_A]], i64 1
+// OGCG: store i32 %[[ELEM_1]], ptr %[[Y_ADDR]], align 4
+
+void element_expr_from_gl_with_vec_result() {
+ vi4 a;
+ vi2 b = a.xy;
+ vi4 c = a.wzyx;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a"]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.vector<2 x !s32i>, !cir.ptr<!cir.vector<2 x !s32i>>, ["b", init]
+// CIR: %[[C_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["c", init]
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
+// CIR: %[[POISON:.*]] = cir.const #cir.poison : !cir.vector<4 x !s32i>
+// CIR: %[[B_VALUE:.*]] = cir.vec.shuffle(%[[TMP_A]], %[[POISON]] : !cir.vector<4 x !s32i>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i] : !cir.vector<2 x !s32i>
+// CIR: cir.store {{.*}} %[[B_VALUE]], %[[B_ADDR]] : !cir.vector<2 x !s32i>, !cir.ptr<!cir.vector<2 x !s32i>>
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
+// CIR: %[[POISON:.*]] = cir.const #cir.poison : !cir.vector<4 x !s32i>
+// CIR: %[[C_VALUE:.*]] = cir.vec.shuffle(%[[TMP_A]], %[[POISON]] : !cir.vector<4 x !s32i>) [#cir.int<3> : !s32i, #cir.int<2> : !s32i, #cir.int<1> : !s32i, #cir.int<0> : !s32i] : !cir.vector<4 x !s32i>
+// CIR: cir.store {{.*}} %[[C_VALUE]], %[[C_ADDR]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
+
+// LLVM: %[[A_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[B_ADDR:.*]] = alloca <2 x i32>, i64 1, align 8
+// LLVM: %[[C_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
+// LLVM: %[[B_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_A]], <4 x i32> poison, <2 x i32> <i32 0, i32 1>
+// LLVM: store <2 x i32> %[[B_VALUE]], ptr %[[B_ADDR]], align 8
+// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
+// LLVM: %[[C_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_A]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+// LLVM: store <4 x i32> %[[C_VALUE]], ptr %[[C_ADDR]], align 16
+
+// OGCG: %[[A_ADDR:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[B_ADDR:.*]] = alloca <2 x i32>, align 8
+// OGCG: %[[C_ADDR:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
+// OGCG: %[[B_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_A]], <4 x i32> poison, <2 x i32> <i32 0, i32 1>
+// OGCG: store <2 x i32> %[[B_VALUE]], ptr %[[B_ADDR]], align 8
+// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
+// OGCG: %[[C_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_A]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+// OGCG: store <4 x i32> %[[C_VALUE]], ptr %[[C_ADDR]], align 16
+
+void element_expr_from_pointer() {
+ vi4 *a;
+ int X = a->x;
+ int Y = a->y;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.ptr<!cir.vector<4 x !s32i>>, !cir.ptr<!cir.ptr<!cir.vector<4 x !s32i>>>, ["a"]
+// CIR: %[[X_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["X", init]
+// CIR: %[[Y_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["Y", init]
+// CIR: %[[TMP_A_PTR:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.ptr<!cir.vector<4 x !s32i>>>, !cir.ptr<!cir.vector<4 x !s32i>>
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[TMP_A_PTR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
+// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s64i
+// CIR: %[[ELEM_0:.*]] = cir.vec.extract %[[TMP_A]][%[[CONST_0]] : !s64i] : !cir.vector<4 x !s32i>
+// CIR: cir.store {{.*}} %[[ELEM_0]], %[[X_ADDR]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[TMP_A_PTR:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.ptr<!cir.vector<4 x !s32i>>>, !cir.ptr<!cir.vector<4 x !s32i>>
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[TMP_A_PTR:.*]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
+// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s64i
+// CIR: %[[ELEM_1:.*]] = cir.vec.extract %[[TMP_A]][%[[CONST_1]] : !s64i] : !cir.vector<4 x !s32i>
+// CIR: cir.store {{.*}} %[[ELEM_1]], %[[Y_ADDR]] : !s32i, !cir.ptr<!s32i>
+
+// LLVM: %[[A_ADDR:.*]] = alloca ptr, i64 1, align 8
+// LLVM: %[[X_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: %[[Y_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: %[[TMP_A_PTR:.*]] = load ptr, ptr %[[A_ADDR]], align 8
+// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[TMP_A_PTR]], align 16
+// LLVM: %[[ELEM_0:.*]] = extractelement <4 x i32> %[[TMP_A]], i64 0
+// LLVM: store i32 %[[ELEM_0]], ptr %[[X_ADDR]], align 4
+// LLVM: %[[TMP_A_PTR:.*]] = load ptr, ptr %[[A_ADDR]], align 8
+// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[TMP_A_PTR]], align 16
+// LLVM: %[[ELEM_1:.*]] = extractelement <4 x i32> %[[TMP_A]], i64 1
+// LLVM: store i32 %[[ELEM_1]], ptr %[[Y_ADDR]], align 4
+
+// OGCG: %[[A_ADDR:.*]] = alloca ptr, align 8
+// OGCG: %[[X_ADDR:.*]] = alloca i32, align 4
+// OGCG: %[[Y_ADDR:.*]] = alloca i32, align 4
+// OGCG: %[[TMP_A_PTR:.*]] = load ptr, ptr %[[A_ADDR]], align 8
+// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[TMP_A_PTR]], align 16
+// OGCG: %[[ELEM_0:.*]] = extractelement <4 x i32> %[[TMP_A]], i64 0
+// OGCG: store i32 %[[ELEM_0]], ptr %[[X_ADDR]], align 4
+// OGCG: %[[TMP_A_PTR:.*]] = load ptr, ptr %[[A_ADDR]], align 8
+// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[TMP_A_PTR]], align 16
+// OGCG: %[[ELEM_1:.*]] = extractelement <4 x i32> %[[TMP_A]], i64 1
+// OGCG: store i32 %[[ELEM_1]], ptr %[[Y_ADDR]], align 4
+
+void element_expr_from_pointer_with_vec_result() {
+ vi4 *a;
+ vi2 b = a->xy;
+ vi4 c = a->wzyx;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.ptr<!cir.vector<4 x !s32i>>, !cir.ptr<!cir.ptr<!cir.vector<4 x !s32i>>>, ["a"]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.vector<2 x !s32i>, !cir.ptr<!cir.vector<2 x !s32i>>, ["b", init]
+// CIR: %[[C_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["c", init]
+// CIR: %[[TMP_A_PTR:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.ptr<!cir.vector<4 x !s32i>>>, !cir.ptr<!cir.vector<4 x !s32i>>
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[TMP_A_PTR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
+// CIR: %[[POISON:.*]] = cir.const #cir.poison : !cir.vector<4 x !s32i>
+// CIR: %[[B_VALUE:.*]] = cir.vec.shuffle(%[[TMP_A]], %[[POISON]] : !cir.vector<4 x !s32i>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i] : !cir.vector<2 x !s32i>
+// CIR: cir.store {{.*}} %[[B_VALUE]], %[[B_ADDR]] : !cir.vector<2 x !s32i>, !cir.ptr<!cir.vector<2 x !s32i>>
+// CIR: %[[TMP_A_PTR:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.ptr<!cir.vector<4 x !s32i>>>, !cir.ptr<!cir.vector<4 x !s32i>>
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[TMP_A_PTR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
+// CIR: %[[POISON:.*]] = cir.const #cir.poison : !cir.vector<4 x !s32i>
+// CIR: %[[C_VALUE:.*]] = cir.vec.shuffle(%[[TMP_A]], %[[POISON]] : !cir.vector<4 x !s32i>) [#cir.int<3> : !s32i, #cir.int<2> : !s32i, #cir.int<1> : !s32i, #cir.int<0> : !s32i] : !cir.vector<4 x !s32i>
+// CIR: cir.store {{.*}} %[[C_VALUE]], %[[C_ADDR]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
+
+// LLVM: %[[A_ADDR:.*]] = alloca ptr, i64 1, align 8
+// LLVM: %[[B_ADDR:.*]] = alloca <2 x i32>, i64 1, align 8
+// LLVM: %[[C_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[TMP_A_PTR:.*]] = load ptr, ptr %[[A_ADDR]], align 8
+// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[TMP_A_PTR]], align 16
+// LLVM: %[[B_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_A]], <4 x i32> poison, <2 x i32> <i32 0, i32 1>
+// LLVM: store <2 x i32> %[[B_VALUE]], ptr %[[B_ADDR]], align 8
+// LLVM: %[[TMP_A_PTR:.*]] = load ptr, ptr %[[A_ADDR]], align 8
+// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[TMP_A_PTR]], align 16
+// LLVM: %[[C_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_A]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+// LLVM: store <4 x i32> %[[C_VALUE]], ptr %[[C_ADDR]], align 16
+
+// OGCG: %[[A_ADDR:.*]] = alloca ptr, align 8
+// OGCG: %[[B_ADDR:.*]] = alloca <2 x i32>, align 8
+// OGCG: %[[C_ADDR:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[TMP_A_PTR:.*]] = load ptr, ptr %[[A_ADDR]], align 8
+// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[TMP_A_PTR]], align 16
+// OGCG: %[[B_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_A]], <4 x i32> poison, <2 x i32> <i32 0, i32 1>
+// OGCG: store <2 x i32> %[[B_VALUE]], ptr %[[B_ADDR]], align 8
+// OGCG: %[[TMP_A_PTR:.*]] = load ptr, ptr %[[A_ADDR]], align 8
+// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[TMP_A_PTR]], align 16
+// OGCG: %[[C_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_A]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+// OGCG: store <4 x i32> %[[C_VALUE]], ptr %[[C_ADDR]], align 16
+
+void element_expr_from_rvalue() {
+ vi4 a;
+ vi4 b;
+ int x = (a + b).x;
+ int y = (a + b).y;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a"]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["b"]
+// CIR: %[[X_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init]
+// CIR: %[[TMP_1_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["tmp"]
+// CIR: %[[Y_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["y", init]
+// CIR: %[[TMP_2_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["tmp"]
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
+// CIR: %[[TMP_B:.*]] = cir.load {{.*}} %[[B_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
+// CIR: %[[ADD_A_B:.*]] = cir.binop(add, %[[TMP_A]], %[[TMP_B]]) : !cir.vector<4 x !s32i>
+// CIR: cir.store {{.*}} %[[ADD_A_B]], %[[TMP_1_ADDR:.*]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
+// CIR: %[[TMP_1:.*]] = cir.load {{.*}} %[[TMP_1_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
+// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s64i
+// CIR: %[[ELEM_0:.*]] = cir.vec.extract %[[TMP_1]][%[[CONST_0]] : !s64i] : !cir.vector<4 x !s32i>
+// CIR: cir.store {{.*}} %[[ELEM_0]], %[[X_ADDR]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
+// CIR: %[[TMP_B:.*]] = cir.load {{.*}} %[[B_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
+// CIR: %[[ADD_A_B:.*]] = cir.binop(add, %[[TMP_A]], %[[TMP_B]]) : !cir.vector<4 x !s32i>
+// CIR: cir.store {{.*}} %[[ADD_A_B]], %[[TMP_2_ADDR]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
+// CIR: %[[TMP_2:.*]] = cir.load {{.*}} %[[TMP_2_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
+// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s64i
+// CIR: %[[ELEM_1:.*]] = cir.vec.extract %[[TMP_2]][%[[CONST_1]] : !s64i] : !cir.vector<4 x !s32i>
+// CIR: cir.store {{.*}} %[[ELEM_1]], %[[Y_ADDR]] : !s32i, !cir.ptr<!s32i>
+
+// LLVM: %[[A_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[B_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[X_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: %[[TMP_1_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[Y_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: %[[TMP_2_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
+// LLVM: %[[TMP_B:.*]] = load <4 x i32>, ptr %[[B_ADDR]], align 16
+// LLVM: %[[ADD_A_B:.*]] = add <4 x i32> %[[TMP_A]], %[[TMP_B]]
+// LLVM: store <4 x i32> %[[ADD_A_B]], ptr %[[TMP_1_ADDR]], align 16
+// LLVM: %[[TMP_1:.*]] = load <4 x i32>, ptr %[[TMP_1_ADDR]], align 16
+// LLVM: %[[ELEM_0:.*]] = extractelement <4 x i32> %[[TMP_1]], i64 0
+// LLVM: store i32 %[[ELEM_0]], ptr %[[X_ADDR]], align 4
+// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
+// LLVM: %[[TMP_B:.*]] = load <4 x i32>, ptr %[[B_ADDR]], align 16
+// LLVM: %[[ADD_A_B:.*]] = add <4 x i32> %[[TMP_A]], %[[TMP_B]]
+// LLVM: store <4 x i32> %[[ADD_A_B]], ptr %[[TMP_2_ADDR]], align 16
+// LLVM: %[[TMP_2:.*]] = load <4 x i32>, ptr %[[TMP_2_ADDR]], align 16
+// LLVM: %[[ELEM_1:.*]] = extractelement <4 x i32> %[[TMP_2]], i64 1
+// LLVM: store i32 %[[ELEM_1]], ptr %[[Y_ADDR]], align 4
+
+// OGCG: %[[A_ADDR:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[B_ADDR:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[X_ADDR:.*]] = alloca i32, align 4
+// OGCG: %[[TMP_1_ADDR:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[Y_ADDR:.*]] = alloca i32, align 4
+// OGCG: %[[TMP_2_ADDR:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
+// OGCG: %[[TMP_B:.*]] = load <4 x i32>, ptr %[[B_ADDR]], align 16
+// OGCG: %[[ADD_A_B:.*]] = add <4 x i32> %[[TMP_A]], %[[TMP_B]]
+// OGCG: store <4 x i32> %[[ADD_A_B]], ptr %[[TMP_1_ADDR]], align 16
+// OGCG: %[[TMP_1:.*]] = load <4 x i32>, ptr %[[TMP_1_ADDR]], align 16
+// OGCG: %[[ELEM_0:.*]] = extractelement <4 x i32> %[[TMP_1]], i64 0
+// OGCG: store i32 %[[ELEM_0]], ptr %[[X_ADDR]], align 4
+// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
+// OGCG: %[[TMP_B:.*]] = load <4 x i32>, ptr %[[B_ADDR]], align 16
+// OGCG: %[[ADD_A_B:.*]] = add <4 x i32> %[[TMP_A]], %[[TMP_B]]
+// OGCG: store <4 x i32> %[[ADD_A_B]], ptr %[[TMP_2_ADDR]], align 16
+// OGCG: %[[TMP_2:.*]] = load <4 x i32>, ptr %[[TMP_2_ADDR]], align 16
+// OGCG: %[[ELEM_1:.*]] = extractelement <4 x i32> %[[TMP_2]], i64 1
+// OGCG: store i32 %[[ELEM_1]], ptr %[[Y_ADDR]], align 4
+
+void element_expr_from_rvalue_with_vec_result() {
+ vi4 a;
+ vi4 b;
+ vi2 c = (a + b).xy;
+ vi4 d = (a + b).wzyx;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a"]
+// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["b"]
+// CIR: %[[C_ADDR:.*]] = cir.alloca !cir.vector<2 x !s32i>, !cir.ptr<!cir.vector<2 x !s32i>>, ["c", init]
+// CIR: %[[TMP_1_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["tmp"]
+// CIR: %[[D_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["d", init]
+// CIR: %[[TMP_2_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["tmp"]
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
+// CIR: %[[TMP_B:.*]] = cir.load {{.*}} %[[B_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
+// CIR: %[[ADD_A_B:.*]] = cir.binop(add, %[[TMP_A]], %[[TMP_B]]) : !cir.vector<4 x !s32i>
+// CIR: cir.store {{.*}} %[[ADD_A_B]], %[[TMP_1_ADDR]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
+// CIR: %[[TMP_1:.*]] = cir.load {{.*}} %[[TMP_1_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
+// CIR: %[[POISON:.*]] = cir.const #cir.poison : !cir.vector<4 x !s32i>
+// CIR: %[[C_VALUE:.*]] = cir.vec.shuffle(%[[TMP_1]], %[[POISON]] : !cir.vector<4 x !s32i>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i] : !cir.vector<2 x !s32i>
+// CIR: cir.store {{.*}} %[[C_VALUE]], %[[C_ADDR]] : !cir.vector<2 x !s32i>, !cir.ptr<!cir.vector<2 x !s32i>>
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
+// CIR: %[[TMP_B:.*]] = cir.load {{.*}} %[[B_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
+// CIR: %[[ADD_A_B:.*]] = cir.binop(add, %[[TMP_A]], %[[TMP_B]]) : !cir.vector<4 x !s32i>
+// CIR: cir.store {{.*}} %[[ADD_A_B]], %[[TMP_2_ADDR]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
+// CIR: %[[TMP_2:.*]] = cir.load {{.*}} %[[TMP_2_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
+// CIR: %[[POISON:.*]] = cir.const #cir.poison : !cir.vector<4 x !s32i>
+// CIR: %[[D_VALUE:.*]] = cir.vec.shuffle(%[[TMP_2]], %[[POISON]] : !cir.vector<4 x !s32i>) [#cir.int<3> : !s32i, #cir.int<2> : !s32i, #cir.int<1> : !s32i, #cir.int<0> : !s32i] : !cir.vector<4 x !s32i>
+// CIR: cir.store {{.*}} %[[D_VALUE]], %[[D_ADDR]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
+
+// LLVM: %[[A_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[B_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[C_ADDR:.*]] = alloca <2 x i32>, i64 1, align 8
+// LLVM: %[[TMP_1_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[D_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[TMP_2_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
+// LLVM: %[[TMP_B:.*]] = load <4 x i32>, ptr %[[B_ADDR]], align 16
+// LLVM: %[[ADD_A_B:.*]] = add <4 x i32> %[[TMP_A]], %[[TMP_B]]
+// LLVM: store <4 x i32> %[[ADD_A_B]], ptr %[[TMP_1_ADDR]], align 16
+// LLVM: %[[TMP_1:.*]] = load <4 x i32>, ptr %[[TMP_1_ADDR]], align 16
+// LLVM: %[[C_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_1]], <4 x i32> poison, <2 x i32> <i32 0, i32 1>
+// LLVM: store <2 x i32> %[[C_VALUE]], ptr %[[C_ADDR]], align 8
+// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
+// LLVM: %[[TMP_B:.*]] = load <4 x i32>, ptr %[[B_ADDR]], align 16
+// LLVM: %[[ADD_A_B:.*]] = add <4 x i32> %[[TMP_A]], %[[TMP_B]]
+// LLVM: store <4 x i32> %[[ADD_A_B]], ptr %[[TMP_2_ADDR]], align 16
+// LLVM: %[[TMP_2:.*]] = load <4 x i32>, ptr %[[TMP_2_ADDR]], align 16
+// LLVM: %[[D_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_2]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+// LLVM: store <4 x i32> %[[D_VALUE]], ptr %[[D_ADDR]], align 16
+
+// OGCG: %[[A_ADDR:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[B_ADDR:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[C_ADDR:.*]] = alloca <2 x i32>, align 8
+// OGCG: %[[TMP_1_ADDR:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[D_ADDR:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[TMP_2_ADDR:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
+// OGCG: %[[TMP_B:.*]] = load <4 x i32>, ptr %[[B_ADDR]], align 16
+// OGCG: %[[ADD_A_B:.*]] = add <4 x i32> %[[TMP_A]], %[[TMP_B]]
+// OGCG: store <4 x i32> %[[ADD_A_B]], ptr %[[TMP_1_ADDR]], align 16
+// OGCG: %[[TMP_1:.*]] = load <4 x i32>, ptr %[[TMP_1_ADDR]], align 16
+// OGCG: %[[C_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_1]], <4 x i32> poison, <2 x i32> <i32 0, i32 1>
+// OGCG: store <2 x i32> %[[C_VALUE]], ptr %[[C_ADDR]], align 8
+// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
+// OGCG: %[[TMP_B:.*]] = load <4 x i32>, ptr %[[B_ADDR]], align 16
+// OGCG: %[[ADD_A_B:.*]] = add <4 x i32> %[[TMP_A]], %[[TMP_B]]
+// OGCG: store <4 x i32> %[[ADD_A_B]], ptr %[[TMP_2_ADDR]], align 16
+// OGCG: %[[TMP_2:.*]] = load <4 x i32>, ptr %[[TMP_2_ADDR]], align 16
+// OGCG: %[[D_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_2]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+// OGCG: store <4 x i32> %[[D_VALUE]], ptr %[[D_ADDR]], align 16
+
+void array_subscript_expr_with_element_expr_base() {
+ vi4 a;
+ a.xyz[1] = 2;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a"]
+// CIR: %[[CONST_2:.*]] = cir.const #cir.int<2> : !s32i
+// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s32i
+// CIR: %[[A_PTR:.*]] = cir.cast bitcast %0 : !cir.ptr<!cir.vector<4 x !s32i>> -> !cir.ptr<!s32i>
+// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s64i
+// CIR: %[[VEC_MEMBER_EXPR:.*]] = cir.ptr_stride %[[A_PTR]], %[[CONST_0]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i>
+// CIR: %[[VEC_ELEM_PTR:.*]] = cir.ptr_stride %[[VEC_MEMBER_EXPR]], %[[CONST_1]] : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
+// CIR: cir.store {{.*}} %[[CONST_2]], %[[VEC_ELEM_PTR]] : !s32i, !cir.ptr<!s32i>
+
+// LLVM: %[[A_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[VEC_MEMBER_EXPR:.*]] = getelementptr i32, ptr %[[A_ADDR]], i64 0
+// LLVM: %[[VEC_ELEM_PTR:.*]] = getelementptr i32, ptr %[[VEC_MEMBER_EXPR]], i64 1
+// LLVM: store i32 2, ptr %[[VEC_ELEM_PTR]], align 4
+
+// OGCG: %[[A_ADDR:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[VEC_MEMBER_EXPR:.*]] = getelementptr inbounds i32, ptr %[[A_ADDR]], i64 0
+// OGCG: %[[VEC_ELEM_PTR:.*]] = getelementptr inbounds i32, ptr %[[VEC_MEMBER_EXPR]], i64 1
+// OGCG: store i32 2, ptr %[[VEC_ELEM_PTR]], align 4
diff --git a/clang/test/CIR/CodeGen/volatile.cpp b/clang/test/CIR/CodeGen/volatile.cpp
index df1d3a6..17a7154 100644
--- a/clang/test/CIR/CodeGen/volatile.cpp
+++ b/clang/test/CIR/CodeGen/volatile.cpp
@@ -9,7 +9,7 @@ int test_load(volatile int *ptr) {
return *ptr;
}
-// CIR: cir.func dso_local @_Z9test_loadPVi
+// CIR: cir.func {{.*}} @_Z9test_loadPVi
// CIR: cir.load volatile
// LLVM: define {{.*}} i32 @_Z9test_loadPVi
@@ -22,7 +22,7 @@ void test_store(volatile int *ptr) {
*ptr = 42;
}
-// CIR: cir.func dso_local @_Z10test_storePVi
+// CIR: cir.func {{.*}} @_Z10test_storePVi
// CIR: cir.store volatile
// LLVM: define {{.*}} void @_Z10test_storePVi
@@ -41,7 +41,7 @@ int test_load_field1(volatile Foo *ptr) {
return ptr->x;
}
-// CIR: cir.func dso_local @_Z16test_load_field1PV3Foo
+// CIR: cir.func {{.*}} @_Z16test_load_field1PV3Foo
// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member
// CIR: %{{.+}} = cir.load volatile{{.*}} %[[MEMBER_ADDR]]
@@ -57,7 +57,7 @@ int test_load_field2(Foo *ptr) {
return ptr->y;
}
-// CIR: cir.func dso_local @_Z16test_load_field2P3Foo
+// CIR: cir.func {{.*}} @_Z16test_load_field2P3Foo
// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member
// CIR: %{{.+}} = cir.load volatile{{.*}} %[[MEMBER_ADDR]]
@@ -73,7 +73,7 @@ int test_load_field3(Foo *ptr) {
return ptr->z;
}
-// CIR: cir.func dso_local @_Z16test_load_field3P3Foo
+// CIR: cir.func {{.*}} @_Z16test_load_field3P3Foo
// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member
// CIR: %{{.*}} = cir.get_bitfield align(4) (#bfi_z, %[[MEMBER_ADDR:.+]] {is_volatile} : !cir.ptr<!u8i>) -> !s32i
@@ -95,7 +95,7 @@ void test_store_field1(volatile Foo *ptr) {
ptr->x = 42;
}
-// CIR: cir.func dso_local @_Z17test_store_field1PV3Foo
+// CIR: cir.func {{.*}} @_Z17test_store_field1PV3Foo
// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member
// CIR: cir.store volatile{{.*}} %{{.+}}, %[[MEMBER_ADDR]]
@@ -111,7 +111,7 @@ void test_store_field2(Foo *ptr) {
ptr->y = 42;
}
-// CIR: cir.func dso_local @_Z17test_store_field2P3Foo
+// CIR: cir.func {{.*}} @_Z17test_store_field2P3Foo
// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member
// CIR: cir.store volatile{{.*}} %{{.+}}, %[[MEMBER_ADDR]]
@@ -127,7 +127,7 @@ void test_store_field3(Foo *ptr) {
ptr->z = 4;
}
-// CIR: cir.func dso_local @_Z17test_store_field3P3Foo
+// CIR: cir.func {{.*}} @_Z17test_store_field3P3Foo
// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member
// CIR: cir.set_bitfield align(4) (#bfi_z, %[[MEMBER_ADDR:.+]] : !cir.ptr<!u8i>, %1 : !s32i) {is_volatile}
@@ -155,7 +155,7 @@ void A::set_x(int val) volatile {
x = val;
}
-// CIR: cir.func dso_local @_ZNV1A5set_xEi
+// CIR: cir.func {{.*}} @_ZNV1A5set_xEi
// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member %{{.*}}[0] {name = "x"}
// CIR: cir.store volatile {{.*}} %{{.*}}, %[[MEMBER_ADDR]]
@@ -171,7 +171,7 @@ int A::get_x() volatile {
return x;
}
-// CIR: cir.func dso_local @_ZNV1A5get_xEv
+// CIR: cir.func {{.*}} @_ZNV1A5get_xEv
// CIR: %[[MEMBER_ADDR:.*]] = cir.get_member %{{.*}}[0] {name = "x"}
// CIR: cir.load volatile {{.*}} %[[MEMBER_ADDR]]
diff --git a/clang/test/CIR/CodeGen/vtable-emission.cpp b/clang/test/CIR/CodeGen/vtable-emission.cpp
index 9a34573..ceefb2a 100644
--- a/clang/test/CIR/CodeGen/vtable-emission.cpp
+++ b/clang/test/CIR/CodeGen/vtable-emission.cpp
@@ -32,7 +32,7 @@ void S::key() {}
// OGCG: @_ZTV1S = unnamed_addr constant { [4 x ptr] } { [4 x ptr]
// OGCG-SAME: [ptr null, ptr null, ptr @_ZN1S3keyEv, ptr @_ZN1S6nonKeyEv] }
-// CHECK: cir.func dso_local @_ZN1S3keyEv
+// CHECK: cir.func {{.*}} @_ZN1S3keyEv
// The reference from the vtable should result in nonKey being emitted.
-// CHECK: cir.func comdat linkonce_odr @_ZN1S6nonKeyEv
+// CHECK: cir.func no_inline comdat linkonce_odr @_ZN1S6nonKeyEv
diff --git a/clang/test/CIR/CodeGen/vtt.cpp b/clang/test/CIR/CodeGen/vtt.cpp
index f9a62e3..d0319b7 100644
--- a/clang/test/CIR/CodeGen/vtt.cpp
+++ b/clang/test/CIR/CodeGen/vtt.cpp
@@ -5,12 +5,12 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fno-rtti -emit-llvm %s -o %t.ll
// RUN: FileCheck --check-prefixes=OGCG-NO-RTTI,OGCG-COMMON --input-file=%t.ll %s
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
-// RUN: FileCheck --check-prefixes=CIR-RTTI,CIR-COMMON --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-prefixes=LLVM-RTTI,LLVM-COMMON --input-file=%t-cir.ll %s
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
-// RUN: FileCheck --check-prefixes=OGCG-RTTI,OGCG-COMMON --input-file=%t.ll %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t-rtti.cir
+// RUN: FileCheck --check-prefixes=CIR-RTTI,CIR-COMMON --input-file=%t-rtti.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir-rtti.ll
+// RUN: FileCheck --check-prefixes=LLVM-RTTI,LLVM-COMMON --input-file=%t-cir-rtti.ll %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t-rtti.ll
+// RUN: FileCheck --check-prefixes=OGCG-RTTI,OGCG-COMMON --input-file=%t-rtti.ll %s
// Note: This test will be expanded to verify VTT emission and VTT implicit
// argument handling. For now, it's just test the record layout.
@@ -170,7 +170,7 @@ void D::y() {}
// CIR-RTTI: cir.global{{.*}} @_ZTI1B : !cir.ptr<!u8i>
-// LLVM-RTTI: @_ZTI1B = external global ptr
+// LLVM-RTTI: @_ZTI1B = external constant ptr
// OGCG-RTTI: @_ZTI1B = external constant ptr