diff options
author | David Green <david.green@arm.com> | 2025-08-19 10:37:17 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-08-19 10:37:17 +0100 |
commit | a7df02f83c74c7229a09b2f89a51b003075560ab (patch) | |
tree | ca07b562c02c152906c00834466057d5243a7ead /llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | |
parent | d286f2ef5578e8e6fb64fa00eefbec3c240063fb (diff) | |
download | llvm-a7df02f83c74c7229a09b2f89a51b003075560ab.zip llvm-a7df02f83c74c7229a09b2f89a51b003075560ab.tar.gz llvm-a7df02f83c74c7229a09b2f89a51b003075560ab.tar.bz2 |
[InstCombine] Make strlen optimization more resilient to different gep types. (#153623)
This makes the optimization in optimizeStringLength for strlen(gep
@glob, %x) -> sub endof@glob, %x a little more resilient, and maybe a
bit more correct for geps with non-array types.
Diffstat (limited to 'llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 17 |
1 files changed, 11 insertions, 6 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index cc4eb2d..2d6a748 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -20,6 +20,7 @@ #include "llvm/Analysis/Loads.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/Analysis/TargetLibraryInfo.h" +#include "llvm/Analysis/Utils/Local.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/AttributeMask.h" #include "llvm/IR/DataLayout.h" @@ -977,8 +978,14 @@ Value *LibCallSimplifier::optimizeStringLength(CallInst *CI, IRBuilderBase &B, // it's not very useful because calling strlen for a pointer of other types is // very uncommon. if (GEPOperator *GEP = dyn_cast<GEPOperator>(Src)) { - // TODO: Handle subobjects. - if (!isGEPBasedOnPointerToString(GEP, CharSize)) + unsigned BW = DL.getIndexTypeSizeInBits(GEP->getType()); + SmallMapVector<Value *, APInt, 4> VarOffsets; + APInt ConstOffset(BW, 0); + assert(CharSize % 8 == 0 && "Expected a multiple of 8 sized CharSize"); + // Check the gep is a single variable offset. + if (!GEP->collectOffset(DL, BW, VarOffsets, ConstOffset) || + VarOffsets.size() != 1 || ConstOffset != 0 || + VarOffsets.begin()->second != CharSize / 8) return nullptr; ConstantDataArraySlice Slice; @@ -1000,10 +1007,8 @@ Value *LibCallSimplifier::optimizeStringLength(CallInst *CI, IRBuilderBase &B, return nullptr; } - Value *Offset = GEP->getOperand(2); + Value *Offset = VarOffsets.begin()->first; KnownBits Known = computeKnownBits(Offset, DL, nullptr, CI, nullptr); - uint64_t ArrSize = - cast<ArrayType>(GEP->getSourceElementType())->getNumElements(); // If Offset is not provably in the range [0, NullTermIdx], we can still // optimize if we can prove that the program has undefined behavior when @@ -1011,7 +1016,7 @@ Value *LibCallSimplifier::optimizeStringLength(CallInst *CI, IRBuilderBase &B, // is a pointer to an object whose memory extent is NullTermIdx+1. if ((Known.isNonNegative() && Known.getMaxValue().ule(NullTermIdx)) || (isa<GlobalVariable>(GEP->getOperand(0)) && - NullTermIdx == ArrSize - 1)) { + NullTermIdx == Slice.Length - 1)) { Offset = B.CreateSExtOrTrunc(Offset, CI->getType()); return B.CreateSub(ConstantInt::get(CI->getType(), NullTermIdx), Offset); |