blob: a5e84669d914d92d6f180fa08ead22cf7526f26c [file]
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
template <typename T>
struct IsChar {
constexpr operator bool() const { return false; }
};
template<>
struct IsChar<char> {
constexpr operator bool() const { return true; }
};
template <typename T>
concept SameAsChar = (bool)IsInt<T>();
// LLVM-DAG: [[STRUCT_A:%.*]] = type { i8, double }
// CIR-DAG: ![[STRUCT_A:.*]] = !cir.record<struct "A" {!s8i, !cir.double}>
struct A {
char i;
double j;
template <SameAsChar T>
operator T() const { return i; };
};
// LLVM-DAG: [[STRUCT_B:%.*]] = type { [[STRUCT_A]], i32 }
// CIR-DAG: ![[STRUCT_B:.*]] = !cir.record<struct "B" {![[STRUCT_A]], !s32i}>
struct B {
A a;
int b;
};
// LLVM-DAG: [[STRUCT_C:%.*]] = type <{ [[STRUCT_B]], [[STRUCT_A]], i32, [4 x i8] }>
// CIR-DAG: ![[STRUCT_C:.*]] = !cir.record<struct "C" packed padded {![[STRUCT_B]], ![[STRUCT_A]], !s32i, !cir.array<!u8i x 4>}>
struct C : public B, public A {
int c;
};
// LLVM-DAG: [[STRUCT_D:%.*]] = type { [[STRUCT_A]], [[STRUCT_A]], i8, [[STRUCT_A]] }
// CIR-DAG: ![[STRUCT_D:.*]] = !cir.record<struct "D" {![[STRUCT_A]], ![[STRUCT_A]], !u8i, ![[STRUCT_A]]}>
struct D {
A a;
A b = A{2, 2.0};
unsigned : 2;
A c;
};
// LLVM-DAG: [[STRUCT_E:%.*]] = type { i32, ptr }
// CIR-DAG: ![[STRUCT_E:.*]] = !cir.record<struct "E" {!s32i, !cir.ptr<!s8i>}>
struct E {
int a;
const char* fn = __builtin_FUNCTION();
~E() {};
};
// CIR-DAG: ![[STRUCT_F:.*]] = !cir.record<struct "F" padded {!u8i}>
struct F {
F (int i = 1);
F (const F &f) = delete;
F (F &&f) = default;
};
// LLVM-DAG: [[STRUCT_G:%.*]] = type <{ i32, [4 x i8] }>
// CIR-DAG: ![[STRUCT_G:.*]] = !cir.record<struct "G" packed padded {!s32i, !cir.array<!u8i x 4>}>
struct G {
int a;
F f;
};
// LLVM-DAG: [[UNION_U:%.*]] = type { [[STRUCT_A]] }
// LLVM-DAG: [[STR:@.*]] = private {{.*}}constant [6 x i8] {{.*}}foo18{{.*}}, align 1
// CIR-DAG: ![[UNION_U:.*]] = !cir.record<union "U" {!u8i, ![[STRUCT_A]], !s8i}>
union U {
unsigned : 1;
A a;
char b;
};
namespace gh61145 {
// LLVM-DAG: [[STRUCT_VEC:%.*Vec.*]] = type { i8 }
// CIR-DAG: ![[STRUCT_VEC:.*]] = !cir.record<struct "gh61145::Vec" padded {!u8i}>
struct Vec {
Vec();
Vec(Vec&&);
~Vec();
};
// LLVM-DAG: [[STRUCT_S1:%.*]] = type { i8 }
// CIR-DAG: ![[STRUCT_S1:.*]] = !cir.record<struct "gh61145::S1" padded {!u8i}>
struct S1 {
Vec v;
};
// LLVM-DAG: [[STRUCT_S2:%.*]] = type { i8, i8 }
// CIR-DAG: ![[STRUCT_S2:.*]] = !cir.record<struct "gh61145::S2" padded {!u8i, !s8i}>
struct S2 {
Vec v;
char c;
};
}
namespace gh62266 {
// LLVM-DAG: [[STRUCT_H:%.*H.*]] = type { i32, i32 }
// CIR-DAG: ![[STRUCT_H:.*]] = !cir.record<struct "gh62266::H<2>" {!s32i, !s32i}>
template <int J>
struct H {
int i;
int j = J;
};
}
namespace gh61567 {
// LLVM-DAG: [[STRUCT_I:%.*I.*]] = type { i32, ptr }
// CIR-DAG: ![[STRUCT_I:.*]] = !cir.record<struct "gh61567::I" {!s32i, !cir.ptr<!s32i>}>
struct I {
int a;
int&& r = 2;
};
}
// LLVM-DAG: [[A1:@.*a1.*]] = internal constant [[STRUCT_A]] { i8 3, double 2.000000e+00 }, align 8
// CIR-DAG: cir.global "private" constant internal dso_local @_ZL2a1 = #cir.const_record<{#cir.int<3> : !s8i, #cir.fp<2.000000e+00> : !cir.double}> : ![[STRUCT_A]] {alignment = 8 : i64}
constexpr A a1(3.1, 2.0);
// LLVM-DAG: [[A2:@.*a2.*]] = internal constant [[STRUCT_A]] { i8 99, double 0.000000e+00 }, align 8
// CIR-DAG: cir.global "private" constant internal dso_local @_ZL2a2 = #cir.const_record<{#cir.int<99> : !s8i, #cir.fp<0.000000e+00> : !cir.double}> : ![[STRUCT_A]] {alignment = 8 : i64}
constexpr auto a2 = static_cast<A>('c');
// LLVM-DAG: [[B1:@.*b1.*]] = internal constant [[STRUCT_B]] { [[STRUCT_A]] { i8 99, double 0.000000e+00 }, i32 0 }, align 8
// CIR-DAG: cir.global "private" constant internal dso_local @_ZL2b1 = #cir.const_record<{#cir.const_record<{#cir.int<99> : !s8i, #cir.fp<0.000000e+00> : !cir.double}> : ![[STRUCT_A]], #cir.int<0> : !s32i}> : ![[STRUCT_B]] {alignment = 8 : i64}
constexpr B b1(A('c'));
// LLVM-DAG: [[C1:@.*c1.*]] = internal constant { [[STRUCT_A]], i32, [4 x i8], i8, double, i32 } { [[STRUCT_A]] { i8 99, double 0.000000e+00 }, i32 0, [4 x i8] {{.*}}, i8 3, double 2.000000e+00, i32 0 }, align
// CIR-DAG: cir.global "private" constant internal dso_local @_ZL2c1 = #cir.const_record<{#cir.const_record<{#cir.int<99> : !s8i, #cir.fp<0.000000e+00> : !cir.double}> : ![[STRUCT_A]], #cir.int<0> : !s32i, #cir.const_array<[#cir.zero : !u8i, #cir.zero : !u8i, #cir.zero : !u8i, #cir.zero : !u8i]> : !cir.array<!u8i x 4>, #cir.int<3> : !s8i, #cir.fp<2.000000e+00> : !cir.double, #cir.int<0> : !s32i}>
constexpr C c1(b1, a1);
// LLVM-DAG: [[U1:@.*]] = internal constant {{.*}} { [[STRUCT_A]] { i8 1, double 1.000000e+00 } }, align 8
// CIR-DAG: cir.global "private" constant internal dso_local @_ZL2u1 = #cir.const_record<{#cir.const_record<{#cir.int<1> : !s8i, #cir.fp<1.000000e+00> : !cir.double}> : ![[STRUCT_A]]}> : !{{.*}}{alignment = 8 : i64}
constexpr U u1(A(1, 1));
// LLVM-DAG: [[D1:@.*d1.*]] = internal constant { [[STRUCT_A]], [[STRUCT_A]], [8 x i8], [[STRUCT_A]] } { [[STRUCT_A]] { i8 2, double 2.000000e+00 }, [[STRUCT_A]] { i8 2, double 2.000000e+00 }, [8 x i8] {{.*}}, [[STRUCT_A]] zeroinitializer }, align 8
// CIR-DAG: cir.global "private" constant internal dso_local @_ZL2d1 = #cir.const_record<{#cir.const_record<{#cir.int<2> : !s8i, #cir.fp<2.000000e+00> : !cir.double}> : ![[STRUCT_A]], #cir.const_record<{#cir.int<2> : !s8i, #cir.fp<2.000000e+00> : !cir.double}> : ![[STRUCT_A]], #cir.const_array<[#cir.zero : !u8i, #cir.zero : !u8i, #cir.zero : !u8i, #cir.zero : !u8i, #cir.zero : !u8i, #cir.zero : !u8i, #cir.zero : !u8i, #cir.zero : !u8i]> : !cir.array<!u8i x 8>, #cir.zero : ![[STRUCT_A]]}>
constexpr D d1(A(2, 2));
// LLVM-DAG: [[ARR1:@.*arr1.*]] = internal constant [3 x i32] [i32 1, i32 2, i32 0], align 4
// CIR-DAG: cir.global "private" constant internal dso_local @_ZL4arr1 = #cir.const_array<[#cir.int<1> : !s32i, #cir.int<2> : !s32i, #cir.int<0> : !s32i]> : !cir.array<!s32i x 3> {alignment = 4 : i64}
constexpr int arr1[3](1, 2);
// LLVM-DAG: [[ARR4:@.*arr4.*]] = internal constant [1 x i32] [i32 1], align 4
// CIR-DAG: cir.global "private" constant internal dso_local @_ZL4arr4 = #cir.const_array<[#cir.int<1> : !s32i]> : !cir.array<!s32i x 1> {alignment = 4 : i64}
constexpr int arr4[](1);
// LLVM-DAG: [[ARR5:@.*arr5.*]] = internal constant [2 x i32] [i32 2, i32 0], align 4
// CIR-DAG: cir.global "private" constant internal dso_local @_ZL4arr5 = #cir.const_array<[#cir.int<2> : !s32i, #cir.int<0> : !s32i]> : !cir.array<!s32i x 2> {alignment = 4 : i64}
constexpr int arr5[2](2);
// LLVM: define dso_local {{.*}} @{{.*foo1.*}}
// LLVM: [[RETVAL:%.*]] = alloca [[STRUCT_A]]
// LLVM-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr {{.*}}[[RETVAL]], ptr {{.*}}[[A1]], i64 16, i1 false)
// LLVM-NEXT: [[TMP_0:%.*]] = load {{.*}}, ptr [[RETVAL]], align 8
// LLVM-NEXT: ret {{.*}}[[TMP_0]]
// CIR-LABEL: cir.func {{.*}}@_Z4foo1v()
// CIR: %[[A_ALLOCA:.*]] = cir.alloca ![[STRUCT_A]], !cir.ptr<![[STRUCT_A]]>, ["__retval"] {alignment = 8 : i64}
// CIR: %[[GET_A1:.*]] = cir.get_global @_ZL2a1 : !cir.ptr<![[STRUCT_A]]>
// CIR: cir.copy %[[GET_A1]] to %[[A_ALLOCA]] : !cir.ptr<![[STRUCT_A]]>
A foo1() {
return a1;
}
// LLVM: define dso_local {{.*}}@{{.*foo2.*}}
// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr {{.*}}, ptr {{.*}}[[B1]], i64 24, i1 false)
// CIR: cir.func {{.*}}@_Z4foo2v()
// CIR: %[[B_ALLOCA:.*]] = cir.alloca ![[STRUCT_B]], !cir.ptr<![[STRUCT_B]]>, ["__retval"] {alignment = 8 : i64}
// CIR: %[[GET_GLOB:.*]] = cir.get_global @_ZL2b1 : !cir.ptr<![[STRUCT_B]]>
// CIR: cir.copy %[[GET_GLOB]] to %[[B_ALLOCA]] : !cir.ptr<![[STRUCT_B]]>
B foo2() {
return b1;
}
// LLVM: define dso_local {{.*}}@{{.*foo3.*}}
// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr {{.*}}, ptr {{.*}}[[C1]], i64 48, i1 false)
// CIR: cir.func {{.*}}@_Z4foo3v()
// CIR: %[[C_ALLOCA:.*]] = cir.alloca ![[STRUCT_C]], !cir.ptr<![[STRUCT_C]]>, ["__retval"] {alignment = 8 : i64}
// CIR: %[[GET_GLOB:.*]] = cir.get_global @_ZL2c1
// CIR: %[[GLOB_CAST:.*]] = cir.cast bitcast %[[GET_GLOB]] : !cir.ptr<!{{.*}}> -> !cir.ptr<![[STRUCT_C]]>
// CIR: cir.copy %[[GLOB_CAST]] to %[[C_ALLOCA]] : !cir.ptr<![[STRUCT_C]]>
C foo3() {
return c1;
}
// LLVM: define dso_local void @{{.*foo4.*}}
// LLVM-DAG: [[C2:%.*]] = alloca [[STRUCT_C]]
// LLVM-DAG: [[REF_TMP:%.*]] = alloca [[STRUCT_B]]
// LLVM-DAG: [[REF_TMP_1:%.*]] = alloca [[STRUCT_A]]
// LLVM: [[A:%.*]] = getelementptr {{.*}}[[STRUCT_B]], ptr [[REF_TMP]], i32 0, i32 0
// LLVM-NEXT: [[I:%.*]] = getelementptr {{.*}}[[STRUCT_A]], ptr [[A]], i32 0, i32 0
// LLVM-NEXT: store i8 1, ptr [[I]], align 8
// LLVM-NEXT: [[J:%.*]] = getelementptr {{.*}}[[STRUCT_A]], ptr [[A]], i32 0, i32 1
// LLVM-NEXT: store double 1.000000e+00, ptr [[J]], align 8
// LLVM-NEXT: [[B:%.*]] = getelementptr {{.*}}[[STRUCT_B]], ptr [[REF_TMP]], i32 0, i32 1
// LLVM-NEXT: store i32 1, ptr [[B]], align 8
// LLVM-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr {{.*}}[[C2]], ptr {{.*}}[[REF_TMP]], i64 24, i1 false)
// LLVM-NEXT: [[TMP_0:%.*]] = getelementptr {{.*}}i8, ptr [[C2]], i{{.*}} 24
// LLVM-NEXT: [[I2:%.*]] = getelementptr {{.*}}[[STRUCT_A]], ptr [[REF_TMP_1]], i32 0, i32 0
// LLVM-NEXT: store i8 97, ptr [[I2]], align 8
// LLVM-NEXT: [[J3:%.*]] = getelementptr {{.*}}[[STRUCT_A]], ptr [[REF_TMP_1]], i32 0, i32 1
// LLVM-NEXT: store double 0.000000e+00, ptr [[J3]], align 8
// LLVM-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr {{.*}}[[TMP_0]], ptr {{.*}}[[REF_TMP_1]], i64 16, i1 false)
// LLVM-NEXT: [[C:%.*]] = getelementptr {{.*}}[[STRUCT_C]], ptr [[C2]], i32 0, i32 2
// LLVM-NEXT: store i32 2, ptr [[C]]
// LLVM: ret void
// CIR-LABEL: cir.func {{.*}}@_Z4foo4v()
// CIR: %[[C2_ALLOCA:.*]] = cir.alloca ![[STRUCT_C]], !cir.ptr<![[STRUCT_C]]>, ["c2", init]
// CIR: %[[B_TMP:.*]] = cir.alloca ![[STRUCT_B]], !cir.ptr<![[STRUCT_B]]>, ["ref.tmp0"]
// CIR: %[[A_TMP:.*]] = cir.alloca ![[STRUCT_A]], !cir.ptr<![[STRUCT_A]]>, ["ref.tmp1"]
// CIR: %[[C_BASE:.*]] = cir.base_class_addr %[[C2_ALLOCA]] : !cir.ptr<![[STRUCT_C]]> nonnull [0] -> !cir.ptr<![[STRUCT_B]]>
// CIR: %[[GET_A:.*]] = cir.get_member %[[B_TMP]][0] {name = "a"} : !cir.ptr<![[STRUCT_B]]> -> !cir.ptr<![[STRUCT_A]]>
// CIR: %[[GET_I:.*]] = cir.get_member %[[GET_A]][0] {name = "i"} : !cir.ptr<![[STRUCT_A]]> -> !cir.ptr<!s8i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s8i
// CIR: cir.store{{.*}} %[[ONE:.*]], %[[GET_I]] : !s8i, !cir.ptr<!s8i>
// CIR: %[[GET_J:.*]] = cir.get_member %[[GET_A]][1] {name = "j"} : !cir.ptr<![[STRUCT_A]]> -> !cir.ptr<!cir.double>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CIR: %[[ONE_F:.*]] = cir.cast int_to_float %[[ONE]] : !s32i -> !cir.double
// CIR: cir.store{{.*}} %[[ONE_F]], %[[GET_J]] : !cir.double, !cir.ptr<!cir.double>
// CIR: %[[GET_B:.*]] = cir.get_member %[[B_TMP]][1] {name = "b"} : !cir.ptr<![[STRUCT_B]]> -> !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CIR: cir.store{{.*}} %[[ONE]], %[[GET_B]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.copy %[[B_TMP]] to %[[C_BASE]] : !cir.ptr<![[STRUCT_B]]>
// CIR: %[[C_BASE_A:.*]] = cir.base_class_addr %[[C2_ALLOCA]] : !cir.ptr<![[STRUCT_C]]> nonnull [24] -> !cir.ptr<![[STRUCT_A]]>
// CIR: %[[GET_I:.*]] = cir.get_member %[[A_TMP]][0] {name = "i"} : !cir.ptr<![[STRUCT_A]]> -> !cir.ptr<!s8i>
// CIR: %[[NINETYSEVEN:.*]] = cir.const #cir.int<97> : !s8i
// CIR: cir.store{{.*}} %[[NINETYSEVEN]], %[[GET_I]] : !s8i, !cir.ptr<!s8i>
// CIR: %[[GET_J:.*]] = cir.get_member %[[A_TMP]][1] {name = "j"} : !cir.ptr<![[STRUCT_A]]> -> !cir.ptr<!cir.double>
// CIR: %[[ZERO_F:.*]] = cir.const #cir.fp<0
// CIR: cir.store{{.*}} %[[ZERO_F]], %[[GET_J]] : !cir.double, !cir.ptr<!cir.double>
// CIR: cir.copy %[[A_TMP]] to %[[C_BASE_A]] : !cir.ptr<![[STRUCT_A]]>
// CIR: %[[GET_C:.*]] = cir.get_member %[[C2_ALLOCA]][2] {name = "c"} : !cir.ptr<![[STRUCT_C]]> -> !cir.ptr<!s32i>
// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s32i
// CIR: cir.store{{.*}} %[[TWO]], %[[GET_C]] : !s32i, !cir.ptr<!s32i>
void foo4() {
C c2(B(A(1, 1), 1), A('a'), 2);
}
// LLVM: define dso_local {{.*}}@{{.*foo5.*}}
// LLVM: [[RETVAL:%.*]] = alloca [[UNION_U]]
// LLVM-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr {{.*}}[[RETVAL]], ptr {{.*}}[[U1]], i64 16, i1 false)
// CIR-LABEL: cir.func no_inline dso_local @_Z4foo5v()
// CIR: %[[RET:.*]] = cir.alloca ![[UNION_U]], !cir.ptr<![[UNION_U]]>, ["__retval"] {alignment = 8 : i64}
// CIR: %[[GET_GLOB:.*]] = cir.get_global @_ZL2u1 : !cir.ptr<!{{.*}}>
// CIR: %[[GLOB_TO_U:.*]] = cir.cast bitcast %[[GET_GLOB]] : !cir.ptr<!{{.*}}> -> !cir.ptr<![[UNION_U]]>
// CIR: cir.copy %[[GLOB_TO_U]] to %[[RET]] : !cir.ptr<![[UNION_U]]>
U foo5() {
return u1;
}
// LLVM: define dso_local {{.*}}@{{.*foo6.*}}
// LLVM-DAG: [[RETVAL:%.*]] = alloca [[UNION_U]]
// LLVM-DAG: [[A:%.*]] = alloca [[STRUCT_A]]
// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr {{.*}}[[RETVAL]], ptr {{.*}}[[A]], i64 16, i1 false)
// CIR-LABEL: cir.func no_inline dso_local @_Z4foo61A(
// CIR: %[[A_ALLOCA:.*]] = cir.alloca ![[STRUCT_A]], !cir.ptr<![[STRUCT_A]]>, ["a", init] {alignment = 8 : i64}
// CIR: %[[RET_ALLOCA:.*]] = cir.alloca ![[UNION_U]], !cir.ptr<![[UNION_U]]>, ["__retval"] {alignment = 8 : i64}
// CIR: %[[GET_A:.*]] = cir.get_member %[[RET_ALLOCA:.*]][1] {name = "a"} : !cir.ptr<![[UNION_U]]> -> !cir.ptr<![[STRUCT_A]]>
// CIR: cir.copy %[[A_ALLOCA]] to %[[GET_A:.*]] : !cir.ptr<![[STRUCT_A]]>
U foo6(A a) {
return U(a);
}
// LLVM: define dso_local void @{{.*foo7.*}}
// LLVM: [[D:%.*]] = alloca [[STRUCT_D]]
// LLVM-NEXT: [[A:%.*]] = getelementptr {{.*}}[[STRUCT_D]], ptr [[D]], i32 0, i32 0
// LLVM-NEXT: [[I:%.*]] = getelementptr {{.*}}[[STRUCT_A]], ptr [[A]], i32 0, i32 0
// LLVM-NEXT: store i8 1, ptr [[I]], align 8
// LLVM-NEXT: [[J:%.*]] = getelementptr {{.*}}[[STRUCT_A]], ptr [[A]], i32 0, i32 1
// LLVM-NEXT: store double 1.000000e+00, ptr [[J]], align 8
// LLVM-NEXT: [[B:%.*]] = getelementptr {{.*}}[[STRUCT_D]], ptr [[D]], i32 0, i32 1
// LLVM-NEXT: [[I1:%.*]] = getelementptr {{.*}}[[STRUCT_A]], ptr [[B]], i32 0, i32 0
// LLVM-NEXT: store i8 11, ptr [[I1]], align 8
// LLVM-NEXT: [[J2:%.*]] = getelementptr {{.*}}[[STRUCT_A]], ptr [[B]], i32 0, i32 1
// LLVM-NEXT: store double 1.100000e+01, ptr [[J2]], align 8
// LLVM-NEXT: [[C:%.*]] = getelementptr {{.*}}[[STRUCT_D]], ptr [[D]], i32 0, i32 3
// LLVM-NEXT: [[I3:%.*]] = getelementptr {{.*}}[[STRUCT_A]], ptr [[C]], i32 0, i32 0
// LLVM-NEXT: store i8 111, ptr [[I3]], align 8
// LLVM-NEXT: [[J4:%.*]] = getelementptr {{.*}}[[STRUCT_A]], ptr [[C]], i32 0, i32 1
// LLVM-NEXT: store double 1.110000e+02, ptr [[J4]], align 8
// LLVM-NEXT: ret void
// CIR-LABEL; cir.func no_inline dso_local @_Z4foo7v()
// CIR: %[[D_ALLOCA:.*]] = cir.alloca ![[STRUCT_D]], !cir.ptr<![[STRUCT_D]]>, ["d", init] {alignment = 8 : i64}
// CIR: %[[GET_A:.*]] = cir.get_member %[[D_ALLOCA]][0] {name = "a"} : !cir.ptr<![[STRUCT_D]]> -> !cir.ptr<![[STRUCT_A]]>
// CIR: %[[GET_I:.*]] = cir.get_member %[[GET_A]][0] {name = "i"} : !cir.ptr<![[STRUCT_A]]> -> !cir.ptr<!s8i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s8i
// CIR: cir.store align(8) %[[ONE]], %[[GET_I]] : !s8i, !cir.ptr<!s8i>
// CIR: %[[GET_J:.*]] = cir.get_member %[[GET_A]][1] {name = "j"} : !cir.ptr<![[STRUCT_A]]> -> !cir.ptr<!cir.double>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CIR: %[[ONE_F:.*]] = cir.cast int_to_float %[[ONE]] : !s32i -> !cir.double
// CIR: cir.store align(8) %[[ONE_F]], %[[GET_J]] : !cir.double, !cir.ptr<!cir.double>
// CIR: %[[GET_B:.*]] = cir.get_member %[[D_ALLOCA]][1] {name = "b"} : !cir.ptr<![[STRUCT_D]]> -> !cir.ptr<![[STRUCT_A]]>
// CIR: %[[GET_I:.*]] = cir.get_member %[[GET_B]][0] {name = "i"} : !cir.ptr<![[STRUCT_A]]> -> !cir.ptr<!s8i>
// CIR: %[[ELEVEN:.*]] = cir.const #cir.int<11> : !s8i
// CIR: cir.store align(8) %[[ELEVEN]], %[[GET_I]] : !s8i, !cir.ptr<!s8i>
// CIR: %[[GET_J:.*]] = cir.get_member %[[GET_B]][1] {name = "j"} : !cir.ptr<![[STRUCT_A]]> -> !cir.ptr<!cir.double>
// CIR: %[[ELEVEN:.*]] = cir.const #cir.int<11> : !s32i
// CIR: %[[ELEVEN_F:.*]] = cir.cast int_to_float %[[ELEVEN]] : !s32i -> !cir.double
// CIR: cir.store align(8) %[[ELEVEN_F]], %[[GET_J]] : !cir.double, !cir.ptr<!cir.double>
// CIR: %[[GET_C:.*]] = cir.get_member %[[D_ALLOCA]][3] {name = "c"} : !cir.ptr<![[STRUCT_D]]> -> !cir.ptr<![[STRUCT_A]]>
// CIR: %[[GET_I:.*]] = cir.get_member %[[GET_C]][0] {name = "i"} : !cir.ptr<![[STRUCT_A]]> -> !cir.ptr<!s8i>
// CIR: %[[ONE_ELEVEN:.*]] = cir.const #cir.int<111> : !s8i
// CIR: cir.store align(8) %[[ONE_ELEVEN]], %[[GET_I]] : !s8i, !cir.ptr<!s8i>
// CIR: %[[GET_J:.*]] = cir.get_member %[[GET_C]][1] {name = "j"} : !cir.ptr<![[STRUCT_A]]> -> !cir.ptr<!cir.double>
// CIR: %[[ONE_ELEVEN:.*]] = cir.const #cir.int<111> : !s32i
// CIR: %[[ONE_ELEVEN_F:.*]] = cir.cast int_to_float %[[ONE_ELEVEN]] : !s32i -> !cir.double
// CIR: cir.store align(8) %[[ONE_ELEVEN_F]], %[[GET_J]] : !cir.double, !cir.ptr<!cir.double>
void foo7() {
D d(A(1, 1), A(11, 11), A(111, 111));
}
// LLVM: dso_local {{.*}}@{{.*foo8.*}}(
// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr {{.*}}, ptr {{.*}}[[D1]], i64 56, i1 false)
// CIR-LABEL: cir.func no_inline dso_local @_Z4foo8v()
// CIR: %[[RET_ALLOCA:.*]] = cir.alloca ![[STRUCT_D]], !cir.ptr<![[STRUCT_D]]>, ["__retval"] {alignment = 8 : i64}
// CIR: %[[GET_GLOB:.*]] = cir.get_global @_ZL2d1 :
// CIR: %[[GLOB_CAST:.*]] = cir.cast bitcast %[[GET_GLOB]] : !cir.ptr<!{{.*}}> -> !cir.ptr<![[STRUCT_D]]>
// CIR: cir.copy %[[GLOB_CAST]] to %[[RET_ALLOCA]] : !cir.ptr<![[STRUCT_D]]>
D foo8() {
return d1;
}
// LLVM: define dso_local void @{{.*foo9.*}}
// LLVM: [[D:%.*]] = alloca [[STRUCT_D]]
// LLVM-NEXT: [[A:%.*]] = getelementptr {{.*}}[[STRUCT_D]], ptr [[D]], i32 0, i32 0
// LLVM-NEXT: [[I]] = getelementptr {{.*}}[[STRUCT_A]], ptr [[A]], i32 0, i32 0
// LLVM-NEXT: store i8 1, ptr [[I]], align 8
// LLVM-NEXT: [[J:%.*]] = getelementptr {{.*}}[[STRUCT_A]], ptr [[A]], i32 0, i32 1
// LLVM-NEXT: store double 1.000000e+00, ptr [[J]], align 8
// LLVM-NEXT: [[B:%.*]] = getelementptr {{.*}}[[STRUCT_D]], ptr [[D]], i32 0, i32 1
// LLVM-NEXT: [[I1:%.*]] = getelementptr {{.*}}[[STRUCT_A]], ptr [[B]], i32 0, i32 0
// LLVM-NEXT: store i8 2, ptr [[I1]], align 8
// LLVM-NEXT: [[J2:%.*]] = getelementptr {{.*}}[[STRUCT_A]], ptr [[B]], i32 0, i32 1
// LLVM-NEXT: store double 2.000000e+00, ptr [[J2]], align 8
// LLVM-NEXT: [[C:%.*]] = getelementptr {{.*}}[[STRUCT_D]], ptr [[D]], i32 0, i32 3
// CIR-LABEL: cir.func no_inline dso_local @_Z4foo9v()
// CIR: %[[D_ALLOCA:.*]] = cir.alloca ![[STRUCT_D]], !cir.ptr<![[STRUCT_D]]>, ["d", init] {alignment = 8 : i64}
// CIR: %[[GET_A:.*]] = cir.get_member %[[D_ALLOCA]][0] {name = "a"} : !cir.ptr<![[STRUCT_D]]> -> !cir.ptr<![[STRUCT_A]]>
// CIR: %[[GET_I:.*]] = cir.get_member %[[GET_A]][0] {name = "i"} : !cir.ptr<![[STRUCT_A]]> -> !cir.ptr<!s8i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s8i
// CIR: cir.store align(8) %[[ONE]], %[[GET_I]] : !s8i, !cir.ptr<!s8i>
// CIR: %[[GET_J:.*]] = cir.get_member %[[GET_A]][1] {name = "j"} : !cir.ptr<![[STRUCT_A]]> -> !cir.ptr<!cir.double>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CIR: %[[ONE_F:.*]] = cir.cast int_to_float %[[ONE]] : !s32i -> !cir.double
// CIR: cir.store align(8) %[[ONE_F]], %[[GET_J]] : !cir.double, !cir.ptr<!cir.double>
// CIR: %[[GET_B:.*]] = cir.get_member %[[D_ALLOCA]][1] {name = "b"} : !cir.ptr<![[STRUCT_D]]> -> !cir.ptr<![[STRUCT_A]]>
// CIR: %[[GET_I:.*]] = cir.get_member %[[GET_B]][0] {name = "i"} : !cir.ptr<![[STRUCT_A]]> -> !cir.ptr<!s8i>
// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s8i
// CIR: cir.store align(8) %[[TWO]], %[[GET_I]] : !s8i, !cir.ptr<!s8i>
// CIR: %[[GET_J:.*]] = cir.get_member %[[GET_B]][1] {name = "j"} : !cir.ptr<![[STRUCT_A]]> -> !cir.ptr<!cir.double>
// CIR: %[[FP_2:.*]] = cir.const #cir.fp<2
// CIR: cir.store align(8) %[[FP_2]], %[[GET_J]] : !cir.double, !cir.ptr<!cir.double>
// CIR: %[[GET_C:.*]] = cir.get_member %[[D_ALLOCA]][3] {name = "c"} : !cir.ptr<![[STRUCT_D]]> -> !cir.ptr<![[STRUCT_A]]>
// CIR: %[[ZERO:.*]] = cir.const #cir.zero : ![[STRUCT_A]]
// CIR: cir.store align(8) %[[ZERO]], %[[GET_C]] : ![[STRUCT_A]], !cir.ptr<![[STRUCT_A]]>
void foo9() {
D d(A(1, 1));
}
// LLVM: define dso_local noundef ptr @{{.*foo10.*}}()
// FIXME: CIR lowering has an extra load here.
// CIR-LABEL: cir.func no_inline dso_local @_Z5foo10v()
// CIR: %[[RET_ALLOCA:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["__retval"] {alignment = 8 : i64}
// CIR: %[[GET_GLOB:.*]] = cir.get_global @_ZL4arr1 : !cir.ptr<!cir.array<!s32i x 3>>
// CIR: %[[GLOB_DECAY:.*]] = cir.cast array_to_ptrdecay %[[GET_GLOB]] : !cir.ptr<!cir.array<!s32i x 3>> -> !cir.ptr<!s32i>
// CIR: cir.store %[[GLOB_DECAY]], %[[RET_ALLOCA]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
const int* foo10() {
return arr1;
}
// LLVM: define dso_local void @{{.*foo11.*}}
// LLVM: [[A_ADDR:%.*]] = alloca i32
// LLVM-NEXT: [[B_ADDR:%.*]] = alloca i32
// LLVM-NEXT: [[ARR_2:%.*]] = alloca [4 x i32]
// LLVM: [[TMP_0:%.*]] = load i32, ptr [[A_ADDR]], align 4
// FIXME: CIR does an additional GEP here to decay the type.
// LLVM: store i32 [[TMP_0]], ptr {{.*}}, align 4
// LLVM-NEXT: [[ARRINIT_ELEM:%.*]] = getelementptr {{.*}}i32, ptr {{.*}}, i64 1
// LLVM-NEXT: [[TMP_1:%.*]] = load i32, ptr [[B_ADDR]], align 4
// FXIME: CIR calculates this via offset from the above ARRINIT_ELEM, not the 0th element.
// LLVM-NEXT: store i32 [[TMP_1]], ptr [[ARRINIT_ELEM]], align 4
// LLVM: [[ARRINIT_START:%.*]] = getelementptr {{.*}}i32, ptr {{.*}}, i64 {{.*}}
// LLVM: [[ARRINIT_END:%.*]] = getelementptr {{.*}}i32, ptr {{.*}}, i64 4
// LLVM-NEXT: br label [[ARRINIT_BODY:%.*]]
// LLVM: [[ARRINIT_DONE:%.*]] = icmp {{.*}} ptr
// LLVM-NEXT: br i1 [[ARRINIT_DONE]], label
// LLVM: ret void
// CIR-LABEL: cir.func no_inline dso_local @_Z5foo11ii
// CIR: %[[A_ALLOCA:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init] {alignment = 4 : i64}
// CIR: %[[B_ALLOCA:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["b", init] {alignment = 4 : i64}
// CIR: %[[ARR2_ALLOCA:.*]] = cir.alloca !cir.array<!s32i x 4>, !cir.ptr<!cir.array<!s32i x 4>>, ["arr2", init] {alignment = 16 : i64}
// CIR: %[[ARR_ITR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["arrayinit.temp", init] {alignment = 8 : i64}
// CIR: %[[ARR2_DECAY:.*]] = cir.cast array_to_ptrdecay %[[ARR2_ALLOCA]] : !cir.ptr<!cir.array<!s32i x 4>> -> !cir.ptr<!s32i>
// CIR: %[[A_LOAD:.*]] = cir.load align(4) %[[A_ALLOCA]] : !cir.ptr<!s32i>, !s32i
// CIR: cir.store align(4) %[[A_LOAD]], %[[ARR2_DECAY]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i
// CIR: %[[ELT1:.*]] = cir.ptr_stride %[[ARR2_DECAY]], %[[ONE]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i>
// CIR: %[[B_LOAD:.*]] = cir.load align(4) %[[B_ALLOCA]] : !cir.ptr<!s32i>, !s32i
// CIR: cir.store align(4) %[[B_LOAD]], %[[ELT1]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i
// CIR: %[[ELT2:.*]] = cir.ptr_stride %[[ELT1]], %[[ONE]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i>
// CIR: cir.store align(8) %[[ELT2]], %[[ARR_ITR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
// CIR: %[[FOUR:.*]] = cir.const #cir.int<4> : !s64i
// CIR: %[[END_ITR:.*]] = cir.ptr_stride %[[ARR2_DECAY]], %[[FOUR]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i>
// CIR: cir.do {
// CIR: %[[ARR_ITR_LOAD:.*]] = cir.load align(8) %[[ARR_ITR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
// CIR: cir.store align(4) %[[ZERO]], %[[ARR_ITR_LOAD]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i
// CIR: %[[NEXT_ITR:.*]] = cir.ptr_stride %[[ARR_ITR_LOAD]], %[[ONE]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i>
// CIR: cir.store align(8) %[[NEXT_ITR]], %[[ARR_ITR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
// CIR: cir.yield
// CIR: } while {
// CIR: %[[ARR_ITR_LOAD:.*]] = cir.load align(8) %[[ARR_ITR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
// CIR: %[[DONE:.*]] = cir.cmp ne %[[ARR_ITR_LOAD]], %[[END_ITR]] : !cir.ptr<!s32i>
// CIR: cir.condition(%[[DONE]])
// CIR: }
void foo11(int a, int b) {
int arr2[4](a, b);
}
// LLVM: define dso_local void @{{.*foo12.*}}
// LLVM: [[A_ADDR:%.*]] = alloca i32
// LLVM-NEXT: [[B_ADDR:%.*]] = alloca i32
// LLVM-NEXT: [[ARR_3:%.*]] = alloca [2 x i32]
// LLVM-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
// LLVM-NEXT: store i32 [[B:%.*]], ptr [[B_ADDR]], align 4
// LLVM: [[TMP_0:%.*]] = load i32, ptr [[A_ADDR]], align 4
// LLVM-NEXT: store i32 [[TMP_0]], ptr {{.*}}, align 4
// LLVM-NEXT: [[ARRINIT_ELEMENT:%.*]] = getelementptr {{.*}}i32, ptr {{.*}}, i64 1
// LLVM-NEXT: [[TMP_1:%.*]] = load i32, ptr [[B_ADDR]], align 4
// LLVM-NEXT: store i32 [[TMP_1]], ptr [[ARRINIT_ELEMENT]], align 4
// LLVM-NEXT: ret void
// CIR-LABEL: cir.func no_inline dso_local @_Z5foo12ii
// CIR: %[[A_ALLOCA:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init] {alignment = 4 : i64}
// CIR: %[[B_ALLOCA:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["b", init] {alignment = 4 : i64}
// CIR: %[[ARR3_ALLOCA:.*]] = cir.alloca !cir.array<!s32i x 2>, !cir.ptr<!cir.array<!s32i x 2>>, ["arr3", init] {alignment = 4 : i64}
// CIR: %[[ARR_DECAY:.*]] = cir.cast array_to_ptrdecay %[[ARR3_ALLOCA]] : !cir.ptr<!cir.array<!s32i x 2>> -> !cir.ptr<!s32i>
// CIR: %[[A_LOAD:.*]] = cir.load align(4) %[[A_ALLOCA]] : !cir.ptr<!s32i>, !s32i
// CIR: cir.store align(4) %[[A_LOAD]], %[[ARR_DECAY]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i
// CIR: %[[ELT_1:.*]] = cir.ptr_stride %[[ARR_DECAY]], %[[ONE]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i>
// CIR: %[[B_LOAD:.*]] = cir.load align(4) %[[B_ALLOCA]] : !cir.ptr<!s32i>, !s32i
// CIR: cir.store align(4) %[[B_LOAD]], %[[ELT_1]] : !s32i, !cir.ptr<!s32i>
void foo12(int a, int b) {
int arr3[](a, b);
}
// LLVM: define {{.*}}@{{.*foo13.*}}
// LLVM: [[RETVAL:%.*]] = alloca [[STRUCT_A]]
// LLVM-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr {{.*}}[[RETVAL]], ptr {{.*}}[[A2]], i64 16, i1 false)
// LLVM-NEXT: [[TMP_0:%.*]] = load {{.*}}, ptr [[RETVAL]], align 8
// LLVM-NEXT: ret {{.*}}[[TMP_0]]
// CIR-LABEL: cir.func no_inline dso_local @_Z5foo13v()
// CIR: %[[RET_ALLOCA:.*]] = cir.alloca ![[STRUCT_A]], !cir.ptr<![[STRUCT_A]]>, ["__retval"] {alignment = 8 : i64}
// CIR; %[[GET_GLOB:.*]] = cir.get_global @_ZL2a2 : !cir.ptr<![[STRUCT_A]]>
// CIR; cir.copy %[[GET_GLOB]] to %[[RET_ALLOCA]] : !cir.ptr<![[STRUCT_A]]>
A foo13() {
return a2;
}
// LLVM: define dso_local noundef ptr @{{.*foo14.*}}()
// LLVM: ret ptr
// CIR-LABEL: cir.func no_inline dso_local @_Z5foo14v()
// CIR: %[[RET_ALLOCA:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["__retval"] {alignment = 8 : i64}
// CIR: %[[GET_GLOB:.*]] = cir.get_global @_ZL4arr4 : !cir.ptr<!cir.array<!s32i x 1>>
// CIR: %[[GLOB_DECAY]] = cir.cast array_to_ptrdecay %[[GET_GLOB]] : !cir.ptr<!cir.array<!s32i x 1>> -> !cir.ptr<!s32i>
// CIR: cir.store %[[GLOB_DECAY]], %[[RET_ALLOCA]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
const int* foo14() {
return arr4;
}
// LLVM: define dso_local noundef ptr @{{.*foo15.*}}()
// LLVM: ret ptr
// CIR-LABEL: cir.func {{.*}}@_Z5foo15v()
// CIR: %[[RET_ALLOCA:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["__retval"] {alignment = 8 : i64}
// CIR: %[[GET_GLOB:.*]] = cir.get_global @_ZL4arr5 : !cir.ptr<!cir.array<!s32i x 2>>
// CIR: %[[GLOB_DECAY:.*]] = cir.cast array_to_ptrdecay %[[GET_GLOB]] : !cir.ptr<!cir.array<!s32i x 2>> -> !cir.ptr<!s32i>
// CIR: cir.store %[[GLOB_DECAY]], %[[RET_ALLOCA]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
const int* foo15() {
return arr5;
}
// LLVM: define dso_local void @{{.*foo16.*}}
// LLVM-DAG: [[ARR_6:%.*]] = alloca ptr
// LLVM-DAG: [[REF_TMP:%.*]] = alloca [1 x i32]
// LLVM: store i32 3, ptr {{.*}}, align 4
// LLVM-NEXT: store ptr [[REF_TMP]], ptr [[ARR_6]], align 8
// LLVM-NEXT: ret void
// CIR-LABEL: cir.func no_inline dso_local @_Z5foo16v()
// CIR: %[[TEMP_ALLOCA:.*]] = cir.alloca !cir.array<!s32i x 1>, !cir.ptr<!cir.array<!s32i x 1>>, ["ref.tmp0"] {alignment = 4 : i64}
// CIR: %[[ARR6_ALLOCA:.*]] = cir.alloca !cir.ptr<!cir.array<!s32i x 0>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 0>>>, ["arr6", init, const] {alignment = 8 : i64}
// CIR: %[[TEMP_DECAY:.*]] = cir.cast array_to_ptrdecay %[[TEMP_ALLOCA]] : !cir.ptr<!cir.array<!s32i x 1>> -> !cir.ptr<!s32i>
// CIR: %[[THREE:.*]] = cir.const #cir.int<3> : !s32i
// CIR: cir.store align(4) %[[THREE]], %[[TEMP_DECAY]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[TEMP_CAST:.*]] = cir.cast bitcast %[[TEMP_ALLOCA]] : !cir.ptr<!cir.array<!s32i x 1>> -> !cir.ptr<!cir.array<!s32i x 0>>
// CIR: cir.store align(8) %[[TEMP_CAST]], %[[ARR6_ALLOCA]] : !cir.ptr<!cir.array<!s32i x 0>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 0>>>
void foo16() {
int (&&arr6)[] = static_cast<int[]>(3);
}
// LLVM: define dso_local void @{{.*foo17.*}}
// LLVM-DAG: [[ARR_7:%.*]] = alloca ptr
// LLVM-DAG: [[REF_TMP:%.*]] = alloca [2 x i32]
// LLVM: store i32 4, ptr {{.*}}, align 4
// LLVM-NEXT: [[ARRINIT_START:%.*]] = getelementptr {{.*}}i32, ptr {{.*}}, i64 1
// LLVM: [[ARRINIT_END:%.*]] = getelementptr {{.*}}i32, ptr {{.*}}, i64 2
// LLVM: br label
// LLVM: [[ARRINIT_DONE:%.*]] = icmp {{.*}} ptr
// LLVM-NEXT: br i1 [[ARRINIT_DONE]], label
// LLVM: store ptr [[REF_TMP]], ptr [[ARR_7]], align 8
// LLVM: ret void
// CIR-LABEL: cir.func no_inline dso_local @_Z5foo17v()
// CIR: %[[ARR_TEMP:.*]] = cir.alloca !cir.array<!s32i x 2>, !cir.ptr<!cir.array<!s32i x 2>>, ["ref.tmp0"] {alignment = 4 : i64}
// CIR: %[[ARR7_ALLOCA:.*]] = cir.alloca !cir.ptr<!cir.array<!s32i x 2>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 2>>>, ["arr7", init, const] {alignment = 8 : i64}
// CIR: %[[ITR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["arrayinit.temp", init] {alignment = 8 : i64}
// CIR: %[[TEMP_LOAD:.*]] = cir.cast array_to_ptrdecay %[[ARR_TEMP]] : !cir.ptr<!cir.array<!s32i x 2>> -> !cir.ptr<!s32i>
// CIR: %[[FOUR:.*]] = cir.const #cir.int<4> : !s32i
// CIR: cir.store align(4) %[[FOUR]], %[[TEMP_LOAD]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i
// CIR: %[[ELT1:.*]] = cir.ptr_stride %[[TEMP_LOAD]], %[[ONE]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i>
// CIR: cir.store align(8) %[[ELT1]], %[[ITR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s64i
// CIR: %[[END_ITR:.*]] = cir.ptr_stride %[[TEMP_LOAD]], %[[TWO]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i>
// CIR: cir.do {
// CIR: %[[ITR_LOAD:.*]] = cir.load align(8) %[[ITR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
// CIR: cir.store align(4) %[[ZERO]], %[[ITR_LOAD]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i
// CIR: %[[NEXT_ITR:.*]] = cir.ptr_stride %[[ITR_LOAD]], %[[ONE]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i>
// CIR: cir.store align(8) %[[NEXT_ITR]], %[[ITR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
// CIR: cir.yield
// CIR: } while {
// CIR: %[[ITR_LOAD:.*]] = cir.load align(8) %[[ITR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
// CIR: %[[COND:.*]] = cir.cmp ne %[[ITR_LOAD]], %[[END_ITR]] : !cir.ptr<!s32i>
// CIR: cir.condition(%[[COND]])
// CIR: }
// CIR: cir.store align(8) %[[ARR_TEMP]], %[[ARR7_ALLOCA]] : !cir.ptr<!cir.array<!s32i x 2>>, !cir.ptr<!cir.ptr<!cir.array<!s32i x 2>>>
void foo17() {
int (&&arr7)[2] = static_cast<int[2]>(4);
}
// LLVM: define dso_local void @{{.*foo18.*}}
// LLVM: [[E:%.*]] = alloca [[STRUCT_E]]
// LLVM-NEXT: [[A:%.*]] = getelementptr {{.*}}[[STRUCT_E]], ptr [[E]], i32 0, i32 0
// LLVM-NEXT: store i32 1, ptr [[A]], align 8
// LLVM-NEXT: [[FN:%.*]] = getelementptr {{.*}}[[STRUCT_E]], ptr [[E]], i32 0, i32 1
// LLVM-NEXT: store ptr [[STR]], ptr [[FN]], align 8
// LLVM: ret void
// CIR: cir.func {{.*}}@_Z5foo18v()
// CIR: %[[E_ALLOCA:.*]] = cir.alloca ![[STRUCT_E]], !cir.ptr<![[STRUCT_E]]>, ["e", init]
// CIR: %[[GET_A:.*]] = cir.get_member %[[E_ALLOCA]][0] {name = "a"} : !cir.ptr<![[STRUCT_E]]> -> !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CIR: cir.store{{.*}} %[[ONE]], %[[GET_A]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[GET_FN:.*]] = cir.get_member %[[E_ALLOCA]][1] {name = "fn"} : !cir.ptr<![[STRUCT_E]]> -> !cir.ptr<!cir.ptr<!s8i>>
// CIR: %[[GET_STR:.*]] = cir.const #cir.global_view<@
// CIR: cir.store{{.*}} %[[GET_STR]], %[[GET_FN]] : !cir.ptr<!s8i>, !cir.ptr<!cir.ptr<!s8i>>
void foo18() {
E e(1);
}
// LLVM: define dso_local void @{{.*foo19.*}}
// LLVM: [[G:%.*]] = alloca [[STRUCT_G]]
// LLVM-NEXT: [[A:%.*]] = getelementptr {{.*}}[[STRUCT_G]], ptr [[G]], i32 0, i32 0
// LLVM-NEXT: store i32 2, ptr [[A]], align 4
// LLVM-NEXT: [[F:%.*]] = getelementptr {{.*}}i8, ptr [[G]], i64 4
// LLVM-NEXT: call void @{{.*F.*}}(ptr noundef nonnull align 1 dereferenceable(1) [[F]], i32 noundef 1)
// LLVM: ret void
// CIR: cir.func no_inline dso_local @_Z5foo19v() attributes {{{.*}}nothrow} {
// CIR: %[[G_ALLOCA:.*]] = cir.alloca ![[STRUCT_G]], !cir.ptr<![[STRUCT_G]]>, ["g", init]
// CIR: %[[GET_A:.*]] = cir.get_member %[[G_ALLOCA]][0] {name = "a"} : !cir.ptr<![[STRUCT_G]]> -> !cir.ptr<!s32i>
// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s32i
// CIR: cir.store{{.*}} %[[TWO]], %[[GET_A]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[G_TO_CHAR:.*]] = cir.cast bitcast %[[G_ALLOCA]] : !cir.ptr<![[STRUCT_G]]> -> !cir.ptr<!u8i>
// CIR: %[[FOUR:.*]] = cir.const #cir.int<4> : !u64i
// CIR: %[[F_OFFSET:.*]] = cir.ptr_stride %[[G_TO_CHAR]], %[[FOUR]] : (!cir.ptr<!u8i>, !u64i) -> !cir.ptr<!u8i>
// CIR: %[[F:.*]] = cir.cast bitcast %[[F_OFFSET]] : !cir.ptr<!u8i> -> !cir.ptr<![[STRUCT_F]]>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CIR: cir.call @_ZN1FC1Ei(%[[F]], %[[ONE]])
void foo19() {
G g(2);
}
namespace gh61145 {
// a.k.a. void make1<0>()
// LLVM: define {{.*}} void @_ZN7gh611455make1ILi0EEEvv
// LLVM-DAG: [[V:%.*]] = alloca [[STRUCT_VEC]]
// LLVM-DAG: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_S1]]
// a.k.a. Vec::Vec()
// LLVM-NEXT: call void @_ZN7gh611453VecC1Ev(ptr {{.*}}[[V]])
// a.k.a. Vec::Vec(Vec&&)
// LLVM: call void @_ZN7gh611453VecC1EOS0_(ptr {{.*}}[[AGG_TMP_ENSURED]], ptr {{.*}}[[V]])
// a.k.a. S1::~S1()
// LLVM: call void @_ZN7gh611452S1D1Ev(ptr {{.*}}[[AGG_TMP_ENSURED]])
// a.k.a.Vec::~Vec()
// LLVM: call void @_ZN7gh611453VecD1Ev(ptr {{.*}}[[V]])
// LLVM: ret void
// CIR-LABEL: cir.func {{.*}}@_ZN7gh611455make1ILi0EEEvv()
// CIR: %[[V_ALLOCA:.*]] = cir.alloca ![[STRUCT_VEC]], !cir.ptr<![[STRUCT_VEC]]>, ["v", init] {alignment = 1 : i64}
// CIR: %[[TMP_ALLOCA:.*]] = cir.alloca ![[STRUCT_S1]], !cir.ptr<![[STRUCT_S1]]>, ["agg.tmp.ensured"]
// CIR: cir.call @_ZN7gh611453VecC1Ev(%[[V_ALLOCA]])
// CIR: %[[S1_TO_VEC:.*]] = cir.cast bitcast %[[TMP_ALLOCA]] : !cir.ptr<![[STRUCT_S1]]> -> !cir.ptr<![[STRUCT_VEC]]>
// CIR: cir.call @_ZN7gh611453VecC1EOS0_(%[[S1_TO_VEC]], %[[V_ALLOCA]])
// CIR: cir.call @_ZN7gh611452S1D1Ev(
// CIR: cir.call @_ZN7gh611453VecD1Ev(
template <int I>
void make1() {
Vec v;
S1((Vec&&) v);
}
// a.k.a. void make2<0>()
// LLVM: define {{.*}} void @_ZN7gh611455make2ILi0EEEvv
// LLVM-DAG: [[V:%.*]] = alloca [[STRUCT_VEC]]
// LLVM-DAG: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_S2]]
// a.k.a. Vec::Vec()
// LLVM: call void @_ZN7gh611453VecC1Ev(ptr {{.*}}[[V]])
// a.k.a. Vec::Vec(Vec&&)
// LLVM: call void @_ZN7gh611453VecC1EOS0_(ptr {{.*}}[[AGG_TMP_ENSURED]], ptr {{.*}}[[V]])
// LLVM-NEXT: [[C:%.*]] = getelementptr {{.*}}[[STRUCT_S2]], ptr [[AGG_TMP_ENSURED]], i32 0, i32
// LLVM-NEXT: store i8 0, ptr [[C]], align 1
// a.k.a. S2::~S2()
// LLVM: call void @_ZN7gh611452S2D1Ev(ptr {{.*}}[[AGG_TMP_ENSURED]])
// a.k.a. Vec::~Vec()
// LLVM: call void @_ZN7gh611453VecD1Ev(ptr {{.*}}[[V]])
// LLVM: ret void
// CIR-LABEL: cir.func {{.*}}@_ZN7gh611455make2ILi0EEEvv()
// CIR: %[[V_ALLOCA:.*]] = cir.alloca ![[STRUCT_VEC]], !cir.ptr<![[STRUCT_VEC]]>, ["v", init] {alignment = 1 : i64}
// CIR: %[[TMP_ALLOCA:.*]] = cir.alloca ![[STRUCT_S2]], !cir.ptr<![[STRUCT_S2]]>, ["agg.tmp.ensured"]
// CIR: cir.call @_ZN7gh611453VecC1Ev(%[[V_ALLOCA]])
// CIR: %[[S2_TO_VEC:.*]] = cir.cast bitcast %[[TMP_ALLOCA]] : !cir.ptr<![[STRUCT_S2]]> -> !cir.ptr<![[STRUCT_VEC]]>
// CIR: cir.call @_ZN7gh611453VecC1EOS0_(%[[S2_TO_VEC]], %[[V_ALLOCA]])
// CIR: %[[GET_C:.*]] = cir.get_member %[[TMP_ALLOCA]][1] {name = "c"} : !cir.ptr<![[STRUCT_S2]]> -> !cir.ptr<!s8i>
// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s8i
// CIR: cir.store{{.*}} %[[ZERO]], %[[GET_C]] : !s8i, !cir.ptr<!s8i>
template <int I>
void make2() {
Vec v;
S2((Vec&&) v, 0);
}
void foo() {
make1<0>();
make2<0>();
}
}
namespace gh62266 {
// LLVM: define {{.*}} void {{.*foo20.*}}
// LLVM: [[H:%.*]] = alloca [[STRUCT_H]]
// LLVM-NEXT: [[I:%.*]] = getelementptr {{.*}}[[STRUCT_H]], ptr [[H]], i32 0, i32 0
// LLVM-NEXT: store i32 1, ptr [[I]], align 4
// LLVM-NEXT: [[J:%.*]] = getelementptr {{.*}}[[STRUCT_H]], ptr [[H]], i32 0, i32 1
// LLVM-NEXT: store i32 2, ptr [[J]], align 4
// LLVM-NEXT: ret void
// CIR-LABEL: cir.func {{.*}}@_ZN7gh622665foo20Ev()
// CIR: %[[TMP_ALLOCA:.*]] = cir.alloca ![[STRUCT_H]], !cir.ptr<![[STRUCT_H]]>, ["h", init]
// CIR: %[[GET_I:.*]] = cir.get_member %[[TMP_ALLOCA]][0] {name = "i"} : !cir.ptr<![[STRUCT_H]]> -> !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CIR: cir.store{{.*}} %[[ONE]], %[[GET_I]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[GET_J:.*]] = cir.get_member %[[TMP_ALLOCA]][1] {name = "j"} : !cir.ptr<![[STRUCT_H]]> -> !cir.ptr<!s32i>
// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s32i
// CIR: cir.store{{.*}} %[[TWO]], %[[GET_J]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.return
void foo20() {
H<2> h(1);
}
}
namespace gh61567 {
int foo20();
// LLVM: define {{.*}} void @{{.*foo21.*}} {
// LLVM: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_I]]
// LLVM-NEXT: [[REF_TMP:%.*]] = alloca i32
// LLVM: [[A:%.*]] = getelementptr {{.*}}[[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0
// LLVM-NEXT: store i32 0, ptr [[A]], align 8
// LLVM-NEXT: [[R:%.*]] = getelementptr {{.*}}[[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 1
// LLVM-NEXT: store i32 1, ptr [[REF_TMP]], align 4
// LLVM-NEXT: store ptr [[REF_TMP]], ptr [[R]], align 8
// LLVM: ret void
// CIR-LABEL: cir.func {{.*}}@_ZN7gh615675foo21Ev()
// CIR: %[[TMP_ALLOCA:.*]] = cir.alloca ![[STRUCT_I]], !cir.ptr<![[STRUCT_I]]>, ["agg.tmp.ensured"]
// CIR: %[[INT_TMP:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["ref.tmp0"]
// CIR: %[[GET_A:.*]] = cir.get_member %[[TMP_ALLOCA]][0] {name = "a"} : !cir.ptr<![[STRUCT_I]]> -> !cir.ptr<!s32i>
// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
// CIR: cir.store{{.*}} %[[ZERO]], %[[GET_A]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[GET_R:.*]] = cir.get_member %[[TMP_ALLOCA]][1] {name = "r"} : !cir.ptr<![[STRUCT_I]]> -> !cir.ptr<!cir.ptr<!s32i>>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CIR: cir.store{{.*}} %[[ONE]], %[[INT_TMP]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.store{{.*}} %[[INT_TMP]], %[[GET_R]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
void foo21() {
I(0, 1);
}
// LLVM: define {{.*}} void @{{.*foo22.*}} {
// LLVM: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_I]]
// LLVM-NEXT: [[REF_TMP:%.*]] = alloca i32
// LLVM: [[A:%.*]] = getelementptr {{.*}}[[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0
// LLVM-NEXT: store i32 0, ptr [[A]], align 8
// LLVM-NEXT: [[R:%.*]] = getelementptr {{.*}}[[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 1
// LLVM-NEXT: [[CALL:%.*]] = call noundef i32 @{{.*foo20.*}}
// LLVM-NEXT: store i32 [[CALL]], ptr [[REF_TMP]], align 4
// LLVM-NEXT: store ptr [[REF_TMP]], ptr [[R]], align 8
// LLVM: ret void
// CIR-LABEL: cir.func {{.*}}@_ZN7gh615675foo22Ev()
// CIR: %[[TMP_ALLOCA:.*]] = cir.alloca ![[STRUCT_I]], !cir.ptr<![[STRUCT_I]]>, ["agg.tmp.ensured"]
// CIR: %[[INT_TMP:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["ref.tmp0"]
// CIR: %[[GET_A:.*]] = cir.get_member %[[TMP_ALLOCA]][0] {name = "a"} : !cir.ptr<![[STRUCT_I]]> -> !cir.ptr<!s32i>
// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
// CIR: cir.store{{.*}} %[[ZERO]], %[[GET_A]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[GET_R:.*]] = cir.get_member %[[TMP_ALLOCA]][1] {name = "r"} : !cir.ptr<![[STRUCT_I]]> -> !cir.ptr<!cir.ptr<!s32i>>
// CIR: %[[GET_CALL:.*]] = cir.call @_ZN7gh615675foo20Ev() : () -> (!s32i {llvm.noundef})
// CIR: cir.store{{.*}} %[[GET_CALL]], %[[INT_TMP]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.store{{.*}} %[[INT_TMP]], %[[GET_R]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
void foo22() {
I(0, foo20());
}
// LLVM: define {{.*}} void @{{.*foo23.*}}
// LLVM: [[I_ADDR:%.*]] = alloca i32
// LLVM-NEXT: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_I]]
// LLVM: [[A:%.*]] = getelementptr {{.*}}[[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0
// LLVM-NEXT: store i32 0, ptr [[A]], align 8
// LLVM-NEXT: [[R:%.*]] = getelementptr {{.*}}[[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 1
// LLVM-NEXT: store ptr [[I_ADDR]], ptr [[R]], align 8
// LLVM-NEXT: ret void
// CIR-LABEL: cir.func no_inline dso_local @_ZN7gh615675foo23Ei(%arg0: !s32i {llvm.noundef}
// CIR: %[[I_ALLOCA:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init]
// CIR: %[[TMP_ALLOCA:.*]] = cir.alloca ![[STRUCT_I]], !cir.ptr<![[STRUCT_I]]>, ["agg.tmp.ensured"]
// CIR: %[[GET_A:.*]] = cir.get_member %[[TMP_ALLOCA]][0] {name = "a"} : !cir.ptr<![[STRUCT_I]]> -> !cir.ptr<!s32i>
// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
// CIR: cir.store{{.*}} %[[ZERO]], %[[GET_A]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[GET_R:.*]] = cir.get_member %[[TMP_ALLOCA]][1] {name = "r"} : !cir.ptr<![[STRUCT_I]]> -> !cir.ptr<!cir.ptr<!s32i>>
// CIR: cir.store{{.*}} %[[I_ALLOCA]], %[[GET_R]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
void foo23(int i) {
I(0, static_cast<int&&>(i));
}
// LLVM: define {{.*}} void @{{.*foo24.*}} {
// LLVM: [[AGG_TMP_ENSURED:%.*]] = alloca [[STRUCT_I]]
// LLVM-NEXT: [[REF_TMP:%.*]] = alloca i32
// LLVM-NEXT: [[A:%.*]] = getelementptr {{.*}}[[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 0
// LLVM-NEXT: store i32 0, ptr [[A]], align 8
// LLVM-NEXT: [[R:%.*]] = getelementptr {{.*}}[[STRUCT_I]], ptr [[AGG_TMP_ENSURED]], i32 0, i32 1
// LLVM-NEXT: store i32 2, ptr [[REF_TMP]], align 4
// LLVM-NEXT: store ptr [[REF_TMP]], ptr [[R]], align 8
// LLVM-NEXT: ret void
// CIR-LABEL: cir.func {{.*}}@_ZN7gh615675foo24Ev()
// CIR: %[[TMP_ALLOCA:.*]] = cir.alloca ![[STRUCT_I]], !cir.ptr<![[STRUCT_I]]>, ["agg.tmp.ensured"]
// CIR: %[[INT_TMP:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["ref.tmp0"]
// CIR: %[[GET_A:.*]] = cir.get_member %[[TMP_ALLOCA:.*]][0] {name = "a"} : !cir.ptr<![[STRUCT_I]]> -> !cir.ptr<!s32i>
// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !s32i
// CIR: cir.store{{.*}} %[[ZERO]], %[[GET_A]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[GET_R:.*]] = cir.get_member %[[TMP_ALLOCA:.*]][1] {name = "r"} : !cir.ptr<![[STRUCT_I]]> -> !cir.ptr<!cir.ptr<!s32i>>
// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s32i
// CIR: cir.store{{.*}} %[[TWO]], %[[INT_TMP]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.store{{.*}} %[[INT_TMP]], %[[GET_R]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
void foo24() {
I(0);
}
}
namespace gh68198 {
// LLVM: define {{.*}} void @{{.*foo25.*}} {
// LLVM: [[ARR_8:%.*]] = alloca ptr
// LLVM-NEXT: [[CALL_PTR:%.*]] = call {{.*}}nonnull ptr @_Znam(i64 noundef 8)
// LLVM-NEXT: store i32 1, ptr [[CALL_PTR]], align 4
// LLVM-NEXT: [[ARRAY_EXP_NEXT:%.*]] = getelementptr {{.*}}i32, ptr [[CALL_PTR]], i64 1
// LLVM-NEXT: store i32 2, ptr [[ARRAY_EXP_NEXT]], align 4
// LLVM-NEXT: [[ARRAY_EXP_NEXT1:%.*]] = getelementptr {{.*}}i32, ptr [[ARRAY_EXP_NEXT]], i64 1
// LLVM-NEXT: store ptr [[CALL_PTR]], ptr [[ARR_8]], align 8
// LLVM-NEXT: ret void
// CIR-LABEL: cir.{{.*}}@_ZN7gh681985foo25Ev()
// CIR: %[[ARR_ALLOCA:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["arr8", init] {alignment = 8 : i64}
// CIR: %[[SIZE:.*]] = cir.const #cir.int<8> : !u64i
// CIR: %[[ALLOC:.*]] = cir.call @_Znam(%[[SIZE]]) {allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> (!cir.ptr<!void> {llvm.nonnull, llvm.noundef})
// CIR: %[[ALLOC_TO_ARR:.*]] = cir.cast bitcast %[[ALLOC]] : !cir.ptr<!void> -> !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CIR: cir.store{{.*}} %[[ONE]], %[[ALLOC_TO_ARR]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CIR: %[[ELT1:.*]] = cir.ptr_stride %[[ALLOC_TO_ARR]], %[[ONE]] : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s32i
// CIR: cir.store{{.*}} %[[TWO]], %[[ELT1]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CIR: %[[ELT2:.*]] = cir.ptr_stride %[[ELT1]], %[[ONE]] : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
// CIR: cir.store{{.*}} %[[ALLOC_TO_ARR]], %[[ARR_ALLOCA]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
void foo25() {
int* arr8 = new int[](1, 2);
}
// LLVM: define {{.*}} void @{{.*foo26.*}} {
// LLVM: [[ARR_10:%.*]] = alloca ptr
// LLVM-NEXT: [[CALL_PTR]] = call {{.*}}nonnull ptr @_Znam(i64 noundef 16)
// LLVM: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr {{.*}}i32, ptr {{.*}}, i64 1
// LLVM-NEXT: store i32 2, ptr [[ARRAYINIT_ELEMENT]], align 4
// LLVM-NEXT: [[ARRAY_EXP_NEXT:%.*]] = getelementptr {{.*}}[2 x i32], ptr {{.*}}, i64 1
// LLVM: store i32 3, ptr {{.*}}, align 4
// LLVM-NEXT: [[ARRAYINIT_ELEMENT2:%.*]] = getelementptr {{.*}}i32, ptr {{.*}}, i64 1
// LLVM-NEXT: store i32 4, ptr [[ARRAYINIT_ELEMENT2]], align 4
// LLVM-NEXT: [[ARRAY_EXP_NEXT3:%.*]] = getelementptr {{.*}}[2 x i32], ptr [[ARRAY_EXP_NEXT]], i64 1
// LLVM-NEXT: store ptr [[CALL_PTR]], ptr [[ARR_10]], align 8
// LLVM-NEXT: ret void
// CIR-LABEL: cir.{{.*}}@_ZN7gh681985foo26Ev()
// CIR: %[[ARR_ALLOCA:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["arr9", init] {alignment = 8 : i64}
// CIR: %[[SIZE:.*]] = cir.const #cir.int<16> : !u64i
// CIR: %[[ALLOC:.*]] = cir.call @_Znam(%[[SIZE]]) {allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> (!cir.ptr<!void> {llvm.nonnull, llvm.noundef})
// CIR: %[[ALLOC_TO_ARR:.*]] = cir.cast bitcast %[[ALLOC]] : !cir.ptr<!void> -> !cir.ptr<!cir.array<!s32i x 2>>
// CIR: %[[ELT0_0:.*]] = cir.cast array_to_ptrdecay %[[ALLOC_TO_ARR]] : !cir.ptr<!cir.array<!s32i x 2>> -> !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CIR: cir.store{{.*}} %[[ONE]], %[[ELT0_0]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i
// CIR: %[[ELT0_1:.*]] = cir.ptr_stride %[[ELT0_0]], %[[ONE]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i>
// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s32i
// CIR: cir.store{{.*}} %[[TWO]], %[[ELT0_1]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CIR: %[[ELT1:.*]] = cir.ptr_stride %[[ALLOC_TO_ARR]], %[[ONE]] : (!cir.ptr<!cir.array<!s32i x 2>>, !s32i) -> !cir.ptr<!cir.array<!s32i x 2>>
// CIR: %[[ELT1_0:.*]] = cir.cast array_to_ptrdecay %[[ELT1]] : !cir.ptr<!cir.array<!s32i x 2>> -> !cir.ptr<!s32i>
// CIR: %[[THREE:.*]] = cir.const #cir.int<3> : !s32i
// CIR: cir.store{{.*}} %[[THREE]], %[[ELT1_0]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i
// CIR: %[[ELT1_1:.*]] = cir.ptr_stride %[[ELT1_0]], %[[ONE]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i>
// CIR: %[[FOUR:.*]] = cir.const #cir.int<4> : !s32i
// CIR: cir.store{{.*}} %[[FOUR]], %[[ELT1_1]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CIR: %[[ELT2:.*]] = cir.ptr_stride %[[ELT1]], %[[ONE]] : (!cir.ptr<!cir.array<!s32i x 2>>, !s32i) -> !cir.ptr<!cir.array<!s32i x 2>>
// CIR: %[[ARR_TO_VOID:.*]] = cir.cast bitcast %[[ALLOC_TO_ARR]] : !cir.ptr<!cir.array<!s32i x 2>> -> !cir.ptr<!void>
// CIR: cir.store{{.*}} %[[ARR_TO_VOID]], %[[ARR_ALLOCA]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
void foo26() {
void* arr9 = new int[][2]({1, 2}, {3, 4});
}
// LLVM: define {{.*}} void @{{.*foo27.*}} {
// LLVM: [[ARR_10:%.*]] = alloca ptr
// LLVM-NEXT: [[CALL_PTR]] = call {{.*}}nonnull {{.*}}@_Znam(i64 noundef 32)
// LLVM: store i32 5, ptr {{.*}}, align 4
// LLVM-NEXT: [[ARRAYINIT_ELEMENT:%.*]] = getelementptr {{.*}}i32, ptr {{.*}}, i64 1
// LLVM-NEXT: store i32 6, ptr [[ARRAYINIT_ELEMENT]], align 4
// LLVM-NEXT: [[ARRAY_EXP_NEXT:%.*]] = getelementptr {{.*}}[2 x i32], ptr {{.*}}, i64 1
// LLVM: store i32 7, ptr {{.*}}, align 4
// LLVM-NEXT: [[ARRAYINIT_ELEMENT2:%.*]] = getelementptr {{.*}}i32, ptr {{.*}}, i64 1
// LLVM-NEXT: store i32 8, ptr [[ARRAYINIT_ELEMENT2]], align 4
// LLVM-NEXT: [[ARRAY_EXP_NEXT3:%.*]] = getelementptr {{.*}}[2 x i32], ptr [[ARRAY_EXP_NEXT]], i64 1
// LLVM-NEXT: call void @llvm.memset.p0.i64(ptr {{.*}}[[ARRAY_EXP_NEXT3]], i8 0, i64 16, i1 false)
// LLVM-NEXT: store ptr [[CALL_PTR]], ptr [[ARR_10]], align 8
// LLVM-NEXT: ret void
// CIR-LABEL: cir.{{.*}}@_ZN7gh681985foo27Ev()
// CIR: %[[ARR_ALLOCA:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["arr10", init] {alignment = 8 : i64}
// CIR: %[[SIZE:.*]] = cir.const #cir.int<32> : !u64i
// CIR: %[[ALLOC:.*]] = cir.call @_Znam(%[[SIZE]]) {allocsize = array<i32: 0>, builtin} : (!u64i {llvm.noundef}) -> (!cir.ptr<!void> {llvm.nonnull, llvm.noundef})
// CIR: %[[ALLOC_TO_ARR:.*]] = cir.cast bitcast %[[ALLOC]] : !cir.ptr<!void> -> !cir.ptr<!cir.array<!s32i x 2>>
// CIR: %[[ELT0_0:.*]] = cir.cast array_to_ptrdecay %[[ALLOC_TO_ARR]] : !cir.ptr<!cir.array<!s32i x 2>> -> !cir.ptr<!s32i>
// CIR: %[[FIVE:.*]] = cir.const #cir.int<5> : !s32i
// CIR: cir.store{{.*}} %[[FIVE]], %[[ELT0_0]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i
// CIR: %[[ELT0_1:.*]] = cir.ptr_stride %[[ELT0_0]], %[[ONE]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i>
// CIR: %[[SIX:.*]] = cir.const #cir.int<6> : !s32i
// CIR: cir.store{{.*}} %[[SIX]], %[[ELT0_1]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CIR: %[[ELT1:.*]] = cir.ptr_stride %[[ALLOC_TO_ARR]], %[[ONE]] : (!cir.ptr<!cir.array<!s32i x 2>>, !s32i) -> !cir.ptr<!cir.array<!s32i x 2>>
// CIR: %[[ELT1_0:.*]] = cir.cast array_to_ptrdecay %[[ELT1]] : !cir.ptr<!cir.array<!s32i x 2>> -> !cir.ptr<!s32i>
// CIR: %[[SEVEN:.*]] = cir.const #cir.int<7> : !s32i
// CIR: cir.store{{.*}} %[[SEVEN]], %[[ELT1_0]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s64i
// CIR: %[[ELT1_1:.*]] = cir.ptr_stride %[[ELT1_0]], %[[ONE]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i>
// CIR: %[[EIGHT:.*]] = cir.const #cir.int<8> : !s32i
// CIR: cir.store{{.*}} %[[EIGHT]], %[[ELT1_1]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[ONE:.*]] = cir.const #cir.int<1> : !s32i
// CIR: %[[ELT2:.*]] = cir.ptr_stride %[[ELT1]], %[[ONE]] : (!cir.ptr<!cir.array<!s32i x 2>>, !s32i) -> !cir.ptr<!cir.array<!s32i x 2>>
// CIR: %[[INIT_SIZE:.*]] = cir.const #cir.int<16> : !u64i
// CIR: %[[ALLOC_DIFF:.*]] = cir.sub %[[SIZE]], %[[INIT_SIZE]] : !u64i
// CIR: %[[ELT2_DECAY:.*]] = cir.cast bitcast %[[ELT2]] : !cir.ptr<!cir.array<!s32i x 2>> -> !cir.ptr<!void>
// CIR: %[[ZERO:.*]] = cir.const #cir.int<0> : !u8i
// CIR: cir.libc.memset %[[ALLOC_DIFF]] bytes at %[[ELT2_DECAY]] to %[[ZERO]] : !cir.ptr<!void>, !u8i, !u64i
// CIR: %[[ARR_TO_VOID:.*]] = cir.cast bitcast %[[ALLOC_TO_ARR]] : !cir.ptr<!cir.array<!s32i x 2>> -> !cir.ptr<!void>
// CIR: cir.store{{.*}} %[[ARR_TO_VOID]], %[[ARR_ALLOCA]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
void foo27() {
void* arr10 = new int[4][2]({5, 6}, {7, 8});
}
}