summaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Scalar/Scalarizer.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
commitcfca06d7963fa0909f90483b42a6d7d194d01e08 (patch)
tree209fb2a2d68f8f277793fc8df46c753d31bc853b /llvm/lib/Transforms/Scalar/Scalarizer.cpp
parent706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff)
Notes
Diffstat (limited to 'llvm/lib/Transforms/Scalar/Scalarizer.cpp')
-rw-r--r--llvm/lib/Transforms/Scalar/Scalarizer.cpp250
1 files changed, 169 insertions, 81 deletions
diff --git a/llvm/lib/Transforms/Scalar/Scalarizer.cpp b/llvm/lib/Transforms/Scalar/Scalarizer.cpp
index c25c6c632b8f0..851bd79cd6d83 100644
--- a/llvm/lib/Transforms/Scalar/Scalarizer.cpp
+++ b/llvm/lib/Transforms/Scalar/Scalarizer.cpp
@@ -22,8 +22,8 @@
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/Dominators.h"
#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InstVisitor.h"
@@ -41,6 +41,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Utils/Local.h"
#include <cassert>
#include <cstdint>
#include <iterator>
@@ -51,6 +52,11 @@ using namespace llvm;
#define DEBUG_TYPE "scalarizer"
+static cl::opt<bool> ScalarizeVariableInsertExtract(
+ "scalarize-variable-insert-extract", cl::init(true), cl::Hidden,
+ cl::desc("Allow the scalarizer pass to scalarize "
+ "insertelement/extractelement with variable index"));
+
// This is disabled by default because having separate loads and stores
// makes it more likely that the -combiner-alias-analysis limits will be
// reached.
@@ -156,8 +162,8 @@ struct VectorLayout {
VectorLayout() = default;
// Return the alignment of element I.
- uint64_t getElemAlign(unsigned I) {
- return MinAlign(VecAlign, I * ElemSize);
+ Align getElemAlign(unsigned I) {
+ return commonAlignment(VecAlign, I * ElemSize);
}
// The type of the vector.
@@ -167,7 +173,7 @@ struct VectorLayout {
Type *ElemTy = nullptr;
// The alignment of the vector.
- uint64_t VecAlign = 0;
+ Align VecAlign;
// The size of each element.
uint64_t ElemSize = 0;
@@ -192,6 +198,8 @@ public:
bool visitGetElementPtrInst(GetElementPtrInst &GEPI);
bool visitCastInst(CastInst &CI);
bool visitBitCastInst(BitCastInst &BCI);
+ bool visitInsertElementInst(InsertElementInst &IEI);
+ bool visitExtractElementInst(ExtractElementInst &EEI);
bool visitShuffleVectorInst(ShuffleVectorInst &SVI);
bool visitPHINode(PHINode &PHI);
bool visitLoadInst(LoadInst &LI);
@@ -203,8 +211,8 @@ private:
void gather(Instruction *Op, const ValueVector &CV);
bool canTransferMetadata(unsigned Kind);
void transferMetadataAndIRFlags(Instruction *Op, const ValueVector &CV);
- bool getVectorLayout(Type *Ty, unsigned Alignment, VectorLayout &Layout,
- const DataLayout &DL);
+ Optional<VectorLayout> getVectorLayout(Type *Ty, Align Alignment,
+ const DataLayout &DL);
bool finish();
template<typename T> bool splitUnary(Instruction &, const T &);
@@ -215,6 +223,8 @@ private:
ScatterMap Scattered;
GatherList Gathered;
+ SmallVector<WeakTrackingVH, 32> PotentiallyDeadInstrs;
+
unsigned ParallelLoopAccessMDKind;
DominatorTree *DT;
@@ -252,7 +262,7 @@ Scatterer::Scatterer(BasicBlock *bb, BasicBlock::iterator bbi, Value *v,
PtrTy = dyn_cast<PointerType>(Ty);
if (PtrTy)
Ty = PtrTy->getElementType();
- Size = Ty->getVectorNumElements();
+ Size = cast<FixedVectorType>(Ty)->getNumElements();
if (!CachePtr)
Tmp.resize(Size, nullptr);
else if (CachePtr->empty())
@@ -269,7 +279,7 @@ Value *Scatterer::operator[](unsigned I) {
return CV[I];
IRBuilder<> Builder(BB, BBI);
if (PtrTy) {
- Type *ElTy = PtrTy->getElementType()->getVectorElementType();
+ Type *ElTy = cast<VectorType>(PtrTy->getElementType())->getElementType();
if (!CV[0]) {
Type *NewPtrTy = PointerType::get(ElTy, PtrTy->getAddressSpace());
CV[0] = Builder.CreateBitCast(V, NewPtrTy, V->getName() + ".i0");
@@ -376,11 +386,6 @@ Scatterer ScalarizerVisitor::scatter(Instruction *Point, Value *V) {
// so that we can avoid creating the gathered form if all uses of Op are
// replaced with uses of CV.
void ScalarizerVisitor::gather(Instruction *Op, const ValueVector &CV) {
- // Since we're not deleting Op yet, stub out its operands, so that it
- // doesn't make anything live unnecessarily.
- for (unsigned I = 0, E = Op->getNumOperands(); I != E; ++I)
- Op->setOperand(I, UndefValue::get(Op->getOperand(I)->getType()));
-
transferMetadataAndIRFlags(Op, CV);
// If we already have a scattered form of Op (created from ExtractElements
@@ -389,13 +394,13 @@ void ScalarizerVisitor::gather(Instruction *Op, const ValueVector &CV) {
if (!SV.empty()) {
for (unsigned I = 0, E = SV.size(); I != E; ++I) {
Value *V = SV[I];
- if (V == nullptr)
+ if (V == nullptr || SV[I] == CV[I])
continue;
Instruction *Old = cast<Instruction>(V);
CV[I]->takeName(Old);
Old->replaceAllUsesWith(CV[I]);
- Old->eraseFromParent();
+ PotentiallyDeadInstrs.emplace_back(Old);
}
}
SV = CV;
@@ -434,25 +439,22 @@ void ScalarizerVisitor::transferMetadataAndIRFlags(Instruction *Op,
}
// Try to fill in Layout from Ty, returning true on success. Alignment is
-// the alignment of the vector, or 0 if the ABI default should be used.
-bool ScalarizerVisitor::getVectorLayout(Type *Ty, unsigned Alignment,
- VectorLayout &Layout, const DataLayout &DL) {
+// the alignment of the vector, or None if the ABI default should be used.
+Optional<VectorLayout>
+ScalarizerVisitor::getVectorLayout(Type *Ty, Align Alignment,
+ const DataLayout &DL) {
+ VectorLayout Layout;
// Make sure we're dealing with a vector.
Layout.VecTy = dyn_cast<VectorType>(Ty);
if (!Layout.VecTy)
- return false;
-
+ return None;
// Check that we're dealing with full-byte elements.
Layout.ElemTy = Layout.VecTy->getElementType();
if (!DL.typeSizeEqualsStoreSize(Layout.ElemTy))
- return false;
-
- if (Alignment)
- Layout.VecAlign = Alignment;
- else
- Layout.VecAlign = DL.getABITypeAlignment(Layout.VecTy);
+ return None;
+ Layout.VecAlign = Alignment;
Layout.ElemSize = DL.getTypeStoreSize(Layout.ElemTy);
- return true;
+ return Layout;
}
// Scalarize one-operand instruction I, using Split(Builder, X, Name)
@@ -463,7 +465,7 @@ bool ScalarizerVisitor::splitUnary(Instruction &I, const Splitter &Split) {
if (!VT)
return false;
- unsigned NumElems = VT->getNumElements();
+ unsigned NumElems = cast<FixedVectorType>(VT)->getNumElements();
IRBuilder<> Builder(&I);
Scatterer Op = scatter(&I, I.getOperand(0));
assert(Op.size() == NumElems && "Mismatched unary operation");
@@ -483,17 +485,19 @@ bool ScalarizerVisitor::splitBinary(Instruction &I, const Splitter &Split) {
if (!VT)
return false;
- unsigned NumElems = VT->getNumElements();
+ unsigned NumElems = cast<FixedVectorType>(VT)->getNumElements();
IRBuilder<> Builder(&I);
- Scatterer Op0 = scatter(&I, I.getOperand(0));
- Scatterer Op1 = scatter(&I, I.getOperand(1));
- assert(Op0.size() == NumElems && "Mismatched binary operation");
- assert(Op1.size() == NumElems && "Mismatched binary operation");
+ Scatterer VOp0 = scatter(&I, I.getOperand(0));
+ Scatterer VOp1 = scatter(&I, I.getOperand(1));
+ assert(VOp0.size() == NumElems && "Mismatched binary operation");
+ assert(VOp1.size() == NumElems && "Mismatched binary operation");
ValueVector Res;
Res.resize(NumElems);
- for (unsigned Elem = 0; Elem < NumElems; ++Elem)
- Res[Elem] = Split(Builder, Op0[Elem], Op1[Elem],
- I.getName() + ".i" + Twine(Elem));
+ for (unsigned Elem = 0; Elem < NumElems; ++Elem) {
+ Value *Op0 = VOp0[Elem];
+ Value *Op1 = VOp1[Elem];
+ Res[Elem] = Split(Builder, Op0, Op1, I.getName() + ".i" + Twine(Elem));
+ }
gather(&I, Res);
return true;
}
@@ -524,7 +528,7 @@ bool ScalarizerVisitor::splitCall(CallInst &CI) {
if (ID == Intrinsic::not_intrinsic || !isTriviallyScalariable(ID))
return false;
- unsigned NumElems = VT->getNumElements();
+ unsigned NumElems = cast<FixedVectorType>(VT)->getNumElements();
unsigned NumArgs = CI.getNumArgOperands();
ValueVector ScalarOperands(NumArgs);
@@ -574,26 +578,33 @@ bool ScalarizerVisitor::visitSelectInst(SelectInst &SI) {
if (!VT)
return false;
- unsigned NumElems = VT->getNumElements();
+ unsigned NumElems = cast<FixedVectorType>(VT)->getNumElements();
IRBuilder<> Builder(&SI);
- Scatterer Op1 = scatter(&SI, SI.getOperand(1));
- Scatterer Op2 = scatter(&SI, SI.getOperand(2));
- assert(Op1.size() == NumElems && "Mismatched select");
- assert(Op2.size() == NumElems && "Mismatched select");
+ Scatterer VOp1 = scatter(&SI, SI.getOperand(1));
+ Scatterer VOp2 = scatter(&SI, SI.getOperand(2));
+ assert(VOp1.size() == NumElems && "Mismatched select");
+ assert(VOp2.size() == NumElems && "Mismatched select");
ValueVector Res;
Res.resize(NumElems);
if (SI.getOperand(0)->getType()->isVectorTy()) {
- Scatterer Op0 = scatter(&SI, SI.getOperand(0));
- assert(Op0.size() == NumElems && "Mismatched select");
- for (unsigned I = 0; I < NumElems; ++I)
- Res[I] = Builder.CreateSelect(Op0[I], Op1[I], Op2[I],
+ Scatterer VOp0 = scatter(&SI, SI.getOperand(0));
+ assert(VOp0.size() == NumElems && "Mismatched select");
+ for (unsigned I = 0; I < NumElems; ++I) {
+ Value *Op0 = VOp0[I];
+ Value *Op1 = VOp1[I];
+ Value *Op2 = VOp2[I];
+ Res[I] = Builder.CreateSelect(Op0, Op1, Op2,
SI.getName() + ".i" + Twine(I));
+ }
} else {
Value *Op0 = SI.getOperand(0);
- for (unsigned I = 0; I < NumElems; ++I)
- Res[I] = Builder.CreateSelect(Op0, Op1[I], Op2[I],
+ for (unsigned I = 0; I < NumElems; ++I) {
+ Value *Op1 = VOp1[I];
+ Value *Op2 = VOp2[I];
+ Res[I] = Builder.CreateSelect(Op0, Op1, Op2,
SI.getName() + ".i" + Twine(I));
+ }
}
gather(&SI, Res);
return true;
@@ -621,7 +632,7 @@ bool ScalarizerVisitor::visitGetElementPtrInst(GetElementPtrInst &GEPI) {
return false;
IRBuilder<> Builder(&GEPI);
- unsigned NumElems = VT->getNumElements();
+ unsigned NumElems = cast<FixedVectorType>(VT)->getNumElements();
unsigned NumIndices = GEPI.getNumIndices();
// The base pointer might be scalar even if it's a vector GEP. In those cases,
@@ -666,7 +677,7 @@ bool ScalarizerVisitor::visitCastInst(CastInst &CI) {
if (!VT)
return false;
- unsigned NumElems = VT->getNumElements();
+ unsigned NumElems = cast<FixedVectorType>(VT)->getNumElements();
IRBuilder<> Builder(&CI);
Scatterer Op0 = scatter(&CI, CI.getOperand(0));
assert(Op0.size() == NumElems && "Mismatched cast");
@@ -685,8 +696,8 @@ bool ScalarizerVisitor::visitBitCastInst(BitCastInst &BCI) {
if (!DstVT || !SrcVT)
return false;
- unsigned DstNumElems = DstVT->getNumElements();
- unsigned SrcNumElems = SrcVT->getNumElements();
+ unsigned DstNumElems = cast<FixedVectorType>(DstVT)->getNumElements();
+ unsigned SrcNumElems = cast<FixedVectorType>(SrcVT)->getNumElements();
IRBuilder<> Builder(&BCI);
Scatterer Op0 = scatter(&BCI, BCI.getOperand(0));
ValueVector Res;
@@ -700,7 +711,7 @@ bool ScalarizerVisitor::visitBitCastInst(BitCastInst &BCI) {
// <M x t1> -> <N*M x t2>. Convert each t1 to <N x t2> and copy the
// individual elements to the destination.
unsigned FanOut = DstNumElems / SrcNumElems;
- Type *MidTy = VectorType::get(DstVT->getElementType(), FanOut);
+ auto *MidTy = FixedVectorType::get(DstVT->getElementType(), FanOut);
unsigned ResI = 0;
for (unsigned Op0I = 0; Op0I < SrcNumElems; ++Op0I) {
Value *V = Op0[Op0I];
@@ -718,7 +729,7 @@ bool ScalarizerVisitor::visitBitCastInst(BitCastInst &BCI) {
} else {
// <N*M x t1> -> <M x t2>. Convert each group of <N x t1> into a t2.
unsigned FanIn = SrcNumElems / DstNumElems;
- Type *MidTy = VectorType::get(SrcVT->getElementType(), FanIn);
+ auto *MidTy = FixedVectorType::get(SrcVT->getElementType(), FanIn);
unsigned Op0I = 0;
for (unsigned ResI = 0; ResI < DstNumElems; ++ResI) {
Value *V = UndefValue::get(MidTy);
@@ -734,12 +745,79 @@ bool ScalarizerVisitor::visitBitCastInst(BitCastInst &BCI) {
return true;
}
+bool ScalarizerVisitor::visitInsertElementInst(InsertElementInst &IEI) {
+ VectorType *VT = dyn_cast<VectorType>(IEI.getType());
+ if (!VT)
+ return false;
+
+ unsigned NumElems = cast<FixedVectorType>(VT)->getNumElements();
+ IRBuilder<> Builder(&IEI);
+ Scatterer Op0 = scatter(&IEI, IEI.getOperand(0));
+ Value *NewElt = IEI.getOperand(1);
+ Value *InsIdx = IEI.getOperand(2);
+
+ ValueVector Res;
+ Res.resize(NumElems);
+
+ if (auto *CI = dyn_cast<ConstantInt>(InsIdx)) {
+ for (unsigned I = 0; I < NumElems; ++I)
+ Res[I] = CI->getValue().getZExtValue() == I ? NewElt : Op0[I];
+ } else {
+ if (!ScalarizeVariableInsertExtract)
+ return false;
+
+ for (unsigned I = 0; I < NumElems; ++I) {
+ Value *ShouldReplace =
+ Builder.CreateICmpEQ(InsIdx, ConstantInt::get(InsIdx->getType(), I),
+ InsIdx->getName() + ".is." + Twine(I));
+ Value *OldElt = Op0[I];
+ Res[I] = Builder.CreateSelect(ShouldReplace, NewElt, OldElt,
+ IEI.getName() + ".i" + Twine(I));
+ }
+ }
+
+ gather(&IEI, Res);
+ return true;
+}
+
+bool ScalarizerVisitor::visitExtractElementInst(ExtractElementInst &EEI) {
+ VectorType *VT = dyn_cast<VectorType>(EEI.getOperand(0)->getType());
+ if (!VT)
+ return false;
+
+ unsigned NumSrcElems = cast<FixedVectorType>(VT)->getNumElements();
+ IRBuilder<> Builder(&EEI);
+ Scatterer Op0 = scatter(&EEI, EEI.getOperand(0));
+ Value *ExtIdx = EEI.getOperand(1);
+
+ if (auto *CI = dyn_cast<ConstantInt>(ExtIdx)) {
+ Value *Res = Op0[CI->getValue().getZExtValue()];
+ gather(&EEI, {Res});
+ return true;
+ }
+
+ if (!ScalarizeVariableInsertExtract)
+ return false;
+
+ Value *Res = UndefValue::get(VT->getElementType());
+ for (unsigned I = 0; I < NumSrcElems; ++I) {
+ Value *ShouldExtract =
+ Builder.CreateICmpEQ(ExtIdx, ConstantInt::get(ExtIdx->getType(), I),
+ ExtIdx->getName() + ".is." + Twine(I));
+ Value *Elt = Op0[I];
+ Res = Builder.CreateSelect(ShouldExtract, Elt, Res,
+ EEI.getName() + ".upto" + Twine(I));
+ }
+ gather(&EEI, {Res});
+ return true;
+}
+
bool ScalarizerVisitor::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
VectorType *VT = dyn_cast<VectorType>(SVI.getType());
if (!VT)
return false;
- unsigned NumElems = VT->getNumElements();
+ unsigned NumElems = cast<FixedVectorType>(VT)->getNumElements();
Scatterer Op0 = scatter(&SVI, SVI.getOperand(0));
Scatterer Op1 = scatter(&SVI, SVI.getOperand(1));
ValueVector Res;
@@ -763,7 +841,7 @@ bool ScalarizerVisitor::visitPHINode(PHINode &PHI) {
if (!VT)
return false;
- unsigned NumElems = VT->getNumElements();
+ unsigned NumElems = cast<FixedVectorType>(VT)->getNumElements();
IRBuilder<> Builder(&PHI);
ValueVector Res;
Res.resize(NumElems);
@@ -789,20 +867,20 @@ bool ScalarizerVisitor::visitLoadInst(LoadInst &LI) {
if (!LI.isSimple())
return false;
- VectorLayout Layout;
- if (!getVectorLayout(LI.getType(), LI.getAlignment(), Layout,
- LI.getModule()->getDataLayout()))
+ Optional<VectorLayout> Layout = getVectorLayout(
+ LI.getType(), LI.getAlign(), LI.getModule()->getDataLayout());
+ if (!Layout)
return false;
- unsigned NumElems = Layout.VecTy->getNumElements();
+ unsigned NumElems = cast<FixedVectorType>(Layout->VecTy)->getNumElements();
IRBuilder<> Builder(&LI);
Scatterer Ptr = scatter(&LI, LI.getPointerOperand());
ValueVector Res;
Res.resize(NumElems);
for (unsigned I = 0; I < NumElems; ++I)
- Res[I] = Builder.CreateAlignedLoad(Layout.VecTy->getElementType(), Ptr[I],
- Layout.getElemAlign(I),
+ Res[I] = Builder.CreateAlignedLoad(Layout->VecTy->getElementType(), Ptr[I],
+ Align(Layout->getElemAlign(I)),
LI.getName() + ".i" + Twine(I));
gather(&LI, Res);
return true;
@@ -814,22 +892,23 @@ bool ScalarizerVisitor::visitStoreInst(StoreInst &SI) {
if (!SI.isSimple())
return false;
- VectorLayout Layout;
Value *FullValue = SI.getValueOperand();
- if (!getVectorLayout(FullValue->getType(), SI.getAlignment(), Layout,
- SI.getModule()->getDataLayout()))
+ Optional<VectorLayout> Layout = getVectorLayout(
+ FullValue->getType(), SI.getAlign(), SI.getModule()->getDataLayout());
+ if (!Layout)
return false;
- unsigned NumElems = Layout.VecTy->getNumElements();
+ unsigned NumElems = cast<FixedVectorType>(Layout->VecTy)->getNumElements();
IRBuilder<> Builder(&SI);
- Scatterer Ptr = scatter(&SI, SI.getPointerOperand());
- Scatterer Val = scatter(&SI, FullValue);
+ Scatterer VPtr = scatter(&SI, SI.getPointerOperand());
+ Scatterer VVal = scatter(&SI, FullValue);
ValueVector Stores;
Stores.resize(NumElems);
for (unsigned I = 0; I < NumElems; ++I) {
- unsigned Align = Layout.getElemAlign(I);
- Stores[I] = Builder.CreateAlignedStore(Val[I], Ptr[I], Align);
+ Value *Val = VVal[I];
+ Value *Ptr = VPtr[I];
+ Stores[I] = Builder.CreateAlignedStore(Val, Ptr, Layout->getElemAlign(I));
}
transferMetadataAndIRFlags(&SI, Stores);
return true;
@@ -852,23 +931,32 @@ bool ScalarizerVisitor::finish() {
if (!Op->use_empty()) {
// The value is still needed, so recreate it using a series of
// InsertElements.
- Type *Ty = Op->getType();
- Value *Res = UndefValue::get(Ty);
- BasicBlock *BB = Op->getParent();
- unsigned Count = Ty->getVectorNumElements();
- IRBuilder<> Builder(Op);
- if (isa<PHINode>(Op))
- Builder.SetInsertPoint(BB, BB->getFirstInsertionPt());
- for (unsigned I = 0; I < Count; ++I)
- Res = Builder.CreateInsertElement(Res, CV[I], Builder.getInt32(I),
- Op->getName() + ".upto" + Twine(I));
+ Value *Res = UndefValue::get(Op->getType());
+ if (auto *Ty = dyn_cast<VectorType>(Op->getType())) {
+ BasicBlock *BB = Op->getParent();
+ unsigned Count = cast<FixedVectorType>(Ty)->getNumElements();
+ IRBuilder<> Builder(Op);
+ if (isa<PHINode>(Op))
+ Builder.SetInsertPoint(BB, BB->getFirstInsertionPt());
+ for (unsigned I = 0; I < Count; ++I)
+ Res = Builder.CreateInsertElement(Res, CV[I], Builder.getInt32(I),
+ Op->getName() + ".upto" + Twine(I));
+ } else {
+ assert(CV.size() == 1 && Op->getType() == CV[0]->getType());
+ Res = CV[0];
+ if (Op == Res)
+ continue;
+ }
Res->takeName(Op);
Op->replaceAllUsesWith(Res);
}
- Op->eraseFromParent();
+ PotentiallyDeadInstrs.emplace_back(Op);
}
Gathered.clear();
Scattered.clear();
+
+ RecursivelyDeleteTriviallyDeadInstructionsPermissive(PotentiallyDeadInstrs);
+
return true;
}