diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp index 2b5b2b05b2c..cb90bdc912a 100644 --- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp +++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp @@ -731,17 +731,17 @@ struct VISIBILITY_HIDDEN MemCmpOpt : public LibCallOptimization { !isa(FT->getParamType(1)) || FT->getReturnType() != Type::Int32Ty) return 0; - + Value *LHS = CI->getOperand(1), *RHS = CI->getOperand(2); - + if (LHS == RHS) // memcmp(s,s,x) -> 0 return Constant::getNullValue(CI->getType()); - + // Make sure we have a constant length. ConstantInt *LenC = dyn_cast(CI->getOperand(3)); if (!LenC) return 0; uint64_t Len = LenC->getZExtValue(); - + if (Len == 0) // memcmp(s1,s2,0) -> 0 return Constant::getNullValue(CI->getType()); @@ -750,18 +750,20 @@ struct VISIBILITY_HIDDEN MemCmpOpt : public LibCallOptimization { Value *RHSV = B.CreateLoad(CastToCStr(RHS, B), "rhsv"); return B.CreateZExt(B.CreateSub(LHSV, RHSV, "chardiff"), CI->getType()); } - + // memcmp(S1,S2,2) != 0 -> (*(short*)LHS ^ *(short*)RHS) != 0 // memcmp(S1,S2,4) != 0 -> (*(int*)LHS ^ *(int*)RHS) != 0 if ((Len == 2 || Len == 4) && IsOnlyUsedInZeroEqualityComparison(CI)) { - LHS = B.CreateBitCast(LHS, PointerType::getUnqual(Type::Int16Ty), "tmp"); - RHS = B.CreateBitCast(RHS, LHS->getType(), "tmp"); + const Type *PTy = PointerType::getUnqual(Len == 2 ? + Type::Int16Ty : Type::Int32Ty); + LHS = B.CreateBitCast(LHS, PTy, "tmp"); + RHS = B.CreateBitCast(RHS, PTy, "tmp"); LoadInst *LHSV = B.CreateLoad(LHS, "lhsv"); LoadInst *RHSV = B.CreateLoad(RHS, "rhsv"); LHSV->setAlignment(1); RHSV->setAlignment(1); // Unaligned loads. return B.CreateZExt(B.CreateXor(LHSV, RHSV, "shortdiff"), CI->getType()); } - + return 0; } }; diff --git a/test/Transforms/SimplifyLibCalls/2008-05-19-memcmp.ll b/test/Transforms/SimplifyLibCalls/2008-05-19-memcmp.ll new file mode 100644 index 00000000000..b6c0ffdb704 --- /dev/null +++ b/test/Transforms/SimplifyLibCalls/2008-05-19-memcmp.ll @@ -0,0 +1,14 @@ +; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | grep i32 +; PR2341 + +@_2E_str = external constant [5 x i8] ; <[5 x i8]*> [#uses=1] + +declare i32 @memcmp(i8*, i8*, i32) nounwind readonly + +define i1 @f(i8** %start_addr) { +entry: + %tmp4 = load i8** %start_addr, align 4 ; [#uses=1] + %tmp5 = call i32 @memcmp( i8* %tmp4, i8* getelementptr ([5 x i8]* @_2E_str, i32 0, i32 0), i32 4 ) nounwind readonly ; [#uses=1] + %tmp6 = icmp eq i32 %tmp5, 0 ; [#uses=1] + ret i1 %tmp6 +}