Index: llvm/include/llvm/Analysis/GuardUtils.h =================================================================== --- llvm/include/llvm/Analysis/GuardUtils.h +++ llvm/include/llvm/Analysis/GuardUtils.h @@ -28,8 +28,8 @@ /// call bool isWidenableCondition(const Value *V); -/// Returns true iff \p U is a widenable branch (that is, parseWidenableBranch -/// returns true). +/// Returns true iff \p U is a widenable branch (that is, +/// extractWidenableCondition returns widenable condition). bool isWidenableBranch(const User *U); /// Returns true iff \p U has semantics of a guard expressed in a form of a @@ -60,6 +60,10 @@ // cond1 && cond2 && cond3 && widenable_contidion ... // Method collects the list of checks, but skips widenable_condition. void parseWidenableGuard(const User *U, llvm::SmallVectorImpl &Checks); + +// Returns widenable_condition if it exists in the expression tree rooting from +// \p U and has only one use. +Value *extractWidenableCondition(const User *U); } // llvm #endif // LLVM_ANALYSIS_GUARDUTILS_H Index: llvm/lib/Analysis/GuardUtils.cpp =================================================================== --- llvm/lib/Analysis/GuardUtils.cpp +++ llvm/lib/Analysis/GuardUtils.cpp @@ -24,18 +24,13 @@ } bool llvm::isWidenableBranch(const User *U) { - Value *Condition, *WidenableCondition; - BasicBlock *GuardedBB, *DeoptBB; - return parseWidenableBranch(U, Condition, WidenableCondition, GuardedBB, - DeoptBB); + return extractWidenableCondition(U) != nullptr; } bool llvm::isGuardAsWidenableBranch(const User *U) { - Value *Condition, *WidenableCondition; - BasicBlock *GuardedBB, *DeoptBB; - if (!parseWidenableBranch(U, Condition, WidenableCondition, GuardedBB, - DeoptBB)) + if (!isWidenableBranch(U)) return false; + BasicBlock *DeoptBB = cast(U)->getSuccessor(1); SmallPtrSet Visited; Visited.insert(DeoptBB); do { @@ -117,7 +112,8 @@ } template -static void parseCondition(Value *Condition, CallbackType Callback) { +static void parseCondition(Value *Condition, + CallbackType RecordCheckOrWidenableCond) { SmallVector Worklist(1, Condition); SmallPtrSet Visited; Visited.insert(Condition); @@ -131,7 +127,8 @@ Worklist.push_back(RHS); continue; } - Callback(Check); + if (!RecordCheckOrWidenableCond(Check)) + break; } while (!Worklist.empty()); } @@ -144,5 +141,28 @@ parseCondition(Condition, [&](Value *Check) { if (!isWidenableCondition(Check)) Checks.push_back(Check); + return true; + }); +} + +Value *llvm::extractWidenableCondition(const User *U) { + auto *BI = dyn_cast(U); + if (!BI || !BI->isConditional()) + return nullptr; + + auto Condition = BI->getCondition(); + if (!Condition->hasOneUse()) + return nullptr; + + Value *WidenableCondition = nullptr; + parseCondition(Condition, [&](Value *Check) { + // We require widenable_condition has only one use, otherwise we don't + // consider appropriate branch as widenable. + if (isWidenableCondition(Check) && Check->hasOneUse()) { + WidenableCondition = Check; + return false; + } + return true; }); + return WidenableCondition; } Index: llvm/lib/Transforms/Scalar/GuardWidening.cpp =================================================================== --- llvm/lib/Transforms/Scalar/GuardWidening.cpp +++ llvm/lib/Transforms/Scalar/GuardWidening.cpp @@ -124,9 +124,7 @@ /// the one described at https://github.com/llvm/llvm-project/issues/60234. The /// safest way to do it is to expand the new condition at WC's block. static Instruction *findInsertionPointForWideCondition(Instruction *Guard) { - Value *Condition, *WC; - BasicBlock *IfTrue, *IfFalse; - if (parseWidenableBranch(Guard, Condition, WC, IfTrue, IfFalse)) + if (auto WC = extractWidenableCondition(Guard)) return cast(WC); return Guard; } Index: llvm/lib/Transforms/Scalar/LoopPredication.cpp =================================================================== --- llvm/lib/Transforms/Scalar/LoopPredication.cpp +++ llvm/lib/Transforms/Scalar/LoopPredication.cpp @@ -755,9 +755,9 @@ } } -void widenChecks(SmallVectorImpl &Checks, - SmallVectorImpl &WidenedChecks, - SCEVExpander &Expander, Instruction *Guard) { +void LoopPredication::widenChecks(SmallVectorImpl &Checks, + SmallVectorImpl &WidenedChecks, + SCEVExpander &Expander, Instruction *Guard) { for (auto &Check : Checks) if (ICmpInst *ICI = dyn_cast(Check)) if (auto NewRangeCheck = widenICmpRangeCheck(ICI, Expander, Guard)) { @@ -802,18 +802,13 @@ LLVM_DEBUG(dbgs() << "Processing guard:\n"); LLVM_DEBUG(BI->dump()); - Value *Cond, *WC; - BasicBlock *IfTrueBB, *IfFalseBB; - bool Parsed = parseWidenableBranch(BI, Cond, WC, IfTrueBB, IfFalseBB); - assert(Parsed && "Must be able to parse widenable branch"); - (void)Parsed; - TotalConsidered++; SmallVector Checks; SmallVector WidenedChecks; parseWidenableGuard(BI, Checks); // At the moment, our matching logic for wideable conditions implicitly // assumes we preserve the form: (br (and Cond, WC())). FIXME + auto WC = extractWidenableCondition(BI); Checks.push_back(WC); widenChecks(Checks, WidenedChecks, Expander, BI); if (WidenedChecks.empty()) @@ -827,6 +822,7 @@ auto *OldCond = BI->getCondition(); BI->setCondition(AllChecks); if (InsertAssumesOfPredicatedGuardsConditions) { + BasicBlock *IfTrueBB = BI->getSuccessor(0); Builder.SetInsertPoint(IfTrueBB, IfTrueBB->getFirstInsertionPt()); // If this block has other predecessors, we might not be able to use Cond. // In this case, create a Phi where every other input is `true` and input @@ -1033,13 +1029,9 @@ } while (true); if (BasicBlock *Pred = BB->getSinglePredecessor()) { - auto *Term = Pred->getTerminator(); - - Value *Cond, *WC; - BasicBlock *IfTrueBB, *IfFalseBB; - if (parseWidenableBranch(Term, Cond, WC, IfTrueBB, IfFalseBB) && - IfTrueBB == BB) - return cast(Term); + if (auto *BI = dyn_cast(Pred->getTerminator())) + if (BI->getSuccessor(0) == BB && isWidenableBranch(BI)) + return BI; } return nullptr; } @@ -1127,13 +1119,13 @@ if (!BI) continue; - Use *Cond, *WC; - BasicBlock *IfTrueBB, *IfFalseBB; - if (parseWidenableBranch(BI, Cond, WC, IfTrueBB, IfFalseBB) && - L->contains(IfTrueBB)) { - WC->set(ConstantInt::getTrue(IfTrueBB->getContext())); - ChangedLoop = true; - } + if (auto WC = extractWidenableCondition(BI)) + if (L->contains(BI->getSuccessor(0))) { + assert(WC->hasOneUse() && "Not appropriate widenable branch!"); + WC->user_back()->replaceUsesOfWith( + WC, ConstantInt::getTrue(BI->getContext())); + ChangedLoop = true; + } } if (ChangedLoop) SE->forgetLoop(L); Index: llvm/lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- llvm/lib/Transforms/Utils/SimplifyCFG.cpp +++ llvm/lib/Transforms/Utils/SimplifyCFG.cpp @@ -4140,10 +4140,10 @@ // 2) We can sink side effecting instructions into BI's fallthrough // successor provided they doesn't contribute to computation of // BI's condition. - Value *CondWB, *WC; - BasicBlock *IfTrueBB, *IfFalseBB; - if (!parseWidenableBranch(PBI, CondWB, WC, IfTrueBB, IfFalseBB) || - IfTrueBB != BI->getParent() || !BI->getParent()->getSinglePredecessor()) + BasicBlock *IfTrueBB = PBI->getSuccessor(0); + BasicBlock *IfFalseBB = PBI->getSuccessor(1); + if (!isWidenableBranch(PBI) || IfTrueBB != BI->getParent() || + !BI->getParent()->getSinglePredecessor()) return false; if (!IfFalseBB->phis().empty()) return false; // TODO