diff --git a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp --- a/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp +++ b/llvm/lib/Transforms/AggressiveInstCombine/AggressiveInstCombine.cpp @@ -934,17 +934,24 @@ size_t ConstantStrSize = ConstantStr.size(); // Trivial cases are optimized during inst combine - if (ConstantStrSize == 0) { + if (ConstantStrSize == 0 || ConstantStrSize > 2) return false; - } - if (ConstantStrSize > 2) { - return false; + // Check if strcmp result is only used in a comparison with zero + + ICmpInst::Predicate Pred; + bool AllCmpPredicateEq = true; + bool AllCmpPredicateNotEq = true; + + for (User *U : CI->users()) { + if (!match(U, m_ICmp(Pred, m_Value(), m_Zero()))) + return false; + + AllCmpPredicateEq &= (Pred == ICmpInst::ICMP_EQ); + AllCmpPredicateNotEq &= (Pred == ICmpInst::ICMP_NE); } - // Check if strcmp result is only used in a comparison with zero - if (!isOnlyUsedInZeroComparison(CI)) - return false; + bool AllCmpPredicateEqOrNotEq = AllCmpPredicateEq || AllCmpPredicateNotEq; // For strcmp(P, "x") do the following transformation: // @@ -960,7 +967,7 @@ // For strcmp(P, "xy") do the following transformation: // // (before) - // dst = strcmp(P, "x") + // dst = strcmp(P, "xy") // // (after) // v0 = P[0] - 'x' @@ -970,6 +977,31 @@ // v2 = P[2] // dst = phi(v0, v1, v2) // + // There are special cases if all uses of strcmp are equal or not equal + // operators. + // + // (before) + // dst = strcmp(P, "x") == / != 0 + // + // (after) + // v0 = P[0] == 'x' + // [if v0] + // v1 = P[1] == '\0' + // + // dst = phi(v0, v1) / phi(not(v0), not(v1)) + // + // (before) + // dst = strcmp(P, "xy") == / != 0 + // + // (after) + // v0 = P[0] == 'x' + // [if v0] + // v1 = P[1] == 'y' + // [if v1] + // v2 = P[2] == '\0' + // + // dst = phi(v0, v1, v2) / phi(not(v0), not(v1), not(v2)) + // IRBuilder<> B(CI->getParent()); DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy); @@ -978,10 +1010,11 @@ BasicBlock *InitialBB = CI->getParent(); BasicBlock *JoinBlock = SplitBlock(InitialBB, CI, &DTU); - JoinBlock->setName("strcmp_expand_sub_join"); + JoinBlock->setName("strcmp_expand_join"); B.SetInsertPoint(CI); - PHINode *ResultPHI = B.CreatePHI(RetType, ConstantStrSize + 1); + PHINode *JoinPHI = B.CreatePHI( + AllCmpPredicateEqOrNotEq ? B.getInt1Ty() : RetType, ConstantStrSize + 1); B.SetInsertPoint(InitialBB); InitialBB->getTerminator()->eraseFromParent(); @@ -990,43 +1023,78 @@ size_t CharacterIndexToCheck = 0; for (; CharacterIndexToCheck < ConstantStrSize; ++CharacterIndexToCheck) { - Value *StrCharacterValue = B.CreateZExt( - B.CreateLoad(B.getInt8Ty(), - B.CreateConstInBoundsGEP1_64(B.getInt8Ty(), NonConstantP, - CharacterIndexToCheck)), - RetType); + Value *JoinPHIValue = nullptr; + BasicBlock *NextBB = nullptr; + + Value *StrCharacterValue = B.CreateLoad( + B.getInt8Ty(), B.CreateConstInBoundsGEP1_64(B.getInt8Ty(), NonConstantP, + CharacterIndexToCheck)); Value *ConstantStrCharacterValue = ConstantInt::get( - RetType, + B.getInt8Ty(), static_cast(ConstantStr[CharacterIndexToCheck])); - Value *CharacterSub = - B.CreateNSWSub(StrCharacterValue, ConstantStrCharacterValue); - Value *IsCharacterSubZero = - B.CreateICmpEQ(CharacterSub, ConstantInt::get(RetType, 0)); - BasicBlock *IsCharacterSubZeroBB = - BasicBlock::Create(B.getContext(), "strcmp_expand_sub_is_zero", - InitialBB->getParent(), JoinBlock); - B.CreateCondBr(IsCharacterSubZero, IsCharacterSubZeroBB, JoinBlock); - - ResultPHI->addIncoming(CharacterSub, B.GetInsertBlock()); - DTUpdates.emplace_back(DominatorTree::Insert, B.GetInsertBlock(), - IsCharacterSubZeroBB); - - B.SetInsertPoint(IsCharacterSubZeroBB); - DTUpdates.emplace_back(DominatorTree::Insert, IsCharacterSubZeroBB, - JoinBlock); + + if (AllCmpPredicateEqOrNotEq) { + Value *CharacterIsEq = + B.CreateICmpEQ(StrCharacterValue, ConstantStrCharacterValue); + BasicBlock *CharacterIsEqBB = + BasicBlock::Create(B.getContext(), "strcmp_expand_character_is_eq", + InitialBB->getParent(), JoinBlock); + B.CreateCondBr(CharacterIsEq, CharacterIsEqBB, JoinBlock); + + NextBB = CharacterIsEqBB; + JoinPHIValue = AllCmpPredicateEq ? B.getFalse() : B.getTrue(); + } else { + Value *ZextStrCharacterValue = B.CreateZExt(StrCharacterValue, RetType); + Value *ZextConstantStrCharacterValue = + B.CreateZExt(ConstantStrCharacterValue, RetType); + Value *CharacterSub = + B.CreateNSWSub(ZextStrCharacterValue, ZextConstantStrCharacterValue); + Value *CharacterSubIsZero = + B.CreateICmpEQ(CharacterSub, ConstantInt::get(RetType, 0)); + BasicBlock *CharacterSubIsZeroBB = + BasicBlock::Create(B.getContext(), "strcmp_expand_sub_is_zero", + InitialBB->getParent(), JoinBlock); + B.CreateCondBr(CharacterSubIsZero, CharacterSubIsZeroBB, JoinBlock); + + NextBB = CharacterSubIsZeroBB; + JoinPHIValue = CharacterSub; + } + + JoinPHI->addIncoming(JoinPHIValue, B.GetInsertBlock()); + DTUpdates.emplace_back(DominatorTree::Insert, B.GetInsertBlock(), NextBB); + + B.SetInsertPoint(NextBB); + DTUpdates.emplace_back(DominatorTree::Insert, NextBB, JoinBlock); } - Value *StrLastCharacterValue = B.CreateZExt( - B.CreateLoad(B.getInt8Ty(), - B.CreateConstInBoundsGEP1_64(B.getInt8Ty(), NonConstantP, - CharacterIndexToCheck)), - RetType); - ResultPHI->addIncoming(StrLastCharacterValue, B.GetInsertBlock()); + Value *StrLastCharacterValue = B.CreateLoad( + B.getInt8Ty(), B.CreateConstInBoundsGEP1_64(B.getInt8Ty(), NonConstantP, + CharacterIndexToCheck)); + Value *JoinPHILastValue = nullptr; + if (AllCmpPredicateEq) + JoinPHILastValue = B.CreateICmpEQ(StrLastCharacterValue, + ConstantInt::get(B.getInt8Ty(), 0)); + else if (AllCmpPredicateNotEq) + JoinPHILastValue = B.CreateICmpNE(StrLastCharacterValue, + ConstantInt::get(B.getInt8Ty(), 0)); + else + JoinPHILastValue = B.CreateZExt(StrLastCharacterValue, RetType); + + JoinPHI->addIncoming(JoinPHILastValue, B.GetInsertBlock()); B.CreateBr(JoinBlock); DTU.applyUpdates(DTUpdates); - CI->replaceAllUsesWith(ResultPHI); + if (AllCmpPredicateEqOrNotEq) { + for (User *U : CI->users()) { + U->replaceAllUsesWith(JoinPHI); + } + + CI->replaceAllUsesWith(ConstantInt::get(CI->getType(), 0)); + } else { + CI->replaceAllUsesWith(JoinPHI); + } + CI->eraseFromParent(); MadeCFGChange = true; diff --git a/llvm/test/Transforms/AggressiveInstCombine/strcmp.ll b/llvm/test/Transforms/AggressiveInstCombine/strcmp.ll --- a/llvm/test/Transforms/AggressiveInstCombine/strcmp.ll +++ b/llvm/test/Transforms/AggressiveInstCombine/strcmp.ll @@ -25,19 +25,16 @@ define i1 @expand_strcmp_eq_s1(ptr %C) { ; CHECK-LABEL: @expand_strcmp_eq_s1( ; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[C:%.*]], align 1 -; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i32 -; CHECK-NEXT: [[TMP3:%.*]] = sub nsw i32 [[TMP2]], 48 -; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 -; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_SUB_JOIN:%.*]] -; CHECK: strcmp_expand_sub_is_zero: -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 1 -; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP5]], align 1 -; CHECK-NEXT: [[TMP7:%.*]] = zext i8 [[TMP6]] to i32 -; CHECK-NEXT: br label [[STRCMP_EXPAND_SUB_JOIN]] -; CHECK: strcmp_expand_sub_join: -; CHECK-NEXT: [[TMP8:%.*]] = phi i32 [ [[TMP3]], [[TMP0:%.*]] ], [ [[TMP7]], [[STRCMP_EXPAND_SUB_IS_ZERO]] ] -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP8]], 0 -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 48 +; CHECK-NEXT: br i1 [[TMP2]], label [[STRCMP_EXPAND_CHARACTER_IS_EQ:%.*]], label [[STRCMP_EXPAND_JOIN:%.*]] +; CHECK: strcmp_expand_character_is_eq: +; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 1 +; CHECK-NEXT: [[TMP4:%.*]] = load i8, ptr [[TMP3]], align 1 +; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i8 [[TMP4]], 0 +; CHECK-NEXT: br label [[STRCMP_EXPAND_JOIN]] +; CHECK: strcmp_expand_join: +; CHECK-NEXT: [[TMP6:%.*]] = phi i1 [ false, [[TMP0:%.*]] ], [ [[TMP5]], [[STRCMP_EXPAND_CHARACTER_IS_EQ]] ] +; CHECK-NEXT: ret i1 [[TMP6]] ; %call = call i32 @strcmp(ptr %C, ptr @s1) %cmp = icmp eq i32 %call, 0 @@ -47,19 +44,16 @@ define i1 @expand_strcmp_eq_s1_commuted(ptr %C) { ; CHECK-LABEL: @expand_strcmp_eq_s1_commuted( ; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[C:%.*]], align 1 -; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i32 -; CHECK-NEXT: [[TMP3:%.*]] = sub nsw i32 [[TMP2]], 48 -; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 -; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_SUB_JOIN:%.*]] -; CHECK: strcmp_expand_sub_is_zero: -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 1 -; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP5]], align 1 -; CHECK-NEXT: [[TMP7:%.*]] = zext i8 [[TMP6]] to i32 -; CHECK-NEXT: br label [[STRCMP_EXPAND_SUB_JOIN]] -; CHECK: strcmp_expand_sub_join: -; CHECK-NEXT: [[TMP8:%.*]] = phi i32 [ [[TMP3]], [[TMP0:%.*]] ], [ [[TMP7]], [[STRCMP_EXPAND_SUB_IS_ZERO]] ] -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP8]], 0 -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 48 +; CHECK-NEXT: br i1 [[TMP2]], label [[STRCMP_EXPAND_CHARACTER_IS_EQ:%.*]], label [[STRCMP_EXPAND_JOIN:%.*]] +; CHECK: strcmp_expand_character_is_eq: +; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 1 +; CHECK-NEXT: [[TMP4:%.*]] = load i8, ptr [[TMP3]], align 1 +; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i8 [[TMP4]], 0 +; CHECK-NEXT: br label [[STRCMP_EXPAND_JOIN]] +; CHECK: strcmp_expand_join: +; CHECK-NEXT: [[TMP6:%.*]] = phi i1 [ false, [[TMP0:%.*]] ], [ [[TMP5]], [[STRCMP_EXPAND_CHARACTER_IS_EQ]] ] +; CHECK-NEXT: ret i1 [[TMP6]] ; %call = call i32 @strcmp(ptr @s1, ptr %C) %cmp = icmp eq i32 %call, 0 @@ -69,19 +63,16 @@ define i1 @expand_strcmp_ne_s1(ptr %C) { ; CHECK-LABEL: @expand_strcmp_ne_s1( ; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[C:%.*]], align 1 -; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i32 -; CHECK-NEXT: [[TMP3:%.*]] = sub nsw i32 [[TMP2]], 48 -; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 -; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_SUB_JOIN:%.*]] -; CHECK: strcmp_expand_sub_is_zero: -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 1 -; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP5]], align 1 -; CHECK-NEXT: [[TMP7:%.*]] = zext i8 [[TMP6]] to i32 -; CHECK-NEXT: br label [[STRCMP_EXPAND_SUB_JOIN]] -; CHECK: strcmp_expand_sub_join: -; CHECK-NEXT: [[TMP8:%.*]] = phi i32 [ [[TMP3]], [[TMP0:%.*]] ], [ [[TMP7]], [[STRCMP_EXPAND_SUB_IS_ZERO]] ] -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP8]], 0 -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 48 +; CHECK-NEXT: br i1 [[TMP2]], label [[STRCMP_EXPAND_CHARACTER_IS_EQ:%.*]], label [[STRCMP_EXPAND_JOIN:%.*]] +; CHECK: strcmp_expand_character_is_eq: +; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 1 +; CHECK-NEXT: [[TMP4:%.*]] = load i8, ptr [[TMP3]], align 1 +; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i8 [[TMP4]], 0 +; CHECK-NEXT: br label [[STRCMP_EXPAND_JOIN]] +; CHECK: strcmp_expand_join: +; CHECK-NEXT: [[TMP6:%.*]] = phi i1 [ true, [[TMP0:%.*]] ], [ [[TMP5]], [[STRCMP_EXPAND_CHARACTER_IS_EQ]] ] +; CHECK-NEXT: ret i1 [[TMP6]] ; %call = call i32 @strcmp(ptr %C, ptr @s1) %cmp = icmp ne i32 %call, 0 @@ -94,13 +85,13 @@ ; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i32 ; CHECK-NEXT: [[TMP3:%.*]] = sub nsw i32 [[TMP2]], 48 ; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 -; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_SUB_JOIN:%.*]] +; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_JOIN:%.*]] ; CHECK: strcmp_expand_sub_is_zero: ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 1 ; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP5]], align 1 ; CHECK-NEXT: [[TMP7:%.*]] = zext i8 [[TMP6]] to i32 -; CHECK-NEXT: br label [[STRCMP_EXPAND_SUB_JOIN]] -; CHECK: strcmp_expand_sub_join: +; CHECK-NEXT: br label [[STRCMP_EXPAND_JOIN]] +; CHECK: strcmp_expand_join: ; CHECK-NEXT: [[TMP8:%.*]] = phi i32 [ [[TMP3]], [[TMP0:%.*]] ], [ [[TMP7]], [[STRCMP_EXPAND_SUB_IS_ZERO]] ] ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP8]], 0 ; CHECK-NEXT: ret i1 [[CMP]] @@ -116,13 +107,13 @@ ; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i32 ; CHECK-NEXT: [[TMP3:%.*]] = sub nsw i32 [[TMP2]], 48 ; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 -; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_SUB_JOIN:%.*]] +; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_JOIN:%.*]] ; CHECK: strcmp_expand_sub_is_zero: ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 1 ; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP5]], align 1 ; CHECK-NEXT: [[TMP7:%.*]] = zext i8 [[TMP6]] to i32 -; CHECK-NEXT: br label [[STRCMP_EXPAND_SUB_JOIN]] -; CHECK: strcmp_expand_sub_join: +; CHECK-NEXT: br label [[STRCMP_EXPAND_JOIN]] +; CHECK: strcmp_expand_join: ; CHECK-NEXT: [[TMP8:%.*]] = phi i32 [ [[TMP3]], [[TMP0:%.*]] ], [ [[TMP7]], [[STRCMP_EXPAND_SUB_IS_ZERO]] ] ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[TMP8]], 0 ; CHECK-NEXT: ret i1 [[CMP]] @@ -138,13 +129,13 @@ ; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i32 ; CHECK-NEXT: [[TMP3:%.*]] = sub nsw i32 [[TMP2]], 48 ; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 -; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_SUB_JOIN:%.*]] +; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_JOIN:%.*]] ; CHECK: strcmp_expand_sub_is_zero: ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 1 ; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP5]], align 1 ; CHECK-NEXT: [[TMP7:%.*]] = zext i8 [[TMP6]] to i32 -; CHECK-NEXT: br label [[STRCMP_EXPAND_SUB_JOIN]] -; CHECK: strcmp_expand_sub_join: +; CHECK-NEXT: br label [[STRCMP_EXPAND_JOIN]] +; CHECK: strcmp_expand_join: ; CHECK-NEXT: [[TMP8:%.*]] = phi i32 [ [[TMP3]], [[TMP0:%.*]] ], [ [[TMP7]], [[STRCMP_EXPAND_SUB_IS_ZERO]] ] ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP8]], 0 ; CHECK-NEXT: ret i1 [[CMP]] @@ -160,13 +151,13 @@ ; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i32 ; CHECK-NEXT: [[TMP3:%.*]] = sub nsw i32 [[TMP2]], 48 ; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 -; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_SUB_JOIN:%.*]] +; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_JOIN:%.*]] ; CHECK: strcmp_expand_sub_is_zero: ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 1 ; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP5]], align 1 ; CHECK-NEXT: [[TMP7:%.*]] = zext i8 [[TMP6]] to i32 -; CHECK-NEXT: br label [[STRCMP_EXPAND_SUB_JOIN]] -; CHECK: strcmp_expand_sub_join: +; CHECK-NEXT: br label [[STRCMP_EXPAND_JOIN]] +; CHECK: strcmp_expand_join: ; CHECK-NEXT: [[TMP8:%.*]] = phi i32 [ [[TMP3]], [[TMP0:%.*]] ], [ [[TMP7]], [[STRCMP_EXPAND_SUB_IS_ZERO]] ] ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[TMP8]], 0 ; CHECK-NEXT: ret i1 [[CMP]] @@ -210,26 +201,21 @@ define i1 @expand_strcmp_eq_s2(ptr %C) { ; CHECK-LABEL: @expand_strcmp_eq_s2( ; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[C:%.*]], align 1 -; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i32 -; CHECK-NEXT: [[TMP3:%.*]] = sub nsw i32 [[TMP2]], 48 -; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 -; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_SUB_JOIN:%.*]] -; CHECK: strcmp_expand_sub_is_zero: -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 1 -; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP5]], align 1 -; CHECK-NEXT: [[TMP7:%.*]] = zext i8 [[TMP6]] to i32 -; CHECK-NEXT: [[TMP8:%.*]] = sub nsw i32 [[TMP7]], 49 -; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 0 -; CHECK-NEXT: br i1 [[TMP9]], label [[STRCMP_EXPAND_SUB_IS_ZERO1:%.*]], label [[STRCMP_EXPAND_SUB_JOIN]] -; CHECK: strcmp_expand_sub_is_zero1: -; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 2 -; CHECK-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP10]], align 1 -; CHECK-NEXT: [[TMP12:%.*]] = zext i8 [[TMP11]] to i32 -; CHECK-NEXT: br label [[STRCMP_EXPAND_SUB_JOIN]] -; CHECK: strcmp_expand_sub_join: -; CHECK-NEXT: [[TMP13:%.*]] = phi i32 [ [[TMP3]], [[TMP0:%.*]] ], [ [[TMP8]], [[STRCMP_EXPAND_SUB_IS_ZERO]] ], [ [[TMP12]], [[STRCMP_EXPAND_SUB_IS_ZERO1]] ] -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP13]], 0 -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 48 +; CHECK-NEXT: br i1 [[TMP2]], label [[STRCMP_EXPAND_CHARACTER_IS_EQ:%.*]], label [[STRCMP_EXPAND_JOIN:%.*]] +; CHECK: strcmp_expand_character_is_eq: +; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 1 +; CHECK-NEXT: [[TMP4:%.*]] = load i8, ptr [[TMP3]], align 1 +; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i8 [[TMP4]], 49 +; CHECK-NEXT: br i1 [[TMP5]], label [[STRCMP_EXPAND_CHARACTER_IS_EQ1:%.*]], label [[STRCMP_EXPAND_JOIN]] +; CHECK: strcmp_expand_character_is_eq1: +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 2 +; CHECK-NEXT: [[TMP7:%.*]] = load i8, ptr [[TMP6]], align 1 +; CHECK-NEXT: [[TMP8:%.*]] = icmp eq i8 [[TMP7]], 0 +; CHECK-NEXT: br label [[STRCMP_EXPAND_JOIN]] +; CHECK: strcmp_expand_join: +; CHECK-NEXT: [[TMP9:%.*]] = phi i1 [ false, [[TMP0:%.*]] ], [ false, [[STRCMP_EXPAND_CHARACTER_IS_EQ]] ], [ [[TMP8]], [[STRCMP_EXPAND_CHARACTER_IS_EQ1]] ] +; CHECK-NEXT: ret i1 [[TMP9]] ; %call = call i32 @strcmp(ptr %C, ptr @s2) %cmp = icmp eq i32 %call, 0 @@ -239,26 +225,21 @@ define i1 @expand_strcmp_ne_s2(ptr %C) { ; CHECK-LABEL: @expand_strcmp_ne_s2( ; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr [[C:%.*]], align 1 -; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i32 -; CHECK-NEXT: [[TMP3:%.*]] = sub nsw i32 [[TMP2]], 48 -; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 -; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_SUB_JOIN:%.*]] -; CHECK: strcmp_expand_sub_is_zero: -; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 1 -; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP5]], align 1 -; CHECK-NEXT: [[TMP7:%.*]] = zext i8 [[TMP6]] to i32 -; CHECK-NEXT: [[TMP8:%.*]] = sub nsw i32 [[TMP7]], 49 -; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 0 -; CHECK-NEXT: br i1 [[TMP9]], label [[STRCMP_EXPAND_SUB_IS_ZERO1:%.*]], label [[STRCMP_EXPAND_SUB_JOIN]] -; CHECK: strcmp_expand_sub_is_zero1: -; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 2 -; CHECK-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP10]], align 1 -; CHECK-NEXT: [[TMP12:%.*]] = zext i8 [[TMP11]] to i32 -; CHECK-NEXT: br label [[STRCMP_EXPAND_SUB_JOIN]] -; CHECK: strcmp_expand_sub_join: -; CHECK-NEXT: [[TMP13:%.*]] = phi i32 [ [[TMP3]], [[TMP0:%.*]] ], [ [[TMP8]], [[STRCMP_EXPAND_SUB_IS_ZERO]] ], [ [[TMP12]], [[STRCMP_EXPAND_SUB_IS_ZERO1]] ] -; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP13]], 0 -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 48 +; CHECK-NEXT: br i1 [[TMP2]], label [[STRCMP_EXPAND_CHARACTER_IS_EQ:%.*]], label [[STRCMP_EXPAND_JOIN:%.*]] +; CHECK: strcmp_expand_character_is_eq: +; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 1 +; CHECK-NEXT: [[TMP4:%.*]] = load i8, ptr [[TMP3]], align 1 +; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i8 [[TMP4]], 49 +; CHECK-NEXT: br i1 [[TMP5]], label [[STRCMP_EXPAND_CHARACTER_IS_EQ1:%.*]], label [[STRCMP_EXPAND_JOIN]] +; CHECK: strcmp_expand_character_is_eq1: +; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 2 +; CHECK-NEXT: [[TMP7:%.*]] = load i8, ptr [[TMP6]], align 1 +; CHECK-NEXT: [[TMP8:%.*]] = icmp ne i8 [[TMP7]], 0 +; CHECK-NEXT: br label [[STRCMP_EXPAND_JOIN]] +; CHECK: strcmp_expand_join: +; CHECK-NEXT: [[TMP9:%.*]] = phi i1 [ true, [[TMP0:%.*]] ], [ true, [[STRCMP_EXPAND_CHARACTER_IS_EQ]] ], [ [[TMP8]], [[STRCMP_EXPAND_CHARACTER_IS_EQ1]] ] +; CHECK-NEXT: ret i1 [[TMP9]] ; %call = call i32 @strcmp(ptr %C, ptr @s2) %cmp = icmp ne i32 %call, 0 @@ -271,20 +252,20 @@ ; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i32 ; CHECK-NEXT: [[TMP3:%.*]] = sub nsw i32 [[TMP2]], 48 ; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 -; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_SUB_JOIN:%.*]] +; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_JOIN:%.*]] ; CHECK: strcmp_expand_sub_is_zero: ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 1 ; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP5]], align 1 ; CHECK-NEXT: [[TMP7:%.*]] = zext i8 [[TMP6]] to i32 ; CHECK-NEXT: [[TMP8:%.*]] = sub nsw i32 [[TMP7]], 49 ; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 0 -; CHECK-NEXT: br i1 [[TMP9]], label [[STRCMP_EXPAND_SUB_IS_ZERO1:%.*]], label [[STRCMP_EXPAND_SUB_JOIN]] +; CHECK-NEXT: br i1 [[TMP9]], label [[STRCMP_EXPAND_SUB_IS_ZERO1:%.*]], label [[STRCMP_EXPAND_JOIN]] ; CHECK: strcmp_expand_sub_is_zero1: ; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 2 ; CHECK-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP10]], align 1 ; CHECK-NEXT: [[TMP12:%.*]] = zext i8 [[TMP11]] to i32 -; CHECK-NEXT: br label [[STRCMP_EXPAND_SUB_JOIN]] -; CHECK: strcmp_expand_sub_join: +; CHECK-NEXT: br label [[STRCMP_EXPAND_JOIN]] +; CHECK: strcmp_expand_join: ; CHECK-NEXT: [[TMP13:%.*]] = phi i32 [ [[TMP3]], [[TMP0:%.*]] ], [ [[TMP8]], [[STRCMP_EXPAND_SUB_IS_ZERO]] ], [ [[TMP12]], [[STRCMP_EXPAND_SUB_IS_ZERO1]] ] ; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP13]], 0 ; CHECK-NEXT: ret i1 [[CMP]] @@ -300,20 +281,20 @@ ; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i32 ; CHECK-NEXT: [[TMP3:%.*]] = sub nsw i32 [[TMP2]], 48 ; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 -; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_SUB_JOIN:%.*]] +; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_JOIN:%.*]] ; CHECK: strcmp_expand_sub_is_zero: ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 1 ; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP5]], align 1 ; CHECK-NEXT: [[TMP7:%.*]] = zext i8 [[TMP6]] to i32 ; CHECK-NEXT: [[TMP8:%.*]] = sub nsw i32 [[TMP7]], 49 ; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 0 -; CHECK-NEXT: br i1 [[TMP9]], label [[STRCMP_EXPAND_SUB_IS_ZERO1:%.*]], label [[STRCMP_EXPAND_SUB_JOIN]] +; CHECK-NEXT: br i1 [[TMP9]], label [[STRCMP_EXPAND_SUB_IS_ZERO1:%.*]], label [[STRCMP_EXPAND_JOIN]] ; CHECK: strcmp_expand_sub_is_zero1: ; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 2 ; CHECK-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP10]], align 1 ; CHECK-NEXT: [[TMP12:%.*]] = zext i8 [[TMP11]] to i32 -; CHECK-NEXT: br label [[STRCMP_EXPAND_SUB_JOIN]] -; CHECK: strcmp_expand_sub_join: +; CHECK-NEXT: br label [[STRCMP_EXPAND_JOIN]] +; CHECK: strcmp_expand_join: ; CHECK-NEXT: [[TMP13:%.*]] = phi i32 [ [[TMP3]], [[TMP0:%.*]] ], [ [[TMP8]], [[STRCMP_EXPAND_SUB_IS_ZERO]] ], [ [[TMP12]], [[STRCMP_EXPAND_SUB_IS_ZERO1]] ] ; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[TMP13]], 0 ; CHECK-NEXT: ret i1 [[CMP]] @@ -329,20 +310,20 @@ ; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i32 ; CHECK-NEXT: [[TMP3:%.*]] = sub nsw i32 [[TMP2]], 48 ; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 -; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_SUB_JOIN:%.*]] +; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_JOIN:%.*]] ; CHECK: strcmp_expand_sub_is_zero: ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 1 ; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP5]], align 1 ; CHECK-NEXT: [[TMP7:%.*]] = zext i8 [[TMP6]] to i32 ; CHECK-NEXT: [[TMP8:%.*]] = sub nsw i32 [[TMP7]], 49 ; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 0 -; CHECK-NEXT: br i1 [[TMP9]], label [[STRCMP_EXPAND_SUB_IS_ZERO1:%.*]], label [[STRCMP_EXPAND_SUB_JOIN]] +; CHECK-NEXT: br i1 [[TMP9]], label [[STRCMP_EXPAND_SUB_IS_ZERO1:%.*]], label [[STRCMP_EXPAND_JOIN]] ; CHECK: strcmp_expand_sub_is_zero1: ; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 2 ; CHECK-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP10]], align 1 ; CHECK-NEXT: [[TMP12:%.*]] = zext i8 [[TMP11]] to i32 -; CHECK-NEXT: br label [[STRCMP_EXPAND_SUB_JOIN]] -; CHECK: strcmp_expand_sub_join: +; CHECK-NEXT: br label [[STRCMP_EXPAND_JOIN]] +; CHECK: strcmp_expand_join: ; CHECK-NEXT: [[TMP13:%.*]] = phi i32 [ [[TMP3]], [[TMP0:%.*]] ], [ [[TMP8]], [[STRCMP_EXPAND_SUB_IS_ZERO]] ], [ [[TMP12]], [[STRCMP_EXPAND_SUB_IS_ZERO1]] ] ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP13]], 0 ; CHECK-NEXT: ret i1 [[CMP]] @@ -358,20 +339,20 @@ ; CHECK-NEXT: [[TMP2:%.*]] = zext i8 [[TMP1]] to i32 ; CHECK-NEXT: [[TMP3:%.*]] = sub nsw i32 [[TMP2]], 48 ; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[TMP3]], 0 -; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_SUB_JOIN:%.*]] +; CHECK-NEXT: br i1 [[TMP4]], label [[STRCMP_EXPAND_SUB_IS_ZERO:%.*]], label [[STRCMP_EXPAND_JOIN:%.*]] ; CHECK: strcmp_expand_sub_is_zero: ; CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 1 ; CHECK-NEXT: [[TMP6:%.*]] = load i8, ptr [[TMP5]], align 1 ; CHECK-NEXT: [[TMP7:%.*]] = zext i8 [[TMP6]] to i32 ; CHECK-NEXT: [[TMP8:%.*]] = sub nsw i32 [[TMP7]], 49 ; CHECK-NEXT: [[TMP9:%.*]] = icmp eq i32 [[TMP8]], 0 -; CHECK-NEXT: br i1 [[TMP9]], label [[STRCMP_EXPAND_SUB_IS_ZERO1:%.*]], label [[STRCMP_EXPAND_SUB_JOIN]] +; CHECK-NEXT: br i1 [[TMP9]], label [[STRCMP_EXPAND_SUB_IS_ZERO1:%.*]], label [[STRCMP_EXPAND_JOIN]] ; CHECK: strcmp_expand_sub_is_zero1: ; CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds i8, ptr [[C]], i64 2 ; CHECK-NEXT: [[TMP11:%.*]] = load i8, ptr [[TMP10]], align 1 ; CHECK-NEXT: [[TMP12:%.*]] = zext i8 [[TMP11]] to i32 -; CHECK-NEXT: br label [[STRCMP_EXPAND_SUB_JOIN]] -; CHECK: strcmp_expand_sub_join: +; CHECK-NEXT: br label [[STRCMP_EXPAND_JOIN]] +; CHECK: strcmp_expand_join: ; CHECK-NEXT: [[TMP13:%.*]] = phi i32 [ [[TMP3]], [[TMP0:%.*]] ], [ [[TMP8]], [[STRCMP_EXPAND_SUB_IS_ZERO]] ], [ [[TMP12]], [[STRCMP_EXPAND_SUB_IS_ZERO1]] ] ; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[TMP13]], 0 ; CHECK-NEXT: ret i1 [[CMP]]