aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/Scalar/Scalarizer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms/Scalar/Scalarizer.cpp')
-rw-r--r--lib/Transforms/Scalar/Scalarizer.cpp70
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;
}