bool TestDataflowGraph::_verifyIdentities( analysis::DataflowGraph& graph )
	{
		analysis::DataflowGraph::Block::RegisterSet global;
		analysis::InstructionConverter converter;

		analysis::DataflowGraph::iterator block1 = graph.begin();
		for( ; block1 != graph.end(); ++block1 ) {
			analysis::DataflowGraph::iterator block2 = graph.begin();
			for( ; block2 != graph.end(); ++block2 ) {

				if (block1 != block2) {
					analysis::DataflowGraph::InstructionVector::const_iterator inst1 = block1->instructions().begin();
					analysis::DataflowGraph::InstructionVector::const_iterator inst2 = block2->instructions().begin();

					while((inst1 != block1->instructions().end()) && (inst2 != block2->instructions().end())) {
						ir::PTXInstruction* ptxInst1 = static_cast< ir::PTXInstruction* >(inst1->i);
						ir::PTXInstruction* ptxInst2 = static_cast< ir::PTXInstruction* >(inst2->i);

						std::cout << ptxInst1->toString() << ": "
								<< hydrazine::toFormattedString( inst1->d.begin(), inst1->d.end(), Double() )
								<< " <- "
								<< hydrazine::toFormattedString( inst1->s.begin(), inst1->s.end(), Double() )
								<< "	|	";

						std::cout << ptxInst2->toString() << ": "
								<< hydrazine::toFormattedString( inst2->d.begin(), inst2->d.end(), Double() )
								<< " <- "
								<< hydrazine::toFormattedString( inst2->s.begin(), inst2->s.end(), Double() )
								<< std::endl;

						// try to match inst1 and inst2
						analysis::DataflowGraph::Instruction matchedInst1;
						analysis::DataflowGraph::Instruction matchedInst2;
						bool matched = converter.normalize(matchedInst1, matchedInst2, *inst1, *inst2);

						if (matched) {
							ir::PTXInstruction* matchedPtx1 = static_cast< ir::PTXInstruction* >(matchedInst1.i);
							ir::PTXInstruction* matchedPtx2 = static_cast< ir::PTXInstruction* >(matchedInst2.i);

							std::cout << "matched:" << std::endl;
							std::cout << matchedPtx1->toString() << ": "
									<< hydrazine::toFormattedString( matchedInst1.d.begin(), matchedInst1.d.end(), Double() )
									<< " <- "
									<< hydrazine::toFormattedString( matchedInst1.s.begin(), matchedInst1.s.end(), Double() )
									<< "	|	";

							std::cout << matchedPtx2->toString() << ": "
									<< hydrazine::toFormattedString( matchedInst2.d.begin(), matchedInst2.d.end(), Double() )
									<< " <- "
									<< hydrazine::toFormattedString( matchedInst2.s.begin(), matchedInst2.s.end(), Double() )
									<< std::endl;
						}

						std::cout << "-----------" << std::endl;

						++inst1;
						++inst2;
					} // while
				} // if

			} // for
		} // for

		return true;
	}
	bool TestDataflowGraph::_verify( const analysis::DataflowGraph& graph )
	{
		for( analysis::DataflowGraph::const_iterator block = graph.begin(); 
			block != graph.end(); ++block )
		{
			analysis::DataflowGraph::Block::RegisterSet defined;
			
			report( " Alive in registers:" );
			for( analysis::DataflowGraph::Block::RegisterSet::const_iterator 
				reg = block->aliveIn().begin(); 
				reg != block->aliveIn().end(); ++reg )
			{
				report( "  " << reg->id );
				defined.insert( *reg );
			}
				
			if( !block->phis().empty() )
			{
				status << "  Block " << block->label() 
					<< " has " << block->phis().size() 
					<< " phi instructions." << std::endl;
				return false;			
			}
			
			for( analysis::DataflowGraph::InstructionVector::const_iterator 
				instruction = block->instructions().begin(); 
				instruction != block->instructions().end(); ++instruction )
			{
				report( " " << instruction->label << ":  " 
					<< hydrazine::toFormattedString( instruction->d.begin(), 
					instruction->d.end(), Double() ) << " <- " 
					<< hydrazine::toFormattedString( instruction->s.begin(), 
					instruction->s.end(), Double() ) );
					
				analysis::DataflowGraph::RegisterPointerVector::const_iterator
					reg = instruction->s.begin();
				for( ; reg != instruction->s.end(); ++reg )
				{
					if( !defined.count( *reg ) )
					{
						status << "  Register " << *reg->pointer 
							<< " in instruction " << instruction->label 
							<< " in block " << block->label() 
							<< " used uninitialized." << std::endl;
						return false;
					}
				}
				
				reg = instruction->d.begin();
					
				for( ; reg != instruction->d.end(); ++reg )
				{
					defined.insert( *reg );
				}
			}
			
			for( analysis::DataflowGraph::Block::RegisterSet::const_iterator 
				reg = block->aliveOut().begin(); 
				reg != block->aliveOut().end(); ++reg )
			{
				if( !defined.count( *reg ) )
				{
					status << "  Register " << reg->id 
						<< " out set of block " << block->label() 
						<< " used uninitialized." << std::endl;
					return false;
				}
			}			
		}
		return true;
	}
	bool TestDataflowGraph::_verifySsa( const analysis::DataflowGraph& graph )
	{
		analysis::DataflowGraph::Block::RegisterSet global;
		for( analysis::DataflowGraph::const_iterator block = graph.begin(); 
			block != graph.end(); ++block )
		{
			analysis::DataflowGraph::Block::RegisterSet defined;
			
			report( block->label() );
			report( " Alive in registers:" );
			for( analysis::DataflowGraph::Block::RegisterSet::const_iterator 
				reg = block->aliveIn().begin(); 
				reg != block->aliveIn().end(); ++reg )
			{
				report( "  " << reg->id );
				defined.insert( *reg );
			}
			
			for( analysis::DataflowGraph::PhiInstructionVector::const_iterator 
				phi = block->phis().begin(); 
				phi != block->phis().end(); ++phi )
			{
				report( " phi " << phi->d.id << " <- " 
					<< hydrazine::toFormattedString( phi->s.begin(), 
						phi->s.end(), ToId() ) );
				for( analysis::DataflowGraph::RegisterVector::const_iterator
					reg = phi->s.begin(); reg != phi->s.end(); ++reg )
				{
					if( !defined.count( *reg ) )
					{
						status << "  Register " << reg->id
							<< " in phi instruction " 
							<< std::distance( block->phis().begin(), phi )
							<< " in " << block->label() 
							<< " used uninitialized." << std::endl;
						return false;
					}
				}
				defined.insert( phi->d );
				if( !global.insert( phi->d ).second )
				{
					status << "  In " << block->label() 
						<< ", instruction phi " 
						<< std::distance( block->phis().begin(), phi )
						<< ", reg " << phi->d.id
						<< " already defined globally." << std::endl;
					return false;
				}
			}
			
			for( analysis::DataflowGraph::InstructionVector::const_iterator 
				instruction = block->instructions().begin(); 
				instruction != block->instructions().end(); ++instruction )
			{
				report( " " << instruction->label << ":  " 
					<< hydrazine::toFormattedString( instruction->d.begin(), 
					instruction->d.end(), Double() ) << " <- " 
					<< hydrazine::toFormattedString( instruction->s.begin(), 
					instruction->s.end(), Double() ) );
					
				analysis::DataflowGraph::RegisterPointerVector::const_iterator
					reg = instruction->s.begin();
				for( ; reg != instruction->s.end(); ++reg )
				{
					if( !defined.count( *reg ) )
					{
						status << "  Register " << *reg->pointer 
							<< " in instruction " << instruction->label 
							<< " in " << block->label() 
							<< " used uninitialized." << std::endl;
						return false;
					}
				}
				
				for( reg = instruction->d.begin(); 
					reg != instruction->d.end(); ++reg )
				{
					defined.insert( *reg );
					if( !global.insert( *reg ).second )
					{
						status << "  In " << block->label() 
							<< ", instruction " 
							<< instruction->label << ", reg " << *reg->pointer
							<< " already defined globally." << std::endl;
						return false;
					}
				}
			}
			
			for( analysis::DataflowGraph::Block::RegisterSet::const_iterator 
				reg = block->aliveOut().begin(); 
				reg != block->aliveOut().end(); ++reg )
			{
				if( !defined.count( *reg ) )
				{
					status << "  Register " << reg->id 
						<< " out set of block " << block->label() 
						<< " used uninitialized." << std::endl;
					return false;
				}
			}			
		}
		return true;
	}