diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-05-23 00:09:29 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2018-05-23 00:09:29 +0000 |
commit | 9062bbf41932e013d00347f6a98848792a6b13c6 (patch) | |
tree | 5b49f60b8ec0bde6529912012250980a5eeb7d4e /clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp | |
parent | 52d0abd7819382ac33ba0226d830638cfcc5a44f (diff) | |
download | bcm5719-llvm-9062bbf41932e013d00347f6a98848792a6b13c6.tar.gz bcm5719-llvm-9062bbf41932e013d00347f6a98848792a6b13c6.zip |
Use zeroinitializer for (trailing zero portion of) large array initializers
more reliably.
Clang has two different ways it emits array constants (from InitListExprs and
from APValues), and both had some ability to emit zeroinitializer, but neither
was able to catch all cases where we could use zeroinitializer reliably. In
particular, emitting from an APValue would fail to notice if all the explicit
array elements happened to be zero. In addition, for large arrays where only an
initial portion has an explicit initializer, we would emit the complete
initializer (which could be huge) rather than emitting only the non-zero
portion. With this change, when the element would have a suffix of more than 8
zero elements, we emit the array constant as a packed struct of its initial
portion followed by a zeroinitializer constant for the trailing zero portion.
In passing, I found a bug where SemaInit would sometimes walk the entire array
when checking an initializer that only covers the first few elements; that's
fixed here to unblock testing of the rest.
Differential Revision: https://reviews.llvm.org/D47166
llvm-svn: 333044
Diffstat (limited to 'clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp')
-rw-r--r-- | clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp b/clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp index 8bf35966f5b..4a593689650 100644 --- a/clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp +++ b/clang/test/CodeGenCXX/cxx11-initializer-aggregate.cpp @@ -11,6 +11,13 @@ namespace NonAggregateCopyInAggregateInit { // PR32044 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}}; +} + // CHECK-LABEL: define {{.*}}@_Z3fn1i( int fn1(int x) { // CHECK: %[[INITLIST:.*]] = alloca %struct.A @@ -51,3 +58,35 @@ namespace NonTrivialInit { // 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 +} |