[InstCombine] clean up code for binop-shuffle transforms; NFCI

llvm-svn: 332399
This commit is contained in:
Sanjay Patel 2018-05-15 21:23:58 +00:00
parent 0366155500
commit 3c569f0de0
1 changed files with 34 additions and 39 deletions

View File

@ -1351,17 +1351,6 @@ Value *InstCombiner::Descale(Value *Val, APInt Scale, bool &NoSignedWrap) {
} while (true);
}
/// Creates node of binary operation with the same attributes as the
/// specified one but with other operands.
static Value *CreateBinOpAsGiven(BinaryOperator &Inst, Value *LHS, Value *RHS,
InstCombiner::BuilderTy &B) {
Value *BO = B.CreateBinOp(Inst.getOpcode(), LHS, RHS);
// If LHS and RHS are constant, BO won't be a binary operator.
if (BinaryOperator *NewBO = dyn_cast<BinaryOperator>(BO))
NewBO->copyIRFlags(&Inst);
return BO;
}
/// Makes transformation of binary operation specific for vector types.
/// \param Inst Binary operator to transform.
/// \return Pointer to node that must replace the original binary operator, or
@ -1380,6 +1369,13 @@ Value *InstCombiner::SimplifyVectorOp(BinaryOperator &Inst) {
assert(cast<VectorType>(LHS->getType())->getNumElements() == VWidth);
assert(cast<VectorType>(RHS->getType())->getNumElements() == VWidth);
auto createBinOpShuffle = [&](Value *X, Value *Y, Constant *M) {
Value *XY = Builder.CreateBinOp(Inst.getOpcode(), X, Y);
if (auto *BO = dyn_cast<BinaryOperator>(XY))
BO->copyIRFlags(&Inst);
return Builder.CreateShuffleVector(XY, UndefValue::get(XY->getType()), M);
};
// If both arguments of the binary operation are shuffles that use the same
// mask and shuffle within a single vector, move the shuffle after the binop.
Value *V1, *V2;
@ -1389,47 +1385,46 @@ Value *InstCombiner::SimplifyVectorOp(BinaryOperator &Inst) {
V1->getType() == V2->getType() &&
(LHS->hasOneUse() || RHS->hasOneUse() || LHS == RHS)) {
// Op(shuffle(V1, Mask), shuffle(V2, Mask)) -> shuffle(Op(V1, V2), Mask)
Value *B = CreateBinOpAsGiven(Inst, V1, V2, Builder);
return Builder.CreateShuffleVector(B, UndefValue::get(V1->getType()), Mask);
return createBinOpShuffle(V1, V2, Mask);
}
// If one argument is a shuffle within one vector, the other is a constant,
// try moving the shuffle after the binary operation.
ShuffleVectorInst *Shuffle = nullptr;
Constant *C1 = nullptr;
if (isa<ShuffleVectorInst>(LHS)) Shuffle = cast<ShuffleVectorInst>(LHS);
if (isa<ShuffleVectorInst>(RHS)) Shuffle = cast<ShuffleVectorInst>(RHS);
if (isa<Constant>(LHS)) C1 = cast<Constant>(LHS);
if (isa<Constant>(RHS)) C1 = cast<Constant>(RHS);
if (Shuffle && C1 &&
(isa<ConstantVector>(C1) || isa<ConstantDataVector>(C1)) &&
isa<UndefValue>(Shuffle->getOperand(1)) &&
Shuffle->getType() == Shuffle->getOperand(0)->getType()) {
SmallVector<int, 16> ShMask = Shuffle->getShuffleMask();
// Find constant C2 that has property:
// shuffle(C2, ShMask) = C1
// If such constant does not exist (example: ShMask=<0,0> and C1=<1,2>)
// If one argument is a shuffle within one vector and the other is a constant,
// try moving the shuffle after the binary operation. This canonicalization
// intends to move shuffles closer to other shuffles and binops closer to
// other binops, so they can be folded. It may also enable demanded elements
// transforms.
Constant *C;
if (match(&Inst, m_c_BinOp(
m_ShuffleVector(m_Value(V1), m_Undef(), m_Constant(Mask)),
m_Constant(C))) &&
V1->getType() == Inst.getType()) {
// Find constant NewC that has property:
// shuffle(NewC, ShMask) = C
// If such constant does not exist (example: ShMask=<0,0> and C=<1,2>)
// reorder is not possible.
SmallVector<Constant*, 16> C2M(VWidth,
UndefValue::get(C1->getType()->getScalarType()));
SmallVector<int, 16> ShMask;
ShuffleVectorInst::getShuffleMask(Mask, ShMask);
SmallVector<Constant *, 16>
NewVecC(VWidth, UndefValue::get(C->getType()->getScalarType()));
bool MayChange = true;
for (unsigned I = 0; I < VWidth; ++I) {
if (ShMask[I] >= 0) {
assert(ShMask[I] < (int)VWidth);
if (!isa<UndefValue>(C2M[ShMask[I]])) {
Constant *CElt = C->getAggregateElement(I);
if (!CElt || !isa<UndefValue>(NewVecC[ShMask[I]])) {
MayChange = false;
break;
}
C2M[ShMask[I]] = C1->getAggregateElement(I);
NewVecC[ShMask[I]] = CElt;
}
}
if (MayChange) {
Constant *C2 = ConstantVector::get(C2M);
Value *NewLHS = isa<Constant>(LHS) ? C2 : Shuffle->getOperand(0);
Value *NewRHS = isa<Constant>(LHS) ? Shuffle->getOperand(0) : C2;
Value *NewBO = CreateBinOpAsGiven(Inst, NewLHS, NewRHS, Builder);
return Builder.CreateShuffleVector(NewBO,
UndefValue::get(Inst.getType()), Shuffle->getMask());
// Op(shuffle(V1, Mask), C) -> shuffle(Op(V1, NewC), Mask)
// Op(C, shuffle(V1, Mask)) -> shuffle(Op(NewC, V1), Mask)
Constant *NewC = ConstantVector::get(NewVecC);
Value *NewLHS = isa<Constant>(LHS) ? NewC : V1;
Value *NewRHS = isa<Constant>(LHS) ? V1 : NewC;
return createBinOpShuffle(NewLHS, NewRHS, Mask);
}
}