Eliminate dead code.

Bug swiftshader:23

Change-Id: Ifb2862e8358141f67a7974d3fa0a11e6fe41b904
Reviewed-on: https://swiftshader-review.googlesource.com/8290
Tested-by: Nicolas Capens <capn@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/Reactor/Optimizer.cpp b/src/Reactor/Optimizer.cpp
index 39de5f0..ffd29bb 100644
--- a/src/Reactor/Optimizer.cpp
+++ b/src/Reactor/Optimizer.cpp
@@ -29,13 +29,14 @@
 
 	private:
 		void analyzeUses(Ice::Cfg *function);
-		void eliminateUnusedAllocas();
+		void eliminateDeadCode();
 		void eliminateUnitializedLoads();
 		void eliminateLoadsFollowingSingleStore();
 		void optimizeStoresInSingleBasicBlock();
 
 		void replace(Ice::Inst *instruction, Ice::Operand *newValue);
 		void deleteInstruction(Ice::Inst *instruction);
+		bool isDead(Ice::Inst *instruction);
 
 		static bool isLoad(const Ice::Inst &instruction);
 		static bool isStore(const Ice::Inst &instruction);
@@ -68,30 +69,37 @@
 
 		analyzeUses(function);
 
-		eliminateUnusedAllocas();
+		eliminateDeadCode();
 		eliminateUnitializedLoads();
 		eliminateLoadsFollowingSingleStore();
 		optimizeStoresInSingleBasicBlock();
+		eliminateDeadCode();
 	}
 
-	void Optimizer::eliminateUnusedAllocas()
+	void Optimizer::eliminateDeadCode()
 	{
-		Ice::CfgNode *entryBlock = function->getEntryNode();
-
-		for(Ice::Inst &alloca : entryBlock->getInsts())
+		bool modified;
+		do
 		{
-			if(!llvm::isa<Ice::InstAlloca>(alloca))
+			modified = false;
+			for(Ice::CfgNode *basicBlock : function->getNodes())
 			{
-				return;   // Allocas are all at the top
-			}
+				for(Ice::Inst &inst : Ice::reverse_range(basicBlock->getInsts()))
+				{
+					if(inst.isDeleted())
+					{
+						continue;
+					}
 
-			Ice::Operand *address = alloca.getDest();
-
-			if(uses[address].empty())
-			{
-				alloca.setDeleted();
+					if(isDead(&inst))
+					{
+						deleteInstruction(&inst);
+						modified = true;
+					}
+				}
 			}
 		}
+		while(modified);
 	}
 
 	void Optimizer::eliminateUnitializedLoads()
@@ -397,7 +405,7 @@
 
 	void Optimizer::deleteInstruction(Ice::Inst *instruction)
 	{
-		if(instruction->isDeleted())
+		if(!instruction || instruction->isDeleted())
 		{
 			return;
 		}
@@ -429,6 +437,30 @@
 		}
 	}
 
+	bool Optimizer::isDead(Ice::Inst *instruction)
+	{
+		Ice::Variable *dest = instruction->getDest();
+
+		if(dest)
+		{
+			return uses[dest].empty() && !instruction->hasSideEffects();
+		}
+		else if(isStore(*instruction))
+		{
+			if(Ice::Variable *address = llvm::dyn_cast<Ice::Variable>(storeAddress(instruction)))
+			{
+				Ice::Inst *def = definition[address];
+
+				if(!def || llvm::isa<Ice::InstAlloca>(def))
+				{
+					return uses[address].size() == 1;   // Dead if this store is the only use
+				}
+			}
+		}
+
+		return false;
+	}
+
 	bool Optimizer::isLoad(const Ice::Inst &instruction)
 	{
 		if(llvm::isa<Ice::InstLoad>(&instruction))