xref: /aosp_15_r20/external/llvm/lib/Transforms/Scalar/Scalarizer.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===--- Scalarizer.cpp - Scalarize vector operations ---------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This pass converts vector operations into scalar operations, in order
11*9880d681SAndroid Build Coastguard Worker // to expose optimization opportunities on the individual scalar operations.
12*9880d681SAndroid Build Coastguard Worker // It is mainly intended for targets that do not have vector units, but it
13*9880d681SAndroid Build Coastguard Worker // may also be useful for revectorizing code to different vector widths.
14*9880d681SAndroid Build Coastguard Worker //
15*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
16*9880d681SAndroid Build Coastguard Worker 
17*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Scalar.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/ADT/STLExtras.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IRBuilder.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/InstVisitor.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Pass.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/BasicBlockUtils.h"
23*9880d681SAndroid Build Coastguard Worker 
24*9880d681SAndroid Build Coastguard Worker using namespace llvm;
25*9880d681SAndroid Build Coastguard Worker 
26*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "scalarizer"
27*9880d681SAndroid Build Coastguard Worker 
28*9880d681SAndroid Build Coastguard Worker namespace {
29*9880d681SAndroid Build Coastguard Worker // Used to store the scattered form of a vector.
30*9880d681SAndroid Build Coastguard Worker typedef SmallVector<Value *, 8> ValueVector;
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker // Used to map a vector Value to its scattered form.  We use std::map
33*9880d681SAndroid Build Coastguard Worker // because we want iterators to persist across insertion and because the
34*9880d681SAndroid Build Coastguard Worker // values are relatively large.
35*9880d681SAndroid Build Coastguard Worker typedef std::map<Value *, ValueVector> ScatterMap;
36*9880d681SAndroid Build Coastguard Worker 
37*9880d681SAndroid Build Coastguard Worker // Lists Instructions that have been replaced with scalar implementations,
38*9880d681SAndroid Build Coastguard Worker // along with a pointer to their scattered forms.
39*9880d681SAndroid Build Coastguard Worker typedef SmallVector<std::pair<Instruction *, ValueVector *>, 16> GatherList;
40*9880d681SAndroid Build Coastguard Worker 
41*9880d681SAndroid Build Coastguard Worker // Provides a very limited vector-like interface for lazily accessing one
42*9880d681SAndroid Build Coastguard Worker // component of a scattered vector or vector pointer.
43*9880d681SAndroid Build Coastguard Worker class Scatterer {
44*9880d681SAndroid Build Coastguard Worker public:
Scatterer()45*9880d681SAndroid Build Coastguard Worker   Scatterer() {}
46*9880d681SAndroid Build Coastguard Worker 
47*9880d681SAndroid Build Coastguard Worker   // Scatter V into Size components.  If new instructions are needed,
48*9880d681SAndroid Build Coastguard Worker   // insert them before BBI in BB.  If Cache is nonnull, use it to cache
49*9880d681SAndroid Build Coastguard Worker   // the results.
50*9880d681SAndroid Build Coastguard Worker   Scatterer(BasicBlock *bb, BasicBlock::iterator bbi, Value *v,
51*9880d681SAndroid Build Coastguard Worker             ValueVector *cachePtr = nullptr);
52*9880d681SAndroid Build Coastguard Worker 
53*9880d681SAndroid Build Coastguard Worker   // Return component I, creating a new Value for it if necessary.
54*9880d681SAndroid Build Coastguard Worker   Value *operator[](unsigned I);
55*9880d681SAndroid Build Coastguard Worker 
56*9880d681SAndroid Build Coastguard Worker   // Return the number of components.
size() const57*9880d681SAndroid Build Coastguard Worker   unsigned size() const { return Size; }
58*9880d681SAndroid Build Coastguard Worker 
59*9880d681SAndroid Build Coastguard Worker private:
60*9880d681SAndroid Build Coastguard Worker   BasicBlock *BB;
61*9880d681SAndroid Build Coastguard Worker   BasicBlock::iterator BBI;
62*9880d681SAndroid Build Coastguard Worker   Value *V;
63*9880d681SAndroid Build Coastguard Worker   ValueVector *CachePtr;
64*9880d681SAndroid Build Coastguard Worker   PointerType *PtrTy;
65*9880d681SAndroid Build Coastguard Worker   ValueVector Tmp;
66*9880d681SAndroid Build Coastguard Worker   unsigned Size;
67*9880d681SAndroid Build Coastguard Worker };
68*9880d681SAndroid Build Coastguard Worker 
69*9880d681SAndroid Build Coastguard Worker // FCmpSpliiter(FCI)(Builder, X, Y, Name) uses Builder to create an FCmp
70*9880d681SAndroid Build Coastguard Worker // called Name that compares X and Y in the same way as FCI.
71*9880d681SAndroid Build Coastguard Worker struct FCmpSplitter {
FCmpSplitter__anon916437db0111::FCmpSplitter72*9880d681SAndroid Build Coastguard Worker   FCmpSplitter(FCmpInst &fci) : FCI(fci) {}
operator ()__anon916437db0111::FCmpSplitter73*9880d681SAndroid Build Coastguard Worker   Value *operator()(IRBuilder<> &Builder, Value *Op0, Value *Op1,
74*9880d681SAndroid Build Coastguard Worker                     const Twine &Name) const {
75*9880d681SAndroid Build Coastguard Worker     return Builder.CreateFCmp(FCI.getPredicate(), Op0, Op1, Name);
76*9880d681SAndroid Build Coastguard Worker   }
77*9880d681SAndroid Build Coastguard Worker   FCmpInst &FCI;
78*9880d681SAndroid Build Coastguard Worker };
79*9880d681SAndroid Build Coastguard Worker 
80*9880d681SAndroid Build Coastguard Worker // ICmpSpliiter(ICI)(Builder, X, Y, Name) uses Builder to create an ICmp
81*9880d681SAndroid Build Coastguard Worker // called Name that compares X and Y in the same way as ICI.
82*9880d681SAndroid Build Coastguard Worker struct ICmpSplitter {
ICmpSplitter__anon916437db0111::ICmpSplitter83*9880d681SAndroid Build Coastguard Worker   ICmpSplitter(ICmpInst &ici) : ICI(ici) {}
operator ()__anon916437db0111::ICmpSplitter84*9880d681SAndroid Build Coastguard Worker   Value *operator()(IRBuilder<> &Builder, Value *Op0, Value *Op1,
85*9880d681SAndroid Build Coastguard Worker                     const Twine &Name) const {
86*9880d681SAndroid Build Coastguard Worker     return Builder.CreateICmp(ICI.getPredicate(), Op0, Op1, Name);
87*9880d681SAndroid Build Coastguard Worker   }
88*9880d681SAndroid Build Coastguard Worker   ICmpInst &ICI;
89*9880d681SAndroid Build Coastguard Worker };
90*9880d681SAndroid Build Coastguard Worker 
91*9880d681SAndroid Build Coastguard Worker // BinarySpliiter(BO)(Builder, X, Y, Name) uses Builder to create
92*9880d681SAndroid Build Coastguard Worker // a binary operator like BO called Name with operands X and Y.
93*9880d681SAndroid Build Coastguard Worker struct BinarySplitter {
BinarySplitter__anon916437db0111::BinarySplitter94*9880d681SAndroid Build Coastguard Worker   BinarySplitter(BinaryOperator &bo) : BO(bo) {}
operator ()__anon916437db0111::BinarySplitter95*9880d681SAndroid Build Coastguard Worker   Value *operator()(IRBuilder<> &Builder, Value *Op0, Value *Op1,
96*9880d681SAndroid Build Coastguard Worker                     const Twine &Name) const {
97*9880d681SAndroid Build Coastguard Worker     return Builder.CreateBinOp(BO.getOpcode(), Op0, Op1, Name);
98*9880d681SAndroid Build Coastguard Worker   }
99*9880d681SAndroid Build Coastguard Worker   BinaryOperator &BO;
100*9880d681SAndroid Build Coastguard Worker };
101*9880d681SAndroid Build Coastguard Worker 
102*9880d681SAndroid Build Coastguard Worker // Information about a load or store that we're scalarizing.
103*9880d681SAndroid Build Coastguard Worker struct VectorLayout {
VectorLayout__anon916437db0111::VectorLayout104*9880d681SAndroid Build Coastguard Worker   VectorLayout() : VecTy(nullptr), ElemTy(nullptr), VecAlign(0), ElemSize(0) {}
105*9880d681SAndroid Build Coastguard Worker 
106*9880d681SAndroid Build Coastguard Worker   // Return the alignment of element I.
getElemAlign__anon916437db0111::VectorLayout107*9880d681SAndroid Build Coastguard Worker   uint64_t getElemAlign(unsigned I) {
108*9880d681SAndroid Build Coastguard Worker     return MinAlign(VecAlign, I * ElemSize);
109*9880d681SAndroid Build Coastguard Worker   }
110*9880d681SAndroid Build Coastguard Worker 
111*9880d681SAndroid Build Coastguard Worker   // The type of the vector.
112*9880d681SAndroid Build Coastguard Worker   VectorType *VecTy;
113*9880d681SAndroid Build Coastguard Worker 
114*9880d681SAndroid Build Coastguard Worker   // The type of each element.
115*9880d681SAndroid Build Coastguard Worker   Type *ElemTy;
116*9880d681SAndroid Build Coastguard Worker 
117*9880d681SAndroid Build Coastguard Worker   // The alignment of the vector.
118*9880d681SAndroid Build Coastguard Worker   uint64_t VecAlign;
119*9880d681SAndroid Build Coastguard Worker 
120*9880d681SAndroid Build Coastguard Worker   // The size of each element.
121*9880d681SAndroid Build Coastguard Worker   uint64_t ElemSize;
122*9880d681SAndroid Build Coastguard Worker };
123*9880d681SAndroid Build Coastguard Worker 
124*9880d681SAndroid Build Coastguard Worker class Scalarizer : public FunctionPass,
125*9880d681SAndroid Build Coastguard Worker                    public InstVisitor<Scalarizer, bool> {
126*9880d681SAndroid Build Coastguard Worker public:
127*9880d681SAndroid Build Coastguard Worker   static char ID;
128*9880d681SAndroid Build Coastguard Worker 
Scalarizer()129*9880d681SAndroid Build Coastguard Worker   Scalarizer() :
130*9880d681SAndroid Build Coastguard Worker     FunctionPass(ID) {
131*9880d681SAndroid Build Coastguard Worker     initializeScalarizerPass(*PassRegistry::getPassRegistry());
132*9880d681SAndroid Build Coastguard Worker   }
133*9880d681SAndroid Build Coastguard Worker 
134*9880d681SAndroid Build Coastguard Worker   bool doInitialization(Module &M) override;
135*9880d681SAndroid Build Coastguard Worker   bool runOnFunction(Function &F) override;
136*9880d681SAndroid Build Coastguard Worker 
137*9880d681SAndroid Build Coastguard Worker   // InstVisitor methods.  They return true if the instruction was scalarized,
138*9880d681SAndroid Build Coastguard Worker   // false if nothing changed.
visitInstruction(Instruction &)139*9880d681SAndroid Build Coastguard Worker   bool visitInstruction(Instruction &) { return false; }
140*9880d681SAndroid Build Coastguard Worker   bool visitSelectInst(SelectInst &SI);
141*9880d681SAndroid Build Coastguard Worker   bool visitICmpInst(ICmpInst &);
142*9880d681SAndroid Build Coastguard Worker   bool visitFCmpInst(FCmpInst &);
143*9880d681SAndroid Build Coastguard Worker   bool visitBinaryOperator(BinaryOperator &);
144*9880d681SAndroid Build Coastguard Worker   bool visitGetElementPtrInst(GetElementPtrInst &);
145*9880d681SAndroid Build Coastguard Worker   bool visitCastInst(CastInst &);
146*9880d681SAndroid Build Coastguard Worker   bool visitBitCastInst(BitCastInst &);
147*9880d681SAndroid Build Coastguard Worker   bool visitShuffleVectorInst(ShuffleVectorInst &);
148*9880d681SAndroid Build Coastguard Worker   bool visitPHINode(PHINode &);
149*9880d681SAndroid Build Coastguard Worker   bool visitLoadInst(LoadInst &);
150*9880d681SAndroid Build Coastguard Worker   bool visitStoreInst(StoreInst &);
151*9880d681SAndroid Build Coastguard Worker 
registerOptions()152*9880d681SAndroid Build Coastguard Worker   static void registerOptions() {
153*9880d681SAndroid Build Coastguard Worker     // This is disabled by default because having separate loads and stores
154*9880d681SAndroid Build Coastguard Worker     // makes it more likely that the -combiner-alias-analysis limits will be
155*9880d681SAndroid Build Coastguard Worker     // reached.
156*9880d681SAndroid Build Coastguard Worker     OptionRegistry::registerOption<bool, Scalarizer,
157*9880d681SAndroid Build Coastguard Worker                                  &Scalarizer::ScalarizeLoadStore>(
158*9880d681SAndroid Build Coastguard Worker         "scalarize-load-store",
159*9880d681SAndroid Build Coastguard Worker         "Allow the scalarizer pass to scalarize loads and store", false);
160*9880d681SAndroid Build Coastguard Worker   }
161*9880d681SAndroid Build Coastguard Worker 
162*9880d681SAndroid Build Coastguard Worker private:
163*9880d681SAndroid Build Coastguard Worker   Scatterer scatter(Instruction *, Value *);
164*9880d681SAndroid Build Coastguard Worker   void gather(Instruction *, const ValueVector &);
165*9880d681SAndroid Build Coastguard Worker   bool canTransferMetadata(unsigned Kind);
166*9880d681SAndroid Build Coastguard Worker   void transferMetadata(Instruction *, const ValueVector &);
167*9880d681SAndroid Build Coastguard Worker   bool getVectorLayout(Type *, unsigned, VectorLayout &, const DataLayout &);
168*9880d681SAndroid Build Coastguard Worker   bool finish();
169*9880d681SAndroid Build Coastguard Worker 
170*9880d681SAndroid Build Coastguard Worker   template<typename T> bool splitBinary(Instruction &, const T &);
171*9880d681SAndroid Build Coastguard Worker 
172*9880d681SAndroid Build Coastguard Worker   ScatterMap Scattered;
173*9880d681SAndroid Build Coastguard Worker   GatherList Gathered;
174*9880d681SAndroid Build Coastguard Worker   unsigned ParallelLoopAccessMDKind;
175*9880d681SAndroid Build Coastguard Worker   bool ScalarizeLoadStore;
176*9880d681SAndroid Build Coastguard Worker };
177*9880d681SAndroid Build Coastguard Worker 
178*9880d681SAndroid Build Coastguard Worker char Scalarizer::ID = 0;
179*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
180*9880d681SAndroid Build Coastguard Worker 
181*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_WITH_OPTIONS(Scalarizer, "scalarizer",
182*9880d681SAndroid Build Coastguard Worker                              "Scalarize vector operations", false, false)
183*9880d681SAndroid Build Coastguard Worker 
Scatterer(BasicBlock * bb,BasicBlock::iterator bbi,Value * v,ValueVector * cachePtr)184*9880d681SAndroid Build Coastguard Worker Scatterer::Scatterer(BasicBlock *bb, BasicBlock::iterator bbi, Value *v,
185*9880d681SAndroid Build Coastguard Worker                      ValueVector *cachePtr)
186*9880d681SAndroid Build Coastguard Worker   : BB(bb), BBI(bbi), V(v), CachePtr(cachePtr) {
187*9880d681SAndroid Build Coastguard Worker   Type *Ty = V->getType();
188*9880d681SAndroid Build Coastguard Worker   PtrTy = dyn_cast<PointerType>(Ty);
189*9880d681SAndroid Build Coastguard Worker   if (PtrTy)
190*9880d681SAndroid Build Coastguard Worker     Ty = PtrTy->getElementType();
191*9880d681SAndroid Build Coastguard Worker   Size = Ty->getVectorNumElements();
192*9880d681SAndroid Build Coastguard Worker   if (!CachePtr)
193*9880d681SAndroid Build Coastguard Worker     Tmp.resize(Size, nullptr);
194*9880d681SAndroid Build Coastguard Worker   else if (CachePtr->empty())
195*9880d681SAndroid Build Coastguard Worker     CachePtr->resize(Size, nullptr);
196*9880d681SAndroid Build Coastguard Worker   else
197*9880d681SAndroid Build Coastguard Worker     assert(Size == CachePtr->size() && "Inconsistent vector sizes");
198*9880d681SAndroid Build Coastguard Worker }
199*9880d681SAndroid Build Coastguard Worker 
200*9880d681SAndroid Build Coastguard Worker // Return component I, creating a new Value for it if necessary.
operator [](unsigned I)201*9880d681SAndroid Build Coastguard Worker Value *Scatterer::operator[](unsigned I) {
202*9880d681SAndroid Build Coastguard Worker   ValueVector &CV = (CachePtr ? *CachePtr : Tmp);
203*9880d681SAndroid Build Coastguard Worker   // Try to reuse a previous value.
204*9880d681SAndroid Build Coastguard Worker   if (CV[I])
205*9880d681SAndroid Build Coastguard Worker     return CV[I];
206*9880d681SAndroid Build Coastguard Worker   IRBuilder<> Builder(BB, BBI);
207*9880d681SAndroid Build Coastguard Worker   if (PtrTy) {
208*9880d681SAndroid Build Coastguard Worker     if (!CV[0]) {
209*9880d681SAndroid Build Coastguard Worker       Type *Ty =
210*9880d681SAndroid Build Coastguard Worker         PointerType::get(PtrTy->getElementType()->getVectorElementType(),
211*9880d681SAndroid Build Coastguard Worker                          PtrTy->getAddressSpace());
212*9880d681SAndroid Build Coastguard Worker       CV[0] = Builder.CreateBitCast(V, Ty, V->getName() + ".i0");
213*9880d681SAndroid Build Coastguard Worker     }
214*9880d681SAndroid Build Coastguard Worker     if (I != 0)
215*9880d681SAndroid Build Coastguard Worker       CV[I] = Builder.CreateConstGEP1_32(nullptr, CV[0], I,
216*9880d681SAndroid Build Coastguard Worker                                          V->getName() + ".i" + Twine(I));
217*9880d681SAndroid Build Coastguard Worker   } else {
218*9880d681SAndroid Build Coastguard Worker     // Search through a chain of InsertElementInsts looking for element I.
219*9880d681SAndroid Build Coastguard Worker     // Record other elements in the cache.  The new V is still suitable
220*9880d681SAndroid Build Coastguard Worker     // for all uncached indices.
221*9880d681SAndroid Build Coastguard Worker     for (;;) {
222*9880d681SAndroid Build Coastguard Worker       InsertElementInst *Insert = dyn_cast<InsertElementInst>(V);
223*9880d681SAndroid Build Coastguard Worker       if (!Insert)
224*9880d681SAndroid Build Coastguard Worker         break;
225*9880d681SAndroid Build Coastguard Worker       ConstantInt *Idx = dyn_cast<ConstantInt>(Insert->getOperand(2));
226*9880d681SAndroid Build Coastguard Worker       if (!Idx)
227*9880d681SAndroid Build Coastguard Worker         break;
228*9880d681SAndroid Build Coastguard Worker       unsigned J = Idx->getZExtValue();
229*9880d681SAndroid Build Coastguard Worker       V = Insert->getOperand(0);
230*9880d681SAndroid Build Coastguard Worker       if (I == J) {
231*9880d681SAndroid Build Coastguard Worker         CV[J] = Insert->getOperand(1);
232*9880d681SAndroid Build Coastguard Worker         return CV[J];
233*9880d681SAndroid Build Coastguard Worker       } else if (!CV[J]) {
234*9880d681SAndroid Build Coastguard Worker         // Only cache the first entry we find for each index we're not actively
235*9880d681SAndroid Build Coastguard Worker         // searching for. This prevents us from going too far up the chain and
236*9880d681SAndroid Build Coastguard Worker         // caching incorrect entries.
237*9880d681SAndroid Build Coastguard Worker         CV[J] = Insert->getOperand(1);
238*9880d681SAndroid Build Coastguard Worker       }
239*9880d681SAndroid Build Coastguard Worker     }
240*9880d681SAndroid Build Coastguard Worker     CV[I] = Builder.CreateExtractElement(V, Builder.getInt32(I),
241*9880d681SAndroid Build Coastguard Worker                                          V->getName() + ".i" + Twine(I));
242*9880d681SAndroid Build Coastguard Worker   }
243*9880d681SAndroid Build Coastguard Worker   return CV[I];
244*9880d681SAndroid Build Coastguard Worker }
245*9880d681SAndroid Build Coastguard Worker 
doInitialization(Module & M)246*9880d681SAndroid Build Coastguard Worker bool Scalarizer::doInitialization(Module &M) {
247*9880d681SAndroid Build Coastguard Worker   ParallelLoopAccessMDKind =
248*9880d681SAndroid Build Coastguard Worker       M.getContext().getMDKindID("llvm.mem.parallel_loop_access");
249*9880d681SAndroid Build Coastguard Worker   ScalarizeLoadStore =
250*9880d681SAndroid Build Coastguard Worker       M.getContext().getOption<bool, Scalarizer, &Scalarizer::ScalarizeLoadStore>();
251*9880d681SAndroid Build Coastguard Worker   return false;
252*9880d681SAndroid Build Coastguard Worker }
253*9880d681SAndroid Build Coastguard Worker 
runOnFunction(Function & F)254*9880d681SAndroid Build Coastguard Worker bool Scalarizer::runOnFunction(Function &F) {
255*9880d681SAndroid Build Coastguard Worker   if (skipFunction(F))
256*9880d681SAndroid Build Coastguard Worker     return false;
257*9880d681SAndroid Build Coastguard Worker   assert(Gathered.empty() && Scattered.empty());
258*9880d681SAndroid Build Coastguard Worker   for (BasicBlock &BB : F) {
259*9880d681SAndroid Build Coastguard Worker     for (BasicBlock::iterator II = BB.begin(), IE = BB.end(); II != IE;) {
260*9880d681SAndroid Build Coastguard Worker       Instruction *I = &*II;
261*9880d681SAndroid Build Coastguard Worker       bool Done = visit(I);
262*9880d681SAndroid Build Coastguard Worker       ++II;
263*9880d681SAndroid Build Coastguard Worker       if (Done && I->getType()->isVoidTy())
264*9880d681SAndroid Build Coastguard Worker         I->eraseFromParent();
265*9880d681SAndroid Build Coastguard Worker     }
266*9880d681SAndroid Build Coastguard Worker   }
267*9880d681SAndroid Build Coastguard Worker   return finish();
268*9880d681SAndroid Build Coastguard Worker }
269*9880d681SAndroid Build Coastguard Worker 
270*9880d681SAndroid Build Coastguard Worker // Return a scattered form of V that can be accessed by Point.  V must be a
271*9880d681SAndroid Build Coastguard Worker // vector or a pointer to a vector.
scatter(Instruction * Point,Value * V)272*9880d681SAndroid Build Coastguard Worker Scatterer Scalarizer::scatter(Instruction *Point, Value *V) {
273*9880d681SAndroid Build Coastguard Worker   if (Argument *VArg = dyn_cast<Argument>(V)) {
274*9880d681SAndroid Build Coastguard Worker     // Put the scattered form of arguments in the entry block,
275*9880d681SAndroid Build Coastguard Worker     // so that it can be used everywhere.
276*9880d681SAndroid Build Coastguard Worker     Function *F = VArg->getParent();
277*9880d681SAndroid Build Coastguard Worker     BasicBlock *BB = &F->getEntryBlock();
278*9880d681SAndroid Build Coastguard Worker     return Scatterer(BB, BB->begin(), V, &Scattered[V]);
279*9880d681SAndroid Build Coastguard Worker   }
280*9880d681SAndroid Build Coastguard Worker   if (Instruction *VOp = dyn_cast<Instruction>(V)) {
281*9880d681SAndroid Build Coastguard Worker     // Put the scattered form of an instruction directly after the
282*9880d681SAndroid Build Coastguard Worker     // instruction.
283*9880d681SAndroid Build Coastguard Worker     BasicBlock *BB = VOp->getParent();
284*9880d681SAndroid Build Coastguard Worker     return Scatterer(BB, std::next(BasicBlock::iterator(VOp)),
285*9880d681SAndroid Build Coastguard Worker                      V, &Scattered[V]);
286*9880d681SAndroid Build Coastguard Worker   }
287*9880d681SAndroid Build Coastguard Worker   // In the fallback case, just put the scattered before Point and
288*9880d681SAndroid Build Coastguard Worker   // keep the result local to Point.
289*9880d681SAndroid Build Coastguard Worker   return Scatterer(Point->getParent(), Point->getIterator(), V);
290*9880d681SAndroid Build Coastguard Worker }
291*9880d681SAndroid Build Coastguard Worker 
292*9880d681SAndroid Build Coastguard Worker // Replace Op with the gathered form of the components in CV.  Defer the
293*9880d681SAndroid Build Coastguard Worker // deletion of Op and creation of the gathered form to the end of the pass,
294*9880d681SAndroid Build Coastguard Worker // so that we can avoid creating the gathered form if all uses of Op are
295*9880d681SAndroid Build Coastguard Worker // replaced with uses of CV.
gather(Instruction * Op,const ValueVector & CV)296*9880d681SAndroid Build Coastguard Worker void Scalarizer::gather(Instruction *Op, const ValueVector &CV) {
297*9880d681SAndroid Build Coastguard Worker   // Since we're not deleting Op yet, stub out its operands, so that it
298*9880d681SAndroid Build Coastguard Worker   // doesn't make anything live unnecessarily.
299*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0, E = Op->getNumOperands(); I != E; ++I)
300*9880d681SAndroid Build Coastguard Worker     Op->setOperand(I, UndefValue::get(Op->getOperand(I)->getType()));
301*9880d681SAndroid Build Coastguard Worker 
302*9880d681SAndroid Build Coastguard Worker   transferMetadata(Op, CV);
303*9880d681SAndroid Build Coastguard Worker 
304*9880d681SAndroid Build Coastguard Worker   // If we already have a scattered form of Op (created from ExtractElements
305*9880d681SAndroid Build Coastguard Worker   // of Op itself), replace them with the new form.
306*9880d681SAndroid Build Coastguard Worker   ValueVector &SV = Scattered[Op];
307*9880d681SAndroid Build Coastguard Worker   if (!SV.empty()) {
308*9880d681SAndroid Build Coastguard Worker     for (unsigned I = 0, E = SV.size(); I != E; ++I) {
309*9880d681SAndroid Build Coastguard Worker       Value *V = SV[I];
310*9880d681SAndroid Build Coastguard Worker       if (V == nullptr)
311*9880d681SAndroid Build Coastguard Worker         continue;
312*9880d681SAndroid Build Coastguard Worker 
313*9880d681SAndroid Build Coastguard Worker       Instruction *Old = cast<Instruction>(V);
314*9880d681SAndroid Build Coastguard Worker       CV[I]->takeName(Old);
315*9880d681SAndroid Build Coastguard Worker       Old->replaceAllUsesWith(CV[I]);
316*9880d681SAndroid Build Coastguard Worker       Old->eraseFromParent();
317*9880d681SAndroid Build Coastguard Worker     }
318*9880d681SAndroid Build Coastguard Worker   }
319*9880d681SAndroid Build Coastguard Worker   SV = CV;
320*9880d681SAndroid Build Coastguard Worker   Gathered.push_back(GatherList::value_type(Op, &SV));
321*9880d681SAndroid Build Coastguard Worker }
322*9880d681SAndroid Build Coastguard Worker 
323*9880d681SAndroid Build Coastguard Worker // Return true if it is safe to transfer the given metadata tag from
324*9880d681SAndroid Build Coastguard Worker // vector to scalar instructions.
canTransferMetadata(unsigned Tag)325*9880d681SAndroid Build Coastguard Worker bool Scalarizer::canTransferMetadata(unsigned Tag) {
326*9880d681SAndroid Build Coastguard Worker   return (Tag == LLVMContext::MD_tbaa
327*9880d681SAndroid Build Coastguard Worker           || Tag == LLVMContext::MD_fpmath
328*9880d681SAndroid Build Coastguard Worker           || Tag == LLVMContext::MD_tbaa_struct
329*9880d681SAndroid Build Coastguard Worker           || Tag == LLVMContext::MD_invariant_load
330*9880d681SAndroid Build Coastguard Worker           || Tag == LLVMContext::MD_alias_scope
331*9880d681SAndroid Build Coastguard Worker           || Tag == LLVMContext::MD_noalias
332*9880d681SAndroid Build Coastguard Worker           || Tag == ParallelLoopAccessMDKind);
333*9880d681SAndroid Build Coastguard Worker }
334*9880d681SAndroid Build Coastguard Worker 
335*9880d681SAndroid Build Coastguard Worker // Transfer metadata from Op to the instructions in CV if it is known
336*9880d681SAndroid Build Coastguard Worker // to be safe to do so.
transferMetadata(Instruction * Op,const ValueVector & CV)337*9880d681SAndroid Build Coastguard Worker void Scalarizer::transferMetadata(Instruction *Op, const ValueVector &CV) {
338*9880d681SAndroid Build Coastguard Worker   SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
339*9880d681SAndroid Build Coastguard Worker   Op->getAllMetadataOtherThanDebugLoc(MDs);
340*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0, E = CV.size(); I != E; ++I) {
341*9880d681SAndroid Build Coastguard Worker     if (Instruction *New = dyn_cast<Instruction>(CV[I])) {
342*9880d681SAndroid Build Coastguard Worker       for (const auto &MD : MDs)
343*9880d681SAndroid Build Coastguard Worker         if (canTransferMetadata(MD.first))
344*9880d681SAndroid Build Coastguard Worker           New->setMetadata(MD.first, MD.second);
345*9880d681SAndroid Build Coastguard Worker       if (Op->getDebugLoc() && !New->getDebugLoc())
346*9880d681SAndroid Build Coastguard Worker         New->setDebugLoc(Op->getDebugLoc());
347*9880d681SAndroid Build Coastguard Worker     }
348*9880d681SAndroid Build Coastguard Worker   }
349*9880d681SAndroid Build Coastguard Worker }
350*9880d681SAndroid Build Coastguard Worker 
351*9880d681SAndroid Build Coastguard Worker // Try to fill in Layout from Ty, returning true on success.  Alignment is
352*9880d681SAndroid Build Coastguard Worker // the alignment of the vector, or 0 if the ABI default should be used.
getVectorLayout(Type * Ty,unsigned Alignment,VectorLayout & Layout,const DataLayout & DL)353*9880d681SAndroid Build Coastguard Worker bool Scalarizer::getVectorLayout(Type *Ty, unsigned Alignment,
354*9880d681SAndroid Build Coastguard Worker                                  VectorLayout &Layout, const DataLayout &DL) {
355*9880d681SAndroid Build Coastguard Worker   // Make sure we're dealing with a vector.
356*9880d681SAndroid Build Coastguard Worker   Layout.VecTy = dyn_cast<VectorType>(Ty);
357*9880d681SAndroid Build Coastguard Worker   if (!Layout.VecTy)
358*9880d681SAndroid Build Coastguard Worker     return false;
359*9880d681SAndroid Build Coastguard Worker 
360*9880d681SAndroid Build Coastguard Worker   // Check that we're dealing with full-byte elements.
361*9880d681SAndroid Build Coastguard Worker   Layout.ElemTy = Layout.VecTy->getElementType();
362*9880d681SAndroid Build Coastguard Worker   if (DL.getTypeSizeInBits(Layout.ElemTy) !=
363*9880d681SAndroid Build Coastguard Worker       DL.getTypeStoreSizeInBits(Layout.ElemTy))
364*9880d681SAndroid Build Coastguard Worker     return false;
365*9880d681SAndroid Build Coastguard Worker 
366*9880d681SAndroid Build Coastguard Worker   if (Alignment)
367*9880d681SAndroid Build Coastguard Worker     Layout.VecAlign = Alignment;
368*9880d681SAndroid Build Coastguard Worker   else
369*9880d681SAndroid Build Coastguard Worker     Layout.VecAlign = DL.getABITypeAlignment(Layout.VecTy);
370*9880d681SAndroid Build Coastguard Worker   Layout.ElemSize = DL.getTypeStoreSize(Layout.ElemTy);
371*9880d681SAndroid Build Coastguard Worker   return true;
372*9880d681SAndroid Build Coastguard Worker }
373*9880d681SAndroid Build Coastguard Worker 
374*9880d681SAndroid Build Coastguard Worker // Scalarize two-operand instruction I, using Split(Builder, X, Y, Name)
375*9880d681SAndroid Build Coastguard Worker // to create an instruction like I with operands X and Y and name Name.
376*9880d681SAndroid Build Coastguard Worker template<typename Splitter>
splitBinary(Instruction & I,const Splitter & Split)377*9880d681SAndroid Build Coastguard Worker bool Scalarizer::splitBinary(Instruction &I, const Splitter &Split) {
378*9880d681SAndroid Build Coastguard Worker   VectorType *VT = dyn_cast<VectorType>(I.getType());
379*9880d681SAndroid Build Coastguard Worker   if (!VT)
380*9880d681SAndroid Build Coastguard Worker     return false;
381*9880d681SAndroid Build Coastguard Worker 
382*9880d681SAndroid Build Coastguard Worker   unsigned NumElems = VT->getNumElements();
383*9880d681SAndroid Build Coastguard Worker   IRBuilder<> Builder(&I);
384*9880d681SAndroid Build Coastguard Worker   Scatterer Op0 = scatter(&I, I.getOperand(0));
385*9880d681SAndroid Build Coastguard Worker   Scatterer Op1 = scatter(&I, I.getOperand(1));
386*9880d681SAndroid Build Coastguard Worker   assert(Op0.size() == NumElems && "Mismatched binary operation");
387*9880d681SAndroid Build Coastguard Worker   assert(Op1.size() == NumElems && "Mismatched binary operation");
388*9880d681SAndroid Build Coastguard Worker   ValueVector Res;
389*9880d681SAndroid Build Coastguard Worker   Res.resize(NumElems);
390*9880d681SAndroid Build Coastguard Worker   for (unsigned Elem = 0; Elem < NumElems; ++Elem)
391*9880d681SAndroid Build Coastguard Worker     Res[Elem] = Split(Builder, Op0[Elem], Op1[Elem],
392*9880d681SAndroid Build Coastguard Worker                       I.getName() + ".i" + Twine(Elem));
393*9880d681SAndroid Build Coastguard Worker   gather(&I, Res);
394*9880d681SAndroid Build Coastguard Worker   return true;
395*9880d681SAndroid Build Coastguard Worker }
396*9880d681SAndroid Build Coastguard Worker 
visitSelectInst(SelectInst & SI)397*9880d681SAndroid Build Coastguard Worker bool Scalarizer::visitSelectInst(SelectInst &SI) {
398*9880d681SAndroid Build Coastguard Worker   VectorType *VT = dyn_cast<VectorType>(SI.getType());
399*9880d681SAndroid Build Coastguard Worker   if (!VT)
400*9880d681SAndroid Build Coastguard Worker     return false;
401*9880d681SAndroid Build Coastguard Worker 
402*9880d681SAndroid Build Coastguard Worker   unsigned NumElems = VT->getNumElements();
403*9880d681SAndroid Build Coastguard Worker   IRBuilder<> Builder(&SI);
404*9880d681SAndroid Build Coastguard Worker   Scatterer Op1 = scatter(&SI, SI.getOperand(1));
405*9880d681SAndroid Build Coastguard Worker   Scatterer Op2 = scatter(&SI, SI.getOperand(2));
406*9880d681SAndroid Build Coastguard Worker   assert(Op1.size() == NumElems && "Mismatched select");
407*9880d681SAndroid Build Coastguard Worker   assert(Op2.size() == NumElems && "Mismatched select");
408*9880d681SAndroid Build Coastguard Worker   ValueVector Res;
409*9880d681SAndroid Build Coastguard Worker   Res.resize(NumElems);
410*9880d681SAndroid Build Coastguard Worker 
411*9880d681SAndroid Build Coastguard Worker   if (SI.getOperand(0)->getType()->isVectorTy()) {
412*9880d681SAndroid Build Coastguard Worker     Scatterer Op0 = scatter(&SI, SI.getOperand(0));
413*9880d681SAndroid Build Coastguard Worker     assert(Op0.size() == NumElems && "Mismatched select");
414*9880d681SAndroid Build Coastguard Worker     for (unsigned I = 0; I < NumElems; ++I)
415*9880d681SAndroid Build Coastguard Worker       Res[I] = Builder.CreateSelect(Op0[I], Op1[I], Op2[I],
416*9880d681SAndroid Build Coastguard Worker                                     SI.getName() + ".i" + Twine(I));
417*9880d681SAndroid Build Coastguard Worker   } else {
418*9880d681SAndroid Build Coastguard Worker     Value *Op0 = SI.getOperand(0);
419*9880d681SAndroid Build Coastguard Worker     for (unsigned I = 0; I < NumElems; ++I)
420*9880d681SAndroid Build Coastguard Worker       Res[I] = Builder.CreateSelect(Op0, Op1[I], Op2[I],
421*9880d681SAndroid Build Coastguard Worker                                     SI.getName() + ".i" + Twine(I));
422*9880d681SAndroid Build Coastguard Worker   }
423*9880d681SAndroid Build Coastguard Worker   gather(&SI, Res);
424*9880d681SAndroid Build Coastguard Worker   return true;
425*9880d681SAndroid Build Coastguard Worker }
426*9880d681SAndroid Build Coastguard Worker 
visitICmpInst(ICmpInst & ICI)427*9880d681SAndroid Build Coastguard Worker bool Scalarizer::visitICmpInst(ICmpInst &ICI) {
428*9880d681SAndroid Build Coastguard Worker   return splitBinary(ICI, ICmpSplitter(ICI));
429*9880d681SAndroid Build Coastguard Worker }
430*9880d681SAndroid Build Coastguard Worker 
visitFCmpInst(FCmpInst & FCI)431*9880d681SAndroid Build Coastguard Worker bool Scalarizer::visitFCmpInst(FCmpInst &FCI) {
432*9880d681SAndroid Build Coastguard Worker   return splitBinary(FCI, FCmpSplitter(FCI));
433*9880d681SAndroid Build Coastguard Worker }
434*9880d681SAndroid Build Coastguard Worker 
visitBinaryOperator(BinaryOperator & BO)435*9880d681SAndroid Build Coastguard Worker bool Scalarizer::visitBinaryOperator(BinaryOperator &BO) {
436*9880d681SAndroid Build Coastguard Worker   return splitBinary(BO, BinarySplitter(BO));
437*9880d681SAndroid Build Coastguard Worker }
438*9880d681SAndroid Build Coastguard Worker 
visitGetElementPtrInst(GetElementPtrInst & GEPI)439*9880d681SAndroid Build Coastguard Worker bool Scalarizer::visitGetElementPtrInst(GetElementPtrInst &GEPI) {
440*9880d681SAndroid Build Coastguard Worker   VectorType *VT = dyn_cast<VectorType>(GEPI.getType());
441*9880d681SAndroid Build Coastguard Worker   if (!VT)
442*9880d681SAndroid Build Coastguard Worker     return false;
443*9880d681SAndroid Build Coastguard Worker 
444*9880d681SAndroid Build Coastguard Worker   IRBuilder<> Builder(&GEPI);
445*9880d681SAndroid Build Coastguard Worker   unsigned NumElems = VT->getNumElements();
446*9880d681SAndroid Build Coastguard Worker   unsigned NumIndices = GEPI.getNumIndices();
447*9880d681SAndroid Build Coastguard Worker 
448*9880d681SAndroid Build Coastguard Worker   Scatterer Base = scatter(&GEPI, GEPI.getOperand(0));
449*9880d681SAndroid Build Coastguard Worker 
450*9880d681SAndroid Build Coastguard Worker   SmallVector<Scatterer, 8> Ops;
451*9880d681SAndroid Build Coastguard Worker   Ops.resize(NumIndices);
452*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0; I < NumIndices; ++I)
453*9880d681SAndroid Build Coastguard Worker     Ops[I] = scatter(&GEPI, GEPI.getOperand(I + 1));
454*9880d681SAndroid Build Coastguard Worker 
455*9880d681SAndroid Build Coastguard Worker   ValueVector Res;
456*9880d681SAndroid Build Coastguard Worker   Res.resize(NumElems);
457*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0; I < NumElems; ++I) {
458*9880d681SAndroid Build Coastguard Worker     SmallVector<Value *, 8> Indices;
459*9880d681SAndroid Build Coastguard Worker     Indices.resize(NumIndices);
460*9880d681SAndroid Build Coastguard Worker     for (unsigned J = 0; J < NumIndices; ++J)
461*9880d681SAndroid Build Coastguard Worker       Indices[J] = Ops[J][I];
462*9880d681SAndroid Build Coastguard Worker     Res[I] = Builder.CreateGEP(GEPI.getSourceElementType(), Base[I], Indices,
463*9880d681SAndroid Build Coastguard Worker                                GEPI.getName() + ".i" + Twine(I));
464*9880d681SAndroid Build Coastguard Worker     if (GEPI.isInBounds())
465*9880d681SAndroid Build Coastguard Worker       if (GetElementPtrInst *NewGEPI = dyn_cast<GetElementPtrInst>(Res[I]))
466*9880d681SAndroid Build Coastguard Worker         NewGEPI->setIsInBounds();
467*9880d681SAndroid Build Coastguard Worker   }
468*9880d681SAndroid Build Coastguard Worker   gather(&GEPI, Res);
469*9880d681SAndroid Build Coastguard Worker   return true;
470*9880d681SAndroid Build Coastguard Worker }
471*9880d681SAndroid Build Coastguard Worker 
visitCastInst(CastInst & CI)472*9880d681SAndroid Build Coastguard Worker bool Scalarizer::visitCastInst(CastInst &CI) {
473*9880d681SAndroid Build Coastguard Worker   VectorType *VT = dyn_cast<VectorType>(CI.getDestTy());
474*9880d681SAndroid Build Coastguard Worker   if (!VT)
475*9880d681SAndroid Build Coastguard Worker     return false;
476*9880d681SAndroid Build Coastguard Worker 
477*9880d681SAndroid Build Coastguard Worker   unsigned NumElems = VT->getNumElements();
478*9880d681SAndroid Build Coastguard Worker   IRBuilder<> Builder(&CI);
479*9880d681SAndroid Build Coastguard Worker   Scatterer Op0 = scatter(&CI, CI.getOperand(0));
480*9880d681SAndroid Build Coastguard Worker   assert(Op0.size() == NumElems && "Mismatched cast");
481*9880d681SAndroid Build Coastguard Worker   ValueVector Res;
482*9880d681SAndroid Build Coastguard Worker   Res.resize(NumElems);
483*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0; I < NumElems; ++I)
484*9880d681SAndroid Build Coastguard Worker     Res[I] = Builder.CreateCast(CI.getOpcode(), Op0[I], VT->getElementType(),
485*9880d681SAndroid Build Coastguard Worker                                 CI.getName() + ".i" + Twine(I));
486*9880d681SAndroid Build Coastguard Worker   gather(&CI, Res);
487*9880d681SAndroid Build Coastguard Worker   return true;
488*9880d681SAndroid Build Coastguard Worker }
489*9880d681SAndroid Build Coastguard Worker 
visitBitCastInst(BitCastInst & BCI)490*9880d681SAndroid Build Coastguard Worker bool Scalarizer::visitBitCastInst(BitCastInst &BCI) {
491*9880d681SAndroid Build Coastguard Worker   VectorType *DstVT = dyn_cast<VectorType>(BCI.getDestTy());
492*9880d681SAndroid Build Coastguard Worker   VectorType *SrcVT = dyn_cast<VectorType>(BCI.getSrcTy());
493*9880d681SAndroid Build Coastguard Worker   if (!DstVT || !SrcVT)
494*9880d681SAndroid Build Coastguard Worker     return false;
495*9880d681SAndroid Build Coastguard Worker 
496*9880d681SAndroid Build Coastguard Worker   unsigned DstNumElems = DstVT->getNumElements();
497*9880d681SAndroid Build Coastguard Worker   unsigned SrcNumElems = SrcVT->getNumElements();
498*9880d681SAndroid Build Coastguard Worker   IRBuilder<> Builder(&BCI);
499*9880d681SAndroid Build Coastguard Worker   Scatterer Op0 = scatter(&BCI, BCI.getOperand(0));
500*9880d681SAndroid Build Coastguard Worker   ValueVector Res;
501*9880d681SAndroid Build Coastguard Worker   Res.resize(DstNumElems);
502*9880d681SAndroid Build Coastguard Worker 
503*9880d681SAndroid Build Coastguard Worker   if (DstNumElems == SrcNumElems) {
504*9880d681SAndroid Build Coastguard Worker     for (unsigned I = 0; I < DstNumElems; ++I)
505*9880d681SAndroid Build Coastguard Worker       Res[I] = Builder.CreateBitCast(Op0[I], DstVT->getElementType(),
506*9880d681SAndroid Build Coastguard Worker                                      BCI.getName() + ".i" + Twine(I));
507*9880d681SAndroid Build Coastguard Worker   } else if (DstNumElems > SrcNumElems) {
508*9880d681SAndroid Build Coastguard Worker     // <M x t1> -> <N*M x t2>.  Convert each t1 to <N x t2> and copy the
509*9880d681SAndroid Build Coastguard Worker     // individual elements to the destination.
510*9880d681SAndroid Build Coastguard Worker     unsigned FanOut = DstNumElems / SrcNumElems;
511*9880d681SAndroid Build Coastguard Worker     Type *MidTy = VectorType::get(DstVT->getElementType(), FanOut);
512*9880d681SAndroid Build Coastguard Worker     unsigned ResI = 0;
513*9880d681SAndroid Build Coastguard Worker     for (unsigned Op0I = 0; Op0I < SrcNumElems; ++Op0I) {
514*9880d681SAndroid Build Coastguard Worker       Value *V = Op0[Op0I];
515*9880d681SAndroid Build Coastguard Worker       Instruction *VI;
516*9880d681SAndroid Build Coastguard Worker       // Look through any existing bitcasts before converting to <N x t2>.
517*9880d681SAndroid Build Coastguard Worker       // In the best case, the resulting conversion might be a no-op.
518*9880d681SAndroid Build Coastguard Worker       while ((VI = dyn_cast<Instruction>(V)) &&
519*9880d681SAndroid Build Coastguard Worker              VI->getOpcode() == Instruction::BitCast)
520*9880d681SAndroid Build Coastguard Worker         V = VI->getOperand(0);
521*9880d681SAndroid Build Coastguard Worker       V = Builder.CreateBitCast(V, MidTy, V->getName() + ".cast");
522*9880d681SAndroid Build Coastguard Worker       Scatterer Mid = scatter(&BCI, V);
523*9880d681SAndroid Build Coastguard Worker       for (unsigned MidI = 0; MidI < FanOut; ++MidI)
524*9880d681SAndroid Build Coastguard Worker         Res[ResI++] = Mid[MidI];
525*9880d681SAndroid Build Coastguard Worker     }
526*9880d681SAndroid Build Coastguard Worker   } else {
527*9880d681SAndroid Build Coastguard Worker     // <N*M x t1> -> <M x t2>.  Convert each group of <N x t1> into a t2.
528*9880d681SAndroid Build Coastguard Worker     unsigned FanIn = SrcNumElems / DstNumElems;
529*9880d681SAndroid Build Coastguard Worker     Type *MidTy = VectorType::get(SrcVT->getElementType(), FanIn);
530*9880d681SAndroid Build Coastguard Worker     unsigned Op0I = 0;
531*9880d681SAndroid Build Coastguard Worker     for (unsigned ResI = 0; ResI < DstNumElems; ++ResI) {
532*9880d681SAndroid Build Coastguard Worker       Value *V = UndefValue::get(MidTy);
533*9880d681SAndroid Build Coastguard Worker       for (unsigned MidI = 0; MidI < FanIn; ++MidI)
534*9880d681SAndroid Build Coastguard Worker         V = Builder.CreateInsertElement(V, Op0[Op0I++], Builder.getInt32(MidI),
535*9880d681SAndroid Build Coastguard Worker                                         BCI.getName() + ".i" + Twine(ResI)
536*9880d681SAndroid Build Coastguard Worker                                         + ".upto" + Twine(MidI));
537*9880d681SAndroid Build Coastguard Worker       Res[ResI] = Builder.CreateBitCast(V, DstVT->getElementType(),
538*9880d681SAndroid Build Coastguard Worker                                         BCI.getName() + ".i" + Twine(ResI));
539*9880d681SAndroid Build Coastguard Worker     }
540*9880d681SAndroid Build Coastguard Worker   }
541*9880d681SAndroid Build Coastguard Worker   gather(&BCI, Res);
542*9880d681SAndroid Build Coastguard Worker   return true;
543*9880d681SAndroid Build Coastguard Worker }
544*9880d681SAndroid Build Coastguard Worker 
visitShuffleVectorInst(ShuffleVectorInst & SVI)545*9880d681SAndroid Build Coastguard Worker bool Scalarizer::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
546*9880d681SAndroid Build Coastguard Worker   VectorType *VT = dyn_cast<VectorType>(SVI.getType());
547*9880d681SAndroid Build Coastguard Worker   if (!VT)
548*9880d681SAndroid Build Coastguard Worker     return false;
549*9880d681SAndroid Build Coastguard Worker 
550*9880d681SAndroid Build Coastguard Worker   unsigned NumElems = VT->getNumElements();
551*9880d681SAndroid Build Coastguard Worker   Scatterer Op0 = scatter(&SVI, SVI.getOperand(0));
552*9880d681SAndroid Build Coastguard Worker   Scatterer Op1 = scatter(&SVI, SVI.getOperand(1));
553*9880d681SAndroid Build Coastguard Worker   ValueVector Res;
554*9880d681SAndroid Build Coastguard Worker   Res.resize(NumElems);
555*9880d681SAndroid Build Coastguard Worker 
556*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0; I < NumElems; ++I) {
557*9880d681SAndroid Build Coastguard Worker     int Selector = SVI.getMaskValue(I);
558*9880d681SAndroid Build Coastguard Worker     if (Selector < 0)
559*9880d681SAndroid Build Coastguard Worker       Res[I] = UndefValue::get(VT->getElementType());
560*9880d681SAndroid Build Coastguard Worker     else if (unsigned(Selector) < Op0.size())
561*9880d681SAndroid Build Coastguard Worker       Res[I] = Op0[Selector];
562*9880d681SAndroid Build Coastguard Worker     else
563*9880d681SAndroid Build Coastguard Worker       Res[I] = Op1[Selector - Op0.size()];
564*9880d681SAndroid Build Coastguard Worker   }
565*9880d681SAndroid Build Coastguard Worker   gather(&SVI, Res);
566*9880d681SAndroid Build Coastguard Worker   return true;
567*9880d681SAndroid Build Coastguard Worker }
568*9880d681SAndroid Build Coastguard Worker 
visitPHINode(PHINode & PHI)569*9880d681SAndroid Build Coastguard Worker bool Scalarizer::visitPHINode(PHINode &PHI) {
570*9880d681SAndroid Build Coastguard Worker   VectorType *VT = dyn_cast<VectorType>(PHI.getType());
571*9880d681SAndroid Build Coastguard Worker   if (!VT)
572*9880d681SAndroid Build Coastguard Worker     return false;
573*9880d681SAndroid Build Coastguard Worker 
574*9880d681SAndroid Build Coastguard Worker   unsigned NumElems = VT->getNumElements();
575*9880d681SAndroid Build Coastguard Worker   IRBuilder<> Builder(&PHI);
576*9880d681SAndroid Build Coastguard Worker   ValueVector Res;
577*9880d681SAndroid Build Coastguard Worker   Res.resize(NumElems);
578*9880d681SAndroid Build Coastguard Worker 
579*9880d681SAndroid Build Coastguard Worker   unsigned NumOps = PHI.getNumOperands();
580*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0; I < NumElems; ++I)
581*9880d681SAndroid Build Coastguard Worker     Res[I] = Builder.CreatePHI(VT->getElementType(), NumOps,
582*9880d681SAndroid Build Coastguard Worker                                PHI.getName() + ".i" + Twine(I));
583*9880d681SAndroid Build Coastguard Worker 
584*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0; I < NumOps; ++I) {
585*9880d681SAndroid Build Coastguard Worker     Scatterer Op = scatter(&PHI, PHI.getIncomingValue(I));
586*9880d681SAndroid Build Coastguard Worker     BasicBlock *IncomingBlock = PHI.getIncomingBlock(I);
587*9880d681SAndroid Build Coastguard Worker     for (unsigned J = 0; J < NumElems; ++J)
588*9880d681SAndroid Build Coastguard Worker       cast<PHINode>(Res[J])->addIncoming(Op[J], IncomingBlock);
589*9880d681SAndroid Build Coastguard Worker   }
590*9880d681SAndroid Build Coastguard Worker   gather(&PHI, Res);
591*9880d681SAndroid Build Coastguard Worker   return true;
592*9880d681SAndroid Build Coastguard Worker }
593*9880d681SAndroid Build Coastguard Worker 
visitLoadInst(LoadInst & LI)594*9880d681SAndroid Build Coastguard Worker bool Scalarizer::visitLoadInst(LoadInst &LI) {
595*9880d681SAndroid Build Coastguard Worker   if (!ScalarizeLoadStore)
596*9880d681SAndroid Build Coastguard Worker     return false;
597*9880d681SAndroid Build Coastguard Worker   if (!LI.isSimple())
598*9880d681SAndroid Build Coastguard Worker     return false;
599*9880d681SAndroid Build Coastguard Worker 
600*9880d681SAndroid Build Coastguard Worker   VectorLayout Layout;
601*9880d681SAndroid Build Coastguard Worker   if (!getVectorLayout(LI.getType(), LI.getAlignment(), Layout,
602*9880d681SAndroid Build Coastguard Worker                        LI.getModule()->getDataLayout()))
603*9880d681SAndroid Build Coastguard Worker     return false;
604*9880d681SAndroid Build Coastguard Worker 
605*9880d681SAndroid Build Coastguard Worker   unsigned NumElems = Layout.VecTy->getNumElements();
606*9880d681SAndroid Build Coastguard Worker   IRBuilder<> Builder(&LI);
607*9880d681SAndroid Build Coastguard Worker   Scatterer Ptr = scatter(&LI, LI.getPointerOperand());
608*9880d681SAndroid Build Coastguard Worker   ValueVector Res;
609*9880d681SAndroid Build Coastguard Worker   Res.resize(NumElems);
610*9880d681SAndroid Build Coastguard Worker 
611*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0; I < NumElems; ++I)
612*9880d681SAndroid Build Coastguard Worker     Res[I] = Builder.CreateAlignedLoad(Ptr[I], Layout.getElemAlign(I),
613*9880d681SAndroid Build Coastguard Worker                                        LI.getName() + ".i" + Twine(I));
614*9880d681SAndroid Build Coastguard Worker   gather(&LI, Res);
615*9880d681SAndroid Build Coastguard Worker   return true;
616*9880d681SAndroid Build Coastguard Worker }
617*9880d681SAndroid Build Coastguard Worker 
visitStoreInst(StoreInst & SI)618*9880d681SAndroid Build Coastguard Worker bool Scalarizer::visitStoreInst(StoreInst &SI) {
619*9880d681SAndroid Build Coastguard Worker   if (!ScalarizeLoadStore)
620*9880d681SAndroid Build Coastguard Worker     return false;
621*9880d681SAndroid Build Coastguard Worker   if (!SI.isSimple())
622*9880d681SAndroid Build Coastguard Worker     return false;
623*9880d681SAndroid Build Coastguard Worker 
624*9880d681SAndroid Build Coastguard Worker   VectorLayout Layout;
625*9880d681SAndroid Build Coastguard Worker   Value *FullValue = SI.getValueOperand();
626*9880d681SAndroid Build Coastguard Worker   if (!getVectorLayout(FullValue->getType(), SI.getAlignment(), Layout,
627*9880d681SAndroid Build Coastguard Worker                        SI.getModule()->getDataLayout()))
628*9880d681SAndroid Build Coastguard Worker     return false;
629*9880d681SAndroid Build Coastguard Worker 
630*9880d681SAndroid Build Coastguard Worker   unsigned NumElems = Layout.VecTy->getNumElements();
631*9880d681SAndroid Build Coastguard Worker   IRBuilder<> Builder(&SI);
632*9880d681SAndroid Build Coastguard Worker   Scatterer Ptr = scatter(&SI, SI.getPointerOperand());
633*9880d681SAndroid Build Coastguard Worker   Scatterer Val = scatter(&SI, FullValue);
634*9880d681SAndroid Build Coastguard Worker 
635*9880d681SAndroid Build Coastguard Worker   ValueVector Stores;
636*9880d681SAndroid Build Coastguard Worker   Stores.resize(NumElems);
637*9880d681SAndroid Build Coastguard Worker   for (unsigned I = 0; I < NumElems; ++I) {
638*9880d681SAndroid Build Coastguard Worker     unsigned Align = Layout.getElemAlign(I);
639*9880d681SAndroid Build Coastguard Worker     Stores[I] = Builder.CreateAlignedStore(Val[I], Ptr[I], Align);
640*9880d681SAndroid Build Coastguard Worker   }
641*9880d681SAndroid Build Coastguard Worker   transferMetadata(&SI, Stores);
642*9880d681SAndroid Build Coastguard Worker   return true;
643*9880d681SAndroid Build Coastguard Worker }
644*9880d681SAndroid Build Coastguard Worker 
645*9880d681SAndroid Build Coastguard Worker // Delete the instructions that we scalarized.  If a full vector result
646*9880d681SAndroid Build Coastguard Worker // is still needed, recreate it using InsertElements.
finish()647*9880d681SAndroid Build Coastguard Worker bool Scalarizer::finish() {
648*9880d681SAndroid Build Coastguard Worker   // The presence of data in Gathered or Scattered indicates changes
649*9880d681SAndroid Build Coastguard Worker   // made to the Function.
650*9880d681SAndroid Build Coastguard Worker   if (Gathered.empty() && Scattered.empty())
651*9880d681SAndroid Build Coastguard Worker     return false;
652*9880d681SAndroid Build Coastguard Worker   for (const auto &GMI : Gathered) {
653*9880d681SAndroid Build Coastguard Worker     Instruction *Op = GMI.first;
654*9880d681SAndroid Build Coastguard Worker     ValueVector &CV = *GMI.second;
655*9880d681SAndroid Build Coastguard Worker     if (!Op->use_empty()) {
656*9880d681SAndroid Build Coastguard Worker       // The value is still needed, so recreate it using a series of
657*9880d681SAndroid Build Coastguard Worker       // InsertElements.
658*9880d681SAndroid Build Coastguard Worker       Type *Ty = Op->getType();
659*9880d681SAndroid Build Coastguard Worker       Value *Res = UndefValue::get(Ty);
660*9880d681SAndroid Build Coastguard Worker       BasicBlock *BB = Op->getParent();
661*9880d681SAndroid Build Coastguard Worker       unsigned Count = Ty->getVectorNumElements();
662*9880d681SAndroid Build Coastguard Worker       IRBuilder<> Builder(Op);
663*9880d681SAndroid Build Coastguard Worker       if (isa<PHINode>(Op))
664*9880d681SAndroid Build Coastguard Worker         Builder.SetInsertPoint(BB, BB->getFirstInsertionPt());
665*9880d681SAndroid Build Coastguard Worker       for (unsigned I = 0; I < Count; ++I)
666*9880d681SAndroid Build Coastguard Worker         Res = Builder.CreateInsertElement(Res, CV[I], Builder.getInt32(I),
667*9880d681SAndroid Build Coastguard Worker                                           Op->getName() + ".upto" + Twine(I));
668*9880d681SAndroid Build Coastguard Worker       Res->takeName(Op);
669*9880d681SAndroid Build Coastguard Worker       Op->replaceAllUsesWith(Res);
670*9880d681SAndroid Build Coastguard Worker     }
671*9880d681SAndroid Build Coastguard Worker     Op->eraseFromParent();
672*9880d681SAndroid Build Coastguard Worker   }
673*9880d681SAndroid Build Coastguard Worker   Gathered.clear();
674*9880d681SAndroid Build Coastguard Worker   Scattered.clear();
675*9880d681SAndroid Build Coastguard Worker   return true;
676*9880d681SAndroid Build Coastguard Worker }
677*9880d681SAndroid Build Coastguard Worker 
createScalarizerPass()678*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createScalarizerPass() {
679*9880d681SAndroid Build Coastguard Worker   return new Scalarizer();
680*9880d681SAndroid Build Coastguard Worker }
681