aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Analysis/ValueTracking.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Analysis/ValueTracking.cpp')
-rw-r--r--llvm/lib/Analysis/ValueTracking.cpp30
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;