• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "Optimizer.hpp"
16 
17 #include "src/IceCfg.h"
18 #include "src/IceCfgNode.h"
19 
20 #include <vector>
21 
22 namespace
23 {
24 	class Optimizer
25 	{
26 	public:
27 		void run(Ice::Cfg *function);
28 
29 	private:
30 		void analyzeUses(Ice::Cfg *function);
31 		void eliminateDeadCode();
32 		void eliminateUnitializedLoads();
33 		void eliminateLoadsFollowingSingleStore();
34 		void optimizeStoresInSingleBasicBlock();
35 
36 		void replace(Ice::Inst *instruction, Ice::Operand *newValue);
37 		void deleteInstruction(Ice::Inst *instruction);
38 		bool isDead(Ice::Inst *instruction);
39 
40 		static const Ice::InstIntrinsicCall *asLoadSubVector(const Ice::Inst *instruction);
41 		static const Ice::InstIntrinsicCall *asStoreSubVector(const Ice::Inst *instruction);
42 		static bool isLoad(const Ice::Inst &instruction);
43 		static bool isStore(const Ice::Inst &instruction);
44 		static Ice::Operand *storeAddress(const Ice::Inst *instruction);
45 		static Ice::Operand *loadAddress(const Ice::Inst *instruction);
46 		static Ice::Operand *storeData(const Ice::Inst *instruction);
47 		static std::size_t storeSize(const Ice::Inst *instruction);
48 		static bool loadTypeMatchesStore(const Ice::Inst *load, const Ice::Inst *store);
49 
50 		Ice::Cfg *function;
51 		Ice::GlobalContext *context;
52 
53 		struct Uses : std::vector<Ice::Inst*>
54 		{
55 			bool areOnlyLoadStore() const;
56 			void insert(Ice::Operand *value, Ice::Inst *instruction);
57 			void erase(Ice::Inst *instruction);
58 
59 			std::vector<Ice::Inst*> loads;
60 			std::vector<Ice::Inst*> stores;
61 		};
62 
63 		struct LoadStoreInst
64 		{
LoadStoreInst__anon5e84af970111::Optimizer::LoadStoreInst65 			LoadStoreInst(Ice::Inst* inst, bool isStore)
66 			  : inst(inst),
67 			    address(isStore ? storeAddress(inst) : loadAddress(inst)),
68 			    isStore(isStore)
69 			{
70 			}
71 
72 			Ice::Inst* inst;
73 			Ice::Operand *address;
74 			bool isStore;
75 		};
76 
77 		Optimizer::Uses* getUses(Ice::Operand*);
78 		void setUses(Ice::Operand*, Optimizer::Uses*);
79 		bool hasUses(Ice::Operand*) const;
80 
81 		Ice::CfgNode* getNode(Ice::Inst*);
82 		void setNode(Ice::Inst*, Ice::CfgNode*);
83 
84 		Ice::Inst* getDefinition(Ice::Variable*);
85 		void setDefinition(Ice::Variable*, Ice::Inst*);
86 
87 		const std::vector<LoadStoreInst>& getLoadStoreInsts(Ice::CfgNode*);
88 		void setLoadStoreInsts(Ice::CfgNode*, std::vector<LoadStoreInst>*);
89 		bool hasLoadStoreInsts(Ice::CfgNode* node) const;
90 
91 		std::vector<Optimizer::Uses*> allocatedUses;
92 	};
93 
run(Ice::Cfg * function)94 	void Optimizer::run(Ice::Cfg *function)
95 	{
96 		this->function = function;
97 		this->context = function->getContext();
98 
99 		analyzeUses(function);
100 
101 		eliminateDeadCode();
102 		eliminateUnitializedLoads();
103 		eliminateLoadsFollowingSingleStore();
104 		optimizeStoresInSingleBasicBlock();
105 		eliminateDeadCode();
106 
107 		for(auto uses : allocatedUses)
108 		{
109 			delete uses;
110 		}
111 		allocatedUses.clear();
112 	}
113 
eliminateDeadCode()114 	void Optimizer::eliminateDeadCode()
115 	{
116 		bool modified;
117 		do
118 		{
119 			modified = false;
120 			for(Ice::CfgNode *basicBlock : function->getNodes())
121 			{
122 				for(Ice::Inst &inst : Ice::reverse_range(basicBlock->getInsts()))
123 				{
124 					if(inst.isDeleted())
125 					{
126 						continue;
127 					}
128 
129 					if(isDead(&inst))
130 					{
131 						deleteInstruction(&inst);
132 						modified = true;
133 					}
134 				}
135 			}
136 		}
137 		while(modified);
138 	}
139 
eliminateUnitializedLoads()140 	void Optimizer::eliminateUnitializedLoads()
141 	{
142 		Ice::CfgNode *entryBlock = function->getEntryNode();
143 
144 		for(Ice::Inst &alloca : entryBlock->getInsts())
145 		{
146 			if(alloca.isDeleted())
147 			{
148 				continue;
149 			}
150 
151 			if(!llvm::isa<Ice::InstAlloca>(alloca))
152 			{
153 				break;   // Allocas are all at the top
154 			}
155 
156 			Ice::Operand *address = alloca.getDest();
157 
158 			if(!hasUses(address))
159 			{
160 				continue;
161 			}
162 
163 			const auto &addressUses = *getUses(address);
164 
165 			if(!addressUses.areOnlyLoadStore())
166 			{
167 				continue;
168 			}
169 
170 			if(addressUses.stores.empty())
171 			{
172 				for(Ice::Inst *load : addressUses.loads)
173 				{
174 					Ice::Variable *loadData = load->getDest();
175 
176 					if(hasUses(loadData))
177 					{
178 						for(Ice::Inst *use : *getUses(loadData))
179 						{
180 							for(Ice::SizeT i = 0; i < use->getSrcSize(); i++)
181 							{
182 								if(use->getSrc(i) == loadData)
183 								{
184 									auto *undef = context->getConstantUndef(loadData->getType());
185 
186 									use->replaceSource(i, undef);
187 								}
188 							}
189 						}
190 
191 						setUses(loadData, nullptr);
192 					}
193 
194 					load->setDeleted();
195 				}
196 
197 				alloca.setDeleted();
198 				setUses(address, nullptr);
199 			}
200 		}
201 	}
202 
eliminateLoadsFollowingSingleStore()203 	void Optimizer::eliminateLoadsFollowingSingleStore()
204 	{
205 		Ice::CfgNode *entryBlock = function->getEntryNode();
206 
207 		for(Ice::Inst &alloca : entryBlock->getInsts())
208 		{
209 			if(alloca.isDeleted())
210 			{
211 				continue;
212 			}
213 
214 			if(!llvm::isa<Ice::InstAlloca>(alloca))
215 			{
216 				break;   // Allocas are all at the top
217 			}
218 
219 			Ice::Operand *address = alloca.getDest();
220 
221 			if(!hasUses(address))
222 			{
223 				continue;
224 			}
225 
226 			auto &addressUses = *getUses(address);
227 
228 			if(!addressUses.areOnlyLoadStore())
229 			{
230 				continue;
231 			}
232 
233 			if(addressUses.stores.size() == 1)
234 			{
235 				Ice::Inst *store = addressUses.stores[0];
236 				Ice::Operand *storeValue = storeData(store);
237 
238 				for(Ice::Inst *load = &*++store->getIterator(), *next = nullptr; load != next; next = load, load = &*++store->getIterator())
239 				{
240 					if(load->isDeleted() || !isLoad(*load))
241 					{
242 						continue;
243 					}
244 
245 					if(loadAddress(load) != address)
246 					{
247 						continue;
248 					}
249 
250 					if(!loadTypeMatchesStore(load, store))
251 					{
252 						continue;
253 					}
254 
255 					replace(load, storeValue);
256 
257 					for(size_t i = 0; i < addressUses.loads.size(); i++)
258 					{
259 						if(addressUses.loads[i] == load)
260 						{
261 							addressUses.loads[i] = addressUses.loads.back();
262 							addressUses.loads.pop_back();
263 							break;
264 						}
265 					}
266 
267 					for(size_t i = 0; i < addressUses.size(); i++)
268 					{
269 						if(addressUses[i] == load)
270 						{
271 							addressUses[i] = addressUses.back();
272 							addressUses.pop_back();
273 							break;
274 						}
275 					}
276 
277 					if(addressUses.size() == 1)
278 					{
279 						assert(addressUses[0] == store);
280 
281 						alloca.setDeleted();
282 						store->setDeleted();
283 						setUses(address, nullptr);
284 
285 						if(hasUses(storeValue))
286 						{
287 							auto &valueUses = *getUses(storeValue);
288 
289 							for(size_t i = 0; i < valueUses.size(); i++)
290 							{
291 								if(valueUses[i] == store)
292 								{
293 									valueUses[i] = valueUses.back();
294 									valueUses.pop_back();
295 									break;
296 								}
297 							}
298 
299 							if(valueUses.empty())
300 							{
301 								setUses(storeValue, nullptr);
302 							}
303 						}
304 
305 						break;
306 					}
307 				}
308 			}
309 		}
310 	}
311 
optimizeStoresInSingleBasicBlock()312 	void Optimizer::optimizeStoresInSingleBasicBlock()
313 	{
314 		Ice::CfgNode *entryBlock = function->getEntryNode();
315 
316 		std::vector<std::vector<LoadStoreInst>* > allocatedVectors;
317 
318 		for(Ice::Inst &alloca : entryBlock->getInsts())
319 		{
320 			if(alloca.isDeleted())
321 			{
322 				continue;
323 			}
324 
325 			if(!llvm::isa<Ice::InstAlloca>(alloca))
326 			{
327 				break;   // Allocas are all at the top
328 			}
329 
330 			Ice::Operand *address = alloca.getDest();
331 
332 			if(!hasUses(address))
333 			{
334 				continue;
335 			}
336 
337 			const auto &addressUses = *getUses(address);
338 
339 			if(!addressUses.areOnlyLoadStore())
340 			{
341 				continue;
342 			}
343 
344 			Ice::CfgNode *singleBasicBlock = getNode(addressUses.stores[0]);
345 
346 			for(size_t i = 1; i < addressUses.stores.size(); i++)
347 			{
348 				Ice::Inst *store = addressUses.stores[i];
349 				if(getNode(store) != singleBasicBlock)
350 				{
351 					singleBasicBlock = nullptr;
352 					break;
353 				}
354 			}
355 
356 			if(singleBasicBlock)
357 			{
358 				if(!hasLoadStoreInsts(singleBasicBlock))
359 				{
360 					std::vector<LoadStoreInst>* loadStoreInstVector = new std::vector<LoadStoreInst>();
361 					setLoadStoreInsts(singleBasicBlock, loadStoreInstVector);
362 					allocatedVectors.push_back(loadStoreInstVector);
363 					for(Ice::Inst &inst : singleBasicBlock->getInsts())
364 					{
365 						if(inst.isDeleted())
366 						{
367 							continue;
368 						}
369 
370 						bool isStoreInst = isStore(inst);
371 						bool isLoadInst = isLoad(inst);
372 
373 						if(isStoreInst || isLoadInst)
374 						{
375 							loadStoreInstVector->push_back(LoadStoreInst(&inst, isStoreInst));
376 						}
377 					}
378 				}
379 
380 				Ice::Inst *store = nullptr;
381 				Ice::Operand *storeValue = nullptr;
382 				bool unmatchedLoads = false;
383 
384 				for (auto& loadStoreInst : getLoadStoreInsts(singleBasicBlock))
385 				{
386 					Ice::Inst* inst = loadStoreInst.inst;
387 
388 					if((loadStoreInst.address != address) || inst->isDeleted())
389 					{
390 						continue;
391 					}
392 
393 					if(loadStoreInst.isStore)
394 					{
395 						// New store found. If we had a previous one, try to eliminate it.
396 						if(store && !unmatchedLoads)
397 						{
398 							// If the previous store is wider than the new one, we can't eliminate it
399 							// because there could be a wide load reading its non-overwritten data.
400 							if(storeSize(inst) >= storeSize(store))
401 							{
402 								deleteInstruction(store);
403 							}
404 						}
405 
406 						store = inst;
407 						storeValue = storeData(store);
408 						unmatchedLoads = false;
409 					}
410 					else
411 					{
412 						if(!loadTypeMatchesStore(inst, store))
413 						{
414 							unmatchedLoads = true;
415 							continue;
416 						}
417 
418 						replace(inst, storeValue);
419 					}
420 				}
421 			}
422 		}
423 
424 		for(auto loadStoreInstVector : allocatedVectors)
425 		{
426 			delete loadStoreInstVector;
427 		}
428 	}
429 
analyzeUses(Ice::Cfg * function)430 	void Optimizer::analyzeUses(Ice::Cfg *function)
431 	{
432 		for(Ice::CfgNode *basicBlock : function->getNodes())
433 		{
434 			for(Ice::Inst &instruction : basicBlock->getInsts())
435 			{
436 				if(instruction.isDeleted())
437 				{
438 					continue;
439 				}
440 
441 				setNode(&instruction, basicBlock);
442 				if(instruction.getDest())
443 				{
444 					setDefinition(instruction.getDest(), &instruction);
445 				}
446 
447 				for(Ice::SizeT i = 0; i < instruction.getSrcSize(); i++)
448 				{
449 					Ice::SizeT unique = 0;
450 					for(; unique < i; unique++)
451 					{
452 						if(instruction.getSrc(i) == instruction.getSrc(unique))
453 						{
454 							break;
455 						}
456 					}
457 
458 					if(i == unique)
459 					{
460 						Ice::Operand *src = instruction.getSrc(i);
461 						getUses(src)->insert(src, &instruction);
462 					}
463 				}
464 			}
465 		}
466 	}
467 
replace(Ice::Inst * instruction,Ice::Operand * newValue)468 	void Optimizer::replace(Ice::Inst *instruction, Ice::Operand *newValue)
469 	{
470 		Ice::Variable *oldValue = instruction->getDest();
471 
472 		if(!newValue)
473 		{
474 			newValue = context->getConstantUndef(oldValue->getType());
475 		}
476 
477 		if(hasUses(oldValue))
478 		{
479 			for(Ice::Inst *use : *getUses(oldValue))
480 			{
481 				assert(!use->isDeleted());   // Should have been removed from uses already
482 
483 				for(Ice::SizeT i = 0; i < use->getSrcSize(); i++)
484 				{
485 					if(use->getSrc(i) == oldValue)
486 					{
487 						use->replaceSource(i, newValue);
488 					}
489 				}
490 
491 				getUses(newValue)->insert(newValue, use);
492 			}
493 
494 			setUses(oldValue, nullptr);
495 		}
496 
497 		deleteInstruction(instruction);
498 	}
499 
deleteInstruction(Ice::Inst * instruction)500 	void Optimizer::deleteInstruction(Ice::Inst *instruction)
501 	{
502 		if(!instruction || instruction->isDeleted())
503 		{
504 			return;
505 		}
506 
507 		instruction->setDeleted();
508 
509 		for(Ice::SizeT i = 0; i < instruction->getSrcSize(); i++)
510 		{
511 			Ice::Operand *src = instruction->getSrc(i);
512 
513 			if(hasUses(src))
514 			{
515 				auto &srcUses = *getUses(src);
516 
517 				srcUses.erase(instruction);
518 
519 				if(srcUses.empty())
520 				{
521 					setUses(src, nullptr);
522 
523 					if(Ice::Variable *var = llvm::dyn_cast<Ice::Variable>(src))
524 					{
525 						deleteInstruction(getDefinition(var));
526 					}
527 				}
528 			}
529 		}
530 	}
531 
isDead(Ice::Inst * instruction)532 	bool Optimizer::isDead(Ice::Inst *instruction)
533 	{
534 		Ice::Variable *dest = instruction->getDest();
535 
536 		if(dest)
537 		{
538 			return (!hasUses(dest) || getUses(dest)->empty()) && !instruction->hasSideEffects();
539 		}
540 		else if(isStore(*instruction))
541 		{
542 			if(Ice::Variable *address = llvm::dyn_cast<Ice::Variable>(storeAddress(instruction)))
543 			{
544 				Ice::Inst *def = getDefinition(address);
545 
546 				if(def && llvm::isa<Ice::InstAlloca>(def))
547 				{
548 					if(hasUses(address))
549 					{
550 						Optimizer::Uses* uses = getUses(address);
551 						return uses->size() == uses->stores.size();   // Dead if all uses are stores
552 					}
553 					else
554 					{
555 						return true; // No uses
556 					}
557 				}
558 			}
559 		}
560 
561 		return false;
562 	}
563 
asLoadSubVector(const Ice::Inst * instruction)564 	const Ice::InstIntrinsicCall *Optimizer::asLoadSubVector(const Ice::Inst *instruction)
565 	{
566 		if(auto *instrinsic = llvm::dyn_cast<Ice::InstIntrinsicCall>(instruction))
567 		{
568 			if(instrinsic->getIntrinsicInfo().ID == Ice::Intrinsics::LoadSubVector)
569 			{
570 				return instrinsic;
571 			}
572 		}
573 
574 		return nullptr;
575 	}
576 
asStoreSubVector(const Ice::Inst * instruction)577 	const Ice::InstIntrinsicCall *Optimizer::asStoreSubVector(const Ice::Inst *instruction)
578 	{
579 		if(auto *instrinsic = llvm::dyn_cast<Ice::InstIntrinsicCall>(instruction))
580 		{
581 			if(instrinsic->getIntrinsicInfo().ID == Ice::Intrinsics::StoreSubVector)
582 			{
583 				return instrinsic;
584 			}
585 		}
586 
587 		return nullptr;
588 	}
589 
isLoad(const Ice::Inst & instruction)590 	bool Optimizer::isLoad(const Ice::Inst &instruction)
591 	{
592 		if(llvm::isa<Ice::InstLoad>(&instruction))
593 		{
594 			return true;
595 		}
596 
597 		return asLoadSubVector(&instruction) != nullptr;
598 	}
599 
isStore(const Ice::Inst & instruction)600 	bool Optimizer::isStore(const Ice::Inst &instruction)
601 	{
602 		if(llvm::isa<Ice::InstStore>(&instruction))
603 		{
604 			return true;
605 		}
606 
607 		return asStoreSubVector(&instruction) != nullptr;
608 	}
609 
storeAddress(const Ice::Inst * instruction)610 	Ice::Operand *Optimizer::storeAddress(const Ice::Inst *instruction)
611 	{
612 		assert(isStore(*instruction));
613 
614 		if(auto *store = llvm::dyn_cast<Ice::InstStore>(instruction))
615 		{
616 			return store->getAddr();
617 		}
618 
619 		if(auto *storeSubVector = asStoreSubVector(instruction))
620 		{
621 			return storeSubVector->getSrc(2);
622 		}
623 
624 		return nullptr;
625 	}
626 
loadAddress(const Ice::Inst * instruction)627 	Ice::Operand *Optimizer::loadAddress(const Ice::Inst *instruction)
628 	{
629 		assert(isLoad(*instruction));
630 
631 		if(auto *load = llvm::dyn_cast<Ice::InstLoad>(instruction))
632 		{
633 			return load->getSourceAddress();
634 		}
635 
636 		if(auto *loadSubVector = asLoadSubVector(instruction))
637 		{
638 			return loadSubVector->getSrc(1);
639 		}
640 
641 		return nullptr;
642 	}
643 
storeData(const Ice::Inst * instruction)644 	Ice::Operand *Optimizer::storeData(const Ice::Inst *instruction)
645 	{
646 		assert(isStore(*instruction));
647 
648 		if(auto *store = llvm::dyn_cast<Ice::InstStore>(instruction))
649 		{
650 			return store->getData();
651 		}
652 
653 		if(auto *storeSubVector = asStoreSubVector(instruction))
654 		{
655 			return storeSubVector->getSrc(1);
656 		}
657 
658 		return nullptr;
659 	}
660 
storeSize(const Ice::Inst * store)661 	std::size_t Optimizer::storeSize(const Ice::Inst *store)
662 	{
663 		assert(isStore(*store));
664 
665 		if(auto *instStore = llvm::dyn_cast<Ice::InstStore>(store))
666 		{
667 			return Ice::typeWidthInBytes(instStore->getData()->getType());
668 		}
669 
670 		if(auto *storeSubVector = asStoreSubVector(store))
671 		{
672 			return llvm::cast<Ice::ConstantInteger32>(storeSubVector->getSrc(3))->getValue();
673 		}
674 
675 		return 0;
676 	}
677 
loadTypeMatchesStore(const Ice::Inst * load,const Ice::Inst * store)678 	bool Optimizer::loadTypeMatchesStore(const Ice::Inst *load, const Ice::Inst *store)
679 	{
680 		if(!load || !store)
681 		{
682 			return false;
683 		}
684 
685 		assert(isLoad(*load) && isStore(*store));
686 		assert(loadAddress(load) == storeAddress(store));
687 
688 		if(auto *instStore = llvm::dyn_cast<Ice::InstStore>(store))
689 		{
690 			if(auto *instLoad = llvm::dyn_cast<Ice::InstLoad>(load))
691 			{
692 				return instStore->getData()->getType() == instLoad->getDest()->getType();
693 			}
694 		}
695 
696 		if(auto *storeSubVector = asStoreSubVector(store))
697 		{
698 			if(auto *loadSubVector = asLoadSubVector(load))
699 			{
700 				// Check for matching type and sub-vector width.
701 				return storeSubVector->getSrc(1)->getType() == loadSubVector->getDest()->getType() &&
702 				       llvm::cast<Ice::ConstantInteger32>(storeSubVector->getSrc(3))->getValue() ==
703 				       llvm::cast<Ice::ConstantInteger32>(loadSubVector->getSrc(2))->getValue();
704 			}
705 		}
706 
707 		return false;
708 	}
709 
getUses(Ice::Operand * operand)710 	Optimizer::Uses* Optimizer::getUses(Ice::Operand* operand)
711 	{
712 		Optimizer::Uses* uses = (Optimizer::Uses*)operand->Ice::Operand::getExternalData();
713 		if(!uses)
714 		{
715 			uses = new Optimizer::Uses;
716 			setUses(operand, uses);
717 			allocatedUses.push_back(uses);
718 		}
719 		return uses;
720 	}
721 
setUses(Ice::Operand * operand,Optimizer::Uses * uses)722 	void Optimizer::setUses(Ice::Operand* operand, Optimizer::Uses* uses)
723 	{
724 		operand->Ice::Operand::setExternalData(uses);
725 	}
726 
hasUses(Ice::Operand * operand) const727 	bool Optimizer::hasUses(Ice::Operand* operand) const
728 	{
729 		return operand->Ice::Operand::getExternalData() != nullptr;
730 	}
731 
getNode(Ice::Inst * inst)732 	Ice::CfgNode* Optimizer::getNode(Ice::Inst* inst)
733 	{
734 		return (Ice::CfgNode*)inst->Ice::Inst::getExternalData();
735 	}
736 
setNode(Ice::Inst * inst,Ice::CfgNode * node)737 	void Optimizer::setNode(Ice::Inst* inst, Ice::CfgNode* node)
738 	{
739 		inst->Ice::Inst::setExternalData(node);
740 	}
741 
getDefinition(Ice::Variable * var)742 	Ice::Inst* Optimizer::getDefinition(Ice::Variable* var)
743 	{
744 		return (Ice::Inst*)var->Ice::Variable::getExternalData();
745 	}
746 
setDefinition(Ice::Variable * var,Ice::Inst * inst)747 	void Optimizer::setDefinition(Ice::Variable* var, Ice::Inst* inst)
748 	{
749 		var->Ice::Variable::setExternalData(inst);
750 	}
751 
getLoadStoreInsts(Ice::CfgNode * node)752 	const std::vector<Optimizer::LoadStoreInst>& Optimizer::getLoadStoreInsts(Ice::CfgNode* node)
753 	{
754 		return *((const std::vector<LoadStoreInst>*)node->Ice::CfgNode::getExternalData());
755 	}
756 
setLoadStoreInsts(Ice::CfgNode * node,std::vector<LoadStoreInst> * insts)757 	void Optimizer::setLoadStoreInsts(Ice::CfgNode* node, std::vector<LoadStoreInst>* insts)
758 	{
759 		node->Ice::CfgNode::setExternalData(insts);
760 	}
761 
hasLoadStoreInsts(Ice::CfgNode * node) const762 	bool Optimizer::hasLoadStoreInsts(Ice::CfgNode* node) const
763 	{
764 		return node->Ice::CfgNode::getExternalData() != nullptr;
765 	}
766 
areOnlyLoadStore() const767 	bool Optimizer::Uses::areOnlyLoadStore() const
768 	{
769 		return size() == (loads.size() + stores.size());
770 	}
771 
insert(Ice::Operand * value,Ice::Inst * instruction)772 	void Optimizer::Uses::insert(Ice::Operand *value, Ice::Inst *instruction)
773 	{
774 		push_back(instruction);
775 
776 		if(isLoad(*instruction))
777 		{
778 			if(value == loadAddress(instruction))
779 			{
780 				loads.push_back(instruction);
781 			}
782 		}
783 		else if(isStore(*instruction))
784 		{
785 			if(value == storeAddress(instruction))
786 			{
787 				stores.push_back(instruction);
788 			}
789 		}
790 	}
791 
erase(Ice::Inst * instruction)792 	void Optimizer::Uses::erase(Ice::Inst *instruction)
793 	{
794 		auto &uses = *this;
795 
796 		for(size_t i = 0; i < uses.size(); i++)
797 		{
798 			if(uses[i] == instruction)
799 			{
800 				uses[i] = back();
801 				pop_back();
802 
803 				for(size_t i = 0; i < loads.size(); i++)
804 				{
805 					if(loads[i] == instruction)
806 					{
807 						loads[i] = loads.back();
808 						loads.pop_back();
809 						break;
810 					}
811 				}
812 
813 				for(size_t i = 0; i < stores.size(); i++)
814 				{
815 					if(stores[i] == instruction)
816 					{
817 						stores[i] = stores.back();
818 						stores.pop_back();
819 						break;
820 					}
821 				}
822 
823 				break;
824 			}
825 		}
826 	}
827 }
828 
829 namespace rr
830 {
optimize(Ice::Cfg * function)831 	void optimize(Ice::Cfg *function)
832 	{
833 		Optimizer optimizer;
834 
835 		optimizer.run(function);
836 	}
837 }