[ConstantFolding] Extend FoldReinterpretLoadFromConstPtr to handle negative offsets

Treat loads which clip before the start of a global initializer the same
way we treat clipping beyond the end of the initializer: use zeros.

llvm-svn: 275345
This commit is contained in:
David Majnemer 2016-07-13 23:33:07 +00:00
parent d77a3b61eb
commit f89660aba7
2 changed files with 28 additions and 10 deletions

View File

@ -442,8 +442,8 @@ Constant *FoldReinterpretLoadFromConstPtr(Constant *C, Type *LoadTy,
return nullptr; return nullptr;
GlobalValue *GVal; GlobalValue *GVal;
APInt Offset; APInt OffsetAI;
if (!IsConstantOffsetFromGlobal(C, GVal, Offset, DL)) if (!IsConstantOffsetFromGlobal(C, GVal, OffsetAI, DL))
return nullptr; return nullptr;
auto *GV = dyn_cast<GlobalVariable>(GVal); auto *GV = dyn_cast<GlobalVariable>(GVal);
@ -451,19 +451,29 @@ Constant *FoldReinterpretLoadFromConstPtr(Constant *C, Type *LoadTy,
!GV->getInitializer()->getType()->isSized()) !GV->getInitializer()->getType()->isSized())
return nullptr; return nullptr;
// If we're loading off the beginning of the global, some bytes may be valid, int64_t Offset = OffsetAI.getSExtValue();
// but we don't try to handle this. int64_t InitializerSize = DL.getTypeAllocSize(GV->getInitializer()->getType());
if (Offset.isNegative())
return nullptr;
// If we're not accessing anything in this constant, the result is undefined. // If we're not accessing anything in this constant, the result is undefined.
if (Offset.getZExtValue() >= if (Offset + BytesLoaded <= 0)
DL.getTypeAllocSize(GV->getInitializer()->getType())) return UndefValue::get(IntType);
// If we're not accessing anything in this constant, the result is undefined.
if (Offset >= InitializerSize)
return UndefValue::get(IntType); return UndefValue::get(IntType);
unsigned char RawBytes[32] = {0}; unsigned char RawBytes[32] = {0};
if (!ReadDataFromGlobal(GV->getInitializer(), Offset.getZExtValue(), RawBytes, unsigned char *CurPtr = RawBytes;
BytesLoaded, DL)) unsigned BytesLeft = BytesLoaded;
// If we're loading off the beginning of the global, some bytes may be valid.
if (Offset < 0) {
CurPtr += -Offset;
BytesLeft += Offset;
Offset = 0;
}
if (!ReadDataFromGlobal(GV->getInitializer(), Offset, CurPtr, BytesLeft, DL))
return nullptr; return nullptr;
APInt ResultVal = APInt(IntType->getBitWidth(), 0); APInt ResultVal = APInt(IntType->getBitWidth(), 0);

View File

@ -20,3 +20,11 @@ define i32 @crash_on_undef() {
ret i32 %load ret i32 %load
} }
@GV = private constant [8 x i32] [i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48, i32 49]
define <8 x i32> @partial_load() {
; CHECK-LABEL: @partial_load(
; CHECK: ret <8 x i32> <i32 0, i32 42, i32 43, i32 44, i32 45, i32 46, i32 47, i32 48>
%load = load <8 x i32>, <8 x i32>* bitcast (i32* getelementptr ([8 x i32], [8 x i32]* @GV, i64 0, i64 -1) to <8 x i32>*)
ret <8 x i32> %load
}