LLVM 22.0.0git
HexagonOptShuffleVector.cpp
Go to the documentation of this file.
1//===---------------------- HexagonOptShuffleVector.cpp -------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Optimize vector shuffles by postponing them as late as possible. The intent
10// here is to remove uncessary shuffles and also increases the oportunities for
11// adjacent shuffles to be merged together.
12//
13//===----------------------------------------------------------------------===//
14
16#include "llvm/ADT/APInt.h"
17#include "llvm/IR/BasicBlock.h"
18#include "llvm/IR/Constants.h"
19#include "llvm/IR/Function.h"
20#include "llvm/IR/IRBuilder.h"
21#include "llvm/IR/Instruction.h"
23#include "llvm/IR/IntrinsicsHexagon.h"
25#include "llvm/IR/Type.h"
26#include "llvm/IR/Value.h"
28#include "llvm/Pass.h"
29
30using namespace llvm;
31using namespace PatternMatch;
32
33#define DEBUG_TYPE "hex-shuff-vec"
34/// A command line argument to limit the search space along def chain.
36 "shuffvec-max-search-count",
37 cl::desc("Maximum number of instructions traversed along def chain."),
38 cl::Hidden, cl::init(15));
39
40#ifndef NDEBUG
41static cl::opt<int>
42 ShuffVecLimit("shuff-vec-max",
43 cl::desc("Maximum number of shuffles to be relocated."),
44 cl::Hidden, cl::init(-1));
45#endif
46
47namespace llvm {
50} // end namespace llvm
51
52namespace {
53
54class HexagonOptShuffleVector : public FunctionPass {
55public:
56 static char ID;
57#ifndef NDEBUG
58 static int NumRelocated;
59#endif
60 HexagonOptShuffleVector() : FunctionPass(ID) {
62 }
63
64 HexagonOptShuffleVector(const HexagonTargetMachine *TM)
65 : FunctionPass(ID), TM(TM) {
67 }
68
69 StringRef getPassName() const override {
70 return "Hexagon Optimize Vector Shuffles";
71 }
72
73 bool runOnFunction(Function &F) override;
74
75 void getAnalysisUsage(AnalysisUsage &AU) const override {
76 FunctionPass::getAnalysisUsage(AU);
77 }
78
79private:
80 using ValueVector = SmallVector<Value *, 8>;
81 const HexagonTargetMachine *TM = nullptr;
82 const HexagonSubtarget *HST = nullptr;
83 SmallPtrSet<Instruction *, 8> Visited;
84 using ShuffUseList =
85 SmallDenseMap<Instruction *, SmallVector<Instruction *, 2>>;
86 ShuffUseList ShuffUses;
87 int DefSearchCount;
88
89 bool visitBlock(BasicBlock *B);
90 bool findNewShuffLoc(Instruction *I, ArrayRef<int> &ShuffMask,
91 Value *&NewLoc);
92 bool isValidIntrinsic(IntrinsicInst *I);
93 bool relocateShuffVec(Instruction *I, ArrayRef<int> &M, Value *NewLoc,
94 std::list<Instruction *> &WorkList);
95 bool getUseList(Instruction *I, ValueVector &UseList);
96 bool analyzeHiLoUse(Instruction *HI, Instruction *LO,
97 ArrayRef<int> &ShuffMask, Value *&NewLoc,
98 ShuffUseList &CurShuffUses);
99 bool isHILo(Value *V, bool IsHI);
100 bool hasDefWithSameShuffMask(Value *V, SmallVector<Instruction *, 2> &ImmUse,
101 ArrayRef<int> &ShuffMask,
102 ShuffUseList &CurShuffUses);
103 void FindHiLoUse(ValueVector &UseList, Instruction *&HI, Instruction *&LO);
104 bool isConcatMask(ArrayRef<int> &Mask, Instruction *ShuffInst);
105 bool isValidUseInstr(ValueVector &UseList, Instruction *&UI);
106 bool areAllOperandsValid(Instruction *I, Instruction *UI,
107 ArrayRef<int> &ShuffMask,
108 ShuffUseList &CurShuffUses);
109 Value *getOperand(Instruction *I, unsigned i);
110 static iterator_range<User::op_iterator> getArgOperands(User *U);
111 static std::pair<Value *, Value *> stripCasts(Value *V);
112 static bool isConstantVectorSplat(Value *V);
113};
114
115} // end anonymous namespace
116
117#ifndef NDEBUG
118int HexagonOptShuffleVector::NumRelocated = 0;
119#endif
120char HexagonOptShuffleVector::ID = 0;
121
122INITIALIZE_PASS_BEGIN(HexagonOptShuffleVector, "shuff-vec",
123 "Hexagon Optimize Shuffle Vector", false, false)
125INITIALIZE_PASS_END(HexagonOptShuffleVector, "shuff-vec",
126 "Hexagon Optimize Shuffle Vector", false, false)
127
128bool HexagonOptShuffleVector::isConcatMask(ArrayRef<int> &Mask,
129 Instruction *ShuffInst) {
130 Type *ShuffTy = ShuffInst->getType();
131 int NumElts = cast<FixedVectorType>(ShuffTy)->getNumElements();
132 for (int i = 0; i < NumElts; i++) {
133 if (Mask[i] != i)
134 return false;
135 }
136 return true;
137}
138
139bool HexagonOptShuffleVector::isValidIntrinsic(IntrinsicInst *I) {
140 switch (I->getIntrinsicID()) {
141 default:
142 return false;
143 case Intrinsic::hexagon_V6_vaddubh_128B:
144 case Intrinsic::hexagon_V6_vadduhw_128B:
145 case Intrinsic::hexagon_V6_vaddhw_128B:
146 case Intrinsic::hexagon_V6_vaddh_dv_128B:
147 case Intrinsic::hexagon_V6_vsububh_128B:
148 case Intrinsic::hexagon_V6_vsubuhw_128B:
149 case Intrinsic::hexagon_V6_vsubhw_128B:
150 case Intrinsic::hexagon_V6_vsubh_dv_128B:
151 case Intrinsic::hexagon_V6_vmpyubv_128B:
152 case Intrinsic::hexagon_V6_vmpybv_128B:
153 case Intrinsic::hexagon_V6_vmpyuhv_128B:
154 case Intrinsic::hexagon_V6_vmpyhv_128B:
155 case Intrinsic::hexagon_V6_vmpybusv_128B:
156 case Intrinsic::hexagon_V6_vmpyhus_128B:
157 case Intrinsic::hexagon_V6_vavgb_128B:
158 case Intrinsic::hexagon_V6_vavgub_128B:
159 case Intrinsic::hexagon_V6_vavgh_128B:
160 case Intrinsic::hexagon_V6_vavguh_128B:
161 case Intrinsic::hexagon_V6_vavgw_128B:
162 case Intrinsic::hexagon_V6_vavguw_128B:
163 case Intrinsic::hexagon_V6_hi_128B:
164 case Intrinsic::hexagon_V6_lo_128B:
165 case Intrinsic::sadd_sat:
166 case Intrinsic::uadd_sat:
167 // Generic hexagon vector intrinsics
168 case Intrinsic::hexagon_vadd_su:
169 case Intrinsic::hexagon_vadd_uu:
170 case Intrinsic::hexagon_vadd_ss:
171 case Intrinsic::hexagon_vadd_us:
172 case Intrinsic::hexagon_vsub_su:
173 case Intrinsic::hexagon_vsub_uu:
174 case Intrinsic::hexagon_vsub_ss:
175 case Intrinsic::hexagon_vsub_us:
176 case Intrinsic::hexagon_vmpy_su:
177 case Intrinsic::hexagon_vmpy_uu:
178 case Intrinsic::hexagon_vmpy_ss:
179 case Intrinsic::hexagon_vmpy_us:
180 case Intrinsic::hexagon_vavgu:
181 case Intrinsic::hexagon_vavgs:
182 case Intrinsic::hexagon_vmpy_ub_b:
183 case Intrinsic::hexagon_vmpy_ub_ub:
184 case Intrinsic::hexagon_vmpy_uh_uh:
185 case Intrinsic::hexagon_vmpy_h_h:
186 return true;
187 }
188 llvm_unreachable("Unsupported instruction!");
189}
190
191bool HexagonOptShuffleVector::getUseList(Instruction *I, ValueVector &UseList) {
192 for (auto UI = I->user_begin(), UE = I->user_end(); UI != UE;) {
194 if (!J)
195 return false;
196 if (auto *C = dyn_cast<CastInst>(*UI)) {
197 if (!getUseList(C, UseList))
198 return false;
199 } else
200 UseList.push_back(*UI);
201 ++UI;
202 }
203 return true;
204}
205
206bool HexagonOptShuffleVector::isHILo(Value *V, bool IsHI) {
207 if (!(dyn_cast<Instruction>(V)))
208 return false;
210 if (!isa<CallInst>(I))
211 return false;
212 IntrinsicInst *II = dyn_cast<IntrinsicInst>(I);
213 if (!II)
214 return false;
215 if ((II->getIntrinsicID() == Intrinsic::hexagon_V6_hi_128B && IsHI) ||
216 (II->getIntrinsicID() == Intrinsic::hexagon_V6_lo_128B && !IsHI))
217 return true;
218 return false;
219}
220
221Value *HexagonOptShuffleVector::getOperand(Instruction *I, unsigned i) {
222 Value *V = I->getOperand(i);
223 if (auto *C = dyn_cast<CastInst>(V))
224 return C->getOperand(0);
225 return V;
226}
227
229HexagonOptShuffleVector::getArgOperands(User *U) {
230 if (auto *CB = dyn_cast<CallBase>(U))
231 return CB->args();
232 return U->operands();
233}
234
235// Strip out all the cast operations to find the first non-cast definition of a
236// value. The function also returns the last cast operation in the def-chain.
237std::pair<Value *, Value *> HexagonOptShuffleVector::stripCasts(Value *V) {
238 Value *LastCast = nullptr;
239 while (auto *C = dyn_cast<CastInst>(V)) {
240 LastCast = V;
241 V = C->getOperand(0);
242 }
243 return std::make_pair(V, LastCast);
244}
245
246bool HexagonOptShuffleVector::isConstantVectorSplat(Value *V) {
247 if (auto *CV = dyn_cast<ConstantVector>(V))
248 return CV->getSplatValue();
249 if (auto *CV = dyn_cast<ConstantDataVector>(V))
250 return CV->isSplat();
251 return false;
252}
253
254// Make sure all the operations on HI and LO counterparts are identical
255// until both halves are merged together. When a merge point (concat)
256// is found, set it as 'NewLoc' and return.
257bool HexagonOptShuffleVector::analyzeHiLoUse(Instruction *HI, Instruction *LO,
258 ArrayRef<int> &ShuffMask,
259 Value *&NewLoc,
260 ShuffUseList &CurShuffUses) {
261 ValueVector HiUseList, LoUseList;
262 getUseList(HI, HiUseList);
263 getUseList(LO, LoUseList);
264
265 // To keep the analsis simple, only handle Hi and Lo with a single use. Also,
266 // not even sure at this point if it will be profitable due to multiple
267 // merge points.
268 if (HiUseList.size() != 1 || LoUseList.size() != 1)
269 return false;
270
271 Instruction *HiUse = dyn_cast<Instruction>(HiUseList[0]);
272 Instruction *LoUse = dyn_cast<Instruction>(LoUseList[0]);
273 if (!HiUse || !LoUse)
274 return false;
275
276 bool IsUseIntrinsic = false;
277 if (isa<CallInst>(HiUse)) {
278 if (!isa<CallInst>(LoUse))
279 return false;
280 // Continue only if both Hi and Lo uses are calls to the same intrinsic.
281 IntrinsicInst *HiUseII = dyn_cast<IntrinsicInst>(HiUse);
282 IntrinsicInst *LoUseII = dyn_cast<IntrinsicInst>(LoUse);
283 if (!HiUseII || !LoUseII ||
284 HiUseII->getIntrinsicID() != LoUseII->getIntrinsicID() ||
285 !isValidIntrinsic(HiUseII))
286 return false;
287 IsUseIntrinsic = true;
288 HiUse = HiUseII;
289 LoUse = LoUseII;
290 }
291 if (HiUse->getOpcode() != LoUse->getOpcode())
292 return false;
293
294 // If both Hi and Lo use are same and is a concat operation, set it
295 // as a 'NewLoc'.
296 if (HiUse == LoUse) {
297 // Return true if use is a concat of Hi and Lo.
298 ArrayRef<int> M;
299 if (match(HiUse, (m_Shuffle(m_Value(), m_Value(), m_Mask(M))))) {
300 if (isConcatMask(M, HiUse)) {
301 NewLoc = HiUse;
302 return true;
303 }
304 }
305 return false;
306 }
307
308 // Check if HiUse and LoUse are shuffles with the same mask. If so, safe to
309 // continue the search.
310 ArrayRef<int> M1, M2;
311 if (match(HiUse, (m_Shuffle(m_Value(), m_Poison(), m_Mask(M1)))) &&
312 match(LoUse, (m_Shuffle(m_Value(), m_Poison(), m_Mask(M2)))) &&
313 M1.equals(M2))
314 return analyzeHiLoUse(HiUse, LoUse, ShuffMask, NewLoc, CurShuffUses);
315
316 // For now, only handling binary ops and some of the instrinsics
317 // which appear to be safe (hardcoded in isValidIntrinsic()).
318 if (!HiUse->isBinaryOp() && !IsUseIntrinsic)
319 return false;
320
321 ValueVector HiUseOperands, LoUseOperands;
322 int HiOpNum = -1, LoOpNum = -1;
323 for (unsigned i = 0; i < HiUse->getNumOperands(); i++) {
324 Value *V = getOperand(HiUse, i);
325 if (V == HI)
326 HiOpNum = i;
327 else
328 HiUseOperands.push_back(V);
329 }
330 for (unsigned i = 0; i < LoUse->getNumOperands(); i++) {
331 Value *V = getOperand(LoUse, i);
332 if (V == LO)
333 LoOpNum = i;
334 else
335 LoUseOperands.push_back(V);
336 }
337
338 // Enforcing strict ordering which is not necessary in case of
339 // commutative operations and may be relaxed in future if needed.
340 if (HiOpNum < 0 || HiOpNum != LoOpNum ||
341 LoUseOperands.size() != HiUseOperands.size())
342 return false;
343
344 unsigned NumOperands = HiUseOperands.size();
345 for (unsigned i = 0; i < NumOperands; i++) {
346 if (HiUseOperands[i] == LoUseOperands[i])
347 continue;
348 // Only handle the case where other operands to Hi and Lo uses
349 // are comming from another Hi and Lo pair.
350 if (!isHILo(HiUseOperands[i], true) || !isHILo(LoUseOperands[i], false))
351 return false;
352
353 Value *DefHiUse = dyn_cast<Instruction>(HiUseOperands[i])->getOperand(0);
354 Value *DefLoUse = dyn_cast<Instruction>(LoUseOperands[i])->getOperand(0);
355 if (!DefHiUse || DefHiUse != DefLoUse)
356 return false;
357 SmallVector<Instruction *, 2> ImmUseList;
358 if (dyn_cast<CastInst>(DefHiUse))
359 ImmUseList.push_back(dyn_cast<Instruction>(DefHiUse));
360 else {
361 ImmUseList.push_back(HiUse);
362 ImmUseList.push_back(LoUse);
363 }
364
365 // Make sure that the Hi/Lo def has the same shuffle mask.
366 if (!hasDefWithSameShuffMask(DefHiUse, ImmUseList, ShuffMask, CurShuffUses))
367 return false;
368 }
369
370 // Continue the search along Hi/Lo use-chain.
371 return analyzeHiLoUse(HiUse, LoUse, ShuffMask, NewLoc, CurShuffUses);
372}
373
374bool HexagonOptShuffleVector::hasDefWithSameShuffMask(
375 Value *V, SmallVector<Instruction *, 2> &ImmUses, ArrayRef<int> &ShuffMask,
376 ShuffUseList &CurShuffUses) {
377 // Follow def-chain until we have found a shuffle_vector or have run out
378 // of max number of attempts.
379 if (DefSearchCount >= MaxDefSearchCount)
380 return false;
381
382 ++DefSearchCount;
383 V = stripCasts(V).first;
385 if (!I)
386 return false;
387 bool Found = true;
388 ArrayRef<int> M;
389 if (match(V, (m_Shuffle(m_Value(), m_Value(), m_Mask(M)))) &&
390 M.equals(ShuffMask)) {
391 CurShuffUses[I] = ImmUses;
392 return true;
393 }
395 m_Poison(), m_ZeroMask()))))
396 return true; // scalar converted to a vector
397
399 if (!I->isBinaryOp() && (!II || !isValidIntrinsic(II)))
400 return false;
401
402 for (Value *OpV : getArgOperands(I)) {
403 std::pair<Value *, Value *> P = stripCasts(OpV);
404 OpV = P.first;
405
406 SmallVector<Instruction *, 2> ImmUseList;
407 if (P.second)
408 ImmUseList.push_back(dyn_cast<Instruction>(P.second));
409 else
410 ImmUseList.push_back(dyn_cast<Instruction>(I));
411
412 if (isa<PoisonValue>(OpV))
413 continue;
414 if (isConstantVectorSplat(OpV))
415 continue;
416 if (!dyn_cast<Instruction>(OpV))
417 return false;
419 m_Poison(), m_ZeroMask()))))
420 continue;
421 Found &= hasDefWithSameShuffMask(OpV, ImmUseList, ShuffMask, CurShuffUses);
422 }
423 return Found;
424}
425
426void HexagonOptShuffleVector::FindHiLoUse(ValueVector &UseList,
427 Instruction *&HI, Instruction *&LO) {
428
429 for (unsigned i = 0; i < UseList.size(); i++) {
430 auto *J = dyn_cast<Instruction>(UseList[i]);
431 auto *CI = dyn_cast<CallInst>(J);
432 if (CI) {
433 auto *II = dyn_cast<IntrinsicInst>(CI);
434 if (II) {
435 Intrinsic::ID IntID = II->getIntrinsicID();
436 if (IntID == Intrinsic::hexagon_V6_hi_128B)
437 HI = J;
438 if (IntID == Intrinsic::hexagon_V6_lo_128B)
439 LO = J;
440 }
441 }
442 }
443}
444
445bool HexagonOptShuffleVector::isValidUseInstr(ValueVector &UseList,
446 Instruction *&UI) {
447 // Don't allow multiple uses. Only done in case of a Hi/Lo pair.
448 if (UseList.size() != 1)
449 return false;
450 UI = dyn_cast<Instruction>(UseList[0]);
451 if (!UI)
452 return false;
453 // Should be either a binary op or one of the supported instrinsics.
454 if (auto *CI = dyn_cast<CallInst>(UI)) {
455 auto *II = dyn_cast<IntrinsicInst>(CI);
456 if (!II || !isValidIntrinsic(II))
457 return false;
458 UI = II;
459 } else if (!UI->isBinaryOp())
460 return false;
461 return true;
462}
463
464// Check all the operands of 'Use' to make sure that they are either:
465// 1) a constant
466// 2) a scalar
467// 3) a constant vector
468// 4) a vector using the same mask as I
469bool HexagonOptShuffleVector::areAllOperandsValid(Instruction *I,
470 Instruction *Use,
471 ArrayRef<int> &ShuffMask,
472 ShuffUseList &CurShuffUses) {
473 bool AllOperandsOK = true;
474 for (Value *OpV : getArgOperands(Use)) {
475 bool HasOneUse = OpV->hasOneUse();
476 std::pair<Value *, Value *> P = stripCasts(OpV);
477 OpV = P.first;
478
479 SmallVector<Instruction *, 2> ImmUseList;
480 if (P.second)
481 ImmUseList.push_back(dyn_cast<Instruction>(P.second));
482 else
483 ImmUseList.push_back(dyn_cast<Instruction>(Use));
484
485 if (OpV == I || isa<PoisonValue>(OpV))
486 continue;
487 if (isConstantVectorSplat(OpV))
488 continue;
489 if (!dyn_cast<Instruction>(OpV) || !HasOneUse)
490 return false;
491
493 m_Poison(), m_ZeroMask()))))
494 continue;
495 AllOperandsOK &=
496 hasDefWithSameShuffMask(OpV, ImmUseList, ShuffMask, CurShuffUses);
497 }
498 return AllOperandsOK;
499}
500
501// Find the new location where it's safe to relocate shuffle instruction 'I'.
502bool HexagonOptShuffleVector::findNewShuffLoc(Instruction *I,
503 ArrayRef<int> &ShuffMask,
504 Value *&NewLoc) {
505 DefSearchCount = 0;
506 ValueVector UseList;
507 if (!getUseList(I, UseList))
508 return false;
509
510 using ShuffUseList =
511 SmallDenseMap<Instruction *, SmallVector<Instruction *, 2>>;
512 ShuffUseList CurShuffUses;
513 // Check for Hi and Lo pair.
514 Instruction *HI = nullptr, *LO = nullptr;
515 FindHiLoUse(UseList, HI, LO);
516 if (UseList.size() == 2 && HI && LO) {
517 // If 'I' has Hi and Lo use-pair, then it can be relocated only after Hi/Lo
518 // use-chain's merge point, i.e., after a concat vector provided it's safe
519 // to do so.
520 LLVM_DEBUG({
521 dbgs() << "\tFollowing the Hi/LO pair :\n";
522 dbgs() << "\t\tHI - ";
523 HI->dump();
524 dbgs() << "\t\tLO - ";
525 LO->dump();
526 });
527 if (!analyzeHiLoUse(HI, LO, ShuffMask, NewLoc, CurShuffUses))
528 return false;
529 for (auto &it : CurShuffUses)
530 ShuffUses[it.first] = it.second;
531 return true;
532 } else { // Single use case
533 Instruction *UI = nullptr;
534 if (!isValidUseInstr(UseList, UI))
535 return false;
536 assert(UI && "Expected a valid use, but found none!!");
537
538 if (HI || LO) {
539 // If the single use case is either Hi or Lo, it is not safe to relocate
540 return false;
541 }
542
543 LLVM_DEBUG(dbgs() << "\tChecking operands in 'use' : \n\t\t"; UI->dump());
544 if (!areAllOperandsValid(I, UI, ShuffMask, CurShuffUses)) {
545 LLVM_DEBUG(dbgs() << "\t\tNOT SAFE -- Exiting!!\n");
546 return false;
547 }
548 for (auto &it : CurShuffUses)
549 ShuffUses[it.first] = it.second;
550 NewLoc = UI;
551 // Keep looking for the new location until can't proceed any longer.
552 findNewShuffLoc(UI, ShuffMask, NewLoc);
553 }
554 return true;
555}
556
557// Move shuffle instruction 'I' after 'NewLoc'.
558bool HexagonOptShuffleVector::relocateShuffVec(
559 Instruction *I, ArrayRef<int> &M, Value *NewLoc,
560 std::list<Instruction *> &WorkList) {
561 // Remove original vector shuffles at the input operands.
562 // However, it can be done only if the replacements have the
563 // same number of vector elements as the original operands.
564 std::map<Instruction *, Value *> InstrMap;
565 bool CanReplace = true;
566 unsigned ShuffInstCount = ShuffUses.size();
567 for (auto &it : ShuffUses) {
568 Instruction *J = it.first;
569 Visited.insert(J);
570 Value *ShuffleOP = nullptr;
571 match(J, (m_Shuffle(m_Value(ShuffleOP), m_Poison(), m_Mask(M))));
573 VectorType *ShuffTy = cast<FixedVectorType>(ShuffleOP->getType());
574 if (JTy->getElementCount() != ShuffTy->getElementCount())
575 CanReplace = false;
576
577 // Relocate shufflevector after a wider instruction only if there are
578 // at least two or more shufflevectors being relocated in order for the
579 // relocation to be profitable as otherwise it will require more shuffles.
580 VectorType *NewShuffTy = cast<FixedVectorType>(NewLoc->getType());
581 if (ShuffInstCount == 1 &&
582 NewShuffTy->getElementType() > ShuffTy->getElementType())
583 CanReplace = false;
584 InstrMap[J] = ShuffleOP;
585 }
586 if (!CanReplace) {
587 LLVM_DEBUG(dbgs() << "\tRelocation FAILED!! \n");
588 return false;
589 }
590 for (auto IM : InstrMap) {
591 Instruction *J = IM.first;
592 assert(ShuffUses.count(J));
593 SmallVector<Instruction *, 2> Uses = ShuffUses[J];
594 if (Uses.size() > 0) {
595 for (auto *U : Uses)
596 U->replaceUsesOfWith(IM.first, IM.second);
597 } else
598 // This is the shuffle we started with, and we have already made sure
599 // that it has either single use or a HI/LO use pair. So, it's okay
600 // to replace all its uses with the input to the shuffle instruction.
601 IM.first->replaceAllUsesWith(IM.second);
602 }
603 // Shuffle the output of NewLoc based on the original mask.
604 Instruction *Pos = dyn_cast<Instruction>(NewLoc);
605 assert(Pos);
606 Pos = Pos->getNextNode();
607 IRBuilder<> IRB(Pos);
608 Value *NewShuffV =
609 IRB.CreateShuffleVector(NewLoc, PoisonValue::get(NewLoc->getType()), M);
610 Instruction *NewInst = dyn_cast<Instruction>(NewShuffV);
611 if (!NewInst) {
612 LLVM_DEBUG(dbgs() << "\tRelocation FAILED!! \n");
613 return false;
614 }
615 for (auto UI = NewLoc->user_begin(), UE = NewLoc->user_end(); UI != UE;) {
616 Use &TheUse = UI.getUse();
617 ++UI;
619 if (J && TheUse.getUser() != NewShuffV)
620 J->replaceUsesOfWith(NewLoc, NewShuffV);
621 }
622 WorkList.push_back(NewInst);
623 LLVM_DEBUG(dbgs() << "\tRelocation Successfull!! \n");
624 LLVM_DEBUG(dbgs() << "\tAdded to Worklist :\n"; NewInst->dump());
625 return true;
626}
627
628bool HexagonOptShuffleVector::visitBlock(BasicBlock *B) {
629 bool Changed = false;
630 ArrayRef<int> M;
631 std::list<Instruction *> WorkList;
632 LLVM_DEBUG(dbgs() << "Preparing worklist for BB:\n");
633 LLVM_DEBUG(B->dump());
634 for (auto &I : *B) {
635 if (match(&I, (m_Shuffle(m_Value(), m_Value(), m_ZeroMask()))))
636 continue; // Skip - building vector from a scalar
637 if (match(&I, (m_Shuffle(m_Value(), m_Poison(), m_Mask(M))))) {
638 WorkList.push_back(&I);
639 LLVM_DEBUG(dbgs() << "\tAdded instr - "; I.dump());
640 }
641 }
642
643 LLVM_DEBUG(dbgs() << "Processing worklist:\n");
644 while (!WorkList.empty()) {
645#ifndef NDEBUG
646 int Limit = ShuffVecLimit;
647 if (Limit >= 0) {
648 if (NumRelocated >= ShuffVecLimit) {
649 LLVM_DEBUG({
650 dbgs() << "Reached maximum limit!! \n";
651 dbgs() << "Can't process any more shuffles.... \n";
652 });
653 return Changed;
654 }
655 }
656#endif
657 Instruction *I = WorkList.front();
658 WorkList.pop_front();
659 LLVM_DEBUG(dbgs() << "\tProcessing instr - "; I->dump());
660 Value *NewLoc = nullptr;
661
662 // 'ShuffUses' is used to keep track of the vector shuffles that need to
663 // be relocated along with their immediate uses that are known to satisfy
664 // all the safety requirements of the relocation.
665 // NOTE: The shuffle instr 'I', where the analysis starts, doesn't have
666 // its immediate uses set in 'ShuffUses'. This can be done but isn't
667 // necessary. At this point, only shuffles with single use or a HI/LO pair
668 // are allowed. This is done mostly because those with the multiple uses
669 // aren't expected to be much profitable and can be extended in the future
670 // if necessary. For now, all the uses in such cases can be safely updated
671 // when the corresponding vector shuffle is relocated.
672
673 ShuffUses.clear();
674 ShuffUses[I] = SmallVector<Instruction *, 2>();
675 // Skip if node already visited.
676 if (!Visited.insert(I).second) {
677 LLVM_DEBUG(dbgs() << "\t\tSKIPPING - Already visited ...\n");
678 continue;
679 }
680 if (!match(I, (m_Shuffle(m_Value(), m_Poison(), m_Mask(M))))) {
681 LLVM_DEBUG(dbgs() << "\t\tSKIPPING - Not a vector shuffle ...\n");
682 continue;
683 }
684 if (!findNewShuffLoc(I, M, NewLoc) || !NewLoc) {
685 LLVM_DEBUG(dbgs() << "\t\tSKIPPING - NewLoc not found ...\n");
686 continue;
687 }
688 LLVM_DEBUG(dbgs() << "\t\tRelocating after -- "; NewLoc->dump());
689 Changed |= relocateShuffVec(I, M, NewLoc, WorkList);
690#ifndef NDEBUG
691 NumRelocated++;
692#endif
693 }
694 return Changed;
695}
696
697bool HexagonOptShuffleVector::runOnFunction(Function &F) {
698 HST = TM->getSubtargetImpl(F);
699 // Works only for 128B mode but can be extended for 64B if needed.
700 if (skipFunction(F) || !HST->useHVX128BOps())
701 return false;
702
703 bool Changed = false;
704 for (auto &B : F)
705 Changed |= visitBlock(&B);
706
707 return Changed;
708}
709
710FunctionPass *
712 return new HexagonOptShuffleVector(&TM);
713}
static bool isConcatMask(ArrayRef< int > Mask, EVT VT, bool SplitLHS)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static bool runOnFunction(Function &F, bool PostInlining)
static cl::opt< int > MaxDefSearchCount("shuffvec-max-search-count", cl::desc("Maximum number of instructions traversed along def chain."), cl::Hidden, cl::init(15))
A command line argument to limit the search space along def chain.
static cl::opt< int > ShuffVecLimit("shuff-vec-max", cl::desc("Maximum number of shuffles to be relocated."), cl::Hidden, cl::init(-1))
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
uint64_t IntrinsicInst * II
#define P(N)
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
Remove Loads Into Fake Uses
SmallVector< Value *, 8 > ValueVector
#define LLVM_DEBUG(...)
Definition Debug.h:114
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
Legacy analysis pass which computes a DominatorTree.
Definition Dominators.h:321
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
const HexagonSubtarget * getSubtargetImpl(const Function &F) const override
Virtual method implemented by subclasses that returns a reference to that target's TargetSubtargetInf...
bool isBinaryOp() const
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
void push_back(const T &Elt)
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
User * getUser() const
Returns the User that contains this Use.
Definition Use.h:61
LLVM_ABI bool replaceUsesOfWith(Value *From, Value *To)
Replace uses of one Value with another.
Definition User.cpp:24
unsigned getNumOperands() const
Definition User.h:254
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:256
user_iterator user_begin()
Definition Value.h:402
user_iterator user_end()
Definition Value.h:410
LLVM_ABI void dump() const
Support for debugging, callable in GDB: V->dump()
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
Definition ilist_node.h:348
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
class_match< PoisonValue > m_Poison()
Match an arbitrary poison constant.
bool match(Val *V, const Pattern &P)
TwoOps_match< V1_t, V2_t, Instruction::ShuffleVector > m_Shuffle(const V1_t &v1, const V2_t &v2)
Matches ShuffleVectorInst independently of mask value.
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
is_zero m_Zero()
Match any null constant or a vector with all elements equal to 0.
ThreeOps_match< Val_t, Elt_t, Idx_t, Instruction::InsertElement > m_InsertElt(const Val_t &Val, const Elt_t &Elt, const Idx_t &Idx)
Matches InsertElementInst.
initializer< Ty > init(const Ty &Val)
NodeAddr< UseNode * > Use
Definition RDFGraph.h:385
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
FunctionPass * createHexagonOptShuffleVector(const HexagonTargetMachine &)
unsigned M1(unsigned Val)
Definition VE.h:377
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
void initializeHexagonOptShuffleVectorPass(PassRegistry &)
IRBuilder(LLVMContext &, FolderTy, InserterTy, MDNode *, ArrayRef< OperandBundleDef >) -> IRBuilder< FolderTy, InserterTy >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559