diff options
author | Nikita Popov <npopov@redhat.com> | 2024-05-31 09:25:38 +0200 |
---|---|---|
committer | Nikita Popov <npopov@redhat.com> | 2024-06-10 10:12:55 +0200 |
commit | cc158d4c0bb50554dadcad44c10cafb052376cea (patch) | |
tree | cc78f7e1c65d23219bf565c88eddab9e7f4401f2 /llvm/lib/IR/ConstantFold.cpp | |
parent | e58f830a1de20af79a6ce41c85b787f4a64b9c74 (diff) | |
download | llvm-cc158d4c0bb50554dadcad44c10cafb052376cea.zip llvm-cc158d4c0bb50554dadcad44c10cafb052376cea.tar.gz llvm-cc158d4c0bb50554dadcad44c10cafb052376cea.tar.bz2 |
Reapply [ConstantFold] Remove non-trivial gep-of-gep fold (#93823)
Reapply after https://github.com/llvm/llvm-project/pull/93956, which
changed clang array initialization codegen to avoid size regressions
for unoptimized builds.
-----
This fold is subtly incorrect, because DL-unaware constant folding does
not know the correct index type to use, and just performs the addition
in the type that happens to already be there. This is incorrect, since
sext(X)+sext(Y) is generally not the same as sext(X+Y). See the
`@constexpr_gep_of_gep_with_narrow_type()` for a miscompile with the
current implementation.
One could try to restrict the fold to cases where no overflow occurs,
but I'm not bothering with that here, because the DL-aware constant
folding will take care of this anyway. I've only kept the
straightforward zero-index case, where we just concatenate two GEPs.
Diffstat (limited to 'llvm/lib/IR/ConstantFold.cpp')
-rw-r--r-- | llvm/lib/IR/ConstantFold.cpp | 56 |
1 files changed, 4 insertions, 52 deletions
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp index 7b8b9a7..77a8336 100644 --- a/llvm/lib/IR/ConstantFold.cpp +++ b/llvm/lib/IR/ConstantFold.cpp @@ -1416,64 +1416,16 @@ static Constant *foldGEPOfGEP(GEPOperator *GEP, Type *PointeeTy, bool InBounds, if (GEP->getInRange()) return nullptr; + // Only handle simple case with leading zero index. We cannot perform an + // actual addition as we don't know the correct index type size to use. Constant *Idx0 = cast<Constant>(Idxs[0]); - if (Idx0->isNullValue()) { - // Handle the simple case of a zero index. - SmallVector<Value*, 16> NewIndices; - NewIndices.reserve(Idxs.size() + GEP->getNumIndices()); - NewIndices.append(GEP->idx_begin(), GEP->idx_end()); - NewIndices.append(Idxs.begin() + 1, Idxs.end()); - return ConstantExpr::getGetElementPtr( - GEP->getSourceElementType(), cast<Constant>(GEP->getPointerOperand()), - NewIndices, InBounds && GEP->isInBounds()); - } - - gep_type_iterator LastI = gep_type_end(GEP); - for (gep_type_iterator I = gep_type_begin(GEP), E = gep_type_end(GEP); - I != E; ++I) - LastI = I; - - // We can't combine GEPs if the last index is a struct type. - if (!LastI.isSequential()) - return nullptr; - // We could perform the transform with non-constant index, but prefer leaving - // it as GEP of GEP rather than GEP of add for now. - ConstantInt *CI = dyn_cast<ConstantInt>(Idx0); - if (!CI) - return nullptr; - - // TODO: This code may be extended to handle vectors as well. - auto *LastIdx = cast<Constant>(GEP->getOperand(GEP->getNumOperands()-1)); - Type *LastIdxTy = LastIdx->getType(); - if (LastIdxTy->isVectorTy()) + if (!Idx0->isNullValue()) return nullptr; SmallVector<Value*, 16> NewIndices; NewIndices.reserve(Idxs.size() + GEP->getNumIndices()); - NewIndices.append(GEP->idx_begin(), GEP->idx_end() - 1); - - // Add the last index of the source with the first index of the new GEP. - // Make sure to handle the case when they are actually different types. - if (LastIdxTy != Idx0->getType()) { - unsigned CommonExtendedWidth = - std::max(LastIdxTy->getIntegerBitWidth(), - Idx0->getType()->getIntegerBitWidth()); - CommonExtendedWidth = std::max(CommonExtendedWidth, 64U); - - Type *CommonTy = - Type::getIntNTy(LastIdxTy->getContext(), CommonExtendedWidth); - if (Idx0->getType() != CommonTy) - Idx0 = ConstantFoldCastInstruction(Instruction::SExt, Idx0, CommonTy); - if (LastIdx->getType() != CommonTy) - LastIdx = - ConstantFoldCastInstruction(Instruction::SExt, LastIdx, CommonTy); - if (!Idx0 || !LastIdx) - return nullptr; - } - - NewIndices.push_back(ConstantExpr::get(Instruction::Add, Idx0, LastIdx)); + NewIndices.append(GEP->idx_begin(), GEP->idx_end()); NewIndices.append(Idxs.begin() + 1, Idxs.end()); - return ConstantExpr::getGetElementPtr( GEP->getSourceElementType(), cast<Constant>(GEP->getPointerOperand()), NewIndices, InBounds && GEP->isInBounds()); |