Commit f4452fc4 by Nicolas Capens

Eliminate loading of uninitialized variables.

Bug swiftshader:27 Change-Id: I58259e00204550a397522fc26578c9f4d847f502 Reviewed-on: https://swiftshader-review.googlesource.com/8272Tested-by: 's avatarNicolas Capens <capn@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent 2ae9d748
......@@ -73,6 +73,43 @@ TEST(SubzeroReactorTest, Sample)
delete routine;
}
TEST(SubzeroReactorTest, Uninitialized)
{
Routine *routine = nullptr;
{
Function<Int()> function;
{
Int a;
Int z = 4;
Int q;
Int c;
Int p;
Bool b;
q += q;
If(b)
{
c = p;
}
Return(a + z + q + c);
}
routine = function(L"one");
if(routine)
{
int (*callable)() = (int(*)())routine->getEntry();
int result = callable();
EXPECT_EQ(result, result); // Anything is fine, just don't crash
}
}
delete routine;
}
TEST(SubzeroReactorTest, SubVectorLoadStore)
{
Routine *routine = nullptr;
......
......@@ -30,19 +30,38 @@ namespace
private:
void analyzeUses(Ice::Cfg *function);
void eliminateUnusedAllocas();
void eliminateUnitializedLoads();
static bool isLoad(const Ice::Inst &instruction);
static bool isStore(const Ice::Inst &instruction);
static Ice::Operand *storeAddress(const Ice::Inst *instruction);
static Ice::Operand *loadAddress(const Ice::Inst *instruction);
Ice::Cfg *function;
Ice::GlobalContext *context;
struct Uses : std::vector<Ice::Inst*>
{
bool areOnlyLoadStore() const;
void insert(Ice::Operand *value, Ice::Inst *instruction);
void erase(Ice::Inst *instruction);
std::vector<Ice::Inst*> loads;
std::vector<Ice::Inst*> stores;
};
std::map<Ice::Operand*, std::vector<Ice::Inst*>> uses;
std::map<Ice::Operand*, Uses> uses;
};
void Optimizer::run(Ice::Cfg *function)
{
this->function = function;
this->context = function->getContext();
analyzeUses(function);
eliminateUnusedAllocas();
eliminateUnitializedLoads();
}
void Optimizer::eliminateUnusedAllocas()
......@@ -65,6 +84,61 @@ namespace
}
}
void Optimizer::eliminateUnitializedLoads()
{
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;
}
if(addressUses.stores.empty())
{
for(Ice::Inst *load : addressUses.loads)
{
Ice::Variable *loadData = load->getDest();
for(Ice::Inst *use : uses[loadData])
{
for(int i = 0; i < use->getSrcSize(); i++)
{
if(use->getSrc(i) == loadData)
{
auto *undef = context->getConstantUndef(loadData->getType());
use->replaceSource(i, undef);
}
}
}
uses.erase(loadData);
load->setDeleted();
}
alloca.setDeleted();
uses.erase(addressEntry);
}
}
}
void Optimizer::analyzeUses(Ice::Cfg *function)
{
uses.clear();
......@@ -91,12 +165,144 @@ namespace
if(i == unique)
{
uses[instruction.getSrc(i)].push_back(&instruction);
Ice::Operand *src = instruction.getSrc(i);
uses[src].insert(src, &instruction);
}
}
}
}
}
bool Optimizer::isLoad(const Ice::Inst &instruction)
{
if(llvm::isa<Ice::InstLoad>(&instruction))
{
return true;
}
if(auto intrinsicCall = llvm::dyn_cast<Ice::InstIntrinsicCall>(&instruction))
{
return intrinsicCall->getIntrinsicInfo().ID == Ice::Intrinsics::LoadSubVector;
}
return false;
}
bool Optimizer::isStore(const Ice::Inst &instruction)
{
if(llvm::isa<Ice::InstStore>(&instruction))
{
return true;
}
if(auto intrinsicCall = llvm::dyn_cast<Ice::InstIntrinsicCall>(&instruction))
{
return intrinsicCall->getIntrinsicInfo().ID == Ice::Intrinsics::StoreSubVector;
}
return false;
}
Ice::Operand *Optimizer::storeAddress(const Ice::Inst *instruction)
{
assert(isStore(*instruction));
if(auto *store = llvm::dyn_cast<Ice::InstStore>(instruction))
{
return store->getAddr();
}
if(auto *instrinsic = llvm::dyn_cast<Ice::InstIntrinsicCall>(instruction))
{
if(instrinsic->getIntrinsicInfo().ID == Ice::Intrinsics::StoreSubVector)
{
return instrinsic->getSrc(2);
}
}
return nullptr;
}
Ice::Operand *Optimizer::loadAddress(const Ice::Inst *instruction)
{
assert(isLoad(*instruction));
if(auto *load = llvm::dyn_cast<Ice::InstLoad>(instruction))
{
return load->getSourceAddress();
}
if(auto *instrinsic = llvm::dyn_cast<Ice::InstIntrinsicCall>(instruction))
{
if(instrinsic->getIntrinsicInfo().ID == Ice::Intrinsics::LoadSubVector)
{
return instrinsic->getSrc(1);
}
}
return nullptr;
}
bool Optimizer::Uses::areOnlyLoadStore() const
{
return size() == (loads.size() + stores.size());
}
void Optimizer::Uses::insert(Ice::Operand *value, Ice::Inst *instruction)
{
push_back(instruction);
if(isLoad(*instruction))
{
if(value == loadAddress(instruction))
{
loads.push_back(instruction);
}
}
else if(isStore(*instruction))
{
if(value == storeAddress(instruction))
{
stores.push_back(instruction);
}
}
}
void Optimizer::Uses::erase(Ice::Inst *instruction)
{
auto &uses = *this;
for(int i = 0; i < uses.size(); i++)
{
if(uses[i] == instruction)
{
uses[i] = back();
pop_back();
for(int i = 0; i < loads.size(); i++)
{
if(loads[i] == instruction)
{
loads[i] = loads.back();
loads.pop_back();
break;
}
}
for(int i = 0; i < stores.size(); i++)
{
if(stores[i] == instruction)
{
stores[i] = stores.back();
stores.pop_back();
break;
}
}
break;
}
}
}
}
namespace sw
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment