diff options
author | Martin Sebor <msebor@redhat.com> | 2022-06-21 11:31:58 -0600 |
---|---|---|
committer | Martin Sebor <msebor@redhat.com> | 2022-06-21 11:55:14 -0600 |
commit | b19194c032e7640be0a482f20491341a62e7304f (patch) | |
tree | f4c8a60c190a55178f34cd38519c19530289aa33 /llvm/lib/Analysis/ConstantFolding.cpp | |
parent | 13eb5b3455fbeb959ab36974e17ba03222d6a4d0 (diff) | |
download | llvm-b19194c032e7640be0a482f20491341a62e7304f.zip llvm-b19194c032e7640be0a482f20491341a62e7304f.tar.gz llvm-b19194c032e7640be0a482f20491341a62e7304f.tar.bz2 |
[InstCombine] handle subobjects of constant aggregates
Remove the known limitation of the library function call folders to only
work with top-level arrays of characters (as per the TODO comment in
the code) and allows them to also fold calls involving subobjects of
constant aggregates such as member arrays.
Diffstat (limited to 'llvm/lib/Analysis/ConstantFolding.cpp')
-rw-r--r-- | llvm/lib/Analysis/ConstantFolding.cpp | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index 8a4da83..0096aa9 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -633,6 +633,39 @@ Constant *FoldReinterpretLoadFromConst(Constant *C, Type *LoadTy, return ConstantInt::get(IntType->getContext(), ResultVal); } +} // anonymous namespace + +// If GV is a constant with an initializer read its representation starting +// at Offset and return it as a constant array of unsigned char. Otherwise +// return null. +Constant *llvm::ReadByteArrayFromGlobal(const GlobalVariable *GV, + uint64_t Offset) { + if (!GV->isConstant() || !GV->hasDefinitiveInitializer()) + return nullptr; + + const DataLayout &DL = GV->getParent()->getDataLayout(); + Constant *Init = const_cast<Constant *>(GV->getInitializer()); + TypeSize InitSize = DL.getTypeAllocSize(Init->getType()); + if (InitSize < Offset) + return nullptr; + + uint64_t NBytes = InitSize - Offset; + if (NBytes > UINT16_MAX) + // Bail for large initializers in excess of 64K to avoid allocating + // too much memory. + // Offset is assumed to be less than or equal than InitSize (this + // is enforced in ReadDataFromGlobal). + return nullptr; + + SmallVector<unsigned char, 256> RawBytes(static_cast<size_t>(NBytes)); + unsigned char *CurPtr = RawBytes.data(); + + if (!ReadDataFromGlobal(Init, Offset, CurPtr, NBytes, DL)) + return nullptr; + + return ConstantDataArray::get(GV->getContext(), RawBytes); +} + /// If this Offset points exactly to the start of an aggregate element, return /// that element, otherwise return nullptr. Constant *getConstantAtOffset(Constant *Base, APInt Offset, @@ -661,8 +694,6 @@ Constant *getConstantAtOffset(Constant *Base, APInt Offset, return C; } -} // end anonymous namespace - Constant *llvm::ConstantFoldLoadFromConst(Constant *C, Type *Ty, const APInt &Offset, const DataLayout &DL) { |