llvm.org GIT mirror llvm / 7b50c8f
Fix bugs in strncmp. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@35708 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 12 years ago
1 changed file(s) with 57 addition(s) and 67 deletion(s). Raw diff Collapse all Expand all
687687 "Number of 'strncmp' calls simplified") {}
688688
689689 /// @brief Make sure that the "strncmp" function has the right prototype
690 virtual bool ValidateCalledFunction(const Function* f, SimplifyLibCalls& SLC){
691 if (f->getReturnType() == Type::Int32Ty && f->arg_size() == 3)
692 return true;
690 virtual bool ValidateCalledFunction(const Function *F, SimplifyLibCalls &SLC){
691 const FunctionType *FT = F->getFunctionType();
692 return FT->getReturnType() == Type::Int32Ty && FT->getNumParams() == 3 &&
693 FT->getParamType(0) == FT->getParamType(1) &&
694 FT->getParamType(0) == PointerType::get(Type::Int8Ty) &&
695 isa(FT->getParamType(2));
693696 return false;
694697 }
695698
696 /// @brief Perform the strncpy optimization
697 virtual bool OptimizeCall(CallInst *ci, SimplifyLibCalls &SLC) {
699 /// @brief Perform the strncmp optimization
700 virtual bool OptimizeCall(CallInst *CI, SimplifyLibCalls &SLC) {
698701 // First, check to see if src and destination are the same. If they are,
699702 // then the optimization is to replace the CallInst with a constant 0
700703 // because the call is a no-op.
701 Value* s1 = ci->getOperand(1);
702 Value* s2 = ci->getOperand(2);
703 if (s1 == s2) {
704 // strncmp(x,x,l) -> 0
705 ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty,0));
706 ci->eraseFromParent();
707 return true;
708 }
709
704 Value *Str1P = CI->getOperand(1);
705 Value *Str2P = CI->getOperand(2);
706 if (Str1P == Str2P) {
707 // strcmp(x,x) -> 0
708 CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 0));
709 CI->eraseFromParent();
710 return true;
711 }
712
710713 // Check the length argument, if it is Constant zero then the strings are
711714 // considered equal.
712 uint64_t len_arg = 0;
713 bool len_arg_is_const = false;
714 if (ConstantInt* len_CI = dyn_cast(ci->getOperand(3))) {
715 len_arg_is_const = true;
716 len_arg = len_CI->getZExtValue();
717 if (len_arg == 0) {
718 // strncmp(x,y,0) -> 0
719 ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty,0));
720 ci->eraseFromParent();
721 return true;
722 }
723 }
724
725 bool isstr_1 = false;
726 uint64_t len_1 = 0, StartIdx;
727 ConstantArray* A1;
728 if (GetConstantStringInfo(s1, A1, len_1, StartIdx)) {
729 isstr_1 = true;
730 if (len_1 == 0) {
731 // strncmp("",x) -> *x
732 LoadInst* load = new LoadInst(s1,ci->getName()+".load",ci);
733 CastInst* cast =
734 CastInst::create(Instruction::SExt, load, Type::Int32Ty,
735 ci->getName()+".int", ci);
736 ci->replaceAllUsesWith(cast);
737 ci->eraseFromParent();
738 return true;
739 }
740 }
741
742 bool isstr_2 = false;
743 uint64_t len_2 = 0;
715 ConstantInt *LengthArg = dyn_cast(CI->getOperand(3));
716 if (LengthArg && LengthArg->isZero()) {
717 // strncmp(x,y,0) -> 0
718 CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 0));
719 CI->eraseFromParent();
720 return true;
721 }
722
723 uint64_t Str1Len, Str1StartIdx;
724 ConstantArray *A1;
725 bool Str1IsCst = GetConstantStringInfo(Str1P, A1, Str1Len, Str1StartIdx);
726 if (Str1IsCst && Str1Len == 0) {
727 // strcmp("", x) -> *x
728 Value *V = new LoadInst(Str2P, CI->getName()+".load", CI);
729 V = new ZExtInst(V, CI->getType(), CI->getName()+".int", CI);
730 CI->replaceAllUsesWith(V);
731 CI->eraseFromParent();
732 return true;
733 }
734
735 uint64_t Str2Len, Str2StartIdx;
744736 ConstantArray* A2;
745 if (GetConstantStringInfo(s2, A2, len_2, StartIdx)) {
746 isstr_2 = true;
747 if (len_2 == 0) {
748 // strncmp(x,"") -> *x
749 LoadInst* load = new LoadInst(s2,ci->getName()+".val",ci);
750 CastInst* cast =
751 CastInst::create(Instruction::SExt, load, Type::Int32Ty,
752 ci->getName()+".int", ci);
753 ci->replaceAllUsesWith(cast);
754 ci->eraseFromParent();
755 return true;
756 }
757 }
758
759 if (isstr_1 && isstr_2 && len_arg_is_const) {
760 // strncmp(x,y,const) -> constant
761 std::string str1 = A1->getAsString();
762 std::string str2 = A2->getAsString();
763 int result = strncmp(str1.c_str(), str2.c_str(), len_arg);
764 ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty,result));
765 ci->eraseFromParent();
737 bool Str2IsCst = GetConstantStringInfo(Str2P, A2, Str2Len, Str2StartIdx);
738 if (Str2IsCst && Str2Len == 0) {
739 // strcmp(x,"") -> *x
740 Value *V = new LoadInst(Str1P, CI->getName()+".load", CI);
741 V = new ZExtInst(V, CI->getType(), CI->getName()+".int", CI);
742 CI->replaceAllUsesWith(V);
743 CI->eraseFromParent();
744 return true;
745 }
746
747 if (LengthArg && Str1IsCst && Str2IsCst && A1->isCString() &&
748 A2->isCString()) {
749 // strcmp(x, y) -> cnst (if both x and y are constant strings)
750 std::string S1 = A1->getAsString();
751 std::string S2 = A2->getAsString();
752 int R = strncmp(S1.c_str()+Str1StartIdx, S2.c_str()+Str2StartIdx,
753 LengthArg->getZExtValue());
754 CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), R));
755 CI->eraseFromParent();
766756 return true;
767757 }
768758 return false;