llvm.org GIT mirror llvm / 386e918
simplify-libcalls: fold strstr(a, b) == a -> strncmp(a, b, strlen(b)) == 0 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@106047 91177308-0d34-0410-b5e6-96231b3b80d8 Benjamin Kramer 10 years ago
4 changed file(s) with 72 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
3232 /// specified pointer and character. Ptr is required to be some pointer type,
3333 /// and the return value has 'i8*' type.
3434 Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B, const TargetData *TD);
35
36 /// EmitStrNCmp - Emit a call to the strncmp function to the builder.
37 Value *EmitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B,
38 const TargetData *TD);
3539
3640 /// EmitStrCpy - Emit a call to the strcpy function to the builder, for the
3741 /// specified pointer arguments.
9191 return true;
9292 }
9393
94 /// IsOnlyUsedInEqualityComparison - Return true if it is only used in equality
95 /// comparisons with With.
96 static bool IsOnlyUsedInEqualityComparison(Value *V, Value *With) {
97 for (Value::use_iterator UI = V->use_begin(), E = V->use_end();
98 UI != E; ++UI) {
99 if (ICmpInst *IC = dyn_cast(*UI))
100 if (IC->isEquality() && IC->getOperand(1) == With)
101 continue;
102 // Unknown instruction.
103 return false;
104 }
105 return true;
106 }
107
94108 //===----------------------------------------------------------------------===//
95109 // String and Memory LibCall Optimizations
96110 //===----------------------------------------------------------------------===//
501515 // fold strstr(x, x) -> x.
502516 if (CI->getOperand(1) == CI->getOperand(2))
503517 return B.CreateBitCast(CI->getOperand(1), CI->getType());
518
519 // fold strstr(a, b) == a -> strncmp(a, b, strlen(b)) == 0
520 if (TD && IsOnlyUsedInEqualityComparison(CI, CI->getOperand(1))) {
521 Value *StrLen = EmitStrLen(CI->getOperand(2), B, TD);
522 Value *StrNCmp = EmitStrNCmp(CI->getOperand(1), CI->getOperand(2),
523 StrLen, B, TD);
524 for (Value::use_iterator UI = CI->use_begin(), UE = CI->use_end();
525 UI != UE; ) {
526 ICmpInst *Old = cast(UI++);
527 Value *Cmp = B.CreateICmp(Old->getPredicate(), StrNCmp,
528 ConstantInt::getNullValue(StrNCmp->getType()),
529 "cmp");
530 Old->replaceAllUsesWith(Cmp);
531 Old->eraseFromParent();
532 }
533 return CI;
534 }
504535
505536 // See if either input string is a constant string.
506537 std::string SearchStr, ToFindStr;
6565 ConstantInt::get(I32Ty, C), "strchr");
6666 if (const Function *F = dyn_cast(StrChr->stripPointerCasts()))
6767 CI->setCallingConv(F->getCallingConv());
68 return CI;
69 }
70
71 /// EmitStrNCmp - Emit a call to the strncmp function to the builder.
72 Value *llvm::EmitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len,
73 IRBuilder<> &B, const TargetData *TD) {
74 Module *M = B.GetInsertBlock()->getParent()->getParent();
75 AttributeWithIndex AWI[3];
76 AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
77 AWI[1] = AttributeWithIndex::get(2, Attribute::NoCapture);
78 AWI[2] = AttributeWithIndex::get(~0u, Attribute::ReadOnly |
79 Attribute::NoUnwind);
80
81 LLVMContext &Context = B.GetInsertBlock()->getContext();
82 Value *StrNCmp = M->getOrInsertFunction("strncmp", AttrListPtr::get(AWI, 3),
83 B.getInt32Ty(),
84 B.getInt8PtrTy(),
85 B.getInt8PtrTy(),
86 TD->getIntPtrType(Context), NULL);
87 CallInst *CI = B.CreateCall3(StrNCmp, CastToCStr(Ptr1, B),
88 CastToCStr(Ptr2, B), Len, "strncmp");
89
90 if (const Function *F = dyn_cast(StrNCmp->stripPointerCasts()))
91 CI->setCallingConv(F->getCallingConv());
92
6893 return CI;
6994 }
7095
4545 ; CHECK: @test4
4646 ; CHECK: ret i8* %P
4747 }
48
49 define i1 @test5(i8* %P, i8* %Q) nounwind readonly {
50 entry:
51 %call = tail call i8* @strstr(i8* %P, i8* %Q) nounwind ; [#uses=1]
52 %cmp = icmp eq i8* %call, %P
53 ret i1 %cmp
54 ; CHECK: @test5
55 ; CHECK: [[LEN:%[a-z]+]] = call {{i[0-9]+}} @strlen(i8* %Q)
56 ; CHECK: [[NCMP:%[a-z]+]] = call {{i[0-9]+}} @strncmp(i8* %P, i8* %Q, {{i[0-9]+}} [[LEN]])
57 ; CHECK: icmp eq {{i[0-9]+}} [[NCMP]], 0
58 ; CHECK: ret i1
59 }