Skip to content

Commit bcaeb14

Browse files
committed
[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 rust-lang/rust#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
1 parent 175df18 commit bcaeb14

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

llvm/lib/Analysis/ConstantFolding.cpp

+13-2
Original file line numberDiff line numberDiff line change
@@ -347,9 +347,20 @@ Constant *llvm::ConstantFoldLoadThroughBitcast(Constant *C, Type *DestTy,
347347

348348
// We're simulating a load through a pointer that was bitcast to point to
349349
// a different type, so we can try to walk down through the initial
350-
// elements of an aggregate to see if some part of th e aggregate is
350+
// elements of an aggregate to see if some part of the aggregate is
351351
// castable to implement the "load" semantic model.
352-
C = C->getAggregateElement(0u);
352+
if (SrcTy->isStructTy()) {
353+
// Struct types might have leading zero-length elements like [0 x i32],
354+
// which are certainly not what we are looking for, so skip them.
355+
unsigned Elem = 0;
356+
Constant *ElemC;
357+
do {
358+
ElemC = C->getAggregateElement(Elem++);
359+
} while (ElemC && DL.getTypeSizeInBits(ElemC->getType()) == 0);
360+
C = ElemC;
361+
} else {
362+
C = C->getAggregateElement(0u);
363+
}
353364
} while (C);
354365

355366
return nullptr;

llvm/test/Transforms/ConstProp/loads.ll

+39
Original file line numberDiff line numberDiff line change
@@ -269,3 +269,42 @@ define i64 @test16.3() {
269269
; BE-LABEL: @test16.3(
270270
; BE: ret i64 0
271271
}
272+
273+
@g7 = constant {[0 x i32], [0 x i8], {}*} { [0 x i32] undef, [0 x i8] undef, {}* null }
274+
275+
define i64* @test_leading_zero_size_elems() {
276+
%v = load i64*, i64** bitcast ({[0 x i32], [0 x i8], {}*}* @g7 to i64**)
277+
ret i64* %v
278+
279+
; LE-LABEL: @test_leading_zero_size_elems(
280+
; LE: ret i64* null
281+
282+
; BE-LABEL: @test_leading_zero_size_elems(
283+
; BE: ret i64* null
284+
}
285+
286+
@g8 = constant {[4294967295 x [0 x i32]], i64} { [4294967295 x [0 x i32]] undef, i64 123 }
287+
288+
define i64 @test_leading_zero_size_elems_big() {
289+
%v = load i64, i64* bitcast ({[4294967295 x [0 x i32]], i64}* @g8 to i64*)
290+
ret i64 %v
291+
292+
; LE-LABEL: @test_leading_zero_size_elems_big(
293+
; LE: ret i64 123
294+
295+
; BE-LABEL: @test_leading_zero_size_elems_big(
296+
; BE: ret i64 123
297+
}
298+
299+
@g9 = constant [4294967295 x [0 x i32]] zeroinitializer
300+
301+
define i64 @test_array_of_zero_size_array() {
302+
%v = load i64, i64* bitcast ([4294967295 x [0 x i32]]* @g9 to i64*)
303+
ret i64 %v
304+
305+
; LE-LABEL: @test_array_of_zero_size_array(
306+
; LE: ret i64 0
307+
308+
; BE-LABEL: @test_array_of_zero_size_array(
309+
; BE: ret i64 0
310+
}

0 commit comments

Comments
 (0)