summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Utils
diff options
context:
space:
mode:
authorDavid Bolvansky <david.bolvansky@gmail.com>2018-08-10 04:32:54 +0000
committerDavid Bolvansky <david.bolvansky@gmail.com>2018-08-10 04:32:54 +0000
commit909889b2cbd55fbc4a5bb7f155bd286a82da1fef (patch)
tree90c700a32a4b9046e0a5155353274f6b67e662a4 /llvm/lib/Transforms/Utils
parent4351f04895a0fc8f9cba510db89cebed15c21257 (diff)
downloadbcm5719-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.cpp59
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;
}
OpenPOWER on IntegriCloud