diff options
author | serge-sans-paille <sguelton@redhat.com> | 2022-04-11 13:38:31 +0200 |
---|---|---|
committer | serge-sans-paille <sguelton@redhat.com> | 2022-04-12 14:47:29 +0200 |
commit | e810d558093cff40caaa1aff24d289c76c59916d (patch) | |
tree | 7f58e9c2fab8bce98123adcf2f84545256f3e57d /llvm/lib/Analysis/ValueTracking.cpp | |
parent | 0231a90bc438f728c81087520d8d5d85101ed05b (diff) | |
download | llvm-e810d558093cff40caaa1aff24d289c76c59916d.zip llvm-e810d558093cff40caaa1aff24d289c76c59916d.tar.gz llvm-e810d558093cff40caaa1aff24d289c76c59916d.tar.bz2 |
[ValueTracking] Make getStringLenth aware of strdup
During strlen compile-time evaluation, make it possible to track size of
strduped strings.
Differential Revision: https://reviews.llvm.org/D123497
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 75381f5..c4ceb91 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -4199,7 +4199,8 @@ bool llvm::getConstantStringInfo(const Value *V, StringRef &Str, /// If we can compute the length of the string pointed to by /// the specified pointer, return 'len+1'. If we can't, return 0. static uint64_t GetStringLengthH(const Value *V, - SmallPtrSetImpl<const PHINode*> &PHIs, + SmallPtrSetImpl<const PHINode *> &PHIs, + const TargetLibraryInfo *TLI, unsigned CharSize) { // Look through noop bitcast instructions. V = V->stripPointerCasts(); @@ -4213,7 +4214,7 @@ static uint64_t GetStringLengthH(const Value *V, // If it was new, see if all the input strings are the same length. uint64_t LenSoFar = ~0ULL; for (Value *IncValue : PN->incoming_values()) { - uint64_t Len = GetStringLengthH(IncValue, PHIs, CharSize); + uint64_t Len = GetStringLengthH(IncValue, PHIs, TLI, CharSize); if (Len == 0) return 0; // Unknown length -> unknown. if (Len == ~0ULL) continue; @@ -4229,9 +4230,9 @@ static uint64_t GetStringLengthH(const Value *V, // strlen(select(c,x,y)) -> strlen(x) ^ strlen(y) if (const SelectInst *SI = dyn_cast<SelectInst>(V)) { - uint64_t Len1 = GetStringLengthH(SI->getTrueValue(), PHIs, CharSize); + uint64_t Len1 = GetStringLengthH(SI->getTrueValue(), PHIs, TLI, CharSize); if (Len1 == 0) return 0; - uint64_t Len2 = GetStringLengthH(SI->getFalseValue(), PHIs, CharSize); + uint64_t Len2 = GetStringLengthH(SI->getFalseValue(), PHIs, TLI, CharSize); if (Len2 == 0) return 0; if (Len1 == ~0ULL) return Len2; if (Len2 == ~0ULL) return Len1; @@ -4239,6 +4240,22 @@ static uint64_t GetStringLengthH(const Value *V, return Len1; } + if (auto *CB = dyn_cast<CallBase>(V)) { + Function *Callee = CB->getCalledFunction(); + if (!Callee) + return 0; + + LibFunc TLIFn; + if (!TLI || !TLI->getLibFunc(*CB->getCalledFunction(), TLIFn) || + !TLI->has(TLIFn)) + return 0; + + if (TLIFn == LibFunc_strdup || TLIFn == LibFunc_dunder_strdup) + return GetStringLengthH(CB->getArgOperand(0), PHIs, TLI, CharSize); + + return 0; + } + // Otherwise, see if we can read the string. ConstantDataArraySlice Slice; if (!getConstantDataArrayInfo(V, Slice, CharSize)) @@ -4259,12 +4276,13 @@ static uint64_t GetStringLengthH(const Value *V, /// If we can compute the length of the string pointed to by /// the specified pointer, return 'len+1'. If we can't, return 0. -uint64_t llvm::GetStringLength(const Value *V, unsigned CharSize) { +uint64_t llvm::GetStringLength(const Value *V, const TargetLibraryInfo *TLI, + unsigned CharSize) { if (!V->getType()->isPointerTy()) return 0; SmallPtrSet<const PHINode*, 32> PHIs; - uint64_t Len = GetStringLengthH(V, PHIs, CharSize); + uint64_t Len = GetStringLengthH(V, PHIs, TLI, CharSize); // If Len is ~0ULL, we had an infinite phi cycle: this is dead code, so return // an empty string as a length. return Len == ~0ULL ? 1 : Len; |