From: Benjamin Kramer Date: Tue, 18 Sep 2012 16:20:46 +0000 (+0000) Subject: SROA: Replace the member function template contraption for recursively splitting... X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=6e67b254ae2cf2411cb2d1ae41bf0fbc05079f40;p=oota-llvm.git SROA: Replace the member function template contraption for recursively splitting aggregates into a real class. No intended functionality change. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@164135 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/Scalar/SROA.cpp b/lib/Transforms/Scalar/SROA.cpp index 09bcc3380f1..b9318db5e33 100644 --- a/lib/Transforms/Scalar/SROA.cpp +++ b/lib/Transforms/Scalar/SROA.cpp @@ -2465,83 +2465,96 @@ private: // Conservative default is to not rewrite anything. bool visitInstruction(Instruction &I) { return false; } - /// \brief Generic recursive split emission routine. - /// - /// This method recursively splits an aggregate op (load or store) into - /// scalar or vector ops. It splits recursively until it hits a single value - /// and emits that single value operation via the template argument. - /// - /// The logic of this routine relies on GEPs and insertvalue and extractvalue - /// all operating with the same fundamental index list, merely formatted - /// differently (GEPs need actual values). - /// - /// \param IRB The builder used to form new instructions. - /// \param Ty The type being split recursively into smaller ops. - /// \param Agg The aggregate value being built up or stored, depending on - /// whether this is splitting a load or a store respectively. - /// \param Ptr The base pointer of the original op, used as a base for GEPing - /// the split operations. - /// \param Indices The indices which to be used with insert- or extractvalue - /// to select the appropriate value within the aggregate for \p Ty. - /// \param GEPIndices The indices to a GEP instruction which will move \p Ptr - /// to the correct slot within the aggregate for \p Ty. - template &IRB, Type *Ty, Value *&Agg, Value *Ptr, - ArrayRef, ArrayRef, - const Twine &Name)> - void emitSplitOps(IRBuilder<> &IRB, Type *Ty, Value *&Agg, Value *Ptr, - SmallVectorImpl &Indices, - SmallVectorImpl &GEPIndices, - const Twine &Name) { - if (Ty->isSingleValueType()) - return (this->*emitFunc)(IRB, Ty, Agg, Ptr, Indices, GEPIndices, Name); - - if (ArrayType *ATy = dyn_cast(Ty)) { - unsigned OldSize = Indices.size(); - (void)OldSize; - for (unsigned Idx = 0, Size = ATy->getNumElements(); Idx != Size; ++Idx) { - assert(Indices.size() == OldSize && "Did not return to the old size"); - Indices.push_back(Idx); - GEPIndices.push_back(IRB.getInt32(Idx)); - emitSplitOps(IRB, ATy->getElementType(), Agg, Ptr, - Indices, GEPIndices, Name + "." + Twine(Idx)); - GEPIndices.pop_back(); - Indices.pop_back(); + /// \brief Generic recursive split emission class. + class OpSplitter { + protected: + /// The builder used to form new instructions. + IRBuilder<> IRB; + /// The indices which to be used with insert- or extractvalue to select the + /// appropriate value within the aggregate. + SmallVector Indices; + /// The indices to a GEP instruction which will move Ptr to the correct slot + /// within the aggregate. + SmallVector GEPIndices; + /// The base pointer of the original op, used as a base for GEPing the + /// split operations. + Value *Ptr; + + /// Initialize the splitter with an insertion point, Ptr and start with a + /// single zero GEP index. + OpSplitter(Instruction *InsertionPoint, Value *Ptr) + : IRB(InsertionPoint), Ptr(Ptr), GEPIndices(1, IRB.getInt32(0)) {} + + public: + virtual void emitFunc(Type *Ty, Value *&Agg, const Twine &Name) = 0; + + /// \brief Generic recursive split emission routine. + /// + /// This method recursively splits an aggregate op (load or store) into + /// scalar or vector ops. It splits recursively until it hits a single value + /// and emits that single value operation via the template argument. + /// + /// The logic of this routine relies on GEPs and insertvalue and + /// extractvalue all operating with the same fundamental index list, merely + /// formatted differently (GEPs need actual values). + /// + /// \param Ty The type being split recursively into smaller ops. + /// \param Agg The aggregate value being built up or stored, depending on + /// whether this is splitting a load or a store respectively. + void emitSplitOps(Type *Ty, Value *&Agg, const Twine &Name) { + if (Ty->isSingleValueType()) + return emitFunc(Ty, Agg, Name); + + if (ArrayType *ATy = dyn_cast(Ty)) { + unsigned OldSize = Indices.size(); + (void)OldSize; + for (unsigned Idx = 0, Size = ATy->getNumElements(); Idx != Size; + ++Idx) { + assert(Indices.size() == OldSize && "Did not return to the old size"); + Indices.push_back(Idx); + GEPIndices.push_back(IRB.getInt32(Idx)); + emitSplitOps(ATy->getElementType(), Agg, Name + "." + Twine(Idx)); + GEPIndices.pop_back(); + Indices.pop_back(); + } + return; } - return; - } - if (StructType *STy = dyn_cast(Ty)) { - unsigned OldSize = Indices.size(); - (void)OldSize; - for (unsigned Idx = 0, Size = STy->getNumElements(); Idx != Size; ++Idx) { - assert(Indices.size() == OldSize && "Did not return to the old size"); - Indices.push_back(Idx); - GEPIndices.push_back(IRB.getInt32(Idx)); - emitSplitOps(IRB, STy->getElementType(Idx), Agg, Ptr, - Indices, GEPIndices, Name + "." + Twine(Idx)); - GEPIndices.pop_back(); - Indices.pop_back(); + if (StructType *STy = dyn_cast(Ty)) { + unsigned OldSize = Indices.size(); + (void)OldSize; + for (unsigned Idx = 0, Size = STy->getNumElements(); Idx != Size; + ++Idx) { + assert(Indices.size() == OldSize && "Did not return to the old size"); + Indices.push_back(Idx); + GEPIndices.push_back(IRB.getInt32(Idx)); + emitSplitOps(STy->getElementType(Idx), Agg, Name + "." + Twine(Idx)); + GEPIndices.pop_back(); + Indices.pop_back(); + } + return; } - return; - } - llvm_unreachable("Only arrays and structs are aggregate loadable types"); - } + llvm_unreachable("Only arrays and structs are aggregate loadable types"); + } + }; - /// Emit a leaf load of a single value. This is called at the leaves of the - /// recursive emission to actually load values. - void emitLoad(IRBuilder<> &IRB, Type *Ty, Value *&Agg, Value *Ptr, - ArrayRef Indices, ArrayRef GEPIndices, - const Twine &Name) { - assert(Ty->isSingleValueType()); - // Load the single value and insert it using the indices. - Value *Load = IRB.CreateLoad(IRB.CreateInBoundsGEP(Ptr, GEPIndices, - Name + ".gep"), - Name + ".load"); - Agg = IRB.CreateInsertValue(Agg, Load, Indices, Name + ".insert"); - DEBUG(dbgs() << " to: " << *Load << "\n"); - } + struct LoadOpSplitter : public OpSplitter { + LoadOpSplitter(Instruction *InsertionPoint, Value *Ptr) + : OpSplitter(InsertionPoint, Ptr) {} + + /// Emit a leaf load of a single value. This is called at the leaves of the + /// recursive emission to actually load values. + virtual void emitFunc(Type *Ty, Value *&Agg, const Twine &Name) { + assert(Ty->isSingleValueType()); + // Load the single value and insert it using the indices. + Value *Load = IRB.CreateLoad(IRB.CreateInBoundsGEP(Ptr, GEPIndices, + Name + ".gep"), + Name + ".load"); + Agg = IRB.CreateInsertValue(Agg, Load, Indices, Name + ".insert"); + DEBUG(dbgs() << " to: " << *Load << "\n"); + } + }; bool visitLoadInst(LoadInst &LI) { assert(LI.getPointerOperand() == *U); @@ -2550,31 +2563,30 @@ private: // We have an aggregate being loaded, split it apart. DEBUG(dbgs() << " original: " << LI << "\n"); - IRBuilder<> IRB(&LI); + LoadOpSplitter Splitter(&LI, *U); Value *V = UndefValue::get(LI.getType()); - SmallVector Indices; - SmallVector GEPIndices; - GEPIndices.push_back(IRB.getInt32(0)); - emitSplitOps<&AggLoadStoreRewriter::emitLoad>( - IRB, LI.getType(), V, *U, Indices, GEPIndices, LI.getName() + ".fca"); + Splitter.emitSplitOps(LI.getType(), V, LI.getName() + ".fca"); LI.replaceAllUsesWith(V); LI.eraseFromParent(); return true; } - /// Emit a leaf store of a single value. This is called at the leaves of the - /// recursive emission to actually produce stores. - void emitStore(IRBuilder<> &IRB, Type *Ty, Value *&Agg, Value *Ptr, - ArrayRef Indices, ArrayRef GEPIndices, - const Twine &Name) { - assert(Ty->isSingleValueType()); - // Extract the single value and store it using the indices. - Value *Store = IRB.CreateStore( - IRB.CreateExtractValue(Agg, Indices, Name + ".extract"), - IRB.CreateInBoundsGEP(Ptr, GEPIndices, Name + ".gep")); - (void)Store; - DEBUG(dbgs() << " to: " << *Store << "\n"); - } + struct StoreOpSplitter : public OpSplitter { + StoreOpSplitter(Instruction *InsertionPoint, Value *Ptr) + : OpSplitter(InsertionPoint, Ptr) {} + + /// Emit a leaf store of a single value. This is called at the leaves of the + /// recursive emission to actually produce stores. + virtual void emitFunc(Type *Ty, Value *&Agg, const Twine &Name) { + assert(Ty->isSingleValueType()); + // Extract the single value and store it using the indices. + Value *Store = IRB.CreateStore( + IRB.CreateExtractValue(Agg, Indices, Name + ".extract"), + IRB.CreateInBoundsGEP(Ptr, GEPIndices, Name + ".gep")); + (void)Store; + DEBUG(dbgs() << " to: " << *Store << "\n"); + } + }; bool visitStoreInst(StoreInst &SI) { if (!SI.isSimple() || SI.getPointerOperand() != *U) @@ -2585,12 +2597,8 @@ private: // We have an aggregate being stored, split it apart. DEBUG(dbgs() << " original: " << SI << "\n"); - IRBuilder<> IRB(&SI); - SmallVector Indices; - SmallVector GEPIndices; - GEPIndices.push_back(IRB.getInt32(0)); - emitSplitOps<&AggLoadStoreRewriter::emitStore>( - IRB, V->getType(), V, *U, Indices, GEPIndices, V->getName() + ".fca"); + StoreOpSplitter Splitter(&SI, *U); + Splitter.emitSplitOps(V->getType(), V, V->getName() + ".fca"); SI.eraseFromParent(); return true; }