blob: 7cc3540e1a4dcaa921a40551eedba2aa4fe1833f [file] [log] [blame]
Nicolas Capens2ae9d742016-11-24 14:43:05 -05001// 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
Nicolas Capens2ae9d742016-11-24 14:43:05 -050020#include <vector>
21
Nicolas Capens157ba262019-12-10 17:49:14 -050022namespace {
23
24class Optimizer
Nicolas Capens2ae9d742016-11-24 14:43:05 -050025{
Nicolas Capens157ba262019-12-10 17:49:14 -050026public:
27 void run(Ice::Cfg *function);
28
29private:
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*>
Nicolas Capens2ae9d742016-11-24 14:43:05 -050054 {
Nicolas Capens157ba262019-12-10 17:49:14 -050055 bool areOnlyLoadStore() const;
56 void insert(Ice::Operand *value, Ice::Inst *instruction);
57 void erase(Ice::Inst *instruction);
Nicolas Capens2ae9d742016-11-24 14:43:05 -050058
Nicolas Capens157ba262019-12-10 17:49:14 -050059 std::vector<Ice::Inst*> loads;
60 std::vector<Ice::Inst*> stores;
Nicolas Capens2ae9d742016-11-24 14:43:05 -050061 };
62
Nicolas Capens157ba262019-12-10 17:49:14 -050063 struct LoadStoreInst
Nicolas Capens2ae9d742016-11-24 14:43:05 -050064 {
Nicolas Capens157ba262019-12-10 17:49:14 -050065 LoadStoreInst(Ice::Inst* inst, bool isStore)
66 : inst(inst),
67 address(isStore ? storeAddress(inst) : loadAddress(inst)),
68 isStore(isStore)
Alexis Hetu932640b2018-06-20 15:35:53 -040069 {
Alexis Hetu932640b2018-06-20 15:35:53 -040070 }
Nicolas Capens2ae9d742016-11-24 14:43:05 -050071
Nicolas Capens157ba262019-12-10 17:49:14 -050072 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
94void 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)
Nicolas Capens2ae9d742016-11-24 14:43:05 -0500108 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500109 delete uses;
110 }
111 allocatedUses.clear();
112}
113
114void Optimizer::eliminateDeadCode()
115{
116 bool modified;
117 do
118 {
119 modified = false;
120 for(Ice::CfgNode *basicBlock : function->getNodes())
Nicolas Capens2ae9d742016-11-24 14:43:05 -0500121 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500122 for(Ice::Inst &inst : Ice::reverse_range(basicBlock->getInsts()))
Nicolas Capens2ae9d742016-11-24 14:43:05 -0500123 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500124 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
140void 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
203void 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
312void 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())
Nicolas Capensc9d70d52016-12-12 15:07:39 -0500364 {
365 if(inst.isDeleted())
366 {
367 continue;
368 }
Nicolas Capens2ae9d742016-11-24 14:43:05 -0500369
Nicolas Capens157ba262019-12-10 17:49:14 -0500370 bool isStoreInst = isStore(inst);
371 bool isLoadInst = isLoad(inst);
372
373 if(isStoreInst || isLoadInst)
Nicolas Capensc9d70d52016-12-12 15:07:39 -0500374 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500375 loadStoreInstVector->push_back(LoadStoreInst(&inst, isStoreInst));
Nicolas Capensc9d70d52016-12-12 15:07:39 -0500376 }
377 }
Nicolas Capens2ae9d742016-11-24 14:43:05 -0500378 }
Nicolas Capens2ae9d742016-11-24 14:43:05 -0500379
Nicolas Capens157ba262019-12-10 17:49:14 -0500380 Ice::Inst *store = nullptr;
381 Ice::Operand *storeValue = nullptr;
382 bool unmatchedLoads = false;
Nicolas Capensf4452fc2016-12-12 13:08:06 -0500383
Nicolas Capens157ba262019-12-10 17:49:14 -0500384 for (auto& loadStoreInst : getLoadStoreInsts(singleBasicBlock))
Nicolas Capensf4452fc2016-12-12 13:08:06 -0500385 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500386 Ice::Inst* inst = loadStoreInst.inst;
Nicolas Capensf4452fc2016-12-12 13:08:06 -0500387
Nicolas Capens157ba262019-12-10 17:49:14 -0500388 if((loadStoreInst.address != address) || inst->isDeleted())
Nicolas Capens2ae9d742016-11-24 14:43:05 -0500389 {
390 continue;
391 }
392
Nicolas Capens157ba262019-12-10 17:49:14 -0500393 if(loadStoreInst.isStore)
Alexis Hetu932640b2018-06-20 15:35:53 -0400394 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500395 // New store found. If we had a previous one, try to eliminate it.
396 if(store && !unmatchedLoads)
Nicolas Capens2ae9d742016-11-24 14:43:05 -0500397 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500398 // 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))
Nicolas Capens2ae9d742016-11-24 14:43:05 -0500401 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500402 deleteInstruction(store);
Nicolas Capens2ae9d742016-11-24 14:43:05 -0500403 }
404 }
405
Nicolas Capens157ba262019-12-10 17:49:14 -0500406 store = inst;
407 storeValue = storeData(store);
408 unmatchedLoads = false;
409 }
410 else
411 {
412 if(!loadTypeMatchesStore(inst, store))
Nicolas Capens2ae9d742016-11-24 14:43:05 -0500413 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500414 unmatchedLoads = true;
415 continue;
Nicolas Capens2ae9d742016-11-24 14:43:05 -0500416 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500417
418 replace(inst, storeValue);
Nicolas Capens2ae9d742016-11-24 14:43:05 -0500419 }
420 }
421 }
422 }
Nicolas Capensf4452fc2016-12-12 13:08:06 -0500423
Nicolas Capens157ba262019-12-10 17:49:14 -0500424 for(auto loadStoreInstVector : allocatedVectors)
Nicolas Capense205c3d2016-11-30 15:14:28 -0500425 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500426 delete loadStoreInstVector;
427 }
428}
Nicolas Capense205c3d2016-11-30 15:14:28 -0500429
Nicolas Capens157ba262019-12-10 17:49:14 -0500430void Optimizer::analyzeUses(Ice::Cfg *function)
431{
432 for(Ice::CfgNode *basicBlock : function->getNodes())
433 {
434 for(Ice::Inst &instruction : basicBlock->getInsts())
Nicolas Capense205c3d2016-11-30 15:14:28 -0500435 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500436 if(instruction.isDeleted())
Nicolas Capense205c3d2016-11-30 15:14:28 -0500437 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500438 continue;
439 }
Alexis Hetu932640b2018-06-20 15:35:53 -0400440
Nicolas Capens157ba262019-12-10 17:49:14 -0500441 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++)
Nicolas Capense205c3d2016-11-30 15:14:28 -0500451 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500452 if(instruction.getSrc(i) == instruction.getSrc(unique))
Alexis Hetu932640b2018-06-20 15:35:53 -0400453 {
Nicolas Capensf4452fc2016-12-12 13:08:06 -0500454 break;
455 }
456 }
457
Nicolas Capens157ba262019-12-10 17:49:14 -0500458 if(i == unique)
Nicolas Capensf4452fc2016-12-12 13:08:06 -0500459 {
Nicolas Capens157ba262019-12-10 17:49:14 -0500460 Ice::Operand *src = instruction.getSrc(i);
461 getUses(src)->insert(src, &instruction);
Nicolas Capensf4452fc2016-12-12 13:08:06 -0500462 }
Nicolas Capensf4452fc2016-12-12 13:08:06 -0500463 }
464 }
465 }
Nicolas Capens2ae9d742016-11-24 14:43:05 -0500466}
467
Nicolas Capens157ba262019-12-10 17:49:14 -0500468void Optimizer::replace(Ice::Inst *instruction, Ice::Operand *newValue)
Nicolas Capens2ae9d742016-11-24 14:43:05 -0500469{
Nicolas Capens157ba262019-12-10 17:49:14 -0500470 Ice::Variable *oldValue = instruction->getDest();
Nicolas Capens2ae9d742016-11-24 14:43:05 -0500471
Nicolas Capens157ba262019-12-10 17:49:14 -0500472 if(!newValue)
473 {
474 newValue = context->getConstantUndef(oldValue->getType());
Nicolas Capens2ae9d742016-11-24 14:43:05 -0500475 }
Nicolas Capens157ba262019-12-10 17:49:14 -0500476
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
500void 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
532bool 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
564const 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
577const 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
590bool 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
600bool 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
610Ice::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
627Ice::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
644Ice::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
661std::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
678bool 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
710Optimizer::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
722void Optimizer::setUses(Ice::Operand* operand, Optimizer::Uses* uses)
723{
724 operand->Ice::Operand::setExternalData(uses);
725}
726
727bool Optimizer::hasUses(Ice::Operand* operand) const
728{
729 return operand->Ice::Operand::getExternalData() != nullptr;
730}
731
732Ice::CfgNode* Optimizer::getNode(Ice::Inst* inst)
733{
734 return (Ice::CfgNode*)inst->Ice::Inst::getExternalData();
735}
736
737void Optimizer::setNode(Ice::Inst* inst, Ice::CfgNode* node)
738{
739 inst->Ice::Inst::setExternalData(node);
740}
741
742Ice::Inst* Optimizer::getDefinition(Ice::Variable* var)
743{
744 return (Ice::Inst*)var->Ice::Variable::getExternalData();
745}
746
747void Optimizer::setDefinition(Ice::Variable* var, Ice::Inst* inst)
748{
749 var->Ice::Variable::setExternalData(inst);
750}
751
752const std::vector<Optimizer::LoadStoreInst>& Optimizer::getLoadStoreInsts(Ice::CfgNode* node)
753{
754 return *((const std::vector<LoadStoreInst>*)node->Ice::CfgNode::getExternalData());
755}
756
757void Optimizer::setLoadStoreInsts(Ice::CfgNode* node, std::vector<LoadStoreInst>* insts)
758{
759 node->Ice::CfgNode::setExternalData(insts);
760}
761
762bool Optimizer::hasLoadStoreInsts(Ice::CfgNode* node) const
763{
764 return node->Ice::CfgNode::getExternalData() != nullptr;
765}
766
767bool Optimizer::Uses::areOnlyLoadStore() const
768{
769 return size() == (loads.size() + stores.size());
770}
771
772void 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
792void 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} // anonymous namespace
829
830namespace rr {
831
832void optimize(Ice::Cfg *function)
833{
834 Optimizer optimizer;
835
836 optimizer.run(function);
837}
838
839} // namespace rr