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

View File

@ -20,3 +20,11 @@ define i32 @crash_on_undef() {
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
}