[PATCH] Optimize memcmp(x, y, n)==0 for small n and suitably aligned x/y.
Eelis
eelis at eelis.net
Tue Jan 13 11:20:39 PST 2015
This fixes http://llvm.org/bugs/show_bug.cgi?id=20673
http://reviews.llvm.org/D6952
Files:
lib/Transforms/Utils/SimplifyLibCalls.cpp
test/Transforms/InstCombine/memcmp-1.ll
Index: lib/Transforms/Utils/SimplifyLibCalls.cpp
===================================================================
--- lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -32,6 +32,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/Transforms/Utils/BuildLibCalls.h"
+#include "llvm/Transforms/Utils/Local.h"
using namespace llvm;
using namespace PatternMatch;
@@ -949,6 +950,27 @@
return B.CreateSub(LHSV, RHSV, "chardiff");
}
+ // memcmp(S1,S2,8)==0 -> (*(int64_t*)S1 != *(int64_t*)S2)==0
+ // (And same for 16/32 bit.)
+ if (Len <= 8 && !(Len & (Len-1))
+ && isOnlyUsedInZeroEqualityComparison(CI)
+ && getKnownAlignment(LHS, DL, nullptr, CI) >= Len
+ && getKnownAlignment(RHS, DL, nullptr, CI) >= Len) {
+
+ if (Type *IntType = IntegerType::get(CI->getContext(), Len << 3)) {
+
+ Type *LHSPtrTy = PointerType::get(IntType,
+ cast<PointerType>(LHS->getType())->getAddressSpace());
+ Type *RHSPtrTy = PointerType::get(IntType,
+ cast<PointerType>(RHS->getType())->getAddressSpace());
+
+ Value *LHSV = B.CreateLoad(B.CreateBitCast(LHS, LHSPtrTy, "lhsc"), "lhsv");
+ Value *RHSV = B.CreateLoad(B.CreateBitCast(RHS, RHSPtrTy, "rhsc"), "rhsv");
+
+ return B.CreateZExt(B.CreateICmpNE(LHSV, RHSV), CI->getType(), "memcmp");
+ }
+ }
+
// Constant folding: memcmp(x, y, l) -> cnst (all arguments are constant)
StringRef LHSStr, RHSStr;
if (getConstantStringInfo(LHS, LHSStr) &&
Index: test/Transforms/InstCombine/memcmp-1.ll
===================================================================
--- test/Transforms/InstCombine/memcmp-1.ll
+++ test/Transforms/InstCombine/memcmp-1.ll
@@ -70,3 +70,54 @@
ret i32 %ret
; CHECK: ret i32 -1
}
+
+; Check memcmp(mem1, mem2, 8)==0 -> *(int64_t*)mem1 == *(int64_t*)mem2
+
+define i1 @test_simplify7(i64 %x, i64 %y) {
+; CHECK-label: @test_simplify7(
+ %x.addr = alloca i64, align 8
+ %y.addr = alloca i64, align 8
+ store i64 %x, i64* %x.addr, align 8
+ store i64 %y, i64* %y.addr, align 8
+ %xptr = bitcast i64* %x.addr to i8*
+ %yptr = bitcast i64* %y.addr to i8*
+ %call = call i32 @memcmp(i8* %xptr, i8* %yptr, i32 8)
+ %cmp = icmp eq i32 %call, 0
+ ret i1 %cmp
+; CHECK: %cmp = icmp eq i64 %x, %y
+; CHECK: ret i1 %cmp
+}
+
+; Check memcmp(mem1, mem2, 4)==0 -> *(int32_t*)mem1 == *(int32_t*)mem2
+
+define i1 @test_simplify8(i32 %x, i32 %y) {
+; CHECK-label: @test_simplify8(
+ %x.addr = alloca i32, align 4
+ %y.addr = alloca i32, align 4
+ store i32 %x, i32* %x.addr, align 4
+ store i32 %y, i32* %y.addr, align 4
+ %xptr = bitcast i32* %x.addr to i8*
+ %yptr = bitcast i32* %y.addr to i8*
+ %call = call i32 @memcmp(i8* %xptr, i8* %yptr, i32 4)
+ %cmp = icmp eq i32 %call, 0
+ ret i1 %cmp
+; CHECK: %cmp = icmp eq i32 %x, %y
+; CHECK: ret i1 %cmp
+}
+
+; Check memcmp(mem1, mem2, 2)==0 -> *(int16_t*)mem1 == *(int16_t*)mem2
+
+define i1 @test_simplify9(i16 %x, i16 %y) {
+; CHECK-label: @test_simplify9(
+ %x.addr = alloca i16, align 2
+ %y.addr = alloca i16, align 2
+ store i16 %x, i16* %x.addr, align 2
+ store i16 %y, i16* %y.addr, align 2
+ %xptr = bitcast i16* %x.addr to i8*
+ %yptr = bitcast i16* %y.addr to i8*
+ %call = call i32 @memcmp(i8* %xptr, i8* %yptr, i32 2)
+ %cmp = icmp eq i32 %call, 0
+ ret i1 %cmp
+; CHECK: %cmp = icmp eq i16 %x, %y
+; CHECK: ret i1 %cmp
+}
EMAIL PREFERENCES
http://reviews.llvm.org/settings/panel/emailpreferences/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D6952.18100.patch
Type: text/x-patch
Size: 3436 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150113/c14b7903/attachment.bin>
More information about the llvm-commits
mailing list