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