From fac8de1fde1dac1f78a7f2e22c536a9781f9a246 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Emmanuel=20Beno=C3=AEt?= <tseeker@nocternity.net>
Date: Fri, 8 Dec 2017 22:00:43 +0100
Subject: [PATCH] Optimizer - Mostly OK use/define chain construction

In which "mostly" means that it will work, unless:
1/ something is used before being defined (will trigger assertion)
2/ a local variable is re-used before being redefined, which will
be detected as using the def from the previous execution (won't be a
problem for now as it'll crash first, due to (1))
---
 c-opopt.cc | 41 ++++++++++++++++++++++++++++++++---------
 1 file changed, 32 insertions(+), 9 deletions(-)

diff --git a/c-opopt.cc b/c-opopt.cc
index a0dd4c4..49c706c 100644
--- a/c-opopt.cc
+++ b/c-opopt.cc
@@ -692,6 +692,7 @@ void T_OptData::buildUseDefineChains(
 					auto& resource{ varUDChains[ rec.entry ] };
 					const auto defId{ (*activeDefs)[ rec.entry ] };
 					// FIXME: must be defined
+					assert( defId != T_HashIndex::INVALID_INDEX );
 					resource.defines[ defId ].refs.add( rec.index );
 					resource.uses[ rec.index ].refs.add( defId );
 					logger( [&](){
@@ -712,7 +713,7 @@ void T_OptData::buildUseDefineChains(
 					(*activeDefs)[ rec.entry ] = rec.index;
 					logger( [&](){
 						T_StringBuilder sb;
-						sb << "DEF " << rec.index
+						sb << "DEF " << rec.index << ' '
 							<< varUDChains[ rec.entry ].var.name
 							<< " @ instr #" << ii;
 						return sb;
@@ -726,10 +727,6 @@ void T_OptData::buildUseDefineChains(
 		}
 
 		// Check for possible next nodes
-		//	-> no output nodes left -> pop stack and keep trying,
-		//		unless we've already processed all nodes
-		// 	-> if there's only one, use it and don't push to stack
-		// 	-> otherwise push to stack, use first available node
 		do {
 			auto const& rcn{ *ctrlFlowGraph[ node ] };
 			const uint32_t nSuccs{ [&](){
@@ -742,23 +739,49 @@ void T_OptData::buildUseDefineChains(
 				}
 				return c;
 			}() };
-			logger( [=]() {
+			logger( [&]() {
 				T_StringBuilder sb;
 				sb << "node " << node << ": " << nSuccs
-					<< " successor(s) left";
+					<< " successor(s) left (stack depth "
+					<< stack.size( ) << ')';
 				return sb;
 			} , LL2 );
 
+			// -> no output nodes left -> pop stack and keep trying,
+			//	unless we've already processed all nodes
 			if ( nSuccs == 0 ) {
 				assert( !stack.empty( ) );
 				node = stack.last( ).node;
 				activeDefs = std::move( stack.last( ).def );
 				stack.removeLast( );
+				logger( [&]() {
+					T_StringBuilder sb;
+					sb << "pop stack -> next node " << node
+						<< " (stack depth "
+						<< stack.size( ) << ')';
+					return sb;
+				} , LL2 );
 				continue;
 			}
 
-			// TODO cases in which there is one or more successors
-		} while ( 0 ); // XXX
+			const auto no{ rcn.outbound.size( ) };
+			uint32_t nn{ T_HashIndex::INVALID_INDEX };
+			for ( auto i = 0u ; i < no ; i ++ ) {
+				if ( !processedNodes[ rcn.outbound[ i ] ] ) {
+					nn = rcn.outbound[ i ];
+					break;
+				}
+			}
+
+			// More than one possible successor? Push to stack
+			if ( nSuccs > 1 ) {
+				M_LOGSTR_( "pushing node" , LL2 );
+				stack.addNew( activeDefs , node );
+			}
+
+			node = nn;
+			break;
+		} while ( 1 );
 
 		// 30 if next block is an end of function, kill locals
 	}