Index: llvm/include/llvm/Analysis/GuardUtils.h =================================================================== --- llvm/include/llvm/Analysis/GuardUtils.h +++ llvm/include/llvm/Analysis/GuardUtils.h @@ -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 @@ -130,7 +130,8 @@ Worklist.push_back(RHS); continue; } - Callback(Check); + if (!Callback(Check)) + break; } while (!Worklist.empty()); } @@ -143,5 +144,26 @@ 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) { + if (isWidenableCondition(Check) && Check->hasOneUse()) { + WidenableCondition = Check; + return false; + } + return true; }); + return WidenableCondition; }