@@ -445,6 +445,7 @@ class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> {
445445 bool canFoldInboundsGEP (GetElementPtrInst &I);
446446 bool accumulateGEPOffset (GEPOperator &GEP, APInt &Offset);
447447 bool simplifyCallSite (Function *F, CallBase &Call);
448+ bool simplifyCmpInst (Function *F, CmpInst &Cmp);
448449 bool simplifyInstruction (Instruction &I);
449450 bool simplifyIntrinsicCallIsConstant (CallBase &CB);
450451 bool simplifyIntrinsicCallObjectSize (CallBase &CB);
@@ -1171,10 +1172,6 @@ class InlineCostCallAnalyzer final : public CallAnalyzer {
11711172 std::optional<CostBenefitPair> getCostBenefitPair () { return CostBenefit; }
11721173 bool wasDecidedByCostBenefit () const { return DecidedByCostBenefit; }
11731174 bool wasDecidedByCostThreshold () const { return DecidedByCostThreshold; }
1174- bool shouldCheckRecursiveCall () {
1175- return IsRecursiveCall && AllowRecursiveCall;
1176- }
1177- bool shouldInlineRecursiveCall (CallBase &Call);
11781175};
11791176
11801177// Return true if CB is the sole call to local function Callee.
@@ -1681,6 +1678,68 @@ bool CallAnalyzer::visitGetElementPtr(GetElementPtrInst &I) {
16811678 return isGEPFree (I);
16821679}
16831680
1681+ // / Simplify \p Cmp if RHS is const and we can ValueTrack LHS,
1682+ // This handles the case when the Cmp instruction is guarded a recursive call
1683+ // that will cause the Cmp to fail/succeed for the next iteration.
1684+ bool CallAnalyzer::simplifyCmpInst (Function *F, CmpInst &Cmp) {
1685+ // Bail out if the RHS is NOT const:
1686+ if (!isa<Constant>(Cmp.getOperand (1 )))
1687+ return false ;
1688+ auto *CmpOp = Cmp.getOperand (0 );
1689+ // Iterate over the users of the function to check if it's a recursive function:
1690+ for (auto *U : F->users ()) {
1691+ CallInst *Call = dyn_cast<CallInst>(U);
1692+ if (!Call || Call->getFunction () != F)
1693+ continue ;
1694+ auto *CallBB = Call->getParent ();
1695+ auto *Predecessor = CallBB->getSinglePredecessor ();
1696+ // Only handle the case when the callsite has a single predecessor:
1697+ if (!Predecessor)
1698+ continue ;
1699+
1700+ auto *Br = dyn_cast<BranchInst>(Predecessor->getTerminator ());
1701+ if (!Br || Br->isUnconditional ())
1702+ continue ;
1703+ // Check if the Br condition is the same Cmp instr we are investigating:
1704+ auto *CmpInstr = dyn_cast<CmpInst>(Br->getCondition ());
1705+ if (!CmpInstr || CmpInstr != &Cmp)
1706+ continue ;
1707+ // Check if there are any arg of the recursive callsite is affecting the cmp instr:
1708+ bool ArgFound = false ;
1709+ Value *FuncArg = nullptr , *CallArg = nullptr ;
1710+ for (unsigned ArgNum = 0 ; ArgNum < F->arg_size () && ArgNum < Call->arg_size (); ArgNum ++) {
1711+ FuncArg = F->getArg (ArgNum);
1712+ CallArg = Call->getArgOperand (ArgNum);
1713+ if ((FuncArg == CmpOp) &&
1714+ (CallArg != CmpOp)) {
1715+ ArgFound = true ;
1716+ break ;
1717+ }
1718+ }
1719+ if (!ArgFound)
1720+ continue ;
1721+ // Now we have a recursive call that is guarded by a cmp instruction.
1722+ // Check if this cmp can be simplified:
1723+ SimplifyQuery SQ (DL, dyn_cast<Instruction>(CallArg));
1724+ DomConditionCache DC;
1725+ DC.registerBranch (Br);
1726+ SQ.DC = &DC;
1727+ DominatorTree DT (*F);
1728+ SQ.DT = &DT;
1729+ Value *simplifiedInstruction = llvm::simplifyInstructionWithOperands (CmpInstr, {CallArg, Cmp.getOperand (1 )}, SQ);
1730+ if (!simplifiedInstruction)
1731+ continue ;
1732+ if (auto *ConstVal = dyn_cast<llvm::ConstantInt>(simplifiedInstruction)) {
1733+ bool isTrueSuccessor = CallBB == Br->getSuccessor (0 );
1734+ SimplifiedValues[&Cmp] = ConstVal;
1735+ if (ConstVal->isOne ())
1736+ return !isTrueSuccessor;
1737+ return isTrueSuccessor;
1738+ }
1739+ }
1740+ return false ;
1741+ }
1742+
16841743// / Simplify \p I if its operands are constants and update SimplifiedValues.
16851744bool CallAnalyzer::simplifyInstruction (Instruction &I) {
16861745 SmallVector<Constant *> COps;
@@ -2065,6 +2124,10 @@ bool CallAnalyzer::visitCmpInst(CmpInst &I) {
20652124 if (simplifyInstruction (I))
20662125 return true ;
20672126
2127+ // Try to handle comparison that can be simplified using ValueTracking.
2128+ if (simplifyCmpInst (I.getFunction (), I))
2129+ return true ;
2130+
20682131 if (I.getOpcode () == Instruction::FCmp)
20692132 return false ;
20702133
@@ -2900,68 +2963,6 @@ InlineResult CallAnalyzer::analyze() {
29002963 return finalizeAnalysis ();
29012964}
29022965
2903- bool InlineCostCallAnalyzer::shouldInlineRecursiveCall (CallBase &Call) {
2904- CallInst *CI = cast<CallInst>(&Call);
2905- auto CIB = CI->getParent ();
2906- // Only handle case when we have sinlge predecessor
2907- if (auto Predecessor = CIB->getSinglePredecessor ()) {
2908- BranchInst *Br = dyn_cast<BranchInst>(Predecessor->getTerminator ());
2909- if (!Br || Br->isUnconditional ()) {
2910- return false ;
2911- }
2912- Value *Var = Br->getCondition ();
2913- CmpInst *CmpInstr = dyn_cast<CmpInst>(Var);
2914- if (CmpInstr && !isa<Constant>(CmpInstr->getOperand (1 ))) {
2915- // Current logic of ValueTracking/DomConditionCache works only if RHS is
2916- // constant.
2917- return false ;
2918- }
2919- unsigned ArgNum = 0 ;
2920- Value *FuncArg = nullptr , *CallArg = nullptr ;
2921- // Check which func argument the cmp instr is using:
2922- for (; ArgNum < CI->getFunction ()->arg_size (); ArgNum++) {
2923- FuncArg = CI->getFunction ()->getArg (ArgNum);
2924- CallArg = CI->getArgOperand (ArgNum);
2925- if (CmpInstr) {
2926- if ((FuncArg == CmpInstr->getOperand (0 )) &&
2927- (CallArg != CmpInstr->getOperand (0 )))
2928- break ;
2929- } else if (FuncArg == Var && (CallArg != Var))
2930- break ;
2931- }
2932- // Only handle the case when a func argument controls the cmp instruction:
2933- if (ArgNum < CI->getFunction ()->arg_size ()) {
2934- bool isTrueSuccessor = CIB == Br->getSuccessor (0 );
2935- if (CmpInstr) {
2936- SimplifyQuery SQ (CI->getFunction ()->getDataLayout (),
2937- dyn_cast<Instruction>(CallArg));
2938- DomConditionCache DC;
2939- DC.registerBranch (Br);
2940- SQ.DC = &DC;
2941- DominatorTree DT (*CI->getFunction ());
2942- SQ.DT = &DT;
2943- Value *simplifiedInstruction = llvm::simplifyInstructionWithOperands (
2944- CmpInstr, {CallArg, CmpInstr->getOperand (1 )}, SQ);
2945- if (!simplifiedInstruction)
2946- return false ;
2947- if (auto *ConstVal =
2948- dyn_cast<llvm::ConstantInt>(simplifiedInstruction)) {
2949- if (ConstVal->isOne ())
2950- return !isTrueSuccessor;
2951- return isTrueSuccessor;
2952- }
2953- } else {
2954- if (auto *ConstVal = dyn_cast<llvm::ConstantInt>(CallArg)) {
2955- if (ConstVal->isOne ())
2956- return !isTrueSuccessor;
2957- return isTrueSuccessor;
2958- }
2959- }
2960- }
2961- }
2962- return false ;
2963- }
2964-
29652966void InlineCostCallAnalyzer::print (raw_ostream &OS) {
29662967#define DEBUG_PRINT_STAT (x ) OS << " " #x " : " << x << " \n "
29672968 if (PrintInstructionComments)
@@ -3193,12 +3194,6 @@ InlineCost llvm::getInlineCost(
31933194
31943195 LLVM_DEBUG (CA.dump ());
31953196
3196- // Check if callee function is recursive:
3197- if (ShouldInline.isSuccess ()) {
3198- if (CA.shouldCheckRecursiveCall () && !CA.shouldInlineRecursiveCall (Call))
3199- return InlineCost::getNever (" deep recursion" );
3200- }
3201-
32023197 // Always make cost benefit based decision explicit.
32033198 // We use always/never here since threshold is not meaningful,
32043199 // as it's not what drives cost-benefit analysis.
@@ -3241,13 +3236,6 @@ InlineResult llvm::isInlineViable(Function &F) {
32413236
32423237 // Disallow recursive calls.
32433238 Function *Callee = Call->getCalledFunction ();
3244- // This function is called when we have "alwaysinline" attribute.
3245- // If we allowed the inlining here given that the recursive inlining is
3246- // allowed, then there will be problem in the second trial of inlining,
3247- // because the Inliner pass allow only one time inlining and then it
3248- // inserts "noinline" attribute which will be in conflict with the
3249- // attribute of "alwaysinline" so, "alwaysinline" for recursive function
3250- // will be disallowed to avoid conflict of attributes.
32513239 if (&F == Callee)
32523240 return InlineResult::failure (" recursive call" );
32533241
0 commit comments