llvm.org GIT mirror llvm / ceb375e
fix 3 miscompilations and several compielr crashes in strcmp optimizer. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@35707 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 12 years ago
1 changed file(s) with 42 addition(s) and 51 deletion(s). Raw diff Collapse all Expand all
620620
621621 /// @brief Make sure that the "strcmp" function has the right prototype
622622 virtual bool ValidateCalledFunction(const Function *F, SimplifyLibCalls &SLC){
623 return F->getReturnType() == Type::Int32Ty && F->arg_size() == 2;
623 const FunctionType *FT = F->getFunctionType();
624 return FT->getReturnType() == Type::Int32Ty && FT->getNumParams() == 2 &&
625 FT->getParamType(0) == FT->getParamType(1) &&
626 FT->getParamType(0) == PointerType::get(Type::Int8Ty);
624627 }
625628
626629 /// @brief Perform the strcmp optimization
627 virtual bool OptimizeCall(CallInst* ci, SimplifyLibCalls& SLC) {
630 virtual bool OptimizeCall(CallInst *CI, SimplifyLibCalls &SLC) {
628631 // First, check to see if src and destination are the same. If they are,
629632 // then the optimization is to replace the CallInst with a constant 0
630633 // because the call is a no-op.
631 Value* s1 = ci->getOperand(1);
632 Value* s2 = ci->getOperand(2);
633 if (s1 == s2) {
634 Value *Str1P = CI->getOperand(1);
635 Value *Str2P = CI->getOperand(2);
636 if (Str1P == Str2P) {
634637 // strcmp(x,x) -> 0
635 ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty,0));
636 ci->eraseFromParent();
637 return true;
638 }
639
640 bool isstr_1 = false;
641 uint64_t len_1 = 0, StartIdx;
638 CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 0));
639 CI->eraseFromParent();
640 return true;
641 }
642
643 uint64_t Str1Len, Str1StartIdx;
642644 ConstantArray *A1;
643 if (GetConstantStringInfo(s1, A1, len_1, StartIdx)) {
644 isstr_1 = true;
645 if (len_1 == 0) {
646 // strcmp("",x) -> *x
647 LoadInst* load =
648 new LoadInst(CastToCStr(s2,*ci), ci->getName()+".load",ci);
649 CastInst* cast =
650 CastInst::create(Instruction::SExt, load, Type::Int32Ty,
651 ci->getName()+".int", ci);
652 ci->replaceAllUsesWith(cast);
653 ci->eraseFromParent();
654 return true;
655 }
656 }
657
658 bool isstr_2 = false;
659 uint64_t len_2;
645 bool Str1IsCst = GetConstantStringInfo(Str1P, A1, Str1Len, Str1StartIdx);
646 if (Str1IsCst && Str1Len == 0) {
647 // strcmp("", x) -> *x
648 Value *V = new LoadInst(Str2P, CI->getName()+".load", CI);
649 V = new ZExtInst(V, CI->getType(), CI->getName()+".int", CI);
650 CI->replaceAllUsesWith(V);
651 CI->eraseFromParent();
652 return true;
653 }
654
655 uint64_t Str2Len, Str2StartIdx;
660656 ConstantArray* A2;
661 if (GetConstantStringInfo(s2, A2, len_2, StartIdx)) {
662 isstr_2 = true;
663 if (len_2 == 0) {
664 // strcmp(x,"") -> *x
665 LoadInst* load =
666 new LoadInst(CastToCStr(s1,*ci),ci->getName()+".val",ci);
667 CastInst* cast =
668 CastInst::create(Instruction::SExt, load, Type::Int32Ty,
669 ci->getName()+".int", ci);
670 ci->replaceAllUsesWith(cast);
671 ci->eraseFromParent();
672 return true;
673 }
674 }
675
676 if (isstr_1 && isstr_2) {
677 // strcmp(x,y) -> cnst (if both x and y are constant strings)
678 std::string str1 = A1->getAsString();
679 std::string str2 = A2->getAsString();
680 int result = strcmp(str1.c_str(), str2.c_str());
681 ci->replaceAllUsesWith(ConstantInt::get(Type::Int32Ty,result));
682 ci->eraseFromParent();
657 bool Str2IsCst = GetConstantStringInfo(Str2P, A2, Str2Len, Str2StartIdx);
658 if (Str2IsCst && Str2Len == 0) {
659 // strcmp(x,"") -> *x
660 Value *V = new LoadInst(Str1P, CI->getName()+".load", CI);
661 V = new ZExtInst(V, CI->getType(), CI->getName()+".int", CI);
662 CI->replaceAllUsesWith(V);
663 CI->eraseFromParent();
664 return true;
665 }
666
667 if (Str1IsCst && Str2IsCst && A1->isCString() && A2->isCString()) {
668 // strcmp(x, y) -> cnst (if both x and y are constant strings)
669 std::string S1 = A1->getAsString();
670 std::string S2 = A2->getAsString();
671 int R = strcmp(S1.c_str()+Str1StartIdx, S2.c_str()+Str2StartIdx);
672 CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), R));
673 CI->eraseFromParent();
683674 return true;
684675 }
685676 return false;