Use the DataLayout-aware TargetFolder instead of ConstantFolder in Clang's CGBuilder. The primary impact of this change is that GEP constant expressions are now emitted in canonical `getelementptr i8` form. This is in preparation for the migration to ptradd, which requires this form. Part of the test updates were performed by Claude Code and reviewed by me.
174 lines
6.6 KiB
C++
174 lines
6.6 KiB
C++
// RUN: %clang_cc1 -std=c++11 -emit-llvm -o - %s -triple x86_64-linux-gnu | FileCheck %s
|
|
// RUN: %clang_cc1 -std=c++17 -emit-llvm -o - %s -triple x86_64-linux-gnu | FileCheck %s
|
|
|
|
struct A { int a, b; int f(); };
|
|
|
|
namespace NonAggregateCopyInAggregateInit { // PR32044
|
|
struct A { constexpr A(int n) : x(n), y() {} int x, y; } extern a;
|
|
// CHECK-DAG: @_ZN31NonAggregateCopyInAggregateInit1bE ={{.*}} global %{{.*}} { ptr @_ZN31NonAggregateCopyInAggregateInit1aE }
|
|
struct B { A &p; } b{{a}};
|
|
// CHECK-DAG: @_ZGRN31NonAggregateCopyInAggregateInit1cE_ = internal global %[[A:.*]] { i32 1, i32 0 }
|
|
// CHECK-DAG: @_ZN31NonAggregateCopyInAggregateInit1cE ={{.*}} global %{{.*}} { ptr @_ZGRN31NonAggregateCopyInAggregateInit1cE_ }
|
|
struct C { A &&p; } c{{1}};
|
|
}
|
|
|
|
namespace NearlyZeroInit {
|
|
// CHECK-DAG: @_ZN14NearlyZeroInit1aE ={{.*}} global {{.*}} <{ i32 1, i32 2, i32 3, [120 x i32] zeroinitializer }>
|
|
int a[123] = {1, 2, 3};
|
|
// CHECK-DAG: @_ZN14NearlyZeroInit1bE ={{.*}} global {{.*}} { i32 1, <{ i32, [2147483647 x i32] }> <{ i32 2, [2147483647 x i32] zeroinitializer }> }
|
|
struct B { int n; int arr[1024 * 1024 * 1024 * 2u]; } b = {1, {2}};
|
|
}
|
|
|
|
namespace PR37560 {
|
|
union U {
|
|
char x;
|
|
int a;
|
|
};
|
|
// FIXME: [dcl.init]p2, the padding bits of the union object should be
|
|
// initialized to 0, not undef, which would allow us to collapse the tail
|
|
// of these arrays to zeroinitializer.
|
|
// CHECK-DAG: @_ZN7PR375601cE ={{.*}} global <{ { i8, [3 x i8] } }> <{ { i8, [3 x i8] } { i8 0, [3 x i8] undef } }>
|
|
U c[1] = {};
|
|
// CHECK-DAG: @_ZN7PR375601dE ={{.*}} global {{.*}} <{ { i8, [3 x i8] } { i8 97, [3 x i8] undef }, %"{{[^"]*}}" { i32 123 }, { i8, [3 x i8] } { i8 98, [3 x i8] undef }, { i8, [3 x i8] } { i8 0, [3 x i8] undef },
|
|
U d[16] = {'a', {.a = 123}, 'b'};
|
|
// CHECK-DAG: @_ZN7PR375601eE ={{.*}} global {{.*}} <{ %"{{[^"]*}}" { i32 123 }, %"{{[^"]*}}" { i32 456 }, { i8, [3 x i8] } { i8 0, [3 x i8] undef },
|
|
U e[16] = {{.a = 123}, {.a = 456}};
|
|
|
|
union V {
|
|
int a;
|
|
char x;
|
|
};
|
|
// CHECK-DAG: @_ZN7PR375601fE ={{.*}} global [1 x %"{{[^"]*}}"] zeroinitializer
|
|
V f[1] = {};
|
|
// CHECK-DAG: @_ZN7PR375601gE ={{.*}} global {{.*}} <{ { i8, [3 x i8] } { i8 97, [3 x i8] undef }, %"{{[^"]*}}" { i32 123 }, { i8, [3 x i8] } { i8 98, [3 x i8] undef }, [13 x %"{{[^"]*}}"] zeroinitializer }>
|
|
V g[16] = {{.x = 'a'}, {.a = 123}, {.x = 'b'}};
|
|
// CHECK-DAG: @_ZN7PR375601hE ={{.*}} global {{.*}} <{ %"{{[^"]*}}" { i32 123 }, %"{{[^"]*}}" { i32 456 }, [14 x %"{{[^"]*}}"] zeroinitializer }>
|
|
V h[16] = {{.a = 123}, {.a = 456}};
|
|
// CHECK-DAG: @_ZN7PR375601iE ={{.*}} global [4 x %"{{[^"]*}}"] [%"{{[^"]*}}" { i32 123 }, %"{{[^"]*}}" { i32 456 }, %"{{[^"]*}}" zeroinitializer, %"{{[^"]*}}" zeroinitializer]
|
|
V i[4] = {{.a = 123}, {.a = 456}};
|
|
}
|
|
|
|
// CHECK-LABEL: define {{.*}}@_Z3fn1i(
|
|
int fn1(int x) {
|
|
// CHECK: %[[INITLIST:.*]] = alloca %struct.A
|
|
// CHECK: %[[A:.*]] = getelementptr inbounds nuw %struct.A, ptr %[[INITLIST]], i32 0, i32 0
|
|
// CHECK: store i32 %{{.*}}, ptr %[[A]], align 4
|
|
// CHECK: %[[B:.*]] = getelementptr inbounds nuw %struct.A, ptr %[[INITLIST]], i32 0, i32 1
|
|
// CHECK: store i32 5, ptr %[[B]], align 4
|
|
// CHECK: call noundef i32 @_ZN1A1fEv(ptr {{[^,]*}} %[[INITLIST]])
|
|
return A{x, 5}.f();
|
|
}
|
|
|
|
struct B { int &r; int &f() { return r; } };
|
|
|
|
// CHECK-LABEL: define {{.*}}@_Z3fn2Ri(
|
|
int &fn2(int &v) {
|
|
// CHECK: %[[INITLIST2:.*]] = alloca %struct.B, align 8
|
|
// CHECK: %[[R:.*]] = getelementptr inbounds nuw %struct.B, ptr %[[INITLIST2:.*]], i32 0, i32 0
|
|
// CHECK: store ptr %{{.*}}, ptr %[[R]], align 8
|
|
// CHECK: call noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) ptr @_ZN1B1fEv(ptr {{[^,]*}} %[[INITLIST2:.*]])
|
|
return B{v}.f();
|
|
}
|
|
|
|
// CHECK-LABEL: define {{.*}}@__cxx_global_var_init(
|
|
//
|
|
// CHECK: call {{.*}}@_ZN14NonTrivialInit1AC1Ev(
|
|
// CHECK: getelementptr inbounds {{.*}}, i64 1
|
|
// CHECK: br i1
|
|
//
|
|
// CHECK: getelementptr inbounds {{.*}}, i64 1
|
|
// CHECK: icmp eq {{.*}}, getelementptr inbounds nuw (i8, ptr @{{.*}}, i64 600)
|
|
// CHECK: br i1
|
|
//
|
|
// CHECK: call i32 @__cxa_atexit(
|
|
namespace NonTrivialInit {
|
|
struct A { A(); A(const A&) = delete; ~A(); };
|
|
struct B { A a[20]; };
|
|
// NB, this must be large enough to be worth memsetting for this test to be
|
|
// meaningful.
|
|
B b[30] = {};
|
|
}
|
|
|
|
namespace ZeroInit {
|
|
enum { Zero, One };
|
|
constexpr int zero() { return 0; }
|
|
constexpr int *null() { return nullptr; }
|
|
struct Filler {
|
|
int x;
|
|
Filler();
|
|
};
|
|
struct S1 {
|
|
int x;
|
|
};
|
|
|
|
// These declarations, if implemented elementwise, require huge
|
|
// amout of memory and compiler time.
|
|
unsigned char data_1[1024 * 1024 * 1024 * 2u] = { 0 };
|
|
unsigned char data_2[1024 * 1024 * 1024 * 2u] = { Zero };
|
|
unsigned char data_3[1024][1024][1024] = {{{0}}};
|
|
unsigned char data_4[1024 * 1024 * 1024 * 2u] = { zero() };
|
|
int *data_5[1024 * 1024 * 512] = { nullptr };
|
|
int *data_6[1024 * 1024 * 512] = { null() };
|
|
struct S1 data_7[1024 * 1024 * 512] = {{0}};
|
|
char data_8[1000 * 1000 * 1000] = {};
|
|
int (&&data_9)[1000 * 1000 * 1000] = {0};
|
|
unsigned char data_10[1024 * 1024 * 1024 * 2u] = { 1 };
|
|
unsigned char data_11[1024 * 1024 * 1024 * 2u] = { One };
|
|
unsigned char data_12[1024][1024][1024] = {{{1}}};
|
|
|
|
// This variable must be initialized elementwise.
|
|
Filler data_e1[1024] = {};
|
|
// CHECK: getelementptr inbounds {{.*}} @_ZN8ZeroInit7data_e1E
|
|
|
|
struct Largeish {
|
|
long a, b, c;
|
|
};
|
|
// CHECK: define {{.*}}@_ZN8ZeroInit9largeish1Ev(
|
|
// CHECK-NOT }
|
|
// CHECK: call {{.*}}memset
|
|
Largeish largeish1() { return {}; }
|
|
// CHECK: define {{.*}}@_ZN8ZeroInit9largeish2Ev(
|
|
// CHECK-NOT }
|
|
// CHECK: call {{.*}}memset
|
|
Largeish largeish2() { return Largeish(); }
|
|
// CHECK: define {{.*}}@_ZN8ZeroInit9largeish3Ev(
|
|
// CHECK-NOT }
|
|
// CHECK: call {{.*}}memset
|
|
Largeish largeish3() { return Largeish{}; }
|
|
// CHECK: define {{.*}}@_ZN8ZeroInit9largeish4Ev(
|
|
// CHECK-NOT }
|
|
// CHECK: call {{.*}}memset
|
|
Largeish largeish4() { return (Largeish){}; }
|
|
// CHECK: define {{.*}}@_ZN8ZeroInit9largeish5Ev(
|
|
// CHECK-NOT }
|
|
// CHECK: call {{.*}}memset
|
|
Largeish largeish5() { return {0, 0, 0}; }
|
|
|
|
typedef __attribute__((ext_vector_type(4))) char CI4;
|
|
struct Conversions {
|
|
_Complex int a;
|
|
_Complex float b;
|
|
short c;
|
|
long double d;
|
|
CI4 e;
|
|
char f;
|
|
char g;
|
|
int *h;
|
|
long i;
|
|
};
|
|
// CHECK: define {{.*}}@_ZN8ZeroInit11conversionsEv(
|
|
// CHECK-NOT }
|
|
// CHECK: call {{.*}}memset
|
|
Conversions conversions() {
|
|
return {0,
|
|
0,
|
|
0,
|
|
0,
|
|
CI4(0),
|
|
static_cast<char>(0.0),
|
|
char(0 + 0i),
|
|
reinterpret_cast<int *>(0),
|
|
reinterpret_cast<long>((int *)nullptr)};
|
|
}
|
|
}
|