OSDN Git Service

Don't eliminate wide store followed by a narrow one.
authorNicolas Capens <capn@google.com>
Tue, 25 Jul 2017 16:57:12 +0000 (12:57 -0400)
committerNicolas Capens <nicolascapens@google.com>
Wed, 26 Jul 2017 19:27:28 +0000 (19:27 +0000)
If the previous store operation is wider than the next one, we can't
eliminate it because there could be a subsequent wide load reading its
non-overwritten data.

Bug swiftshader:48

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

index 4fd5d2f..fc69906 100644 (file)
@@ -45,6 +45,7 @@ namespace
                static Ice::Operand *storeAddress(const Ice::Inst *instruction);
                static Ice::Operand *loadAddress(const Ice::Inst *instruction);
                static Ice::Operand *storeData(const Ice::Inst *instruction);
+               static std::size_t storeSize(const Ice::Inst *instruction);
 
                Ice::Cfg *function;
                Ice::GlobalContext *context;
@@ -312,10 +313,15 @@ namespace
                                                        continue;
                                                }
 
-                                               // New store found. If we had a previous one, eliminate it.
+                                               // New store found. If we had a previous one, try to eliminate it.
                                                if(store)
                                                {
-                                                       deleteInstruction(store);
+                                                       // If the previous store is wider than the new one, we can't eliminate it
+                                                       // because there could be a wide load reading its non-overwritten data.
+                                                       if(storeSize(&inst) >= storeSize(store))
+                                                       {
+                                                               deleteInstruction(store);
+                                                       }
                                                }
 
                                                store = &inst;
@@ -563,6 +569,23 @@ namespace
                return nullptr;
        }
 
+       std::size_t Optimizer::storeSize(const Ice::Inst *store)
+       {
+               assert(isStore(*store));
+
+               if(auto *instStore = llvm::dyn_cast<Ice::InstStore>(store))
+               {
+                       return Ice::typeWidthInBytes(instStore->getData()->getType());
+               }
+
+               if(auto *storeSubVector = asStoreSubVector(store))
+               {
+                       return llvm::cast<Ice::ConstantInteger32>(storeSubVector->getSrc(3))->getValue();
+               }
+
+               return 0;
+       }
+
        bool Optimizer::Uses::areOnlyLoadStore() const
        {
                return size() == (loads.size() + stores.size());