Loading llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp +1 −50 Original line number Diff line number Diff line Loading @@ -104,54 +104,6 @@ static bool CallHasFloatingPointArgument(const CallInst *CI) { //===----------------------------------------------------------------------===// namespace { //===---------------------------------------===// // 'memcmp' Optimizations struct MemCmpOpt : public LibCallOptimization { virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { FunctionType *FT = Callee->getFunctionType(); if (FT->getNumParams() != 3 || !FT->getParamType(0)->isPointerTy() || !FT->getParamType(1)->isPointerTy() || !FT->getReturnType()->isIntegerTy(32)) return 0; Value *LHS = CI->getArgOperand(0), *RHS = CI->getArgOperand(1); if (LHS == RHS) // memcmp(s,s,x) -> 0 return Constant::getNullValue(CI->getType()); // Make sure we have a constant length. ConstantInt *LenC = dyn_cast<ConstantInt>(CI->getArgOperand(2)); if (!LenC) return 0; uint64_t Len = LenC->getZExtValue(); if (Len == 0) // memcmp(s1,s2,0) -> 0 return Constant::getNullValue(CI->getType()); // memcmp(S1,S2,1) -> *(unsigned char*)LHS - *(unsigned char*)RHS if (Len == 1) { Value *LHSV = B.CreateZExt(B.CreateLoad(CastToCStr(LHS, B), "lhsc"), CI->getType(), "lhsv"); Value *RHSV = B.CreateZExt(B.CreateLoad(CastToCStr(RHS, B), "rhsc"), CI->getType(), "rhsv"); return B.CreateSub(LHSV, RHSV, "chardiff"); } // Constant folding: memcmp(x, y, l) -> cnst (all arguments are constant) StringRef LHSStr, RHSStr; if (getConstantStringInfo(LHS, LHSStr) && getConstantStringInfo(RHS, RHSStr)) { // Make sure we're not reading out-of-bounds memory. if (Len > LHSStr.size() || Len > RHSStr.size()) return 0; uint64_t Ret = memcmp(LHSStr.data(), RHSStr.data(), Len); return ConstantInt::get(CI->getType(), Ret); } return 0; } }; //===---------------------------------------===// // 'memcpy' Optimizations Loading Loading @@ -887,7 +839,7 @@ namespace { StringMap<LibCallOptimization*> Optimizations; // Memory LibCall Optimizations MemCmpOpt MemCmp; MemCpyOpt MemCpy; MemMoveOpt MemMove; MemSetOpt MemSet; MemCpyOpt MemCpy; MemMoveOpt MemMove; MemSetOpt MemSet; // Math Library Optimizations CosOpt Cos; PowOpt Pow; Exp2Opt Exp2; UnaryDoubleFPOpt UnaryDoubleFP, UnsafeUnaryDoubleFP; Loading Loading @@ -954,7 +906,6 @@ void SimplifyLibCalls::AddOpt(LibFunc::Func F1, LibFunc::Func F2, /// we know. void SimplifyLibCalls::InitOptimizations() { // Memory LibCall Optimizations Optimizations["memcmp"] = &MemCmp; AddOpt(LibFunc::memcpy, &MemCpy); Optimizations["memmove"] = &MemMove; AddOpt(LibFunc::memset, &MemSet); Loading llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +53 −2 Original line number Diff line number Diff line Loading @@ -914,6 +914,51 @@ struct StrStrOpt : public LibCallOptimization { } }; struct MemCmpOpt : public LibCallOptimization { virtual Value *callOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { FunctionType *FT = Callee->getFunctionType(); if (FT->getNumParams() != 3 || !FT->getParamType(0)->isPointerTy() || !FT->getParamType(1)->isPointerTy() || !FT->getReturnType()->isIntegerTy(32)) return 0; Value *LHS = CI->getArgOperand(0), *RHS = CI->getArgOperand(1); if (LHS == RHS) // memcmp(s,s,x) -> 0 return Constant::getNullValue(CI->getType()); // Make sure we have a constant length. ConstantInt *LenC = dyn_cast<ConstantInt>(CI->getArgOperand(2)); if (!LenC) return 0; uint64_t Len = LenC->getZExtValue(); if (Len == 0) // memcmp(s1,s2,0) -> 0 return Constant::getNullValue(CI->getType()); // memcmp(S1,S2,1) -> *(unsigned char*)LHS - *(unsigned char*)RHS if (Len == 1) { Value *LHSV = B.CreateZExt(B.CreateLoad(CastToCStr(LHS, B), "lhsc"), CI->getType(), "lhsv"); Value *RHSV = B.CreateZExt(B.CreateLoad(CastToCStr(RHS, B), "rhsc"), CI->getType(), "rhsv"); return B.CreateSub(LHSV, RHSV, "chardiff"); } // Constant folding: memcmp(x, y, l) -> cnst (all arguments are constant) StringRef LHSStr, RHSStr; if (getConstantStringInfo(LHS, LHSStr) && getConstantStringInfo(RHS, RHSStr)) { // Make sure we're not reading out-of-bounds memory. if (Len > LHSStr.size() || Len > RHSStr.size()) return 0; uint64_t Ret = memcmp(LHSStr.data(), RHSStr.data(), Len); return ConstantInt::get(CI->getType(), Ret); } return 0; } }; } // End anonymous namespace. namespace llvm { Loading @@ -932,7 +977,7 @@ class LibCallSimplifierImpl { StpCpyChkOpt StpCpyChk; StrNCpyChkOpt StrNCpyChk; // String and memory library call optimizations. // String library call optimizations. StrCatOpt StrCat; StrNCatOpt StrNCat; StrChrOpt StrChr; Loading @@ -949,6 +994,9 @@ class LibCallSimplifierImpl { StrCSpnOpt StrCSpn; StrStrOpt StrStr; // Memory library call optimizations. MemCmpOpt MemCmp; void initOptimizations(); void addOpt(LibFunc::Func F, LibCallOptimization* Opt); public: Loading @@ -972,7 +1020,7 @@ void LibCallSimplifierImpl::initOptimizations() { Optimizations["__strncpy_chk"] = &StrNCpyChk; Optimizations["__stpncpy_chk"] = &StrNCpyChk; // String and memory library call optimizations. // String library call optimizations. addOpt(LibFunc::strcat, &StrCat); addOpt(LibFunc::strncat, &StrNCat); addOpt(LibFunc::strchr, &StrChr); Loading @@ -994,6 +1042,9 @@ void LibCallSimplifierImpl::initOptimizations() { addOpt(LibFunc::strspn, &StrSpn); addOpt(LibFunc::strcspn, &StrCSpn); addOpt(LibFunc::strstr, &StrStr); // Memory library call optimizations. addOpt(LibFunc::memcmp, &MemCmp); } Value *LibCallSimplifierImpl::optimizeCall(CallInst *CI) { Loading llvm/test/Transforms/InstCombine/memcmp-1.ll 0 → 100644 +63 −0 Original line number Diff line number Diff line ; Test that the memcmp library call simplifier works correctly. ; ; RUN: opt < %s -instcombine -S | FileCheck %s target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" @foo = constant [4 x i8] c"foo\00" @hel = constant [4 x i8] c"hel\00" @hello_u = constant [8 x i8] c"hello_u\00" declare i32 @memcmp(i8*, i8*, i32) ; Check memcmp(mem, mem, size) -> 0. define i32 @test_simplify1(i8* %mem, i32 %size) { ; CHECK: @test_simplify1 %ret = call i32 @memcmp(i8* %mem, i8* %mem, i32 %size) ret i32 %ret ; CHECK: ret i32 0 } ; Check memcmp(mem1, mem2, 0) -> 0. define i32 @test_simplify2(i8* %mem1, i8* %mem2) { ; CHECK: @test_simplify2 %ret = call i32 @memcmp(i8* %mem1, i8* %mem2, i32 0) ret i32 %ret ; CHECK: ret i32 0 } ;; Check memcmp(mem1, mem2, 1) -> *(unsigned char*)mem1 - *(unsigned char*)mem2. define i32 @test_simplify3(i8* %mem1, i8* %mem2) { ; CHECK: @test_simplify3 %ret = call i32 @memcmp(i8* %mem1, i8* %mem2, i32 1) ; CHECK: [[LOAD1:%[a-z]+]] = load i8* %mem1, align 1 ; CHECK: [[ZEXT1:%[a-z]+]] = zext i8 [[LOAD1]] to i32 ; CHECK: [[LOAD2:%[a-z]+]] = load i8* %mem2, align 1 ; CHECK: [[ZEXT2:%[a-z]+]] = zext i8 [[LOAD2]] to i32 ; CHECK: [[RET:%[a-z]+]] = sub i32 [[ZEXT1]], [[ZEXT2]] ret i32 %ret ; CHECK: ret i32 [[RET]] } ; Check memcmp(mem1, mem2, size) -> cnst, where all arguments are constants. define i32 @test_simplify4() { ; CHECK: @test_simplify4 %mem1 = getelementptr [4 x i8]* @hel, i32 0, i32 0 %mem2 = getelementptr [8 x i8]* @hello_u, i32 0, i32 0 %ret = call i32 @memcmp(i8* %mem1, i8* %mem2, i32 3) ret i32 %ret ; CHECK: ret i32 0 } define i32 @test_simplify5() { ; CHECK: @test_simplify5 %mem1 = getelementptr [4 x i8]* @hel, i32 0, i32 0 %mem2 = getelementptr [4 x i8]* @foo, i32 0, i32 0 %ret = call i32 @memcmp(i8* %mem1, i8* %mem2, i32 3) ret i32 %ret ; CHECK: ret i32 2 } llvm/test/Transforms/InstCombine/memcmp-2.ll 0 → 100644 +17 −0 Original line number Diff line number Diff line ; Test that the memcmp library call simplifier works correctly. ; ; RUN: opt < %s -instcombine -S | FileCheck %s target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" declare i32* @memcmp(i8*, i8*, i32) ; Check that memcmp functions with the wrong prototype aren't simplified. define i32* @test_no_simplify1(i8* %mem, i32 %size) { ; CHECK: @test_no_simplify1 %ret = call i32* @memcmp(i8* %mem, i8* %mem, i32 %size) ; CHECK-NEXT: call i32* @memcmp ret i32* %ret ; CHECK-NEXT: ret i32* %ret } llvm/test/Transforms/InstCombine/strncmp-1.ll +6 −4 Original line number Diff line number Diff line Loading @@ -67,12 +67,14 @@ define i32 @test5() { } ; strncmp(x,y,1) -> memcmp(x,y,1) ; TODO: Once the memcmp simplifier gets moved into the instcombine pass ; the following memcmp will be folded into two loads and a subtract. define i32 @test6(i8* %str1, i8* %str2) { ; CHECK: @test6 ; CHECK: call i32 @memcmp ; CHECK: ret i32 %memcmp ; CHECK: [[LOAD1:%[a-z]+]] = load i8* %str1, align 1 ; CHECK: [[ZEXT1:%[a-z]+]] = zext i8 [[LOAD1]] to i32 ; CHECK: [[LOAD2:%[a-z]+]] = load i8* %str2, align 1 ; CHECK: [[ZEXT2:%[a-z]+]] = zext i8 [[LOAD2]] to i32 ; CHECK: [[RET:%[a-z]+]] = sub i32 [[ZEXT1]], [[ZEXT2]] ; CHECK: ret i32 [[RET]] %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 1) ret i32 %temp1 Loading Loading
llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp +1 −50 Original line number Diff line number Diff line Loading @@ -104,54 +104,6 @@ static bool CallHasFloatingPointArgument(const CallInst *CI) { //===----------------------------------------------------------------------===// namespace { //===---------------------------------------===// // 'memcmp' Optimizations struct MemCmpOpt : public LibCallOptimization { virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { FunctionType *FT = Callee->getFunctionType(); if (FT->getNumParams() != 3 || !FT->getParamType(0)->isPointerTy() || !FT->getParamType(1)->isPointerTy() || !FT->getReturnType()->isIntegerTy(32)) return 0; Value *LHS = CI->getArgOperand(0), *RHS = CI->getArgOperand(1); if (LHS == RHS) // memcmp(s,s,x) -> 0 return Constant::getNullValue(CI->getType()); // Make sure we have a constant length. ConstantInt *LenC = dyn_cast<ConstantInt>(CI->getArgOperand(2)); if (!LenC) return 0; uint64_t Len = LenC->getZExtValue(); if (Len == 0) // memcmp(s1,s2,0) -> 0 return Constant::getNullValue(CI->getType()); // memcmp(S1,S2,1) -> *(unsigned char*)LHS - *(unsigned char*)RHS if (Len == 1) { Value *LHSV = B.CreateZExt(B.CreateLoad(CastToCStr(LHS, B), "lhsc"), CI->getType(), "lhsv"); Value *RHSV = B.CreateZExt(B.CreateLoad(CastToCStr(RHS, B), "rhsc"), CI->getType(), "rhsv"); return B.CreateSub(LHSV, RHSV, "chardiff"); } // Constant folding: memcmp(x, y, l) -> cnst (all arguments are constant) StringRef LHSStr, RHSStr; if (getConstantStringInfo(LHS, LHSStr) && getConstantStringInfo(RHS, RHSStr)) { // Make sure we're not reading out-of-bounds memory. if (Len > LHSStr.size() || Len > RHSStr.size()) return 0; uint64_t Ret = memcmp(LHSStr.data(), RHSStr.data(), Len); return ConstantInt::get(CI->getType(), Ret); } return 0; } }; //===---------------------------------------===// // 'memcpy' Optimizations Loading Loading @@ -887,7 +839,7 @@ namespace { StringMap<LibCallOptimization*> Optimizations; // Memory LibCall Optimizations MemCmpOpt MemCmp; MemCpyOpt MemCpy; MemMoveOpt MemMove; MemSetOpt MemSet; MemCpyOpt MemCpy; MemMoveOpt MemMove; MemSetOpt MemSet; // Math Library Optimizations CosOpt Cos; PowOpt Pow; Exp2Opt Exp2; UnaryDoubleFPOpt UnaryDoubleFP, UnsafeUnaryDoubleFP; Loading Loading @@ -954,7 +906,6 @@ void SimplifyLibCalls::AddOpt(LibFunc::Func F1, LibFunc::Func F2, /// we know. void SimplifyLibCalls::InitOptimizations() { // Memory LibCall Optimizations Optimizations["memcmp"] = &MemCmp; AddOpt(LibFunc::memcpy, &MemCpy); Optimizations["memmove"] = &MemMove; AddOpt(LibFunc::memset, &MemSet); Loading
llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +53 −2 Original line number Diff line number Diff line Loading @@ -914,6 +914,51 @@ struct StrStrOpt : public LibCallOptimization { } }; struct MemCmpOpt : public LibCallOptimization { virtual Value *callOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { FunctionType *FT = Callee->getFunctionType(); if (FT->getNumParams() != 3 || !FT->getParamType(0)->isPointerTy() || !FT->getParamType(1)->isPointerTy() || !FT->getReturnType()->isIntegerTy(32)) return 0; Value *LHS = CI->getArgOperand(0), *RHS = CI->getArgOperand(1); if (LHS == RHS) // memcmp(s,s,x) -> 0 return Constant::getNullValue(CI->getType()); // Make sure we have a constant length. ConstantInt *LenC = dyn_cast<ConstantInt>(CI->getArgOperand(2)); if (!LenC) return 0; uint64_t Len = LenC->getZExtValue(); if (Len == 0) // memcmp(s1,s2,0) -> 0 return Constant::getNullValue(CI->getType()); // memcmp(S1,S2,1) -> *(unsigned char*)LHS - *(unsigned char*)RHS if (Len == 1) { Value *LHSV = B.CreateZExt(B.CreateLoad(CastToCStr(LHS, B), "lhsc"), CI->getType(), "lhsv"); Value *RHSV = B.CreateZExt(B.CreateLoad(CastToCStr(RHS, B), "rhsc"), CI->getType(), "rhsv"); return B.CreateSub(LHSV, RHSV, "chardiff"); } // Constant folding: memcmp(x, y, l) -> cnst (all arguments are constant) StringRef LHSStr, RHSStr; if (getConstantStringInfo(LHS, LHSStr) && getConstantStringInfo(RHS, RHSStr)) { // Make sure we're not reading out-of-bounds memory. if (Len > LHSStr.size() || Len > RHSStr.size()) return 0; uint64_t Ret = memcmp(LHSStr.data(), RHSStr.data(), Len); return ConstantInt::get(CI->getType(), Ret); } return 0; } }; } // End anonymous namespace. namespace llvm { Loading @@ -932,7 +977,7 @@ class LibCallSimplifierImpl { StpCpyChkOpt StpCpyChk; StrNCpyChkOpt StrNCpyChk; // String and memory library call optimizations. // String library call optimizations. StrCatOpt StrCat; StrNCatOpt StrNCat; StrChrOpt StrChr; Loading @@ -949,6 +994,9 @@ class LibCallSimplifierImpl { StrCSpnOpt StrCSpn; StrStrOpt StrStr; // Memory library call optimizations. MemCmpOpt MemCmp; void initOptimizations(); void addOpt(LibFunc::Func F, LibCallOptimization* Opt); public: Loading @@ -972,7 +1020,7 @@ void LibCallSimplifierImpl::initOptimizations() { Optimizations["__strncpy_chk"] = &StrNCpyChk; Optimizations["__stpncpy_chk"] = &StrNCpyChk; // String and memory library call optimizations. // String library call optimizations. addOpt(LibFunc::strcat, &StrCat); addOpt(LibFunc::strncat, &StrNCat); addOpt(LibFunc::strchr, &StrChr); Loading @@ -994,6 +1042,9 @@ void LibCallSimplifierImpl::initOptimizations() { addOpt(LibFunc::strspn, &StrSpn); addOpt(LibFunc::strcspn, &StrCSpn); addOpt(LibFunc::strstr, &StrStr); // Memory library call optimizations. addOpt(LibFunc::memcmp, &MemCmp); } Value *LibCallSimplifierImpl::optimizeCall(CallInst *CI) { Loading
llvm/test/Transforms/InstCombine/memcmp-1.ll 0 → 100644 +63 −0 Original line number Diff line number Diff line ; Test that the memcmp library call simplifier works correctly. ; ; RUN: opt < %s -instcombine -S | FileCheck %s target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" @foo = constant [4 x i8] c"foo\00" @hel = constant [4 x i8] c"hel\00" @hello_u = constant [8 x i8] c"hello_u\00" declare i32 @memcmp(i8*, i8*, i32) ; Check memcmp(mem, mem, size) -> 0. define i32 @test_simplify1(i8* %mem, i32 %size) { ; CHECK: @test_simplify1 %ret = call i32 @memcmp(i8* %mem, i8* %mem, i32 %size) ret i32 %ret ; CHECK: ret i32 0 } ; Check memcmp(mem1, mem2, 0) -> 0. define i32 @test_simplify2(i8* %mem1, i8* %mem2) { ; CHECK: @test_simplify2 %ret = call i32 @memcmp(i8* %mem1, i8* %mem2, i32 0) ret i32 %ret ; CHECK: ret i32 0 } ;; Check memcmp(mem1, mem2, 1) -> *(unsigned char*)mem1 - *(unsigned char*)mem2. define i32 @test_simplify3(i8* %mem1, i8* %mem2) { ; CHECK: @test_simplify3 %ret = call i32 @memcmp(i8* %mem1, i8* %mem2, i32 1) ; CHECK: [[LOAD1:%[a-z]+]] = load i8* %mem1, align 1 ; CHECK: [[ZEXT1:%[a-z]+]] = zext i8 [[LOAD1]] to i32 ; CHECK: [[LOAD2:%[a-z]+]] = load i8* %mem2, align 1 ; CHECK: [[ZEXT2:%[a-z]+]] = zext i8 [[LOAD2]] to i32 ; CHECK: [[RET:%[a-z]+]] = sub i32 [[ZEXT1]], [[ZEXT2]] ret i32 %ret ; CHECK: ret i32 [[RET]] } ; Check memcmp(mem1, mem2, size) -> cnst, where all arguments are constants. define i32 @test_simplify4() { ; CHECK: @test_simplify4 %mem1 = getelementptr [4 x i8]* @hel, i32 0, i32 0 %mem2 = getelementptr [8 x i8]* @hello_u, i32 0, i32 0 %ret = call i32 @memcmp(i8* %mem1, i8* %mem2, i32 3) ret i32 %ret ; CHECK: ret i32 0 } define i32 @test_simplify5() { ; CHECK: @test_simplify5 %mem1 = getelementptr [4 x i8]* @hel, i32 0, i32 0 %mem2 = getelementptr [4 x i8]* @foo, i32 0, i32 0 %ret = call i32 @memcmp(i8* %mem1, i8* %mem2, i32 3) ret i32 %ret ; CHECK: ret i32 2 }
llvm/test/Transforms/InstCombine/memcmp-2.ll 0 → 100644 +17 −0 Original line number Diff line number Diff line ; Test that the memcmp library call simplifier works correctly. ; ; RUN: opt < %s -instcombine -S | FileCheck %s target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" declare i32* @memcmp(i8*, i8*, i32) ; Check that memcmp functions with the wrong prototype aren't simplified. define i32* @test_no_simplify1(i8* %mem, i32 %size) { ; CHECK: @test_no_simplify1 %ret = call i32* @memcmp(i8* %mem, i8* %mem, i32 %size) ; CHECK-NEXT: call i32* @memcmp ret i32* %ret ; CHECK-NEXT: ret i32* %ret }
llvm/test/Transforms/InstCombine/strncmp-1.ll +6 −4 Original line number Diff line number Diff line Loading @@ -67,12 +67,14 @@ define i32 @test5() { } ; strncmp(x,y,1) -> memcmp(x,y,1) ; TODO: Once the memcmp simplifier gets moved into the instcombine pass ; the following memcmp will be folded into two loads and a subtract. define i32 @test6(i8* %str1, i8* %str2) { ; CHECK: @test6 ; CHECK: call i32 @memcmp ; CHECK: ret i32 %memcmp ; CHECK: [[LOAD1:%[a-z]+]] = load i8* %str1, align 1 ; CHECK: [[ZEXT1:%[a-z]+]] = zext i8 [[LOAD1]] to i32 ; CHECK: [[LOAD2:%[a-z]+]] = load i8* %str2, align 1 ; CHECK: [[ZEXT2:%[a-z]+]] = zext i8 [[LOAD2]] to i32 ; CHECK: [[RET:%[a-z]+]] = sub i32 [[ZEXT1]], [[ZEXT2]] ; CHECK: ret i32 [[RET]] %temp1 = call i32 @strncmp(i8* %str1, i8* %str2, i32 1) ret i32 %temp1 Loading