xref: /aosp_15_r20/external/swiftshader/src/Reactor/Optimizer.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*03ce13f7SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*03ce13f7SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*03ce13f7SAndroid Build Coastguard Worker //
7*03ce13f7SAndroid Build Coastguard Worker //    http://www.apache.org/licenses/LICENSE-2.0
8*03ce13f7SAndroid Build Coastguard Worker //
9*03ce13f7SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*03ce13f7SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*03ce13f7SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*03ce13f7SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*03ce13f7SAndroid Build Coastguard Worker // limitations under the License.
14*03ce13f7SAndroid Build Coastguard Worker 
15*03ce13f7SAndroid Build Coastguard Worker #include "Optimizer.hpp"
16*03ce13f7SAndroid Build Coastguard Worker 
17*03ce13f7SAndroid Build Coastguard Worker #include "src/IceCfg.h"
18*03ce13f7SAndroid Build Coastguard Worker #include "src/IceCfgNode.h"
19*03ce13f7SAndroid Build Coastguard Worker 
20*03ce13f7SAndroid Build Coastguard Worker #include <unordered_map>
21*03ce13f7SAndroid Build Coastguard Worker #include <vector>
22*03ce13f7SAndroid Build Coastguard Worker 
23*03ce13f7SAndroid Build Coastguard Worker namespace {
24*03ce13f7SAndroid Build Coastguard Worker 
25*03ce13f7SAndroid Build Coastguard Worker class Optimizer
26*03ce13f7SAndroid Build Coastguard Worker {
27*03ce13f7SAndroid Build Coastguard Worker public:
Optimizer(rr::Nucleus::OptimizerReport * report)28*03ce13f7SAndroid Build Coastguard Worker 	Optimizer(rr::Nucleus::OptimizerReport *report)
29*03ce13f7SAndroid Build Coastguard Worker 	    : report(report)
30*03ce13f7SAndroid Build Coastguard Worker 	{
31*03ce13f7SAndroid Build Coastguard Worker 	}
32*03ce13f7SAndroid Build Coastguard Worker 
33*03ce13f7SAndroid Build Coastguard Worker 	void run(Ice::Cfg *function);
34*03ce13f7SAndroid Build Coastguard Worker 
35*03ce13f7SAndroid Build Coastguard Worker private:
36*03ce13f7SAndroid Build Coastguard Worker 	void analyzeUses(Ice::Cfg *function);
37*03ce13f7SAndroid Build Coastguard Worker 
38*03ce13f7SAndroid Build Coastguard Worker 	void eliminateDeadCode();
39*03ce13f7SAndroid Build Coastguard Worker 	void eliminateUnitializedLoads();
40*03ce13f7SAndroid Build Coastguard Worker 	void propagateAlloca();
41*03ce13f7SAndroid Build Coastguard Worker 	void performScalarReplacementOfAggregates();
42*03ce13f7SAndroid Build Coastguard Worker 	void optimizeSingleBasicBlockLoadsStores();
43*03ce13f7SAndroid Build Coastguard Worker 
44*03ce13f7SAndroid Build Coastguard Worker 	void replace(Ice::Inst *instruction, Ice::Operand *newValue);
45*03ce13f7SAndroid Build Coastguard Worker 	void deleteInstruction(Ice::Inst *instruction);
46*03ce13f7SAndroid Build Coastguard Worker 	bool isDead(Ice::Inst *instruction);
47*03ce13f7SAndroid Build Coastguard Worker 	bool isStaticallyIndexedArray(Ice::Operand *allocaAddress);
48*03ce13f7SAndroid Build Coastguard Worker 	Ice::InstAlloca *allocaOf(Ice::Operand *address);
49*03ce13f7SAndroid Build Coastguard Worker 
50*03ce13f7SAndroid Build Coastguard Worker 	static const Ice::InstIntrinsic *asLoadSubVector(const Ice::Inst *instruction);
51*03ce13f7SAndroid Build Coastguard Worker 	static const Ice::InstIntrinsic *asStoreSubVector(const Ice::Inst *instruction);
52*03ce13f7SAndroid Build Coastguard Worker 	static bool isLoad(const Ice::Inst &instruction);
53*03ce13f7SAndroid Build Coastguard Worker 	static bool isStore(const Ice::Inst &instruction);
54*03ce13f7SAndroid Build Coastguard Worker 	static bool loadTypeMatchesStore(const Ice::Inst *load, const Ice::Inst *store);
55*03ce13f7SAndroid Build Coastguard Worker 	static bool storeTypeMatchesStore(const Ice::Inst *store1, const Ice::Inst *store2);
56*03ce13f7SAndroid Build Coastguard Worker 
57*03ce13f7SAndroid Build Coastguard Worker 	void collectDiagnostics();
58*03ce13f7SAndroid Build Coastguard Worker 
59*03ce13f7SAndroid Build Coastguard Worker 	Ice::Cfg *function;
60*03ce13f7SAndroid Build Coastguard Worker 	Ice::GlobalContext *context;
61*03ce13f7SAndroid Build Coastguard Worker 
62*03ce13f7SAndroid Build Coastguard Worker 	struct Uses : std::vector<Ice::Inst *>
63*03ce13f7SAndroid Build Coastguard Worker 	{
64*03ce13f7SAndroid Build Coastguard Worker 		bool areOnlyLoadStore() const;
65*03ce13f7SAndroid Build Coastguard Worker 		void insert(Ice::Operand *value, Ice::Inst *instruction);
66*03ce13f7SAndroid Build Coastguard Worker 		void erase(Ice::Inst *instruction);
67*03ce13f7SAndroid Build Coastguard Worker 
68*03ce13f7SAndroid Build Coastguard Worker 		std::vector<Ice::Inst *> loads;
69*03ce13f7SAndroid Build Coastguard Worker 		std::vector<Ice::Inst *> stores;
70*03ce13f7SAndroid Build Coastguard Worker 	};
71*03ce13f7SAndroid Build Coastguard Worker 
72*03ce13f7SAndroid Build Coastguard Worker 	struct LoadStoreInst
73*03ce13f7SAndroid Build Coastguard Worker 	{
LoadStoreInst__anonb40bc2440111::Optimizer::LoadStoreInst74*03ce13f7SAndroid Build Coastguard Worker 		LoadStoreInst(Ice::Inst *inst, bool isStore)
75*03ce13f7SAndroid Build Coastguard Worker 		    : inst(inst)
76*03ce13f7SAndroid Build Coastguard Worker 		    , address(isStore ? inst->getStoreAddress() : inst->getLoadAddress())
77*03ce13f7SAndroid Build Coastguard Worker 		    , isStore(isStore)
78*03ce13f7SAndroid Build Coastguard Worker 		{
79*03ce13f7SAndroid Build Coastguard Worker 		}
80*03ce13f7SAndroid Build Coastguard Worker 
81*03ce13f7SAndroid Build Coastguard Worker 		Ice::Inst *inst;
82*03ce13f7SAndroid Build Coastguard Worker 		Ice::Operand *address;
83*03ce13f7SAndroid Build Coastguard Worker 		bool isStore;
84*03ce13f7SAndroid Build Coastguard Worker 	};
85*03ce13f7SAndroid Build Coastguard Worker 
86*03ce13f7SAndroid Build Coastguard Worker 	Optimizer::Uses *getUses(Ice::Operand *);
87*03ce13f7SAndroid Build Coastguard Worker 	void setUses(Ice::Operand *, Optimizer::Uses *);
88*03ce13f7SAndroid Build Coastguard Worker 	bool hasUses(Ice::Operand *) const;
89*03ce13f7SAndroid Build Coastguard Worker 
90*03ce13f7SAndroid Build Coastguard Worker 	Ice::Inst *getDefinition(Ice::Variable *);
91*03ce13f7SAndroid Build Coastguard Worker 	void setDefinition(Ice::Variable *, Ice::Inst *);
92*03ce13f7SAndroid Build Coastguard Worker 
93*03ce13f7SAndroid Build Coastguard Worker 	std::vector<Ice::Operand *> operandsWithUses;
94*03ce13f7SAndroid Build Coastguard Worker 
95*03ce13f7SAndroid Build Coastguard Worker 	rr::Nucleus::OptimizerReport *report = nullptr;
96*03ce13f7SAndroid Build Coastguard Worker };
97*03ce13f7SAndroid Build Coastguard Worker 
run(Ice::Cfg * function)98*03ce13f7SAndroid Build Coastguard Worker void Optimizer::run(Ice::Cfg *function)
99*03ce13f7SAndroid Build Coastguard Worker {
100*03ce13f7SAndroid Build Coastguard Worker 	this->function = function;
101*03ce13f7SAndroid Build Coastguard Worker 	this->context = function->getContext();
102*03ce13f7SAndroid Build Coastguard Worker 
103*03ce13f7SAndroid Build Coastguard Worker 	analyzeUses(function);
104*03ce13f7SAndroid Build Coastguard Worker 
105*03ce13f7SAndroid Build Coastguard Worker 	// Start by eliminating any dead code, to avoid redundant work for the
106*03ce13f7SAndroid Build Coastguard Worker 	// subsequent optimization passes.
107*03ce13f7SAndroid Build Coastguard Worker 	eliminateDeadCode();
108*03ce13f7SAndroid Build Coastguard Worker 	eliminateUnitializedLoads();
109*03ce13f7SAndroid Build Coastguard Worker 
110*03ce13f7SAndroid Build Coastguard Worker 	// Eliminate allocas which store the address of other allocas.
111*03ce13f7SAndroid Build Coastguard Worker 	propagateAlloca();
112*03ce13f7SAndroid Build Coastguard Worker 
113*03ce13f7SAndroid Build Coastguard Worker 	// Replace arrays with individual elements if only statically indexed.
114*03ce13f7SAndroid Build Coastguard Worker 	performScalarReplacementOfAggregates();
115*03ce13f7SAndroid Build Coastguard Worker 
116*03ce13f7SAndroid Build Coastguard Worker 	// Iterate through basic blocks to propagate loads following stores.
117*03ce13f7SAndroid Build Coastguard Worker 	optimizeSingleBasicBlockLoadsStores();
118*03ce13f7SAndroid Build Coastguard Worker 
119*03ce13f7SAndroid Build Coastguard Worker 	for(auto operand : operandsWithUses)
120*03ce13f7SAndroid Build Coastguard Worker 	{
121*03ce13f7SAndroid Build Coastguard Worker 		// Deletes the Uses instance on the operand
122*03ce13f7SAndroid Build Coastguard Worker 		setUses(operand, nullptr);
123*03ce13f7SAndroid Build Coastguard Worker 	}
124*03ce13f7SAndroid Build Coastguard Worker 	operandsWithUses.clear();
125*03ce13f7SAndroid Build Coastguard Worker 
126*03ce13f7SAndroid Build Coastguard Worker 	collectDiagnostics();
127*03ce13f7SAndroid Build Coastguard Worker }
128*03ce13f7SAndroid Build Coastguard Worker 
129*03ce13f7SAndroid Build Coastguard Worker // Eliminates allocas which store the address of other allocas.
propagateAlloca()130*03ce13f7SAndroid Build Coastguard Worker void Optimizer::propagateAlloca()
131*03ce13f7SAndroid Build Coastguard Worker {
132*03ce13f7SAndroid Build Coastguard Worker 	Ice::CfgNode *entryBlock = function->getEntryNode();
133*03ce13f7SAndroid Build Coastguard Worker 	Ice::InstList &instList = entryBlock->getInsts();
134*03ce13f7SAndroid Build Coastguard Worker 
135*03ce13f7SAndroid Build Coastguard Worker 	for(Ice::Inst &inst : instList)
136*03ce13f7SAndroid Build Coastguard Worker 	{
137*03ce13f7SAndroid Build Coastguard Worker 		if(inst.isDeleted())
138*03ce13f7SAndroid Build Coastguard Worker 		{
139*03ce13f7SAndroid Build Coastguard Worker 			continue;
140*03ce13f7SAndroid Build Coastguard Worker 		}
141*03ce13f7SAndroid Build Coastguard Worker 
142*03ce13f7SAndroid Build Coastguard Worker 		auto *alloca = llvm::dyn_cast<Ice::InstAlloca>(&inst);
143*03ce13f7SAndroid Build Coastguard Worker 
144*03ce13f7SAndroid Build Coastguard Worker 		if(!alloca)
145*03ce13f7SAndroid Build Coastguard Worker 		{
146*03ce13f7SAndroid Build Coastguard Worker 			break;  // Allocas are all at the top
147*03ce13f7SAndroid Build Coastguard Worker 		}
148*03ce13f7SAndroid Build Coastguard Worker 
149*03ce13f7SAndroid Build Coastguard Worker 		// Look for stores of this alloca's address.
150*03ce13f7SAndroid Build Coastguard Worker 		Ice::Operand *address = alloca->getDest();
151*03ce13f7SAndroid Build Coastguard Worker 		Uses uses = *getUses(address);  // Hard copy
152*03ce13f7SAndroid Build Coastguard Worker 
153*03ce13f7SAndroid Build Coastguard Worker 		for(auto *store : uses)
154*03ce13f7SAndroid Build Coastguard Worker 		{
155*03ce13f7SAndroid Build Coastguard Worker 			if(isStore(*store) && store->getData() == address)
156*03ce13f7SAndroid Build Coastguard Worker 			{
157*03ce13f7SAndroid Build Coastguard Worker 				Ice::Operand *dest = store->getStoreAddress();
158*03ce13f7SAndroid Build Coastguard Worker 				Ice::Variable *destVar = llvm::dyn_cast<Ice::Variable>(dest);
159*03ce13f7SAndroid Build Coastguard Worker 				Ice::Inst *def = destVar ? getDefinition(destVar) : nullptr;
160*03ce13f7SAndroid Build Coastguard Worker 
161*03ce13f7SAndroid Build Coastguard Worker 				// If the address is stored into another stack variable, eliminate the latter.
162*03ce13f7SAndroid Build Coastguard Worker 				if(def && def->getKind() == Ice::Inst::Alloca)
163*03ce13f7SAndroid Build Coastguard Worker 				{
164*03ce13f7SAndroid Build Coastguard Worker 					Uses destUses = *getUses(dest);  // Hard copy
165*03ce13f7SAndroid Build Coastguard Worker 
166*03ce13f7SAndroid Build Coastguard Worker 					// Make sure the only store into the stack variable is this address, and that all of its other uses are loads.
167*03ce13f7SAndroid Build Coastguard Worker 					// This prevents dynamic array loads/stores to be replaced by a scalar.
168*03ce13f7SAndroid Build Coastguard Worker 					if((destUses.stores.size() == 1) && (destUses.loads.size() == destUses.size() - 1))
169*03ce13f7SAndroid Build Coastguard Worker 					{
170*03ce13f7SAndroid Build Coastguard Worker 						for(auto *load : destUses.loads)
171*03ce13f7SAndroid Build Coastguard Worker 						{
172*03ce13f7SAndroid Build Coastguard Worker 							replace(load, address);
173*03ce13f7SAndroid Build Coastguard Worker 						}
174*03ce13f7SAndroid Build Coastguard Worker 
175*03ce13f7SAndroid Build Coastguard Worker 						// The address is now only stored, never loaded, so the store can be eliminated, together with its alloca.
176*03ce13f7SAndroid Build Coastguard Worker 						assert(getUses(dest)->size() == 1);
177*03ce13f7SAndroid Build Coastguard Worker 						deleteInstruction(store);
178*03ce13f7SAndroid Build Coastguard Worker 						assert(def->isDeleted());
179*03ce13f7SAndroid Build Coastguard Worker 					}
180*03ce13f7SAndroid Build Coastguard Worker 				}
181*03ce13f7SAndroid Build Coastguard Worker 			}
182*03ce13f7SAndroid Build Coastguard Worker 		}
183*03ce13f7SAndroid Build Coastguard Worker 	}
184*03ce13f7SAndroid Build Coastguard Worker }
185*03ce13f7SAndroid Build Coastguard Worker 
pointerType()186*03ce13f7SAndroid Build Coastguard Worker Ice::Type pointerType()
187*03ce13f7SAndroid Build Coastguard Worker {
188*03ce13f7SAndroid Build Coastguard Worker 	if(sizeof(void *) == 8)
189*03ce13f7SAndroid Build Coastguard Worker 	{
190*03ce13f7SAndroid Build Coastguard Worker 		return Ice::IceType_i64;
191*03ce13f7SAndroid Build Coastguard Worker 	}
192*03ce13f7SAndroid Build Coastguard Worker 	else
193*03ce13f7SAndroid Build Coastguard Worker 	{
194*03ce13f7SAndroid Build Coastguard Worker 		return Ice::IceType_i32;
195*03ce13f7SAndroid Build Coastguard Worker 	}
196*03ce13f7SAndroid Build Coastguard Worker }
197*03ce13f7SAndroid Build Coastguard Worker 
198*03ce13f7SAndroid Build Coastguard Worker // Replace arrays with individual elements if only statically indexed.
performScalarReplacementOfAggregates()199*03ce13f7SAndroid Build Coastguard Worker void Optimizer::performScalarReplacementOfAggregates()
200*03ce13f7SAndroid Build Coastguard Worker {
201*03ce13f7SAndroid Build Coastguard Worker 	std::vector<Ice::InstAlloca *> newAllocas;
202*03ce13f7SAndroid Build Coastguard Worker 
203*03ce13f7SAndroid Build Coastguard Worker 	Ice::CfgNode *entryBlock = function->getEntryNode();
204*03ce13f7SAndroid Build Coastguard Worker 	Ice::InstList &instList = entryBlock->getInsts();
205*03ce13f7SAndroid Build Coastguard Worker 
206*03ce13f7SAndroid Build Coastguard Worker 	for(Ice::Inst &inst : instList)
207*03ce13f7SAndroid Build Coastguard Worker 	{
208*03ce13f7SAndroid Build Coastguard Worker 		if(inst.isDeleted())
209*03ce13f7SAndroid Build Coastguard Worker 		{
210*03ce13f7SAndroid Build Coastguard Worker 			continue;
211*03ce13f7SAndroid Build Coastguard Worker 		}
212*03ce13f7SAndroid Build Coastguard Worker 
213*03ce13f7SAndroid Build Coastguard Worker 		auto *alloca = llvm::dyn_cast<Ice::InstAlloca>(&inst);
214*03ce13f7SAndroid Build Coastguard Worker 
215*03ce13f7SAndroid Build Coastguard Worker 		if(!alloca)
216*03ce13f7SAndroid Build Coastguard Worker 		{
217*03ce13f7SAndroid Build Coastguard Worker 			break;  // Allocas are all at the top
218*03ce13f7SAndroid Build Coastguard Worker 		}
219*03ce13f7SAndroid Build Coastguard Worker 
220*03ce13f7SAndroid Build Coastguard Worker 		uint32_t sizeInBytes = llvm::cast<Ice::ConstantInteger32>(alloca->getSizeInBytes())->getValue();
221*03ce13f7SAndroid Build Coastguard Worker 		uint32_t alignInBytes = alloca->getAlignInBytes();
222*03ce13f7SAndroid Build Coastguard Worker 
223*03ce13f7SAndroid Build Coastguard Worker 		// This pass relies on array elements to be naturally aligned (i.e. matches the type size).
224*03ce13f7SAndroid Build Coastguard Worker 		assert(sizeInBytes >= alignInBytes);
225*03ce13f7SAndroid Build Coastguard Worker 		assert(sizeInBytes % alignInBytes == 0);
226*03ce13f7SAndroid Build Coastguard Worker 		uint32_t elementCount = sizeInBytes / alignInBytes;
227*03ce13f7SAndroid Build Coastguard Worker 
228*03ce13f7SAndroid Build Coastguard Worker 		Ice::Operand *address = alloca->getDest();
229*03ce13f7SAndroid Build Coastguard Worker 
230*03ce13f7SAndroid Build Coastguard Worker 		if(isStaticallyIndexedArray(address))
231*03ce13f7SAndroid Build Coastguard Worker 		{
232*03ce13f7SAndroid Build Coastguard Worker 			// Delete the old array.
233*03ce13f7SAndroid Build Coastguard Worker 			alloca->setDeleted();
234*03ce13f7SAndroid Build Coastguard Worker 
235*03ce13f7SAndroid Build Coastguard Worker 			// Allocate new stack slots for each element.
236*03ce13f7SAndroid Build Coastguard Worker 			std::vector<Ice::Variable *> newAddress(elementCount);
237*03ce13f7SAndroid Build Coastguard Worker 			auto *bytes = Ice::ConstantInteger32::create(context, Ice::IceType_i32, alignInBytes);
238*03ce13f7SAndroid Build Coastguard Worker 
239*03ce13f7SAndroid Build Coastguard Worker 			for(uint32_t i = 0; i < elementCount; i++)
240*03ce13f7SAndroid Build Coastguard Worker 			{
241*03ce13f7SAndroid Build Coastguard Worker 				newAddress[i] = function->makeVariable(pointerType());
242*03ce13f7SAndroid Build Coastguard Worker 				auto *alloca = Ice::InstAlloca::create(function, newAddress[i], bytes, alignInBytes);
243*03ce13f7SAndroid Build Coastguard Worker 				setDefinition(newAddress[i], alloca);
244*03ce13f7SAndroid Build Coastguard Worker 
245*03ce13f7SAndroid Build Coastguard Worker 				newAllocas.push_back(alloca);
246*03ce13f7SAndroid Build Coastguard Worker 			}
247*03ce13f7SAndroid Build Coastguard Worker 
248*03ce13f7SAndroid Build Coastguard Worker 			Uses uses = *getUses(address);  // Hard copy
249*03ce13f7SAndroid Build Coastguard Worker 
250*03ce13f7SAndroid Build Coastguard Worker 			for(auto *use : uses)
251*03ce13f7SAndroid Build Coastguard Worker 			{
252*03ce13f7SAndroid Build Coastguard Worker 				assert(!use->isDeleted());
253*03ce13f7SAndroid Build Coastguard Worker 
254*03ce13f7SAndroid Build Coastguard Worker 				if(isLoad(*use))  // Direct use of base address
255*03ce13f7SAndroid Build Coastguard Worker 				{
256*03ce13f7SAndroid Build Coastguard Worker 					use->replaceSource(asLoadSubVector(use) ? 1 : 0, newAddress[0]);
257*03ce13f7SAndroid Build Coastguard Worker 					getUses(newAddress[0])->insert(newAddress[0], use);
258*03ce13f7SAndroid Build Coastguard Worker 				}
259*03ce13f7SAndroid Build Coastguard Worker 				else if(isStore(*use))  // Direct use of base address
260*03ce13f7SAndroid Build Coastguard Worker 				{
261*03ce13f7SAndroid Build Coastguard Worker 					use->replaceSource(asStoreSubVector(use) ? 2 : 1, newAddress[0]);
262*03ce13f7SAndroid Build Coastguard Worker 					getUses(newAddress[0])->insert(newAddress[0], use);
263*03ce13f7SAndroid Build Coastguard Worker 				}
264*03ce13f7SAndroid Build Coastguard Worker 				else  // Statically indexed use
265*03ce13f7SAndroid Build Coastguard Worker 				{
266*03ce13f7SAndroid Build Coastguard Worker 					auto *arithmetic = llvm::cast<Ice::InstArithmetic>(use);
267*03ce13f7SAndroid Build Coastguard Worker 
268*03ce13f7SAndroid Build Coastguard Worker 					if(arithmetic->getOp() == Ice::InstArithmetic::Add)
269*03ce13f7SAndroid Build Coastguard Worker 					{
270*03ce13f7SAndroid Build Coastguard Worker 						auto *rhs = arithmetic->getSrc(1);
271*03ce13f7SAndroid Build Coastguard Worker 						int32_t offset = llvm::cast<Ice::ConstantInteger32>(rhs)->getValue();
272*03ce13f7SAndroid Build Coastguard Worker 
273*03ce13f7SAndroid Build Coastguard Worker 						assert(offset % alignInBytes == 0);
274*03ce13f7SAndroid Build Coastguard Worker 						int32_t index = offset / alignInBytes;
275*03ce13f7SAndroid Build Coastguard Worker 						assert(static_cast<uint32_t>(index) < elementCount);
276*03ce13f7SAndroid Build Coastguard Worker 
277*03ce13f7SAndroid Build Coastguard Worker 						replace(arithmetic, newAddress[index]);
278*03ce13f7SAndroid Build Coastguard Worker 					}
279*03ce13f7SAndroid Build Coastguard Worker 					else
280*03ce13f7SAndroid Build Coastguard Worker 						assert(false && "Mismatch between isStaticallyIndexedArray() and scalarReplacementOfAggregates()");
281*03ce13f7SAndroid Build Coastguard Worker 				}
282*03ce13f7SAndroid Build Coastguard Worker 			}
283*03ce13f7SAndroid Build Coastguard Worker 		}
284*03ce13f7SAndroid Build Coastguard Worker 	}
285*03ce13f7SAndroid Build Coastguard Worker 
286*03ce13f7SAndroid Build Coastguard Worker 	// After looping over all the old allocas, add any new ones that replace them.
287*03ce13f7SAndroid Build Coastguard Worker 	// They're added to the front in reverse order, to retain their original order.
288*03ce13f7SAndroid Build Coastguard Worker 	for(size_t i = newAllocas.size(); i-- != 0;)
289*03ce13f7SAndroid Build Coastguard Worker 	{
290*03ce13f7SAndroid Build Coastguard Worker 		if(!isDead(newAllocas[i]))
291*03ce13f7SAndroid Build Coastguard Worker 		{
292*03ce13f7SAndroid Build Coastguard Worker 			instList.push_front(newAllocas[i]);
293*03ce13f7SAndroid Build Coastguard Worker 		}
294*03ce13f7SAndroid Build Coastguard Worker 	}
295*03ce13f7SAndroid Build Coastguard Worker }
296*03ce13f7SAndroid Build Coastguard Worker 
eliminateDeadCode()297*03ce13f7SAndroid Build Coastguard Worker void Optimizer::eliminateDeadCode()
298*03ce13f7SAndroid Build Coastguard Worker {
299*03ce13f7SAndroid Build Coastguard Worker 	bool modified;
300*03ce13f7SAndroid Build Coastguard Worker 	do
301*03ce13f7SAndroid Build Coastguard Worker 	{
302*03ce13f7SAndroid Build Coastguard Worker 		modified = false;
303*03ce13f7SAndroid Build Coastguard Worker 		for(Ice::CfgNode *basicBlock : function->getNodes())
304*03ce13f7SAndroid Build Coastguard Worker 		{
305*03ce13f7SAndroid Build Coastguard Worker 			for(Ice::Inst &inst : Ice::reverse_range(basicBlock->getInsts()))
306*03ce13f7SAndroid Build Coastguard Worker 			{
307*03ce13f7SAndroid Build Coastguard Worker 				if(inst.isDeleted())
308*03ce13f7SAndroid Build Coastguard Worker 				{
309*03ce13f7SAndroid Build Coastguard Worker 					continue;
310*03ce13f7SAndroid Build Coastguard Worker 				}
311*03ce13f7SAndroid Build Coastguard Worker 
312*03ce13f7SAndroid Build Coastguard Worker 				if(isDead(&inst))
313*03ce13f7SAndroid Build Coastguard Worker 				{
314*03ce13f7SAndroid Build Coastguard Worker 					deleteInstruction(&inst);
315*03ce13f7SAndroid Build Coastguard Worker 					modified = true;
316*03ce13f7SAndroid Build Coastguard Worker 				}
317*03ce13f7SAndroid Build Coastguard Worker 			}
318*03ce13f7SAndroid Build Coastguard Worker 		}
319*03ce13f7SAndroid Build Coastguard Worker 	} while(modified);
320*03ce13f7SAndroid Build Coastguard Worker }
321*03ce13f7SAndroid Build Coastguard Worker 
eliminateUnitializedLoads()322*03ce13f7SAndroid Build Coastguard Worker void Optimizer::eliminateUnitializedLoads()
323*03ce13f7SAndroid Build Coastguard Worker {
324*03ce13f7SAndroid Build Coastguard Worker 	Ice::CfgNode *entryBlock = function->getEntryNode();
325*03ce13f7SAndroid Build Coastguard Worker 
326*03ce13f7SAndroid Build Coastguard Worker 	for(Ice::Inst &alloca : entryBlock->getInsts())
327*03ce13f7SAndroid Build Coastguard Worker 	{
328*03ce13f7SAndroid Build Coastguard Worker 		if(alloca.isDeleted())
329*03ce13f7SAndroid Build Coastguard Worker 		{
330*03ce13f7SAndroid Build Coastguard Worker 			continue;
331*03ce13f7SAndroid Build Coastguard Worker 		}
332*03ce13f7SAndroid Build Coastguard Worker 
333*03ce13f7SAndroid Build Coastguard Worker 		if(!llvm::isa<Ice::InstAlloca>(alloca))
334*03ce13f7SAndroid Build Coastguard Worker 		{
335*03ce13f7SAndroid Build Coastguard Worker 			break;  // Allocas are all at the top
336*03ce13f7SAndroid Build Coastguard Worker 		}
337*03ce13f7SAndroid Build Coastguard Worker 
338*03ce13f7SAndroid Build Coastguard Worker 		Ice::Operand *address = alloca.getDest();
339*03ce13f7SAndroid Build Coastguard Worker 
340*03ce13f7SAndroid Build Coastguard Worker 		if(!hasUses(address))
341*03ce13f7SAndroid Build Coastguard Worker 		{
342*03ce13f7SAndroid Build Coastguard Worker 			continue;
343*03ce13f7SAndroid Build Coastguard Worker 		}
344*03ce13f7SAndroid Build Coastguard Worker 
345*03ce13f7SAndroid Build Coastguard Worker 		const auto &addressUses = *getUses(address);
346*03ce13f7SAndroid Build Coastguard Worker 
347*03ce13f7SAndroid Build Coastguard Worker 		if(!addressUses.areOnlyLoadStore())
348*03ce13f7SAndroid Build Coastguard Worker 		{
349*03ce13f7SAndroid Build Coastguard Worker 			continue;
350*03ce13f7SAndroid Build Coastguard Worker 		}
351*03ce13f7SAndroid Build Coastguard Worker 
352*03ce13f7SAndroid Build Coastguard Worker 		if(addressUses.stores.empty())
353*03ce13f7SAndroid Build Coastguard Worker 		{
354*03ce13f7SAndroid Build Coastguard Worker 			for(Ice::Inst *load : addressUses.loads)
355*03ce13f7SAndroid Build Coastguard Worker 			{
356*03ce13f7SAndroid Build Coastguard Worker 				Ice::Variable *loadData = load->getDest();
357*03ce13f7SAndroid Build Coastguard Worker 
358*03ce13f7SAndroid Build Coastguard Worker 				if(hasUses(loadData))
359*03ce13f7SAndroid Build Coastguard Worker 				{
360*03ce13f7SAndroid Build Coastguard Worker 					for(Ice::Inst *use : *getUses(loadData))
361*03ce13f7SAndroid Build Coastguard Worker 					{
362*03ce13f7SAndroid Build Coastguard Worker 						for(Ice::SizeT i = 0; i < use->getSrcSize(); i++)
363*03ce13f7SAndroid Build Coastguard Worker 						{
364*03ce13f7SAndroid Build Coastguard Worker 							if(use->getSrc(i) == loadData)
365*03ce13f7SAndroid Build Coastguard Worker 							{
366*03ce13f7SAndroid Build Coastguard Worker 								auto *undef = context->getConstantUndef(loadData->getType());
367*03ce13f7SAndroid Build Coastguard Worker 
368*03ce13f7SAndroid Build Coastguard Worker 								use->replaceSource(i, undef);
369*03ce13f7SAndroid Build Coastguard Worker 							}
370*03ce13f7SAndroid Build Coastguard Worker 						}
371*03ce13f7SAndroid Build Coastguard Worker 					}
372*03ce13f7SAndroid Build Coastguard Worker 
373*03ce13f7SAndroid Build Coastguard Worker 					setUses(loadData, nullptr);
374*03ce13f7SAndroid Build Coastguard Worker 				}
375*03ce13f7SAndroid Build Coastguard Worker 
376*03ce13f7SAndroid Build Coastguard Worker 				load->setDeleted();
377*03ce13f7SAndroid Build Coastguard Worker 			}
378*03ce13f7SAndroid Build Coastguard Worker 
379*03ce13f7SAndroid Build Coastguard Worker 			alloca.setDeleted();
380*03ce13f7SAndroid Build Coastguard Worker 			setUses(address, nullptr);
381*03ce13f7SAndroid Build Coastguard Worker 		}
382*03ce13f7SAndroid Build Coastguard Worker 	}
383*03ce13f7SAndroid Build Coastguard Worker }
384*03ce13f7SAndroid Build Coastguard Worker 
385*03ce13f7SAndroid Build Coastguard Worker // Iterate through basic blocks to propagate stores to subsequent loads.
optimizeSingleBasicBlockLoadsStores()386*03ce13f7SAndroid Build Coastguard Worker void Optimizer::optimizeSingleBasicBlockLoadsStores()
387*03ce13f7SAndroid Build Coastguard Worker {
388*03ce13f7SAndroid Build Coastguard Worker 	for(Ice::CfgNode *block : function->getNodes())
389*03ce13f7SAndroid Build Coastguard Worker 	{
390*03ce13f7SAndroid Build Coastguard Worker 		// For each stack variable keep track of the last store instruction.
391*03ce13f7SAndroid Build Coastguard Worker 		// To eliminate a store followed by another store to the same alloca address
392*03ce13f7SAndroid Build Coastguard Worker 		// we must also know whether all loads have been replaced by the store value.
393*03ce13f7SAndroid Build Coastguard Worker 		struct LastStore
394*03ce13f7SAndroid Build Coastguard Worker 		{
395*03ce13f7SAndroid Build Coastguard Worker 			Ice::Inst *store;
396*03ce13f7SAndroid Build Coastguard Worker 			bool allLoadsReplaced = true;
397*03ce13f7SAndroid Build Coastguard Worker 		};
398*03ce13f7SAndroid Build Coastguard Worker 
399*03ce13f7SAndroid Build Coastguard Worker 		// Use the (unique) index of the alloca's destination argument (i.e. the address
400*03ce13f7SAndroid Build Coastguard Worker 		// of the allocated variable), which is of type SizeT, as the key. Note we do not
401*03ce13f7SAndroid Build Coastguard Worker 		// use the pointer to the alloca instruction or its resulting address, to avoid
402*03ce13f7SAndroid Build Coastguard Worker 		// undeterministic unordered_map behavior.
403*03ce13f7SAndroid Build Coastguard Worker 		std::unordered_map<Ice::SizeT, LastStore> lastStoreTo;
404*03ce13f7SAndroid Build Coastguard Worker 
405*03ce13f7SAndroid Build Coastguard Worker 		for(Ice::Inst &inst : block->getInsts())
406*03ce13f7SAndroid Build Coastguard Worker 		{
407*03ce13f7SAndroid Build Coastguard Worker 			if(inst.isDeleted())
408*03ce13f7SAndroid Build Coastguard Worker 			{
409*03ce13f7SAndroid Build Coastguard Worker 				continue;
410*03ce13f7SAndroid Build Coastguard Worker 			}
411*03ce13f7SAndroid Build Coastguard Worker 
412*03ce13f7SAndroid Build Coastguard Worker 			if(isStore(inst))
413*03ce13f7SAndroid Build Coastguard Worker 			{
414*03ce13f7SAndroid Build Coastguard Worker 				Ice::Operand *address = inst.getStoreAddress();
415*03ce13f7SAndroid Build Coastguard Worker 
416*03ce13f7SAndroid Build Coastguard Worker 				if(Ice::InstAlloca *alloca = allocaOf(address))
417*03ce13f7SAndroid Build Coastguard Worker 				{
418*03ce13f7SAndroid Build Coastguard Worker 					// Only consider this store for propagation if its address is not used as
419*03ce13f7SAndroid Build Coastguard Worker 					// a pointer which could be used for indirect stores.
420*03ce13f7SAndroid Build Coastguard Worker 					if(getUses(address)->areOnlyLoadStore())
421*03ce13f7SAndroid Build Coastguard Worker 					{
422*03ce13f7SAndroid Build Coastguard Worker 						Ice::SizeT addressIdx = alloca->getDest()->getIndex();
423*03ce13f7SAndroid Build Coastguard Worker 
424*03ce13f7SAndroid Build Coastguard Worker 						// If there was a previous store to this address, and it was propagated
425*03ce13f7SAndroid Build Coastguard Worker 						// to all subsequent loads, it can be eliminated.
426*03ce13f7SAndroid Build Coastguard Worker 						if(auto entry = lastStoreTo.find(addressIdx); entry != lastStoreTo.end())
427*03ce13f7SAndroid Build Coastguard Worker 						{
428*03ce13f7SAndroid Build Coastguard Worker 							Ice::Inst *previousStore = entry->second.store;
429*03ce13f7SAndroid Build Coastguard Worker 
430*03ce13f7SAndroid Build Coastguard Worker 							if(storeTypeMatchesStore(&inst, previousStore) &&
431*03ce13f7SAndroid Build Coastguard Worker 							   entry->second.allLoadsReplaced)
432*03ce13f7SAndroid Build Coastguard Worker 							{
433*03ce13f7SAndroid Build Coastguard Worker 								deleteInstruction(previousStore);
434*03ce13f7SAndroid Build Coastguard Worker 							}
435*03ce13f7SAndroid Build Coastguard Worker 						}
436*03ce13f7SAndroid Build Coastguard Worker 
437*03ce13f7SAndroid Build Coastguard Worker 						lastStoreTo[addressIdx] = { &inst };
438*03ce13f7SAndroid Build Coastguard Worker 					}
439*03ce13f7SAndroid Build Coastguard Worker 				}
440*03ce13f7SAndroid Build Coastguard Worker 			}
441*03ce13f7SAndroid Build Coastguard Worker 			else if(isLoad(inst))
442*03ce13f7SAndroid Build Coastguard Worker 			{
443*03ce13f7SAndroid Build Coastguard Worker 				if(Ice::InstAlloca *alloca = allocaOf(inst.getLoadAddress()))
444*03ce13f7SAndroid Build Coastguard Worker 				{
445*03ce13f7SAndroid Build Coastguard Worker 					Ice::SizeT addressIdx = alloca->getDest()->getIndex();
446*03ce13f7SAndroid Build Coastguard Worker 					auto entry = lastStoreTo.find(addressIdx);
447*03ce13f7SAndroid Build Coastguard Worker 					if(entry != lastStoreTo.end())
448*03ce13f7SAndroid Build Coastguard Worker 					{
449*03ce13f7SAndroid Build Coastguard Worker 						const Ice::Inst *store = entry->second.store;
450*03ce13f7SAndroid Build Coastguard Worker 
451*03ce13f7SAndroid Build Coastguard Worker 						if(loadTypeMatchesStore(&inst, store))
452*03ce13f7SAndroid Build Coastguard Worker 						{
453*03ce13f7SAndroid Build Coastguard Worker 							replace(&inst, store->getData());
454*03ce13f7SAndroid Build Coastguard Worker 						}
455*03ce13f7SAndroid Build Coastguard Worker 						else
456*03ce13f7SAndroid Build Coastguard Worker 						{
457*03ce13f7SAndroid Build Coastguard Worker 							entry->second.allLoadsReplaced = false;
458*03ce13f7SAndroid Build Coastguard Worker 						}
459*03ce13f7SAndroid Build Coastguard Worker 					}
460*03ce13f7SAndroid Build Coastguard Worker 				}
461*03ce13f7SAndroid Build Coastguard Worker 			}
462*03ce13f7SAndroid Build Coastguard Worker 		}
463*03ce13f7SAndroid Build Coastguard Worker 	}
464*03ce13f7SAndroid Build Coastguard Worker 
465*03ce13f7SAndroid Build Coastguard Worker 	// This can leave some dead instructions. Specifically stores.
466*03ce13f7SAndroid Build Coastguard Worker 	// TODO(b/179668593): Check just for dead stores by iterating over allocas?
467*03ce13f7SAndroid Build Coastguard Worker 	eliminateDeadCode();
468*03ce13f7SAndroid Build Coastguard Worker }
469*03ce13f7SAndroid Build Coastguard Worker 
analyzeUses(Ice::Cfg * function)470*03ce13f7SAndroid Build Coastguard Worker void Optimizer::analyzeUses(Ice::Cfg *function)
471*03ce13f7SAndroid Build Coastguard Worker {
472*03ce13f7SAndroid Build Coastguard Worker 	for(Ice::CfgNode *basicBlock : function->getNodes())
473*03ce13f7SAndroid Build Coastguard Worker 	{
474*03ce13f7SAndroid Build Coastguard Worker 		for(Ice::Inst &instruction : basicBlock->getInsts())
475*03ce13f7SAndroid Build Coastguard Worker 		{
476*03ce13f7SAndroid Build Coastguard Worker 			if(instruction.isDeleted())
477*03ce13f7SAndroid Build Coastguard Worker 			{
478*03ce13f7SAndroid Build Coastguard Worker 				continue;
479*03ce13f7SAndroid Build Coastguard Worker 			}
480*03ce13f7SAndroid Build Coastguard Worker 
481*03ce13f7SAndroid Build Coastguard Worker 			if(instruction.getDest())
482*03ce13f7SAndroid Build Coastguard Worker 			{
483*03ce13f7SAndroid Build Coastguard Worker 				setDefinition(instruction.getDest(), &instruction);
484*03ce13f7SAndroid Build Coastguard Worker 			}
485*03ce13f7SAndroid Build Coastguard Worker 
486*03ce13f7SAndroid Build Coastguard Worker 			for(Ice::SizeT i = 0; i < instruction.getSrcSize(); i++)
487*03ce13f7SAndroid Build Coastguard Worker 			{
488*03ce13f7SAndroid Build Coastguard Worker 				Ice::SizeT unique = 0;
489*03ce13f7SAndroid Build Coastguard Worker 				for(; unique < i; unique++)
490*03ce13f7SAndroid Build Coastguard Worker 				{
491*03ce13f7SAndroid Build Coastguard Worker 					if(instruction.getSrc(i) == instruction.getSrc(unique))
492*03ce13f7SAndroid Build Coastguard Worker 					{
493*03ce13f7SAndroid Build Coastguard Worker 						break;
494*03ce13f7SAndroid Build Coastguard Worker 					}
495*03ce13f7SAndroid Build Coastguard Worker 				}
496*03ce13f7SAndroid Build Coastguard Worker 
497*03ce13f7SAndroid Build Coastguard Worker 				if(i == unique)
498*03ce13f7SAndroid Build Coastguard Worker 				{
499*03ce13f7SAndroid Build Coastguard Worker 					Ice::Operand *src = instruction.getSrc(i);
500*03ce13f7SAndroid Build Coastguard Worker 					getUses(src)->insert(src, &instruction);
501*03ce13f7SAndroid Build Coastguard Worker 				}
502*03ce13f7SAndroid Build Coastguard Worker 			}
503*03ce13f7SAndroid Build Coastguard Worker 		}
504*03ce13f7SAndroid Build Coastguard Worker 	}
505*03ce13f7SAndroid Build Coastguard Worker }
506*03ce13f7SAndroid Build Coastguard Worker 
replace(Ice::Inst * instruction,Ice::Operand * newValue)507*03ce13f7SAndroid Build Coastguard Worker void Optimizer::replace(Ice::Inst *instruction, Ice::Operand *newValue)
508*03ce13f7SAndroid Build Coastguard Worker {
509*03ce13f7SAndroid Build Coastguard Worker 	Ice::Variable *oldValue = instruction->getDest();
510*03ce13f7SAndroid Build Coastguard Worker 
511*03ce13f7SAndroid Build Coastguard Worker 	if(!newValue)
512*03ce13f7SAndroid Build Coastguard Worker 	{
513*03ce13f7SAndroid Build Coastguard Worker 		newValue = context->getConstantUndef(oldValue->getType());
514*03ce13f7SAndroid Build Coastguard Worker 	}
515*03ce13f7SAndroid Build Coastguard Worker 
516*03ce13f7SAndroid Build Coastguard Worker 	if(hasUses(oldValue))
517*03ce13f7SAndroid Build Coastguard Worker 	{
518*03ce13f7SAndroid Build Coastguard Worker 		for(Ice::Inst *use : *getUses(oldValue))
519*03ce13f7SAndroid Build Coastguard Worker 		{
520*03ce13f7SAndroid Build Coastguard Worker 			assert(!use->isDeleted());  // Should have been removed from uses already
521*03ce13f7SAndroid Build Coastguard Worker 
522*03ce13f7SAndroid Build Coastguard Worker 			for(Ice::SizeT i = 0; i < use->getSrcSize(); i++)
523*03ce13f7SAndroid Build Coastguard Worker 			{
524*03ce13f7SAndroid Build Coastguard Worker 				if(use->getSrc(i) == oldValue)
525*03ce13f7SAndroid Build Coastguard Worker 				{
526*03ce13f7SAndroid Build Coastguard Worker 					use->replaceSource(i, newValue);
527*03ce13f7SAndroid Build Coastguard Worker 				}
528*03ce13f7SAndroid Build Coastguard Worker 			}
529*03ce13f7SAndroid Build Coastguard Worker 
530*03ce13f7SAndroid Build Coastguard Worker 			getUses(newValue)->insert(newValue, use);
531*03ce13f7SAndroid Build Coastguard Worker 		}
532*03ce13f7SAndroid Build Coastguard Worker 
533*03ce13f7SAndroid Build Coastguard Worker 		setUses(oldValue, nullptr);
534*03ce13f7SAndroid Build Coastguard Worker 	}
535*03ce13f7SAndroid Build Coastguard Worker 
536*03ce13f7SAndroid Build Coastguard Worker 	deleteInstruction(instruction);
537*03ce13f7SAndroid Build Coastguard Worker }
538*03ce13f7SAndroid Build Coastguard Worker 
deleteInstruction(Ice::Inst * instruction)539*03ce13f7SAndroid Build Coastguard Worker void Optimizer::deleteInstruction(Ice::Inst *instruction)
540*03ce13f7SAndroid Build Coastguard Worker {
541*03ce13f7SAndroid Build Coastguard Worker 	if(!instruction || instruction->isDeleted())
542*03ce13f7SAndroid Build Coastguard Worker 	{
543*03ce13f7SAndroid Build Coastguard Worker 		return;
544*03ce13f7SAndroid Build Coastguard Worker 	}
545*03ce13f7SAndroid Build Coastguard Worker 
546*03ce13f7SAndroid Build Coastguard Worker 	assert(!instruction->getDest() || getUses(instruction->getDest())->empty());
547*03ce13f7SAndroid Build Coastguard Worker 	instruction->setDeleted();
548*03ce13f7SAndroid Build Coastguard Worker 
549*03ce13f7SAndroid Build Coastguard Worker 	for(Ice::SizeT i = 0; i < instruction->getSrcSize(); i++)
550*03ce13f7SAndroid Build Coastguard Worker 	{
551*03ce13f7SAndroid Build Coastguard Worker 		Ice::Operand *src = instruction->getSrc(i);
552*03ce13f7SAndroid Build Coastguard Worker 
553*03ce13f7SAndroid Build Coastguard Worker 		if(hasUses(src))
554*03ce13f7SAndroid Build Coastguard Worker 		{
555*03ce13f7SAndroid Build Coastguard Worker 			auto &srcUses = *getUses(src);
556*03ce13f7SAndroid Build Coastguard Worker 
557*03ce13f7SAndroid Build Coastguard Worker 			srcUses.erase(instruction);
558*03ce13f7SAndroid Build Coastguard Worker 
559*03ce13f7SAndroid Build Coastguard Worker 			if(srcUses.empty())
560*03ce13f7SAndroid Build Coastguard Worker 			{
561*03ce13f7SAndroid Build Coastguard Worker 				setUses(src, nullptr);
562*03ce13f7SAndroid Build Coastguard Worker 
563*03ce13f7SAndroid Build Coastguard Worker 				if(Ice::Variable *var = llvm::dyn_cast<Ice::Variable>(src))
564*03ce13f7SAndroid Build Coastguard Worker 				{
565*03ce13f7SAndroid Build Coastguard Worker 					deleteInstruction(getDefinition(var));
566*03ce13f7SAndroid Build Coastguard Worker 				}
567*03ce13f7SAndroid Build Coastguard Worker 			}
568*03ce13f7SAndroid Build Coastguard Worker 		}
569*03ce13f7SAndroid Build Coastguard Worker 	}
570*03ce13f7SAndroid Build Coastguard Worker }
571*03ce13f7SAndroid Build Coastguard Worker 
isDead(Ice::Inst * instruction)572*03ce13f7SAndroid Build Coastguard Worker bool Optimizer::isDead(Ice::Inst *instruction)
573*03ce13f7SAndroid Build Coastguard Worker {
574*03ce13f7SAndroid Build Coastguard Worker 	Ice::Variable *dest = instruction->getDest();
575*03ce13f7SAndroid Build Coastguard Worker 
576*03ce13f7SAndroid Build Coastguard Worker 	if(dest)
577*03ce13f7SAndroid Build Coastguard Worker 	{
578*03ce13f7SAndroid Build Coastguard Worker 		return (!hasUses(dest) || getUses(dest)->empty()) && !instruction->hasSideEffects();
579*03ce13f7SAndroid Build Coastguard Worker 	}
580*03ce13f7SAndroid Build Coastguard Worker 	else if(isStore(*instruction))
581*03ce13f7SAndroid Build Coastguard Worker 	{
582*03ce13f7SAndroid Build Coastguard Worker 		if(Ice::Variable *address = llvm::dyn_cast<Ice::Variable>(instruction->getStoreAddress()))
583*03ce13f7SAndroid Build Coastguard Worker 		{
584*03ce13f7SAndroid Build Coastguard Worker 			Ice::Inst *def = getDefinition(address);
585*03ce13f7SAndroid Build Coastguard Worker 
586*03ce13f7SAndroid Build Coastguard Worker 			if(def && llvm::isa<Ice::InstAlloca>(def))
587*03ce13f7SAndroid Build Coastguard Worker 			{
588*03ce13f7SAndroid Build Coastguard Worker 				if(hasUses(address))
589*03ce13f7SAndroid Build Coastguard Worker 				{
590*03ce13f7SAndroid Build Coastguard Worker 					Optimizer::Uses *uses = getUses(address);
591*03ce13f7SAndroid Build Coastguard Worker 					return uses->size() == uses->stores.size();  // Dead if all uses are stores
592*03ce13f7SAndroid Build Coastguard Worker 				}
593*03ce13f7SAndroid Build Coastguard Worker 				else
594*03ce13f7SAndroid Build Coastguard Worker 				{
595*03ce13f7SAndroid Build Coastguard Worker 					return true;  // No uses
596*03ce13f7SAndroid Build Coastguard Worker 				}
597*03ce13f7SAndroid Build Coastguard Worker 			}
598*03ce13f7SAndroid Build Coastguard Worker 		}
599*03ce13f7SAndroid Build Coastguard Worker 	}
600*03ce13f7SAndroid Build Coastguard Worker 
601*03ce13f7SAndroid Build Coastguard Worker 	return false;
602*03ce13f7SAndroid Build Coastguard Worker }
603*03ce13f7SAndroid Build Coastguard Worker 
isStaticallyIndexedArray(Ice::Operand * allocaAddress)604*03ce13f7SAndroid Build Coastguard Worker bool Optimizer::isStaticallyIndexedArray(Ice::Operand *allocaAddress)
605*03ce13f7SAndroid Build Coastguard Worker {
606*03ce13f7SAndroid Build Coastguard Worker 	auto &uses = *getUses(allocaAddress);
607*03ce13f7SAndroid Build Coastguard Worker 
608*03ce13f7SAndroid Build Coastguard Worker 	for(auto *use : uses)
609*03ce13f7SAndroid Build Coastguard Worker 	{
610*03ce13f7SAndroid Build Coastguard Worker 		// Direct load from base address.
611*03ce13f7SAndroid Build Coastguard Worker 		if(isLoad(*use) && use->getLoadAddress() == allocaAddress)
612*03ce13f7SAndroid Build Coastguard Worker 		{
613*03ce13f7SAndroid Build Coastguard Worker 			continue;  // This is fine.
614*03ce13f7SAndroid Build Coastguard Worker 		}
615*03ce13f7SAndroid Build Coastguard Worker 
616*03ce13f7SAndroid Build Coastguard Worker 		if(isStore(*use))
617*03ce13f7SAndroid Build Coastguard Worker 		{
618*03ce13f7SAndroid Build Coastguard Worker 			// Can either be the address we're storing to, or the data we're storing.
619*03ce13f7SAndroid Build Coastguard Worker 			if(use->getStoreAddress() == allocaAddress)
620*03ce13f7SAndroid Build Coastguard Worker 			{
621*03ce13f7SAndroid Build Coastguard Worker 				continue;
622*03ce13f7SAndroid Build Coastguard Worker 			}
623*03ce13f7SAndroid Build Coastguard Worker 			else
624*03ce13f7SAndroid Build Coastguard Worker 			{
625*03ce13f7SAndroid Build Coastguard Worker 				// propagateAlloca() eliminates most of the stores of the address itself.
626*03ce13f7SAndroid Build Coastguard Worker 				// For the cases it doesn't handle, assume SRoA is not feasible.
627*03ce13f7SAndroid Build Coastguard Worker 				return false;
628*03ce13f7SAndroid Build Coastguard Worker 			}
629*03ce13f7SAndroid Build Coastguard Worker 		}
630*03ce13f7SAndroid Build Coastguard Worker 
631*03ce13f7SAndroid Build Coastguard Worker 		// Pointer arithmetic is fine if it only uses constants.
632*03ce13f7SAndroid Build Coastguard Worker 		auto *arithmetic = llvm::dyn_cast<Ice::InstArithmetic>(use);
633*03ce13f7SAndroid Build Coastguard Worker 		if(arithmetic && arithmetic->getOp() == Ice::InstArithmetic::Add)
634*03ce13f7SAndroid Build Coastguard Worker 		{
635*03ce13f7SAndroid Build Coastguard Worker 			auto *rhs = arithmetic->getSrc(1);
636*03ce13f7SAndroid Build Coastguard Worker 
637*03ce13f7SAndroid Build Coastguard Worker 			if(llvm::isa<Ice::Constant>(rhs))
638*03ce13f7SAndroid Build Coastguard Worker 			{
639*03ce13f7SAndroid Build Coastguard Worker 				continue;
640*03ce13f7SAndroid Build Coastguard Worker 			}
641*03ce13f7SAndroid Build Coastguard Worker 		}
642*03ce13f7SAndroid Build Coastguard Worker 
643*03ce13f7SAndroid Build Coastguard Worker 		// If there's any other type of use, bail out.
644*03ce13f7SAndroid Build Coastguard Worker 		return false;
645*03ce13f7SAndroid Build Coastguard Worker 	}
646*03ce13f7SAndroid Build Coastguard Worker 
647*03ce13f7SAndroid Build Coastguard Worker 	return true;
648*03ce13f7SAndroid Build Coastguard Worker }
649*03ce13f7SAndroid Build Coastguard Worker 
allocaOf(Ice::Operand * address)650*03ce13f7SAndroid Build Coastguard Worker Ice::InstAlloca *Optimizer::allocaOf(Ice::Operand *address)
651*03ce13f7SAndroid Build Coastguard Worker {
652*03ce13f7SAndroid Build Coastguard Worker 	Ice::Variable *addressVar = llvm::dyn_cast<Ice::Variable>(address);
653*03ce13f7SAndroid Build Coastguard Worker 	Ice::Inst *def = addressVar ? getDefinition(addressVar) : nullptr;
654*03ce13f7SAndroid Build Coastguard Worker 	Ice::InstAlloca *alloca = def ? llvm::dyn_cast<Ice::InstAlloca>(def) : nullptr;
655*03ce13f7SAndroid Build Coastguard Worker 
656*03ce13f7SAndroid Build Coastguard Worker 	return alloca;
657*03ce13f7SAndroid Build Coastguard Worker }
658*03ce13f7SAndroid Build Coastguard Worker 
asLoadSubVector(const Ice::Inst * instruction)659*03ce13f7SAndroid Build Coastguard Worker const Ice::InstIntrinsic *Optimizer::asLoadSubVector(const Ice::Inst *instruction)
660*03ce13f7SAndroid Build Coastguard Worker {
661*03ce13f7SAndroid Build Coastguard Worker 	if(auto *instrinsic = llvm::dyn_cast<Ice::InstIntrinsic>(instruction))
662*03ce13f7SAndroid Build Coastguard Worker 	{
663*03ce13f7SAndroid Build Coastguard Worker 		if(instrinsic->getIntrinsicID() == Ice::Intrinsics::LoadSubVector)
664*03ce13f7SAndroid Build Coastguard Worker 		{
665*03ce13f7SAndroid Build Coastguard Worker 			return instrinsic;
666*03ce13f7SAndroid Build Coastguard Worker 		}
667*03ce13f7SAndroid Build Coastguard Worker 	}
668*03ce13f7SAndroid Build Coastguard Worker 
669*03ce13f7SAndroid Build Coastguard Worker 	return nullptr;
670*03ce13f7SAndroid Build Coastguard Worker }
671*03ce13f7SAndroid Build Coastguard Worker 
asStoreSubVector(const Ice::Inst * instruction)672*03ce13f7SAndroid Build Coastguard Worker const Ice::InstIntrinsic *Optimizer::asStoreSubVector(const Ice::Inst *instruction)
673*03ce13f7SAndroid Build Coastguard Worker {
674*03ce13f7SAndroid Build Coastguard Worker 	if(auto *instrinsic = llvm::dyn_cast<Ice::InstIntrinsic>(instruction))
675*03ce13f7SAndroid Build Coastguard Worker 	{
676*03ce13f7SAndroid Build Coastguard Worker 		if(instrinsic->getIntrinsicID() == Ice::Intrinsics::StoreSubVector)
677*03ce13f7SAndroid Build Coastguard Worker 		{
678*03ce13f7SAndroid Build Coastguard Worker 			return instrinsic;
679*03ce13f7SAndroid Build Coastguard Worker 		}
680*03ce13f7SAndroid Build Coastguard Worker 	}
681*03ce13f7SAndroid Build Coastguard Worker 
682*03ce13f7SAndroid Build Coastguard Worker 	return nullptr;
683*03ce13f7SAndroid Build Coastguard Worker }
684*03ce13f7SAndroid Build Coastguard Worker 
isLoad(const Ice::Inst & instruction)685*03ce13f7SAndroid Build Coastguard Worker bool Optimizer::isLoad(const Ice::Inst &instruction)
686*03ce13f7SAndroid Build Coastguard Worker {
687*03ce13f7SAndroid Build Coastguard Worker 	if(llvm::isa<Ice::InstLoad>(&instruction))
688*03ce13f7SAndroid Build Coastguard Worker 	{
689*03ce13f7SAndroid Build Coastguard Worker 		return true;
690*03ce13f7SAndroid Build Coastguard Worker 	}
691*03ce13f7SAndroid Build Coastguard Worker 
692*03ce13f7SAndroid Build Coastguard Worker 	return asLoadSubVector(&instruction) != nullptr;
693*03ce13f7SAndroid Build Coastguard Worker }
694*03ce13f7SAndroid Build Coastguard Worker 
isStore(const Ice::Inst & instruction)695*03ce13f7SAndroid Build Coastguard Worker bool Optimizer::isStore(const Ice::Inst &instruction)
696*03ce13f7SAndroid Build Coastguard Worker {
697*03ce13f7SAndroid Build Coastguard Worker 	if(llvm::isa<Ice::InstStore>(&instruction))
698*03ce13f7SAndroid Build Coastguard Worker 	{
699*03ce13f7SAndroid Build Coastguard Worker 		return true;
700*03ce13f7SAndroid Build Coastguard Worker 	}
701*03ce13f7SAndroid Build Coastguard Worker 
702*03ce13f7SAndroid Build Coastguard Worker 	return asStoreSubVector(&instruction) != nullptr;
703*03ce13f7SAndroid Build Coastguard Worker }
704*03ce13f7SAndroid Build Coastguard Worker 
loadTypeMatchesStore(const Ice::Inst * load,const Ice::Inst * store)705*03ce13f7SAndroid Build Coastguard Worker bool Optimizer::loadTypeMatchesStore(const Ice::Inst *load, const Ice::Inst *store)
706*03ce13f7SAndroid Build Coastguard Worker {
707*03ce13f7SAndroid Build Coastguard Worker 	if(!load || !store)
708*03ce13f7SAndroid Build Coastguard Worker 	{
709*03ce13f7SAndroid Build Coastguard Worker 		return false;
710*03ce13f7SAndroid Build Coastguard Worker 	}
711*03ce13f7SAndroid Build Coastguard Worker 
712*03ce13f7SAndroid Build Coastguard Worker 	assert(isLoad(*load) && isStore(*store));
713*03ce13f7SAndroid Build Coastguard Worker 	assert(load->getLoadAddress() == store->getStoreAddress());
714*03ce13f7SAndroid Build Coastguard Worker 
715*03ce13f7SAndroid Build Coastguard Worker 	if(store->getData()->getType() != load->getDest()->getType())
716*03ce13f7SAndroid Build Coastguard Worker 	{
717*03ce13f7SAndroid Build Coastguard Worker 		return false;
718*03ce13f7SAndroid Build Coastguard Worker 	}
719*03ce13f7SAndroid Build Coastguard Worker 
720*03ce13f7SAndroid Build Coastguard Worker 	if(auto *storeSubVector = asStoreSubVector(store))
721*03ce13f7SAndroid Build Coastguard Worker 	{
722*03ce13f7SAndroid Build Coastguard Worker 		if(auto *loadSubVector = asLoadSubVector(load))
723*03ce13f7SAndroid Build Coastguard Worker 		{
724*03ce13f7SAndroid Build Coastguard Worker 			// Check for matching sub-vector width.
725*03ce13f7SAndroid Build Coastguard Worker 			return llvm::cast<Ice::ConstantInteger32>(storeSubVector->getSrc(2))->getValue() ==
726*03ce13f7SAndroid Build Coastguard Worker 			       llvm::cast<Ice::ConstantInteger32>(loadSubVector->getSrc(1))->getValue();
727*03ce13f7SAndroid Build Coastguard Worker 		}
728*03ce13f7SAndroid Build Coastguard Worker 	}
729*03ce13f7SAndroid Build Coastguard Worker 
730*03ce13f7SAndroid Build Coastguard Worker 	return true;
731*03ce13f7SAndroid Build Coastguard Worker }
732*03ce13f7SAndroid Build Coastguard Worker 
storeTypeMatchesStore(const Ice::Inst * store1,const Ice::Inst * store2)733*03ce13f7SAndroid Build Coastguard Worker bool Optimizer::storeTypeMatchesStore(const Ice::Inst *store1, const Ice::Inst *store2)
734*03ce13f7SAndroid Build Coastguard Worker {
735*03ce13f7SAndroid Build Coastguard Worker 	assert(isStore(*store1) && isStore(*store2));
736*03ce13f7SAndroid Build Coastguard Worker 	assert(store1->getStoreAddress() == store2->getStoreAddress());
737*03ce13f7SAndroid Build Coastguard Worker 
738*03ce13f7SAndroid Build Coastguard Worker 	if(store1->getData()->getType() != store2->getData()->getType())
739*03ce13f7SAndroid Build Coastguard Worker 	{
740*03ce13f7SAndroid Build Coastguard Worker 		return false;
741*03ce13f7SAndroid Build Coastguard Worker 	}
742*03ce13f7SAndroid Build Coastguard Worker 
743*03ce13f7SAndroid Build Coastguard Worker 	if(auto *storeSubVector1 = asStoreSubVector(store1))
744*03ce13f7SAndroid Build Coastguard Worker 	{
745*03ce13f7SAndroid Build Coastguard Worker 		if(auto *storeSubVector2 = asStoreSubVector(store2))
746*03ce13f7SAndroid Build Coastguard Worker 		{
747*03ce13f7SAndroid Build Coastguard Worker 			// Check for matching sub-vector width.
748*03ce13f7SAndroid Build Coastguard Worker 			return llvm::cast<Ice::ConstantInteger32>(storeSubVector1->getSrc(2))->getValue() ==
749*03ce13f7SAndroid Build Coastguard Worker 			       llvm::cast<Ice::ConstantInteger32>(storeSubVector2->getSrc(2))->getValue();
750*03ce13f7SAndroid Build Coastguard Worker 		}
751*03ce13f7SAndroid Build Coastguard Worker 	}
752*03ce13f7SAndroid Build Coastguard Worker 
753*03ce13f7SAndroid Build Coastguard Worker 	return true;
754*03ce13f7SAndroid Build Coastguard Worker }
755*03ce13f7SAndroid Build Coastguard Worker 
collectDiagnostics()756*03ce13f7SAndroid Build Coastguard Worker void Optimizer::collectDiagnostics()
757*03ce13f7SAndroid Build Coastguard Worker {
758*03ce13f7SAndroid Build Coastguard Worker 	if(report)
759*03ce13f7SAndroid Build Coastguard Worker 	{
760*03ce13f7SAndroid Build Coastguard Worker 		*report = {};
761*03ce13f7SAndroid Build Coastguard Worker 
762*03ce13f7SAndroid Build Coastguard Worker 		for(auto *basicBlock : function->getNodes())
763*03ce13f7SAndroid Build Coastguard Worker 		{
764*03ce13f7SAndroid Build Coastguard Worker 			for(auto &inst : basicBlock->getInsts())
765*03ce13f7SAndroid Build Coastguard Worker 			{
766*03ce13f7SAndroid Build Coastguard Worker 				if(inst.isDeleted())
767*03ce13f7SAndroid Build Coastguard Worker 				{
768*03ce13f7SAndroid Build Coastguard Worker 					continue;
769*03ce13f7SAndroid Build Coastguard Worker 				}
770*03ce13f7SAndroid Build Coastguard Worker 
771*03ce13f7SAndroid Build Coastguard Worker 				if(llvm::isa<Ice::InstAlloca>(inst))
772*03ce13f7SAndroid Build Coastguard Worker 				{
773*03ce13f7SAndroid Build Coastguard Worker 					report->allocas++;
774*03ce13f7SAndroid Build Coastguard Worker 				}
775*03ce13f7SAndroid Build Coastguard Worker 				else if(isLoad(inst))
776*03ce13f7SAndroid Build Coastguard Worker 				{
777*03ce13f7SAndroid Build Coastguard Worker 					report->loads++;
778*03ce13f7SAndroid Build Coastguard Worker 				}
779*03ce13f7SAndroid Build Coastguard Worker 				else if(isStore(inst))
780*03ce13f7SAndroid Build Coastguard Worker 				{
781*03ce13f7SAndroid Build Coastguard Worker 					report->stores++;
782*03ce13f7SAndroid Build Coastguard Worker 				}
783*03ce13f7SAndroid Build Coastguard Worker 			}
784*03ce13f7SAndroid Build Coastguard Worker 		}
785*03ce13f7SAndroid Build Coastguard Worker 	}
786*03ce13f7SAndroid Build Coastguard Worker }
787*03ce13f7SAndroid Build Coastguard Worker 
getUses(Ice::Operand * operand)788*03ce13f7SAndroid Build Coastguard Worker Optimizer::Uses *Optimizer::getUses(Ice::Operand *operand)
789*03ce13f7SAndroid Build Coastguard Worker {
790*03ce13f7SAndroid Build Coastguard Worker 	Optimizer::Uses *uses = (Optimizer::Uses *)operand->Ice::Operand::getExternalData();
791*03ce13f7SAndroid Build Coastguard Worker 	if(!uses)
792*03ce13f7SAndroid Build Coastguard Worker 	{
793*03ce13f7SAndroid Build Coastguard Worker 		uses = new Optimizer::Uses;
794*03ce13f7SAndroid Build Coastguard Worker 		setUses(operand, uses);
795*03ce13f7SAndroid Build Coastguard Worker 		operandsWithUses.push_back(operand);
796*03ce13f7SAndroid Build Coastguard Worker 	}
797*03ce13f7SAndroid Build Coastguard Worker 	return uses;
798*03ce13f7SAndroid Build Coastguard Worker }
799*03ce13f7SAndroid Build Coastguard Worker 
setUses(Ice::Operand * operand,Optimizer::Uses * uses)800*03ce13f7SAndroid Build Coastguard Worker void Optimizer::setUses(Ice::Operand *operand, Optimizer::Uses *uses)
801*03ce13f7SAndroid Build Coastguard Worker {
802*03ce13f7SAndroid Build Coastguard Worker 	if(auto *oldUses = reinterpret_cast<Optimizer::Uses *>(operand->Ice::Operand::getExternalData()))
803*03ce13f7SAndroid Build Coastguard Worker 	{
804*03ce13f7SAndroid Build Coastguard Worker 		delete oldUses;
805*03ce13f7SAndroid Build Coastguard Worker 	}
806*03ce13f7SAndroid Build Coastguard Worker 
807*03ce13f7SAndroid Build Coastguard Worker 	operand->Ice::Operand::setExternalData(uses);
808*03ce13f7SAndroid Build Coastguard Worker }
809*03ce13f7SAndroid Build Coastguard Worker 
hasUses(Ice::Operand * operand) const810*03ce13f7SAndroid Build Coastguard Worker bool Optimizer::hasUses(Ice::Operand *operand) const
811*03ce13f7SAndroid Build Coastguard Worker {
812*03ce13f7SAndroid Build Coastguard Worker 	return operand->Ice::Operand::getExternalData() != nullptr;
813*03ce13f7SAndroid Build Coastguard Worker }
814*03ce13f7SAndroid Build Coastguard Worker 
getDefinition(Ice::Variable * var)815*03ce13f7SAndroid Build Coastguard Worker Ice::Inst *Optimizer::getDefinition(Ice::Variable *var)
816*03ce13f7SAndroid Build Coastguard Worker {
817*03ce13f7SAndroid Build Coastguard Worker 	return (Ice::Inst *)var->Ice::Variable::getExternalData();
818*03ce13f7SAndroid Build Coastguard Worker }
819*03ce13f7SAndroid Build Coastguard Worker 
setDefinition(Ice::Variable * var,Ice::Inst * inst)820*03ce13f7SAndroid Build Coastguard Worker void Optimizer::setDefinition(Ice::Variable *var, Ice::Inst *inst)
821*03ce13f7SAndroid Build Coastguard Worker {
822*03ce13f7SAndroid Build Coastguard Worker 	var->Ice::Variable::setExternalData(inst);
823*03ce13f7SAndroid Build Coastguard Worker }
824*03ce13f7SAndroid Build Coastguard Worker 
areOnlyLoadStore() const825*03ce13f7SAndroid Build Coastguard Worker bool Optimizer::Uses::areOnlyLoadStore() const
826*03ce13f7SAndroid Build Coastguard Worker {
827*03ce13f7SAndroid Build Coastguard Worker 	return size() == (loads.size() + stores.size());
828*03ce13f7SAndroid Build Coastguard Worker }
829*03ce13f7SAndroid Build Coastguard Worker 
insert(Ice::Operand * value,Ice::Inst * instruction)830*03ce13f7SAndroid Build Coastguard Worker void Optimizer::Uses::insert(Ice::Operand *value, Ice::Inst *instruction)
831*03ce13f7SAndroid Build Coastguard Worker {
832*03ce13f7SAndroid Build Coastguard Worker 	push_back(instruction);
833*03ce13f7SAndroid Build Coastguard Worker 
834*03ce13f7SAndroid Build Coastguard Worker 	if(isLoad(*instruction))
835*03ce13f7SAndroid Build Coastguard Worker 	{
836*03ce13f7SAndroid Build Coastguard Worker 		if(value == instruction->getLoadAddress())
837*03ce13f7SAndroid Build Coastguard Worker 		{
838*03ce13f7SAndroid Build Coastguard Worker 			loads.push_back(instruction);
839*03ce13f7SAndroid Build Coastguard Worker 		}
840*03ce13f7SAndroid Build Coastguard Worker 	}
841*03ce13f7SAndroid Build Coastguard Worker 	else if(isStore(*instruction))
842*03ce13f7SAndroid Build Coastguard Worker 	{
843*03ce13f7SAndroid Build Coastguard Worker 		if(value == instruction->getStoreAddress())
844*03ce13f7SAndroid Build Coastguard Worker 		{
845*03ce13f7SAndroid Build Coastguard Worker 			stores.push_back(instruction);
846*03ce13f7SAndroid Build Coastguard Worker 		}
847*03ce13f7SAndroid Build Coastguard Worker 	}
848*03ce13f7SAndroid Build Coastguard Worker }
849*03ce13f7SAndroid Build Coastguard Worker 
erase(Ice::Inst * instruction)850*03ce13f7SAndroid Build Coastguard Worker void Optimizer::Uses::erase(Ice::Inst *instruction)
851*03ce13f7SAndroid Build Coastguard Worker {
852*03ce13f7SAndroid Build Coastguard Worker 	auto &uses = *this;
853*03ce13f7SAndroid Build Coastguard Worker 
854*03ce13f7SAndroid Build Coastguard Worker 	for(size_t i = 0; i < uses.size(); i++)
855*03ce13f7SAndroid Build Coastguard Worker 	{
856*03ce13f7SAndroid Build Coastguard Worker 		if(uses[i] == instruction)
857*03ce13f7SAndroid Build Coastguard Worker 		{
858*03ce13f7SAndroid Build Coastguard Worker 			uses[i] = back();
859*03ce13f7SAndroid Build Coastguard Worker 			pop_back();
860*03ce13f7SAndroid Build Coastguard Worker 
861*03ce13f7SAndroid Build Coastguard Worker 			for(size_t i = 0; i < loads.size(); i++)
862*03ce13f7SAndroid Build Coastguard Worker 			{
863*03ce13f7SAndroid Build Coastguard Worker 				if(loads[i] == instruction)
864*03ce13f7SAndroid Build Coastguard Worker 				{
865*03ce13f7SAndroid Build Coastguard Worker 					loads[i] = loads.back();
866*03ce13f7SAndroid Build Coastguard Worker 					loads.pop_back();
867*03ce13f7SAndroid Build Coastguard Worker 					break;
868*03ce13f7SAndroid Build Coastguard Worker 				}
869*03ce13f7SAndroid Build Coastguard Worker 			}
870*03ce13f7SAndroid Build Coastguard Worker 
871*03ce13f7SAndroid Build Coastguard Worker 			for(size_t i = 0; i < stores.size(); i++)
872*03ce13f7SAndroid Build Coastguard Worker 			{
873*03ce13f7SAndroid Build Coastguard Worker 				if(stores[i] == instruction)
874*03ce13f7SAndroid Build Coastguard Worker 				{
875*03ce13f7SAndroid Build Coastguard Worker 					stores[i] = stores.back();
876*03ce13f7SAndroid Build Coastguard Worker 					stores.pop_back();
877*03ce13f7SAndroid Build Coastguard Worker 					break;
878*03ce13f7SAndroid Build Coastguard Worker 				}
879*03ce13f7SAndroid Build Coastguard Worker 			}
880*03ce13f7SAndroid Build Coastguard Worker 
881*03ce13f7SAndroid Build Coastguard Worker 			break;
882*03ce13f7SAndroid Build Coastguard Worker 		}
883*03ce13f7SAndroid Build Coastguard Worker 	}
884*03ce13f7SAndroid Build Coastguard Worker }
885*03ce13f7SAndroid Build Coastguard Worker 
886*03ce13f7SAndroid Build Coastguard Worker }  // anonymous namespace
887*03ce13f7SAndroid Build Coastguard Worker 
888*03ce13f7SAndroid Build Coastguard Worker namespace rr {
889*03ce13f7SAndroid Build Coastguard Worker 
optimize(Ice::Cfg * function,Nucleus::OptimizerReport * report)890*03ce13f7SAndroid Build Coastguard Worker void optimize(Ice::Cfg *function, Nucleus::OptimizerReport *report)
891*03ce13f7SAndroid Build Coastguard Worker {
892*03ce13f7SAndroid Build Coastguard Worker 	Optimizer optimizer(report);
893*03ce13f7SAndroid Build Coastguard Worker 
894*03ce13f7SAndroid Build Coastguard Worker 	optimizer.run(function);
895*03ce13f7SAndroid Build Coastguard Worker }
896*03ce13f7SAndroid Build Coastguard Worker 
897*03ce13f7SAndroid Build Coastguard Worker }  // namespace rr
898