From 6baafaafae4329f378b973edc7bd1dc360318674 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Tue, 6 Feb 2018 23:22:14 +0000 Subject: [PATCH] Place undefined globals in .bss instead of .data Following up on the discussion from http://lists.llvm.org/pipermail/llvm-dev/2017-April/112305.html, undef values are now placed in the .bss as well as null values. This prevents undef global values taking up potentially huge amounts of space in the .data section. The following two lines now both generate equivalent .bss data: @vals1 = internal unnamed_addr global [20000000 x i32] zeroinitializer, align 4 @vals2 = internal unnamed_addr global [20000000 x i32] undef, align 4 ; previously unaccounted for This is primarily motivated by the corresponding issue in the Rust compiler (https://github.com/rust-lang/rust/issues/41315). Differential Revision: https://reviews.llvm.org/D41705 Patch by varkor! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@324424 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/TargetLoweringObjectFile.cpp | 15 ++++++++++++++- test/CodeGen/ARM/memfunc.ll | 6 ++++-- test/CodeGen/X86/undef-globals-bss.ll | 12 ++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 test/CodeGen/X86/undef-globals-bss.ll diff --git a/lib/Target/TargetLoweringObjectFile.cpp b/lib/Target/TargetLoweringObjectFile.cpp index 72baf5985eac..6654eab7f01e 100644 --- a/lib/Target/TargetLoweringObjectFile.cpp +++ b/lib/Target/TargetLoweringObjectFile.cpp @@ -52,11 +52,24 @@ TargetLoweringObjectFile::~TargetLoweringObjectFile() { delete Mang; } +static bool isNullOrUndef(const Constant *C) { + // Check that the constant isn't all zeros or undefs. + if (C->isNullValue() || isa(C)) + return true; + if (!isa(C)) + return false; + for (auto Operand : C->operand_values()) { + if (!isNullOrUndef(cast(Operand))) + return false; + } + return true; +} + static bool isSuitableForBSS(const GlobalVariable *GV, bool NoZerosInBSS) { const Constant *C = GV->getInitializer(); // Must have zero initializer. - if (!C->isNullValue()) + if (!isNullOrUndef(C)) return false; // Leave constant zeros in readonly constant sections, so they can be shared. diff --git a/test/CodeGen/ARM/memfunc.ll b/test/CodeGen/ARM/memfunc.ll index ed6746290b75..8d9c7cdea81c 100644 --- a/test/CodeGen/ARM/memfunc.ll +++ b/test/CodeGen/ARM/memfunc.ll @@ -421,8 +421,10 @@ entry: ; CHECK: arr5: ; CHECK-NOT: .p2align ; CHECK: arr6: -; CHECK: .p2align 4 -; CHECK: arr8: +; CHECK-IOS: arr8,128,4 +; CHECK-DARWIN: arr8,128,4 +; CHECK-EABI: arr8,128,16 +; CHECK-GNUEABI: arr8,128,16 ; CHECK: .p2align 4 ; CHECK: arr9: diff --git a/test/CodeGen/X86/undef-globals-bss.ll b/test/CodeGen/X86/undef-globals-bss.ll new file mode 100644 index 000000000000..85bec9eb6c70 --- /dev/null +++ b/test/CodeGen/X86/undef-globals-bss.ll @@ -0,0 +1,12 @@ +; RUN: llc < %s | FileCheck %s +target triple = "x86_64-apple-darwin" + +; CHECK: .zerofill __DATA,__bss,_vals,8000000,2 ## @vals +@vals = internal unnamed_addr global [2000000 x i32] undef, align 4 + +; CHECK: .zerofill __DATA,__bss,_struct,8000040,3 ## @struct +@struct = internal global { i1, [8000000 x i8], [7 x i8], i64, { [4 x i32], { i8 }, i1 } } + { i1 false, [8000000 x i8] zeroinitializer, [7 x i8] undef, i64 0, + { [4 x i32], { i8 }, i1 } + { [4 x i32] zeroinitializer, { i8 } { i8 undef }, i1 false } + }, align 8