diff options
Diffstat (limited to 'lib/Transforms/Scalar/Scalarizer.cpp')
-rw-r--r-- | lib/Transforms/Scalar/Scalarizer.cpp | 70 |
1 files changed, 54 insertions, 16 deletions
diff --git a/lib/Transforms/Scalar/Scalarizer.cpp b/lib/Transforms/Scalar/Scalarizer.cpp index 5eb3fdab6d5c..2ee1a3a95f2a 100644 --- a/lib/Transforms/Scalar/Scalarizer.cpp +++ b/lib/Transforms/Scalar/Scalarizer.cpp @@ -1,9 +1,8 @@ //===- Scalarizer.cpp - Scalarize vector operations -----------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -125,6 +124,18 @@ struct ICmpSplitter { ICmpInst &ICI; }; +// UnarySpliiter(UO)(Builder, X, Name) uses Builder to create +// a unary operator like UO called Name with operand X. +struct UnarySplitter { + UnarySplitter(UnaryOperator &uo) : UO(uo) {} + + Value *operator()(IRBuilder<> &Builder, Value *Op, const Twine &Name) const { + return Builder.CreateUnOp(UO.getOpcode(), Op, Name); + } + + UnaryOperator &UO; +}; + // BinarySpliiter(BO)(Builder, X, Y, Name) uses Builder to create // a binary operator like BO called Name with operands X and Y. struct BinarySplitter { @@ -174,6 +185,7 @@ public: bool visitSelectInst(SelectInst &SI); bool visitICmpInst(ICmpInst &ICI); bool visitFCmpInst(FCmpInst &FCI); + bool visitUnaryOperator(UnaryOperator &UO); bool visitBinaryOperator(BinaryOperator &BO); bool visitGetElementPtrInst(GetElementPtrInst &GEPI); bool visitCastInst(CastInst &CI); @@ -188,11 +200,12 @@ private: Scatterer scatter(Instruction *Point, Value *V); void gather(Instruction *Op, const ValueVector &CV); bool canTransferMetadata(unsigned Kind); - void transferMetadata(Instruction *Op, const ValueVector &CV); + void transferMetadataAndIRFlags(Instruction *Op, const ValueVector &CV); bool getVectorLayout(Type *Ty, unsigned Alignment, VectorLayout &Layout, const DataLayout &DL); bool finish(); + template<typename T> bool splitUnary(Instruction &, const T &); template<typename T> bool splitBinary(Instruction &, const T &); bool splitCall(CallInst &CI); @@ -246,14 +259,13 @@ Value *Scatterer::operator[](unsigned I) { return CV[I]; IRBuilder<> Builder(BB, BBI); if (PtrTy) { + Type *ElTy = PtrTy->getElementType()->getVectorElementType(); if (!CV[0]) { - Type *Ty = - PointerType::get(PtrTy->getElementType()->getVectorElementType(), - PtrTy->getAddressSpace()); - CV[0] = Builder.CreateBitCast(V, Ty, V->getName() + ".i0"); + Type *NewPtrTy = PointerType::get(ElTy, PtrTy->getAddressSpace()); + CV[0] = Builder.CreateBitCast(V, NewPtrTy, V->getName() + ".i0"); } if (I != 0) - CV[I] = Builder.CreateConstGEP1_32(nullptr, CV[0], I, + CV[I] = Builder.CreateConstGEP1_32(ElTy, CV[0], I, V->getName() + ".i" + Twine(I)); } else { // Search through a chain of InsertElementInsts looking for element I. @@ -349,7 +361,7 @@ void ScalarizerVisitor::gather(Instruction *Op, const ValueVector &CV) { for (unsigned I = 0, E = Op->getNumOperands(); I != E; ++I) Op->setOperand(I, UndefValue::get(Op->getOperand(I)->getType())); - transferMetadata(Op, CV); + transferMetadataAndIRFlags(Op, CV); // If we already have a scattered form of Op (created from ExtractElements // of Op itself), replace them with the new form. @@ -385,7 +397,8 @@ bool ScalarizerVisitor::canTransferMetadata(unsigned Tag) { // Transfer metadata from Op to the instructions in CV if it is known // to be safe to do so. -void ScalarizerVisitor::transferMetadata(Instruction *Op, const ValueVector &CV) { +void ScalarizerVisitor::transferMetadataAndIRFlags(Instruction *Op, + const ValueVector &CV) { SmallVector<std::pair<unsigned, MDNode *>, 4> MDs; Op->getAllMetadataOtherThanDebugLoc(MDs); for (unsigned I = 0, E = CV.size(); I != E; ++I) { @@ -393,6 +406,7 @@ void ScalarizerVisitor::transferMetadata(Instruction *Op, const ValueVector &CV) for (const auto &MD : MDs) if (canTransferMetadata(MD.first)) New->setMetadata(MD.first, MD.second); + New->copyIRFlags(Op); if (Op->getDebugLoc() && !New->getDebugLoc()) New->setDebugLoc(Op->getDebugLoc()); } @@ -410,8 +424,7 @@ bool ScalarizerVisitor::getVectorLayout(Type *Ty, unsigned Alignment, // Check that we're dealing with full-byte elements. Layout.ElemTy = Layout.VecTy->getElementType(); - if (DL.getTypeSizeInBits(Layout.ElemTy) != - DL.getTypeStoreSizeInBits(Layout.ElemTy)) + if (!DL.typeSizeEqualsStoreSize(Layout.ElemTy)) return false; if (Alignment) @@ -422,6 +435,26 @@ bool ScalarizerVisitor::getVectorLayout(Type *Ty, unsigned Alignment, return true; } +// Scalarize one-operand instruction I, using Split(Builder, X, Name) +// to create an instruction like I with operand X and name Name. +template<typename Splitter> +bool ScalarizerVisitor::splitUnary(Instruction &I, const Splitter &Split) { + VectorType *VT = dyn_cast<VectorType>(I.getType()); + if (!VT) + return false; + + unsigned NumElems = VT->getNumElements(); + IRBuilder<> Builder(&I); + Scatterer Op = scatter(&I, I.getOperand(0)); + assert(Op.size() == NumElems && "Mismatched unary operation"); + ValueVector Res; + Res.resize(NumElems); + for (unsigned Elem = 0; Elem < NumElems; ++Elem) + Res[Elem] = Split(Builder, Op[Elem], I.getName() + ".i" + Twine(Elem)); + gather(&I, Res); + return true; +} + // Scalarize two-operand instruction I, using Split(Builder, X, Y, Name) // to create an instruction like I with operands X and Y and name Name. template<typename Splitter> @@ -554,6 +587,10 @@ bool ScalarizerVisitor::visitFCmpInst(FCmpInst &FCI) { return splitBinary(FCI, FCmpSplitter(FCI)); } +bool ScalarizerVisitor::visitUnaryOperator(UnaryOperator &UO) { + return splitUnary(UO, UnarySplitter(UO)); +} + bool ScalarizerVisitor::visitBinaryOperator(BinaryOperator &BO) { return splitBinary(BO, BinarySplitter(BO)); } @@ -744,7 +781,8 @@ bool ScalarizerVisitor::visitLoadInst(LoadInst &LI) { Res.resize(NumElems); for (unsigned I = 0; I < NumElems; ++I) - Res[I] = Builder.CreateAlignedLoad(Ptr[I], Layout.getElemAlign(I), + Res[I] = Builder.CreateAlignedLoad(Layout.VecTy->getElementType(), Ptr[I], + Layout.getElemAlign(I), LI.getName() + ".i" + Twine(I)); gather(&LI, Res); return true; @@ -773,7 +811,7 @@ bool ScalarizerVisitor::visitStoreInst(StoreInst &SI) { unsigned Align = Layout.getElemAlign(I); Stores[I] = Builder.CreateAlignedStore(Val[I], Ptr[I], Align); } - transferMetadata(&SI, Stores); + transferMetadataAndIRFlags(&SI, Stores); return true; } |