diff options
author | Nikita Popov <npopov@redhat.com> | 2024-05-30 08:36:44 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-30 08:36:44 +0200 |
commit | d10b76552f919ddb84347ab03908a55804ea6b8a (patch) | |
tree | a5a8b88d3823a49477df9fc49030b65369686b87 /llvm/lib/IR/ConstantFold.cpp | |
parent | 4bce270157f9a81bd7e38dc589a2970a445d1e96 (diff) | |
download | llvm-d10b76552f919ddb84347ab03908a55804ea6b8a.zip llvm-d10b76552f919ddb84347ab03908a55804ea6b8a.tar.gz llvm-d10b76552f919ddb84347ab03908a55804ea6b8a.tar.bz2 |
[ConstantFold] Remove notional over-indexing fold (#93697)
The data-layout independent constant folding currently has some rather
gnarly code for canonicalizing GEP indices to reduce "notional
overindexing", and then infers inbounds based on that canonicalization.
Now that we canonicalize to i8 GEPs, this canonicalization is
essentially useless, as we'll discard it as soon as the GEP hits the
data-layout aware constant folder anyway. As such, I'd like to remove
this code entirely.
This shouldn't have any impact on optimization capabilities.
Diffstat (limited to 'llvm/lib/IR/ConstantFold.cpp')
-rw-r--r-- | llvm/lib/IR/ConstantFold.cpp | 196 |
1 files changed, 0 insertions, 196 deletions
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp index 8fce782..9a7d437 100644 --- a/llvm/lib/IR/ConstantFold.cpp +++ b/llvm/lib/IR/ConstantFold.cpp @@ -1417,50 +1417,6 @@ Constant *llvm::ConstantFoldCompareInstruction(CmpInst::Predicate Predicate, return nullptr; } -/// Test whether the given sequence of *normalized* indices is "inbounds". -template<typename IndexTy> -static bool isInBoundsIndices(ArrayRef<IndexTy> Idxs) { - // No indices means nothing that could be out of bounds. - if (Idxs.empty()) return true; - - // If the first index is zero, it's in bounds. - if (cast<Constant>(Idxs[0])->isNullValue()) return true; - - // If the first index is one and all the rest are zero, it's in bounds, - // by the one-past-the-end rule. - if (auto *CI = dyn_cast<ConstantInt>(Idxs[0])) { - if (!CI->isOne()) - return false; - } else { - auto *CV = cast<ConstantDataVector>(Idxs[0]); - CI = dyn_cast_or_null<ConstantInt>(CV->getSplatValue()); - if (!CI || !CI->isOne()) - return false; - } - - for (unsigned i = 1, e = Idxs.size(); i != e; ++i) - if (!cast<Constant>(Idxs[i])->isNullValue()) - return false; - return true; -} - -/// Test whether a given ConstantInt is in-range for a SequentialType. -static bool isIndexInRangeOfArrayType(uint64_t NumElements, - const ConstantInt *CI) { - // We cannot bounds check the index if it doesn't fit in an int64_t. - if (CI->getValue().getSignificantBits() > 64) - return false; - - // A negative index or an index past the end of our sequential type is - // considered out-of-range. - int64_t IndexVal = CI->getSExtValue(); - if (IndexVal < 0 || (IndexVal != 0 && (uint64_t)IndexVal >= NumElements)) - return false; - - // Otherwise, it is in-range. - return true; -} - // Combine Indices - If the source pointer to this getelementptr instruction // is a getelementptr instruction, combine the indices of the two // getelementptr instructions into a single instruction. @@ -1572,157 +1528,5 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C, if (Constant *C = foldGEPOfGEP(GEP, PointeeTy, InBounds, Idxs)) return C; - // Check to see if any array indices are not within the corresponding - // notional array or vector bounds. If so, try to determine if they can be - // factored out into preceding dimensions. - SmallVector<Constant *, 8> NewIdxs; - Type *Ty = PointeeTy; - Type *Prev = C->getType(); - auto GEPIter = gep_type_begin(PointeeTy, Idxs); - bool Unknown = - !isa<ConstantInt>(Idxs[0]) && !isa<ConstantDataVector>(Idxs[0]); - for (unsigned i = 1, e = Idxs.size(); i != e; - Prev = Ty, Ty = (++GEPIter).getIndexedType(), ++i) { - if (!isa<ConstantInt>(Idxs[i]) && !isa<ConstantDataVector>(Idxs[i])) { - // We don't know if it's in range or not. - Unknown = true; - continue; - } - if (!isa<ConstantInt>(Idxs[i - 1]) && !isa<ConstantDataVector>(Idxs[i - 1])) - // Skip if the type of the previous index is not supported. - continue; - if (isa<StructType>(Ty)) { - // The verify makes sure that GEPs into a struct are in range. - continue; - } - if (isa<VectorType>(Ty)) { - // There can be awkward padding in after a non-power of two vector. - Unknown = true; - continue; - } - auto *STy = cast<ArrayType>(Ty); - if (ConstantInt *CI = dyn_cast<ConstantInt>(Idxs[i])) { - if (isIndexInRangeOfArrayType(STy->getNumElements(), CI)) - // It's in range, skip to the next index. - continue; - if (CI->isNegative()) { - // It's out of range and negative, don't try to factor it. - Unknown = true; - continue; - } - } else { - auto *CV = cast<ConstantDataVector>(Idxs[i]); - bool IsInRange = true; - for (unsigned I = 0, E = CV->getNumElements(); I != E; ++I) { - auto *CI = cast<ConstantInt>(CV->getElementAsConstant(I)); - IsInRange &= isIndexInRangeOfArrayType(STy->getNumElements(), CI); - if (CI->isNegative()) { - Unknown = true; - break; - } - } - if (IsInRange || Unknown) - // It's in range, skip to the next index. - // It's out of range and negative, don't try to factor it. - continue; - } - if (isa<StructType>(Prev)) { - // It's out of range, but the prior dimension is a struct - // so we can't do anything about it. - Unknown = true; - continue; - } - - // Determine the number of elements in our sequential type. - uint64_t NumElements = STy->getArrayNumElements(); - if (!NumElements) { - Unknown = true; - continue; - } - - // It's out of range, but we can factor it into the prior - // dimension. - NewIdxs.resize(Idxs.size()); - - // Expand the current index or the previous index to a vector from a scalar - // if necessary. - Constant *CurrIdx = cast<Constant>(Idxs[i]); - auto *PrevIdx = - NewIdxs[i - 1] ? NewIdxs[i - 1] : cast<Constant>(Idxs[i - 1]); - bool IsCurrIdxVector = CurrIdx->getType()->isVectorTy(); - bool IsPrevIdxVector = PrevIdx->getType()->isVectorTy(); - bool UseVector = IsCurrIdxVector || IsPrevIdxVector; - - if (!IsCurrIdxVector && IsPrevIdxVector) - CurrIdx = ConstantDataVector::getSplat( - cast<FixedVectorType>(PrevIdx->getType())->getNumElements(), CurrIdx); - - if (!IsPrevIdxVector && IsCurrIdxVector) - PrevIdx = ConstantDataVector::getSplat( - cast<FixedVectorType>(CurrIdx->getType())->getNumElements(), PrevIdx); - - Constant *Factor = - ConstantInt::get(CurrIdx->getType()->getScalarType(), NumElements); - if (UseVector) - Factor = ConstantDataVector::getSplat( - IsPrevIdxVector - ? cast<FixedVectorType>(PrevIdx->getType())->getNumElements() - : cast<FixedVectorType>(CurrIdx->getType())->getNumElements(), - Factor); - - NewIdxs[i] = - ConstantFoldBinaryInstruction(Instruction::SRem, CurrIdx, Factor); - - Constant *Div = - ConstantFoldBinaryInstruction(Instruction::SDiv, CurrIdx, Factor); - - // We're working on either ConstantInt or vectors of ConstantInt, - // so these should always fold. - assert(NewIdxs[i] != nullptr && Div != nullptr && "Should have folded"); - - unsigned CommonExtendedWidth = - std::max(PrevIdx->getType()->getScalarSizeInBits(), - Div->getType()->getScalarSizeInBits()); - CommonExtendedWidth = std::max(CommonExtendedWidth, 64U); - - // Before adding, extend both operands to i64 to avoid - // overflow trouble. - Type *ExtendedTy = Type::getIntNTy(Div->getContext(), CommonExtendedWidth); - if (UseVector) - ExtendedTy = FixedVectorType::get( - ExtendedTy, - IsPrevIdxVector - ? cast<FixedVectorType>(PrevIdx->getType())->getNumElements() - : cast<FixedVectorType>(CurrIdx->getType())->getNumElements()); - - if (!PrevIdx->getType()->isIntOrIntVectorTy(CommonExtendedWidth)) - PrevIdx = - ConstantFoldCastInstruction(Instruction::SExt, PrevIdx, ExtendedTy); - - if (!Div->getType()->isIntOrIntVectorTy(CommonExtendedWidth)) - Div = ConstantFoldCastInstruction(Instruction::SExt, Div, ExtendedTy); - - assert(PrevIdx && Div && "Should have folded"); - NewIdxs[i - 1] = ConstantExpr::getAdd(PrevIdx, Div); - } - - // If we did any factoring, start over with the adjusted indices. - if (!NewIdxs.empty()) { - for (unsigned i = 0, e = Idxs.size(); i != e; ++i) - if (!NewIdxs[i]) NewIdxs[i] = cast<Constant>(Idxs[i]); - return ConstantExpr::getGetElementPtr(PointeeTy, C, NewIdxs, InBounds, - InRange); - } - - // If all indices are known integers and normalized, we can do a simple - // check for the "inbounds" property. - if (!Unknown && !InBounds) - if (auto *GV = dyn_cast<GlobalVariable>(C)) - if (!GV->hasExternalWeakLinkage() && GV->getValueType() == PointeeTy && - isInBoundsIndices(Idxs)) - // TODO(gep_nowrap): Can also set NUW here. - return ConstantExpr::getGetElementPtr( - PointeeTy, C, Idxs, GEPNoWrapFlags::inBounds(), InRange); - return nullptr; } |