// Converts LLVM encoding of comparison predicates to the // corresponding bitcode versions. static unsigned GetEncodedCmpPredicate(const CmpInst &Cmp) { switch (Cmp.getPredicate()) { default: report_fatal_error( "Comparison predicate not supported by PNaCl bitcode"); case CmpInst::FCMP_FALSE: return naclbitc::FCMP_FALSE; case CmpInst::FCMP_OEQ: return naclbitc::FCMP_OEQ; case CmpInst::FCMP_OGT: return naclbitc::FCMP_OGT; case CmpInst::FCMP_OGE: return naclbitc::FCMP_OGE; case CmpInst::FCMP_OLT: return naclbitc::FCMP_OLT; case CmpInst::FCMP_OLE: return naclbitc::FCMP_OLE; case CmpInst::FCMP_ONE: return naclbitc::FCMP_ONE; case CmpInst::FCMP_ORD: return naclbitc::FCMP_ORD; case CmpInst::FCMP_UNO: return naclbitc::FCMP_UNO; case CmpInst::FCMP_UEQ: return naclbitc::FCMP_UEQ; case CmpInst::FCMP_UGT: return naclbitc::FCMP_UGT; case CmpInst::FCMP_UGE: return naclbitc::FCMP_UGE; case CmpInst::FCMP_ULT: return naclbitc::FCMP_ULT; case CmpInst::FCMP_ULE: return naclbitc::FCMP_ULE; case CmpInst::FCMP_UNE: return naclbitc::FCMP_UNE; case CmpInst::FCMP_TRUE: return naclbitc::FCMP_TRUE; case CmpInst::ICMP_EQ: return naclbitc::ICMP_EQ; case CmpInst::ICMP_NE: return naclbitc::ICMP_NE; case CmpInst::ICMP_UGT: return naclbitc::ICMP_UGT; case CmpInst::ICMP_UGE: return naclbitc::ICMP_UGE; case CmpInst::ICMP_ULT: return naclbitc::ICMP_ULT; case CmpInst::ICMP_ULE: return naclbitc::ICMP_ULE; case CmpInst::ICMP_SGT: return naclbitc::ICMP_SGT; case CmpInst::ICMP_SGE: return naclbitc::ICMP_SGE; case CmpInst::ICMP_SLT: return naclbitc::ICMP_SLT; case CmpInst::ICMP_SLE: return naclbitc::ICMP_SLE; } }
/// 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); }
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; }
/// If \param [in] BB has more than one predecessor that is a conditional /// branch, attempt to use parallel and/or for the branch condition. \returns /// true on success. /// /// Before: /// ...... /// %cmp10 = fcmp une float %tmp1, %tmp2 /// br i1 %cmp1, label %if.then, label %lor.rhs /// /// lor.rhs: /// ...... /// %cmp11 = fcmp une float %tmp3, %tmp4 /// br i1 %cmp11, label %if.then, label %ifend /// /// if.end: // the merge block /// ...... /// /// if.then: // has two predecessors, both of them contains conditional branch. /// ...... /// br label %if.end; /// /// After: /// ...... /// %cmp10 = fcmp une float %tmp1, %tmp2 /// ...... /// %cmp11 = fcmp une float %tmp3, %tmp4 /// %cmp12 = or i1 %cmp10, %cmp11 // parallel-or mode. /// br i1 %cmp12, label %if.then, label %ifend /// /// if.end: /// ...... /// /// if.then: /// ...... /// br label %if.end; /// /// Current implementation handles two cases. /// Case 1: \param BB is on the else-path. /// /// BB1 /// / | /// BB2 | /// / \ | /// BB3 \ | where, BB1, BB2 contain conditional branches. /// \ | / BB3 contains unconditional branch. /// \ | / BB4 corresponds to \param BB which is also the merge. /// BB => BB4 /// /// /// Corresponding source code: /// /// if (a == b && c == d) /// statement; // BB3 /// /// Case 2: \param BB BB is on the then-path. /// /// BB1 /// / | /// | BB2 /// \ / | where BB1, BB2 contain conditional branches. /// BB => BB3 | BB3 contains unconditiona branch and corresponds /// \ / to \param BB. BB4 is the merge. /// BB4 /// /// Corresponding source code: /// /// if (a == b || c == d) /// statement; // BB3 /// /// In both cases, \param BB is the common successor of conditional branches. /// In Case 1, \param BB (BB4) has an unconditional branch (BB3) as /// its predecessor. In Case 2, \param BB (BB3) only has conditional branches /// as its predecessors. /// bool FlattenCFGOpt::FlattenParallelAndOr(BasicBlock *BB, IRBuilder<> &Builder, Pass *P) { PHINode *PHI = dyn_cast<PHINode>(BB->begin()); if (PHI) return false; // For simplicity, avoid cases containing PHI nodes. BasicBlock *LastCondBlock = NULL; BasicBlock *FirstCondBlock = NULL; BasicBlock *UnCondBlock = NULL; int Idx = -1; // Check predecessors of \param BB. SmallPtrSet<BasicBlock *, 16> Preds(pred_begin(BB), pred_end(BB)); for (SmallPtrSetIterator<BasicBlock *> PI = Preds.begin(), PE = Preds.end(); PI != PE; ++PI) { BasicBlock *Pred = *PI; BranchInst *PBI = dyn_cast<BranchInst>(Pred->getTerminator()); // All predecessors should terminate with a branch. if (!PBI) return false; BasicBlock *PP = Pred->getSinglePredecessor(); if (PBI->isUnconditional()) { // Case 1: Pred (BB3) is an unconditional block, it should // have a single predecessor (BB2) that is also a predecessor // of \param BB (BB4) and should not have address-taken. // There should exist only one such unconditional // branch among the predecessors. if (UnCondBlock || !PP || (Preds.count(PP) == 0) || Pred->hasAddressTaken()) return false; UnCondBlock = Pred; continue; } // Only conditional branches are allowed beyond this point. assert(PBI->isConditional()); // Condition's unique use should be the branch instruction. Value *PC = PBI->getCondition(); if (!PC || !PC->hasOneUse()) return false; if (PP && Preds.count(PP)) { // These are internal condition blocks to be merged from, e.g., // BB2 in both cases. // Should not be address-taken. if (Pred->hasAddressTaken()) return false; // Instructions in the internal condition blocks should be safe // to hoist up. for (BasicBlock::iterator BI = Pred->begin(), BE = PBI; BI != BE;) { Instruction *CI = BI++; if (isa<PHINode>(CI) || !isSafeToSpeculativelyExecute(CI)) return false; } } else { // This is the condition block to be merged into, e.g. BB1 in // both cases. if (FirstCondBlock) return false; FirstCondBlock = Pred; } // Find whether BB is uniformly on the true (or false) path // for all of its predecessors. BasicBlock *PS1 = PBI->getSuccessor(0); BasicBlock *PS2 = PBI->getSuccessor(1); BasicBlock *PS = (PS1 == BB) ? PS2 : PS1; int CIdx = (PS1 == BB) ? 0 : 1; if (Idx == -1) Idx = CIdx; else if (CIdx != Idx) return false; // PS is the successor which is not BB. Check successors to identify // the last conditional branch. if (Preds.count(PS) == 0) { // Case 2. LastCondBlock = Pred; } else { // Case 1 BranchInst *BPS = dyn_cast<BranchInst>(PS->getTerminator()); if (BPS && BPS->isUnconditional()) { // Case 1: PS(BB3) should be an unconditional branch. LastCondBlock = Pred; } } } if (!FirstCondBlock || !LastCondBlock || (FirstCondBlock == LastCondBlock)) return false; TerminatorInst *TBB = LastCondBlock->getTerminator(); BasicBlock *PS1 = TBB->getSuccessor(0); BasicBlock *PS2 = TBB->getSuccessor(1); BranchInst *PBI1 = dyn_cast<BranchInst>(PS1->getTerminator()); BranchInst *PBI2 = dyn_cast<BranchInst>(PS2->getTerminator()); // If PS1 does not jump into PS2, but PS2 jumps into PS1, // attempt branch inversion. if (!PBI1 || !PBI1->isUnconditional() || (PS1->getTerminator()->getSuccessor(0) != PS2)) { // Check whether PS2 jumps into PS1. if (!PBI2 || !PBI2->isUnconditional() || (PS2->getTerminator()->getSuccessor(0) != PS1)) return false; // Do branch inversion. BasicBlock *CurrBlock = LastCondBlock; bool EverChanged = false; while (1) { BranchInst *BI = dyn_cast<BranchInst>(CurrBlock->getTerminator()); CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition()); CmpInst::Predicate Predicate = CI->getPredicate(); // Cannonicalize icmp_ne -> icmp_eq, fcmp_one -> fcmp_oeq if ((Predicate == CmpInst::ICMP_NE) || (Predicate == CmpInst::FCMP_ONE)) { CI->setPredicate(ICmpInst::getInversePredicate(Predicate)); BI->swapSuccessors(); EverChanged = true; } if (CurrBlock == FirstCondBlock) break; CurrBlock = CurrBlock->getSinglePredecessor(); } return EverChanged; } // PS1 must have a conditional branch. if (!PBI1 || !PBI1->isUnconditional()) return false; // PS2 should not contain PHI node. PHI = dyn_cast<PHINode>(PS2->begin()); if (PHI) return false; // Do the transformation. BasicBlock *CB; BranchInst *PBI = dyn_cast<BranchInst>(FirstCondBlock->getTerminator()); bool Iteration = true; BasicBlock *SaveInsertBB = Builder.GetInsertBlock(); BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint(); Value *PC = PBI->getCondition(); do { CB = PBI->getSuccessor(1 - Idx); // Delete the conditional branch. FirstCondBlock->getInstList().pop_back(); FirstCondBlock->getInstList() .splice(FirstCondBlock->end(), CB->getInstList()); PBI = cast<BranchInst>(FirstCondBlock->getTerminator()); Value *CC = PBI->getCondition(); // Merge conditions. Builder.SetInsertPoint(PBI); Value *NC; if (Idx == 0) // Case 2, use parallel or. NC = Builder.CreateOr(PC, CC); else // Case 1, use parallel and. NC = Builder.CreateAnd(PC, CC); PBI->replaceUsesOfWith(CC, NC); PC = NC; if (CB == LastCondBlock) Iteration = false; // Remove internal conditional branches. CB->dropAllReferences(); // make CB unreachable and let downstream to delete the block. new UnreachableInst(CB->getContext(), CB); } while (Iteration); Builder.SetInsertPoint(SaveInsertBB, SaveInsertPt); DEBUG(dbgs() << "Use parallel and/or in:\n" << *FirstCondBlock); return true; }
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); } } }