From 489b5d645f370926894c88d8e5fd27f17aabff82 Mon Sep 17 00:00:00 2001 From: Meador Inge Date: Thu, 8 Nov 2012 01:33:50 +0000 Subject: [PATCH] instcombine: Migrate strspn optimizations This patch migrates the strspn optimizations from the simplify-libcalls pass into the instcombine library call simplifier. llvm-svn: 167568 --- llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp | 35 +--------------- llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 31 ++++++++++++++ llvm/test/Transforms/InstCombine/strspn-1.ll | 56 +++++++++++++++++++++++++ llvm/test/Transforms/SimplifyLibCalls/StrSpn.ll | 16 ------- 4 files changed, 88 insertions(+), 50 deletions(-) create mode 100644 llvm/test/Transforms/InstCombine/strspn-1.ll diff --git a/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp index bacada5..7d652de 100644 --- a/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Scalar/SimplifyLibCalls.cpp @@ -119,38 +119,6 @@ static bool IsOnlyUsedInEqualityComparison(Value *V, Value *With) { namespace { //===---------------------------------------===// -// 'strspn' Optimizations - -struct StrSpnOpt : public LibCallOptimization { - virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { - FunctionType *FT = Callee->getFunctionType(); - if (FT->getNumParams() != 2 || - FT->getParamType(0) != B.getInt8PtrTy() || - FT->getParamType(1) != FT->getParamType(0) || - !FT->getReturnType()->isIntegerTy()) - return 0; - - StringRef S1, S2; - bool HasS1 = getConstantStringInfo(CI->getArgOperand(0), S1); - bool HasS2 = getConstantStringInfo(CI->getArgOperand(1), S2); - - // strspn(s, "") -> 0 - // strspn("", s) -> 0 - if ((HasS1 && S1.empty()) || (HasS2 && S2.empty())) - return Constant::getNullValue(CI->getType()); - - // Constant folding. - if (HasS1 && HasS2) { - size_t Pos = S1.find_first_not_of(S2); - if (Pos == StringRef::npos) Pos = S1.size(); - return ConstantInt::get(CI->getType(), Pos); - } - - return 0; - } -}; - -//===---------------------------------------===// // 'strcspn' Optimizations struct StrCSpnOpt : public LibCallOptimization { @@ -1037,7 +1005,7 @@ namespace { StringMap Optimizations; // String and Memory LibCall Optimizations - StrSpnOpt StrSpn; StrCSpnOpt StrCSpn; StrStrOpt StrStr; + StrCSpnOpt StrCSpn; StrStrOpt StrStr; MemCmpOpt MemCmp; MemCpyOpt MemCpy; MemMoveOpt MemMove; MemSetOpt MemSet; // Math Library Optimizations CosOpt Cos; PowOpt Pow; Exp2Opt Exp2; @@ -1105,7 +1073,6 @@ void SimplifyLibCalls::AddOpt(LibFunc::Func F1, LibFunc::Func F2, /// we know. void SimplifyLibCalls::InitOptimizations() { // String and Memory LibCall Optimizations - Optimizations["strspn"] = &StrSpn; Optimizations["strcspn"] = &StrCSpn; Optimizations["strstr"] = &StrStr; Optimizations["memcmp"] = &MemCmp; diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index 581b8d3..64c7011 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -772,6 +772,35 @@ struct StrToOpt : public LibCallOptimization { } }; +struct StrSpnOpt : public LibCallOptimization { + virtual Value *callOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 2 || + FT->getParamType(0) != B.getInt8PtrTy() || + FT->getParamType(1) != FT->getParamType(0) || + !FT->getReturnType()->isIntegerTy()) + return 0; + + StringRef S1, S2; + bool HasS1 = getConstantStringInfo(CI->getArgOperand(0), S1); + bool HasS2 = getConstantStringInfo(CI->getArgOperand(1), S2); + + // strspn(s, "") -> 0 + // strspn("", s) -> 0 + if ((HasS1 && S1.empty()) || (HasS2 && S2.empty())) + return Constant::getNullValue(CI->getType()); + + // Constant folding. + if (HasS1 && HasS2) { + size_t Pos = S1.find_first_not_of(S2); + if (Pos == StringRef::npos) Pos = S1.size(); + return ConstantInt::get(CI->getType(), Pos); + } + + return 0; + } +}; + } // End anonymous namespace. namespace llvm { @@ -802,6 +831,7 @@ class LibCallSimplifierImpl { StrLenOpt StrLen; StrPBrkOpt StrPBrk; StrToOpt StrTo; + StrSpnOpt StrSpn; void initOptimizations(); public: @@ -842,6 +872,7 @@ void LibCallSimplifierImpl::initOptimizations() { Optimizations["strtoll"] = &StrTo; Optimizations["strtold"] = &StrTo; Optimizations["strtoull"] = &StrTo; + Optimizations["strspn"] = &StrSpn; } Value *LibCallSimplifierImpl::optimizeCall(CallInst *CI) { diff --git a/llvm/test/Transforms/InstCombine/strspn-1.ll b/llvm/test/Transforms/InstCombine/strspn-1.ll new file mode 100644 index 0000000..393f887 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/strspn-1.ll @@ -0,0 +1,56 @@ +; Test that the strspn 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" + +@abcba = constant [6 x i8] c"abcba\00" +@abc = constant [4 x i8] c"abc\00" +@null = constant [1 x i8] zeroinitializer + +declare i64 @strspn(i8*, i8*) + +; Check strspn(s, "") -> 0. + +define i64 @test_simplify1(i8* %str) { +; CHECK: @test_simplify1 + %pat = getelementptr [1 x i8]* @null, i32 0, i32 0 + + %ret = call i64 @strspn(i8* %str, i8* %pat) + ret i64 %ret +; CHECK-NEXT: ret i64 0 +} + +; Check strspn("", s) -> 0. + +define i64 @test_simplify2(i8* %pat) { +; CHECK: @test_simplify2 + %str = getelementptr [1 x i8]* @null, i32 0, i32 0 + + %ret = call i64 @strspn(i8* %str, i8* %pat) + ret i64 %ret +; CHECK-NEXT: ret i64 0 +} + +; Check strspn(s1, s2), where s1 and s2 are constants. + +define i64 @test_simplify3() { +; CHECK: @test_simplify3 + %str = getelementptr [6 x i8]* @abcba, i32 0, i32 0 + %pat = getelementptr [4 x i8]* @abc, i32 0, i32 0 + + %ret = call i64 @strspn(i8* %str, i8* %pat) + ret i64 %ret +; CHECK-NEXT: ret i64 5 +} + +; Check cases that shouldn't be simplified. + +define i64 @test_no_simplify1(i8* %str, i8* %pat) { +; CHECK: @test_no_simplify1 + + %ret = call i64 @strspn(i8* %str, i8* %pat) +; CHECK-NEXT: %ret = call i64 @strspn(i8* %str, i8* %pat) + ret i64 %ret +; CHECK-NEXT: ret i64 %ret +} diff --git a/llvm/test/Transforms/SimplifyLibCalls/StrSpn.ll b/llvm/test/Transforms/SimplifyLibCalls/StrSpn.ll index 800c190..2660ee9 100644 --- a/llvm/test/Transforms/SimplifyLibCalls/StrSpn.ll +++ b/llvm/test/Transforms/SimplifyLibCalls/StrSpn.ll @@ -6,22 +6,6 @@ target datalayout = "-p:64:64:64" @abc = constant [4 x i8] c"abc\00" @null = constant [1 x i8] zeroinitializer -declare i64 @strspn(i8*, i8*) - -define i64 @testspn(i8* %s1, i8* %s2) { - %abcba_p = getelementptr [6 x i8]* @abcba, i32 0, i32 0 - %abc_p = getelementptr [4 x i8]* @abc, i32 0, i32 0 - %null_p = getelementptr [1 x i8]* @null, i32 0, i32 0 - %test1 = call i64 @strspn(i8* %s1, i8* %null_p) - %test2 = call i64 @strspn(i8* %null_p, i8* %s2) - %test3 = call i64 @strspn(i8* %abcba_p, i8* %abc_p) -; CHECK-NOT: call i64 @strspn - %test4 = call i64 @strspn(i8* %s1, i8* %s2) -; CHECK: call i64 @strspn(i8* %s1, i8* %s2) - ret i64 %test3 -; CHECK: ret i64 5 -} - declare i64 @strcspn(i8*, i8*) define i64 @testcspn(i8* %s1, i8* %s2) { -- 2.7.4