aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
diff options
context:
space:
mode:
authorDavid Green <david.green@arm.com>2025-08-19 10:37:17 +0100
committerGitHub <noreply@github.com>2025-08-19 10:37:17 +0100
commita7df02f83c74c7229a09b2f89a51b003075560ab (patch)
treeca07b562c02c152906c00834466057d5243a7ead /llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
parentd286f2ef5578e8e6fb64fa00eefbec3c240063fb (diff)
downloadllvm-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.cpp17
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);