diff options
author | David Bolvansky <david.bolvansky@gmail.com> | 2018-08-10 04:32:54 +0000 |
---|---|---|
committer | David Bolvansky <david.bolvansky@gmail.com> | 2018-08-10 04:32:54 +0000 |
commit | 909889b2cbd55fbc4a5bb7f155bd286a82da1fef (patch) | |
tree | 90c700a32a4b9046e0a5155353274f6b67e662a4 /llvm/lib/Transforms/Utils | |
parent | 4351f04895a0fc8f9cba510db89cebed15c21257 (diff) | |
download | bcm5719-llvm-909889b2cbd55fbc4a5bb7f155bd286a82da1fef.tar.gz bcm5719-llvm-909889b2cbd55fbc4a5bb7f155bd286a82da1fef.zip |
[InstCombine] Transform str(n)cmp to memcmp
Summary:
Motivation examples:
int strcmp_memcmp() {
char buf[12];
return strcmp(buf, "key") == 0;
}
int strcmp_memcmp2() {
char buf[12];
return strcmp(buf, "key") != 0;
}
int strncmp_memcmp() {
char buf[12];
return strncmp(buf, "key", 3) == 0;
}
can be turned to memcmp.
See test file for more cases.
Reviewers: efriedma
Reviewed By: efriedma
Subscribers: spatel, llvm-commits
Differential Revision: https://reviews.llvm.org/D50233
llvm-svn: 339410
Diffstat (limited to 'llvm/lib/Transforms/Utils')
-rw-r--r-- | llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index 33371e71b91..67127af4a52 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -22,6 +22,7 @@ #include "llvm/Transforms/Utils/Local.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/Analysis/CaptureTracking.h" +#include "llvm/Analysis/Loads.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" @@ -150,6 +151,29 @@ static bool isLocallyOpenedFile(Value *File, CallInst *CI, IRBuilder<> &B, return true; } +static bool isOnlyUsedInComparisonWithZero(Value *V) { + for (User *U : V->users()) { + if (ICmpInst *IC = dyn_cast<ICmpInst>(U)) + if (Constant *C = dyn_cast<Constant>(IC->getOperand(1))) + if (C->isNullValue()) + continue; + // Unknown instruction. + return false; + } + return true; +} + +static bool canTransformToMemCmp(CallInst *CI, Value *Str, uint64_t Len, + const DataLayout &DL) { + if (!isOnlyUsedInComparisonWithZero(CI)) + return false; + + if (!isDereferenceableAndAlignedPointer(Str, 1, APInt(64, Len), DL)) + return false; + + return true; +} + //===----------------------------------------------------------------------===// // String and Memory Library Call Optimizations //===----------------------------------------------------------------------===// @@ -322,6 +346,21 @@ Value *LibCallSimplifier::optimizeStrCmp(CallInst *CI, IRBuilder<> &B) { B, DL, TLI); } + // strcmp to memcmp + if (!HasStr1 && HasStr2) { + if (canTransformToMemCmp(CI, Str1P, Len2, DL)) + return emitMemCmp( + Str1P, Str2P, + ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len2), B, DL, + TLI); + } else if (HasStr1 && !HasStr2) { + if (canTransformToMemCmp(CI, Str2P, Len1, DL)) + return emitMemCmp( + Str1P, Str2P, + ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len1), B, DL, + TLI); + } + return nullptr; } @@ -361,6 +400,26 @@ Value *LibCallSimplifier::optimizeStrNCmp(CallInst *CI, IRBuilder<> &B) { if (HasStr2 && Str2.empty()) // strncmp(x, "", n) -> *x return B.CreateZExt(B.CreateLoad(Str1P, "strcmpload"), CI->getType()); + uint64_t Len1 = GetStringLength(Str1P); + uint64_t Len2 = GetStringLength(Str2P); + + // strncmp to memcmp + if (!HasStr1 && HasStr2) { + Len2 = std::min(Len2, Length); + if (canTransformToMemCmp(CI, Str1P, Len2, DL)) + return emitMemCmp( + Str1P, Str2P, + ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len2), B, DL, + TLI); + } else if (HasStr1 && !HasStr2) { + Len1 = std::min(Len1, Length); + if (canTransformToMemCmp(CI, Str2P, Len1, DL)) + return emitMemCmp( + Str1P, Str2P, + ConstantInt::get(DL.getIntPtrType(CI->getContext()), Len1), B, DL, + TLI); + } + return nullptr; } |