void ConditionalConstantPropagation::ExampleCode(raw_ostream& O, Function& F) {

	std::set<StringRef> var_set;
	var_set.clear();
	BasicBlock* bb_entry 	= NULL;
	BasicBlock* bb_if_then 	= NULL;
	BasicBlock* bb_if_else 	= NULL;
	BasicBlock* bb_if_end  	= NULL;


	// TA: The fol lowing code shows how you iterate over variables 
	// defined in this function
	O << "All Variables Defined in Function " << F.getName() <<   "\n";
	for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) {
		BasicBlock* BB = dyn_cast<BasicBlock>(&*FI);
		for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();
			BI != BE; ++BI) {
			Instruction *instr = dyn_cast<Instruction>(&*BI);
			LatticeMap[instr] = new Lattice();
			LatticeMap[instr]->TOP = true;
			LatticeMap[instr]->BOT = false;
			if ( BI->hasName() ) 
			{
				StringRef var_name = BI->getValueName()->first();
				O << "VARIABLE:\t" << var_name << "\tdefined in ";
				BI->print(O);
				O << "\n";
			}
		}
		if ( !bb_entry )
			bb_entry = BB;
		else if ( !bb_if_then )
			bb_if_then = BB;
		else if ( !bb_if_else )
			bb_if_else = BB;
		else if ( !bb_if_end )
			bb_if_end = BB;
	}

/*

//intialization
CFGWorklist.push(bb_entry);  //need to initialize bb_entry as the first node, caution: I do not know what entry node contains
for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) 
{
	BasicBlock* BB = dyn_cast<BasicBlock>(&*FI);
	ExecutableMap[BB->getName()] = 0;
	int count = 0;	
	for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) 
	{
	  count++;
	}
	ExecutableMax[BB->getName()] = count;	
}
//initialize the VALUE OBJECTS (THIS SHOULD ALREADY BE DONE ABOVE IN EXAMPLE CODE)



while (CFGWorklist.size()!=0 || SSAWorklist.size()!=0) 
{
	while(CFGWorklist.size()!=0)
	{
		BasicBlock* BB = CFGWorklist.front();
		CFGWorklist.pop();
		if((ExecutableMap[BB->getName()]==0) || (ExecutableMap[BB->getName()] < ExecutableMax[BB->getName()] ))
		{
			ExecutableMap[BB->getName()]+=1;
			//evaluate each phi-function in BB <----- can this be done in Evaluate()?
			for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();BI != BE; ++BI) 
			{
				//evaluate BI (and update lattice?) <------
	 			Instruction* definition = dyn_cast<Instruction> (&*BI);
				O<< "reached before evaluate" << *definition  << BB->getName()<<"\n";
				O << "\ninst lattice of:" << *definition << "\n \t\t--TOP ::" << LatticeMap[definition]->TOP <<" \t " << "BOT::"<< LatticeMap[definition]->BOT <<" \t " << "constant:: " << LatticeMap[definition]->constant <<" \n\n "  ;
				*LatticeMap[definition] = Evaluate(O,definition);

				O<< "reached after evaluate" << *definition  << BB->getName()<<"\n";
				O << "\ninst lattice of:" << *definition << "\n \t\t--TOP ::" << LatticeMap[definition]->TOP <<" \t " << "BOT::"<< LatticeMap[definition]->BOT <<" \t " << "constant:: " << LatticeMap[definition]->constant <<" \n\n "  ;					
				for (Instruction::use_iterator UI= definition->use_begin(), UE=definition->use_end(); UI!=UE; ++UI) 
				{
					Instruction* usage = dyn_cast<Instruction> (*UI);
					///NOTE, WE CANNOT DO &* HERE LIKE FOR 'definition' ABOVE.  DOES THIS CAUSE PROBLEMS??
					BasicBlock* parent = usage->getParent();
					if (ExecutableMap[parent->getName()] > 0)
					{
						SSAWorklist.push(usage);
					}
					//DEBUGGING CODE IS COMMENTED OUT BELOW:
			
					//if ( UI->hasName() ) 
					//{							
						//StringRef var_name = BI->getValueName()->first();
						//O << "USE :::" << UI->getValueName()->first()<<"  " << "VARIABLE:\t" << var_name<<"\tdefined in ";
						//UI->print(O);
						//O << "\n";
					//}
				}
			}				
		}
	}
	while(SSAWorklist.size()!=0) 
	{
		Instruction* instr = SSAWorklist.front();
		SSAWorklist.pop();
		O << "SSA before evaluate" << *instr << "\n";
		O << "\ninst lattice of:" << *instr << "\n \t\t--TOP ::" << LatticeMap[instr]->TOP <<" \t " << "BOT::"<< LatticeMap[instr]->BOT <<" \t " << "constant:: " << LatticeMap[instr]->constant <<" \n\n "  ;			
		Lattice t = Evaluate(O,instr);// ********** need to make evaluate function
		O << "SSA after evaluate" << *instr << "\n";
		O << "\ninst lattice of:" << *instr << "\n \t\t--TOP ::" << LatticeMap[instr]->TOP <<" \t " << "BOT::"<< LatticeMap[instr]->BOT <<" \t " << "constant:: " << LatticeMap[instr]->constant <<" \n\n "  ;					
		if (!LatEquals(t,*LatticeMap[instr])) //do get equals function
		{
			//O << "\ninst values change from:" << *instr << "\n \t\t--TOP ::" << LatticeMap[instr]->TOP <<" \t " << "BOT::"<< LatticeMap[instr]->BOT <<" \t " << "constant:: " << LatticeMap[instr]->constant <<" \n\n "  ;
			*LatticeMap[instr] = MeetFunc(*LatticeMap[instr],t);
			//O << "\ninst values change2:" << *instr << "\n \t\t--TOP ::" << LatticeMap[instr]->TOP <<" \t " << "BOT::"<< LatticeMap[instr]->BOT <<" \t " << "constant:: " << LatticeMap[instr]->constant <<" \n\n "  ; 
			for (Instruction::use_iterator UI= instr->use_begin(), UE=instr->use_end(); UI!=UE; ++UI) 
			{
				Instruction* usage = dyn_cast<Instruction> (*UI);
				BasicBlock* parent = usage->getParent();
				if (ExecutableMap[parent->getName()] > 0)
				{
					SSAWorklist.push(usage);
				}
			}
		}
	}
}		

for (std::map<Instruction*, Lattice*> ::iterator it = LatticeMap.begin(); it!= LatticeMap.end(); ++it) {
	O << "\ninst ::" << *(it->first) << "\n \t\t--TOP ::" << it->second->TOP <<" \t " << "BOT::"<<it->second->BOT <<" \t " << "constant:: " << it->second->constant <<" \n\n "  ;
}
/*
for (std::map<Instruction*, Lattice*> ::iterator it = LatticeMap.begin(); it!= LatticeMap.end(); ++it) {

	Instruction * instr = dyn_cast<Instruction> (&*(it->first));
	O << *instr << "\n";
	if ( !(LatticeMap[instr]->TOP || LatticeMap[instr]->BOT) )
	{
		BasicBlock::iterator ii(instr);
		if( ICmpInst * icmpinst = dyn_cast<ICmpInst>(&*instr) ) 
		{
			int64_t taken = LatticeMap[instr]->constant;
			Constant *x = ConstantInt::get(instr->getType(), 0x1);
			ConstantInt *ret1 = dyn_cast<ConstantInt>(&*x);
			x = ConstantInt::get(instr->getType(), 0x0);
			ConstantInt *ret0 =dyn_cast<ConstantInt>(&*x);
			if(taken == 0)
			{
				llvm::ReplaceInstWithValue(instr->getParent()->getInstList(),ii,ret0);			
			}
			else
			{
				llvm::ReplaceInstWithValue(instr->getParent()->getInstList(),ii,ret1);
			}
		}
		else if( isa<PHINode>(instr) )
		{
			int64_t lat_constant = LatticeMap[instr]->constant;
			// convert lat_constant to ConstantInt
			Constant * newConst = ConstantInt::getSigned(instr->getType(),lat_constant);
			if (ConstantInt * ptr = dyn_cast<ConstantInt>(newConst)) 
			{
				ReplaceInstWithValue(instr->getParent()->getInstList(), ii, ptr);
			}
		}
		else if ( BranchInst *BI = dyn_cast<BranchInst>(instr))
		{
			int64_t taken = LatticeMap[instr]->constant;
			if(taken == 0)
			{
				O << *instr << " replacing with false value\n";
				//BranchInst * new_branch = BranchInst::Create(BI->getSuccessor(0),BI->getSuccessor(1),cast<Value>(&*ConstantInt::getFalse(BI->getContext())));
				BranchInst * new_branch = BranchInst::Create(BI->getSuccessor(1));
				O << *new_branch << " <- false value\n";
				ReplaceInstWithInst(BI->getParent()->getInstList(), ii, cast<Instruction>(&*new_branch));
			}
			else
			{
				O << *instr << " replacing with true value\n";
				BranchInst * new_branch = BranchInst::Create(BI->getSuccessor(0));
				O << *new_branch << " <- true value\n";
				ReplaceInstWithInst(BI->getParent()->getInstList(), ii, cast<Instruction>(&*new_branch));
			}			
		}
		else if ( instr->getOpcode() == Instruction::Sub || instr->getOpcode() == Instruction::Add)  
		{
			int64_t lat_constant = LatticeMap[instr]->constant;
			// convert lat_constant to ConstantInt
			Constant * newConst = ConstantInt::getSigned(instr->getType(),lat_constant);
			if (ConstantInt * ptr = dyn_cast<ConstantInt>(newConst)) 
			{
				ReplaceInstWithValue(instr->getParent()->getInstList(), ii, ptr);
			}
		}
	}
}


/*my propagation code:
for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) 
{
	BasicBlock* BB = dyn_cast<BasicBlock>(&*FI);
	for (BasicBlock::iterator BI = BB->begin(), BE = BB->end(); BI != BE; ++BI) 
	{
		
	}
}*/
/*
after running the above code 
for(each value in "Value" map)
{
	if( value is not TOP or BOT)
	{
		set original instruction RHS equal to value
	}
}



run simplify cfg to eliminate deadcode (values with TOP)
*/
/*
	//TA: The following code examines the last instruction of 
	// each basic block, and print if the last instruction is 
	// condtional or unconditional branch
	for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) {
		BasicBlock* BB = dyn_cast<BasicBlock>(&*FI);
		O << "----------------------------------------------------\n";
		O << "BB: " << BB ->getName() << '\n';
		TerminatorInst *TI = BB->getTerminator();
		O << "\tTerminatorInst: " << *TI << '\n';
		if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
			if (BI->isUnconditional())
				O << "\tInstruction is uncondtional\n";
			else  {
				O << "\tInstruction is conditional\n";
				Value * condition = BI->getCondition();
				O << "\t\tcondtion is " << *condition << "\n";
			}
		}
	}
	
	// TA: the following code shows how to perform the symbolic execution 
	for (Function::iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) 
	{
		BasicBlock* BB = dyn_cast<BasicBlock>(&*FI);
		for (BasicBlock::iterator BI = BB->begin(), BE = BB->end();
			BI != BE; ++BI) {
			if ( BI->getOpcode() == Instruction::Sub)  
			{
				O << "Sub Instr: " << *BI << "\n";
				unsigned operand_size = BI->getNumOperands();
				assert ( operand_size == 2 );
				if ( dyn_cast<ConstantInt>(&*BI->getOperand(0)) && dyn_cast<ConstantInt>(&*BI->getOperand(1)) ) 
				{
					Constant * expr_result = ConstantExpr::getSub(dyn_cast<Constant>(&*BI->getOperand(0)), dyn_cast<Constant>(&*BI->getOperand(1)) );
					if ( ConstantInt * int_result = dyn_cast<ConstantInt>(&*expr_result) ) {
						O << "Both operands are constant, result is: " << int_result->getValue() << "\n"; 
						// replace instruction using 
						// ReplaceInstWithValue
						//BasicBlock::iterator ii(instToReplace);
						ReplaceInstWithValue(BI->getParent()->getInstList(), BI, int_result );
					}
				}
			}
		}
	}

	// TA: the following code shows how to change the IF condition
	// when it always executes false path
	TerminatorInst *TI; 
	TI = bb_entry->getTerminator();
	O << "TerminatorInst in Entry Block: " << *TI;
	if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
		if (BI->isUnconditional())
			O << " (Uncondtional)\n";
		else if (BI->isConditional())
			O << " (Condtional)\n";
	}
	BasicBlock::iterator BI = bb_entry->begin();
	if ( ICmpInst * icmpinst = dyn_cast<ICmpInst>(&*BI) ) {
		O << " ICmpInst " << *icmpinst << "\n";
		if ( icmpinst->isSigned() ) {
			if (icmpinst->getSignedPredicate () == CmpInst::ICMP_SGT ) {
				O << icmpinst->getSignedPredicate ()  << ": int signed greater than\n";
				Value * left_hand_side  = icmpinst->getOperand(0);
				Value * right_hand_side = icmpinst->getOperand(1);
				if ( dyn_cast<ConstantInt> (&*left_hand_side) && dyn_cast<ConstantInt>(&*right_hand_side)) {
					ConstantInt * left_const  = dyn_cast<ConstantInt> (&*left_hand_side);
					ConstantInt * right_const = dyn_cast<ConstantInt> (&*right_hand_side);   
					O << "LHS is constant: " << *left_const << ", value: " << left_const->getValue() << "\n";
					O << "RHS is constant: " << *right_const<< ", value: " << right_const->getValue() << "\n";
					int64_t left_value = left_const->getValue().getSExtValue();
					int64_t right_value = right_const->getValue().getSExtValue();
					if ( left_value > right_value ) {
						O << "this if statement will always be true\n";
					} else {
						O << "this if statement will always be false\n";
						// if this is the case, we need to replace the terminator instruction (condtional branch ) with new one
						BasicBlock::iterator ii(TI);
						BranchInst * new_branch = BranchInst::Create(TI->getSuccessor(0),TI->getSuccessor(1),cast<Value>(&*ConstantInt::getFalse(TI->getContext())));
						//TI->getParent());
						ReplaceInstWithInst(TI->getParent()->getInstList(), ii, cast<Instruction>(&*new_branch));
					}
				}
			}
		}
	}*/
}