/// isFormingBranchFromSelectProfitable - Returns true if a SelectInst should be /// turned into an explicit branch. static bool isFormingBranchFromSelectProfitable(SelectInst *SI) { // FIXME: This should use the same heuristics as IfConversion to determine // whether a select is better represented as a branch. This requires that // branch probability metadata is preserved for the select, which is not the // case currently. CmpInst *Cmp = dyn_cast<CmpInst>(SI->getCondition()); // If the branch is predicted right, an out of order CPU can avoid blocking on // the compare. Emit cmovs on compares with a memory operand as branches to // avoid stalls on the load from memory. If the compare has more than one use // there's probably another cmov or setcc around so it's not worth emitting a // branch. if (!Cmp) return false; Value *CmpOp0 = Cmp->getOperand(0); Value *CmpOp1 = Cmp->getOperand(1); // We check that the memory operand has one use to avoid uses of the loaded // value directly after the compare, making branches unprofitable. return Cmp->hasOneUse() && ((isa<LoadInst>(CmpOp0) && CmpOp0->hasOneUse()) || (isa<LoadInst>(CmpOp1) && CmpOp1->hasOneUse())); }
/// Try to simplify cmp instruction. bool UnrolledInstAnalyzer::visitCmpInst(CmpInst &I) { Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); // First try to handle simplified comparisons. if (!isa<Constant>(LHS)) if (Constant *SimpleLHS = SimplifiedValues.lookup(LHS)) LHS = SimpleLHS; if (!isa<Constant>(RHS)) if (Constant *SimpleRHS = SimplifiedValues.lookup(RHS)) RHS = SimpleRHS; if (!isa<Constant>(LHS) && !isa<Constant>(RHS)) { auto SimplifiedLHS = SimplifiedAddresses.find(LHS); if (SimplifiedLHS != SimplifiedAddresses.end()) { auto SimplifiedRHS = SimplifiedAddresses.find(RHS); if (SimplifiedRHS != SimplifiedAddresses.end()) { SimplifiedAddress &LHSAddr = SimplifiedLHS->second; SimplifiedAddress &RHSAddr = SimplifiedRHS->second; if (LHSAddr.Base == RHSAddr.Base) { LHS = LHSAddr.Offset; RHS = RHSAddr.Offset; } } } } if (Constant *CLHS = dyn_cast<Constant>(LHS)) { if (Constant *CRHS = dyn_cast<Constant>(RHS)) { if (Constant *C = ConstantExpr::getCompare(I.getPredicate(), CLHS, CRHS)) { SimplifiedValues[&I] = C; return true; } } } return Base::visitCmpInst(I); }
// Predict that a comparison in which a register is an operand, the register is // used before being defined in a successor block, and the successor block // does not post-dominate will reach the successor block. int BranchProbabilities::CheckGuardHeuristic() { BranchInst *BI = dyn_cast<BranchInst>(_TI); bool bUses[2] = {false, false}; // If we don't have a conditional branch, abandon if ((!BI) || (BI->isUnconditional())) return -1; // If the condition is not immediately dependent on a comparison, abandon CmpInst *cmp = dyn_cast<CmpInst>(BI->getCondition()); if (!cmp) return -1; for (int i = 0; i < 2; i++) { if (_bPostDoms[i]) continue; // Get the values being compared Value *v = cmp->getOperand(i); // For all uses of the first value check if the use post-dominates for (Value::use_iterator UI = v->use_begin(), UE = v->use_end(); UI != UE; ++UI) { // if the use is not an instruction, skip it Instruction *I = dyn_cast<Instruction>(*UI); if (!I) continue; BasicBlock *UsingBlock = I->getParent(); // Check if the use is in either successor for (int i = 0; i < 2; i++) if (UsingBlock == _Succ[i]) bUses[i] = true; } } if (bUses[0] == bUses[1]) return -1; if (bUses[0]) return 0; else return 1; }
void SystemZTDCPass::convertFCmp(CmpInst &I) { Value *Op0 = I.getOperand(0); auto *Const = dyn_cast<ConstantFP>(I.getOperand(1)); auto Pred = I.getPredicate(); // Only comparisons with consts are interesting. if (!Const) return; // Compute the smallest normal number (and its negation). auto &Sem = Op0->getType()->getFltSemantics(); APFloat Smallest = APFloat::getSmallestNormalized(Sem); APFloat NegSmallest = Smallest; NegSmallest.changeSign(); // Check if Const is one of our recognized consts. int WhichConst; if (Const->isZero()) { // All comparisons with 0 can be converted. WhichConst = 0; } else if (Const->isInfinity()) { // Likewise for infinities. WhichConst = Const->isNegative() ? 2 : 1; } else if (Const->isExactlyValue(Smallest)) { // For Smallest, we cannot do EQ separately from GT. if ((Pred & CmpInst::FCMP_OGE) != CmpInst::FCMP_OGE && (Pred & CmpInst::FCMP_OGE) != 0) return; WhichConst = 3; } else if (Const->isExactlyValue(NegSmallest)) { // Likewise for NegSmallest, we cannot do EQ separately from LT. if ((Pred & CmpInst::FCMP_OLE) != CmpInst::FCMP_OLE && (Pred & CmpInst::FCMP_OLE) != 0) return; WhichConst = 4; } else { // Not one of our special constants. return; } // Partial masks to use for EQ, GT, LT, UN comparisons, respectively. static const int Masks[][4] = { { // 0 SystemZ::TDCMASK_ZERO, // eq SystemZ::TDCMASK_POSITIVE, // gt SystemZ::TDCMASK_NEGATIVE, // lt SystemZ::TDCMASK_NAN, // un }, { // inf SystemZ::TDCMASK_INFINITY_PLUS, // eq 0, // gt (SystemZ::TDCMASK_ZERO | SystemZ::TDCMASK_NEGATIVE | SystemZ::TDCMASK_NORMAL_PLUS | SystemZ::TDCMASK_SUBNORMAL_PLUS), // lt SystemZ::TDCMASK_NAN, // un }, { // -inf SystemZ::TDCMASK_INFINITY_MINUS, // eq (SystemZ::TDCMASK_ZERO | SystemZ::TDCMASK_POSITIVE | SystemZ::TDCMASK_NORMAL_MINUS | SystemZ::TDCMASK_SUBNORMAL_MINUS), // gt 0, // lt SystemZ::TDCMASK_NAN, // un }, { // minnorm 0, // eq (unsupported) (SystemZ::TDCMASK_NORMAL_PLUS | SystemZ::TDCMASK_INFINITY_PLUS), // gt (actually ge) (SystemZ::TDCMASK_ZERO | SystemZ::TDCMASK_NEGATIVE | SystemZ::TDCMASK_SUBNORMAL_PLUS), // lt SystemZ::TDCMASK_NAN, // un }, { // -minnorm 0, // eq (unsupported) (SystemZ::TDCMASK_ZERO | SystemZ::TDCMASK_POSITIVE | SystemZ::TDCMASK_SUBNORMAL_MINUS), // gt (SystemZ::TDCMASK_NORMAL_MINUS | SystemZ::TDCMASK_INFINITY_MINUS), // lt (actually le) SystemZ::TDCMASK_NAN, // un } }; // Construct the mask as a combination of the partial masks. int Mask = 0; if (Pred & CmpInst::FCMP_OEQ) Mask |= Masks[WhichConst][0]; if (Pred & CmpInst::FCMP_OGT) Mask |= Masks[WhichConst][1]; if (Pred & CmpInst::FCMP_OLT) Mask |= Masks[WhichConst][2]; if (Pred & CmpInst::FCMP_UNO) Mask |= Masks[WhichConst][3]; // A lone fcmp is unworthy of tdc conversion on its own, but may become // worthy if combined with fabs. bool Worthy = false; if (CallInst *CI = dyn_cast<CallInst>(Op0)) { Function *F = CI->getCalledFunction(); if (F && F->getIntrinsicID() == Intrinsic::fabs) { // Fold with fabs - adjust the mask appropriately. Mask &= SystemZ::TDCMASK_PLUS; Mask |= Mask >> 1; Op0 = CI->getArgOperand(0); // A combination of fcmp with fabs is a win, unless the constant // involved is 0 (which is handled by later passes). Worthy = WhichConst != 0; PossibleJunk.insert(CI); }
bool CallAnalyzer::visitCmpInst(CmpInst &I) { Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); // First try to handle simplified comparisons. if (!isa<Constant>(LHS)) if (Constant *SimpleLHS = SimplifiedValues.lookup(LHS)) LHS = SimpleLHS; if (!isa<Constant>(RHS)) if (Constant *SimpleRHS = SimplifiedValues.lookup(RHS)) RHS = SimpleRHS; if (Constant *CLHS = dyn_cast<Constant>(LHS)) { if (Constant *CRHS = dyn_cast<Constant>(RHS)) if (Constant *C = ConstantExpr::getCompare(I.getPredicate(), CLHS, CRHS)) { SimplifiedValues[&I] = C; return true; } } if (I.getOpcode() == Instruction::FCmp) return false; // Otherwise look for a comparison between constant offset pointers with // a common base. Value *LHSBase, *RHSBase; APInt LHSOffset, RHSOffset; std::tie(LHSBase, LHSOffset) = ConstantOffsetPtrs.lookup(LHS); if (LHSBase) { std::tie(RHSBase, RHSOffset) = ConstantOffsetPtrs.lookup(RHS); if (RHSBase && LHSBase == RHSBase) { // We have common bases, fold the icmp to a constant based on the // offsets. Constant *CLHS = ConstantInt::get(LHS->getContext(), LHSOffset); Constant *CRHS = ConstantInt::get(RHS->getContext(), RHSOffset); if (Constant *C = ConstantExpr::getICmp(I.getPredicate(), CLHS, CRHS)) { SimplifiedValues[&I] = C; ++NumConstantPtrCmps; return true; } } } // If the comparison is an equality comparison with null, we can simplify it // for any alloca-derived argument. if (I.isEquality() && isa<ConstantPointerNull>(I.getOperand(1))) if (isAllocaDerivedArg(I.getOperand(0))) { // We can actually predict the result of comparisons between an // alloca-derived value and null. Note that this fires regardless of // SROA firing. bool IsNotEqual = I.getPredicate() == CmpInst::ICMP_NE; SimplifiedValues[&I] = IsNotEqual ? ConstantInt::getTrue(I.getType()) : ConstantInt::getFalse(I.getType()); return true; } // Finally check for SROA candidates in comparisons. Value *SROAArg; DenseMap<Value *, int>::iterator CostIt; if (lookupSROAArgAndCost(I.getOperand(0), SROAArg, CostIt)) { if (isa<ConstantPointerNull>(I.getOperand(1))) { accumulateSROACost(CostIt, InlineConstants::InstrCost); return true; } disableSROA(CostIt); } return false; }
void CGGraph::constructGraph() { std::vector<CGConstraint*>::iterator it; std::string nodeName; CGConstraint* curConstraint; CGNode* firstNode; CGNode* secondNode; std::vector<int>::iterator lengthIt; int curValue; ConstantInt* cInt; for (it = constraints.begin(); it != constraints.end(); ++it) { curConstraint = *it; Instruction* PP = curConstraint->programPoint; switch(curConstraint->type) { case CGConstraint::C1: { firstNode = getNode(getNameFromValue(curConstraint->programPoint->getOperand(0), PP)); secondNode = getNode(getNameFromValue(curConstraint->programPoint->getOperand(1), PP)); firstNode->connectTo(secondNode, 0); break; } case CGConstraint::C2: { if (isa<StoreInst>(PP)) { /* operand(0) = constant int or variable of int type operand(1) = var being stored into */ firstNode = getNode(getNameFromValue(PP->getOperand(0), PP)); secondNode = getNode(getNameFromValue(PP->getOperand(1), PP)); firstNode->connectTo(secondNode, 0); } else if (isa<LoadInst>(PP)) { /* operand(0) = pointer being loaded from (Value*)PP = var being loaded into */ firstNode = getNode(getNameFromValue(PP->getOperand(0), PP)); secondNode = getNode(getNameFromValue(PP, PP)); firstNode->connectTo(secondNode, 0); } else if (isa<CastInst>(PP)) { /* operand(0) = var being casted (Value*)PP = var getting the result of the cast */ firstNode = getNode(getNameFromValue(PP->getOperand(0), PP)); secondNode = getNode(getNameFromValue(PP, PP)); firstNode->connectTo(secondNode, 0); } break; } case CGConstraint::C3: { secondNode = getNode(getNameFromValue(PP, PP)); if ((cInt = dyn_cast<ConstantInt>(curConstraint->programPoint->getOperand(0)))) { firstNode = getNode(getNameFromValue(curConstraint->programPoint->getOperand(1), PP)); } else if ((cInt = dyn_cast<ConstantInt>(curConstraint->programPoint->getOperand(1)))) { firstNode = getNode(getNameFromValue(curConstraint->programPoint->getOperand(0), PP)); } else { return; } curValue = cInt->getSExtValue(); firstNode->connectTo(secondNode, curValue); break; } case CGConstraint::C4: { CmpInst* cmpInst; BranchInst* branchInst; if( !(branchInst = dyn_cast<BranchInst>(curConstraint->programPoint)) ) { errs() << "ERROR: BranchInst cast unsuccessful for C4 in CGGraph::constructGraph() \n"; return; } if( !(cmpInst = dyn_cast<CmpInst>(owner->branchToCompare[branchInst])) ) { errs() << "ERROR: CmpInst not found for C4 in CGGraph::constructGraph() \n"; return; } int size1, size2; size1 = curConstraint->piAssignments.size(); size2 = curConstraint->piAssignments2.size(); /* There are two possibilities here: (a) size1 = size2 = 2, or (b) size1 = size2 = 1; If (b), there will be one operand in the compare inst that is a literal value. That literal value still generates a constraint although it does not generate a pi assignment. We need to account for that. */ if (size1 != size2) { errs() << "ERROR: piAssignments not of equal length for C4 in CGGraph::constructGraph()\n"; return; } if ( (size1 < 1) || (size1 > 2) ) { errs() << "ERROR: piAssignments.size() != 1 or 2 for C4 in CGGraph::constructGraph()\n"; return; } //this takes care of the first two constraints for both cases (size = 1 or size = 2) //first branch for (int i = 0; i < size1; ++i) { firstNode = getNode(curConstraint->piAssignments[i]->getOperandName()); //vi - wr secondNode = getNode(curConstraint->piAssignments[i]->getAssignedName()); //vj - ws firstNode->connectTo(secondNode, 0); //vi -> vj 0 - wr -> ws 0 } //second branch for (int i = 0; i < size2; ++i) { firstNode = getNode(curConstraint->piAssignments2[i]->getOperandName()); //vi - wr secondNode = getNode(curConstraint->piAssignments2[i]->getAssignedName()); //vk - wt firstNode->connectTo(secondNode, 0); //vi -> vk 0 - wr -> wt 0 } /* - first and second op names for the third constraint for branches 1 and 2 - each case is stored in the order of the pi assignments, which is also the order of the cmp instruction operands */ std::string firstOpNameBr1, secondOpNameBr1, firstOpNameBr2, secondOpNameBr2; if (size1 == 1) { /* the 2nd constraint in the table will not exist in this case, but there will be a 3rd constraint that was missed by the above, e.g. if (x1 <= 10) 1. x2 <= x1 2. nothing 3. x2 <= 10 <---- we need to add this here */ //prune the int from the CmpInst if (cmpInst->getNumOperands() != 2) { errs() << "ERROR: cmpInst->getNumOperands() != 2 in CGGraph::constructGraph()\n"; return; } if ((cInt = dyn_cast<ConstantInt>(cmpInst->getOperand(0)))) { //int is first op firstOpNameBr1 = getNameFromValue(cInt, PP); secondOpNameBr1 = curConstraint->piAssignments[0]->getAssignedName(); firstOpNameBr2 = firstOpNameBr1; secondOpNameBr2 = curConstraint->piAssignments2[0]->getAssignedName(); } else if ((cInt = dyn_cast<ConstantInt>(cmpInst->getOperand(1)))) { //int is second op firstOpNameBr1 = curConstraint->piAssignments[0]->getAssignedName(); secondOpNameBr1 = getNameFromValue(cInt, PP); firstOpNameBr2 = curConstraint->piAssignments2[0]->getAssignedName(); secondOpNameBr2 = secondOpNameBr1; } else { errs() << "ERROR: int not found in cmpInstr in CGGraph::constructGraph()\n"; return; } } else if (size1 == 2) { //store in order of pi assignments firstOpNameBr1 = curConstraint->piAssignments[0]->getAssignedName(); secondOpNameBr1 = curConstraint->piAssignments[1]->getAssignedName(); firstOpNameBr2 = curConstraint->piAssignments2[0]->getAssignedName(); secondOpNameBr2 = curConstraint->piAssignments2[1]->getAssignedName(); } CGNode* firstNodeBr1 = getNode(firstOpNameBr1); CGNode* secondNodeBr1 = getNode(secondOpNameBr1); CGNode* firstNodeBr2 = getNode(firstOpNameBr2); CGNode* secondNodeBr2 = getNode(secondOpNameBr2); switch(cmpInst->getPredicate()) { case CmpInst::ICMP_SGT: // > firstNodeBr1->connectTo(secondNodeBr1, -1); //vj -> ws -1 secondNodeBr2->connectTo(firstNodeBr2, 0); //wt -> vk 0 break; case CmpInst::ICMP_SLT: // < secondNodeBr1->connectTo(firstNodeBr1, -1); //ws -> vj -1 firstNodeBr2->connectTo(secondNodeBr2, 0); //vk -> wt 0 break; case CmpInst::ICMP_SGE: // >= firstNodeBr1->connectTo(secondNodeBr1, 0); //vj -> ws 0 secondNodeBr2->connectTo(firstNodeBr2, -1); //wt -> vk -1 break; case CmpInst::ICMP_SLE: // <= secondNodeBr1->connectTo(firstNodeBr1, 0); //ws -> vj 0 firstNodeBr2->connectTo(secondNodeBr2, -1); //vk -> wt -1 break; default: break; } break; } case CGConstraint::C5: { //operand 1 = array length firstNode = getNode(getNameFromValue(PP->getOperand(1), PP)); secondNode = getNode(curConstraint->piAssignments[0]->getAssignedName()); firstNode->connectTo(secondNode, -1); break; } case CGConstraint::CONTROL_FLOW: { //Done and ready to test firstNode = getNode(getNameFromValue(curConstraint->programPoint->getOperand(0), PP)); secondNode = getNode(getNameFromValue(curConstraint->programPoint, PP)); firstNode->connectTo(secondNode, 0); firstNode = getNode(getNameFromValue(curConstraint->programPoint->getOperand(1), PP)); firstNode->connectTo(secondNode, 0); break; } } //end switch } //end for } //end constructGraph()
// Compute the unlikely successors to the block BB in the loop L, specifically // those that are unlikely because this is a loop, and add them to the // UnlikelyBlocks set. static void computeUnlikelySuccessors(const BasicBlock *BB, Loop *L, SmallPtrSetImpl<const BasicBlock*> &UnlikelyBlocks) { // Sometimes in a loop we have a branch whose condition is made false by // taking it. This is typically something like // int n = 0; // while (...) { // if (++n >= MAX) { // n = 0; // } // } // In this sort of situation taking the branch means that at the very least it // won't be taken again in the next iteration of the loop, so we should // consider it less likely than a typical branch. // // We detect this by looking back through the graph of PHI nodes that sets the // value that the condition depends on, and seeing if we can reach a successor // block which can be determined to make the condition false. // // FIXME: We currently consider unlikely blocks to be half as likely as other // blocks, but if we consider the example above the likelyhood is actually // 1/MAX. We could therefore be more precise in how unlikely we consider // blocks to be, but it would require more careful examination of the form // of the comparison expression. const BranchInst *BI = dyn_cast<BranchInst>(BB->getTerminator()); if (!BI || !BI->isConditional()) return; // Check if the branch is based on an instruction compared with a constant CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition()); if (!CI || !isa<Instruction>(CI->getOperand(0)) || !isa<Constant>(CI->getOperand(1))) return; // Either the instruction must be a PHI, or a chain of operations involving // constants that ends in a PHI which we can then collapse into a single value // if the PHI value is known. Instruction *CmpLHS = dyn_cast<Instruction>(CI->getOperand(0)); PHINode *CmpPHI = dyn_cast<PHINode>(CmpLHS); Constant *CmpConst = dyn_cast<Constant>(CI->getOperand(1)); // Collect the instructions until we hit a PHI SmallVector<BinaryOperator *, 1> InstChain; while (!CmpPHI && CmpLHS && isa<BinaryOperator>(CmpLHS) && isa<Constant>(CmpLHS->getOperand(1))) { // Stop if the chain extends outside of the loop if (!L->contains(CmpLHS)) return; InstChain.push_back(cast<BinaryOperator>(CmpLHS)); CmpLHS = dyn_cast<Instruction>(CmpLHS->getOperand(0)); if (CmpLHS) CmpPHI = dyn_cast<PHINode>(CmpLHS); } if (!CmpPHI || !L->contains(CmpPHI)) return; // Trace the phi node to find all values that come from successors of BB SmallPtrSet<PHINode*, 8> VisitedInsts; SmallVector<PHINode*, 8> WorkList; WorkList.push_back(CmpPHI); VisitedInsts.insert(CmpPHI); while (!WorkList.empty()) { PHINode *P = WorkList.back(); WorkList.pop_back(); for (BasicBlock *B : P->blocks()) { // Skip blocks that aren't part of the loop if (!L->contains(B)) continue; Value *V = P->getIncomingValueForBlock(B); // If the source is a PHI add it to the work list if we haven't // already visited it. if (PHINode *PN = dyn_cast<PHINode>(V)) { if (VisitedInsts.insert(PN).second) WorkList.push_back(PN); continue; } // If this incoming value is a constant and B is a successor of BB, then // we can constant-evaluate the compare to see if it makes the branch be // taken or not. Constant *CmpLHSConst = dyn_cast<Constant>(V); if (!CmpLHSConst || std::find(succ_begin(BB), succ_end(BB), B) == succ_end(BB)) continue; // First collapse InstChain for (Instruction *I : llvm::reverse(InstChain)) { CmpLHSConst = ConstantExpr::get(I->getOpcode(), CmpLHSConst, cast<Constant>(I->getOperand(1)), true); if (!CmpLHSConst) break; } if (!CmpLHSConst) continue; // Now constant-evaluate the compare Constant *Result = ConstantExpr::getCompare(CI->getPredicate(), CmpLHSConst, CmpConst, true); // If the result means we don't branch to the block then that block is // unlikely. if (Result && ((Result->isZeroValue() && B == BI->getSuccessor(0)) || (Result->isOneValue() && B == BI->getSuccessor(1)))) UnlikelyBlocks.insert(B); } } }
/// MatchGuardHeuristic - Predict that a comparison in which a register is /// an operand, the register is used before being defined in a successor /// block, and the successor block does not post-dominate will reach the /// successor block. /// @returns a Prediction that is a pair in which the first element is the /// successor taken, and the second the successor not taken. Prediction BranchHeuristicsInfo::MatchGuardHeuristic(BasicBlock *root) const { bool matched = false; Prediction pred; // Last instruction of basic block. TerminatorInst *TI = root->getTerminator(); // Basic block successors. True and False branches. BasicBlock *trueSuccessor = TI->getSuccessor(0); BasicBlock *falseSuccessor = TI->getSuccessor(1); // Is the last instruction a Branch Instruction? BranchInst *BI = dyn_cast<BranchInst>(TI); if (!BI || !BI->isConditional()) return empty; // Conditional instruction. Value *cond = BI->getCondition(); // Find if the variable used in the branch instruction is // in fact a comparison instruction. CmpInst *CI = dyn_cast<CmpInst>(cond); if (!CI) return empty; // Seek over all of the operands of this comparison instruction. for (unsigned ops = 0; ops < CI->getNumOperands(); ++ops) { // Find the operand. Value *operand = CI->getOperand(ops); // Check if the operand is neither a function argument or a value. if (!isa<Argument>(operand) && !isa<User>(operand)) continue; // Check if this variable was used in the true successor and // does not post dominate. // Since LLVM is in SSA form, it's impossible for a variable being used // before being defined, so that statement is skipped. if (operand->isUsedInBasicBlock(trueSuccessor) && !PDT->dominates(trueSuccessor, root)) { // If a heuristic was already matched, predict none and abort immediately. if (matched) return empty; matched = true; pred = std::make_pair(trueSuccessor, falseSuccessor); } // Check if this variable was used in the false successor and // does not post dominate. if (operand->isUsedInBasicBlock(falseSuccessor) && !PDT->dominates(falseSuccessor, root)) { // If a heuristic was already matched, predict none and abort immediately. if (matched) return empty; matched = true; pred = std::make_pair(falseSuccessor, trueSuccessor); } } return (matched ? pred : empty); }