[InstCombine] clean up code for binop-shuffle transforms; NFCI
llvm-svn: 332399
This commit is contained in:
parent
0366155500
commit
3c569f0de0
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue