OSDN Git Service

Optimize stores in a single basic block.
authorNicolas Capens <capn@google.com>
Wed, 30 Nov 2016 21:15:28 +0000 (16:15 -0500)
committerNicolas Capens <capn@google.com>
Tue, 13 Dec 2016 16:43:13 +0000 (16:43 +0000)
Bug swiftshader:27

Change-Id: Ia5f7da431902c3e87aab47b1dd388e05ced74cd3
Reviewed-on: https://swiftshader-review.googlesource.com/8274
Tested-by: Nicolas Capens <capn@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
src/Reactor/Optimizer.cpp

index a3b328e..39de5f0 100644 (file)
@@ -32,6 +32,7 @@ namespace
                void eliminateUnusedAllocas();
                void eliminateUnitializedLoads();
                void eliminateLoadsFollowingSingleStore();
+               void optimizeStoresInSingleBasicBlock();
 
                void replace(Ice::Inst *instruction, Ice::Operand *newValue);
                void deleteInstruction(Ice::Inst *instruction);
@@ -70,6 +71,7 @@ namespace
                eliminateUnusedAllocas();
                eliminateUnitializedLoads();
                eliminateLoadsFollowingSingleStore();
+               optimizeStoresInSingleBasicBlock();
        }
 
        void Optimizer::eliminateUnusedAllocas()
@@ -243,6 +245,88 @@ namespace
                }
        }
 
+       void Optimizer::optimizeStoresInSingleBasicBlock()
+       {
+               Ice::CfgNode *entryBlock = function->getEntryNode();
+
+               for(Ice::Inst &alloca : entryBlock->getInsts())
+               {
+                       if(alloca.isDeleted())
+                       {
+                               continue;
+                       }
+
+                       if(!llvm::isa<Ice::InstAlloca>(alloca))
+                       {
+                               return;   // Allocas are all at the top
+                       }
+
+                       Ice::Operand *address = alloca.getDest();
+                       const auto &addressEntry = uses.find(address);
+                       const auto &addressUses = addressEntry->second;
+
+                       if(!addressUses.areOnlyLoadStore())
+                       {
+                               continue;
+                       }
+
+                       Ice::CfgNode *singleBasicBlock = node[addressUses.stores[0]];
+
+                       for(int i = 1; i < addressUses.stores.size(); i++)
+                       {
+                               Ice::Inst *store = addressUses.stores[i];
+                               if(node[store] != singleBasicBlock)
+                               {
+                                       singleBasicBlock = nullptr;
+                                       break;
+                               }
+                       }
+
+                       if(singleBasicBlock)
+                       {
+                               auto &insts = singleBasicBlock->getInsts();
+                               Ice::Inst *store = nullptr;
+                               Ice::Operand *storeValue = nullptr;
+
+                               for(Ice::Inst &inst : insts)
+                               {
+                                       if(inst.isDeleted())
+                                       {
+                                               continue;
+                                       }
+
+                                       if(isStore(inst))
+                                       {
+                                               if(storeAddress(&inst) != address)
+                                               {
+                                                       continue;
+                                               }
+
+                                               // New store found. If we had a previous one, eliminate it.
+                                               if(store)
+                                               {
+                                                       deleteInstruction(store);
+                                               }
+
+                                               store = &inst;
+                                               storeValue = storeData(store);
+                                       }
+                                       else if(isLoad(inst))
+                                       {
+                                               Ice::Inst *load = &inst;
+
+                                               if(loadAddress(load) != address)
+                                               {
+                                                       continue;
+                                               }
+
+                                               replace(load, storeValue);
+                                       }
+                               }
+                       }
+               }
+       }
+
        void Optimizer::analyzeUses(Ice::Cfg *function)
        {
                uses.clear();