From 79c994d9767212c97f87846c7cd76e678f889052 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 11 Dec 2018 20:29:16 +0000 Subject: [PATCH] [ConstantFolding] Handle leading zero-size elements in load folding Struct types may have leading zero-size elements like [0 x i32], in which case the "real" element at offset 0 will not necessarily coincide with the 0th element of the aggregate. ConstantFoldLoadThroughBitcast() wants to drill down the element at offset 0, but currently always picks the 0th aggregate element to do so. This patch changes the code to find the first non-zero-size element instead, for the struct case. The motivation behind this change is https://github.com/rust-lang/rust/issues/48627. Rust is fond of emitting [0 x iN] separators between struct elements to enforce alignment, which prevents constant folding in this particular case. The additional tests with [4294967295 x [0 x i32]] check that we don't end up unnecessarily looping over a large number of zero-size elements of a zero-size array. Differential Revision: https://reviews.llvm.org/D55169 llvm-svn: 348895 --- llvm/lib/Analysis/ConstantFolding.cpp | 15 +++++++++++-- llvm/test/Transforms/ConstProp/loads.ll | 39 +++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index fded0c6..6180886 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -347,9 +347,20 @@ Constant *llvm::ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy, // We're simulating a load through a pointer that was bitcast to point to // a different type, so we can try to walk down through the initial - // elements of an aggregate to see if some part of th e aggregate is + // elements of an aggregate to see if some part of the aggregate is // castable to implement the "load" semantic model. - C = C->getAggregateElement(0u); + if (SrcTy->isStructTy()) { + // Struct types might have leading zero-length elements like [0 x i32], + // which are certainly not what we are looking for, so skip them. + unsigned Elem = 0; + Constant *ElemC; + do { + ElemC = C->getAggregateElement(Elem++); + } while (ElemC && DL.getTypeSizeInBits(ElemC->getType()) == 0); + C = ElemC; + } else { + C = C->getAggregateElement(0u); + } } while (C); return nullptr; diff --git a/llvm/test/Transforms/ConstProp/loads.ll b/llvm/test/Transforms/ConstProp/loads.ll index dce2068..68d7390 100644 --- a/llvm/test/Transforms/ConstProp/loads.ll +++ b/llvm/test/Transforms/ConstProp/loads.ll @@ -269,3 +269,42 @@ define i64 @test16.3() { ; BE-LABEL: @test16.3( ; BE: ret i64 0 } + +@g7 = constant {[0 x i32], [0 x i8], {}*} { [0 x i32] undef, [0 x i8] undef, {}* null } + +define i64* @test_leading_zero_size_elems() { + %v = load i64*, i64** bitcast ({[0 x i32], [0 x i8], {}*}* @g7 to i64**) + ret i64* %v + +; LE-LABEL: @test_leading_zero_size_elems( +; LE: ret i64* null + +; BE-LABEL: @test_leading_zero_size_elems( +; BE: ret i64* null +} + +@g8 = constant {[4294967295 x [0 x i32]], i64} { [4294967295 x [0 x i32]] undef, i64 123 } + +define i64 @test_leading_zero_size_elems_big() { + %v = load i64, i64* bitcast ({[4294967295 x [0 x i32]], i64}* @g8 to i64*) + ret i64 %v + +; LE-LABEL: @test_leading_zero_size_elems_big( +; LE: ret i64 123 + +; BE-LABEL: @test_leading_zero_size_elems_big( +; BE: ret i64 123 +} + +@g9 = constant [4294967295 x [0 x i32]] zeroinitializer + +define i64 @test_array_of_zero_size_array() { + %v = load i64, i64* bitcast ([4294967295 x [0 x i32]]* @g9 to i64*) + ret i64 %v + +; LE-LABEL: @test_array_of_zero_size_array( +; LE: ret i64 0 + +; BE-LABEL: @test_array_of_zero_size_array( +; BE: ret i64 0 +} -- 2.7.4