diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 73bdd99fcc97..dcfe700bf94f 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -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(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); diff --git a/llvm/test/Transforms/InstSimplify/load.ll b/llvm/test/Transforms/InstSimplify/load.ll index ba789df4ddbd..8b2b5a17660f 100644 --- a/llvm/test/Transforms/InstSimplify/load.ll +++ b/llvm/test/Transforms/InstSimplify/load.ll @@ -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> + %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 +}