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()
/// 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); }